Files
gstack/docs/designs/fork-port-residual-2026-09/REPORT.md
T
Garry TanandClaude Fable 5.1 529ee9ab46 docs: README Chromium note outside the CLAUDE.md fence; report banner stripped; deferrals name the four gate sites
- README: the Chromium troubleshooting paragraph sat inside the CLAUDE.md
  snippet code fence, so copy-paste put it into users' CLAUDE.md. Moved to
  the troubleshooting list.
- docs/designs/fork-port-residual-2026-09/REPORT.md: the scratch-run
  preamble banner is gone; SHAS.md re-hashed.
- TODOS: the ownership-gate deferral names the four sites and the
  marker-path idea for the fork-with-banner residual.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 17:28:00 +00:00

62 KiB

Is there anything else worth taking in from time-attack/gstack?

Evaluation of the time-attack/gstack fork (Sina Matian, MIT; fork main 0aca1f77, tip of the "GStack 2 public beta" release merged as PR #53 at 41927ca8, 2026-08-10; merge-base 7c9df1c5) against upstream garrytan/gstack main v1.79.0.0 (2026-09-01). Sources: /tmp/ta-eval/summary.json, residual-index.json (287 items, read in full), records-other.json (128 items), records-residual.json (per-item lookups), refute-batch-1..6.json (48 items) and the appended adversarial refuter verdicts. Upstream claims below were re-checked by grep at HEAD where cited as file:line.

1. Bottom line

After the seven directly merged fork PRs, the iOS suite, port waves 1 and 2 (v1.63, v1.65) and the security sweep (v1.67.1), the fork's 583 raw candidates collapse to 415 canonical items, of which 128 are already absorbed, superseded or not applicable and 287 carry some residual. The panel rated 269 of those 287 as take or take-partial, but when the 48 top-ranked candidates were put through adversarial refutation only 14 survived, and two of those are the same defect counted twice, so the honest answer is about a dozen genuine ports plus a cluster of ten small grep-verified bin/browse fixes, with a further 39 panel-P1 items that were never refuted and are listed in section 5a so nothing is silently misfiled. Almost none of it is "GStack 2": the surviving items are correctness bugs and consent gaps in upstream's own code that the fork happened to notice, and roughly a third of the shortlist is really "merge a stale community PR the fork carried" (#1509, #2119, #1900, #1777, #1096). The top five by user impact are: (1) ./setup aborting before any skill is registered when Playwright's Chromium download fails (setup:3 set -e, setup:806, setup:850 vs skills at setup:1657); (2) the /freeze deny hook reading a different state dir than /freeze writes, so the boundary fails open whenever GSTACK_HOME is set (freeze/bin/check-freeze.sh:35); (3) /ship Step 5/6 still hardcoding bin/test-lane, Rails and a Ruby eval runner (ship/sections/tests.md.tmpl:9-113); (4) the question-preference PreToolUse hook keying project preferences by cwd basename while the writer keys by owner-repo, so the "never ask again" enforcement layer never fires for any repo with a remote (hosts/claude/hooks/question-preference-hook.ts:300-306); (5) transcript_ingest_mode=off being a documented consent switch that no binary reads (bin/gstack-config:181 is the only occurrence). Safely ignorable: the entire GStack 2 architecture (six dispatchers, fifteen-vector scale system, SHARED-JUDGMENT and VERIFICATION contracts, zero-question budget), the web-data provider stack, PRIVACY.md, issue forms and labels, the multi-OS CI lane, the Node .cjs team hook, and the persona-fleet methodology already parked in TODOS.md.

2. Ranked shortlist — worth taking

Sorted by panel priority, then user_value_score + fit_score. Every item here either survived refutation (refuted=false) or is a cheap fix whose upstream premise I re-verified by grep at HEAD; the latter are flagged as such and clustered.

Footnote on the survivor count: the 14 survivors reflect the final (appended) refutation pass. The residual-index.json prior_refuter field records an earlier pass with a different boundary on 7 of the 48: s1-prewave-transcript-ingest-mode-off and s1-prewave-terminal-ws-extension-id-pin were refuted=true in the earlier pass and refuted=false in the final one; s1-prewave-setup-install-deadline-and-continue, s1-prewave-readme-update-check-disclosure, s1-prewave-review-loosened-inputs-stale-strings, s6-branches-web-data-official-api-first-rule and s1-prewave-auth-json-file-write-removal had no earlier verdict (prior_refuter is null, not false) and are refuted=true in the final pass. This report follows the final pass throughout.

1. /freeze hook state-dir chain (gap2-skillwave-hooks-envelope-and-state-dir-chain-1509), P0, val 8 / fit 10. The hookSpecificOutput envelope half of #1509 is absorbed, but freeze/bin/check-freeze.sh:35 still reads STATE_DIR="${CLAUDE_PLUGIN_DATA:-$HOME/.gstack}" while every writer (freeze/SKILL.md.tmpl:61-64, guard/SKILL.md.tmpl:70-73, unfreeze/SKILL.md.tmpl:31-35, investigate/SKILL.md.tmpl:131-134) resolves through bin/gstack-paths GSTACK_HOME-first. GSTACK_HOME is a documented production knob (bin/gstack-config:16, setup:2135) and the same hook's analytics helper already honours it (careful/bin/hook-extract.sh:71). Result: with GSTACK_HOME set, /freeze prints "boundary set" and the hook hits the no-file allow branch, contradicting its own header ("a boundary that fails open is not a boundary"). Fork refs: bbad1bab (check-freeze.sh hunk), c896016b (test pin); upstream PR #1509 and issue #1459 both OPEN. Port: one line, STATE_DIR="${GSTACK_HOME:-${CLAUDE_PLUGIN_DATA:-$HOME/.gstack}}", mirroring hook-extract.sh; do not port the fork's 12-line probe-and-eval of gstack-paths inside a hook that fires on every Edit. Update test/hook-scripts.test.ts:690-893 to pass {GSTACK_HOME, CLAUDE_PLUGIN_DATA} and add the missing regression (GSTACK_HOME dir with freeze-dir.txt, HOME elsewhere, must deny). Credit @NikhileshNanduri, close #1459/#1509. Effort: human 2-3 hours, CC+gstack 15 min. Refuter's strongest counter: only the fork's shape (subprocess in a hot hook) is wrong; the defect itself could not be refuted.

2. /ship hardcoded test lanes (s9-skills-ship-hardcoded-test-lanes), P1, val 8 / fit 10. ship/sections/tests.md.tmpl:9-22 is still a literal bash block that runs bin/test-lane 2>&1 and npm run test 2>&1 and warns about RAILS_ENV=test bin/rails db:migrate; Step 6 (:44-113) matches app/services/*_prompt_builder.rb, runs EVAL_JUDGE_TIER=full bin/test-lane --eval, and ships a Haiku/Sonnet/Opus price table; ship/SKILL.md.tmpl:381 hardcodes the tests/vitest label pair for the evidence check. This is a direct violation of upstream CLAUDE.md "Platform-agnostic design" and survived both port waves because v1.66.1 wrapped the hardcode in evidence labels instead of removing it. Fork refs: 8bc0a04f, d72133e1 (0aca1f77:skills/ship/references/sections/ship/tests.md); upstream issue #1069 and PR #1102 (@JiayuuWang) OPEN. Nothing from the fork transfers (its version is a 2.0 legacy overlay); this is upstream's own deletion-heavy rewrite: Step 5 consumes the command Step 4 ({{TEST_BOOTSTRAP}}) resolved from CLAUDE.md or asked and persisted, one evidence label per resolved command; Step 6 conditional on a CLAUDE.md-declared eval command; Step 16 evidence check becomes repeated --label/--expect-cmd pairs; same fix at land-and-deploy/sections/readiness-gate.md.tmpl:111-116. Regenerate the three ship goldens; extend test/ship-test-detection-markers.test.ts to reject bin/test-lane|RAILS_ENV|_prompt_builder|EVAL_JUDGE_TIER in rendered output. Effort: human ~2 days, CC+gstack 1-1.5 hours. Refuter's counter: TEST_BOOTSTRAP already says "use CLAUDE.md's command"; does not hold because the literal block still runs afterwards regardless.

3. Playwright Chromium failure becomes a named warning, not a mid-setup abort (gap3-setup-playwright-best-effort-not-fatal), P1, val 9 / fit 9. setup:3 set -e plus the bare bunx playwright install chromium at setup:806 (and the explicit exit 1 at :850) sit under "# 2." (setup:764), ahead of "# 4. Install for Claude" (:1657), migrations (:1943) and hooks (:1990). An offline, proxied, AppArmor-restricted or Bun-on-Windows box ends with zero skills and a re-run that dies at the same line, even though every later step is already best-effort (emoji font :853-864 is warn-only). Playwright already retries the download five times internally, so what reaches this path is real unavailability, exactly when the 35+ non-browser skills matter most. Issues #1900, #1901, #1902, #913, PR #2233 all OPEN on this behaviour. Fork ref: ce9f0f9a (David Miserak; reachable only from origin/backup/pre-isolated-wave-review-2026-07-14). Port: re-implement on upstream's block, not cherry-pick: wrap the install in if ! ( ... ) so set -e cannot abort, a _PW_FAIL_REASON accumulator (chromium-install | windows-no-node | windows-node-modules | post-install-launch), keep _PW_LOCK contention fatal (setup:815-819), keep _clear_playwright_quarantine and the EXIT-trap chaining, loud stderr naming the unavailable skills (/qa, /design-review, /browse, make-pdf, /pair-agent) repeated in the final summary, optionally honour GSTACK_SKIP_PLAYWRIGHT=1 (#913). Add the static test the TODOS.md:199-202 entry asks for. Credit @DavidMiserak, close #1900/#1901/#1902/#2233. Effort: human 2-3 hours, CC+gstack 15-20 min plus one free-suite run. Refuter's counter: the fork's message text is false in upstream ordering and its block-wide "no exit 1" test would flag the lock exit; both are port corrections, not reasons to keep the abort.

4. gstack-relink ownership guard (gap3-relink-ownership-guard-on-prefix-flip), P1 (refuter says P2), val 8 / fit 9. bin/gstack-relink:46-53 _cleanup_skill_entry does rm -f on any symlink and rm -rf on any dir with a symlinked SKILL.md with no readlink check, is called on every flat name in prefix mode (:93) and every gstack-* name in flat mode (:99), and setup runs relink as a self-healing step on every install (setup:1679-1685). Upstream already adopted the opposite policy at every sibling site (setup:1040-1057 readlink gate, bin/gstack-uninstall:204-230), so this is the one remaining unguarded deleter of a class fixed three times. Fork refs: 5ed18036 (smblight, upstream PR #2119 MERGEABLE), 4d5f0309. Port: re-implement, gating on the resolved target being inside $INSTALL_DIR or $RENDER_DIR (relink:43, the fork's */gstack/* pattern misses the render dir and lexically matches non-owned paths); port smblight's two regression tests plus a RENDER_DIR case; decide the flat-mode collision policy at relink:104 (loud skip rather than silent overwrite). Credit @smblight. Effort: human ~2 hours, CC+gstack 15-20 min. Refuter's counter: blast radius is narrower than the panel implied (only prefix-mode users with foreign symlinked skills sharing a name, and only the registration link is lost); accepted, hence P2, but the bug stands.

5. Merge two stale community PRs the fork carried: taste direction-aware confidence (s8-codediff-taste-direction-aware-confidence, val 6 / fit 10) and setup-deploy Render key bytes (s1-prewave-setup-deploy-render-key-bytes, val 6 / fit 10), both P1 (refuter: P2/P3 housekeeping). bin/gstack-taste-update:199-201 computes confidence = approved_count/(total+1) for both buckets, so a rejected preference is pinned at 0 forever; cmdShow's rejected sort at :243 is a no-op and the drift warning at :204 is unreachable; upstream's own test hand-seeds confidence 0.8 to dodge it (test/taste-engine.test.ts:269-270). Fork 944dcab2 is a strict subset of upstream PR #1777 (@jbetala7, MERGEABLE). setup-deploy/SKILL.md.tmpl:104 still says echo $RENDER_API_KEY | head -c 4; fork fc8dded2 is byte-identical to upstream PR #1096 (@JiayuuWang, MERGEABLE). Port: merge #1777 (rebase, line moved 196 to 201) and #1096 as-is, regen SKILL.md, close #1776/#1078. Skip the fork's executable snippet test and tree-wide regex (false positives on test/evidence.test.ts:117). Effort: human 1 hour total, CC+gstack 15 min. Refuter's counter: nothing here is from the fork and severity is overstated (Render keys carry a fixed prefix, unverified); true, but both fixes are correct and free.

6. make-pdf preview fires remote image GETs despite the offline promise (s8-codediff-make-pdf-preview-offline-gate), P1, val 6 / fit 10. make-pdf/src/orchestrator.ts:361-362 writes rendered.html verbatim to the preview path; opts.allowNetwork is read only on the generate path (:170); make-pdf/src/cli.ts:197 parses --allow-network into PreviewOptions where it is dead; render.ts:256-258 deliberately leaves remote <img src> for the inliner that preview skips by design (:331-345). So $P preview beacons once per hotlinked image with no flag passed, and shows images the PDF will not contain. Fork ref: 8fae162d (~30 lines, reuses IMG_TAG_RE/SRC_RE and buildBlockedRemotePlaceholder in diagram-prepass.ts, unit test included). Port: cherry-pick, keep upstream's browseClient.PAYLOAD_TMP_DIR path, export blockRemoteImages, gate in preview() unless allowNetwork === true, add an orchestrator-level assertion. No egress receipt needed: it removes a fetch. Effort: human 2 hours, CC+gstack 10 min. Refuter's counter: "the user's browser fetching the user's own images is not gstack egress" is answered by the documented promise and the dead flag.

7. browse click on a missing selector waits twice (s8-codediff-browse-click-missing-selector-no-second-wait), P1, val 7 / fit 9. browse/src/write-commands.ts:349-369: after .click({ timeout: 5000 }) throws, the catch calls locator.evaluate(el => el.tagName === 'OPTION') on the same locator; Playwright auto-waits, browse sets no default timeout (grep setDefaultTimeout in browse/src = 0), so the 30s library default collides with the CLI's 30s abort at browse/src/cli.ts:828 and the user sees "Command timed out" instead of the precise selector error at ~5s. Fork ref: a84a6e23 (~12 lines: optionLocator.count().catch(() => 0), evaluate only when count === 1, plus a regression test). Port: cherry-pick only that hunk and test; bump the test's own timeout to 10s; reproduce pre-fix timing once with Playwright installed for the CHANGELOG line. Effort: human 2 hours, CC+gstack 10 min. Refuter found no counter beyond CI timing tightness.

8. ios-qa proxy hangs forever on a suspended app (s8-codediff-iosqa-proxy-timeout-hardening), P1, val 7 / fit 9. ios-qa/daemon/src/proxy.ts:57-84 passes timeout: 30_000 to httpRequest but per Node docs the 'timeout' event only notifies; the request must be destroyed manually. No outer deadline exists (grep setTimeout|headersTimeout in ios-qa/daemon/src/index.ts = none), so shouldRefreshTunnel's 504 branch (index.ts:245-256) is unreachable and /ios-qa, /ios-fix wedge with no typed error. Upstream has zero behavioural tests of proxyToDevice. Fork ref: 2c487305. Port: adapt, do not cherry-pick: add the settled guard, req.on('timeout') to 504 upstream_timeout then req.destroy(), res.on('aborted') to 503, opts.timeoutMs; KEEP reject(err) for unmapped codes so index.ts:213-243's ECONNRESET/EPIPE to 503 device_disconnected re-bootstrap still fires; leave out the bundled x-gstack-expected-bundle-id header. Port the bounded-504 test. Effort: human ~2 hours, CC+gstack 15 min. Refuter's counter: a verbatim port would defeat upstream's recovery mapping; adaptation resolves it.

9. transcript_ingest_mode=off is a dead consent switch (s1-prewave-transcript-ingest-mode-off, clustered with residual (d) of s8-codediff-bin-lib-absorbed-batch), P1, val 7 / fit 9. bin/gstack-config:181 (transcript_ingest_mode) echo "off") is the only non-prose occurrence in the repo; bin/gstack-memory-ingest.ts:541-545 gates transcripts solely on --sources (default ALL_TYPES at :234) and bin/gstack-gbrain-sync.ts:1211-1265 never reads the key. Yet setup-gbrain/memory.md:138 advertises it as "Disable entirely" and setup-gbrain/sections/transcript-gate.md.tmpl:47-53 offers "E) Never ingest transcripts (off)" and then runs gbrain-sync --full unconditionally, so a user who declined gets every transcript ingested on every /sync-gbrain. Fork refs: 6249074d (PR #2232 slice, /tmp/ta-wt/memory-trust:bin/gstack-memory-ingest.ts:523-538), fork PR #7 commit 7260b8e2 (CLOSED; not in the local clone, verified via gh pr diff 7; exempts --probe). Port: natively, not cherry-pick: decide semantics (honour only an explicit off; either change the :181 default to empty and update test/gstack-config-defaults.test.ts:139, or read the raw key with a comment explaining why); pass memory-ingest's existing --sources minus transcript from gbrain-sync when off; exempt --probe; one stderr line when the skip fires; fix transcript-gate.md.tmpl:52 so option E does not run --full; port the "honors off mode before invoking gbrain" test. Effort: human ~1 day, CC+gstack 30-45 min. Refuter's counter: the fork regex-parses config.yaml directly, bypassing gstack-config's GSTACK_STATE_ROOT resolution, and PR #2232 is CONFLICTING; both are shape objections, and this slice is independently shippable because it only removes writes.

10. question-preference hook slug mismatch (s2-runtime-question-pref-hook-slug-mismatch), P1, val 8 / fit 8. hosts/claude/hooks/question-preference-hook.ts:300-306 slugFromCwd returns path.basename(cwd), fed at :395 to lookupPreference (:149-159) which reads projects/<slug>/question-preferences.json; the only writer, bin/gstack-question-preference:36-38, buckets by gstack-slug which is owner-repo for any repo with an origin remote (bin/gstack-slug:17-20). Additionally, no writer of global-question-preferences exists anywhere (only the hook reads it and the test seeds it), so the Layer 2 deny is effectively inert outside the no-.git test fixture. Fork ref: b6572ebb (mechanism is GStack-2 runtime/identity.js, not portable). Port: replace slugFromCwd's body with slugFromEnvironment(stateRoot(), stdin.cwd) from lib/bin-context.ts:150 (git-spawn-free on cache hits, writes the same slug-cache as gstack-slug), keep 'unknown' for missing cwd; add a fixture that pre-seeds the slug-cache and asserts a deny; measure first-miss cost inside the 3s hook budget; confirm the Windows lane. Effort: human ~4 hours, CC+gstack 20 min. Refuter's counter: Layer 1 (gstack-question-preference --check) already honours project prefs so users mostly see correct behaviour; does not excuse a documented enforcement layer that never fires.

11. Chromium dead on Ubuntu 24.04 default kernel (s8-codediff-browse-userns-sandbox-probe), P1, val 8 / fit 8. browse/src/browser-manager.ts:88-99 shouldEnableChromiumSandbox checks only win32, GSTACK_CHROMIUM_NO_SANDBOX, CI, CONTAINER and root; repo-wide grep for apparmor|userns hits only xprotect-heal.ts NEGATIVE_SIGNATURES; #2157 is OPEN and describes the Ubuntu 24.04 LTS default (apparmor_restrict_unprivileged_userns=1). Fork ref: 4a8833cc (sysctl probe, isNoUsableSandboxError, relaunch-once, warnSandboxUnavailableOnce, 8 unit tests). Port: take the relaunch-once fallback first, composed inside the doLaunch closure at all three sites (browser-manager.ts:528, :744, :1821) so launchWithXProtectHeal stays the outer layer; emit SANDBOX_UNAVAILABLE once and surface it in browse status; append the GSTACK_CHROMIUM_NO_SANDBOX=1 hint to the startup-error text; treat the sysctl probe as optional (it saves one failed launch but can downgrade where a setuid helper would have worked). Port the unit tests; extend the static tripwire to all three launch sites. Cite #2157 as closing; #2101 is not fixed by this. Effort: human 1 day incl. an Ubuntu 24.04 VM check, CC+gstack 30-45 min. Refuter's counters: the fork author asked to close #2157 as resolved by the env var; upstream deliberately chose opt-in (CHANGELOG.md:3960); the fork's warning goes to the daemon log. None outweighs a dead daemon on the current LTS default, and a relaunch on the literal zygote fatal has zero false positives.

12. Terminal-agent WS Origin pin is never armed (s1-prewave-terminal-ws-extension-id-pin), P1, val 6 / fit 9. browse/src/terminal-agent.ts:41 const EXTENSION_ID = process.env.BROWSE_EXTENSION_ID || '', :602 gated compare; browse/src/terminal-agent-control.ts:77-79 spawns the agent with only BROWSE_STATE_FILE/BROWSE_SERVER_PORT/BROWSE_OWNER_PID, so production never sets it, while the comment at :583-584 says the Origin gate is "required, not optional". Fork refs: 7b3f391b, d947d2e1 (PR #2226). Port ONLY the pin: split GSTACK_EXTENSION_ID into a small browse/src/extension-identity.ts (new file) re-exported from server.ts, make the /ws Origin compare unconditional (403), update the fake-origin test sites (terminal-agent-integration.test.ts:120-135) and add a foreign-ID case; before merge confirm GStack Browser.app / GBrowser's baked extension carries the same manifest key or gate the strict compare behind isCustomExtensionBakedChromium(); never copy the fork constant (hjcdll... is NOT upstream's dgbkdb..., server.ts:306). Effort: human 2 hours, CC+gstack 15 min. Refuter's counter: defense in depth only, since AUTH_TOKEN is already released only to the pinned origin via POST /extension-token (server.ts:1886-1897); accepted, which is why this is last, but the code comment and the code disagree and the fix is two lines.

13. Cluster: ten small bin/browse/template fixes (grep-verified at HEAD, panel TAKE P1, not adversarially refuted). Each is a few lines with the upstream defect re-confirmed by me at the cited line; none carries voice or design risk.

  • gh pr checks field names (gap2-skillwave-land-gh-checks-targeturl-bugfix, val 6 / fit 10): land-and-deploy/sections/first-run-validation.md.tmpl:112 --json name,targetUrl and land-and-deploy/SKILL.md.tmpl:154 --json name,state,status,conclusion; the panel verified live with gh 2.83.2 that both field sets are rejected ("Unknown JSON field"). Fix: name,link and name,state,bucket, regen. Fork ref: bbad1bab.
  • Codex/Factory /ship skips plan verification (gap5-hygiene-codex-ship-qa-only-path, val 6 / fit 9): scripts/resolvers/review.ts:1178 cat ${CLAUDE_SKILL_DIR}/../qa-only/SKILL.md; hosts/codex.ts has no qa-only pathRewrite (grep = 0). Fix: pathRewrite to $GSTACK_ROOT/../gstack-qa-only/SKILL.md for codex and factory, regen goldens, test. Upstream PR #1772 (@spacegeologist) OPEN since 2026-05-28.
  • Detached HEAD emits BRANCH=HEAD (s8-codediff-slug-detached-head-branch, val 6 / fit 10): bin/gstack-slug:274-276 passes git rev-parse --abbrev-ref HEAD through, so CI runs and bisects pool review/evidence logs under HEAD-reviews.jsonl. One-line map to unknown, plus a test. Fork ref: b6572ebb.
  • brain-cache hardcodes ~/.claude/skills/gstack/bin/gstack-config (s8-codediff-brain-cache-gstack-config-hardcoded-path, val 6 / fit 10): bin/gstack-brain-cache:614-616 silently falls back to defaults on every non-Claude host. Fix: join(import.meta.dir, 'gstack-config').
  • gstack-config ignores inline # comments (gap3-config-inline-comment-stripping, val 6 / fit 9): bin/gstack-config:321-329 read_config_value has no # strip, so update_check: false # temp fails to disable; browse/src/config.ts:208-229 (the "single source of truth" TS reader) does strip. Fix: one sed clause ordered before the key strip; two tests.
  • welcome.html loads Google Fonts and Fontshare (s8-codediff-browse-welcome-offline-fonts, val 6 / fit 9): browse/src/welcome.html:7-8; server auto-navigates the headed browser there on launch, unreceipted. Fix: system font stack (+9/-7) and a no-remote-asset tripwire. Fork ref: e1cd3096.
  • Dangling symlink passes validateOutputPath (s8-codediff-browse-path-security-dangling-symlink, val 6 / fit 9): browse/src/path-security.ts:43-54 shares one try for lstatSync and realpathSync with if (e.code !== 'ENOENT') throw e, so a dangling link under /tmp pointing outside falls through to the parent-dir check. Fork ref: f14445bb (restructure + test).
  • v1.27 artifacts rename uses bare repo names (gap3-migration-v127-owner-qualified-gh-rename-and-heal, val 8 / fit 8): gstack-upgrade/migrations/v1.27.0.0.sh:219-224 gh repo rename NEW --repo OLD with stderr discarded; gh requires OWNER/REPO so the GitHub-side rename fails every time. Take the owner-qualification hunk (fork 5c5b8c4e, Brandon Pugsley) and consider the heal migration (56425c9a); keep upstream's #1383 failure semantics.
  • GSTACK_HOME not honoured as state root in four bins (s8-codediff-gstack-home-state-dir-consistency, val 5 / fit 10): bin/gstack-update-check:25 and bin/gstack-telemetry-log:27 read only GSTACK_STATE_DIR; bin/gstack-detach writes ~/.gstack/locks and its test cleans the real home (test/gstack-detach.test.ts:141). Six one-line edits.
  • buildGbrainEnv passes a project's DATABASE_URL into a PGLite gbrain (s8-codediff-gbrain-exec-strip-caller-database-url, val 7 / fit 8): lib/gbrain-exec.ts:117-125 returns the caller env untouched when config has no database_url; issue #1917 OPEN. Adapt (strip only when config exists and lacks database_url; keep GSTACK_RESPECT_ENV_DATABASE_URL), flip the three pinning tests. Effort for the cluster: human ~2 days, CC+gstack ~1.5 hours across two or three bisected PRs.

3. Contested — take only if the maintainer agrees

  • Self-contained questions (s3-judgment-self-contained-questions). Refuted as a universal preamble rule (doubles output tokens at every gate; hardcodes host UI collapsing behaviour); the office-hours-specific failure in issue #879 is real. Tie-break: add one sentence at office-hours/sections/design-and-handoff.md.tmpl:168 printing the saved path plus the doc body as assistant text before the Approve/Revise gate (credit @RyanAlberts, close #879/#1116), and nothing universal?
  • /review small-diff coverage (s9-skills-review-small-diff-sweep-hole). Refuted as a Pass 3 sweep (upstream runs an adversarial subagent on every diff, review.ts:509); what remains is one inaccurate sentence at review/checklist.md:10 and no Access Control bullet in Pass 1 CRITICAL. Tie-break: is an Access Control bullet (missing auth middleware, IDOR, path traversal) worth its bytes in a forced-read file under the context-budget ratchet?
  • Reply in the user's language (s9-skills-match-user-language, #679). Refuted as an always-on Voice-section line (community-PR guardrail, chat-only scoping leaves reports English). Tie-break: an opt-in reply_language config key rendered into Writing Style, with the mixed-language tests time-attack asked for on #679?
  • AskUserQuestion compact payload (gap2-skillwave-askuserquestion-compact-payload-1241). Refuted: shrinking question to 80 chars strips what question-log-hook and question-preference-hook hash and classify (hosts/claude/hooks/question-log-hook.ts:288-313, question-preference-hook.ts:404-457) and re-legitimises prose-then-tool. Tie-break: reproduce #1208 on the VSCode host first; if real, decide payload-vs-prose as a deliberate AUQ resolver design with an A/B receipt.
  • Catalog trim on external hosts (gap3-catalog-trim-external-hosts, #1972). Refuted: on Codex the description is the only routing signal and the fork's own maintainer refused this on #1972 without routing evals. Tie-break: run a Codex routing eval; if it passes, merge #1972 with @hadrien-de-march credit.
  • $B record (s6-branches-browse-record-cdp-screencast, fork PR #54). Refuted as a drop-in: record in SCOPE_READ, spawnSync ffmpeg in the daemon request path, frames never cleaned, cap evaluated only on frame arrival, VP9 into .mp4, and #2497 is already queued at TODOS.md:43. Tie-break: CDP screencast (no context rebuild, works headed, no-ffmpeg fallback) versus #2497's recordVideo .webm; decide once at triage and land one.
  • Codex sandbox canary (s8-codediff-codex-sandbox-canary), panel TAKE_PARTIAL P1, val 8 / fit 7, xref PARTIAL, not among the 48 refuted. Fork ref 8abb08e5 (bin/gstack-codex-probe:110-142 in the fork tree). Upstream has a real round-trip model probe (bin/gstack-codex-probe:39-142) and typed CODEX_MODE degradation (scripts/resolvers/constants.ts:118-160) but no sandbox/userns signature (grep bwrap|bubblewrap|landlock|user namespace across bin/ lib/ scripts/ codex/ review/ ship/ = 0), so a Codex that exits empty because bwrap cannot create user namespaces reads as a clean pass in /review, /ship and /autoplan on devcontainers, Flatpak and hardened Ubuntu. Issue #1892 is OPEN. The appended refuter for s8-codediff-bin-lib-absorbed-batch directs this to be handled under #1892 on its own merits, not as a fork port. Tie-break: does Garry want a fail-closed sandbox_unavailable CODEX_MODE with the mandated one-liner "codex skipped: sandbox unavailable" plus the same signature in review.ts:383-385/548-550/689-691 and codex/SKILL.md.tmpl:310, or the GSTACK_CODEX_NO_SANDBOX opt-in that #1892 asks for, or both? Effort: human ~1 day, CC+gstack ~45 min (+15 min for the env gate).
  • Privacy page (s7-docs-method-privacy-data-flow-doc). Refuted as a fork port (Context.dev-flavoured, drifts). The real defect surfaced: gstack-egress grants enumerates four grants (bin/gstack-egress:155-190) while bin/gstack-config defines update_check, codex_reviews, pair_agent. Tie-break: fix the grants under-enumeration (upstream bug, no fork lineage) and stop there, or also write a short table in README's Privacy section?
  • Codex dispatch consent and scan-at-sink (s4-fleet-codex-consent-and-redact-at-sink). Refuted: Codex runs locally with -s read-only in the repo and reads any file, so scanning a materialised diff is scan-then-re-render, and codex_reviews is already the master switch. Tie-break: an egress receipt (fail-open) at each codex dispatch, since test/egress-receipt-wiring.test.ts:138-143 exempts skill prose, plus one disclosure line in the preflight?
  • Untrusted-data authority rule (gap6-s15-hostadv-untrusted-data-authority-rule). Refuted as a preamble generator (generate-evidence-directive.ts:3-12 records the decision not to import SHARED-JUDGMENT). Concrete gap: qa/qa-only use {{BROWSE_SETUP}} which does not carry UNTRUSTED_CONTENT_WARNING (scripts/resolvers/browse.ts:58-60). Tie-break: wire the existing warning into BROWSE_SETUP and take the two per-skill lines from PR #2186 (@danlayfield), nothing else?
  • Delete ~/.gstack/.auth.json writer (s1-prewave-auth-json-file-write-removal). Refuted for now: browser-manager.ts:638-640 says the component-baked GBrowser extension reads it, and the token is already on disk 0600 in the browse state file. Tie-break: does Garry know whether GBrowser's baked extension bootstraps via POST /extension-token? If yes, delete plus a migration.
  • Loosened inputs and stale strings (s1-prewave-review-loosened-inputs-stale-strings). Byte-for-byte upstream PR #2141 (@aversini, MERGEABLE), not a fork item. Tie-break: does Garry want two more anecdote-derived categories in a forced-read checklist? If yes, merge #2141 keeping the "Enum & Value Completeness" heading (test pin at test/skill-validation.test.ts:893-897).
  • Base detection for local-only repos (s9-skills-base-detection-local-only). Refuted: the fork ladder adds git remote set-head -a (network) and a merge-base guess, and upstream pins "fall back to main" (test/gen-skill-docs.test.ts:649-651). Two literal-main sites bypassing BASE_BRANCH_DETECT are upstream bugs: scripts/resolvers/utility.ts:111-112 and design.ts:83. Tie-break: fix those two now; revisit a "no remote" terminal state only on field reports.
  • "Pre-existing" requires evidence (s9-skills-pre-existing-requires-base-run). Refuted as an automatic base-branch run (deps, DB side effects, minutes per ship). Tie-break: rewrite T1 vocabulary to verified/unverified with base-branch CI status (gh run list --branch <base>) as default evidence and a failing-files-only worktree run as an opt-in option?
  • CLAUDE.md ## Review section (s9-skills-review-claudemd-review-section, #452). Refuted: the host already loads CLAUDE.md, and free-form suppression rules cannot be told from tightening. Tie-break: a docs/skills.md paragraph documenting the convention (credit @evb87-tech) and close #452?
  • /scrape evidence gate (gap2-skillwave-scrape-evidence-gate-1717). Refuted as a 40-line step (coached E2E, breaks skillify's final-attempt slice). Tie-break: two sentences in Step 4 ("if the intent names a filter, count or ordering, the rows must demonstrate it"), credit @orendi84, close #1717?
  • gen-skill-docs single-host failure exits 0 (s2-runtime-gen-skill-docs-single-host-fatal). Refuted as P1: setup:727-731 renders codex unconditionally under set -e, so flipping :1150 would let a Codex render error abort the Claude install. Tie-break: P3, only with a setup decision to warn-and-continue for unselected hosts and a throwing-template test.

4. Defer

  • Codex prompt over stdin (s7-docs-method-regression-pr2370-stdin-prompt-dispatch; also s4-fleet-codex-mktemp-portable's residual). Blocked on a real bug: bin/gstack-codex-probe:194 runs "$@" & in the no-gtimeout watchdog, and bash redirects an async command's stdin from /dev/null, so codex exec - < file would dispatch an empty prompt on stock macOS. Unblocks: change :194 to "$@" <&0 & with a PATH-masked test, then convert exactly review-mode.md.tmpl:87 and review.ts:373.
  • Time constraint as a ceiling (s3-judgment-time-constraint-caps-scale). Contradicts autoplan/SKILL.md.tmpl:150-159 "MUST NOT compress"; docs/designs/PACING_UPDATES_V0.md:97-110 already owns chain-scoped accounting. Unblocks: fold "a time box caps question rounds, never review completeness" into PACING V1.1.
  • Transcript source-id isolation and current-repo scoping (s1-prewave-transcript-source-id-isolation, s1-prewave-transcript-current-repo-scope; PR #2232 remainder, issue #2140). Fork passes --source-id to gbrain import with no support probe (gbrain docs spell it --source); two-pass split must be re-derived across resume, reconciliation (bin/gstack-memory-ingest.ts:1803-1812, :2316-2330) and BulkResult merging. Unblocks: the never-double-store review TODOS.md:3947 gates on, a flag probe in the #2662 pattern, and confirmation that gbrain can exclude a source from dream; sequence after the off fix.
  • Defensive framing for red-team and security specialists (gap2-skillwave-review-defensive-framing-shared-resolver-1921). No reproducible denial trace exists for those two prompts (time-attack's own #1921 review asked for one). Unblocks: an E2E trace; then frame only the red-team prompt via a shared constant.
  • Recording caps/fallbacks, QA recording prose, shutdown flush and tunnel-denial pins (s6-branches-record-caps-and-fallbacks, s6-branches-qa-recording-specialist-judgment, s6-branches-record-shutdown-flush, s6-branches-record-tunnel-denial-and-scope). Nothing to govern until a record primitive lands. The fourth item (panel TAKE_PARTIAL P1, val 4 / fit 9, fork ref 76c89d56) is two one-line negative pins in browse/test/dual-listener.test.ts:109-120 and browse/test/tunnel-gate-unit.test.ts:41-53 plus the scope decision; upstream's closed TUNNEL_COMMANDS allowlist (browse/src/server.ts:315-344) already denies any unlisted command, so the pins are documentation of a property, not a behaviour change, and its earlier refuter said exactly that. Unblocks: the #2497/#54 decision; then wall-clock cap, byte ceiling, zero-frame screenshot, .webm for VP9, the tunnel pins with the "a continuous capture is a larger exfil surface than a single screenshot" rationale, the scope classification (panel recommends SCOPE_WRITE over the fork's SCOPE_READ or #2497's SCOPE_CONTROL), and four neutral prose rules written against the real semantics.
  • Web-data task taxonomy (s6-branches-web-data-task-taxonomy-and-rankings). Points at providers upstream does not ship; the authenticated-to-own-browser rule already lives in scripts/resolvers/third-party-actions.ts:35-37. Unblocks: the Aside Phase 2 product call at TODOS.md:462-486; then two sentences in scrape's "does NOT do" list.
  • ios-qa local package wording (gap5-hygiene-ios-qa-local-package-wording-1735). Not a fork item; an upstream #1735 close-out: ios-qa/SKILL.md.tmpl:124/:255 and ios-clean/SKILL.md.tmpl:82's wrong .package(url:) line. Unblocks: whoever closes #1735; decide bearer persistence separately against #1796.
  • make-pdf entity-obfuscated javascript: href (gap3-makepdf-parser-backed-sanitizer-not-recommended, skeptic flip, never panel-judged). Skeptic reports make-pdf/src/render.ts:243-246 rewrites only a literal javascript: and fork PR #6 commit f1a92355 (CLOSED; not in the local clone, verified via gh pr diff 6) has a test for java&#x73;cript:. Exploitability is low (output is a PDF rendered by Chromium), so not a shortlist item. Unblocks: port that one test; if it fails, extend the existing decode step, not the parser-backed sanitizer.
  • ios-qa per-mutation bundle guard (s8-codediff-iosqa-active-bundle-assertion, skeptic flip). Needs StateServer.swift.template changes; decide with the ios-qa maintainers alongside #1796/#1975.
  • Panel DEFERs: parallel /batch across tab groups (s6-branches-browser-batch-multitab-plan; blocked on the global switchTab pin at browse/src/server.ts:1063-1072); fast-path gate E2E (s4-fleet-fast-path-gate-e2e; presupposes a trivial-change fast path upstream has not adopted); Windows console-flash residue (gap1-s10-browsewave-windows-console-flash-suite; #1784's claim that Bun.spawnSync ignores windowsHide is unverified, needs a Windows tester); iOS XCUITest evidence schema and flow runner (gap4-s13-ios-xcuitest-evidence-schema, gap4-s13-ios-xcuitest-flow-runner; contradict ios-qa/SKILL.md.tmpl:41 "No simulator, no XCTest", needs an architecture decision); /cso --fix (gap2-skillwave-cso-fix-mode-safe-autofixes-1053; inverts cso's report-only contract at cso/SKILL.md.tmpl:44, needs a safe redesign); Windows network lockdown CI (s6-branches-windows-network-lockdown-ci; no offline CI phase exists to use it).

5. Skip

Item Reason
Bound Playwright install + continue (s1-prewave-setup-install-deadline-and-continue) Duplicate of gap3 wearing a 300s deadline that would kill legitimate slow downloads; Playwright already retries 5x. Close #2233 once gap3 lands.
Setup probe deadline (s1-prewave-setup-probe-deadline) Headline absorbed (setup:417-466 _kill_tree/_wait_with_deadline, #2136 CLOSED); install bound better served by upstream PR #2359.
Official-API-first rule (s6-branches-web-data-official-api-first-rule) Truism already in the tier-3 reuse ladder; motivated by one planning anecdote; targets /scrape, which is one-shot by contract.
PR mutations via REST (s9-skills-pr-mutations-rest) Ship Step 19 rewrites the body with the #1079 REST fallback after document-release; #1079 CLOSED; standalone exposure is warn-and-continue.
Team hook as Node .cjs (s1-prewave-team-hook-cross-platform-cjs, #2229) Claude Code on Windows requires Git Bash; the real fix is the bash prefix convention (setup:2060-2071) on bin/gstack-team-init:183-189; fork re-introduces the #2500 false-block and a Node dependency.
Matcher Skill|skill (s1-prewave-team-hook-matcher-lowercase-skill) No-op on every supported host; Copilot CLI does not read .claude/settings.json.
Issue forms and labels (s7-docs-method-issue-templates-and-labels) Fork never implemented them either; upstream triage is wave-based, not label-based. Do fix the dangling "The evidence bar" link at .github/PULL_REQUEST_TEMPLATE.md:4 (grep 'evidence bar' CONTRIBUTING.md = 0); that fix is record s7-docs-method-contributing-evidence-bar-section, see section 5a.
Multi-OS static tree lane (s7-docs-method-multi-os-static-tree-gate) Static budget tests have zero platform dependence; a macOS lane is an upstream CI decision (mktemp/keychain files), not a fork import.
README update-check disclosure (s1-prewave-readme-update-check-disclosure) Fork line is now inaccurate (ls-remote plus raw fetch, two cache windows); rewrite natively from bin/gstack-update-check:157-243 if wanted.
Hardcoded origin/main residue (s4-fleet-hardcoded-origin-main-residue) Three descriptive prose sites with near-zero impact (review/checklist.md:5, review/greptile-triage.md:86, office-hours/SKILL.md.tmpl:87); fix as housekeeping when touching those files, do not adopt the fork's banned-regex tripwire.
/plan-pm-review (gap2-skillwave-plan-pm-review-1666) Explicitly declined by Garry on #1412 ("The user IS the PM").
Conductor implicit AUQ hook opt-in removal (s1-prewave-conductor-implicit-auq-hook-optin) Upstream deliberately narrowed rather than removed it (setup:2294-2307) and pins the contract in test/setup-plan-tune-hooks-noninteractive.test.ts:91-95.
QA evidence-per-finding layout (gap5-hygiene-1484-qa-evidence-per-finding) Panel SKIP: judgment already upstream; #1484 folder layout adds nothing.
patchright stealth backend (gap1-s10-browsewave-patchright-stealth-backend) Panel SKIP: ongoing per-Playwright-bump cost for a CDP leak upstream's Layer C already addresses.
BACKLOG-MAP generator (s7-docs-method-backlog-map-triage-generator) Panel SKIP: 810-line offline triage generator for a fork process.
browse-migrate legacy extension IDs (s1-prewave-browse-migrate-legacy-extension) Panel SKIP: path-derived legacy IDs are not an upstream state.
CLAUDE.md node -e snippet (s1-prewave-team-claude-md-node-snippet) Panel SKIP: same Node dependency argument as #2229.
/setup-search-mcp with Exa (gap2-skillwave-setup-search-mcp-exa-2168) Panel SKIP: adds a third-party MCP endpoint to Search Before Building.
GStack 2 judgment contracts: verification contract, total-verification ledger, execution depth profiles, build-scale classification, zero-question budget, proportional planning, trivial-change fast path, one-inspection-command-per-call, dispatcher precedence (s9-skills-, s3-judgment-) Depend on the six-dispatcher architecture and the fifteen-vector scale system; PACING_UPDATES_V0.md:97-110 already recorded what to fold in.
Fleet harness sub-ideas: tEnd bookend, rage taxonomy, abandonment contract, metric provenance (s4-fleet-*) Methodology for the persona-fleet harness TODOS.md already defers.
Docs/method artifacts: ADR series, audit-backlog ledger, bloat ledger, host compat evidence tiers, routing scenario fixtures, install-matrix artifacts, skills.sh distribution, devcontainer, upgrade/rollback doc, egress audit doc (s7-docs-method-*) Contributor-facing process artifacts in fork voice; upstream keeps the equivalents machine-readable (receipts, ratchet fixtures).
New skills: /yc-review, /diagnose, /fanout, /community-review, /land merge queue, /plan-status, /pr-prep audit (s6-branches-yc-review-skill, gap2-skillwave-*) Each adds catalog bytes under the enforced 1,150-token discovery ceiling for a niche. #1815 is Garry's own still-OPEN /land proposal (gh: OPEN, author garrytan) and should be decided there, not via the fork; #1949 (/fanout) is a CLOSED community PR by @sohmn.
Host adapters: Grok Build, Pi/Antigravity/Vibe/Qoder, Codex ~/.agents migration, request_user_input rewrite, native image_gen (gap3-hosts-*) Host-config refactor is blocked (docs/designs/SLATE_HOST.md); declarative configs alone ship untested surfaces.

Beyond the items above, 39 panel-P1 and roughly 130 P2/P3 take or take-partial items (170 P2/P3 in total: P2 126, P3 44 per summary.json) were neither adversarially refuted nor grep-verified for this report. The P2/P3 leftover (browse env knobs, retro/health additions, ios-qa docs, test-infra pins, Windows PowerShell bootstrap, statusline, learnings refine, design round artifacts) is individually small and can be picked up opportunistically from /tmp/ta-eval/residual-index.json. The 39 P1 items are listed next so they are not mistaken for P2/P3.

5a. Unrefuted panel-P1 take / take-partial items (39)

Scores are user_value / fit from residual-index.json. "Panel only" means no evidence beyond the panel record was gathered for this report; the panel was generous, so treat these verdicts as unproven until grep-verified or refuted. Two entries carry an earlier prior_refuter refuted=true and are marked.

Id Panel Val/Fit Xref Disposition
s8-codediff-browse-absorbed-batch TAKE_PARTIAL 7/9 PARTIAL Mis-titled batch; 12 of 13 absorbed. Panel only for the one residual.
s9-skills-ship-breaking-change-over-linecount TAKE_PARTIAL 7/9 PARTIAL Overlaps CLAUDE.md "Scale-aware bumps" prose; panel only.
s9-skills-eng-review-pre-mortem-and-data-model TAKE_PARTIAL 8/8 MISSING Adds a pre-mortem step to plan-eng-review; voice-bearing template change, needs Garry's read. Panel only.
gap3-codex-probe-custom-provider-env-key TAKE 7/9 MISSING Codex auth probe for config.toml env_key providers; panel only.
gap2-skillwave-office-hours-codebase-surface-premise-verify-1738 TAKE_PARTIAL 8/8 MISSING Verify codebase-fact premises before AUQ in office-hours; template change, panel only.
gap2-skillwave-retro-persist-recommendations-followthrough-1834 TAKE 8/8 MISSING /retro persists recommendations and scores follow-through; panel only.
gap2-skillwave-retro-language-agnostic-test-detection-2037-2013 TAKE 8/8 PARTIAL Python/Terraform/Bats test-file detection in retro metrics; consistent with platform-agnostic rule, panel only.
gap2-skillwave-cso-mini-shai-hulud-tier3-1523 TAKE 8/8 MISSING /cso Tier 3 known-campaign IOC rules; panel only.
gap6-s15-hostadv-fixture-set-and-schema TAKE 8/8 MISSING Injection-resistance fixture set; sibling of the persona-fleet harness TODOS.md defers, panel only.
s8-codediff-iosqa-drop-resolve6-unicast-dns TAKE 6/9 MISSING Drop dns.resolve6 fallback leaking device hostname; panel only.
s8-codediff-memory-ingest-default-secret-gate TAKE 7/8 MISSING Default-ON redact scan over staged ingest bytes; panel only.
s8-codediff-iosqa-devicectl-typed-errors-hwudid TAKE 7/8 MISSING devicectl typed errors + hardware-UDID match; same fork commit as shortlist item 8, panel only.
s8-codediff-codex-sandbox-canary TAKE_PARTIAL 8/7 PARTIAL Listed in section 3 (Contested); handle under OPEN issue #1892 on its own merits per the bin-lib refuter.
gap2-skillwave-reviewer-discipline-gate-884 TAKE_PARTIAL 7/8 MISSING Requested human review as merge gate (#884); panel only.
s2-runtime-workflow-hardening-tripwire-test TAKE 6/9 MISSING Free test for mutable action refs / permissions / concurrency; pairs with the sha-pins item below, panel only.
s4-fleet-spec-execute-host-neutral-spawn TAKE 6/9 MISSING /spec --execute spawns claude -p on every host; panel only.
s4-fleet-review-precision-answer-key-corpus TAKE_PARTIAL 7/8 PARTIAL Answer-key review corpus; TODOS.md already defers answer-key evals, panel only.
s7-docs-method-contributing-evidence-bar-section TAKE 6/9 PARTIAL The record behind the dangling PULL_REQUEST_TEMPLATE.md:4 link (verified: grep 'evidence bar' CONTRIBUTING.md = 0). Write the section in house voice or re-point the link; do not paste fork prose. Human 2-3 hours, CC+gstack 15 min.
s8-codediff-make-pdf-render-sentinel-invariant TAKE 6/9 PARTIAL Strip U+0000 at render entry, throw on surviving placeholder; panel only.
s9-skills-system-functional-qa TAKE 8/7 MISSING QA for APIs/CLIs/jobs/webhooks; new skill-sized surface under the catalog ceiling, needs a product call. Panel only.
s9-skills-debug-bisect-and-nonreproduction-taxonomy TAKE_PARTIAL 7/8 MISSING /investigate bounded bisect + non-reproduction classes; panel only.
s9-skills-review-finding-validation-gate TAKE_PARTIAL 7/8 PARTIAL VALIDATED/REJECTED/UNCERTAIN per finding before Fix-First; panel only.
gap1-s10-browsewave-chromium-path-setup-probe TAKE 6/9 MISSING setup launch probe honours GSTACK_CHROMIUM_PATH; natural rider on shortlist item 3, panel only.
gap1-s10-browsewave-cookie-import-cdp-pipe TAKE 7/8 MISSING Windows cookie import over --remote-debugging-pipe; panel only.
gap1-s10-browsewave-untrusted-content-hardening-prose TAKE_PARTIAL 7/8 MISSING Skill-prose hardening across investigate/browse/qa/canary/ship; overlaps the BROWSE_SETUP tie-break in section 3, panel only.
gap3-codex-jsonl-parser-bin TAKE 7/8 MISSING bin/gstack-codex-jsonl-parser replacing inline python in /codex (#1329); panel only.
gap2-skillwave-land-and-deploy-configurable-merge-method-726 TAKE 7/8 MISSING Configurable merge method via CLAUDE.md Deploy Configuration; fits utility.ts:65 idiom, panel only.
s9-skills-ask-only-uninferable TAKE_PARTIAL 7/7 MISSING SHARED-JUDGMENT clause 10; preamble growth under the ratchet, panel only.
s3-judgment-session-start-code-intelligence-offer TAKE_PARTIAL 6/8 PARTIAL Session-start indexing offer; panel only.
s7-docs-method-workflow-sha-pins-and-permissions TAKE 5/9 PARTIAL SHA-pin actions + top-level permissions; CI hygiene, panel only.
gap5-hygiene-chromium-path-status-correction TAKE 5/9 PARTIAL GSTACK_CHROMIUM_PATH for headless launch; panel only.
s9-skills-external-effects-no-blind-retry TAKE_PARTIAL 7/7 PARTIAL EXTERNAL-EFFECTS semantics; the PR-mutations sibling was refuted (section 5), panel only.
s1-prewave-uninstall-preserve-unowned-codex-dirs TAKE_PARTIAL 6/8 PARTIAL Prior refuter refuted=true: bug is real but is upstream's own TODOS.md:258-262 backlog item; do it there, not as a port.
s5-beta-human-era-anchors TAKE_PARTIAL 7/7 MISSING Retire file-count/human-day proxies; touches ship/review heuristics Garry wrote, panel only.
s9-skills-ship-smallest-release-convention TAKE_PARTIAL 7/7 MISSING Honour the repo's release convention at its smallest; panel only.
gap3-codex-global-discover-ssh-url-form TAKE 5/9 MISSING normalizeRemoteUrl ssh:// slash form; small, panel only.
s6-branches-record-tunnel-denial-and-scope TAKE_PARTIAL 4/9 MISSING Prior refuter refuted=true (already guaranteed by the closed TUNNEL_COMMANDS allowlist); folded into the record cluster in section 4.
s5-beta-hung-child-stall-guards TAKE_PARTIAL 5/8 PARTIAL E2E idle-stall/wall-clock guards; overlaps v1.77 test-infra wave, panel only.
gap2-skillwave-office-hours-artifact-outcome-1049 TAKE 6/7 MISSING Verify design doc exists before outcome:success (#1049); panel only.

6. Already absorbed / superseded / not applicable

From records-other.json (100 ABSORBED, 25 NOT_APPLICABLE, 3 SUPERSEDED), grouped:

Cluster Status Evidence
Apple App Store release journey (10 items: core roll-up plus adapter before branch gate, classify errors before credentials, browser credential ban + escalation ladder, deck editor, macOS CI runner split, pricing in authorization, session-minted upload key, sticky assets, two permitted interactions) ABSORBED ship/sections/apple-release.md.tmpl (header credits time-attack; wave 2, then hardened with allAppsVisible:false)
Judgment rules: design docs repo-local (#703), decision-record concision (#2000), evidence-before-claimed-limitations, third-party web actions contract, founder-resources opt-out (#538), prose fallback when no question tool ABSORBED office-hours/sections/design-and-handoff.md.tmpl:20-42, :343-366; scripts/resolvers/preamble/generate-evidence-directive.ts:15-17; scripts/resolvers/third-party-actions.ts:29-45; generate-ask-user-format.ts:13-37
Egress receipts, gstack-egress CLI, context-bill, discovery-surface ceiling, distill/eval model host-neutral ABSORBED (wave 1) bin/gstack-egress, lib/egress-receipt.ts, test/egress-receipt-wiring.test.ts; test/catalog-budget.test.ts; lib/eval-model.ts
Browse daemon: bun-polyfill spawn parity, disconnect-cause null browser, numbered-profile cookies (#2139), Playwright ^1.62 pin, Windows ACL SID (#2170), closeTab race, handoff SingletonLock, stop-ack before shutdown (#2020), live-but-busy daemon preservation (#2219/#2231), lock errno honesty (#1084), extension getPort withhold (#1822), CJK IME (#1272), WS subprotocol echo, /health token removal, stealth tests, telemetry config tier ABSORBED browse/src/browser-manager.ts:194,986-1020,1796-1798; cli.ts:608-641,684-745; meta-commands.ts:424-436; file-permissions.ts:45-87; server.ts:1870-1915; extension/sender-auth.js; browse/src/telemetry.ts:47-91
Setup/install: --help side-effect free, gstack-paths shell quoting, settings-hook fail-closed, mirror support files (#1502), absolute bin path (#1820), investigate hook paths (#1873), freeze symlink resolution (#781), careful compound-command guard (#2039), Codex/setup wave set, codex web-search flag ABSORBED setup:16-49, :871, :964-967; bin/gstack-paths:16-22; bin/gstack-settings-hook:70-223; freeze/bin/check-freeze.sh:100-116; careful/bin/check-careful.sh:186-189; scripts/resolvers/constants.ts:50-65
CI / supply chain: bun-version pin, dependency-review + osv-scanner, OSV config, fork-PR secret guards, gate secret scan, workflow concurrency, basic-ftp pin, diff ^9 bump ABSORBED 9 workflows pin bun 1.3.13; .github/workflows/{dependency-review,osv-scanner}.yml; .osv-scanner.toml; evals.yml:78-107; .github/scripts/gate-secret-scan.mjs; test/workflow-concurrency.test.ts; package.json:59
gbrain / memory: policy tier chokepoint, ingest staging, brain-context-load cold probe, brain-sync tilde paths (#1656), decision-log --supersede, setup-gbrain provider Step 0, codex-session-import xargs -r, deprecated brain-consumer scripts deleted ABSORBED bin/gstack-gbrain-sync.ts:45,839-880; bin/gstack-brain-context-load.ts:72-200; bin/gstack-decision-log:57,97; setup-gbrain/SKILL.md.tmpl:107-142; bin/gstack-codex-session-import:67-71
ios-qa: boot token out of os_log, loopback bind, hashed session tokens, touch selectors out of Release ABSORBED ios-qa/templates/StateServer.swift.template:100-105,154-167; ios-qa/daemon/src/index.ts:365-397; DebugBridgeTouch.m.template:23
make-pdf: invisible preamble, sibling browse before PATH, absorbed fix batch (render/smartypants) ABSORBED make-pdf/src/render.ts:69-70,213-265,487-515; browseClient.ts:10-20
Test infra: hermetic skills config dir, no-suicide-exit guard, handoff test isolation, sharded paid tier, CI gate binaries + poppler, codex E2E MCP isolation, multi-ecosystem ship test markers, Xvfb argv0 match, design timeout/count validation, benchmark timeout validation, catalog lead periods, artifacts-init push protocol (#2225), telemetry error mapping (#769), context-recovery slug (#1851), autoplan jq bind (#2021), land-and-deploy squash readback (#2011), one-way-door reset/revoke (#2024), document-generate (#1477), Opus 4.7 migration, codex openai.yaml, Windows spawn/DACL, question-format hook outputs ABSORBED test/helpers/hermetic-env.ts:278; test/no-suicide-exit.test.ts; scripts/test-paid-shards.ts; free-tests.yml:92-128; codex-session-runner.ts:211-214; scripts/resolvers/testing.ts:8-50; browse/src/xvfb.ts:144-170; bin/gstack-artifacts-init:67-82,218-256; scripts/one-way-doors.ts:66-72
Nine further ABSORBED items not named in a row above: s1-prewave-sidebar-chat-era-test-deletion (#1984), gap3-test-infra-wave-fully-absorbed (14 community PRs), gap2-skillwave-env-var-resolver-paths-1704, gap1-s10-browsewave-merged-pair-blocklist-and-brain-trust-ids (#2228), gap1-s10-browsewave-update-check-hardening (#1982), gap1-s10-browsewave-spawned-session-helper-and-telemetry-state (#1188), s6-branches-investigate-brokenness-v035, gap5-hygiene-bac5d9a5-unreachable-gate-tests-closed, s5-beta-body-floor-guard ABSORBED One-line evidence per id in records-other.json; with these the 100 ABSORBED reconcile against the rows above
GStack 2 runtime internals: execution-result envelope, release pipeline/attestation, shard heuristics, dispatcher headers and alias tables, runtime/cli main guard, deepeval/platform bakeoff, PostHog, demos fixture, Windows isolated gates harness, web-data egress rails, browser-provider eval, telemetry domain hashing, ios executor planner NOT_APPLICABLE No runtime/, evals/, demos/ or executor/ directories upstream; TODOS.md:460-505 and PACING_UPDATES_V0.md:97-110 record what was folded in instead
Deliberate upstream decisions: generic gpt-5.6 overlay (#2245; Sol is exact-only, scripts/models.ts:26-41), Slate first-class arm (docs/designs/SLATE_HOST.md), Hermes install arm/frontmatter (hosts/hermes.ts:32-37), careful text-segment filter (#1110, a destructive-command bypass), gstack-paths --get, extension storage.session auth (POST /extension-token chosen), Apple intermediate browser-drive states (s3-judgment-apple-intermediate-browser-drive-and-asc-cli), beta-first eval recalibration, slop-diff generated exclusion, windows-setup-e2e runtime lane NOT_APPLICABLE As cited per row in records-other.json
design daemon reset timers; Claude Desktop AUQ pre-empt (#2146); memory-ingest total-files tripwire (#2144) SUPERSEDED design/src/daemon.ts:206,489 (different shape); question-preference-hook.ts:21-23 never emits 'defer'; bin/gstack-memory-ingest.ts:2303-2346 reconciliation check

7. Open time-attack PRs on upstream

All eight upstream PRs are OPEN and CONFLICTING as of 2026-09-02 (gh); none can merge as-is.

PR Title Disposition Grounding
#2235 /bug-report skill Port-the-residual, then close Panel P2 val 7 / fit 5: a new tier-2 skill overlapping /investigate under the 1,150-token catalog cap. The independently useful piece is the redact-doc retain argument: scripts/resolvers/redact-doc.ts:85-88 deletes $REDACT_FILE right after the scan while the prose says "pass the SAME file downstream" (s1-prewave-bug-report-skill). Take retain, decline the skill.
#2233 Bound Playwright bootstrap, preserve skill registration Close-superseded Probe deadline absorbed (setup:417-466, #2136 CLOSED); install bound better served by PR #2359 (30 min, GSTACK_PLAYWRIGHT_INSTALL_TIMEOUT); the continue-after-failure half lands via the gap3 re-implementation crediting #1900. Update TODOS.md:3951-3953.
#2232 Transcript trust, scope, source isolation Port-the-residual Take the transcript_ingest_mode=off slice natively now (shortlist item 9); defer scope and --source-id behind the never-double-store review (TODOS.md:3947) and a gbrain flag probe. Close the PR after the off fix with a pointer to the deferred design.
#2231 Preserve live daemon during busy loads Close-superseded browse/src/cli.ts:684-686 daemonPidAlive + probeHealthWithBackoff, :733-745 "#2219 IRON RULE"; issue #2219 CLOSED 2026-08-17 (records-other: s1-prewave-live-daemon-preservation ABSORBED).
#2230 Test fixes for 182 failures unmasked by #2172 Close-superseded 5 of 6 fixes absorbed or superseded plus the bunfig PATH-restore preload (s1-prewave-hermetic-test-fixes). Optional 15-minute residual: one shared codex --version availability helper replacing seven which codex gates.
#2229 Team-init cross-platform hook + Copilot lowercase skill Close-not-wanted Fork re-introduces the #2500 false-block (checks only ~/.claude/skills/gstack), adds a Node dependency, Copilot does not read .claude/settings.json, README hunk is a voice rewrite. Native fix instead: bash "$CLAUDE_PROJECT_DIR/.claude/hooks/check-gstack.sh" on Windows at bin/gstack-team-init:183-189, or route through gstack-settings-hook.
#2226 Browse local auth leak + legacy profile migration Port-the-residual Take only the terminal-agent WS Origin pin (shortlist item 12). auth.json deletion gated on a GBrowser source check; bin/gstack-browse-migrate, bin/gstack-browse-repair and the whole-surface Host check (#1324) stay separate decisions. Never copy the fork's extension ID constant.
#2225 artifacts-init HTTPS push remotes Close-superseded bin/gstack-artifacts-init:11, :67-82, :218-256 --push-protocol incl. preserve and gh config get git_protocol; test/gstack-artifacts-init.test.ts:277-380 carries the same test titles.

Fork's own open PRs:

PR Title Disposition
time-attack #54 $B record (CDP screencast) + iOS session poller Do not merge as-is. Treat as the design alternative when triaging #2497 (TODOS.md:43): fix SCOPE_READ to a stricter scope, no spawnSync ffmpeg in the daemon, wall-clock cap, frame cleanup, .webm for VP9, tunnel-denial pins (s6-branches-record-tunnel-denial-and-scope), then land one implementation with @Topherhindman and @itstimwhite credit. The iOS poller (s6-branches-ios-record-session-poller) follows the same decision.
time-attack #40 Web-data provider contract (Firecrawl/Exa/Context.dev/Aside) Not wanted now (CONFLICTING on the fork too). Revisit only at the Aside Phase 2 product call (TODOS.md:462-486); upstream deliberately ships no off-machine scraping providers (s6-branches-web-data-provider-cli, s6-branches-web-data-task-taxonomy-and-rankings).
time-attack #55 AGENTS.md Cursor Cloud notes Do not put in AGENTS.md (upstream's is the generated catalog). The useful residual is routing raw git commit calls in test/diff-scope.test.ts:21-31, gstack-version-bump, team-mode, worktree and gstack-repo-mode tests through test/helpers/scratch-repo.ts (gpgsign/fsmonitor neutralised) plus one CONTRIBUTING.md:175-177 sandbox sentence (s7-docs-method-agents-md-cursor-cloud-gotcha).

8. Suggested port order

  1. Wave A: setup and hook correctness (three bisected commits, one PR). Playwright best-effort block (credit #1900), check-freeze STATE_DIR line plus test pins (credit #1509), gstack-relink ownership gate plus tests (credit #2119). Effort: human ~1.5 days, CC+gstack ~1 hour plus one free-suite run.
  2. Wave B: stale community PR merges and contributor-doc fixes. #1777 (taste confidence), #1096 (Render key), optionally #2141 if the checklist growth is accepted, the #1772-equivalent Codex/Factory qa-only pathRewrite with golden regen, and the CONTRIBUTING "The evidence bar" section or link re-point (s7-docs-method-contributing-evidence-bar-section). Effort: human ~half a day, CC+gstack ~45 min.
  3. Wave C: browse, make-pdf, ios small fixes. make-pdf preview offline gate, click no-second-wait, ios proxy timeout (adapted), terminal WS Origin pin, welcome.html system fonts, dangling-symlink validateOutputPath, Ubuntu userns relaunch-once (closes #2157). One commit each. Effort: human ~2.5 days incl. an Ubuntu 24.04 check, CC+gstack ~2 hours.
  4. Wave D: /ship platform-agnostic purge. tests.md.tmpl Steps 5/6 rewrite, ship/SKILL.md.tmpl:381 evidence pairs, readiness-gate default, gh pr checks field fix, goldens regen, marker test extension (credit #1102, close #1069). Effort: human ~2.5 days, CC+gstack ~2 hours.
  5. Wave E: consent and state hygiene. transcript_ingest_mode=off honoured plus transcript-gate prose; GSTACK_HOME in update-check/telemetry-log/detach; brain-cache config path; gstack-config inline comments; detached-HEAD slug; v1.27 migration owner qualification; gbrain-exec DATABASE_URL strip (adapted); gstack-egress grants under-enumeration (update_check, codex_reviews, pair_agent). Effort: human ~2.5 days, CC+gstack ~2 hours.
  6. Wave F: contested items, only after Garry's calls in section 3. Office-hours #879 one-sentence fix, Access Control bullet, opt-in reply_language, UNTRUSTED_CONTENT_WARNING into BROWSE_SETUP, egress receipt at codex dispatch, Codex sandbox canary under #1892, literal-main fixes at utility.ts:111-112 and design.ts:83, codex stdin dispatch after the gstack-codex-probe:194 wrapper fix. Effort: human ~3 days, CC+gstack ~2.5 hours, plus one paid AUQ/ship eval run for anything touching the preamble. The 39 unrefuted P1 items in section 5a are not scheduled; each needs the same grep-verify-or-refute pass the 48 received before it earns a wave.