# TODOS ## NEXT PRIORITY ### P3: Oct 8 fix wave, safety hooks follow-ups (filed 2026-10-08) Left open by the PowerShell/NotebookEdit hook fix (v1.91.47.0, #3067), each with its reason. - **Forced overwrite patterns for `/careful`** — `Set-Content -Force` / `Out-File -Force` over an existing file (and the Bash `>` overwrite twin) still pass. Deferred: the Bash side has no overwrite pattern either, and adding one is a new family for both shells, not PowerShell parity. **Effort:** S. **Priority:** P3. - **Quote-aware masking in `check-careful.sh` (#1060)** — `git commit -m "rm -rf build"` still asks. Deferred: masking quoted text inside a safety hook can open bypasses (PR #1110's `echo hi; rm -rf ~` showed how); it needs its own design with the #1110 strings as controls. **Effort:** M. **Priority:** P3. - **Hooks on Windows without Git Bash** — the frontmatter hook commands run `bash -c ...`, and Claude Code runs hook commands through PowerShell when Git Bash is absent, so the guards cannot start there. gstack requires Git Bash today; a native PowerShell hook launcher would lift that. **Effort:** M. **Priority:** P3. ### P2/P3: iOS QA fix-wave follow-ups (filed 2026-10-07, v1.91.38.0) Left open by the iPad and route-drop release, each with its reason. - **Device verification of v1.91.38.0** — the iPad bootstrap, route-drop recovery on a real Xcode 26 tunnel drop, the multiple-devices error and the `NOT READY` path were proven only against the simulated device; the changed `StateServer` passed `swiftc -parse` but no Apple-SDK build. Run `test/skill-e2e-ios-device.test.ts` and the Swift build lane on a Mac with an iPhone and an iPad. **Effort:** S. **Priority:** P2. - **`GSTACK_IOS_LAUNCH_ENV` (split from #1796, @Bmathews721)** — pass launch environment to the app through `devicectl process launch`. Nothing equivalent exists on main; land it as its own small PR with credit, then close #1796. **Effort:** S. **Priority:** P2. - **A restarted daemon still relaunches the app once** — a new daemon has no session bearer and the one-use boot token is gone. Fixing it needs either a device-side re-mint with proof of the old session or a persisted bearer under the state root, and both change the token's security model. Needs a design. **Effort:** M. **Priority:** P3. - **iPad Stage Manager and multiple scenes** — overlay and window selection (`frontmostWindow`, `searchRoots`) are unverified on iPad multi-window layouts. **Effort:** S (verify) / M (fix). **Priority:** P3. - **Stale "Session warm-start" phase in `/ios-qa`** — Phase 0 describes an `ios-qa-session.json` cache that no daemon code writes. Implement it with the state-root chain or remove the phase. **Effort:** S. **Priority:** P3. - **Sanctioned input-routing hook for SwiftUI gestures** (#1975 finding 2) — synthesized touches miss `DragGesture` on iOS 26; a documented `#if DEBUG` hook would let gesture-driven apps route `/tap` and `/swipe` to their own handlers. **Effort:** M. **Priority:** P3. ### P1/P2: /cso capacity follow-ups (filed 2026-10-08) Left open by v1.91.42.0, which lifted the snapshot file-count ceiling. - **Tracked symlinks refuse the whole /cso run** — `capture()` fails closed on any tracked symlink ("Symlink or special source file"). 5 of 8 mid-size OSS repos measured for v1.91.42.0 stop there (django, rails, terraform, grafana, vscode; 1-10 symlinks each, mostly test fixtures). Recording them as unread exclusions in the manifest, like dependency trees, is a security design call for Garry. **Effort:** M. **Priority:** P1. - **64 MiB aggregate source cap (#2993)** — files over 1 MiB are withheld from the audit but still read and counted. Stream-hash them without counting toward the cap, report them as unread coverage, and add an admission estimate to `doctor`. grafana (211 MiB) and vscode (540 MiB) hit it once symlinks are out of the way. A `GSTACK_CSO_SNAPSHOT_MAX_BYTES` knob was deferred with it. **Effort:** L. **Priority:** P2. - **`inspect` prints the whole public manifest** — about 2.8 MB of stdout for 5,000 files, more than an agent's tool output keeps. The skill reads paths from it, so trimming it is a skill-contract change with evals. **Effort:** M. **Priority:** P2. - **Repair bundles carry every transformation** — `lib/cso/verification.ts` binds the full transformation list into a 1 MiB immutable bundle. Only runtime verification writes bundles, and no qualified runtime catalog exists yet. **Effort:** M. **Priority:** P3. ### P2/P3: iOS QA fix-wave follow-ups (filed 2026-10-07, v1.91.38.0) Left open by the iPad and route-drop release, each with its reason. - **Device verification of v1.91.38.0** — the iPad bootstrap, route-drop recovery on a real Xcode 26 tunnel drop, the multiple-devices error and the `NOT READY` path were proven only against the simulated device; the changed `StateServer` passed `swiftc -parse` but no Apple-SDK build. Run `test/skill-e2e-ios-device.test.ts` and the Swift build lane on a Mac with an iPhone and an iPad. **Effort:** S. **Priority:** P2. - **`GSTACK_IOS_LAUNCH_ENV` (split from #1796, @Bmathews721)** — pass launch environment to the app through `devicectl process launch`. Nothing equivalent exists on main; land it as its own small PR with credit, then close #1796. **Effort:** S. **Priority:** P2. - **A restarted daemon still relaunches the app once** — a new daemon has no session bearer and the one-use boot token is gone. Fixing it needs either a device-side re-mint with proof of the old session or a persisted bearer under the state root, and both change the token's security model. Needs a design. **Effort:** M. **Priority:** P3. - **iPad Stage Manager and multiple scenes** — overlay and window selection (`frontmostWindow`, `searchRoots`) are unverified on iPad multi-window layouts. **Effort:** S (verify) / M (fix). **Priority:** P3. - **Stale "Session warm-start" phase in `/ios-qa`** — Phase 0 describes an `ios-qa-session.json` cache that no daemon code writes. Implement it with the state-root chain or remove the phase. **Effort:** S. **Priority:** P3. - **Sanctioned input-routing hook for SwiftUI gestures** (#1975 finding 2) — synthesized touches miss `DragGesture` on iOS 26; a documented `#if DEBUG` hook would let gesture-driven apps route `/tap` and `/swipe` to their own handlers. **Effort:** M. **Priority:** P3. ### P2/P3: Oct 7 fix-wave follow-ups (filed 2026-10-07) Left open by the Oct 7 wave (docs/designs/FOLLOWUP_WAVE_2026_10_07.md), each with its reason. - **/autoplan permission cards after a background reviewer finishes (Claude Code 2.1.292)** — once a background reviewer's completion notice starts a new turn, Claude Code stops applying the skill's allowed tools, so Reads outside the project (the close packet, the next phase's section file) show permission cards. Seen in both foreground and `--bg` PTY runs. Options: keep those artifacts readable without a card, or detect it and explain it once. **Effort:** M. **Priority:** P2. - **macOS numbers for the bounded journal read** — the guard's 120 MiB read meets the Linux budget (0.43-0.87 s, at most 235 MiB peak RSS on 4 vCPU) and a resumed 102 MiB session entered Phase 1 end to end. The macOS run is recorded by dispatching `.github/workflows/measure-journal-read.yml`, which GitHub only allows once the workflow is on main. **Effort:** S. **Priority:** P3. - **Every-transition manual /autoplan session on 2.1.292** — the replay fixtures and the scripted live boundary (foreground and `--bg`) cover the guard; one full recorded run through every phase transition is still to do. **Effort:** S. **Priority:** P3. - **Remove the sourced Codex probe (on or after 2026-10-21)** — delete the sourcing path of `bin/gstack-codex-probe`, its deprecation line, the zsh self-locate block, the probe's entry in the zsh sourced-helper test and `test/helpers/codex-probe-sourcing.ts`. **Effort:** S. **Priority:** P3. - **Move the remaining PR and issue writers to gstack-post** — /document-release's PR body and title edit (with its own scan) and the test-failure triage issue (`--assignee`) still call gh/glab directly. **Effort:** S. **Priority:** P3. - **`gstack-doctor --json`** — machine-readable rows for CI and bug-report bots. Deferred as DX polish. **Effort:** S. **Priority:** P3. - **Doctor guard check against a named session journal** — run the guard's reader on a given journal from `gstack-doctor`. Deferred: doctor runs outside a session and the design is unclear. **Effort:** M. **Priority:** P3. - **One secret scanner for artifacts sync** — replace `bin/gstack-brain-sync`'s Python scanner (and the hook copies written by init and restore) with `lib/redact-engine.ts`. Deferred: a cross-language rewrite outside the per-file hold. **Effort:** L. **Priority:** P3. - **Timed novice install journey** — measure a fresh install to a first skill run, end to end. Deferred: outside a fix wave. **Effort:** M. **Priority:** P3. - **Native Windows Docker transport for /cso (#3028)** — `lib/cso/docker.ts` accepts only `unix:///` endpoints, so /cso on Windows reports "static assessment only" even with a trusted `docker.exe`. Add named-pipe transport with the same trust checks. **Effort:** L. **Priority:** P2. ### P2/P3: reliability follow-ups deferrals (filed 2026-10-04, v1.91.30.0) Deferred from the approved reliability follow-ups plan (docs/designs/RELIABILITY_FOLLOWUPS_2026_10.md), each with its reason. - **Free-suite git hang behind shard neighbors (B5): Bun spawnSync loses the child's exit (oven-sh/bun#34069, open upstream)** — CI shard 1 (PR runs 37242691914 and earlier) timed out `execFileSync`/`spawnSync` git calls in redact-prepush-rebase-force-push, render-sections-provenance and shared-libs-stage-actor. A watcher on Ubicloud caught it: every "hung" git is a zombie (exited, never reaped) while the `bun test` main thread runs, matching the upstream report. CI's shard-1 file list reproduces it in about 3 of 60 runs (none of 20 without pty-workspace-trust, not significant). Next step: move the git calls in shared fixture helpers to async spawn with a hard timeout, or take a Bun release that fixes #34069. **Effort:** M. **Priority:** P2. - **Judge rubric anchors (C1, needs Garry: EVAL_POLICY)** — the pre-registered control panels (`docs/evals/judge-controls-2026-10.md`, 36 calls) showed every workflow judge separates gross breakage, but the qa workflow judge passed a /qa bundle with Phase 10 Report removed (no sample noticed) and the review judge passed /review with Step 3 removed (two of three samples noticed it and rated it minor); no positive sample scored 5 on any dimension. Missing-step coverage now lives in `test/workflow-required-steps.test.ts`. Proposal: anchor completeness/actionability 4 and 5 to named deliverables and inputs, as a pre-registered EVAL_POLICY change. **Effort:** M. **Priority:** P2. - **auto-decide-preserved: the CEO handoff line no longer depends on the model** — periodic run 37272185151 went red because the model led its chat with a paraphrase; a reminder beside the line measured 1/10. The Oct 6 wave shows the line through /plan-ceo-review's PostToolUse hook (system message), which measured 10/10 with the line visible in every trial while no trial's chat led with it. The native detector still credits only a chat that begins with the line; if the screen path ever stops carrying the hook message, make the detector read the hook's record instead. **Effort:** S. **Priority:** P3. - **Named red: ship-docsync-late-result on PR run 37237194905** — the model wrote its report to a mistyped shard root (`…-3GanyY` for `…-3GanyU`) at call 20, disclosed it, then wrote the real report at the right path. The authority detector is correct (the file was created outside the fixture); `test/docsync-authority.test.ts` replays the capture. If any docsync case writes to a near-miss shard path again, give the model a short stable fixture root (env var or fixed short symlink) instead of random tokens to copy, without loosening the authority check. **Effort:** S. **Priority:** P2. - **PTY sessions are cost-unknown** — `test/helpers/pricing.ts` excludes cache-write charges, so PTY trials stay `cost_known: false`. Price them from native transcript usage once pricing covers cache writes. **Effort:** S. **Priority:** P3. - **Custom SDK query providers stream no partial messages** — overlay-case, the ship hook/skip actors, workflow-boundaries and the setup-gbrain sandbox record raw events, so their ledger rows carry no stall evidence (never `provider_stall`). Let them drop `stream_event` rows and opt in to stream liveness. **Effort:** S. **Priority:** P3. - **Name PTY sessions by case** at their call sites so multi-case shards attribute ledger rows (single-case shards already do). **Effort:** S. **Priority:** P3. - **Red lines link the native-captures artifact** — they name the slice artifact; `native-captures-` embeds the job id, which the report job does not know. **Effort:** S. **Priority:** P3. - **EVAL_POLICY v2: provider_stall as INFRA** — decide with two censuses of `eval:pass-rates --reds` cause data (labels only today). **Effort:** S. **Priority:** P3 (Garry). - **Detector convert candidates (B2)** — `docs/evals/detector-inventory.md` lists 38 phrase-only checks with a structured source (top: S5 screen-first auto-decision, PTY plan_ready/silent_write from journal tool calls, setup selectors keyed on wording, the bws READY probe), and periodic "surface" checks that match the injected SKILL.md body (context-restore-*, scrape-prototype-path). **Effort:** M. **Priority:** P3. - **Retain the owned transcript tail in floor captures** — PR run 37176835584's public transcript never showed the pending Edit, so the B3 parser fix may not have been sufficient there. **Effort:** S. **Priority:** P3. - **CEO decision procedure latency** (~60 s per question: grid, save, Read-back, ask) bounds plan-ceo-mode-routing's 240 s post-selection window. Named, not cut. **Effort:** M. **Priority:** P3. - **Value-card JSON wording** — two of three qa-only judge samples still say "written JSON keeps full values" names no file. Name the JSON per mode (ship Step 7, /test-audit's sidecar) and drop the clause where no JSON carries cards. **Effort:** S. **Priority:** P3. - **Windows check of E4's private object directory** — `GIT_ALTERNATE_OBJECT_DIRECTORIES` uses `;` on Git for Windows (only matters when alternates are already set) and the `cygpath -m` conversion is unverified there. **Effort:** S. **Priority:** P3. - **Fresh /ship marathon case** — the marathon lane runs a fresh /plan-eng-review; a fresh /ship journey case is new harness work. **Effort:** M. **Priority:** P3. - **Refresh the E5/E6 duration seeds** — `codex-multiblock-live` (180 s) and `design-model-smoke` (90 s) are estimates in `scripts/paid-test-durations.json`; refresh them with `--write-durations` from their first census, and close "Periodic paid smoke for the default design model pairing" once it has run there. **Effort:** S. **Priority:** P3. - **Env-var hosts: optional runtime files outside the runtime root** — the Chrome extension lookup in /open-gstack-browser and /connect-chrome, and the prose pointers to `$GSTACK_ROOT/docs/...` and `$GSTACK_ROOT/scripts/...` (question-split guide, jargon list, question registry) name files the Codex/Factory runtime roots do not link. Executed fences are covered by `test/env-host-runtime-assets.test.ts`; these reads are not. **Effort:** S. **Priority:** P3. - **Product A/B against the stock host agent** — compare gstack end to end with the stock Claude Code/Codex agent on product outcomes (the overlay harness covers model-level deltas only). Its own project. **Effort:** L. **Priority:** P3. ### P1–P3: test/eval/CI audit wave follow-ups (filed 2026-10-04) From the approved 2026-10 test/eval/CI audit plan; the audit PR files these. - **Post-merge audit metrics (due merge + 7 days)** — run `bun run test:health --since-days 7` and record the PR full-fallback rate, recorded PR-lane spend per merged PR (target: down at least 50%), cancelled slice-minutes per week, push-to-verdict p50/p95 and the free flaky-pass rate in `docs/test-audit-2026-10.md` as a dated follow-up. **Effort:** S. **Priority:** P1. - **Census reliability metric (due after the fourth scheduled census after merge, about merge + 28 days)** — run `bun run test:health --since-days 28` and record expected failed trials per periodic run (target at most 1.0) and per gate census (target at most 0.5), each as raw trial failure rate, false-blocking probability and the old-policy re-aggregation. A miss opens a P1 entry here with the per-kind, per-failure-class breakdown. **Effort:** S. **Priority:** P1. - **Remove the one-release command stubs** — delete the retired package scripts (`test:evals`, `test:evals:all`, `test:e2e`, `test:e2e:all`, `test:gate`, `test:periodic`, `test:codex`, `test:codex:all`, `eval:bg`, `eval:bg:all`, `eval:flake-rank`, `eval:watch`, `test:audit`), `scripts/retired-command.ts`, `test/retired-commands.test.ts` and CONTRIBUTING.md's "Retired commands" table. They exist only to redirect old agent memories and docs. **Depends on:** the audit release shipped. **Effort:** S. **Priority:** P2. - **Reclaim `test:gate` / `test:periodic` for the sharded runner** — after the stubs are gone, point the short names at `test-paid-shards.ts` and retire the `:sharded` suffix. **Depends on:** stub removal. **Effort:** S. **Priority:** P3. - **One diff-aware command for free + paid checks** — plan `test:quick` and the paid PR profile from the same touchfile closure so one command answers "what does my diff need?". **Effort:** M. **Priority:** P3. ### P2/P3: severe fix wave follow-ups (filed 2026-10-03, v1.91.19.0) Deferred from the approved severe fix wave (docs/designs/SEVERE_FIX_WAVE_2026_10.md), each with its reason. - ~~**Enforce the Bun floor at setup (#2815)**~~ — done in v1.91.30.0: setup refuses Bun below 1.3.3 and warns below 1.4.2; auto-update and /gstack-upgrade check the incoming floor before moving the checkout. Original note: — `engines.bun` is now `>=1.4.0` (the CI pin), but Bun does not enforce `engines` and setup never checks the version. Bun older than 1.3.3 silently ignores `--no-compile-autoload-dotenv` and `--no-env-file` (verified with 1.3.2), so D0's protection against a project's `.env`/`bunfig.toml` is silently off there. Setup should refuse or warn below the floor. **Effort:** S. **Priority:** P2. - **Windows Node CLI lane for Smart App Control (E3; #2596, #2595, #2124)** — a `dist/browse` wrapper would shadow `browse.exe` for every Windows user; launcher precedence (browse vs browse.exe vs browse.cmd under Git Bash and cmd) and the node-missing message need a Windows SAC machine to verify. **Effort:** M. **Priority:** P2. - **C8 router wording behind a routing panel** — disabled skills now leave the router, but the "When in doubt, invoke the skill" wording change (Tier 3) was not run through a routing eval panel. **Effort:** S. **Priority:** P3. - ~~**Cross-block variables on fresh-shell hosts: make-pdf `$P`**~~ — done in v1.91.30.0: env-var hosts re-derive `$P` in every block (MAKE_PDF_BIN honored). Original note: — make-pdf "exports" `$P` for later blocks, which Codex and the other env-var hosts lose between blocks (same class as `$B`/`$D`, which the shared prelude now re-derives). Add `P` to the runtime prelude or resolve it per block. **Effort:** S. **Priority:** P2. - ~~**#2709's recorded-Chromium reap never runs on Playwright 1.62**~~ — done in v1.91.30.0: the owned headless launch records the browser PID over CDP `SystemInfo.getProcessInfo`. Original note: — Playwright 1.62's `Browser` has no `process()`, so `chromiumProcInfo` is always null and the cleanup is a no-op (verified by probe). Record the PID another way (CDP `SystemInfo.getProcessInfo` or the launch server). **Effort:** S. **Priority:** P2. - **#2670's bash half in `bin/gstack-brain-sync`** — the TypeScript stage verdict now reports a 0-page artifacts source; the bash brain-sync still has no `index_failed` status file or page-count probe. **Effort:** S. **Priority:** P3. - **Navigation guard acts after the request is sent** — Playwright routing cannot see redirect hops, so a blocked hop resets the tab and fails the command after the request left. Pre-send blocking needs CDP Fetch interception, including out-of-process iframes. **Effort:** M. **Priority:** P3. - **Redaction repo allowlist (#2598)** — a per-repo `+++ b/` skip list (generated `*.svg`/`*.excalidraw`, #2827) for noise context rules cannot cover. New config surface, so out of the wave. **Effort:** M. **Priority:** P2. - **Global-discover Codex session schema (#2750)**, **absolute bun path for compiled browse spawns (#931; macOS repro unclear)** and **GitLab CI `curl | bash` (#1713)** — out of the wave's scope. (The ios-qa boot-token items #1837 and #1975 landed in v1.91.38.0.) **Priority:** P3 each. - **Upstream gbrain batch lookup** — a per-slug existence lookup and a separate `pending` list in `gbrain import --json`, so the landing check need not list a whole source and spawn `get` per page. **Effort:** M (upstream). **Priority:** P2. - **Memory follow-ups** — record repo identity for gbrain sources at registration (prune can prove ownership of a pre-wave source only from the same repository's main checkout); a deliberate migration of pre-wave transcripts out of `default` into per-repo sources (needs gbrain-side page moves); decide #2778's "nearest existing ancestor" attribution for deleted worktrees (risk: attributing to an unrelated parent repo like a dotfiles repo). **Priority:** P3 each. - **G2 on the TS twin** — `lib/bin-context.ts` (the Windows fallback) shares the common-dir slug keying but does not record former worktree buckets. **Effort:** S. **Priority:** P3. - **Codex follow-ups** — post-run `codex_sandbox_unavailable` telemetry (only the preflight logs it today); the Q2 first-use notice covers Codex only, not the Codex host's Claude Code outside voice; the bash-native timeout watchdog cannot reap grandchildren when `pkill` is missing; document enabling unprivileged user namespaces in common containers. **Priority:** P3 each. - **Live Codex multi-block check as a periodic paid case** — the wave ran it once by hand (fresh `CODEX_HOME`, fresh clone, `./setup --host codex`, one multi-block skill). Make it a periodic case so a regression shows up weekly. **Effort:** M. **Priority:** P2. - **/review's working-tree fingerprint under Codex's default sandbox** — the live Codex check (v1.91.19.0) showed `bin/gstack-wtree` exits 1 inside `codex exec -s workspace-write`, because Codex mounts `.git` read-only and the fingerprint writes untracked content into `.git/objects`. `gstack-review-log --start review` then fails with `cannot capture a diff review without a working-tree fingerprint` (loud, not a false pass), and `git fetch` cannot write `FETCH_HEAD`. Use a private object directory (`GIT_OBJECT_DIRECTORY` + `GIT_ALTERNATE_OBJECT_DIRECTORIES` under `$TMPDIR`) for the fingerprint, and report the fetch as stale-base coverage. **Effort:** S. **Priority:** P2. - **Closed by the wave's evals2 lane (run 37162480720):** Codex paid evals now run commands in CI (host-run job; all 8 Codex cases executed real commands), ship-exploratory-late-input no longer ends `inconclusive` (capture names the probes to rerun after an input change), plan-eng-multi-finding-batching's checker and office-hours-brain-writeback's prompt are fixed (3/3). plan-eng-review-artifact (0/4 since #3017) measured a shortcut prompt that skipped the workflow; it now drives the real interactive /plan-eng-review in a PTY. A fresh run needs more than its 600 s budget (498 s pass; 595 s timeouts in census 37174266054 and a local run), so the periodic case resumes at Test review from that census run's real Scope Challenge ledger (pass, 364 s) and the fresh run is the marathon case plan-eng-review-artifact-full. - **Gate-outcome telemetry** — count `not_run`/`unavailable` outcomes per reason code from `lib/gate-outcomes.ts` so the most common gaps get fixed first. **Effort:** S. **Priority:** P3. - **/gstack-upgrade redesign around the install registry**, a **marketplace distribution channel**, and a **placeholder convention for generated bash** (`` vs real syntax in fences). **Priority:** P3 each. - **Design CLI health subcommand** — the DESIGN SETUP probe uses `--version`; a richer `design health` could check the API key and model access too. **Effort:** S. **Priority:** P3. - **Autoplan publication hook under cmd.exe** — `scripts/resolvers/composition.ts` still registers `bash -c '