Repository navigation
v1.91.32.0 fix: Codex works from zsh, free text never enters shell commands, honest failures - #3057
Merged
Merged
Conversation
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>
…routing sentence in the autoplan fixture
…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.
This was referenced Oct 6, 2026
Closed
Closed
5 tasks done
This was referenced Oct 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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-byon the commit that uses their diagnosis.Release promises
CODEX_MODEL: invalid.gstack-codex-probeandgstack-egress-lib.shnow share one self-locate block that works under bash and zsh. Any other shell getsCODEX_MODE: helper_unavailablewith a fix link, instead of reading as "not logged in". A free class test derives every sourced helper (nested sources included) from the generated skills. It sources each one under bash, zsh and dash, from an unrelated cwd, and makes one real call per helper. CI installs zsh in the free lane andDockerfile.ci, and the macOS job sources the probe from zsh.mktempfile under the project's.gstack/tmp/(excluded from git). The agent writes the text into it with its file-write tool, and the command reads it via--body-file,-F body=@or stdin. There is no heredoc fallback. If the file was never written, nothing is sent, and the skill prints the exact command to send it by hand..gstack/tmp/is the only location Claude Code 2.1.284 writes without a prompt inacceptEdits; this was probed headless.fix;id, whichgit check-ref-formataccepts.$(...), apostrophes,EOFlines) go through the real generated text and arrive byte for byte.quota_exhaustedrelays Codex's line with the reset time, is cached 15 minutes, makes no more Codex calls, andGSTACK_CODEX_PROBE_RETRY=1re-probes early. A bare 429 isunverified (rate_limited). Matching reads only Codex's own error lines, never an echoed prompt.identityfailure #3050):too_largeon every read path, with the size and a recovery that keeps the work.browse chainwith empty or failed input (fix(browse): chain reads piped stdin on Windows #3039): usage error, exit 1, before any daemon boots..source-path, guarded against version skew.docker.exeis found and the report says native Windows Docker transport is not supported yet (static only). A Java repo is no longer asked forrequirements.txt.scripts/ship-measure.tsmeasures a red case alone with per-kind panels: rule 10/9; behavior 4 panels of 3; judge 10 outputs at 2/3. It enforces an admission budget (asks above $2 a trial, stops at $25 a case), allows 3 repair rounds, keeps diagnostic-only artifacts and prints the PR table. Free-shard reruns run with the flaky retry off. /ship runs classify → measure → fix → re-measure → gate once. Controls areship_measure_*config keys. A seeded-flake paid case (periodic, behavior) passed 3/3 locally on Claude Code 2.1.284.Also in this wave
auto-decide-preserved). The captured run replays as the known Step 0E handoff-line class: the model ran the helper and then paraphrased its line. A reminder beside the line measured 1/10. /plan-ceo-review now declares a Claude-only PostToolUse hook that shows the helper's line as a system message. Diagnostic measurement on this branch: 10/10, with the line visible in every trial while no trial's chat led with it. The early-question harness admits that hook by its exact command only."off"inskillOverridesis absent from that list. The router now says when to answer directly; "When in doubt" is gone everywhere.--from-filepasses its path (fix(redact): ignore TypeScript parameter types and dynamic JSX values #3048).ghis missing or logged out, or the remote is not GitHub (Greptile awkwardness #3020).--dream, verified live against gbrain 0.60.96 (fix(sync-gbrain): a code-verbcount: 0is not a reason to run --dream, and a markdown-only source is currently offered one #3029).GSTACK_DISABLE_GPU=off(browse: two small clarity fixes (WebGL side effect of the macOS GPU flags, and the config-mismatch message) #3030).osv-scanner --config=.osv-scanner.tomlon this head: no issues found. Three advisories with no usable fix get justified ignores expiring 2026-11-30: braces is build-time only (a test checks the page), sprintf-js, and katex.Validation
4db6f20: 16 of 17 shards passed. The one failure,cso-scanner-clion a Docker-less VM, was diagnosed there and fixed in1a3a603, and the file passes. That fix changes only that test file.typecheckis clean andtypecheck:testhas no new diagnostics. Parity, archaeology, module-size and spawnSync tripwires pass, and all-host generation is fresh.ship-measure-seeded-flake: 3/3.auto-decide-preserved: 1/10 with the reminder, then 10/10 with the hook.Not verified
windows-setup-e2e.yml. The PowerShell known-folder lookup, Copilot's interpreter choice and actual Docker operation are unverified until those lanes run./plan-tunefree-text tune events, native Windows Docker, and a readiness command.