Merge remote-tracking branch 'origin/main' into HEAD

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

# Conflicts:
#	bin/gstack-review-dispatch
This commit is contained in:
garrytan committed 2026-10-31 11:05:05 +00:00
commit c8e63c31c8
61 files changed
+2795 -79

No files matched your search

+1 -1
View File
@@ -20,7 +20,7 @@ cuts to the coverage audit, review army, or voice directive have real quality co
A second, harder ceiling guards the DISCOVERY surface: `test/catalog-budget.test.ts`
caps the aggregate frontmatter `name` + `description` across all skills at
`CATALOG_BUDGET_TOKEN_EQUIVALENTS` (1,393 today; each new skill ratchets it)
`CATALOG_BUDGET_TOKEN_EQUIVALENTS` (1,423 today; each new skill ratchets it)
token-equivalents (260-byte per-skill sub-cap), counted through the shared census
in `test/helpers/skill-census.ts`. This one is enforced, not a warning — every
host loads the full catalog every session, so growth here taxes every
+1
View File
@@ -68,6 +68,7 @@ gstack/
├── modernize/ # /modernize skill (aging PR → MODERNIZE / REWORK / CLOSE disposition, range-diff proof, pinned-lease push)
├── office-hours/ # /office-hours skill (YC Office Hours — startup diagnostic + builder brainstorm)
├── investigate/ # /investigate skill (systematic root-cause debugging)
├── verify/ # /verify skill (build-and-verify loop over bin/gstack-checks + lib/checks.ts; tests come from lib/pregate)
├── spec/ # /spec skill (five-phase spec → GitHub issue, optional agent spawn, /ship auto-closes)
├── retro/ # Retrospective skill (includes /retro global cross-project mode)
├── careful/ # /careful skill; bin/check-careful.sh (PreToolUse destructive-command hook) + bin/hook-extract.sh (shared hook helpers: payload extraction, deny JSON, gstack_hook_state_root)
+26 -7
View File
@@ -31,7 +31,8 @@ the root they checked.
A dispatched reviewer (an /autoplan voice, a second opinion) reads a plan and
reports; it runs no workflow. `--for review-voice` gives its machine a real
trailer in seconds: clone or fast-forward, Bun at gstack's own supported
trailer in seconds: a clone when absent (an existing checkout is used as it
is, unless it is below the supported minimum), Bun at gstack's own supported
minimum (the project's pins are not applied, since no repo tests run there; the
trailer says `pins: skipped (helper runtime)`), no `./setup`, no host profiles
and no bun shim. The doctor certifies only the read-only helpers (`PASS
@@ -52,8 +53,18 @@ the lane on the same machine may be in the middle of a workflow on it: when
origin is ahead it prints `SELF_UPGRADE: skipped (review-voice never
self-upgrades a shared checkout; …)`, certifies the installed revision and
stays ok with `behind=<n> … (UPGRADE_SKIPPED); fix: <root>/bin/gstack-upgrade`.
The bootstrapper still fast-forwards a checkout below the supported minimum.
Every /autoplan reviewer prompt
The bootstrapper still fast-forwards a checkout below the supported minimum,
for a reviewer too (GST-395): below it every session's trailer on that checkout
fails (REVISION_BELOW_MINIMUM), the lane's own next install would move it
anyway, and the minimum rises only for install-honesty or security fixes.
When a reviewer keeps a fuller verdict, it also leaves that install's launch
environment alone (GST-401): it writes no launch file and announces the fuller
install's own `GSTACK_LAUNCH_FILE` and `GSTACK_LAUNCH_PATH`, so the lane's
`<verdict>.env` and `<verdict>.launch` are never rewritten and the reviewer
runs the helpers on the Bun that verdict certified. A launch directory the
reviewer needs for its own Bun lives under `<verdict>.profile/review-voice.launch`
(mode 0700), never `<verdict>.launch`; a failing review-voice check removes
`<verdict>.profile/`. Every /autoplan reviewer prompt
ends with this command (`GSTACK TRAILER`); the warm run's budget, under 20 s,
is measured by `test/capy-review-voice.test.ts`.
@@ -108,8 +119,9 @@ there is refused with the usual `--for <skill>` fix.
(next section).
`SELF_UPGRADE: none (current)` when nothing is ahead;
`--for review-voice` prints `SELF_UPGRADE: skipped (review-voice never
self-upgrades a shared checkout; fix: <root>/bin/gstack-upgrade when no other
session uses this checkout (UPGRADE_SKIPPED))` whenever origin is ahead,
self-upgrades a shared checkout; fix: GSTACK_UPGRADE_FORCE=1
<root>/bin/gstack-upgrade when no other session uses this checkout
(UPGRADE_SKIPPED))` whenever origin is ahead,
with or without a lease, and `GSTACK_UPGRADE_FORCE=1` does not change that
([reviewer machines](#reviewer-machines---for-review-voice));
`GSTACK_CAPY_SELF_UPGRADE=off` (or `GSTACK_CAPY_AUTO_UPGRADE=0`) prints
@@ -174,8 +186,15 @@ session holds a workflow lease on this installation: ... (UPGRADE_BUSY))`,
leaves the checkout where the run started and stays ok with `behind=`. Each
`gstack-skill-start` renews the lease. On Capy the leased pid is the machine's
long-lived `capy-server`, so the deferral ends when the lease turns 120
minutes old, not when the process exits; `bin/gstack-upgrade` run by hand
moves the checkout sooner. The team-mode SessionStart hook
minutes old, not when the process exits. Every session on the machine runs
under that same `capy-server`, so `bin/gstack-upgrade` run by hand also
counts a `capy-server` lease under 120 minutes old (it may be a sibling's) and
refuses with `a shared harness (capy-server, pid <p>) holds a lease <n>m old;
… (UPGRADE_BUSY)`; `GSTACK_UPGRADE_FORCE=1` moves it sooner when no other
session uses the checkout (GST-396). The age counts from the last renewal by
any session, so a workflow idle for more than 120 minutes since its last
`gstack-skill-start` can be moved by any session on the machine: Capy gives
the shell no per-session identity to tell the leases apart. The team-mode SessionStart hook
(`bin/gstack-session-update`) honors the same leases: it logs
`SKIP leased pid=<p>/<age>m` to `analytics/session-update.log` and tries again at
the next session start, without writing its hourly throttle stamp. A lease whose
+14 -1
View File
@@ -511,10 +511,23 @@ ones, and the arm lost blockers. `bin/gstack-review-dispatch` closes both ends:
against the merged lines they produced, and the judgment rerun against the
recorded judged set, covering every collected id. A ledger from a run that kept no
prompts prints `VERIFY: no brief records` (exit 3), never clean.
6. `pass --base <b> --out <dir> --pass <id> -- <plan flags>` runs one pass from a
staged manifest (`<dir>/pass-manifest.json`): audit readers marked first, then
the specialists with QA and the other audits, then the Red Team, then Step 11's
voices. Each reviewer keeps its plan entry and is rendered by the same code as
`render`, once its inputs exist; the Red Team's findings file is the specialists'
`merged.jsonl` lines byte for byte. A brief leaves the bin in indexed chunks of at
most 65,536 characters (`chunk`), so no tool output line carries a whole brief and a
host's line or output cap cannot cut one. Each reader's intent is recorded before its
subagent is created and its path right after (`mark`), so a resumed pass finds a
create whose result was lost by its title and never starts a reader twice; a
missing or doubled title stops the pass. On Capy the pass runs as one call to the
checked-in program `lib/capy-review-pass.js`, served by `program` and loaded
unchanged by the gstack Capy skill.
## Where this is enforced
- `lib/review-brief.ts`, `lib/review-ledger.ts`, `bin/gstack-review-dispatch`: [verbatim dispatch](#verbatim-dispatch) (`test/review-dispatch.test.ts`).
- `lib/review-brief.ts`, `lib/review-ledger.ts`, `lib/review-pass.ts`, `lib/capy-review-pass.js`, `bin/gstack-review-dispatch`: [verbatim dispatch](#verbatim-dispatch) (`test/review-dispatch.test.ts`, `test/review-pass.test.ts`).
- `scripts/resolvers/review-army.ts`: the floor and `NO FINDINGS` in every specialist and Red Team prompt (rendered into `review/sections/review-army.md` and `ship/sections/review-army.md`), and the lead judgment's "On record" line that turns a [ruled class](#rulings-below-the-floor) into a note; in `/ship` every specialist and Red Team prompt it renders carries its diff base as a literal sha the parent writes in (`DIFF_BASE=<diff-base>`: the merge base on pass 1, `RANGE_BASE` from pass 2 on) beside its plan's `DIFF_CMD` excludes, because a reviewer is its own process and never sees the parent's shell variables; the fan-out batches above.
- `ship/sections/review-army.md` Step 9: the plan's `REVIEW_DEPTH`, `GATE_SCAN` and `--depth-floor` on every run, the depth fields of the review-log row, passes, `RANGE_BASE`, classify, defer, render, the cap check before any edit, the Step 11 late-defer row, scratch files under `.gstack/tmp/`, the cap decisions; `ship/sections/adversarial.md` Step 11: the outside voice reads the same range and scopes queued fixes the same way.
+9
View File
@@ -12,6 +12,7 @@ Detailed guides for every gstack skill — philosophy, workflow, and examples.
| [`/design-consultation`](#design-consultation) | **Design Partner** | Build a complete design system from scratch. Knows the landscape, proposes creative risks, generates realistic product mockups. Design at the heart of all other phases. |
| [`/review`](#review) | **Staff Engineer** | Find the bugs that pass CI but blow up in production. Auto-fixes the obvious ones. Flags completeness gaps. Advisory simplification lens flags over-built code — never blocks, never auto-applies. |
| [`/investigate`](#investigate) | **Debugger** | Systematic root-cause debugging. Iron Law: no fixes without investigation. Traces data flow, tests hypotheses, stops after 3 failed fixes. |
| [`/verify`](#verify) | **Build Loop** | Run the repo's checks and the tests `/ship`'s pre-gate would pick for your change, fix, repeat until green, then hand off to `/ship`. Never green on an unmapped change. |
| [`/design-review`](#design-review) | **Designer Who Codes** | Live-site visual audit + fix loop. 80-item audit, then fixes what it finds. Atomic commits, before/after screenshots. |
| [`/design-shotgun`](#design-shotgun) | **Design Explorer** | Generate multiple AI design variants, open a comparison board in your browser, and iterate until you approve a direction. Taste memory biases toward your preferences. |
| [`/design-html`](#design-html) | **Design Engineer** | Generates production-quality Pretext-native HTML. Works with approved mockups, CEO plans, design reviews, or from scratch. Text reflows on resize, heights adjust to content. Smart API routing per design type. Framework detection for React/Svelte/Vue. Previews render through your Aside browser. |
@@ -659,6 +660,14 @@ Instead of guessing and patching, it traces data flow, matches against known bug
---
## `/verify`
`/verify` is the loop you run while you build: change something, run the repo's checks, fix what broke, run again. `gstack-checks detect` finds the checks the repo already declares (a `gstack:verify:` line or a `## Health Stack` section in CLAUDE.md, else package.json scripts, tsconfig, eslint or biome, pyproject, Cargo.toml, go.mod) and never makes one up. `gstack-checks run` runs them plus the tests `/ship`'s pre-gate selects for your change, using pregate's own selector, so a green `/verify` predicts a green pre-gate.
It asks once before running any repo command (`gstack-checks trust`) and asks again when a command changes. A touched file no test covers is `UNMAPPED`, a selection that ran zero tests is `ZERO_RUN`, and neither counts as green. A missing tool or service is reported, not worked around. It stops after five runs or when the same failure comes back twice, and sends a stubborn red to `/investigate`. When everything passes, `gstack-checks status` prints `READY_FOR_SHIP tree=<tree>` without rerunning anything, and you run `/ship`. It never reviews, bumps versions, pushes or opens a PR.
---
## `/qa`
This is my **QA lead mode**.
+12 -5
View File
@@ -1554,7 +1554,7 @@ branch), then re-run `bin/gstack-upgrade`. A reinstall that failed after the
fast-forward is completed by the next run (`reinstall pending from <version>`).
<a id="upgrade-busy"></a>
### `gstack-upgrade: live gstack sessions hold this installation: pid <p> (<age>m), ...; nothing was changed; fix: ... (UPGRADE_BUSY)`
### `gstack-upgrade: live gstack sessions hold this installation: pid <p> (<age>m), ...; nothing was changed; fix: ... (UPGRADE_BUSY)` / `gstack-upgrade: a shared harness (capy-server, pid <p>) holds a lease <n>m old; ... (UPGRADE_BUSY)`
**Meaning.** Several agents share this checkout (Capy subagents on one
machine, say). Each session start writes a workflow lease,
@@ -1567,20 +1567,27 @@ process has exited never blocks, and neither does a stale one: each lease
records its process's start identity, so a pid reused after a reboot or a
machine wake (GBRA-105's lease named pid 379, which had become dbus-daemon)
is reclaimed instead of blocking. The upgrader's own session (the pid chain it
runs under) never counts for `bin/gstack-upgrade` run by hand. A Capy install
runs under) never counts for `bin/gstack-upgrade` run by hand, except under a
shared harness: on Capy every tool call of every session runs under one
`capy-server`, so a `capy-server` lease in the caller's chain may be a
sibling's. `bin/gstack-upgrade` counts it until it is 120 minutes old, counted
from the last renewal by any session on the machine (`a shared harness
(capy-server, pid <p>) holds a lease <n>m old; …`, GST-396). A Capy install
in install mode (`bin/gstack-capy-session`) counts it while that lease is under
120 minutes old: an install run from inside a workflow that holds the lease
(/ship's docs step, #3571) prints `SELF_UPGRADE: skipped (a gstack run in this
session holds a workflow lease on this installation: pid <p> (<age>m
<command>), so the upgrade waits until the lease is 120 minutes old; fix:
<checkout>/bin/gstack-upgrade once the run ends (UPGRADE_BUSY))` and leaves the
<checkout>/bin/gstack-upgrade once the lease is 120 minutes old, or
GSTACK_UPGRADE_FORCE=1 <checkout>/bin/gstack-upgrade when no other session uses
this checkout (UPGRADE_BUSY))` and leaves the
checkout where the run started. Each `gstack-skill-start` renews the lease.
**Fix.** Wait for those sessions to finish (`bin/gstack-lease list` shows
every lease with its age and `alive|dead|stale`; a holder is named as
`pid <p> (<age>m <command>)`), then re-run `bin/gstack-upgrade`. For the
session's own run, run the printed `bin/gstack-upgrade` after the run ends.
When you know they are idle, `GSTACK_UPGRADE_FORCE=1 bin/gstack-upgrade`
session's own run, or a shared-harness lease, re-run once the lease is 120
minutes old. When you know no other session uses the checkout, `GSTACK_UPGRADE_FORCE=1 bin/gstack-upgrade`
proceeds. At a Capy session start the same refusal appears as
`SELF_UPGRADE: skipped (live gstack sessions hold this installation: ...)`,
the doctor adds `WARN behind — … (UPGRADE_BUSY)` and the trailer stays