* chore(scripts): retire hollow and legacy paid package scripts behind one-release stubs (W8a, DX-4, CEO-31) test:codex*, test:evals*, test:e2e*, test:gate, test:periodic, eval:bg, eval:bg:all, eval:flake-rank, eval:watch and test:audit now print their replacement and exit 1 via scripts/retired-command.ts. CONTRIBUTING.md carries the same table; test/retired-commands.test.ts pins both. Eval CLI empty-state hints point at eval:bg:pr. * chore: delete dead update-readme-throughput, eval-watch, orphan fixtures and QA_FUNCTIONAL_INPUTS (W8b, CEO-24) Retired with named behavior: - update-readme-throughput.ts + readme-throughput test: replaced a README anchor that no longer exists from a JSON file that was never produced; the script was a no-op. Guarantee withdrawn (nothing to protect). - eval-watch.ts + its dashboard tests: rendered ~/.gstack-dev/e2e-live.json and _partial-e2e.json, written only by unsharded runs, so it showed nothing for every supported (sharded) entry point. Guarantee withdrawn; live progress is the gstack-detach log or gh run watch. Manual-review rendering stays covered by eval-list and eval-summary tests. - Orphan fixtures (autoplan-pending-artifact-ae.json, autoplan-existing-app/, autoplan-sign-in-ui/, parity baselines v1.47.0.0/v1.57.7.0/v1.69.1.0): no test, touchfile or script reads them; superseded baselines stay in git history. - QA_FUNCTIONAL_INPUTS: exported, never imported. * refactor(test-free): delete dead WORKER_HOSTILE list and buildShardArgs parallel mode Neither had a production caller: full-suite mode runs shard processes, so the worker quarantine was inert and --parallel was never passed (W8b). * docs(test-value): narrow prompt-byte contract to machine-read tokens (D2) Define prompt-byte contract as machine-read tokens (markers, field names, command lines, enum values, file paths, security-boundary strings) and add a sentence-pin glossary entry: convert to structural checks or delete when a behavioral eval covers the behavior. * test(ratchet): count free tests that slice a paid test's source A free test that binds readFileSync(<paid test file>) and cuts it with .slice() tests the paid harness's code out of context even when it imports a lib/ symbol. Record the 15 existing files with reasons; new ones fail with fix text. Self-test covers positive and negative shapes. * test(browse): un-quarantine compare-board; all 16 board tests pass headless (W8d, CEO-24) The GSTACK_COMPARE_BOARD_TESTS opt-in hid a headless mismatch that no longer reproduces: all 16 tests pass on Bun 1.4.0 with the bundled headless Chromium, solo, repeated, and beside other in-process browser files. Protected behavior (the comparison-board DOM contract the plan-design-review/office-hours/design-consultation feedback loop polls) is checked on every free run again. * test: replace silent existsSync early returns with explicit skips or assertions (W8d) - browse/test/build.test.ts: server-node.mjs checks skip only when the bundle is absent and GSTACK_EXPECT_BINARIES is unset; the free CI lane and test:ubicloud build it and set the flag, so a dropped build step fails with the build command instead of passing with no assertions. - gstack-update-check: VERSION is tracked; the guard could only hide a bug. - gen-skill-docs host leakage/frontmatter checks assert the host tree exists (the module-level render always produces it). - cso-docker staged-runtime test uses test.skipIf so reports show it as skipped, not passed. * test(ship): convert ship-workflow-clarity sentence pins to structural checks Add test/helpers/prompt-structure.ts (between, expectTokens, expectAbsent, expectOrdered, expectMentions) with fix text on failure. ship-workflow-clarity now pins headings, step order and machine-read tokens (commands, fields, enum and status strings); safety rules are meaning-level keyword checks. Wording is judged by the 'ship/SKILL.md workflow' judge in skill-llm-eval. Sentence pins: 90 -> 0. * ci: add platform-qualification lane for opt-in ML, gitleaks and Swift tests (W8d, CEO-24) security-bench + security-live-playwright L4 (SECURITY_BENCH), the real gitleaks 8.30.1 memory-ingest cases (GSTACK_TEST_GITLEAKS) and the DebugBridge Swift build invariants (GSTACK_TEST_SWIFT) self-skip in every lane today. No scheduled lane has their prerequisites, so per CEO-24 they move to an owned dispatch + quarterly workflow instead of being deleted. Each job was run locally (ML 10 pass, gitleaks 130 pass; Swift needs macOS). test/platform-qualification-workflow.test.ts pins gate variable, job and file together. * fix(scripts): capture-baseline and preflight-agent-sdk no longer act on --help or typos (W8e) capture-baseline parses its flags strictly: --help prints usage, an unknown or valueless flag exits 2, and only a valid invocation writes a fixture (--help used to write test/fixtures/parity-baseline-current.json). preflight-agent-sdk gains --help, rejects unknown flags, and runs the live SDK query (API spend) only with --live. * test(evals): register the three keyless periodic paid files with case ids (W1b) skill-e2e-auq-consistency, skill-e2e-auq-verbose-vs-carved-ab and codex-e2e-recommendation-substance now carry touchfiles, a periodic tier and kind rule (one trial, unchanged), so editing one selects its own case instead of restoring the full PR gate. The verbose A/B case also registers the vendored pre-cut fixture it reads, and review-army-migration-safety registers the SQL fixture it reads. * feat(evals): narrow PR fallback for free-only inputs (W1a, CEO-13/20, ENG-13) The PR profile now exempts the duration seeds, every free-lane workflow (explicit list; inventory test fails on an unclassified workflow, .yaml and workflow_call included), scripts/ubicloud/** and fixtures declared in the explicit FREE_FIXTURES map. Each remaining unknown file carries a label and fix (needs touchfile entry / add to FREE_ONLY_PR_FILES / real unknown dependency). evals.yml itself still restores the full gate. * ci: delete ci-image.yml; the eval workflows already build and push the same content-hash tag (W8f) evals.yml, evals-periodic.yml and evals-marathon.yml each compute the identical hashFiles() tag and build/push it (with :buildcache and :latest) when missing, so ci-image's push trigger and weekly cron were no-ops (30-day median 0.5 min, 36/36 success). ci-image-tag-binding now pins the three eval workflows. * ci(evals): key periodic/marathon concurrency on ref+event; branch periodic dispatch skips the gate census (W2a, ENG-9, CEO-04) * refactor(paid): drop ~160 unused imports; leaf paid-types/paid-select modules break the paid-* import cycle (W8c) * ci(quality-gate): per-PR concurrency, free runner, drop unscoped bun audit (W2a, W8f) - Concurrency keys on pull_request.number || run_id, so back-to-back main pushes no longer cancel each other's credential scan. - ubuntu-24.04 instead of a billed 8-vCPU Ubicloud runner for a ~1 min job. - bun audit --audit-level=critical ran on every PR regardless of diff, so a newly published advisory turned unrelated PRs red, with its own ignore policy. dependency-review (lockfile PRs, fail >= high) and the weekly OSV sweep remain the dependency gates. * chore(test-free): refresh the free duration seed from the audit's Ubicloud recording Adds the 19 files merged after the last refresh, including the 115 s claude-overlay-setup that packed as ~1 s and doubled a shard (W6a). The seed is re-recorded on the final tree at the end of this wave. * ci: move tiny ubicloud-standard-2 jobs to free ubuntu-24.04 runners (W8f) actionlint, skill-docs, dependency-review, version-gate and pr-title-sync are sub-minute jobs; GitHub-hosted runners are free for this public repo. * feat(test-free): pessimistic unseeded packing, seed growth ratchet and CI health summary - Unseeded files pack at the seed's p99 instead of p75 (W6a). - --ci-plan warns in the job summary past 5 unseeded files; --ci-verify lists shards that outran their prediction by 1.5x (and 30 s) plus every flaky pass absorbed by the serial retry (W6a, W7a job summary). - test/free-seed-ratchet.test.ts fails when a seeded file over 60 s is not on scripts/free-test-seed-allowlist.json, when an entry is stale, and when the allowlist grows versus its merge-base copy unless the new entry is an annotated exception with a todo (CEO-10, DX-7). free-plan runs it with full history so the shrink check is real in the required lane. - Every message names the fix command and docs anchor (DX-6). * feat(evals): state PR coverage mode, counts, reuse and fallback files in the summary and comment (CEO-13) * test: make the tracked-tree skill-doc freshness check local-only; tidy skill-docs header (W8f) Every free CI shard regenerates the tracked SKILL.md files before running tests, so the --dry-run freshness assertion compared the regenerated tree with itself and could not fail there. It now skips under GitHub Actions; skill-docs.yml's git diff --exit-code is CI's freshness gate. Removes a stale concurrency comment in skill-docs.yml. * ci(free-tests): install zsh so the bash+zsh portability arms run (W6f) ~42 zsh-arm tests (aside-probe-shell, qa-browser-preservation, generated-docs-fences) skipped in CI because zsh is not in the runner image. All 141 tests in those files pass with zsh present. * feat(evals): executors write negative receipts at the execution boundary (CEO-25, ENG-6) A completed single-trial rule/judge shard that did not pass now writes its negative receipt beside the pass receipts in the slice artifact, so a cancelled run's FAIL still blocks an older PASS when its report never runs. Receipts merge negatives first and order by (run attempt, completedAt); a same-second FAIL/PASS tie resolves to FAIL. The runner call site is a one-line hunk in scripts/test-paid-shards.ts. * docs(cso): state that contained runtime/scanner execution is unavailable today The scanner catalog is empty while its build inputs await review and the runtime catalog holds no qualified profile until the private evaluator exists, so /cso runs static assessment only. AGENTS.md, README and docs/cso-release-qualification.md now say so; docs/cso-scanners.md already did. * test(helpers): expectMentions splits on sentence ends only Clauses joined by ';' or ':' are one rule; splitting there made a reworded rule fail for punctuation. * test(plan-ceo): convert skill-ceo-section-ordering sentence pins Safety and authority rules (never/do not/stop/only/without/wait/approval) are meaning-level expectMentions checks; other sentence pins are dropped. Headings, labels, option rows, placeholders and machine-read lines (auto-decide annotation, Mode:/approved decisions format, STATUS/SOURCE fields, CROSS-MODEL marker, gstack-ceo-mode-handoff) stay as tokens; ordering checks unchanged. Behavior is covered by the periodic PTY case in skill-e2e-plan-ceo-review-section-loading.test.ts. Sentence pins: 210 -> 23. * test(helpers): expectMentions treats wrapped lines as one sentence Templates hard-wrap prose; only sentence ends and blank lines separate rules. * test(gen-skill-docs): convert sentence pins to meaning checks or drop them Safety/authority sentences become expectMentions keyword checks; other English sentences are dropped (wording is judged by the per-skill workflow judges in skill-llm-eval and the E2E cases in touchfiles-data). Commands, config keys, markers (PLAN MODE EXCEPTION, NO UNRESOLVED DECISIONS, Gate outcome), field names and alternation-based meaning regexes stay. Removed the now-empty 'contains opt-in AskUserQuestion text' test (only pinned a sentence; the resolver's AskUserQuestion wiring is covered by the codex second-opinion tests in the same describe). Lane E's existsSync hunks are untouched. Sentence pins: 216 -> 65 (remaining lines carry machine tokens). * ci(windows): shard the Windows lane via --ci-plan/--ci-run/--ci-verify; move native campaigns to native-qualification.yml - windows-free-tests.yml: a Linux plan job curates and packs the Windows-safe files into 6 shards, one strict serial shard per windows-latest job, and a Linux aggregate verifies exact coverage and every result (8.1 min on one runner today). --windows-only now combines with the CI modes; the plan binds the curated file set (W6e). - Every Windows plan and --list run prints the curated count with its top exclusion reasons in the job summary; a free ratchet fails when the curated subset drops below its floor, with the fix (W6e). - The four Dia/cookie diagnostic dispatch campaigns move to the dispatch-only native-qualification.yml with one exclusive `mode` choice input, so their red dispatch runs no longer read as a red PR lane (W8f). Their workflow pins move to test/windows-native-workflows.test.ts; the boolean-exclusivity guard is replaced by the choice input. * feat(paid): per-slice CI job ceilings and an in-process slice deadline with not_run/hung outcomes and checkpoints (W2c, ENG-2) * fix(pass-rates): segment trial history strictly by EVAL_POLICY version Reader-compatibility floor for EVAL_POLICY v2 (ENG-14/CEO-35/DX-12). Only trials under the reader's own policy version feed labels and alarms; older policy trials stay visible but are never scored or used as a drift baseline; trials from a newer policy are ignored with a printed count and fix text. Reverting the later v2 writer commits leaves a reader that cannot pool v2 records into v1 series (the pre-PR reader at2db0b3adoes: it reports a mixed fixture as FAILING with drift alarms). * docs: one contributor command table; retired commands, seed sources and current workflows (W8g, DX-5, DX-13, CEO-12) - CONTRIBUTING.md gains 'Which command do I run?' (task -> command -> cost/time -> needs, including branch validation via gh workflow run); CLAUDE.md, AGENTS.md and TESTING_INTERNALS.md link to it instead of repeating command lists. Tier tables drop retired commands and stale per-run dollar estimates. - Retired names (test:evals, test:e2e, eval:bg, eval:flake-rank, eval:watch, ...) are gone from CLAUDE.md, CONTRIBUTING.md, TESTING_INTERNALS.md, ARCHITECTURE.md and USING_GBRAIN_WITH_GSTACK.md. - The flake-ledger claim now says what happens: CI uploads flake-ledger-* artifacts; eval:pass-rates reads only the local ledger. - TESTING_INTERNALS states that only test:ubicloud --record-durations produces an acceptable duration seed (DX-13). - CI section: quality gate no longer runs bun audit; dependency-review's real trigger; the platform-qualification lane. - docs/test-audit-2026-09.md gets a corrections section for its stale claims. - TODOS.md: audit follow-ups (post-merge metrics, stub removal, name reclaim, diff-aware planner); eval-watch shard-awareness and the image freshness tripwire closed as won't-do. * feat(evals): recover receipts of cancelled PR runs (W1c, CEO-14/34, ENG-4/5/7) A new recover-receipts job runs base-ref code with actions: read, restores the PR's store, merges the receipts of completed cancelled evals.yml runs for this PR (provenance-checked, at most 5, oldest first, negatives first), reconstructs completed panel negatives with panelVerdict() (partial panels get no credit) and keeps a recovery.json checkpoint that never advances past an unresolved run. plan-slices keeps contents: read, takes the store as an artifact, turns reuse off when recovery degraded or a run is unresolved, and carries the whole store to slices-report so nothing is lost. Any gh problem degrades to no recovered receipts with a named reason. * feat(evals): classify this wave's free-only tools and workflows for PR selection platform-qualification.yml, retired-command.ts, test-health-report.ts, bump-harness-version.ts and eval-bg.ts never run inside a paid case. * feat(evals): debounce PR push bursts before planning paid slices (W1d, CEO-15, ENG-11, DX-7) A tiny ubuntu-24.04 job waits 90 s only on synchronize when another run for the PR started in the last 15 minutes; cancel-in-progress supersedes, and a run that outlives the wait reports "superseded by <sha>" and plans nothing. Labels: evals-no-debounce skips the wait, evals-fresh disables receipt reuse. * perf(test): move the real-process browser settlement cases out of test-free-shards.test.ts (W6b) The 19 owned-browser settlement modes were 85 s of the file's 95 s and could not be packed apart from the fast runner unit cases. They move to a shared fixture with two files (lifecycle 47 s, ownership 39 s); the unit file drops to 10 s. Same modes, same assertions. * chore(evals): delete the finished validation_phase dispatch and its inline planner (W8f) Retirement (CEO-24): the protected behavior was a one-off cookie-repair validation subset (eight dependent cases) and a quality/behavior split of the census; that validation is complete, so the guarantee is withdrawn. Branch validation dispatches evals.yml with evals_all. * perf(test): inject the office-hours record grace in non-cooperative deadline tests * perf(test): shrink aside-render process slack via GSTACK_RENDER_SLACK_MS in timeout tests * perf(test): make the memorable lock give-up configurable for lock-contention tests * perf(test): check install-timeout knob normalization through its own setup lines * perf(test): inject a 2 s storage-reset deadline in the late isolated dispatch test * perf(test): shorten the slow gbrain fake to 1 s, still past the 300 ms probe timeout * ci(free-tests): run only cso-docker-integration in the free CSO Docker job (F16) cso-node-lifecycle-integration and cso-stack-cold-integration need GSTACK_CSO_TEST_STACK images and always skipped there; they stay in the CSO runtime workflows through test:cso:docker. * test(gen-skill-docs,plan-ceo): split mixed sentence pins into tokens and rules Sentences that wrap a backticked or bold token keep the token (expectTokens) and, when they state a safety rule, a keyword check; short safety sentences (25-39 chars) get the same treatment. * test(plan-ceo): convert ceo-workflow-clarity.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: periodic PTY case skill-e2e-plan-ceo-review-section-loading and the plan-ceo workflow judges. Sentence pins: 13 -> 1. * test(plan-eng): convert eng-review-routing.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: plan-eng E2E cases (skill-e2e-plan-eng-*) and the plan-eng workflow judge. Sentence pins: 28 -> 6. * test(plan-eng): convert eng-scope-entry-ap.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: plan-eng E2E cases (skill-e2e-plan-eng-*) and the plan-eng workflow judge. Sentence pins: 16 -> 5. * test(plan): convert plan-scope-selection.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: plan-review E2E cases and workflow judges in skill-llm-eval. Sentence pins: 19 -> 2. * test(qa): convert qa-lazy-sections.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: qa/qa-only E2E cases (skill-e2e-qa-*) and the qa workflow judge. Sentence pins: 71 -> 11. * test(qa): convert qa-browser-preservation.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: qa/qa-only E2E cases (skill-e2e-qa-*) and the qa workflow judge. Sentence pins: 25 -> 11. * test(qa): convert qa-probe-gates.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: qa/qa-only E2E cases (skill-e2e-qa-*) and the qa workflow judge. Sentence pins: 20 -> 5. * test(qa): convert qa-checkpoint-evidence.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: qa/qa-only E2E cases (skill-e2e-qa-*) and the qa workflow judge. Sentence pins: 7 -> 5. * test(qa): convert qa-evidence.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: qa/qa-only E2E cases (skill-e2e-qa-*) and the qa workflow judge. Sentence pins: 4 -> 3. * test(design): convert design-consultation-contract.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: design-consultation E2E/judge cases in touchfiles-data. Sentence pins: 44 -> 11. * test(outside-voice): convert run-in-background-guidance.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: outside-voice E2E cases and plan-review workflow judges. Sentence pins: 35 -> 5. * test(spec): convert spec-template-invariants.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: spec E2E/judge cases in touchfiles-data. Sentence pins: 36 -> 21. * perf(evals): 420 s census slice budget; case-shard skill-e2e-qa-workflow; seed its case walls (W5c) * feat(evals): evals.yml dispatch contract for eval:bg (CEO-17/29, DX-1, ENG-8/12) workflow_dispatch gains base_ref, base_sha, expected_sha, nonce and pr_receipts. The nonce appears in run-name so the dispatcher resolves its own run; evals_all=false runs the PR profile against base_sha/base_ref; a checkout that differs from expected_sha fails before any paid work with a named fix; pr_receipts reads that PR's receipts read-only through the recover-receipts artifact path (never the cache) and never saves. * ci(windows): pack the Windows lane with Windows-measured durations (W6e) The first sharded run (37221451711) finished in 6.0 min: the Linux seed has browse/test/cookie-import-native-job.test.ts at ~0 s (its cases skip on Linux) but it takes 122 s on Windows, so one shard ran 242 s against an 84 s prediction. The plan now reads scripts/free-test-durations-windows.json; a record_durations dispatch times every Windows-safe file alone and uploads it. * test(free): settlement case files import the runner rule they exercise Keeps the split files out of the test-of-test ratchet: the retry-eligibility rule is a direct runner import passed to the shared fixture. * fix(marathon): no hollow plan-decision-classification shard; office-hours marathon scenario scoped to the pilot (W2f) * test(free): satisfy the typecheck:test ratchet in the seed ratchet test * refactor(ci-history): one shared GitHub history reader with the CI flake-ledger reader Extract pass-rates' gh fetch layer into scripts/lib/ci-history.ts (CEO-09) and add the W7a reader: paged run listings that fail whole on any page error, per-run artifact downloads (cached, size-capped, data only), flake-ledger parsing, the pre-registered flaky-file rule (> 5% of main free-tests runs over a window of at least 20 runs, widened to the newest 20 runs when the window is thinner), a job-summary table, and named unavailable reasons with next steps. * feat(test-health): test:health report of the audit success metrics scripts/test-health-report.ts (CEO-09/06/22/32, DX-8/9/12/13) prints every success metric with its counting rule from CI history: PR full-fallback rate, reused PR trial records, PR-lane spend per merged PR and per validated revision, cancelled slice-minutes per week, push-to-verdict p50/p95, census expected failed trials per run with raw failure rate per kind/class and P(lane red) under the recorded panels vs single-trial aggregation, INFRA re-dispatches, quarantine evidence (insufficient evidence distinct from healthy), free flaky-pass rate, free/Windows wall, free serial time and the net-complexity line. An unreadable input prints 'unavailable: <reason>; next: <step>', never 0. --enforce fails on a flaky file (W7a) or > 5 unseeded free files (CEO-10); unavailable checks never fail and keep the issue open. * test(review): convert review-workflow-clarity.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: review E2E cases (skill-e2e-review*) and the review workflow judge in skill-llm-eval. Sentence pins: 85 -> 17. * test(review): convert review-entry-and-design-clarity-au.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: review E2E cases (skill-e2e-review*) and the review workflow judge in skill-llm-eval. Sentence pins: 15 -> 4. * test(review): convert review-enum-lifecycle.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: review E2E cases (skill-e2e-review*) and the review workflow judge in skill-llm-eval. Sentence pins: 8 -> 0. * test(ship): convert ship-control-flow.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: ship E2E cases (skill-e2e-ship*, skill-e2e-workflow) and the 'ship/SKILL.md workflow' judge. Sentence pins: 74 -> 9. * test(ship): convert ship-skip-requeue.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: ship E2E cases (skill-e2e-ship*, skill-e2e-workflow) and the 'ship/SKILL.md workflow' judge. Sentence pins: 28 -> 3. * test(ship): convert ship-plan-completion-invariants.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: ship E2E cases (skill-e2e-ship*, skill-e2e-workflow) and the 'ship/SKILL.md workflow' judge. Sentence pins: 28 -> 12. * test(ship): convert ship-reentry-gates.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: ship E2E cases (skill-e2e-ship*, skill-e2e-workflow) and the 'ship/SKILL.md workflow' judge. Sentence pins: 16 -> 4. * test(ship): convert ship-document-release-dispatch.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: ship E2E cases (skill-e2e-ship*, skill-e2e-workflow) and the 'ship/SKILL.md workflow' judge. Sentence pins: 11 -> 4. * test(ship): convert ship-apple-gate.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: ship E2E cases (skill-e2e-ship*, skill-e2e-workflow) and the 'ship/SKILL.md workflow' judge. Sentence pins: 7 -> 0. * test(ship): convert ship-skip-actor.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: ship E2E cases (skill-e2e-ship*, skill-e2e-workflow) and the 'ship/SKILL.md workflow' judge. Sentence pins: 6 -> 1. * test(ship): convert ship-template-redaction.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: ship E2E cases (skill-e2e-ship*, skill-e2e-workflow) and the 'ship/SKILL.md workflow' judge. Sentence pins: 5 -> 4. * test(ship): convert ship-publication-gates.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: ship E2E cases (skill-e2e-ship*, skill-e2e-workflow) and the 'ship/SKILL.md workflow' judge. Sentence pins: 5 -> 2. * test(ship): convert ship-review-loop.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: ship E2E cases (skill-e2e-ship*, skill-e2e-workflow) and the 'ship/SKILL.md workflow' judge. Sentence pins: 3 -> 1. * test(ship): convert ship-version-sync.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: ship E2E cases (skill-e2e-ship*, skill-e2e-workflow) and the 'ship/SKILL.md workflow' judge. Sentence pins: 5 -> 2. * test(ship): convert ship-pr-liveness-policy.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: ship E2E cases (skill-e2e-ship*, skill-e2e-workflow) and the 'ship/SKILL.md workflow' judge. Sentence pins: 4 -> 0. * test(plan-review): convert plan-review-cases.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: plan-review E2E cases and workflow judges in skill-llm-eval. Sentence pins: 58 -> 15. * test(autoplan): convert autoplan-phase-order.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: autoplan E2E cases (skill-e2e-autoplan-*) and the autoplan workflow judge. Sentence pins: 42 -> 11. * test(autoplan): convert autoplan-phase-handoff.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: autoplan E2E cases (skill-e2e-autoplan-*) and the autoplan workflow judge. Sentence pins: 20 -> 4. * test(autoplan): convert autoplan-snapshot.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: autoplan E2E cases (skill-e2e-autoplan-*) and the autoplan workflow judge. Sentence pins: 21 -> 5. * test(outside-voice): convert outside-voice-preflight.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: outside-voice E2E cases and plan-review workflow judges. Sentence pins: 26 -> 9. * test(ask-format): convert resolver-ask-user-format.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: AUQ E2E cases (skill-e2e-auq-*); prompt-injection rule kept as a meaning check. Sentence pins: 32 -> 15. * test(skills): convert binding-template-drift.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: workflow judges in skill-llm-eval. Sentence pins: 19 -> 13. * test(skills): convert carve-plan-fixture.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: workflow judges in skill-llm-eval. Sentence pins: 20 -> 6. * test(land-and-deploy): convert land-and-deploy-postfail.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: land-and-deploy E2E cases and its workflow judge. Sentence pins: 21 -> 14. * test(land-and-deploy): convert land-and-deploy-ci-gate.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: land-and-deploy E2E cases and its workflow judge. Sentence pins: 5 -> 4. * test(land-and-deploy): convert land-and-deploy-flow.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: land-and-deploy E2E cases and its workflow judge. Sentence pins: 5 -> 3. * test(office-hours): convert office-hours-completion.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: office-hours E2E cases (skill-e2e-office-hours*). Sentence pins: 16 -> 1. * test(plan-ceo): restore the stale closing-route guard The negative check for 'Closing hooks' / 'return to section' guards a retired route token, not a sentence; the first conversion pass dropped it. * ci(test-health): weekly test-health workflow with an honest tracking issue New test-health.yml (CEO-18/DX-9): Monday 10:00 UTC after the periodic census plus dispatch, free ubuntu-24.04 runner, permissions contents:read + actions:read + issues:write only. Runs bun run test:health --since-days 7 --enforce; an enforced failure upserts one tracking issue, a run with unavailable inputs keeps it open and lists them, and it closes only when every enforced check has evidence and passes. Only main runs touch the issue. * feat(evals): an edited paid test file runs its own gate cases in the PR lane (DX-11) A gate case outside the audited fast profile is selected when its single owning paid test file changed and the runner can select it by name (its Bun test is named by the case id). The manifest records directCases and validation accepts only recorded, name-addressable ones; the runner and planner read the file->cases map from test-pr-profile. Cases the runner cannot address stay deferred with the fix. An inventory test covers every owned gate case. Touches one hunk each in test-paid-shards.ts and lib/paid-plan.ts, and pr-shared-input-selection.test.ts's ship-skip pin. * ci(osv): tracking issue for scheduled reds and a 14-day suppression expiry test F11/W8f: a failed main OSV scan now upserts one tracking issue and a clean scan closes it (scheduled reds notified no one during the August backlog). A free test fails 14 days before any .osv-scanner.toml ignoreUntil (all four expire 2026-11-30), with the fix: upgrade and delete, or re-justify and move the date. * test(ship,review): keep guards against retired fail-open instructions 'skip silently' on reviewer failure and 'do not block /ship on subagent failure' were harmful instructions, not prose style; keep them absent with the shortest distinctive phrase. * feat(eval-select): default to the pr profile DX-10: eval:select previews the PR lane's selection by default, matching test:pr and eval:bg:pr; --profile full (or EVALS_PROFILE=full) keeps the plain touchfile selection. * test(evals): type-clean the recovery gh fake (typecheck:test ratchet) * chore(windows): record the Windows duration seed (run 37221963236) 573 Windows-safe files timed alone on windows-latest; cookie-import-native-job is 102 s there. Six shards now predict 154 s each. * feat(evals): eval:bg dispatches the pushed ref to CI or runs locally under a 1.5x-planned cap (W5d, CEO-17/29, DX-1/2/3/7, ENG-12/19) * feat(runners): --help on both shard runners via the shared flag loop; paid runner header describes today's planner/executor/report (W8e) * test(windows): drop the stale Playwright exclusion and force-include probe-proven files (W6e) A temporary windows-latest probe (run 37221995077) ran each of the 97 files excluded for 'launches Playwright browser' or 'raw /tmp/ path' alone: all 17 Playwright files pass (Chromium is installed and Bun drives it there), and 41 of the /tmp files pass with executed cases. The Playwright pattern is removed and the 41 files are force-included with the probe as their reason; the 36 real failures stay excluded. The curated subset grows from 573 to 631 files and the ratchet floor follows. Windows curation moves to scripts/lib/windows-curation.ts (the runner drops to 2000 lines). * test(free): one install fixture cloned from a read-only seed (W6c, ENG-1) Merge test/helpers/setup-codex-scope-fixture.ts into install-fixture.ts. The checkout is built once per test file into a read-only seed and cloned per fixture with copy-on-write where the filesystem has it (full copy otherwise), restoring each file's own mode; clones never hard-link the seed because put() and tests write in place. Callers register afterAll(cleanupSeed); Bun's runner fires no exit event, so seeds of killed runs are swept by pid. test/install-fixture.test.ts is the ENG-1 tripwire: put/setVersion/chmod in one clone leave the seed and a sibling unchanged, and clones share no inodes with the read-only seed. * test(free): split claude-overlay-setup by describe (W6b) The 115 s serial file becomes default/lifecycle/installs files (5/4/3 tests, unchanged bodies) sharing test/helpers/claude-overlay-fixture.ts, so the shard packer can balance them. * test(cso): convert cso-contracts.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: cso E2E/judge cases (skill-e2e-cso*, cso-eval). Sentence pins: 16 -> 8. * test(cso): convert cso-preserved.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: cso E2E/judge cases (skill-e2e-cso*, cso-eval). Sentence pins: 10 -> 3. * test(cso): convert cso-eval.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: cso E2E/judge cases (skill-e2e-cso*, cso-eval). Sentence pins: 7 -> 4. * test(browser): convert aside-driver.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: Aside/browse E2E cases; the installer ban stays a meaning check. Sentence pins: 27 -> 9. * test(browser): convert third-party-actions.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: Aside/browse E2E cases; the installer ban stays a meaning check. Sentence pins: 17 -> 2. * test(skills): convert skill-validation.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: workflow judges in skill-llm-eval. Sentence pins: 19 -> 6. * test(skills): convert workflow-excerpt.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: workflow judges in skill-llm-eval. Sentence pins: 37 -> 10. * test(skills): convert question-tuning-registry-path.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: workflow judges in skill-llm-eval. Sentence pins: 4 -> 0. * test(skills): convert host-conformance.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: workflow judges in skill-llm-eval. Sentence pins: 4 -> 4. * test(memory): convert memory-ingest-landing.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: memory-ingest free tests that run the binary. Sentence pins: 11 -> 9. * test(windows): exclude the skip-only claude-overlay setup files from the Windows subset Their real-setup cases are describe.skipIf(win32); after the split their bin/ spawns live in the shared helper, so the source scan stopped seeing them. * test(skills): convert agents-digest.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: the owning skills' E2E cases and workflow judges; CLI/hook output and fixture-data pins in the tail were left alone. Sentence pins: 1 -> 0. * test(skills): convert brain-preflight.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: the owning skills' E2E cases and workflow judges; CLI/hook output and fixture-data pins in the tail were left alone. Sentence pins: 2 -> 1. * test(skills): convert codex-skill-isolation.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: the owning skills' E2E cases and workflow judges; CLI/hook output and fixture-data pins in the tail were left alone. Sentence pins: 1 -> 0. * test(skills): convert office-hours-review.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: the owning skills' E2E cases and workflow judges; CLI/hook output and fixture-data pins in the tail were left alone. Sentence pins: 2 -> 1. * test(skills): convert onboarding-moved-literals.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: the owning skills' E2E cases and workflow judges; CLI/hook output and fixture-data pins in the tail were left alone. Sentence pins: 2 -> 2. * test(skills): convert open-gstack-browser-liveness.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: the owning skills' E2E cases and workflow judges; CLI/hook output and fixture-data pins in the tail were left alone. Sentence pins: 3 -> 2. * test(skills): convert plan-floor-review.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: the owning skills' E2E cases and workflow judges; CLI/hook output and fixture-data pins in the tail were left alone. Sentence pins: 3 -> 2. * test(skills): convert plan-review-report-recording.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: the owning skills' E2E cases and workflow judges; CLI/hook output and fixture-data pins in the tail were left alone. Sentence pins: 4 -> 2. * test(skills): convert regression-1539-review-self-verify.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: the owning skills' E2E cases and workflow judges; CLI/hook output and fixture-data pins in the tail were left alone. Sentence pins: 4 -> 0. * test(skills): convert skill-fixture.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: the owning skills' E2E cases and workflow judges; CLI/hook output and fixture-data pins in the tail were left alone. Sentence pins: 6 -> 3. * test(skills): convert template-context-parity.test.ts sentence pins Safety and authority sentences become expectMentions keyword checks (reword freely, keep the rule); other English sentence pins are dropped. Headings, labels, placeholders, commands, field names, enum/status tokens and ordering checks stay. Behavior and wording: the owning skills' E2E cases and workflow judges; CLI/hook output and fixture-data pins in the tail were left alone. Sentence pins: 1 -> 0. * test: restore pins on renderer output and paid-fixture inputs cso-contracts (the report renderer's required empty phrase), memory-ingest (binary output), carve-plan-fixture, ship-skip-actor and cso-eval (inputs the paid harness builds) assert product or fixture output, not skill prose, so the value-bar narrowing does not apply to them. * feat(eval-policy): v2 series identity, HARNESS_VERSION guard and identity backtest W4a (CEO-27/ENG-3/DX-6), not yet wired to the writer: caseSeriesIdentitiesV2 keys a case by the bytes it owns (paid test file, fixtures, its skills' prompt files including the generated SKILL.md) plus HARNESS_VERSION, and records the full consumed-input fingerprint as provenance. scripts/harness-version.json pins the blob of every shared-harness file (GLOBAL_TOUCHFILES plus the session runners, PTY harness, e2e gate and LLM judge), one line per file; test/harness-version.test.ts fails on drift with both fixes, and scripts/bump-harness-version.ts records the decision: --bump (new series for every case) or --non-behavioral (compatibility entry, no reset). eval-trial-series --backtest replays identities over weekly main revisions and recorded trials (ENG-3/DX-12). * feat(pass-rates): weekly history is main's scheduled runs plus main dispatches W4b: pass-rates reads evals-periodic history from main only, keeping scheduled runs and main dispatches and never a branch dispatch, so back-to-back branch validation runs neither feed pass rates nor count as weeks for quarantine expiry or drift. --branch <name> still reads one branch's runs for inspection. * docs(test-audit): EVAL_POLICY v2 decision memo with the identity backtest D1 memo (CEO-33, ENG-3, DX-12, CEO-27): P(green) arithmetic, false-blocking targets, the v2 identity rule and harness guard, weekly history, W4c evidence (the named 'stochastic' cases pass 26/27 to 34/34, so they stay rule), the backtest over 29 weekly main revisions and 14,898 recorded trials, what it means for quarantine reachability, alternatives (gating vs trended, adaptive panels not adopted, buy vs build), and the rollback proof on the pre-PR reader. * feat(eval-policy): EVAL_POLICY v2 writer: case-owned series identity The v2 writer, last commit of the W4 block (DX-12/ENG-14/ENG-21): the report job's stamp now writes caseSeriesIdentitiesV2 (case-owned bytes plus HARNESS_VERSION) as series_identity, the full consumed-input fingerprint as series_fingerprint and harness_version as provenance, and EVAL_POLICY.version is 2 (approved 2026-10-04, D1). The v1 touchfile identity is removed. Rollback = revert this commit (and the W4 commits above the reader-compat floor); readers then ignore the v2 records with a printed count. * test: restore pins on paid-harness prompt inputs review-enum-lifecycle and plan-review-report-recording assert the prompt a paid case's harness builds (opts.prompt / call.prompt), a fixture contract, not skill prose. * test(security): check injected safety lines on meaning, not capitals content-security, the canary instruction and the arm judge prompt still must carry their never-follow / never-output / exact-"none" rules; the checks are case-insensitive keyword checks so emphasis can change. The UNTRUSTED envelope markers and "none" value stay exact tokens. (Hidden element stripping fails locally only because Playwright Chromium is not installed; same at base.) * test(plan-ceo): keep the outside-voice scope-summary rule as a meaning check The first codemod pass left an empty if body (TS1313). * chore(windows): re-record the Windows duration seed for the 631-file subset (run 37222668939) * ci(free-tests): summarize every shard's flake ledger in the aggregate job (W7a) The aggregate downloads flake-ledger-* (one subdirectory per shard) and appends lane C's `scripts/test-health-report.ts flake-summary` output to the job summary before strict verification. The runner's own flaky table is dropped so the ledger reader stays the single source; --ci-verify keeps the shard-overrun warning. * feat(evals): free test files anywhere and the stored-zip helper never restore the full PR gate (W1a) The CEO-23 replay found design/test free tests forcing fallback (36485436963). * feat(evals): replay recorded PR pushes through today's selector (CEO-23, ENG-18) scripts/replay-pr-selection.ts reports per push the recorded vs replayed mode and case count, dropped gate cases, retired failed cases and every miss (a failed case that depends on the diff but is no longer selected). * refactor(evals): one case-sharded carve-section-loading file with a case id and touchfiles per skill (W5a) * test(free): hold qa-deadline's full-pipe case on a FIFO, not a paused Bun stream Bun gives a child 'pipe' stdio a unix socketpair, so whether the 2 MB fill actually blocks depends on the parent's reader and the host's socket buffer sizes. CI (run 36761671811, both attempts) saw exit 0 after ~130 ms; with net.core.{w,r}mem_default=4 MiB locally the old case fails 3/3 the same way. A FIFO the test never reads is bounded by the kernel pipe buffer, so the receipt write genuinely blocks and the 5 s settlement deadline must fire. The 7 s bound now starts once the preload has queued the write. * test(free): event-driven waits in pty-output-wake close-releases-observers: the 500 ms wall race becomes an ordering check (the waiter is released while only SIGINT has been sent, before close's escalation finishes), and the Bun.spawn spy fakes only the PTY launch so a shard neighbor's in-process spawn cannot add a stray SIGTERM (CI runs 36015568981, 36036582721, 36074636848). continuous-redraws: the fixture spinner stops once the observer has made five coalesced reads, so the run reaches its work deadline with no redraw in flight. Streaming right up to the deadline raced the helper's screen drain and failed as 'PTY screen parse failed; viewport is incomplete' (5 CI runs 09-30..10-03; 4/40 locally under 8 busy loops, 0/40 after). * test(free): session-runner long-capture handshake waits for the collected Read event The fake CLI's init line arms the runner's work-phase timer, so the worker's handshake (work-ready + a >200 s timer) could pass before the runner's read loop had collected the Read event printed just before work-ready. Advancing the clock then killed the run with the Read lost: readSection false (CI run 37194511124). The worker now also waits for the runner's own progress line for that Read. Forcing the observed ordering (work-ready 200 ms before the Read line) fails the old test deterministically and passes the new one. * test(free): budget-override restores the CI variables it rewrites Its provenance cases set and then deleted CI, GITHUB_ACTIONS, GITHUB_REF_NAME, GITHUB_SHA and the GitLab CI_* names without restoring them, so in a CI shard every later file ran with CI unset. qa-only-cleanup's real browse daemons then launched Chromium without --no-sandbox, the sandbox failed on the runner, and both real-Chromium cases timed out with 'QA cleanup fixture did not become ready' (shard 12 attempt 1 of six runs on 10-04, retry alone green). Retained startup log: 'Chromium sandboxing failed!', child env with no CI. Reproduced 3/3 with CI=true, userns denied and budget-override ahead of qa-only-cleanup in one process; 0/3 after. * test(free): pr-shared-input-selection names its base and package history Every selection now passes EVALS_BASE and packageVersionOnly explicitly, so no case reads the checkout's git state. Before, 12 calls ran detectBaseBranch and the cumulative case diffed package.json against merge-base(origin/main, HEAD) — the ambient input that turned main red in runs 36572856858 and 36594314027. A PATH git spy counts 14 git calls in the old file and 0 now. * feat(evals): derive PR-lane dependents for unmapped files instead of restoring the full gate scripts/pr-dependencies.ts derives, from the checked-out tree, which paid cases consume each repository file: test import closures, repo paths and path.join segments in code/shell/skill text (whole-line comments and selection data excluded), bin script names, compiled binaries by outfile path (scripts/build.sh), package scripts, template placeholders through RESOLVERS, and host configs by host id. The global touchfiles' import closure is global. PR selection: an unmapped file with derived consumers puts the run in the new 'dependents' mode (every dependent gate case and judge, no profile cut); a tracked file under a derivable directory that nothing reaches is exempt; periodic/marathon workflows, .gitignore and tsconfig.test.json never run the PR gate. PR_FULL_GATE_FILES is the fail-closed list (deps, CI image, setup, build, evals.yml and its actions, test preload, tsconfig.json, .gitattributes, the skill generator and preamble resolvers, the eval policy). Untracked or underivable files restore the full gate with fix text. The summary and PR comment list derived dependents. * feat(evals): replay misses count derived dependents; report wave vs ordinary pushes (CEO-23) * test: drop FREE_FIXTURES entries for fixtures deleted in W8b * test: re-shape the census attribution fixture to qa-workflow and carve case shards * test: census fixture case order * ci: 420 s PR-lane slices with per-slice ceilings; periodic tracking issue only on main evals.yml joins the census lanes at the 420 s slice budget (W5c/CEO-15) and indexes each eval slice's job timeout from .plan.sliceCiTimeoutMinutes with the slice-deadline clock as its first step (W2c/ENG-2). evals-periodic.yml's tracking-issue upsert and close run only on refs/heads/main, so a branch dispatch whose gate census is skipped (CEO-04) never opens or closes #2755. * docs: integrate lane docs for the audit wave (eval-bg backends, PR fallback, policy v2, ceilings, evidence) - CLAUDE.md: 'Running evals as an agent' describes scripts/eval-bg.ts's dispatch and local backends, forcing flags, the sentinel and status; eval:select's PR-profile default; prompt-structure helper and value-bar terms. instruction-facts now requires scripts/eval-bg.ts in that section. - CONTRIBUTING.md: decision table gains test:health, eval:select default, eval:bg backends and the include_gate_census / evals_all dispatch lines; 420 s runners and per-runner ceilings; flake ledger, OSV tracking issue and expiry test, weekly test health; prompt-structure guidance. - AGENTS.md: build commands name the eval:bg backend choice and test:health. - docs/TESTING_INTERNALS.md: anchors the fix texts point to (#pr-paid-lane-fallback, #pass-rate-policy-versions, #harness-version, #flake-ledger, #duration-seed), receipts/recovery/debounce, per-slice ceilings, the slice deadline with not_run/hung and checkpoints, the eval-bg cap formula in place of the detach floors, EVAL_POLICY v2 history, carve case shards via --case. - docs/test-audit-2026-10.md: CEO-23 replay (165/168 -> 164/168 full-fallback, 0 misses), ENG-17 slice table (re-measured on this tree), D2 prose-pin metric. - TODOS.md: progress note on 'Let pass-rate history decide the rest'. - test/testing-internals-anchors.test.ts: every TESTING_INTERNALS.md#anchor named in code must match a heading. * test(free): hold qa-deadline's blocked-output-pipe receipts on a FIFO The five 'guard %s receipts survive a blocked output pipe' cases filled a paused Bun child pipe with 2 MiB. That pipe is a unix socketpair, so the fill only blocks while the host's socket buffers are smaller than the write: with net.core.{w,r}mem_default=4 MiB the old cases fail 13 of 15 case runs (the guard finishes before the test resumes the stream). The held stream is now a FIFO the test drains only after resume(), bounded by the kernel pipe buffer; Windows keeps the paused pipe. Bounds and assertions are unchanged. * test(free): qa-deadline waits for a written pid, not just the pid file DRIVER and LEAF write their pid with writeFileSync, so under load ready() can see the file before its digits and fail 'expected > 0, received 0' (seen once in 150 loaded runs). After any early failure the finally SIGKILLs the CLI, which orphans the detached command group; a leaf whose pid file is not yet readable then keeps the output stream open and the case hangs to its 15 s timeout (2/80 old-file runs and 3/310 FIFO-only runs under 8 busy loops; the instrumented hang showed the CLI already SIGKILLed by the finally). ready() now polls within the same 3 s bound until the file holds a positive pid. * fix(evals): a deleted file selects the dependents of the live files that still reference it PR selection treated every path absent from the head tree as an unknown dependency, so any PR that deleted a file forced the full gate. A deleted path is now placed like a live one, against the head tree: a matching touchfile selects its cases; live code, skill text or a full-gate input that still references it (path, extensionless import target, relative import, bin name, ancestor directory, compiled-binary outfile; whole-line comments and data files excluded) contributes its dependents, a full-gate referencer restores the full gate with a 'deleted but still referenced' fix, and an unreferenced deleted path has no dependents. Deleted PR_FULL_GATE_FILES entries still force the full gate. Tests that used absent paths as stand-ins for new unmapped files now use tracked root files (or an explicit tracked set); the CEO-23 replay counts misses through those references too. * docs: integrate free-suite lane docs (seed anchor, Windows lane, native qualification, install fixture, flake rules) - docs/TESTING_INTERNALS.md: '### Free suite duration seed' (the anchor the seed messages link) with DX-13, the 99th-percentile packing, --ci-plan warning, --ci-verify overruns and the CEO-10 seed ratchet; the Windows 6-job lane, its Windows-measured seed and refresh dispatch, curation and WINDOWS_CURATED_FLOOR; native-qualification.yml modes; the merged install fixture; test-only timing knobs; the flake-ledger job summary, Windows ledger names and three free-suite flake rules; zsh in the Ubicloud mirror. - scripts/test-health-report.ts links #free-suite-duration-seed, so the two seed messages share one heading (the anchor test caught the split). - CONTRIBUTING.md: Windows seed refresh and native qualification rows; seed-source pointer. AGENTS.md: Windows six-job lane. - docs/cso-release-qualification.md: the free CSO Docker job runs only cso-docker-integration.test.ts. - docs/test-audit-2026-10.md: free-suite evidence lines. - TODOS.md: CEO-11b progress note on the pre-push hook hang. * test: final duration seeds on the integrated tree; retire the emptied cookie-validation-phases file Linux seed re-recorded on Ubicloud standard-16 and the Windows seed from dispatch run 37227140871, both atc903310. The seed allowlist drops the three entries that are no longer over the ceiling. cookie-validation-phases lost its validation-phase pins with W8f and its Windows/Dia pins moved to windows-native-workflows with native-qualification.yml, so the file is deleted and the curated Windows floor rises to 638. The Windows recorder writes the seed at its default path so GSTACK_FREE_TEST_DURATIONS never leaks into timed tests. * test: re-express stale PR-lane pins against the new evals.yml contract - ci-eval-cache: the profile/fresh expressions now include evals_all=false dispatches and pr_receipts/evals-fresh; the PR store is restored only by recover-receipts (still scoped to repository_id + PR, PR events only), plan-slices takes it as an artifact and never touches the cache, saves stay PR-only, EVALS_CACHE_PR binds pr_receipts dispatches, and the report verdict artifact carries report receipts. - ci-paid-coordination: plan-slices needs only the two ubuntu coordination jobs (never the image); the fork/Dependabot clause is unchanged on plan-slices and also gates debounce and recover-receipts; only recovery holds actions: read. - qa-supervision-selection: auq-consistency and auq-verbose-vs-carved-ab (W1b) reach claude-pty-runner and pty-screen through auq-sdk-capture, exactly as auq-format-gate does. - paid-retry-supervision: the full-validation plan uses a tracked full-gate input (setup); an absent path is now a deletion placed by its references. * ci(windows): record the Windows seed at the default path * chore: HARNESS_VERSION non-behavioral decision for the audit-wave integration * v1.91.20.0 release metadata: test, eval and CI audit wave * test(compare-board): wait for the post-submit state the feedback POST settles The two post-submit assertions read the board once, but the board disables the submit button and shows the message only after its feedback POST resolves. On a loaded Ubicloud shard the read beat the round trip (FLAKY-PASS in the final free-suite run). Delaying the POST by 400 ms reproduces both failures at HEAD; polling for the settled state passes. * test(plan-eng plan-mode): run the seeded STOP-gate smoke in its own fixture project The seeded plan proposes a custom test runner, so the review's Step 0 reads the working tree's test setup. In the gstack checkout that is gstack's own sharded runner, and the case timed out at 300 s in census 37228573062 after this wave reshaped the runner. It now runs in a four-file Bun project with git history, with the product-notice suppression auto-decide-preserved's standalone fixture already uses. Local pass on Bun 1.4.0 + Claude Code 2.1.284: asked in 121 s, seed tokens observed. * test(plan-mode evidence): pin the seeded eng smoke's isolated fixture cwd and env * ci(image): Git >= 2.44 so paid shared-libs cases run the supported safe-git path bin/gstack-safe-git prefixes every /deslop-shared-libs Git read with --no-lazy-fetch, which noble's git 2.43 rejects (exit 129). The eval image therefore ran every paid shared-libs case on the unsupported-Git fallback: local history unavailable, branch HEAD unknown. shared-libs-read-only failed on exactly that in PR run 37230639146 ("Current branch HEAD: unknown. The safe-git probe failed (unknown option: --no-lazy-fetch, git 2.43.0)") and in 2 of 74 earlier PR runs. The image installs current Git from the Ubuntu Git Maintainers PPA and fails its build if --no-lazy-fetch is missing; the deliberate unsupported-Git case keeps its fake Git. * eval: pool matching branch census trials into main's pass-rate series (D1 option b) Approved 2026-10-05. eval:pass-rates also reads completed branch census runs in the weekly window. A branch trial counts only toward a series a main run also has (same case-owned bytes, HARNESS_VERSION, model and CLI), so a branch extends main's history but never starts or becomes a case's current series; weeks for quarantine expiry still count main runs only. The D1 backtest put this at 67 of 210 cases with enough trials for the entry rule, against 0 of 195 on main alone. * C2: /qa defines its outcome filename fields; QA report templates name the measured timing fields Low judge samples in failing panels named both: qa workflow (37186854666) 'an undefined {user} in the outcome filename', and qa-only workflow (37198445662) 'template asks for Duration / durationMs totals while reporting.md mandates Probe budget and Guarded command time'. The qa union stays under its 1.11 size ratio (93292 of 93294 bytes). (cherry picked from commite14c0c1de1) * C2: Browser Quick gets a feasible budget; QA loop names its directory and stop path Judge rationales on the qa-only panels (2 of the last 3) cited the 30 s Browser Quick budget: homepage + 5 targets, each a checkpoint write and a guarded command, left ~5 s per probe. Quick is now 180 s (method text: 3 minutes); the qa-only-no-fix paid check expects the same native deadline. PROBE_DIR points at its source line, a stopped loop goes to the final report steps (annotations, materialize, Markdown), and /review and /ship say that after smoke expiry only plan checks rerun in revalidation. (cherry picked from commit78d4a2a343) * qa: fit the C2 judge fixes under the qa and review size caps Brings GSTA-21's qa.ts trims (3bd625d,ce73af0) for the cherry-picked C2 wording: PROBE_DIR keeps 'owned', the stop line points at §4, and the post-expiry rule is one sentence, so /review fits its cap. qa measures 93,303 / 84,049 = 1.11010 against the same 1.1102 cap GSTA-21 set. The qa-only workflow judge passed 10 of 10 local trials on this wording (7 of 10 before the C2 fixes). * test: qa-only fixture keeps its caller-set 30 s deadline The qa-only-no-fix fixture tells the model to start the guard with 30 s (a caller limit), so its deadline assertion's default stays 30 000 ms; the product's Browser Quick default (180 s) does not apply to it. Reverts the helper and its test to their base. (cherry picked from commite36e622add) * test: qa-quick sets a caller probe limit and drains past its session budget C2 raised Browser Quick's native budget to 180 s. qa-quick is the only gate case on the native budget, and its wall went 194 s (main periodic, pre-C2) -> 254 s and 274 s (this PR's runs) -> 300 s session timeout (run 37242691913): the agent now probes every navigation target with a checkpoint, then needs ~80 s to report. Like qa-only-no-fix, the eval now sets a caller probe limit (30 s), scopes the fixture, and gives bun's outer timeout the session drain margin instead of racing the 300 s session. The product's 180 s budget and the session budget are unchanged. Diagnostic rerun passed in 195 s. (cherry picked from commitf8dc64031e) * chore: restore the audit wave's package scripts after the main merge (version 1.91.23) * qa: keep main's one-sentence post-expiry rule for /review and /ship The C2 variants ("step 4c reruns plan checks only" and "even in 4c") read to the review workflow judge as conflicting with Step 5.8's repeat-pass reruns: 6 of 10 local trials passed with the longer sentence and PR run 37248650879 failed on the shorter one. Main's "Post-expiry smoke rechecks are not-run." passed 10 of 10. qa (9/10), qa-only (10/10) and ship-managed-hook-refresh (10/10) were measured on the same tree. * v1.91.24.0: move off the slot #3036 claims
gstack
"I don't think I've typed like a line of code probably since December, basically, which is an extremely large change." — Andrej Karpathy, No Priors podcast, March 2026
When I heard Karpathy say this, I wanted to find out how. How does one person ship like a team of twenty? Peter Steinberger built OpenClaw — 247K GitHub stars — essentially solo with AI agents. The revolution is here. A single builder with the right tooling can move faster than a traditional team.
I'm Garry Tan, President & CEO of Y Combinator. I've worked with thousands of startups — Coinbase, Instacart, Rippling — when they were one or two people in a garage. Before YC, I was one of the first eng/PM/designers at Palantir, cofounded Posterous (sold to Twitter), and built Bookface, YC's internal social network.
gstack is my answer. I've been building products for twenty years, and right now I'm shipping more products than I ever have. In the last 60 days: 3 production services, 40+ shipped features, part-time, while running YC full-time. On logical code change — not raw LOC, which AI inflates — my 2026 run rate is ~810× my 2013 pace (11,417 vs 14 logical lines/day). Year-to-date (through April 18), 2026 has already produced 240× the entire 2013 year. Measured across 40 public + private garrytan/* repos including Bookface, after excluding one demo repo. AI wrote most of it. The point isn't who typed it, it's what shipped.
The LOC critics aren't wrong that raw line counts inflate with AI. They are wrong that normalized-for-inflation, I'm less productive. I'm more productive, by a lot. Full methodology, caveats, and reproduction script: On the LOC Controversy.
2026 — 1,237 contributions and counting:
2013 — when I built Bookface at YC (772 contributions):
Same person. Different era. The difference is the tooling.
gstack is how I do it. It turns Claude Code into a virtual engineering team — a CEO who rethinks the product, an eng manager who locks architecture, a designer who catches AI slop, a reviewer who finds production bugs, a QA lead who opens a real browser, a security officer who runs OWASP + STRIDE audits, and a release engineer who ships the PR. Twenty-three specialists and eight power tools, all slash commands, all Markdown, all free, MIT license.
This is my open source software factory. I use it every day. I'm sharing it because these tools should be available to everyone.
Fork it. Improve it. Make it yours. And if you want to hate on free open source software — you're welcome to, but I'd rather you just try it first.
Who this is for:
- Founders and CEOs — especially technical ones who still want to ship
- First-time Claude Code users — structured roles instead of a blank prompt
- Tech leads and staff engineers — rigorous review, QA, and release automation on every PR
Quick start
- Install gstack (about 30 seconds of setup — see below)
- Run
/office-hours— describe what you're building - Run
/plan-ceo-reviewon any feature idea - Run
/reviewon any branch with changes - Run
/qaon your staging URL or an isolated local API, CLI, job or webhook - Stop there. You'll know if this is for you.
Install — about 30 seconds
./setup took 31 seconds after the clone on a 4-vCPU Linux cloud machine (v1.91.13.0, clean HOME, including the binary build and the Chromium download). Slower networks and laptops take longer.
Requirements: Claude Code, Git, Bun v1.0+, Node.js (Windows only). Recommended on macOS: the Aside browser (macOS 15+) — browser skills, /make-pdf, and /diagram drive it first, with your real logged-in sessions. Without it, ./setup builds gstack's own bundled browser and the same skills use that. /cso additionally needs a Bun release with all four --no-compile-autoload-* build flags plus a native toolchain: a static-capable C compiler on Linux, Xcode command-line tools on macOS, or Visual Studio 2022 Build Tools with Desktop development with C++ on Windows. If those are absent, setup installs everything else, removes stale CSO helpers, and /cso reports not assessed with the prerequisite.
When qualified CSO runtime images are published, setup gives each automatic preload a 30-second window plus a bounded setup allowance for the declared catalog. For slower registries, set an integer such as GSTACK_CSO_IMAGE_PULL_TIMEOUT_SECONDS=120 (accepted range: 5–300 seconds). One image timing out does not consume the remaining images' windows; setup reports partial progress and a later run resumes from exact digests already present in local Docker. The complete preload is capped at one hour.
Step 1: Install on your machine
Open Claude Code and paste this. Claude does the rest.
Install gstack: run
git clone --single-branch --depth 1 https://github.com/garrytan/gstack.git ~/.claude/skills/gstack && cd ~/.claude/skills/gstack && ./setupthen add a "gstack" section to CLAUDE.md that says to use the /browse skill from gstack for all web browsing, never use mcp__claude-in-chrome__* tools, and lists the available skills: /office-hours, /plan-ceo-review, /plan-eng-review, /plan-design-review, /design-consultation, /design-shotgun, /design-html, /review, /deslop-shared-libs, /test-audit, /ship, /land-and-deploy, /canary, /benchmark, /browse, /connect-chrome, /qa, /qa-only, /design-review, /scrape, /setup-browser-cookies, /setup-deploy, /setup-gbrain, /retro, /investigate, /document-release, /document-generate, /codex, /cso, /autoplan, /plan-devex-review, /devex-review, /careful, /freeze, /guard, /unfreeze, /gstack-upgrade, /learn. Then ask the user if they also want to add gstack to the current project so teammates get it.
Step 2: Team mode — auto-update for shared repos (recommended)
From inside your repo, paste this. Switches you to team mode, bootstraps the repo so teammates get gstack automatically, and commits the change:
(cd ~/.claude/skills/gstack && ./setup --team) && ~/.claude/skills/gstack/bin/gstack-team-init required && git add .claude/ CLAUDE.md && git commit -m "require gstack for AI-assisted work"
No vendored files in your repo, no version drift, no manual upgrades. Every Claude Code session starts with a fast auto-update check (throttled to once/hour, network-failure-safe, completely silent).
Swap required for optional if you'd rather nudge teammates than block them.
OpenClaw
OpenClaw spawns Claude Code sessions via ACP, so every gstack skill just works when Claude Code has gstack installed. Paste this to your OpenClaw agent:
Install gstack: run
git clone --single-branch --depth 1 https://github.com/garrytan/gstack.git ~/.claude/skills/gstack && cd ~/.claude/skills/gstack && ./setupto install gstack for Claude Code. Then add a "Coding Tasks" section to AGENTS.md that says: when spawning Claude Code sessions for coding work, tell the session to use gstack skills. Include these examples — security audit: "Load gstack. Run /cso", code review: "Load gstack. Run /review", QA test a URL: "Load gstack. Run /qa https://...", build a feature end-to-end: "Load gstack. Run /autoplan, implement the plan, then run /ship", plan before building: "Load gstack. Run /office-hours then /autoplan. Save the plan, don't implement."
After setup, just talk to your OpenClaw agent naturally:
| You say | What happens |
|---|---|
| "Fix the typo in README" | Simple — Claude Code session, no gstack needed |
| "Run a security audit on this repo" | Spawns Claude Code with Run /cso |
| "Build me a notifications feature" | Spawns Claude Code with /autoplan → implement → /ship |
| "Help me plan the v2 API redesign" | Spawns Claude Code with /office-hours → /autoplan, saves plan |
See docs/OPENCLAW.md for advanced dispatch routing and the gstack-lite/gstack-full prompt templates.
Native OpenClaw Skills (via ClawHub)
Four methodology skills that work directly in your OpenClaw agent, no Claude Code session needed. Install from ClawHub:
clawhub install gstack-openclaw-office-hours gstack-openclaw-ceo-review gstack-openclaw-investigate gstack-openclaw-retro
| Skill | What it does |
|---|---|
gstack-openclaw-office-hours |
Product interrogation with 6 forcing questions |
gstack-openclaw-ceo-review |
Strategic challenge with 4 scope modes |
gstack-openclaw-investigate |
Root cause debugging methodology |
gstack-openclaw-retro |
Weekly engineering retrospective |
These are conversational skills. Your OpenClaw agent runs them directly via chat.
Other AI Agents
gstack runs on more agents than Claude. Bare ./setup installs for Claude
Code only. Pick another agent with --host <name>, or install for every agent
setup detects on this machine with --host auto:
git clone --single-branch --depth 1 https://github.com/garrytan/gstack.git ~/gstack
cd ~/gstack && ./setup --host auto # or: ./setup --host codex
./setup --status # one row per install: host, tier, scope, version, path
An explicit --host X installs for X only and never changes another agent's
install. /gstack-upgrade refreshes every install it registered, one row per
host, and says which ones failed.
Tiers: full is certified by a real workflow run (see Certify your host); experimental installs and passes the conformance tests but has no certification run yet; instruction-only installs nothing: setup prints what to copy.
| Agent | Tier | Install | First invocation | Safety skills | Outside review needs | Repair |
|---|---|---|---|---|---|---|
| Claude Code | full | --host claude (default) |
/office-hours |
enforced (hooks block) | Codex CLI, signed in | ./setup --host claude |
| OpenAI Codex CLI | experimental | --host codex → ${CODEX_HOME:-~/.codex}/skills/gstack-*/ |
ask for gstack-office-hours |
advisory, not blocked | Claude Code CLI, signed in | ./setup --host codex |
| OpenCode | experimental | --host opencode → ~/.config/opencode/skills/gstack-*/ + /gstack-* commands |
/gstack-office-hours |
advisory, not blocked | Codex CLI, signed in | ./setup --host opencode |
| Cursor | experimental | --host cursor → ~/.cursor/skills/gstack-*/ |
ask for gstack-office-hours |
advisory, not blocked | Codex CLI, signed in | ./setup --host cursor |
| Factory Droid | experimental | --host factory → ~/.factory/skills/gstack-*/ |
ask for gstack-office-hours |
advisory, not blocked | Codex CLI, signed in | ./setup --host factory |
| Kiro | experimental | --host kiro → ~/.kiro/skills/gstack-*/ |
ask for gstack-office-hours |
advisory, not blocked | Codex CLI, signed in | ./setup --host kiro |
| GitHub Copilot CLI | experimental | --host copilot → ~/.copilot/skills/gstack-*/ |
/gstack-office-hours |
advisory, not blocked | Codex CLI, signed in | ./setup --host copilot |
| Slate | instruction-only | --host slate (points at the Claude install; Slate reads .claude/skills) |
/office-hours via the Claude install |
advisory, not blocked | — | ./setup --host claude |
| OpenClaw | instruction-only | --host openclaw (prints the digest path; ACP spawns Claude Code — docs/OPENCLAW.md) |
"Load gstack. Run /review" | advisory, not blocked | — | re-copy the digest after upgrades |
| Hermes | instruction-only | --host hermes (prints the digest path and gen:skill-docs --host hermes) |
copy the digest, or render skills yourself | advisory, not blocked | — | re-copy the digest after upgrades |
| GBrain (mod) | instruction-only | --host gbrain (brain-aware variants ship from the GBrain repo) |
— | advisory, not blocked | — | — |
Copilot invokes gstack skills by their prefixed names (/gstack-review) because
/review is a Copilot built-in. Copilot ignores skill hooks, so /careful and
/freeze only advise there, and COPILOT_HOME other than ~/.copilot is not
supported yet (setup refuses and changes nothing).
Outside reviews require the selected CLI to be installed and authenticated: Claude Code when using gstack in Codex, or Codex on other harnesses. External harnesses discover these commands as /gstack-claude-code and /gstack-codex; each harness omits its own wrapper. Explicit provider requests keep that provider. The existing codex_reviews setting controls automatic outside reviews where supported, regardless of the provider selected.
/claude has been renamed to /claude-code. Re-run ./setup --host <name> to migrate managed installations, including other harnesses sharing the checkout. Setup preserves the previous installation if replacement generation or installation fails and prints repair instructions.
Instruction-only tier (any rules-reading agent — Zed, Amp, Jules, side projects):
copy the 2KB digest at agents-digest/gstack-AGENTS.md
into a location your agent reads (for example, append it to your project's AGENTS.md).
It carries gstack's ethos, reuse ladder, and voice rules — no install required. The
digest's first line shows its gstack version; re-copy it after upgrading.
For Codex, setup reads the top-level model from
${CODEX_HOME:-~/.codex}/config.toml and generates the matching behavioral
profile, falling back to gpt-6-astra when no usable model is configured.
gpt-5.6-sol automatically receives bounded-scope instructions that
finish the requested lake without expanding into adjacent cleanup or speculative
hardening. The Sol profile is exact-match only: dated snapshots and other 5.6
variants get the generic GPT profile, and setup warns on near-misses like
gpt-5.6-sol-2026-08-01. Override detection with ./setup --host codex --model <id> — the
override applies to that run only; set model in your Codex config.toml to
make it stick across upgrades. After changing your Codex model, rerun
./setup --host codex to regenerate the skills.
Which Codex model gstack uses. For every Codex call (outside voices,
/codex, review and ship adversarial passes), gstack picks the model in this
order: a model you name for that request, then GSTACK_CODEX_MODEL, then
model in your Codex config.toml (for native codex review, review_model
first; a custom CODEX_HOME is honored), and only then gstack's default,
gpt-6-astra. Before spending anything, it prints the choice and where it came
from, for example CODEX_MODEL: gpt-5.6-terra (exec; source: ~/.codex/config.toml model).
If your choice is invalid or your account cannot use it, gstack stops with a
repair message and reports the outside review as unavailable. It never silently
switches to its default. Nested Codex reviews also run with installed skills
hidden (-c skills.include_instructions=false), so a review cannot turn into a
whole nested skill run. Runtime model selection is separate from the setup-time
behavioral profile above. /claude-code (gstack-claude-code
on Codex) preserves Claude's configured model. Set GSTACK_CLAUDE_MODEL=<model>
or name a model in your request to override it for the invocation, including
resumed consultations. See eval defaults and overrides
for capture, judge, and benchmark model selection.
The design binary ($D) uses OpenAI's gpt-5.5 by default, with image
generation through gpt-image-2. Set GSTACK_DESIGN_MODEL=<model> to use
another gpt-5-class model for both image generation and screenshot analysis;
if OpenAI rejects it, the error names GSTACK_DESIGN_MODEL. Check a key
against the defaults with bun run design/scripts/live-model-check.ts.
Want to add support for another agent? See docs/ADDING_A_HOST.md. Rendering a new agent is one TypeScript config file; installing it also needs a setup arm and the conformance kit, and it starts as experimental.
See it work
You: I want to build a daily briefing app for my calendar.
You: /office-hours
Claude: [asks about the pain — specific examples, not hypotheticals]
You: Multiple Google calendars, events with stale info, wrong locations.
Prep takes forever and the results aren't good enough...
Claude: I'm going to push back on the framing. You said "daily briefing
app." But what you actually described is a personal chief of
staff AI.
[extracts 5 capabilities you didn't realize you were describing]
[challenges 4 premises — you agree, disagree, or adjust]
[generates 3 implementation approaches with effort estimates]
RECOMMENDATION: Ship the narrowest wedge tomorrow, learn from
real usage. The full vision is a 3-month project — start with
the daily briefing that actually works.
[writes design doc → feeds into downstream skills automatically]
You: /plan-ceo-review
[reads the design doc, challenges scope, runs 10-section review]
You: /plan-eng-review
[ASCII diagrams for data flow, state machines, error paths]
[test matrix, failure modes, security concerns]
You: Approve plan. Exit plan mode.
[writes 2,400 lines across 11 files. ~8 minutes.]
You: /review
[AUTO-FIXED] 2 issues. [ASK] Race condition → you approve fix.
You: /qa https://staging.myapp.com
[opens real browser, clicks through flows, finds and fixes a bug]
You: /ship
Tests: 42 → 51 (+9 new). PR: github.com/you/app/pull/42
You said "daily briefing app." The agent said "you're building a chief of staff AI" — because it listened to your pain, not your feature request. Eight commands, end to end. That is not a copilot. That is a team.
The sprint
gstack is a process, not a collection of tools. The skills run in the order a sprint runs:
Think → Plan → Build → Review → Test → Ship → Reflect
Each skill feeds into the next. /office-hours writes a design doc that /plan-ceo-review reads. /plan-eng-review writes a test plan that /qa picks up. /review catches bugs that /ship verifies are fixed. Nothing falls through the cracks because every step knows what came before it.
| Skill | Your specialist | What they do |
|---|---|---|
/office-hours |
YC Office Hours | Start here. Six forcing questions that reframe your product before you write code. Pushes back on your framing, challenges premises, generates implementation alternatives. Design doc feeds into every downstream skill. |
/plan-ceo-review |
CEO / Founder | Rethink the problem. Find the 10-star product hiding inside the request. Four modes: Expansion, Selective Expansion, Hold Scope, Reduction. |
/plan-eng-review |
Eng Manager | Lock in architecture, data flow, diagrams, edge cases, and tests. Forces hidden assumptions into the open. |
/plan-design-review |
Senior Designer | Rates each design dimension 0-10, explains what a 10 looks like, then edits the plan to get there. AI Slop detection. Interactive — one AskUserQuestion per design choice. |
/plan-devex-review |
Developer Experience Lead | Interactive DX review: explores developer personas, benchmarks against competitors' TTHW, designs your magical moment, traces friction points step by step. Three modes: DX EXPANSION, DX POLISH, DX TRIAGE. 20-45 forcing questions. |
/design-consultation |
Design Partner | Build a complete design system from scratch. Researches the landscape, proposes creative risks, generates realistic product mockups. Writes DESIGN.md in the open DESIGN.md format, so impeccable, Google Stitch, and any tool that reads it share one file. |
/review |
Staff Engineer | Find the bugs that pass CI but blow up in production. Auto-fixes the obvious ones. Flags completeness gaps. Advisory simplification lens flags over-built code — never blocks, never auto-applies. |
/deslop-shared-libs |
Shared Code Reviewer | Find worthwhile shared-code extractions in recent work. Compares up to five opportunities and recommends the best three, with source evidence, reliability gains, and total code savings. Recommendations only. |
/test-audit |
Test Auditor | Sweep existing tests for ones that cost more than they protect: source greps, duplicates, assertion-free probes, test-only exports. Every candidate carries an evidence card; report-only unless you approve a batch. |
/investigate |
Debugger | Systematic root-cause debugging. Iron Law: no fixes without investigation. Traces data flow, tests hypotheses, stops after 3 failed fixes. |
/design-review |
Designer Who Codes | Same audit as /plan-design-review, then fixes what it finds. Atomic commits, before/after screenshots. If you have impeccable installed, its engine runs first and every mechanical finding arrives tagged with its rule id. |
/devex-review |
DX Tester | Live developer experience audit. Actually tests your onboarding: navigates docs, tries the getting started flow, times TTHW, screenshots errors. Compares against /plan-devex-review scores — the boomerang that shows if your plan matched reality. |
/design-shotgun |
Design Explorer | "Show me options." Generates 4-6 AI mockup variants, opens a comparison board in your browser, collects your feedback, and iterates. Taste memory learns what you like. Repeat until you love something, then hand it to /design-html. |
/design-html |
Design Engineer | Turn a mockup into production HTML that actually works. Pretext computed layout: text reflows, heights adjust, layouts are dynamic. 30KB, zero deps. Detects React/Svelte/Vue. Smart API routing per design type (landing page vs dashboard vs form). One slop-gate pass through the impeccable engine when you have it. The output is shippable, not a demo. |
/qa |
QA Lead | Explore browser, API, CLI, job and webhook behavior. Reproduce bugs, write failing regressions, fix the cause and re-verify before committing. |
/qa-only |
QA Reporter | Explore and report with replayable evidence. Suggest regression cases without changing product code or tests. |
/pair-agent |
Multi-Agent Coordinator | Share gstack's own browser with any AI agent. One command, one paste, connected. Works with OpenClaw, Hermes, Codex, Cursor, or anything that can curl. Each agent gets its own tab. Auto-launches headed mode so you watch everything. Auto-starts ngrok tunnel for remote agents. Scoped tokens, tab isolation, rate limiting, activity attribution. (Runs on the bundled browser — the fallback engine; agents driving Aside just open their own tabs.) |
/cso |
Chief Security Officer | Security audit with an application model, supported findings, independent challenge, and explicit coverage. Static assessment remains available without catalog profiles. With matching qualified profiles, comprehensive mode adds contained runtime/scanner execution and reviewable repair candidates for Node/Bun, Python, and Rails; no qualified runtime or scanner profile is published yet, so audits run static assessment only. Runtime-tested bundles authenticate separate external assertions. Project-test completion remains self_reported because target code controls the test process; tested is reserved for a future target-independent completion witness. |
/ship |
Release Engineer | Sync main, run tests, explore changed behavior, audit coverage and docs, then verify, push and open a PR. |
/land-and-deploy |
Release Engineer | Merge the PR, wait for CI and deploy, verify production health. One command from "approved" to "verified in production." |
/canary |
SRE | Post-deploy monitoring loop. Watches for console errors, performance regressions, and page failures. |
/benchmark |
Performance Engineer | Baseline page load times, Core Web Vitals, and resource sizes. Compare before/after on every PR. |
/document-release |
Technical Writer | Audit changed behavior against project docs on every ship, before final verification and publication. Also runs standalone. Shows updated, reviewed/current or blocked docs and any remaining gaps. |
/document-generate |
Documentation Author | Generate missing docs from scratch using the Diataxis framework. Researches the codebase first, then writes reference / how-to / tutorial / explanation docs that actually match the code. Invokable standalone or chained from /document-release when the coverage map finds gaps. Learn more: tutorial • how-to • why Diataxis. |
/retro |
Eng Manager | Team-aware weekly retro. Per-person breakdowns, shipping streaks, test health trends, growth opportunities. /retro global runs across all your projects and AI tools (Claude Code, Codex, Gemini). |
/browse |
QA Engineer | Give the agent eyes. Drives your Aside browser first — your real sessions, real clicks, real screenshots — through deterministic aside repl scripts. No Aside? It falls back to gstack's own Chromium: real clicks, ~100ms per command, and /open-gstack-browser shows it headed with sidebar, anti-bot stealth, and auto model routing. Every other browser skill stands on it. |
/scrape |
Data Extractor | Pull structured data off a web page — tables, lists, prices — in your Aside browser with the page's real logged-in state. On the fallback browser, /skillify turns the flow into a permanent browser-skill that runs in ~200ms next time. |
/setup-browser-cookies |
Session Manager | Copy selected cookies from Chrome, Chromium, Brave, Edge, Windows-only Opera and Opera GX, or macOS-only Comet, Arc, and Dia into gstack's bundled browser. Choose your profile and domains; copying and sign-in verification are separate. Only needed on the fallback path — Aside already has your sessions. |
/autoplan |
Review Pipeline | One command, fully reviewed plan. Runs CEO → design → DX → eng review automatically (eng always last, so the shipping gate reviews the final amended plan) with encoded decision principles. Surfaces only taste decisions for your approval. |
/spec |
Spec Author | Turn vague intent into a precise, executable spec in five phases (why, scope, technical with mandatory code-reading, draft, file). Outside-review quality gate before filing (Claude Code on Codex; Codex on other harnesses; blocks below 7/10), fail-closed secret redaction, dedupe against existing issues, archive to $GSTACK_STATE_ROOT/projects/$SLUG/specs/ for team-corpus recall. --execute spawns claude -p in a fresh worktree; /ship auto-closes the source issue on merge. Plan-mode aware. |
/learn |
Memory | Manage what gstack learned across sessions. Review, search, prune, and export project-specific patterns, pitfalls, and preferences. Learnings compound across sessions so gstack gets smarter on your codebase over time. |
/make-pdf |
Publisher | Markdown in, publication-quality document out. Mermaid and excalidraw fences render as vector diagrams, fully offline. Images scale to the page and never truncate; wide diagrams get their own landscape page. --to html emits one self-contained file, --to docx a Word doc. |
/diagram |
Diagram Maker | English in, editable diagram out. Emits a triplet: mermaid source, .excalidraw you can open and edit on excalidraw.com (hand-drawn style), and rendered SVG/PNG. Zero network. Embed the source in markdown and /make-pdf renders it. |
QA without a webpage
Use the same commands for browser and non-browser software. Start in a repository with its documented native command and an isolated local fixture; name the target and the behavior you want checked. For example:
/qa-only Test this repo's CLI using its documented local fixture. Check valid and invalid input, exit codes, stdout/stderr, and cancellation. Report only; do not change code or tests. For each finding, include the exact command, expected and actual results, and which checks remain untested. Keep requests inside the fixture; ask before contacting an external service.
/qa Test this repo's local webhook and worker fixture. Explore duplicate deliveries and recovery after a partial failure. Keep all effects inside the fixture; preserve reproduced bugs in native regression tests before repairing them.
QA first tells you which surface, tools and write permissions it will use. A CLI or API does not need a browser. Browser targets keep real browser testing; developer experience audits load only when onboarding, installation or ergonomics are in scope. If the native tools or safe fixture are unavailable, the report names the blocker and untested contracts instead of inventing a pass or installing another framework.
Exploration means learning from each result and choosing the next useful challenge,
not running random commands. Before the next discovery probe, QA saves a short
exploration-NNN.json evidence note with the previous result, the assumption being
tested and the next command. The final report links these notes; they do not require
an extra chat message between probes. A discovered bug must be reproducible, and its new test
must fail for the bug before the repair and pass afterward. Unit tests protect logic;
integration and end-to-end tests protect real boundaries that mocks would hide.
/qa-only proposes those tests without writing them.
Normal /review and /ship run a bounded version on changed behavior and nearby
risks automatically, including small diffs without a plan or web server. Existing
fix/test approval rules still apply. Missing dependencies, denied actions and time
limits remain visible coverage gaps; a short smoke pass never means exhaustive QA.
Production access and destructive or external effects require specific permission.
Bounded exploration uses an executable deadline guard, not an estimated clock: it refuses late probes and stops owned foreground work at the limit. Unfinished checks stay visible in the report. Required plan checks remain outside the review/ship smoke budget. See QA deadlines for command, platform and cleanup limits.
Every ship also runs the existing documentation audit, including repeat ships and existing PR updates. Clear factual corrections join the final checked change; risky rewrites need approval. A failed audit stops for recovery or explicit acceptance of the named risk rather than silently dropping its result. Ship owns versioning, Git and PR publication; the docs helper does not commit or push independently.
Which review should I use?
| Building for... | Plan stage (before code) | Live audit (after shipping) |
|---|---|---|
| End users (UI, web app, mobile) | /plan-design-review |
/design-review |
| Developers (API, CLI, SDK, docs) | /plan-devex-review |
/devex-review |
| Architecture (data flow, perf, tests) | /plan-eng-review |
/review |
| All of the above | /autoplan (runs CEO → design → DX → eng, auto-detects which apply; eng always last) |
— |
Power tools
| Skill | What it does |
|---|---|
/codex |
Second Opinion — independent code review from OpenAI Codex CLI. Review, challenge, and consult modes. Available on every harness except Codex. |
/claude-code |
Second Opinion — independent code review from Claude Code. Review, challenge, and consult modes, with session continuity for consultation. Available on every harness except Claude Code. |
/careful |
Safety Guardrails — warns before destructive commands (rm -rf, DROP TABLE, force-push). Say "be careful" to activate. Override any MEDIUM warning; root/home recursive deletes and default-branch force-pushes are hard-denied. |
/freeze |
Edit Lock — restrict file edits to one directory. Prevents accidental changes outside scope while debugging. |
/guard |
Full Safety — /careful + /freeze in one command. Maximum safety for prod work. |
/unfreeze |
Unlock — remove the /freeze boundary. |
/open-gstack-browser |
GStack Browser — launch gstack's own browser headed, with sidebar, anti-bot stealth, auto model routing (Sonnet for actions, Opus for analysis), one-click cookie import, and Claude Code integration. Clean up pages, take smart screenshots, edit CSS, and pass info back to your terminal. The visible face of the fallback engine; with Aside open you watch the agent's tabs there instead. |
/setup-deploy |
Deploy Configurator — one-time setup for /land-and-deploy. Detects your platform, production URL, and deploy commands. |
/setup-gbrain |
GBrain Onboarding — from zero to running gbrain in under 5 minutes. PGLite local, Supabase existing URL, or auto-provision a new Supabase project via Management API. MCP registration for Claude Code + per-repo trust triad (read-write/read-only/deny). Full guide. |
/sync-gbrain |
Keep Brain Current — re-index this repo's code into gbrain via gbrain sources add + gbrain sync --strategy code, refresh the ## GBrain Search Guidance block in CLAUDE.md, and auto-remove guidance when the capability check fails. --incremental (default), --full, --dry-run. Idempotent; safe to re-run. |
/gstack-upgrade |
Self-Updater — upgrade gstack to latest. Detects global vs vendored install, syncs both, shows what changed. |
/ios-qa |
iOS Live-Device QA (v1.43.0.0+) — drive a real iPhone over USB CoreDevice via an embedded StateServer in the app. Read Swift source, codegen typed @Observable accessors, run the agent loop. Optional --tailnet flag exposes the device to OpenClaw or any HTTP-capable agent on your Tailscale tailnet so remote agents can run iOS QA without ever touching the hardware. Capability-tier allowlist (observe/interact/mutate/restore), per-device session lock, audit log. |
/ios-fix, /ios-design-review, /ios-clean, /ios-sync |
iOS bug-fix loop, designer's-eye HIG audit, debug-bridge cleanup, and accessor resync. See docs/skills.md. End-to-end walkthrough: docs/howto-ios-testing-with-gstack.md. |
Standalone binaries
Beyond the slash-command skills, gstack ships standalone CLIs for workflows that don't belong inside a session:
| Command | What it does |
|---|---|
gstack-model-benchmark |
Cross-model benchmark — run the same prompt through Claude, GPT (via Codex CLI), and Gemini; compare latency, tokens, cost, and (optionally) LLM-judge quality score. Auth detected per provider, unavailable providers skip cleanly. Output as table, JSON, or markdown. --dry-run validates flags + auth without spending API calls. |
gstack-taste-update |
Design taste learning — writes approvals and rejections from /design-shotgun into a persistent per-project taste profile. Decays 5%/week. Feeds back into future variant generation so the system learns what you actually pick. |
gstack-egress |
Egress receipt auditor — every gstack-initiated off-machine send writes a tamper-evident, hash-chained receipt to ~/.gstack/security/egress.jsonl before the send. list shows what gstack attempted to send and to which host, grants shows the standing consent settings plus the exact command that revokes each, verify recomputes the hash chain and exits 3 on tamper (catches edits, reordering, and mid-chain deletion; truncating or deleting the ledger itself is out of scope — it's a forensic log, not tamper-proof storage). |
gstack-context-bill |
Token bill-of-materials — read-only, offline audit of what an installed skills tree costs in tokens: always-on frontmatter every session pays vs per-invocation SKILL.md + forced references. --diff compares two trees, --budget enforces a ceiling, --exact opts into Anthropic count_tokens (sends file text off-machine; writes an egress receipt first, degrades to the offline estimate if the receipt can't be written). |
gstack-code-intelligence |
Code-intelligence provider picker — wraps GBrain, Sourcebot, and Graphify behind one interface: options/status to see what's available, select to pick one, index/search to use it, suggest to check whether the one-time indexing offer should fire here. The offer triggers on large repos (1,000+ tracked files; a decline is persisted). Non-local providers refuse to index or search until you record per-repo consent (consent <repo> yes|no — the query text is repo-derived content), the per-repo trust policy's deny and read-only tiers veto write-class operations regardless of consent, and every off-machine send writes an egress receipt. Fully optional — with nothing selected, gstack falls back to grep. |
gstack-verify-gate |
Verification stop hook (opt-in) — blocks a Claude Code turn from ending until the project's declared verify command passes (after 3 blocked re-entries it yields with a loud still-RED warning instead of looping forever). Declare it on one line in CLAUDE.md: <!-- gstack:verify: bun test -->. Hooks bypass the permission system, so a declared command never runs until you trust it once per repo (gstack-verify-gate --trust); editing the command invalidates trust until re-granted, and every grant is audit-logged. ./setup never registers it for you — opt in with gstack-settings-hook add-event --event Stop --command ~/.claude/skills/gstack/bin/gstack-verify-gate --source verify-gate, remove with gstack-settings-hook remove-source --source verify-gate. |
gstack-memorable |
Memorable recall bridge (opt-in, third party, Claude Code only) — connects Claude Code to the external Memorable CLI through gstack instead of the vendor's own installer, so the hook gets gstack's guarantees: an explicit consent key (memorable_recall, off by default, listed by gstack-egress grants), a fail-closed egress receipt for every prompt handed over (gstack-egress list --sink memorable-recall), a HIGH-tier secret pre-scan, a trust envelope and 8 KiB cap on whatever comes back, an allowlisted environment and process-group containment for the vendor process, and clean removal. enable registers the hook at the stable install with a 5 s timeout and never runs the vendor's own consent command; disable revokes the gate first and removes the entry by identity even after Claude Code strips the tag; status is read-only. gstack never installs Memorable, and what its binary sends is the vendor's claim, not gstack's. Not available on Windows yet. Full guide. |
gstack-wtree |
Working-tree fingerprint — prints a content hash of what's actually on disk (temp index seeded from the stat cache, ~40x cheaper than a full re-hash; untracked source counts, gitignored scratch doesn't). Identical content fingerprints identically through commits, rebases, amends, and squashes — it's what binds reviews and test evidence to content instead of commit SHAs. |
gstack-review-log |
Review-pass receipts — --start <skill> captures the working-tree fingerprint before a diff review; '<JSON>' --finish <token> consumes that single-use, repository/branch/skill-scoped receipt. Binding requires matching start/end content and reviewer-reported completed:true and converged:true; it is not independent proof that a model read the source. --check-shared-libs <token> reads a current finding as JSON on stdin and checks prior Skip decisions against the actual branch, capture and eligible raw source blobs. It returns reusable:false when proof is missing or unsafe, including older records without logger-versioned coverage. Final review logging computes shared-code fingerprints and coverage rather than trusting supplied proof. |
gstack-review-read |
Review freshness — emits review records with computed review_freshness.status and reason: CURRENT, STALE, or UNVERIFIED for diff reviews. /ship and /land-and-deploy use the same grade; a matching commit alone never certifies a diff review. Dashboard rules. |
gstack-evidence |
Verification-evidence ledger — run --label <lane> -- <cmd> transparently wraps any test command (the child's exit code always passes through) and records what ran against which working-tree fingerprint; check grades each label FRESH/STALE/MISSING with --expect-cmd, --max-age, and --allow-paths binding. /ship and /land-and-deploy cite fresh evidence instead of re-running suites. Per-run logs are 0600, capped at 2MB, pruned after 30 days; the ledger and logs stay machine-local by design. |
gstack-issue-guard |
Tracker-text trust envelope — fetches GitHub issue/PR text (issue <n>, pr-body, pr-comments, or --stdin) and wraps it in a labeled envelope so agents treat it as data: injection-shaped lines get labeled even through fullwidth and invisible-character evasion, and forged envelope banners are defused. Every tracker-text ingress in gstack routes through it, enforced by a CI scanner. |
gstack-ios-qa-daemon |
iOS QA daemon — Mac-side broker between an agent and a connected iPhone over USB CoreDevice. Loopback by default; --tailnet opens a Tailscale-facing listener with identity-gated capability tiers. Single-instance via flock on ~/.gstack/ios-qa-daemon.pid. See docs/howto-ios-testing-with-gstack.md. |
gstack-ios-qa-mint |
iOS allowlist manager — owner-grant CLI for the tailnet allowlist. grant/revoke/list against ~/.gstack/ios-qa-allowlist.json (mode 0600). Remote agents never auto-allowlist; this is the explicit-intent path. |
gstack-ios-qa-regen |
iOS bridge regenerator — deterministically installs the canonical DebugBridge package, generates typed state accessors, and records the installed gstack version. Safe to rerun after source changes or upgrades. |
The private paid CSO evaluation producer is a packaging contract, not an ordinary bun run build artifact. On macOS or Linux, a release operator compiles cso-eval-producer with the documented hardened Bun flags in the same clean build session as bun run build:cso, then installs it beside gstack-cso-launcher, gstack-cso-core, gstack-cso-watchdog, and the hidden .gstack-cso-generation manifest as one root-owned, nonwritable five-artifact unit. The producer rejects root execution, writable/symlinked/incomplete installations, and unreviewed provider CLI versions; each receipt binds all five artifact hashes, and collection rejects receipts from different unit identities. See the clean producer procedure. Paid producer evaluation remains unavailable on Windows because the detached watchdog has no Windows build.
Each producer gets a curated one-cell source copy with directories sealed to 0555 and files to 0444, plus pre/post content, Git, and mode checks. Claude receives that exact copy as a restricted read-only add-directory so its constrained launcher command can reach it. Gemini receives no source working directory or include-directory. Codex technically receives read-only filesystem access to the exact curated source root because the trusted helper inherits the Codex permission profile; its private provider work directory and exact cso-home artifact directory are the only write roots, every other root path remains denied, and the producer prompt requires source access through the helper. This is evaluation containment for an immutable public fixture, not a claim that Codex cannot directly read that fixture.
Copy each completed cell's receipt together with state/cso-home/security/cso/ to the trusted adjudication host. Receipt entries are sorted paths relative to that directory and bind every retained file's size and SHA-256 plus an aggregate inventory hash. Provider homes, settings, sessions, and credentials live under separate disposable directories and are removed after the cell; they are never part of the retained artifact tree. The adjudicator must re-hash the transported tree against the receipt before trusting reports or repair bundles.
Paid producer qualification uses this explicit host matrix:
| Producer host | Daily/static cells | Comprehensive target execution |
|---|---|---|
| Codex CLI 0.153.4 | Supported under the custom permission profile | Fails closed because Docker/socket access is not granted to the model command sandbox; report the setup gap as partial |
| Claude Code 2.1.263 | Supported under restricted safe mode | Fails closed when the restricted launcher child cannot reach Docker; report the setup gap as partial |
| Gemini CLI 0.59.0 | Supported with isolated home/settings | Private release qualification host: the exact run_shell_command(<launcher>) policy can run the trusted helper without exposing a general shell |
Every setup-blocked comprehensive cell remains a miss in release-gate denominators. The evaluator does not silently count a host or workflow as supported when its containment policy prevents required setup.
./setup also registers one default-on Stop hook in ~/.claude/settings.json:
gstack-timeline-stop (closes dangling session-timeline entries when a session
is interrupted; fail-open — 2s internal budget, always exits 0, can never block
a session). Opt out persistently with ./setup --no-timeline-stop-hook — the
choice lands in the timeline_stop_hook config key, survives upgrades, and an
explicit "no" removes a live registration. GSTACK_TIMELINE_STOP_HOOK=no and
gstack-config set timeline_stop_hook no work too (flag > env > config).
./setup --no-team skips it for that run, gstack-settings-hook remove-source --source gstack-timeline-stop removes it by hand, and gstack-uninstall
removes it too.
Hook registration is canonical-only: every hook command points at the stable
~/.claude/skills/gstack install, never the tree setup ran from, so deleting
a worktree or Conductor workspace can't leave dead hooks erroring in your
sessions. Every ./setup run also heals first: gstack-settings-hook prune-stale --repoint removes dead gstack hook entries, re-points stale ones
at the stable install, and collapses duplicates, printing one line (and
writing a backup beside the file) only when it changed something.
Domain skills + raw CDP escape hatch
Two browser primitives in gstack's own engine (the fallback path when Aside isn't there) compound the agent over time:
$B domain-skill save— agent saves a per-site note (e.g., "LinkedIn's Apply button lives in an iframe") that fires automatically next time it visits that hostname. Quarantined → active after 3 successful uses → optional cross-project promotion via$B domain-skill promote-to-global. Storage lives alongside/learn's per-project learnings file. Full reference: docs/domain-skills.md.$B cdp <Domain.method>— raw Chrome DevTools Protocol escape hatch for the rare case curated commands miss. Deny-default: methods must be explicitly added tobrowse/src/cdp-allowlist.tswith a one-line justification. Two-tier mutex serializes browser-scoped CDP calls against per-tab work. Output for data-exfil methods is wrapped in the UNTRUSTED envelope.
Want raw CDP with no rails, no allowlist, no daemon — just thin transport from agent to Chrome? browser-use/browser-harness-js is a different philosophy (agent-authored helpers vs gstack's curated commands) and a good fit if you don't want gstack's security stack. The two can coexist: gstack's
$B cdpand harness can both attach to the same Chrome via Playwright'snewCDPSession.
Deep dives with examples and philosophy for every skill →
Karpathy's four failure modes? Already covered.
Andrej Karpathy's AI coding rules (17K stars) nail four failure modes: wrong assumptions, overcomplexity, orthogonal edits, imperative over declarative. gstack's workflow skills enforce all four. /office-hours forces assumptions into the open before code is written. The Confusion Protocol stops Claude from guessing on architectural decisions. /review catches unnecessary complexity and drive-by edits. /ship transforms tasks into verifiable goals with test-first execution. If you already use Karpathy-style CLAUDE.md rules, gstack is the workflow enforcement layer that makes them stick across entire sprints, not just single prompts.
Parallel sprints
gstack works well with one sprint. It gets interesting with ten running at once.
Design is at the heart. /design-consultation builds your design system from scratch, researches what's out there, proposes creative risks, and writes DESIGN.md. But the real magic is the shotgun-to-HTML pipeline.
/design-shotgun is how you explore. You describe what you want. It generates 4-6 AI mockup variants using GPT Image. Then it opens a comparison board in your browser with all variants side by side. You pick favorites, leave feedback ("more whitespace", "bolder headline", "lose the gradient"), and it generates a new round. Repeat until you love something. Taste memory kicks in after a few rounds so it starts biasing toward what you actually like. No more describing your vision in words and hoping the AI gets it. You see options, pick the good ones, and iterate visually.
Works with impeccable. If you use impeccable too, gstack does not fight it. gstack runs impeccable's deterministic engine as a pre-pass in /design-review, /review, /ship, and /design-html when you have it installed (gstack never runs impeccable's installer or launcher; the first time a design skill finds no engine it asks once whether to download the engine binary, checksum-pinned and logged, into ~/.impeccable, and remembers your answer), speaks the same 61 rule ids in its own voice, reads PRODUCT.md, writes DESIGN.md in the open DESIGN.md format both tools read, and hands deferred findings to /impeccable <command>. Say no and nothing changes: no nag, no missing step. gstack-config set design_detector off turns the pre-pass off. Attribution for the material gstack derived from impeccable and the DESIGN.md spec is in NOTICE.md.
/design-html makes it real. Take that approved mockup (from /design-shotgun, a CEO plan, a design review, or just a description) and turn it into production-quality HTML/CSS. Not the kind of AI HTML that looks fine at one viewport width and breaks everywhere else. This uses Pretext for computed text layout: text actually reflows on resize, heights adjust to content, layouts are dynamic. 30KB overhead, zero dependencies. It detects your framework (React, Svelte, Vue) and outputs the right format. Smart API routing picks different Pretext patterns depending on whether it's a landing page, dashboard, form, or card layout. The output is something you'd actually ship, not a demo.
/qa was a massive unlock. It let me go from 6 to 12 parallel workers. Claude Code saying "I SEE THE ISSUE" and then actually fixing it, generating a regression test, and verifying the fix — that changed how I work. The agent has eyes now.
Smart review routing. Just like at a well-run startup: CEO doesn't have to look at infra bug fixes, design review isn't needed for backend changes. gstack tracks what reviews are run, figures out what's appropriate, and just does the smart thing. The Review Readiness Dashboard tells you where you stand before you ship.
Test everything. /ship bootstraps test frameworks from scratch if your project doesn't have one. Every /ship run produces a coverage audit. /qa creates native regressions when infrastructure is available and explicitly reports missing test coverage; CSS-only fixes may use browser evidence instead. 100% test coverage is the goal — tests make vibe coding safe instead of yolo coding.
/document-release is the engineer you never had. It audits relevant authored docs against the release diff and corrects factual drift before final verification. Risky changes return for approval. /ship invokes it on every run and owns TODOS, release metadata, generation and publication; the child reports updated, current or blocked documentation.
Aside is the browser gstack drives first. For browser surfaces, on a Mac with the Aside AI browser open, /qa, /qa-only, /design-review, /canary, /benchmark, /scrape, and /browse all run there — your real browser, with your real logged-in sessions, in tabs the agent opens for itself and closes when it's done. No cookie import, no "open the browser" step, no CAPTCHA handoff dance: hit a sign-in wall, sign in inside Aside, say "done", and the agent continues. Anything a page returns is treated as untrusted content — the agent takes syntax from it, never instructions. /make-pdf, /diagram, and design previews print and screenshot through Aside too (served from your machine on loopback, one render per script), and the planning skills do their web research through Aside's own agent before reaching for a search tool.
When Aside isn't there, gstack's own browser takes over — automatically. Linux, Windows, or a Mac with Aside closed: the same skills use the bundled headless Chromium that ./setup builds, produce the same evidence, and light up the features below that only make sense when the browser is gstack's rather than yours.
Real browser mode. /open-gstack-browser launches GStack Browser, an AI-controlled Chromium with anti-bot stealth, custom branding, and the sidebar extension baked in. Sites like Google and NYTimes work without captchas. The menu bar says "GStack Browser" instead of "Chrome for Testing." Your regular Chrome stays untouched. All existing browse commands work unchanged. $B disconnect returns to headless. The browser stays alive as long as the window is open... no idle timeout killing it while you're working.
Sidebar agent — your AI browser assistant. Type natural language in the Chrome side panel and a child Claude instance executes it. "Navigate to the settings page and screenshot it." "Fill out this form with test data." "Go through every item in this list and extract the prices." The sidebar auto-routes to the right model: Sonnet for fast actions (click, navigate, screenshot) and Opus for reading and analysis. Each task gets up to 5 minutes. The sidebar agent runs in an isolated session, so it won't interfere with your main Claude Code window. One-click cookie import right from the sidebar footer.
Personal automation. The sidebar agent isn't just for dev workflows. Example: "Browse my kid's school parent portal and add all the other parents' names, phone numbers, and photos to my Google Contacts." Two ways to get authenticated: (1) log in once in the headed browser, your session persists, or (2) click the "cookies" button in the sidebar footer to import cookies from your real Chrome. Once authenticated, Claude navigates the directory, extracts the data, and creates the contacts.
Prompt injection defense. Hostile web pages try to hijack your sidebar agent. gstack ships a layered defense: content filters (datamarking, hidden-element stripping, ARIA scrubbing, URL blocklist) on every page read, plus a 22MB ML classifier running locally in a sidecar subprocess that scans page-derived content before the agent sees it, with a verdict combiner that requires classifier agreement before blocking (prevents single-model false positives on Stack Overflow-style instruction pages). Everything runs on your machine, no network calls. Emergency kill switch: GSTACK_SECURITY_OFF=1. See ARCHITECTURE.md for the full stack.
Browser handoff when the AI gets stuck. Hit a CAPTCHA, auth wall, or MFA prompt? $B handoff opens a visible Chrome at the exact same page with all your cookies and tabs intact. Solve the problem, tell Claude you're done, $B resume picks up right where it left off. The agent even suggests it automatically after 3 consecutive failures.
/pair-agent is cross-agent coordination. You're in Claude Code. You also have OpenClaw running. Or Hermes. Or Codex. You want them both looking at the same website. Type /pair-agent, pick your agent, and a GStack Browser window opens so you can watch. The skill prints a block of instructions. Paste that block into the other agent's chat. It exchanges a one-time setup key for a session token, creates its own tab, and starts browsing. You see both agents working in the same browser, each in their own tab, neither able to interfere with the other. If ngrok is installed, the tunnel starts automatically so the other agent can be on a completely different machine. Same-machine agents get a zero-friction shortcut that writes credentials directly. This is the first time AI agents from different vendors can coordinate through a shared browser with real security: scoped tokens, tab isolation, rate limiting, domain restrictions, and activity attribution.
Multi-AI second opinion. In Codex, gstack sends outside reviews to Claude Code through /claude-code. In Claude Code, /codex sends them to OpenAI Codex. Other harnesses expose both skills and use Codex where automatic outside reviews are supported. Each skill supports code review, adversarial challenge, and consultation with session continuity. Routing follows the harness, so changing your configured model does not change the outside reviewer. Reports identify the provider that actually completed each review; unavailable outside coverage remains visible.
Safety guardrails on demand. Say "be careful" and /careful warns before any destructive command — rm -rf, DROP TABLE, force-push, git reset --hard. /freeze locks edits to one directory while debugging so Claude can't accidentally "fix" unrelated code. /guard activates both. /investigate auto-freezes to the module being investigated.
Proactive skill suggestions. gstack notices what stage you're in — brainstorming, reviewing, debugging, testing — and suggests the right skill. Don't like it? Say "stop suggesting" and it remembers across sessions.
10-15 parallel sprints
gstack is powerful with one sprint. It is transformative with ten running at once.
Conductor runs multiple Claude Code sessions in parallel — each in its own isolated workspace. One session running /office-hours on a new idea, another doing /review on a PR, a third implementing a feature, a fourth running /qa on staging, and six more on other branches. All at the same time. I regularly run 10-15 parallel sprints — that's the practical max right now.
The sprint structure is what makes parallelism work. Without a process, ten agents is ten sources of chaos. With a process — think, plan, build, review, test, ship — each agent knows exactly what to do and when to stop. You manage them the way a CEO manages a team: check in on the decisions that matter, let the rest run.
Voice input (AquaVoice, Whisper, etc.)
gstack skills have voice-friendly trigger phrases. Say what you want naturally — "run a security check", "test the website", "do an engineering review" — and the right skill activates. You don't need to remember slash command names or acronyms.
Uninstall
Option 1: Run the uninstall script
If gstack is installed on your machine:
~/.claude/skills/gstack/bin/gstack-uninstall
This handles skills, symlinks, global state (~/.gstack/), project-local state, browse daemons, and temp files. Use --keep-state to preserve config and analytics. Use --force to skip confirmation.
Option 2: Manual removal (no local repo)
If you don't have the repo cloned (e.g. you installed via a Claude Code paste and later deleted the clone):
# 1. Stop browse daemons
pkill -f "gstack.*browse" 2>/dev/null || true
# 2. Remove per-skill directories whose SKILL.md points into gstack/
# (rm -rf, not rmdir — installed dirs also contain runtime-asset links)
find ~/.claude/skills -mindepth 1 -maxdepth 1 -type d ! -name gstack 2>/dev/null |
while IFS= read -r dir; do
link="$dir/SKILL.md"
[ -L "$link" ] || continue
target=$(readlink "$link" 2>/dev/null) || continue
case "$target" in
gstack/*|*/gstack/*)
rm -rf "$dir"
;;
esac
done
# Directories gstack created carry a .gstack-owned marker (the only signal on
# Windows, where installs are file copies with no symlink to read)
for marker in ~/.claude/skills/*/.gstack-owned; do
[ -f "$marker" ] && rm -rf "$(dirname "$marker")"
done
# Alias skills install as copies (no symlink to detect) — remove by name
rm -rf ~/.claude/skills/_gstack-command ~/.claude/skills/connect-chrome 2>/dev/null
# 3. Remove gstack
rm -rf ~/.claude/skills/gstack
# 4. Remove global state
rm -rf ~/.gstack
# 5. Remove integrations (skip any you never installed)
rm -rf "${CODEX_HOME:-$HOME/.codex}/skills/gstack"* 2>/dev/null
rm -rf ~/.factory/skills/gstack* 2>/dev/null
rm -rf ~/.kiro/skills/gstack* 2>/dev/null
rm -rf ~/.openclaw/skills/gstack* 2>/dev/null
rm -rf ~/.cursor/skills/gstack* 2>/dev/null
rm -rf ~/.config/opencode/skills/gstack* 2>/dev/null
# 6. Remove temp files
rm -f /tmp/gstack-* 2>/dev/null
# 7. Per-project cleanup (run from each project root)
rm -rf .gstack .gstack-worktrees .claude/skills/gstack 2>/dev/null
rm -rf .agents/skills/gstack* .factory/skills/gstack* 2>/dev/null
Manual removal leaves gstack's hook entries behind in ~/.claude/settings.json
(the uninstall script removes all of them for you, including entries whose
_gstack_source tag was stripped). Edit that file and delete every hook whose
command path points into .claude/skills/gstack/: the SessionStart auto-update
hook, the AskUserQuestion PreToolUse/PostToolUse hooks, and the Stop hooks
(session timeline, plus verify-gate if you opted in). Left in place, they error
on every matching event once the install directory is gone.
Clean up CLAUDE.md
The uninstall script does not edit CLAUDE.md. In each project where gstack was added, remove the ## gstack and ## Skill routing sections.
Playwright
~/Library/Caches/ms-playwright/ (macOS) is left in place because other tools may share it. Remove it if nothing else needs it.
Aside
gstack never installed Aside, so it never uninstalls it. Keep it or remove it like any other app.
Free, MIT licensed, open source. No premium tier, no waitlist.
I open sourced how I build software. You can fork it and make it your own.
We're hiring. Want to ship real products at AI-coding speed and help harden gstack? Come work at YC — ycombinator.com/software Extremely competitive salary and equity. San Francisco, Dogpatch District.
GBrain — persistent knowledge for your coding agent
GBrain is a persistent knowledge base for AI agents — think of it as the memory your agent actually keeps between sessions. GStack gives you a one-command path from zero to "it's running, my agent can call it."
/setup-gbrain
Four paths, pick one:
- Supabase, existing URL — your cloud agent already provisioned a brain; paste the Session Pooler URL, now this laptop uses the same data.
- Supabase, auto-provision — paste a Supabase Personal Access Token; the skill creates a new project, polls to healthy, fetches the pooler URL, hands it to
gbrain init. ~90 seconds end-to-end. - PGLite local — zero accounts, zero network, ~30 seconds. Isolated brain on this Mac only. Great for try-first; migrate to Supabase later with
/setup-gbrain --switch. - Remote gbrain MCP — your brain runs on another machine (Tailscale, ngrok, internal LAN) or a teammate's server; paste an MCP URL and bearer token. Optionally pair with a local PGLite for symbol-aware code search in split-engine mode. Best for cross-machine memory without standing up a local DB.
After init, the skill offers to register gbrain as an MCP server for Claude Code (claude mcp add gbrain -- gbrain serve) so gbrain search, gbrain put, etc. show up as first-class typed tools — not bash shell-outs.
Keeping the brain current. Run /sync-gbrain from any repo to re-index its code into gbrain (incremental by default, --full for a full reindex, --dry-run to preview). The skill registers the cwd as a federated source via gbrain sources add, runs gbrain sync --strategy code, and writes a ## GBrain Search Guidance block to your project's CLAUDE.md so the agent prefers gbrain search/code-def/code-refs over Grep. The block is removed automatically if the capability check fails — no stale guidance pointing at tools that aren't installed.
Per-remote trust policy. Each repo on your machine gets one of three tiers:
read-write— agent can search the brain AND write new pages back from this reporead-only— agent can search but never writes (best for multi-client consultants: search the shared brain, don't contaminate it with Client A's work while in Client B's repo)deny— no gbrain interaction at all
The skill asks once per repo. The decision is sticky across worktrees and branches of the same remote.
GStack memory sync (different feature, same private-repo infra). Optionally pushes your gstack state (learnings, CEO plans, design docs, retros, developer profile) to a private git repo so your memory follows you across machines, with a one-time privacy prompt (everything allowlisted / artifacts only / off) and a defense-in-depth secret scanner that blocks AWS keys, tokens, PEM blocks, and JWTs before they leave your machine.
gstack-artifacts-init
Running gstack in Conductor? Conductor explicitly strips ANTHROPIC_API_KEY and OPENAI_API_KEY from every workspace's process env, so paid evals and gbrain embeddings won't work out of the box. Set GSTACK_ANTHROPIC_API_KEY and GSTACK_OPENAI_API_KEY in Conductor's workspace env config instead — gstack's TS entry points promote them to canonical names at runtime. Full details and the contributor checklist for adding the import to new entry points: Conductor + GSTACK_* env vars.
Full monty — every scenario, every flag, every bin helper, every troubleshooting step: USING_GBRAIN_WITH_GSTACK.md
Other references: docs/gbrain-sync.md (sync-specific guide) • docs/gbrain-sync-errors.md (error index)
Docs
| Doc | What it covers |
|---|---|
| Skill Deep Dives | Philosophy, examples, and workflow for every skill (includes Greptile integration) |
| Diagrams & Document Formats | Mermaid/excalidraw fences in PDFs, image sizing and safety defaults, --to html|docx, /diagram triplets |
| Builder Ethos | Builder philosophy: Boil the Ocean, Search Before Building, three layers of knowledge |
| Using GBrain with GStack | Every path, flag, bin helper, and troubleshooting step for /setup-gbrain |
| GBrain Sync | Cross-machine memory setup, privacy modes, troubleshooting |
| Architecture | Design decisions and system internals |
| Browser | How gstack drives Aside first (the contract, the cookbook, rendering, research), when the fallback engine kicks in, and the fallback's full $B command reference |
| Contributing | Dev setup, testing, contributor mode, and dev mode |
| Memorable recall bridge | Opt-in third-party workflow memory through gstack: two consents, what gstack hands over and can attest, removal, troubleshooting |
| Troubleshooting | Every not run / unavailable message, what it means, and the fix |
| Changelog | What's new in every version |
Privacy & Telemetry
gstack includes opt-in usage telemetry to help improve the project. Here's exactly what happens:
- Default is off. Nothing is sent anywhere unless you explicitly say yes.
- On first run, gstack asks if you want to share anonymous usage data. You can say no.
- What's sent (if you opt in): skill name, duration, success/fail, gstack version, OS. That's it.
- What's never sent: code, file paths, repo names, branch names, prompts, or any user-generated content.
- Change anytime:
gstack-config set telemetry offdisables everything instantly. - Every off-machine send is receipted. Any gstack-initiated network send — telemetry included — writes a hash-chained, tamper-evident receipt to
~/.gstack/security/egress.jsonlbefore the send; sensitive sinks refuse to send at all if the receipt can't be written. Audit withgstack-egress list, verify the chain withgstack-egress verify(exit 3 on tamper), see the standing consent settings withgstack-egress grants. The ledger records attempted sends so accidents are auditable — it's an audit trail, not a network firewall. - Optional third-party bridges are off by default and receipted too. The one that exists today, the Memorable recall bridge, hands your prompt to a locally installed vendor binary only after you run
gstack-memorable enable; every hand-off writes a receipt first, the consent shows up ingstack-egress grants, and what the vendor then sends is documented as the vendor's claim.
Data is stored in Supabase (open source Firebase alternative). The schema is in supabase/migrations/ — you can verify exactly what's collected. The Supabase publishable key in the repo is a public key (like a Firebase API key) — row-level security policies deny all direct access. Telemetry flows through validated edge functions that enforce schema checks, event type allowlists, and field length limits.
Local analytics are always available. Run gstack-analytics to see your personal usage dashboard from the local JSONL file — no remote data needed.
Troubleshooting
A message says not run, unavailable or names a fix? Look it up in
docs/troubleshooting.md: every gate message gstack
prints, what it means, what was kept, and the command that fixes it.
Skill not showing up? Run ./setup --status from your gstack checkout. It
prints every install (host, scope, version, skills directory, source checkout)
and, for a stale, missing or unregistered row, the exact command that fixes
it. The usual fix is to re-run setup from that row's source for that host, e.g.
cd ~/.claude/skills/gstack && ./setup (Claude) or cd ~/gstack && ./setup --host codex.
A project install lives in the project's .claude/skills/gstack or
.agents/skills/gstack; run its setup from inside the project.
/browse (or /qa, /design-review) says NEEDS_ASIDE or ASIDE_NOT_RUNNING? That's the probe telling you it's about to use the fallback browser. Want Aside? Open the app and sign in — aside --version should print a version and aside repl 'console.log("ok")' should print ok — then re-run. gstack never installs it for you. Want the fallback on purpose while Aside is open? GSTACK_SKIP_ASIDE=1 makes every skill, the renderer, and ./setup treat Aside as absent. When Aside is absent the probe prints NEEDS_ASIDE: <OS> and skills trust that line for the macOS-only download pitch; GSTACK_PLATFORM overrides the OS it names, for tests and unusual hosts (set it in your shell — gstack never reads it from a project .env).
/browse fails on the fallback browser? cd ~/.claude/skills/gstack && bun install && bun run build
/make-pdf or /diagram can't render? Same two paths: with Aside open they print through Aside (bun run ~/.claude/skills/gstack/bin/gstack-render.ts some.html --screenshot /tmp/out.png tests it directly, and its first line, ENGINE=aside or ENGINE=browse, names the browser that actually rendered); without it they use the bundled browser, so bun run build is the fix.
Stale install? Run /gstack-upgrade — or set auto_upgrade: true in ~/.gstack/config.yaml.
On Codex and the other non-Claude hosts, upgrade from a terminal: find the
checkout in the source column of ./setup --status, then
cd <source> && git pull && ./setup --host <host>, and start a new session.
Typing into a specific field with the fallback browser? browse type --selector '<css>' <text>
types into that element; bare browse type <text> types into whatever has focus.
State in the wrong place, or a setting that won't stick? ~/.claude/skills/gstack/bin/gstack-paths --explain shows which directory gstack uses for its state and why. See docs/state-root.md.
Want shorter commands? cd ~/.claude/skills/gstack && ./setup --no-prefix — switches from /gstack-qa to /qa. Your choice is remembered for future upgrades.
Don't use some skills? gstack-config set disabled_skills make-pdf,pair-agent stops registering them on every host, so their descriptions stop loading into each session. Claude Code updates right away; other hosts on their next ./setup --host <name> or /gstack-upgrade. Their files stay installed, so a skill that calls a disabled one still works (you get a warning). Typos are rejected with the closest skill name, gstack-upgrade can't be disabled, and gstack-config set disabled_skills "" re-enables everything.
Want namespaced commands? cd ~/.claude/skills/gstack && ./setup --prefix — switches from /qa to /gstack-qa. Useful if you run other skill packs alongside gstack.
Codex says "Skipped loading skill(s) due to invalid SKILL.md"? Your Codex skill descriptions are stale. ${CODEX_HOME:-~/.codex}/skills/gstack is a runtime directory, not the checkout: ./setup --status shows the Codex row's source checkout. Fix: cd <that source> && git pull && ./setup --host codex — for a repo-local install, run it from inside the project.
Windows users: gstack works on Windows 11 via Git Bash or WSL. Aside is macOS-only, so on Windows (and Linux) the browser skills, /make-pdf, and /diagram always use gstack's bundled browser. Node.js is required in addition to Bun — Bun has a known bug with Playwright's pipe transport on Windows (bun#4253). The browse server automatically falls back to Node.js. Make sure both bun and node are on your PATH. Native /cso additionally requires Windows PowerShell and Visual Studio 2022 Build Tools with the Desktop development with C++ workload; setup leaves that skill explicitly unavailable when they are absent.
On Windows without Developer Mode (MSYS2 / Git Bash), setup falls back to file copies instead of symlinks because ln -snf produces frozen copies that don't refresh on git pull. Re-run cd ~/.claude/skills/gstack && ./setup after every git pull so your skill files match the repo. setup prints a one-line note reminding you. Unix and WSL keep symlinks and don't need the re-run.
Chromium install failed or hung during ./setup? The bundled browser is
best-effort: setup records the reason, finishes registering every skill, and
prints which skills are affected (/qa, /qa-only, /design-review,
/browse, make-pdf, /diagram, /pair-agent). With Aside open, the browser
skills keep running in Aside and only the fallback engine is missing;
/pair-agent always needs the bundled browser. Fix the cause and re-run
./setup. Knobs:
GSTACK_PLAYWRIGHT_INSTALL_TIMEOUT=<seconds> raises the download bound
(default 600) on slow links; GSTACK_SKIP_PLAYWRIGHT=1 skips the Chromium
install entirely (CI, no-browser boxes); GSTACK_CHROMIUM_NO_SANDBOX=1 is the
fix when Chromium installs but cannot launch because the host blocks
unprivileged user namespaces (Ubuntu 24.04+ AppArmor default, #2157).
Setup ended with "Not registered (a skill you own already uses the name; left untouched)"?
gstack only deletes or links over a skill entry it can prove it created: a
symlink into gstack, a directory carrying the .gstack-owned marker ./setup
writes into every directory it creates, or a SKILL.md that is byte-identical to
gstack's or carries the generated <!-- AUTO-GENERATED from ... --> banner. A
qa/ or ship/ you wrote yourself is left untouched by ./setup,
gstack-relink, and both prefix-mode flips, and the linker names it in the
final summary. Rename or move yours, or switch modes (./setup --prefix /
--no-prefix) so the names stop colliding. If you started your own skill from
a generated gstack SKILL.md and then edited it, that file is moved to
~/.gstack/backups/skills/<timestamp>/<skill>/SKILL.md before gstack's is
linked in, never deleted.
Claude says it can't see the skills? Make sure your project's CLAUDE.md has a gstack section. Add this:
## gstack
Use /browse from gstack for all web browsing. Never use mcp__claude-in-chrome__* tools.
Available skills: /office-hours, /plan-ceo-review, /plan-eng-review, /plan-design-review,
/design-consultation, /design-shotgun, /design-html, /review, /deslop-shared-libs, /test-audit, /ship, /land-and-deploy,
/canary, /benchmark, /browse, /open-gstack-browser, /qa, /qa-only, /design-review, /scrape,
/setup-browser-cookies, /setup-deploy, /setup-gbrain, /sync-gbrain, /retro, /investigate,
/document-release, /document-generate, /codex, /cso, /autoplan, /pair-agent, /careful, /freeze,
/guard, /unfreeze, /gstack-upgrade, /learn.
License
MIT. Free forever. Go build something.

