Skip to content

v1.91.32.0 fix: Codex works from zsh, free text never enters shell commands, honest failures - #3057

Merged
capy-ai[bot] merged 90 commits into
mainfrom
garrytan/fix-wave-oct6
Oct 6, 2026
Merged

capy-ai[bot] merged 90 commits into
mainfrom
garrytan/fix-wave-oct6

Conversation

@garrytan

@garrytan garrytan commented Oct 6, 2026 •

Copy link
Copy Markdown
Owner

The Oct 6 fix wave. Plan: docs/designs/FIX_WAVE_2026_10_06.md, reviewed through /autoplan (CEO, DX, Eng; Claude plus GPT-6 Astra as the outside voice). Contributor PRs were read as evidence and every fix was rewritten; each contributor is credited with Co-authored-by on the commit that uses their diagnosis.

Release promises

Also in this wave

Validation

  • Full free suite on Ubicloud (16 vCPU), head 4db6f20: 16 of 17 shards passed. The one failure, cso-scanner-cli on a Docker-less VM, was diagnosed there and fixed in 1a3a603, and the file passes. That fix changes only that test file.
  • typecheck is clean and typecheck:test has no new diagnostics. Parity, archaeology, module-size and spawnSync tripwires pass, and all-host generation is fresh.
  • Paid, diagnostic only (never uploaded as verdicts):
    • ship-measure-seeded-flake: 3/3.
    • auto-decide-preserved: 1/10 with the reminder, then 10/10 with the hook.
    • A main baseline was started and cancelled, because the working tree changed under it mid-run.
  • Parity caps were raised with measured notes: ship 1.494, plan-eng-review 1.185, review 1.217, plus skeleton caps from the free-text sweep.

Not verified

  • Windows hardware: the Windows behaviors are exercised by the Windows CI lanes and the new isolated-install journey in windows-setup-e2e.yml. The PowerShell known-folder lookup, Copilot's interpreter choice and actual Docker operation are unverified until those lanes run.
  • Timed macOS zsh journey (DX-8): no Mac was available, so it is unmeasured.
  • Deferred to TODOS.md: a bounded owned-journal read (P1), Greptile in parallel, an executed-subcommand probe, an argument-array posting helper, the remaining free-text sites the lint cannot see yet, /plan-tune free-text tune events, native Windows Docker, and a readiness command.

Open in Capy

garrytan and others added 30 commits October 6, 2026 18:02
Skill blocks source bin/gstack-codex-probe and bin/gstack-egress-lib.sh into
the host's shell. Under zsh (macOS default) BASH_SOURCE is empty, so Codex
model selection resolved /../scripts/... and every outside pass reported
CODEX_MODEL: invalid; the egress lib resolved to the caller's cwd. Resolve
the file once at source time (BASH_SOURCE under bash, %x under zsh), and
replace the bash-only ${!name} indirection in the auth probe. A free test
derives every sourced helper from the generated skills and sources each
under bash and zsh.

Co-authored-by: marcosdetry <marcosdetry@users.noreply.github.com>
Co-authored-by: akshaykalia <akshaykalia@users.noreply.github.com>
Co-authored-by: scottgigante-hubflow <scottgigante-hubflow@users.noreply.github.com>
Co-authored-by: woodsonl <woodsonl@users.noreply.github.com>
Co-authored-by: bezdekt <bezdekt@users.noreply.github.com>
…otes (#3046)

greptile-triage's reply APIs posted -f body="<reply text>" while the
templates quote SHAs and diff code in backticks; in double quotes bash ran
each span (replies posted as 'Fixed in .', and diff or reviewer text ran as
a command). The pre-existing-failure issue template and /spec's issue title
had the same shape. All three now go through quoted heredocs. The
generated-bash lint gains untrusted-in-quotes and now also covers runtime
reference docs in skill directories (review/greptile-triage.md).

Co-authored-by: dgrant <dgrant@users.noreply.github.com>
…ing' (#3051)

The model probe matched only model and broken-install errors, so a usage or
rate limit fell through to MODEL_PROBE_INCONCLUSIVE: Codex's own message
(with the reset time) was dropped, the hint pointed at model config, and
every later skill re-probed for 30 s. The probe now returns
MODEL_QUOTA_EXHAUSTED (exit 4) on a failed, non-timeout call that names a
usage limit, rate limit, insufficient_quota or 429, relays Codex's line
verbatim and caches it for 15 minutes. Preflights map it to
CODEX_MODE: quota_exhausted (missing coverage, no further Codex calls), and
classifyOutsideReview reports a mid-run limit as unavailable (quota) with
its own troubleshooting anchor.

Co-authored-by: venkatareddyg <venkatareddyg@users.noreply.github.com>
The bash-native watchdog (stock macOS, no timeout binary) ran pkill -P on
the command's children and then killed the command. Between the two, the
command continued past its killed child and printed output after its
deadline. Stop it first. The test's minimal PATH also lacked pkill, which
the watchdog uses to reap children (stock macOS ships it), so the orphaned
child held stdout open and the capture waited out its sleep.
…, not a retryable identity failure (#3050)

The guard capped journal reads at 32 MiB and reported a longer journal as
'identity', which the hook treats as deny-and-retry. A journal only grows,
so /autoplan could never enter Phase 1 in a long session, and the
troubleshooting row sent people chasing symlinks. Oversize journals now
report too_large as a hard cause that names the size and the supported
fallback (run the reviews by hand or start a new session).

Co-authored-by: venkatareddyg <venkatareddyg@users.noreply.github.com>
Raise overrides to fixed releases: ip-address 10.7.3 (our own pin was the
vulnerable 10.3.1; reachable through socks in browse's proxy path),
fast-uri 3.1.8, hono 4.13.13, proxy-addr 2.0.8, @modelcontextprotocol/sdk
1.31.0, sharp 0.35.5, and in lib/diagram-render dompurify 3.4.16 (bundled
by mermaid) and source-map-js 1.2.2; the render page is rebuilt. Three
advisories without a usable fix get justified, expiring ignores: braces
(build-time only, excalidraw -> sass -> chokidar; a test checks the page
carries no chokidar code), sprintf-js (roarr's constant-format logger) and
katex (needs pre-existing prototype pollution; fix outside mermaid's range).
osv-scanner with the repo config: no issues found.
…issing-evidence denial (#3045)

The guard binds a phase entry only to a literal snapshot-init Bash call.
When the model resolved the tool path into a variable, chained or piped the
call, init ran and succeeded but the denial said 'Complete the existing
snapshot init step', which reads as already done, so the run gave up. When
no init binds but a Bash call looks like one, the denial now says the shape
cannot be bound and prints the literal re-run (answers reused:true). The
binding rule is unchanged, and the skill says to run init on its own.

Co-authored-by: CharlesBerg85 <CharlesBerg85@users.noreply.github.com>
…he flow (#3039)

On Windows, an awaited Bun.stdin.text() inside the CLI's un-awaited main()
let the process exit 0 before reading stdin: a replayed flow reported
success with nothing sent to the daemon. Read fd 0 synchronously (skipped
for a terminal); empty input now gets the server's usage error and a
non-zero exit.

Co-authored-by: VaibDeveloper <VaibDeveloper@users.noreply.github.com>
… macOS GPU flags (#3030)

A plain call refused because another session started the daemon with
--headed/--proxy was told to 'apply --proxy/--headed', flags it never
passed. It now says who started the daemon and offers both remedies. The
BROWSER.md env table notes that the default macOS GPU flags disable WebGL
and that GSTACK_DISABLE_GPU=off restores it for WebGL QA.

Co-authored-by: Hagetino <Hagetino@users.noreply.github.com>
/ship's first run on a branch dispatched a triage subagent only to learn
there was no PR. Step 10 now checks for a PR inline (gh's 'no pull requests
found') and records that Greptile runs on the PR once it exists; other gh
errors still dispatch so the child can report unavailable.

Co-authored-by: dgrant <dgrant@users.noreply.github.com>
…3018)

The root router listed every skill and ended 'When in doubt, invoke the
skill'. Current Claude models follow that literally: they tried to invoke
skills a user had turned off in Claude Code's skillOverrides (which gstack's
own disabled_skills render cannot see), and borderline requests tipped into
full workflows. The router now routes only to skills in the session's
available-skills list and names when to answer directly; the CLAUDE.md
routing block skill-start offers says the same.

Co-authored-by: Rekin226 <Rekin226@users.noreply.github.com>
…hine (#3016)

Spawned sessions auto-choose the recommended option except for destructive
or irreversible choices. Main already withholds the artifacts-sync consent
prompt from spawned sessions; the remaining gap was any other prompt whose
recommended option grants a consent or syncs data off the machine. Every
spawned directive (skill-start's block, the escape sentence, the Conductor
deny reason and the AUQ-error fallback) now names that as irreversible. A
consent the user already gave interactively stays in force.

Co-authored-by: ekson73 <ekson73@users.noreply.github.com>
…v secrets (#3048)

A credential-named parameter or prop with an unquoted code value
(`session: SessionState,`, `key={turn.requestId + turn.role}`,
`apiKey={settings.apiKey}`) cleared the entropy gate and blocked pushes as
a MEDIUM env.kv finding. One rule replaces the PR's two keyword heuristics:
a value that reads as a code name (no digits, word-like camelCase or dotted
parts) with a code terminator, or a brace expression of such names with no
quoted literal, is source syntax. Paired controls keep firing on quoted,
brace-wrapped, concatenated, YAML-bare and random-letter literals.

Co-authored-by: tianxchen <tianxchen@users.noreply.github.com>
Claude Code runs gstack's hook shims through /bin/sh; a shim that does not
parse exits 2, which for a PreToolUse hook blocks the tool call in every
session until someone finds the file. Before any hook registration is
healed or written, setup now runs bash -n on each registered shim and a Bun
parse of its TypeScript entry, and stops with the file, line and fix. A
lean rewrite of the PR's idea (one gate block plus a test that runs it).

Co-authored-by: BenjaminDSmithy <BenjaminDSmithy@users.noreply.github.com>
…heckout's bundle (#3026)

On Windows a host runtime root (~/.codex/skills/gstack and the other
env-var hosts) holds file copies of browse/dist and no node_modules, so
its server-node.mjs could not import playwright and every browser skill
died (the module-scope server.ts half was fixed in v1.91.19.0). setup now
records the source checkout in every runtime root's .source-path, and the
CLI runs that checkout's bundle when the adjacent one cannot reach
playwright. Verified by unit layout tests and the Windows CI lane, not
live on Windows.

Co-authored-by: ubay887 <ubay887@users.noreply.github.com>
)

Copilot CLI on Windows ran gstack's extensionless helpers straight from
PowerShell, which opened an app picker, and bare bash can resolve to WSL.
The Copilot tool glossary (rendered into every Copilot skill) now says to
run each bash block in Git for Windows Bash by its full path and never to
translate a block into PowerShell. The PR's PowerShell repair skill and
README section are not taken.

Co-authored-by: nareshh74 <nareshh74@users.noreply.github.com>
…ecovery that keeps the work

Review follow-up to the #3050 fix. The summed batch read and the narrowed
parent loop now report too_large with the real size instead of a plain
error naming a hard-coded 32 MiB. The denial names the size and the cap,
and gives the recovery that keeps work (/context-save, new session,
/context-restore, /autoplan) with a docs anchor. A test seam that can only
lower the cap replaces the 33 MiB fixture.
…e shape

Review follow-up to the #3048 fix. The word-shape heuristic also exempted
real secrets made of words (API_KEY=VelvetRiverOrbitSunset; in a .env).
The scanner now takes the file path (ScanOptions.sourcePath): the pre-push
hook scans the pushed diff per file with its +++ b/ path, and gstack-redact
--from-file passes its path. Only in a TypeScript/JSX file is an unquoted
value after ':' or a JSX brace of names treated as source; the same line in
.env/YAML, or with no path, is scanned as a literal, and the jwt pattern
still fires in .ts files.

Co-authored-by: tianxchen <tianxchen@users.noreply.github.com>
…ding

Live check (Claude Code 2.1.284): a skill set to "off" in skillOverrides
is absent from the session's skill list while its sibling is listed, and
both are listed without the override, so 'route only to skills in your
available-skills list' holds.
… code pages (#3029)

Step 3.5 offered --dream for any source with pages, including one that
holds only markdown (synced with gbrain's default strategy), where a build
cannot help, and the injected CLAUDE.md guidance told future sessions to run
--dream for any count: 0. On gbrain >= 0.60, code-def for an impossible
symbol answers .status (probed live against gbrain 0.60.96: ready for a
code source, out_of_scope for a markdown-only one). Step 3.5 now probes the
pinned source first, reports the cause instead of asking on out_of_scope,
and keeps today's offer when the probe is unknown (older gbrain, an error).
gstack's own sync uses --strategy code, so the PR's soft-delete claim does
not apply to gstack's path.

Co-authored-by: syong <syong@users.noreply.github.com>
…line (#3032)

The landed gate stopped setup before any registration, so one unparseable
hook left every other hook unregistered. On the Claude install the canonical
root is the checkout Claude Code runs hooks from, so there is no staged swap
to abort: setup now registers the hooks that parse, refuses the ones that do
not with file and line, finishes the install and exits non-zero, saying it
is a gstack bug and that a skipped hook keeps running from the checkout.

bin/gstack-hook-check derives its list from setup's _hook_command_path calls
plus the autoplan phase-publication hook (a test keeps them equal), parses
each shim with its shebang's interpreter, and bundles each TypeScript entry
with its local imports (packages external) into a temp dir, so a broken or
missing import, or a missing entry, fails.

Co-authored-by: BenjaminDSmithy <BenjaminDSmithy@users.noreply.github.com>
… checkout moves

bin/gstack-session-update fast-forwards the live checkout before setup runs,
and Claude Code runs hooks straight from it, so setup's gate cannot protect
an auto-update. After the Bun floor check the updater extracts the incoming
revision with git archive and runs bin/gstack-hook-check on it; a failure
holds the update like bun-too-old, records hook-does-not-parse with file:line
in the update status, and the next session start says the current hooks keep
running. Fixture-remote tests cover a broken shim, a broken imported module
and a parseable control.

Co-authored-by: BenjaminDSmithy <BenjaminDSmithy@users.noreply.github.com>
On Windows the absolute bash path has a space, so the stub never ran and
every case read 'gh not logged in' (windows-free-shard 1).
The PATH-only stub bin could not run its stub on Windows (every case read
'gh not logged in'). Stub cases now keep the real PATH with the stub first;
only the no-gh case drops directories holding a real gh.
@capy-ai
capy-ai Bot merged commit 28f1385 into main Oct 6, 2026
79 checks passed
This was referenced Oct 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant