mirror of
https://github.com/garrytan/gstack.git
synced 2026-11-09 10:18:32 +01:00
bd3f01281f7c921634e45ba030d75e6f2fa673d4
79
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
01572dec6d |
docs: crew lanes keep context cheap (bounded warm waits, lane start card, names-only AGENTS.md index) (#4060)
* docs: lane context (warm waits, batched reads, start card, tail check) and a names-only AGENTS.md index Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes (bounded warm waits, real spend stop, lane-card fallback and exemptions) Review-Finding: p1/targeted#1 reader=targeted Review-Finding: p1/adversarial-native#1 reader=adversarial-native Review-Finding: p1/red-team#3 reader=red-team Review-Finding: p1/red-team#4 reader=red-team Review-Finding: p1/red-team#5 reader=red-team Review-Finding: p1/red-team#6 reader=red-team Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
4a2e208e3d |
docs: on Capy, comment and request reviews only through tools.pr.comment / tools.pr.edit, never gh (GST-1417 follow-up) (#4027)
* docs: on Capy, comment, tag and request reviews only through tools.pr.comment / tools.pr.edit, never gh; unattended /modernize posts nothing (GST-1417 follow-up) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * changelog: own fragment for the GST-1417 follow-up; landed fragments are never edited Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
a102f5849f |
docs: agents comment on GitHub only under a bot identity; email, chat and DMs to people stay banned (GST-1417) (#4022)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
7c918efcda |
docs: agents close or label with no comment; notes to people are drafts for the maintainer (GST-1376) (#4010)
* docs: agents close or label with no comment; notes to people are drafts for the maintainer (GST-1376) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(modernize): pin the no-comment rule (GST-1376) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(modernize): Step 3 asks before any push or close, never a closing comment (GST-1376) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
56a800da98 |
feat: /runaway-stopper — detect, stop and prevent runaway threads and subagents (GST-1279) (#3975)
* feat(runaway-stopper): detect, stop and prevent runaway threads and subagents (GST-1279) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(runaway-stopper): autoplan review fixes: input validation, exact /ship task-row meter at 100M, rotation hand-off of subagents and PR watches, bounded fetch program Skill-Size: 0→6747 bytes (SKILL.md.tmpl) Evidence: plan docs/evals/runaway-stopper-prereg.md measure_by 2026-11-24 Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(ship-budget): describe the task-row reading without a literal thread_id this Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(runaway-stopper): ship review pass 1: DEFER holds rotation and a self-stop only, working-only defer, subagents file validation, scan exit kept, DRIVER and factory.md within their size budgets Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(runaway-stopper): ship voices: list limit clamp, allSettled fetch, waiting /ship and shipping descendants defer, unknown flags refused, GSTACK_SHIP_TASK_TITLE implies the task-row meter Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(ship): leave DRIVER.md unchanged; main left 21 bytes under its 12 KB cap Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
ade35bc813 |
v1.94.29.0 R56: everything in gstack earns its place (principle, evidence gates, inventory) (#3837)
* eval-plan: a no-gstack arm needs masking, install and audit lines prereg --check now refuses a loaded comparison whose ## No-gstack arm section lacks masking:, install: or audit:, or says none for one of them (PREREG_NO_GSTACK_ARM). On Capy, run agents inherit the instruction to load the user-drive gstack skill, so the arm hides both Capy drives, checks that no gstack is installed, and audits drive reads; an arm that read a gstack skill file is contaminated and gets zero credit (TESTING_INTERNALS.md #no-gstack-arm). The prereg template, /eval-plan, troubleshooting and the two passing prereg fixtures carry the new lines. eval-plan's paragraph was dieted to hold its context-budget ceiling. Evidence: safety: keeps the no-gstack control uncontaminated (Captain order, FOUN-32 via GGST-6) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * inventory: the R56 evidence ledger, gstack-inventory and skill-bill EVIDENCE docs/inventory/evidence.json holds one row per inventory key: the skill folders discoverTemplates() finds (root skill as gstack, symlinked folders excluded) plus seven shared parts, 71 keys. lib/inventory.ts validates each row by its status's own fields, with named codes (LEDGER_*), and joins the ledger with lib/context-bill.ts buildBill. bin/gstack-inventory writes docs/inventory.md, --check validates (exit 1 with codes), --json prints. Paid dispatches per run for /ship and /autoplan are quoted from their own docs and found by line, so a moved citation fails --check (INVENTORY_SOURCE_MISSING). Every current row is grandfathered and seeded from GEVA-2's table (org-gstack-gbrain/research/gstack-part-evidence.json): in-flight fair tests and proposed registry rows as plans, earlier unfair results under prior with why (stub, unmasked, ceiling, ...), five safety rows. gstack-skill-bill prints the skill's EVIDENCE line. Evidence: plan none (owner ruling R56, GST-914); the ledger itself is the measurement record Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * ETHOS 9, Earn Its Place: factory, /write-skill and /autoplan carry it Garry, 2026-11-02: "Also work this principle of only include it if it is beneficial and good into gstack". ETHOS.md principle 9 states the rule, the fair test (claude_code preset, frontier models per R54, masked no-gstack arm), the R48 Why-null cycle, the safety exception, and measure biggest first, linking docs/inventory.md. factory.md item 8 cites it, trimmed elsewhere to 3,298 of 3,300 bytes with no rule dropped. /write-skill's edit ladder step 2 is the evidence rule and section 4 adds the Evidence: commit line. /autoplan's CEO phase lists each part a plan adds to gstack with its evidence or owned, dated plan; two redundant lines went to keep autoplan under its size pins (pins lowered by 17). CONTRIBUTING.md "Adding a new skill" and docs/skills.md point at the ledger. Skill-Size: 3273→3666 bytes (write-skill/SKILL.md.tmpl) Skill-Size: 12738→12721 bytes (autoplan/sections/ceo-phase.md) Evidence: plan none (owner ruling R56, GST-914); write-skill and autoplan rows stay grandfathered untested Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fixup! inventory: the R56 evidence ledger, gstack-inventory and skill-bill EVIDENCE Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * inventory: list the evidence table's other names and its unmapped rows Ledger rows carry aliases (the name GEVA-2's table uses where it differs from the key, such as upgrade for gstack-upgrade), and docs/inventory.md lists them beside the installed-name rule. Unmapped rows are labeled as evidence-table rows, and the ranking notes that a skill's on-demand files can also be a shared row's. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: the first inventory snapshot and the R56 changelog fragment docs/inventory.md is generated by bin/gstack-inventory at the previous commit: 71 parts ranked by load per run, 0 helps, 0 no-effect, 0 hurts, 16 untested with a plan (4 fair tests under way, 12 proposed), 50 untested with plan none, 5 safety. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * inventory: investigate's step procedure is a fair-test CUT-CANDIDATE (GST-814) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: the inventory snapshot after investigate's no-effect row Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * inventory: only the seeded backlog may be grandfathered, so a new part's row is checked (review fix) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * inventory: devex-review and retro name their GEVA-2 registry rows (R56-11, R56-12) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: the inventory snapshot after the review fixes Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * inventory: a concrete plan is a path, gstack-inventory never writes into a gstack install, and the ledger checks aliases, r48 and prior.why (review fixes) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * inventory: investigate's no-effect row notes that only Opus 5.5 was measured Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: the inventory snapshot after the review fixes Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * changelog: R56 counts after investigate's row; grandfathering and the install guard Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test: register inventory-grandfathered.json as a free fixture free-suite (1) at |
||
|
|
c197a139b7 |
v1.94.8.0 fix(approvals): no identifying approval text in public-repo PR bodies (GST-1160) (#3918)
* fix(approvals): render no identifying approval text on public repositories (GST-1160) gstack-approvals render asks gh for the repo's visibility. A public repo, or one gh cannot read, gets only 'Approved: yes|no (record r-<id>)'; a PR description keeps every edit, so the owner's words, run ids and plan hashes stay in the private record. --full prints the rows only when the repo is not reported public. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes (check the origin repository's visibility too, GST-1160) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: say render prints one line on public repositories (GST-1160) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: leave docs/captain.md for a follow-up; /ship reads it as agent prose (GST-1160) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
14d7414af3 |
v1.93.33.0 wave(review): #3705 #3744 #3745 #3764 #3765 #3795 (#3852)
* fix(ship): base merges, adjacent base edits, test-only and audit-requested fixes no longer force a second review loop (GST-407, GST-384, GST-391) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * ship driver: trim two phrases for headroom with #3662 Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * ship driver: keep the Next steps heading phrase the handoff check reads; trim elsewhere Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test: regenerate ship goldens Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes comparePath returns same only when every hunk sits where the base change puts it (patch-ids ignore positions) and treats a file-mode change as changed; the scoped-review packet says when a fence is truncated; --docs-result must be the posted audit's result; the --context-reviewed record goes beside the packet, outside the worktree. Negative controls for each. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pass-2 review fixes A test edit routes as tests= only when it adds lines with no gate tag; a removed or changed line or an unreadable test diff goes through the full loop. Diffs skip textconv. A hunkless patch (binary, empty, mode-only) is same when its patch-id matches. Without --reviewed-base test files route as before. finish's packet path and attempt's state directory have fallbacks. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: Step 11 review fixes; a version-only stamp_files edit after review is release metadata (GBRA-251) gateEditedPaths reads removed lines only inside hunks; carry refuses when a path listing fails; docs freshness stops on a failed listing; attempt counts an unreadable state file. releasePaths includes stamp_files paths whose edit is a version swap under stamp_patterns. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: no test edit skips review; guard packet writes; exclusive attempt state A test-only edit with no gate tag gets the scoped fix-check of its test hunks instead of a lanes-only rerun. Packet write failures print a STOP or RECEIPT_CARRY_REFUSED. attempt's allowance uses an exclusive create. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: attempt prints gstack's install command; carry checks the product diff outside context paths The attempt STOP no longer echoes the audit child's fix text. A scoped-review carry now requires the product patch-id without the context paths to match at both heads. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: oversized packets take the full loop; exact --docs-requested match; name-only test globs only in test dirs A scoped-review packet section over 200 lines sends that path to the full loop instead of a truncated packet. The docs-result path match is exact. test_*.py, *Test.java and similar count as test code only under a test directory. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(unattended): carry's scoped-review refusal and what it keeps Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: carry's scoped-review route in ship-policy, review-policy and troubleshooting (docs-a-1) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(windows): curate ship-rereview-triggers out of the Windows lane like ship-release (run 41193336209) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(review-log): record a notes-only /ship pass clean; name the cause and repair when a pass's tree moved (GST-430) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(receipt): carry and write handle PRs with thousands of files; tree receipt fails closed on a failed diff (GST-448) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(ship): preflight routes RECEIPT_CARRY_SCOPED_REVIEW to the scoped review; carry --dry-run writes no packet (GST-442) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(ship): Step 1.4 and Step 16 route the scoped-review refusal and the --docs-requested fix; trims keep the cap (GST-442, GST-444) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: /ship review pass 1: notes-only floor, scoped carry order, named temp and diff refusals - A notes-only pass is recorded clean only when every finding is fixed, or noted or deferred below the blocking floor (never CRITICAL or blocking), by its logger-stamped action, and the findings account for the claimed issue and critical counts (GST-430). - The preflight scoped carry route commits and pushes the base-merge fix before writing the packet (GST-442). - patchId refuses by name on an unwritable TMPDIR; the tree receipt names why its diff failed (GST-448). - Step 16 stage 3 spells out --docs-requested with its --docs-result (GST-444). Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test: pin the Step 16 --docs-requested route with its --docs-result Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: a claimed clean review row with a logger-stamped open gate finding reads UNVERIFIED (red-team, pass 1) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: Step 11 findings: gate rows from --findings are stamped, one open rule, stale patch-id dirs swept - deriveFromFindings stamps gate rows with the session kind before deriving status, so a findings file cannot dispose of a gate finding the unattended logger forces open (outside-voice#1). - reviewFreshness reads a claimed row's findings with isOpenByAction, the rule the notes-only rewrite uses; noted and deferred clear a finding only when it is marked blocking: false and is not CRITICAL. - patchId sweeps gstack-patch-id-* directories over an hour old that a killed carry left in TMPDIR. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: Step 11 round 2: stamped-open gates win over status and disposition; resolved gate, skipped and below-floor actions stay CURRENT - isOpenFinding treats action 'open' (the logger's forced-open stamp) as open before a row's status or disposition. - reviewFreshness flags a claimed clean row only for an 'open' action or a CRITICAL or blocking deferral or note, so interactive kept and restored gates, skipped advisories and INFORMATIONAL deferrals read CURRENT as before. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: carry dry run offers the scoped route last; patch-id diff under the git dir; changelog matches the review-log floor Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: a claimed clean review row with any unresolved non-gate CRITICAL finding reads UNVERIFIED (pass 2 red-team) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: carry dry-run scoped route, patch-id directory, tree-receipt refusal (docs-d-1 audit) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(ship): Step 3 names merge conflicts in its STOP sentence again (ship-workflow-clarity pin) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(tree-receipt): keep the gated-to-current diff at the file helper timeout (60 s); pregate literals check Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(carry): large-diff fixture sets core.longpaths so Git for Windows can add its long receipt paths (windows-free-shard 1, run 41210080055) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(review): a stale local base branch yields to its origin twin in gate-diff and diff-scope (GST-462) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(ship): Step 11 saves the targeted record and the receipt writes carry it; Step 9 clears it (GST-464) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * changelog: GST-464 and GST-462 Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(review): pass 1: ahead and diverged labels, diff-scope needs shared history; preflight refreshes origin/<base> and stops on a diff far beyond the PR (GST-462, HARN-15) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pass-2 review fixes for base twin, prSized stop and targeted record Resolve the tracking twin by refs/remotes/<remote>/<ref> and only for a bare branch name, keep a local base that is ahead or diverged, quote the prSized stop's base and name the fork case, and have every Step 9 entry create, exclude and clear .gstack/tmp/targeted.json. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: origin's tracking base wins whenever related; prSized lower bound The fix-check found that keeping a local base ahead of origin left unpushed base commits out of the gate scan while review-plan listed them. The tracking branch now wins whenever it shares history with HEAD, an explicit origin/main reads refs/remotes/origin/main, the preflight also stops when the diff lists fewer files than the PR, and the Step 9 exclude line survives a missing .git/info and an exclude file without a final newline. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * changelog: the tracking-ref claim holds while the tracking branch exists Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test: repin the two ship section briefs under no-loss replay GST-464 GST-464 brief-identity check: every reviewer brief lib/review-brief.ts cuts from ship/sections/review-army.md and adversarial.md stays byte-identical to the bodies the L and GST-257 replays admitted; only lead instructions outside the cut spans changed. The check is a test CI runs. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * ship: keep Step 9's PASS_HEAD sentence whole; repin review-army under GST-464 The targeted-record line follows the PASS_HEAD/RANGE_BASE sentence instead of splitting it (test/review-fix-range.test.ts pins that sentence). The brief-body check still holds: every reviewer brief is byte-identical. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: restore bin/gstack-ship-receipt after the main merge The merge commit |
||
|
|
daf661374f |
v1.93.10.0 wave(docs): #3590 #3591 #3819 #3618 #3824 #3828 (#3847)
* Attribute every paid trial's cost: bind label-named records by testName, price aborted SDK sessions from streamed usage, model-free cases cost $0
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: case cost adds streamed sessions to record sums and keeps record cost_known
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: the paid report headline counts ledger-only session cost once
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: a cost-only record never sets the trial model
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test: recordE2E writes cost_case_id only for a registered label-named case
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: CHANGELOG for paid-report cost attribution (Unreleased)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: the headline adds only streamed session cost; cache writes without a 5m key
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: how the paid report prices a trial and what stays cost-unknown
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* Price PTY sessions from their transcripts: pin a session id, sum the session's and its subagents' usage into the ledger's streamed_cost_usd
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: transcript pricing never throws from a PTY ledger writer
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* chore: pin transcript-cost.ts as non-behavioral at HARNESS_VERSION 6
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: recognise --session-id= and --resume= forms
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: CHANGELOG for PTY transcript pricing (Unreleased)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: PTY sessions priced from their transcripts
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: price PTY transcripts without adding a launch argument; native AUQ capture opts out
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: harness notes and CHANGELOG match the transcript claim
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat(flaky): gstack-flaky run reruns a failed JUnit test once and ledgers the flake (GSTA-158)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(flaky): stream output, keep unreported runner failures red, fail-closed duplicates and nonzero reruns
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
gstack-flaky never greens an incomplete run: a targeted rerun needs the
runner's summary proving the first run complete, otherwise (and always for
generic runners) the rerun repeats the whole command. A rerun clears a test
only when it exits 0 and the test passes once on its first attempt. Killed
runners exit 3 (FLAKY_COMMAND_KILLED) and signals are forwarded. The first
report is restored at --junit with reruns kept beside it; ids are redacted at
every output; the ledger gets its own GSTACK_FLAKE_LEDGER_JUNIT; fixtures are
registered in FREE_FIXTURES.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: latch cancellation and check whole-command rerun reports
A cancel forwarded to a runner that traps the signal now counts as killed for
every later attempt, so a cancelled job is never rerun or greened. A
whole-command rerun clears nothing when its report has a failed test, misses a
first-run test, or its runner counted failures outside the report.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: whole-command rerun when coverage or runner-flaky tests can fail the run
A coverage threshold or a fail-on-flaky policy fails a run for a reason a
narrowed rerun cannot reproduce, so either forces a whole-command rerun.
--junit refuses an existing file that is not a JUnit report instead of
deleting it.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat(flaky): rerun the whole command by default; targeted rerun is opt-in
A rerun counts only on the runner's own full green verdict: exit 0, no failed
or missing test, nothing counted outside the report. That covers every way a
run can fail, which a narrowed rerun cannot (a coverage threshold with an lcov
reporter, a fail-on-flaky policy, a test never reached). --rerun-scope test
reruns the failed test alone, with its preconditions documented and the
complete-run checks kept as a safety net. An unreadable existing --junit file
is a usage error, not a crash.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: gstack-flaky CHANGELOG entry and standalone-binaries row (GSTA-158)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat(flaky): quarantine registry for repeat flakes (GSTA-158 P2)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(flaky): bound renewal dates; match non-ASCII paths in check --base
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(flaky): reword the FLAKY_QUARANTINE_BASE hint so the egress scanner does not read it as a network op
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(agent-sdk): every SDK caller passes the claude_code preset or names why not
The SDK's default system prompt is a bare stub that drops the line telling the
model to run /skill through the Skill tool. runAgentSdkTest now refuses a
missing, empty or bare-string prompt; non-preset callers name a reason; a free
tripwire scans test/ and scripts/ for the same mistake.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test: record the SDK prompt guard as a non-behavioral harness change and baseline its tripwire
harness-version: runAgentSdkTest validates systemPrompt before starting; every
live caller already passed the claude_code preset, so no verdict can change.
test-of-test ratchet: the tripwire's subject is the eval harness by design.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: name the preset literal callers pass and the unnamed-prompt refusal
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat(eval-plan): frontier models under test (R54)
Haiku and Sonnet are not models under test. dry-run refuses a plan whose every
arm is Haiku or Sonnet unless --tier-question names what it asks about that
tier, warns on a mix, and re-costs the plan on Opus 5.5 and GPT-6.1 Sol.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(eval-plan): trim R54 skill prose and raise the eval-plan context ceiling
The R54 paragraph and CHECK: frontier bullet were cut to the minimum; the
exemptions and verdict rule stay in docs/TESTING_INTERNALS.md. The remaining
growth is the feature, so only the eval-plan eager ceiling moves (4887 -> 5458,
the capture helper's value); other skills' ceilings are left as they were.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(eval-plan): pilot start keeps the R54 refusal; --tier-question rejects a flag
Review pass 1 (full depth) found the frontier refusal could be skipped by
starting a pilot on Haiku or Sonnet arms behind a dry run made on other arms,
or behind a dry-run.json written before the check existed. startPilot now
refuses a pilot whose every arm is Haiku or Sonnet unless its dry run recorded
a tier question. dry-run --tier-question no longer takes the next flag as its
answer. The testing doc now says the frontier re-cost is printed for
comparison with the brief cap, not enforced.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(support-tiers): Windows CI in the present tense now that windows-smoke is required (#3806)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* chore: empty commit for a clean check set at the same tree (cancelled orphan free-suite check at
|
||
|
|
9d9d4c31bb |
v1.93.0.0 wave(browse): #3700 #3773 #3779 #3817 #3842 (#3858)
* feat(loadouts): Opus 5.5 lite loadout with explicit model detection (GSTA-161)
modules/loadouts.json gains the lite loadout (eleven coaching preamble
pieces dropped; upgrade-check and brain-sync kept) and a models map that
sends only claude-opus-5-5 (and its dated snapshots) to it. Detection is
explicit: Capy passes --model to the installer, Claude Code opts in with
./setup --loadout lite; anything unmapped, invalid or unreadable serves full.
The checkout always stays the full render.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(loadouts): Opus 5.5 lite, detection order, Capy SKILL_ROOT, setup --loadout; troubleshooting anchors; changelog fragment (GSTA-161)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(loadouts): claude_loadout read through CONFIG_BIN; capy skill context ceiling for the --model line (GSTA-161)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes (prune keeps a reused loadout folder, GSTACK_LOADOUT_SKILL_ROOT, claude_loadout guard test) (GSTA-161)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes (Capy skill passes the model as GSTACK_MODEL so an older installer ignores it) (GSTA-161)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes (prune only owned, unused folders; full root from the canonical Claude install; fallback reason and source) (GSTA-161)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: loadout source example, install and resolve commands, Capy launch-file note (GSTA-161)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat(autoplan): --ceo-only runs the CEO review alone with zero questions (GST-537)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test: classify autoplan-ceo-only in the Codex host metadata
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: select autoplan-ceo-only on the skills it runs; say it needs Claude Code
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test: run autoplan-ceo-only in the marathon lane
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: changelog entry for /autoplan --ceo-only
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test: count the autoplan-ceo-only paid file in the shard inventory
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat: gstack-autoplan next --ceo-only runs the CEO review alone and ends reviewed (GST-537)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: budget and close recover a budget-stopped CEO-only run; reviewed is at rest for checkpoints
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: CEO-only finish leaves owner-only cap items undecided, refuses marker phase flags and a plan at the report path, and replaces ceo-review.md atomically
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: the CEO-only report-path guard compares real paths and refuses at the finish when the report file is the plan
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: CEO_ONLY_CONFLICT covers a plan linked to the report path
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(browse): failing-first device and touch tests (GSTA-227 F3, #3058)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: the report-path guard keeps the lexical check, skips safe hard links and compares bigint file ids
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* browse: per-session tabs for parallel agents; tab pins stop moving the shared active tab (#1961)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* browse: keep the server.ts tab-pin anchor comment for source guards
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat(browse): per-tab phone emulation and touch input ($B device, tap, swipe, pinch, touch; #3058, GSTA-227 F3)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test: copy lib/result-codes-autoplan.ts into the fixtures that copy the result-code tables, and keep it out of derived closures
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(qa, aside): touch pointer in /qa, Aside touch recipe verified on Aside 1.26, report Phones row (GSTA-227 F3, #3058)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* browse: drop the sessions paragraph from /browse to stay inside the parity cap
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* changelog: F3 phone emulation and touch entry
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* browse: hide the ps window in the session harness walk
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: the decisions.jsonl status list names auto_kept
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(browse): session cap, LRU eviction, headed release and scoped auto-session rows
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* browse: sessions keep tab <id> picks, sidebar claude stays on the user's tab, pinned rebuild and state load rebind the scope
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes (touch cancel with no finger held is a no-op)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: Step 11 review fixes (headed tab adoption, pinned viewport reset, CLI retry keeps --session, rebuild id remap, --json notice, evicted-session reset, device kept after annotated captures, render opts out of sessions, session: client ids reserved)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: headed viewport auto keeps the user's active tab; render's closetab opts out of sessions
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: sessions, phone emulation and touch in BROWSER.md; session: client ids reserved; TODOS #1961/#3058 shipped
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test: copy lib/result-codes-browse.ts into the fixtures that copy the result-code modules
lib/result-codes.ts imports ./result-codes-browse, so fixtures with an explicit
lib list failed with 'Cannot find module'. pr-dependencies lists it with the other
reason-code modules as selection data. GSTA-227
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat: gstack-clean reclaims per-repo .gstack scratch and logs, dry run by default (#2627)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* browse: name the Aside touch recipe's coordinates <tap-x>/<tap-y> with a numeric grammar
The generated-bash lint (INV-3) rejected the free-text <x>/<y> placeholders. GSTA-227
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(clean): leave hard-linked and unreadable logs alone; cut through a no-follow descriptor checked against the evaluated inode
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(clean): tests that expect tmp removal see a quiet ps, so a codex elsewhere on the host cannot flake them
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(clean): an unlistable tmp/ skips its group; liveness asked once per group on apply; BROWSER.md says which logs reset at daemon start
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(clean): write output synchronously so --json reaches a pipe whole; test fixes for root, wrapper git and the ps stub
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(clean): every change rechecks the verified folder and the measured file; full writes; EPIPE ends output quietly
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(clean): the early-close test checks the bin's own exit status
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: list gstack-clean among the standalone CLIs
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(clean): copied-install fixtures and the dependency list carry lib/result-codes-clean.ts
The remote pregate failed 11 cases in gstack-doctor, plan-tune-cathedral and
timeline-stop-hook-slug: each copies an explicit list of lib/result-codes-*.ts
files into a temp install, and lib/result-codes.ts now imports
./result-codes-clean. Same lists GSTA-168 extended for result-codes-eval.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* chore: regenerate gstack-doctor-components.sh for the gstack-clean result codes
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* qa: fold the touch pointer into the Phases sentence to fit the parity size cap after the main merge
qa's union was 95988 bytes (ratio 1.142 > maxSizeRatio 1.142, train 75). Now 95975 (1.1419). GSTA-227
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: #3058 troubleshooting 'Fixed in' lines name v1.92.10.0 after the main merge
GSTA-227
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(clean): classify gstack-tasks rows files (tasks-*) as kept, after main added the producer
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: #3058 troubleshooting 'Fixed in' lines name v1.92.20.0 after the main merge
GSTA-227
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes (restore the lib/result-codes-plan.ts ratchet row the base merge dropped)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(clean): the producer scan ends a name at a colon, so prose after a path names the file (train 78)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: #3058 troubleshooting 'Fixed in' lines name v1.92.30.0 after the main merge
GSTA-227
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* outside-voice-api: caller receipts, stop_reason, OpenAI max_completion_tokens
A caller can write its own egress receipt (sink, consent, payload class);
the default stays the outside-voice receipt, so existing callers send and
record the same bytes. The result carries the provider's stop reason, and
an OpenAI request gets max_completion_tokens only when the caller sets an
output limit (GST-537 PR 3).
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* autoplan gate: item classes and the owner's answer provenance
Gate items carry item_class, ruleKept() names the keep-direction pick, and
answered decision rows record owner_mode, owner_named, rec_hash and
answered_role parsed from the owner's own words (GST-537 PR 3).
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* autoplan: shadow-mode decider module, frozen prompt and spend accounting
The switch (off by default, fixed at init), the lease, one model call per
gate with a page retry and a truncation retry under one deadline, the
once-per-revision record with its journaled sha256, the 10% audit mark,
and shadow-labeled ledger rows that count against the cap, show as
shadow= on GATE_SPEND and stay out of the per-voice price (GST-537 PR 3).
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* gstack-autoplan: shadow every published gate, the shadow export, config and docs
Every driver command that prints a gate records the shadow first and
checkpoints after it; answer waits for a live lease and records a dead
one retrospectively; gstack-autoplan shadow exports answered revisions
for taste-replay R2 (SHADOW_BEFORE_ANSWER otherwise); gstack-config
autoplan_shadow / autoplan_shadow_model; gstack-artifact validate checks
the record's hash (GST-537 PR 3).
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* changelog: shadow mode for the CEO-only decider (GST-537 PR 3)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* autoplan shadow: /ship review fixes
- register test/fixtures/shadow-fake-model.ts in FREE_FIXTURES (free-fixtures inventory failed)
- withRunLock: count dead-owner reclaims apart from waitMs iterations, so a long wait can still reclaim
- buildPage: fill the decider template in one pass, so slot names inside the plan stay plan text
- revise regate: the shared publish step prints the GATE and ESCALATE lines once
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* autoplan shadow: reply files never follow a link; the retry reserves against the current cap
- a model reply is written by temp file and rename, so a link at the reply path is replaced, not written through
- each shadow reservation reads the run's current spend cap, so a budget change during the call is not undone
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* outside-voice-api: write the egress receipt under the caller's env
callModel resolved the receipt's state root from process.env even when the caller passed env, so the shadow
tests wrote to the real ~/.gstack (the free-suite home-containment guard caught it). The receipt now uses
req.env; the shadow tests give the fake model a private HOME, GSTACK_HOME and GSTACK_STATE_ROOT, and the receipt
test no longer sets process.env to pass.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(autoplan): CEO-only runs leave main's open Critical/High finding items to the owner (no decision row)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(autoplan): shadow pages carry main's finding items; a finding item is never ceo_eligible
After merging #3767 (main
|
||
|
|
3d99c22497 |
v1.92.76.0 wave(review): #3809 #3813 #3826 #3831 #3838 (#3848)
* fix(retro): keep retro history in the state root, shared across worktrees (#3749) /retro saved snapshots under .context/retros inside the working tree, so a run in a linked worktree saw none of the main checkout's history, reported "First retro recorded", and wrote a snapshot that git worktree remove deletes. gstack-retro-metrics --history [--next <date>] now resolves the history directory as <state root>/projects/<slug>/retros (the slug is keyed on the git common dir, so every worktree shares it), moves any legacy .context/retros from this worktree and the main checkout into it, lists prior snapshots and prints the next snapshot path. Step 12/13 and the gbrain prior-retros query use it. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(gate-diff): read a bare base as origin/<base> in gate-diff and diff-scope (#3650) gstack-gate-diff and gstack-diff-scope resolved a bare base such as main to the local branch whenever it shared history with HEAD. A local main that is behind origin/main (a linked worktree, or a Capy clone, where local main never moves) then set the merge base, so /ship's gate scan and specialist scope also read commits already upstream. Both now prefer origin/<base> when it resolves, the base /ship fetches and merges against. Fixes #3650 Co-authored-by: exGeni <135786749+exGeni@users.noreply.github.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(retro): make history migration safe against symlinks and concurrent runs (#3749 review) Review pass 1 findings: a .context/retros that resolves outside its worktree (or to the shared history itself) is left alone, so migration can no longer delete the history it points at; moves are no-clobber with retry; a copy identical to any same-date snapshot collapses; RETRO_FILE is reserved as {} so overlapping runs in two worktrees never share a path; --next must be a YYYY-MM-DD date; a missing option value no longer loops forever. Step 12 names RETRO_HISTORY_ERROR instead of reading it as a stale helper. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(changelog): fragment for the #3749 retro history fix Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes (diff-scope reads slash-named bases through origin too) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(retro): trim Step 12/13 prose back under the parity skeleton cap Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: Step 11 review fixes (a fork branch, a colliding tag or another remote never replaces the base) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(retro): keep today="<today>" in Step 12 so the judge excerpt keeps both date inputs Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(changelog): describe the fork, tag and remote guards (#3650) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(retro): compare #3749 history paths with forward slashes so the Windows shard passes Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(review): review-plan and gate-diff plan the same with a stale local main or a shadowing tag (GST-883, failing first) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(review): gate-diff and review-plan resolve a branch base to origin/<base> by full ref name; review-plan scans the merge base its own diff used (GST-883) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(changelog): GST-883 fragment Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(review-risk): hostile-input time bounds for every risk pattern; the R51 rm and rmSync rules fail (GST-898) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(review-risk): the R51 rm and rmSync rules run in linear time (GST-898) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(review-packets-removed): repin lib/review-risk.ts on the GST-898 verdict-identity replay Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(review-risk): padding cannot push recursive: true out of the rmSync window; repin on the GST-898 no-loss replay Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(changelog): GST-898 fragment wording Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(review): planner misreads: SVG chart as runtime, session data as auth, bare base in diff-scope and receipt depth (GST-911, GST-884, failing first) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(review): a drawing-only SVG is data and a scripted one is security; session data files are not auth; diff-scope and the receipt depth read origin/<base> by full ref name (GST-911, GST-884) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(review): the SVG drawing check refuses CSS escapes and reads zero-padded character references; the security class reads a file's changed SVG lines joined (GST-911 review pass 1) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(review): a stray quote cannot hide an external href in a drawing SVG (GST-911 review pass 2, failing first) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(review): the SVG drawing check reads every name= without consuming its value, so a stray quote cannot hide an external href (GST-911 review pass 2) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(review): CSS in a drawing SVG holds only declarations and url(#id): image-set(), image(), element() keep it code (GST-911 Step 11, failing first) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(review): a drawing SVG's CSS holds declarations only, no @ rule and no function but url(#id), which closes image-set(), image(), element() and every other CSS load (GST-911 Step 11) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(review): a style element's CSS is read past comments and CDATA, unclosed style tags are refused in linear time, and every drawing verdict holds at 1 MB and 8 MB (GST-911, failing first) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(review): walk a style element's CSS with indexOf, dropping comments and reading CDATA, so no hidden </style> ends it early and unclosed style tags refuse in linear time (GST-911) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(review-policy): the linear-time claim covers R51's rm and rmSync rules (GST-898) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(review-policy): state the rmSync padding rule exactly (GST-898) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(review-depth): linear url() refusal in svgDrawing (wave review-2, red-team CRITICAL) SVG_REFUSED's url() entry backtracked quadratically on url( followed by a long whitespace run (80k spaces: 820 ms; 1 MB: over 230 s), and svgDrawing runs in collectLive and in collectCommit, which ship-queue ready, train build and land call with no timeout. The rewritten entry refuses exactly what #3838's pattern refused. Repin lib/review-depth.ts under no-loss replay GST-911-redos (verdict identity: 60,000 seeded strings, the edges and every SVG blob in history, zero differences). Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes (wave review-2, pass 1) - bin/gstack-diff-scope: _resolve_base takes a related local <base> before another remote's twin, the order resolveBase uses, so the two tools pick the same base for a bare name when origin/<base> is unrelated. - lib/review-depth.ts: a drawing's DOCTYPE names no document but W3C's SVG DTD; SYSTEM and other PUBLIC identifiers keep the SVG code. Repin lib/review-depth.ts under no-loss replay GST-911-redos (the DOCTYPE change only keeps more SVGs code, so it drops no reviewer). Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: freeze the exported SVG_REFUSED list (wave review-2, Step 11) Exported only so test/review-risk-redos.test.ts can reach the url() entry; a frozen readonly copy keeps any importer from changing verdicts while DEPTH_RULES still reports the original rules. Repin lib/review-depth.ts under no-loss replay GST-911-redos (no pattern changed). Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * Revert "fix: freeze the exported SVG_REFUSED list (wave review-2, Step 11)" The fix-check (wave review-2) showed Object.freeze is shallow: each RegExp can still be changed in place, so the freeze did not close adversarial-native#1, and it moved the tree past the one the Step 11 voices reviewed. The finding ships as an open note (its reviewer rated it Low, not blocking; no production caller mutates the list). Restores the lib/review-depth.ts pin under no-loss replay GST-911-redos. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(changelog): wave review-2 entry for the integrator fixes Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(review-policy): a drawing's DOCTYPE names no outside document (wave review-2 docs audit) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> Co-authored-by: exGeni <135786749+exGeni@users.noreply.github.com> |
||
|
|
1a22ae9652 |
v1.92.68.0 feat(health): Step 1 detects tools with gstack-checks, no check lost (GST-116 PR 2) (#3691)
* feat(health): Step 1 detects tools with gstack-checks detect --for health, no check lost (GST-116 PR 2) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test: register the frozen /health detection fixture as free Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test: Health Stack normalization and --for refusals (review pass 1) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(health): keep Health Stack command bytes, honor an empty section, detect from the working directory (review pass 1) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(health): a multi-line test script is reported, not printed into the line protocol Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(health): Health Stack rows stay markdown like /verify reads them; an empty section names why (fix-check) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test: the PATH-stub cases of the /health no-loss test run on Linux and macOS (windows-latest cannot launch sh stubs) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
693ee7132a |
v1.92.53.0 fix(ubicloud): reap destroys only the caller's own VMs (GST-573) (#3756)
* fix(ubicloud): pack and usage on macOS, empty projects (#3680, #3679, #3678) pack builds its archive in two tar passes plus gzip, which bsdtar and GNU tar both accept, with COPYFILE_DISABLE=1 so Apple's tar adds no ._* files. vm_rows skips the blank row Ubicloud returns for a project with no VMs. usage parenthesizes its ternary for the one-true-awk and exits 1 on an unreadable list or size; the quota preflight logs that and defers to the API. Co-authored-by: Jared <182125291+yolo-jared@users.noreply.github.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes (usage skips a VM destroyed since the list; spawn timeout) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes (quota wait retries an unreadable usage) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: changelog fragment for the ubicloud macOS and empty-project fixes Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: TESTING_INTERNALS notes the quota preflight's unreadable-usage path Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(ubicloud): reap destroys only the caller's own VMs (GST-573) reap, which every up runs first, destroyed any VM in the project whose TTL had ended, whatever owner created it. That broke the owner-scoped cloud-deletes rule. It now destroys only the caller's own expired and old TTL-less VMs and logs a count of other owners' expired VMs. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(ubicloud): trim the owner-scoped reap prose back under the context budget Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: TESTING_INTERNALS says the TTL reaper covers only this owner's VMs Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(ubicloud): restore the expiry and reap conditions in the trimmed reap prose Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: Jared <182125291+yolo-jared@users.noreply.github.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
90a170c941 |
v1.92.50.0 wave(autoplan): #3781 #3743 #3751 #3762 (#3788)
* fix(eval-plan): per-arm pilot projection and --seat-metered arms (#3653) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(autoplan): guard tolerates Claude Code's cwd-reset footer and recovers after an unreadable init (#3651) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes (journal reader strips the cwd-reset footer; an init with no text block no longer locks the session) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: journal reader skips a failed or unreadable init, as invocation() does Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * feat(autoplan): --ceo-only runs the CEO review alone with zero questions (GST-537) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(eval-plan): all-seat pilot, single-attempt arm and --seat-metered CLI wiring Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(eval-plan): summed deviation adds arm deviations, matching the summed band (arms share rows) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes (test pins an unpriced seat-metered arm) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes (seat-metered declaration fixed per --out, price row still required, a real charge settles as spent) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test: classify autoplan-ceo-only in the Codex host metadata Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: a seat-metered arm that settles a charge is projected as a priced arm Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: select autoplan-ceo-only on the skills it runs; say it needs Claude Code Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(skills): /eval-plan --seat-metered and per-arm projection Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(eval-plan): skill prose stays under its context budget and carries no $N token Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test: run autoplan-ceo-only in the marathon lane Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(skills): a seat-metered arm leaves the seat set once it settles a charge Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: changelog entry for /autoplan --ceo-only Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(autoplan): init_failed covers unreadable init output and the cwd-reset line (#3651) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test: count the autoplan-ceo-only paid file in the shard inventory Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(autoplan): #3651 tests pass the test-code type ratchet Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(dx): CAP finding titles carry a one-line description (GBRA-223 claim 2) The DX error contract told both autoplan DX voices to title capped findings exactly CAP4:<path>:<item>, so gates, tasks and reconcile saw a bare code. The title is now CAP4:<path>:<item> <what fails>; the grader already parses that shape. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(autoplan): reconcile pairs same-file findings that carry no line (GBRA-223 claim 1) Plan reviews name files, rarely lines, and reconcile associated by location only when both findings had a line, so findings both voices raised on one file were filed new and native-only. A same-file pair with a missing line is now associated as unverified (basis file), never confirmed; a CAP code no longer counts in title comparison. DRIVER.md names submit --reconcile. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(autoplan): open Critical and High findings reach the gate as apply items (GBRA-223 claim 3) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(autoplan): a spend cap binds on every unattended host; --estimate-usd persists; DRIVER names --usage-usd (GBRA-223 claim 4) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(autoplan): run binds complete api results, names a truncated response, --max-tokens; DRIVER documents run (GBRA-223 claim 6) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * feat(autoplan): carry an item-by-item answer when the later gate asks nothing new (GBRA-223 claim 7) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(dx): trim the compact error contract so plan-devex-review stays under its size pin Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes (p1b applies finding fixes, api attempts reserve no host default, cross-file title pairing, paired severity counted) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: review fixes (priced api reservations, no file-only twins, two-pass pairing, partial replies keep p1-dependent defaults open, outside refusal degrades) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * P7: record whose words answered a gate (--words-by agent:<id>), never carry an agent's own words, import each row under its own answerer (GEVA-2) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: review pass 2 (p1b needs --rec-hash after recommend; api calls send the output limit they reserve for) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * changelog: fragment for the /autoplan field-report wave (GST-672) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: captain record notes --words-by agent attribution Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test: follow finding apply items in approval-class and Captain flow tests; bind run-api limit to DEFAULT_MAX_TOKENS Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * wave autoplan: lower the gemini plan-devex-review pin to its exact size after #3781's DX trim Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(autoplan): CAP titles on different paths never match by title in reconcile or confirm rounds (wave review) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(autoplan): a truncated api call settles its cost and a retry is admitted afresh against the cap Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(autoplan): an applied finding stays open until the revised plan is reviewed; a shared location alone never twins two findings Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(approval): a plan gate answered in an agent's own words is not owner approval Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(gate): a new answer replaces the earlier answer's authorship and words Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(autoplan): a failed api call with no usage keeps its attempt open; reservations price the bound prompt (wave fix-check) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(autoplan): a spend cap fails closed: only a call refused before sending keeps its attempt; a sent call with unknown usage settles at its reservation Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(autoplan): the 16384 output default applies to both providers; changelog for the wave's integrator fixes Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(autoplan): how run settles a failed api call; changelog scopes it to the native voice Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(autoplan): a spend cap fails closed on every exit of run; an unpriced model reserves the default once a cap is set Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(autoplan): every sent call settles; an unpriced model under a cap reserves the default Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(autoplan): DRIVER and help say a cap reserves in any session kind and how run settles a sent call Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
4eff47c5cf |
v1.92.2.0 evals: no-gstack arms for the model panel, arm-benchmark, safety and routing evals (#3708)
* feat(eval-plan): results --check refuses a results table without its no-gstack rows Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(model-panel): a <model>#no-gstack arm per model, identity-keyed cells, one campaign, results.md (GST-468) Each panel model also runs as <model>#no-gstack: the same fixture, ticket, tools, limits, route and reservation, with no skill folder and no routing line. The arm identity keys the ledger attempt, test name, row and summary; candidate folders are named after the fixture project and the seed commit has a neutral author. summarize reads one campaign (run id and PREREG.md sha256) and refuses a duplicate cell; suggestionLine reads the skill arms only, so the preregistered particle-1 line is unchanged. renderResults writes results.md, which passes gstack-eval-plan results --check against the new test/fixtures/model-panel/PREREG.md (supersedes GSTA-173 for later runs). Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * feat(arm-benchmark): no-gstack arm on a pinned model, 3 paired trials, both-order paired judge, spend ledger (GST-469) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(evals): no-gstack arm for the safety-rule and router evals (GST-470) GSTACK_SAFETY_ARM and GSTACK_ROUTER_ARM take a third value, none: the same fixture, tools and user request with no skill excerpt, rule text, step file or installed skill. Under none every behavioral check is recorded as an observation (none-arm-observations.jsonl) and never fails the case or writes contract-violations.jsonl; harness preconditions still assert. The four safety prompt builders (ship-evidence, codex-boundary, codex-consult, design-risk) and the router fixtures move into helpers; the rule, removed, current and before prompts stay byte-identical, proven against reference copies of main's code. pair-agent and ios-demo refuse none with the reason (NO_NONE_ARM). GSTACK_ROUTER_ARM now throws on an unknown value instead of silently running current. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * chore: changelog fragment for the no-gstack arms in existing evals Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(arm-benchmark): arm-pair paired-judge calibration run (bar met 6/6, $7.22) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(paid-shards): keep loop-named panel and arm-benchmark cases selectable by --case The lanes moved each cell's testName into helpers, so the static detector no longer saw a computed registration and B4 failed for all eight cases. Same runtime test names; the paid runs are unaffected. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(tests): keep FREE_FIXTURES and the placeholder allowlist current for the no-gstack arms scripts/judge-calibration.ts is now an arm-benchmark paid touchfile, so it can no longer be a free consumer of test/fixtures/judge-calibration/** (CI free-suite 8). The eval-plan Step 5 fence names <prereg-path> and <results-path>; allowlist both as PATH placeholders (CI free-suite 19). Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(eval-plan): cover a complete table after a partial one, --json output and the results usage error Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(eval-plan): keep the Step 7 coverage test as reviewed Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * chore: name the changelog fragment after the branch slug Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: arm-benchmark project folder names and the arm-pair calibration corpus Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: keep the judge-calibration fixture README as reviewed Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(skills): describe eval-plan results --check Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
923ed3cddc |
v1.91.359.0 feat(verify): /verify skill and gstack-checks bin (GST-116 PR 1) (#3672)
* verify: add /verify skill and gstack-checks (GST-116 PR 1) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes (pass 2) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: adversarial review fixes Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: win32 NUL discard for the Go build check; unique Health Stack names (rule 23 grant) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: changelog fragment for /verify Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
2356792e43 |
v1.91.352.0 feat(benchmark): particle-1 awareness, OpenRouter gateway provider, preregistered model panel (GSTA-173) (#3631)
* feat(benchmark): particle-1 and DeepSeek V4.1 Flash awareness, gateway provider, preregistered model panel (GSTA-173) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(evals): particle-1 model panel results, run 2026-10-30-0105 (GSTA-173) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(model-panel): name the task field id (credential scanner false positive on key) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test: gateway reports a missing OpenRouter key first; register the model panel in the paid count and test-of-test baseline Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test: run the fake claude through bun so the gateway provider test passes on Windows Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: gateway benchmark runs load no Claude Code settings A settings.json env block's ANTHROPIC_API_KEY was sent to the OpenRouter base URL as x-api-key; --setting-sources '' loads no settings source. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: name particle-1 and DeepSeek V4.1 Flash in the /benchmark-models row Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * chore: changelog fragment and TODOS for the particle-1 model panel Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: name particle-1 and DeepSeek V4.1 Flash in the AGENTS.md /benchmark-models row Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
8966f3620c |
v1.91.350.0 feat(review): GSTA-167 variant G reviewer stack: blocking floor in both voices, one batched specialist, data-file classifier (#3660)
* feat(review): variant G part 4: data files no code names are docs in classifyDiff, untested state-matrix cells map below the floor per cell (GSTA-167 PR-a)
Part 4a: lib/review-depth.ts owns DATA_PATH (JSON, JSONL, NDJSON, CSV, TSV, raster
images; YAML, TOML and SVG stay code) and applies the data rule only in classifyDiff,
to candidates lib/review-collect.ts finds no non-docs consumer for (git grep of
basenames at head, merge base and, live, the working tree; data-to-data chains four
deep; over 2,000 candidates keeps all code; a grep failure fails closed). classifyPath
and every path-only caller are unchanged; the receipt gate scan decides through
gateScanNeeded (path-only), so it cannot be skipped. gstack-ship-preflight computes
RUNTIME_LINES with classifyDiff over gstack-review-plan --json (now with consumed).
Part 4b: lib/review-scope.ts mapStateMatrixOutput maps an "untested cell" finding to
INFORMATIONAL when its cell has test null in the same output's matrix and it is the
only finding on that cell; gstack-state-matrix findings prints it for Step 9.2 before
the merge. state-machines.md is byte-identical; check still reads the raw output.
Reviewer-brief pins repinned under no-loss replay PR-a (Arm 4: plan identity at the 14
cohort heads; free exact re-score of saved C, D and A' findings).
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat(review): variant G parts 1 and 3: blocking floor in both prose voices, specialists at medium (GSTA-167)
Part 1: the native adversarial and outside-voice prompts end with the blocking
floor ("would fail a test, break production, or lose data or secrets") and ask
each finding for Severity and Blocks: yes|no. Additive rule: a finding is
CRITICAL when its label rule says so or it says Blocks: yes; Blocks: no never
lowers one (proseVoiceSeverity, BLOCKING_FLOOR in lib/review-scope.ts).
Part 3: ROLE_EFFORT puts specialists at medium; Red Team, native adversarial
and fix-check stay full; light's batched specialist (carries the Red Team
prompt) stays full; --no-tiers sends specialists to host.
Repinned reviewer briefs with no-loss replay G1 (live Arm G1, not yet run):
ship/sections/review-army.md, ship/sections/adversarial.md,
review/sections/adversarial.md, lib/review-depth.ts. Merge only on G1's pass.
Review-skill parity ratio 1.3136 -> 1.3180 and the gstack-review size pins
+537 for the approved +0.3k tokens per voice.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat(review): variant G part 2: lean ensemble, one batched specialist at every depth (GSTA-167)
planReview dispatches one 'specialist batched' at standard and full depth (and
light, which adds the Red Team checklist): Testing and Security always on code
and gate class, plus State-machines, Data-migration, API-contract and Design
when scope asks; a forced checklist always joins. Maintainability, Performance
and Simplification are read only when forced (SKIP names them). LIGHT_FIXED is
[testing, security]; BATCH_SCOPED joins DEPTH_RULES so old receipts re-plan.
The Red Team rule and prompt are unchanged; it reads the batched reader's
merged findings. specialistsFor stays as the legacy selection the dispatch
compare script models.
Repinned reviewer briefs with no-loss replay L (live Arm L, scored L∘G1 vs G1;
not yet run): ship/sections/review-army.md, lib/review-depth.ts. Merge only on
L's pass.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat(review): variant G on #3648's dispatch: Blocks: yes collects as CRITICAL, batched checklists by name (GSTA-167)
Integrates parts 1 and 2 with gstack-review-dispatch (#3648):
- lib/review-ledger.ts parseFindings: a prose voice's "Blocks: yes" makes its
own line, or the finding on the line just before it, CRITICAL in
merged.jsonl (normalizer v2, certified by round 5's G1), so judge refuses a
lead that keeps it below the floor; with no finding before it the Blocks
line is its own CRITICAL finding. "Blocks: no" never lowers a label.
- lib/review-brief.ts: the outside-voice brief no longer appends "Give each
finding a severity"; the section's prompt now asks for Severity and Blocks,
so the brief is the certified section prompt plus the branch diff.
- bin/gstack-review-dispatch render --checklists takes the plan's
checklists= names (review/specialists/<name>.md) as well as paths and
refuses an unknown one, since the batched reader is now every depth's
specialist dispatch.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* chore(changelog): GSTA-167 variant G reviewer stack fragment
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(review): consumer scan survives grep.lineNumber/grep.column; collect reads separate-line Severity/Blocks
/ship pass 1 (PR #3660): the Red Team CRITICAL at lib/review-collect.ts:120 and the
informational findings in the same batch. proseVoiceSeverity had no caller and is
removed; the normalizer v2 table now runs through parseFindings, the path collect uses.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(review): collect keeps every prose blocker and one id per finding
/ship pass 2 (PR #3660): an unlabeled line carrying an inline Blocks: yes collects as
CRITICAL again; Severity/Blocks continuation needs a colon, stops at a list item, heading,
bold paragraph opener or a repeated field, and never swallows a top-level bullet or its
section label; the native voice's FIXABLE collects as CRITICAL under its role with or
without a dispatch name; the consumer scan adds --no-color.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(review): a later finding's fields never land on the one before it; explicit Severity wins its line
/ship pass 2 Red Team (PR #3660): prose after a finding's Severity/Blocks field, a
post-blank paragraph or a line in an indented block starts the next finding, and a
line's explicit Severity: label decides it over other label words on the line.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(review): FIXABLE outranks a Severity label on its line; a blocker keeps its own id and subject
/ship fix-check (PR #3660): labels are named before the strongest is taken, so a one-line
native FIXABLE ... Severity: Medium collects as CRITICAL; a later finding starts at a
file:line after the open finding's fields, field bullets stay on their finding, a field
line may omit the colon, and continuation prose never replaces a list item's subject.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(changelog): GSTA-167 fragment adds round 6 and the collect and consumer-scan fixes
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
---------
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
|
||
|
|
53522b1bbc |
v1.91.342.0 ship-policy: gstack versions its own PRs at merge time (changelog_fragments on; GSTA-154 P) (#3654)
* captain: train land per slot under changelog_fragments (skill and skills.md) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * ship-policy: turn changelog_fragments on for gstack (required checks, key version 1.91.336.0); mergeChangelogs keeps a stacked child's only line inside its released parent's list Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * review fixes: a carried child entry never repeats a released parent line; min_gstack_version 1.91.340.0; required-check names as GitHub reports them Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
5532345a10 |
v1.91.341.0 fix(ubicloud): no zombie VMs: owner required, 3h TTL, legacy sweep, leftover line (GST-118) (#3652)
* fix(ubicloud): no zombie VMs — owner required, 3h TTL, legacy sweep, UBICLOUD left line (GST-118) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test: extend ubicloud runner and pregate-remote coverage (legacy-hours override, --keep, leak exit status, missing left= line) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes (TTL checks only on create, leftover line via UBI_LEFT_FILE, pregate TTL from its deadline) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: name UBI_OWNER as a prerequisite for test:ubicloud and the keyed remote pregate Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * chore: changelog for GST-118 (unreleased) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test: give the left-file parser spawnSync a timeout (spawnsync tripwire) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(ubicloud): legacy sweep reaps only the caller's own TTL-less VMs (GST-324) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * v1.91.341.0 stamp Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
1bd2330350 |
v1.91.318.0 test(skill-evals): office-hours eval tasks for the shared skill eval; /write-skill diet locks tasks before a paid run (GSTA-142) (#3550)
* test(skill-evals): office-hours contract tasks and sidecar; diet lock step; contract notes (GSTA-142) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * chore: CHANGELOG [Unreleased] for office-hours eval tasks and the diet lock step (GSTA-142) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: /write-skill diet summary names the lock step (GSTA-142) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: office-hours seed excludes .gstack-home before the first commit; tighter pushback and builder patterns Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
415e343b52 |
v1.91.298.0 chore: remove Dia from gstack (cookie source and qualification harness) (#3551)
* chore: remove Dia from gstack (cookie source and qualification harness) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test: pin the removed Dia harness so pregate selects a lane for its deleted scripts Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: CHANGELOG names every doc the Dia removal touched Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
a14c28aca7 |
v1.91.289.0 feat: skill diet pilots for plan-design-review, office-hours and design-review (GSTA-134) (#3525)
* feat(plan-design-review): skill diet (GSTA-134 pilot 1) SKILL.md 66,063 -> 56,209 B (claude host); review-sections.md 52,243 -> 50,183 B. Cut model-known prose (cognitive patterns, verbose designer prose, duplicated formatting rules); UX principles kept as a five-line Krug summary after the blind judge showed wayfinding loss without it. Section layout unchanged: autoplan's methodology snapshot requires review-sections.md as the only indexed section. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * feat(office-hours): skill diet (GSTA-134 pilot 2) Moves the Phase 3.5 Codex second opinion and the Phase 4.25 visual design (designer mockups / HTML sketch) out of the eager SKILL.md into on-demand sections behind STOP pointers; the CODEX_SECOND_OPINION, DESIGN_MOCKUP and DESIGN_SKETCH resolvers are untouched. Claude-host SKILL.md 73,248 -> 43,885 bytes. skill-diet before/after (Opus, 9 tasks x 3): success 26/27 -> 27/27, median tokens per successful run 170,197 -> 124,941; blind judge after 10, before 5 of 15. YC pitch, flattery and promo text unchanged (sections byte-identical to main). Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * feat(design-review): skill diet (GSTA-134 pilot 3) Moves the outside voices and the test-framework bootstrap into on-demand sections (the bootstrap now loads at Phase 8e.5, its only consumer: a JS-behavior fix that needs a regression test with no known test command), replaces the UX principles block with a Krug summary, and tightens the DESIGN_METHODOLOGY prose (design-review is its only consumer). Shared resolvers TEST_BOOTSTRAP and DESIGN_OUTSIDE_VOICES are untouched. Claude-host SKILL.md 115,947 -> 84,869 bytes. skill-diet before/after (Opus, 12 tasks x 3): success 32/36 -> 34/36, median tokens per successful run 326,662 -> 257,819; blind judge after 9, before 5, tie 1. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test: re-pin size, context and carve guards for the GSTA-134 skill diets Every pin moves down except office-hours' parity maxSizeRatio (1.1796 -> 1.1921, GStack Minder's call as merge-queue owner): its union grew 1,662 B because the second-opinion question now sits in the skeleton while the untouched CODEX_SECOND_OPINION resolver keeps its own copy. design-review leaves the size allowlist on every host. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: drop the stale <affected-url> placeholder after the design-review Phase 8d diet Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: design-review checklist headers count the items they list after the diet Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: design-review report path and UX_PRINCIPLES consumers after the skill diets Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * chore: CHANGELOG [Unreleased] for the GSTA-134 skill diets Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
7204a39a27 |
v1.91.287.0 feat(write-skill): write, change and diet skills; /learn at half its template size (#3524)
* test(skill-evals): /learn before/after tasks, written before any cut (GSTA-133) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(learnings): --help, unknown-flag errors and --stats on the learnings bins; cross-project search no longer drops every project when the state root path contains the slug Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * refactor(learn): diet /learn onto the levels: tool flags replace the inline stats program, one mode table, prune rules kept Skill-Diet: learn Skill-Size: 5797→2586 bytes (SKILL.md.tmpl) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * feat(write-skill): /write-skill skill, gstack-skill-bill, static skill-to-bin drift ratchet, shared skill eval contract Skill-Size: 0→3245 bytes (write-skill/SKILL.md.tmpl) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(learn): guard the state-root lookup in Prune; re-measure the learn ceiling Skill-Size: 2586→2707 bytes (learn/SKILL.md.tmpl) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes (drift scanner, learnings flags, skill-bill baselines, eval fixtures) - skill-bin-drift: a redirect no longer ends a command, so `bin/x 2>/dev/null --bogus` is checked - gstack-learnings-search: a missing value or a non-positive --limit exits 2 like an unknown flag - gstack-skill-bill: the gstack root skill is a checkout skill; Skill-Diet trailers match the exact name; the baseline counts the committed bytes untrimmed - skill-evals task files get a free contract test and are registered in FREE_FIXTURES, with the drift allowlist - learn eval: the no-code-change safety task no longer asks the model to fix code (its check penalised obeying the user) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(learn,write-skill): full bin paths in the mode table; prune asks per entry unless the request names the action Skill-Diet: learn Skill-Size: 2707→2955 bytes (learn/SKILL.md.tmpl) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(changelog): /write-skill, gstack-skill-bill, drift ratchet, eval contract, /learn diet Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: drift ratchet in CONTRIBUTING's static tests; /learn prune example asks per entry Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(skill-bill): report a checkout skill's eval task file and check it against the contract The skill-evals task-file test now exercises lib/skill-bill.ts's checkEvalTasks, with a negative control, instead of a test-only validator (test-of-test ratchet). Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(skill-bill): EVAL TASKS path uses forward slashes on every platform; a non-object task entry is a problem, not a crash Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(learn): BASH_COMPAT guard on in-window heredocs; count skill-e2e-write-skill in the paid census Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
737e5a239e |
v1.91.285.0 docs(captain): plan before build — a sized /autoplan is a building lane's first act, the owner's word gates the build (#3521)
* docs(captain): plan before build — a sized /autoplan is a building lane's first act, the owner's word gates the build (GSTA-130) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(capy skill): Plan, approve, ship — the Capy-wide short form (autoplan sized to the work, ELI5 with rec and do it, APPROVED before the build, /ship at the final head, no merge without the owner's word) (GSTA-130) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(changelog): restore the full history; the Unreleased block had been written over a truncated read (GSTA-130) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(capy skill): tighten Plan, approve, ship to one-line bullets so the Capy skill stays under its 4120-token eager ceiling (GSTA-130) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes — import --by takes the owner alone, the controller checks the row against its relay, brief.md spells the full answer command and carries the run dir, first act after the install check (GSTA-130) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(captain): name the lane brief in the template lists; fix two template command lines docs/skills.md and docs/PROJECT_STRUCTURE.md enumerate captain/templates/ and omitted brief.md (document-release audit gsta130-docs-1). brief.md's restore line now names the checkpoint dir that resume --from takes, and plan-ask.md's answer line carries --rec-hash like brief.md (ship review pass 2). Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
10b77de4f2 |
v1.91.284.0 feat(absorb-tstack): /modernize skill, per-skill Codex default prompts, gstack-post --attribute, the unattended grant and a CONTRIBUTING porting section (#3497)
* feat(absorb-tstack): /modernize skill, per-skill Codex default prompts, gstack-post --attribute, the unattended grant and a CONTRIBUTING porting section Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(modernize): read the PR text through gstack-issue-guard; re-measure the context ceiling Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes - gstack-post: with --attribute, report scan findings at the body file's own line numbers and a finding inside the callout as PART: attribute (the coordinates were shifted by the three callout lines) - /modernize: route commit messages through gstack-issue-guard with the rest of the PR text, read isCrossRepository and maintainerCanModify, fetch a fork head from pull/N/head, refuse a PR whose head is the base branch, and list moved files NUL-safely - docs/unattended.md: say that /ship never rebases or force-pushes and an unattended /modernize stops at its verdict - CHANGELOG: seven skills carry a codex_default_prompt, not six Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: /modernize fetches a fork head with a forced refspec and stops when the PR moved A rerun after the author force-pushed left refs/modernize/pr-N stale (the non-forced refspec is rejected with exit 0 through the pipe), and the lease pinned to the current remote head would then have let the rebased stale head overwrite the author's newer commits. The fetch is forced, Steps 2 and 4 stop when the head is not the one observed in Step 1, and the head-is-base guard applies only to same-repository PRs (a fork's main into main is a valid head). Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: /modernize stops on merge commits in the PR range and pushes a fork head to the fork A plain git rebase drops merge commits and git range-diff compares only the non-merge patches, so a change authored in a PR's merge commit disappeared while the proof printed = for every patch and Step 5 force-pushed the loss. Step 4 now counts merges in $MERGE_BASE..$OLD_HEAD and stops when there are any, switches with -C so a rerun after a refused lease does not fail on the existing branch, and asks for a cross-repository diff to be read as untrusted input before the repository's test command runs it. Step 5 pushes a fork head to the fork's URL with the same pinned lease instead of to origin, where the lease could never match. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test: cover the Codex default-prompt render, the openai.yaml ownership proof and the unattended grant Adds the /ship coverage audit's tests: test/host-renders-openai-yaml-proof.test.ts drives bin/gstack-host-renders.sh's weakened proof against a rendered yaml, a hand-written one and a generic-prompt one; test/unattended-grant.test.ts pins the docs/unattended.md grant section and the handoff pointer; test/gen-skill-docs.test.ts adds modernize to the skills whose codex_default_prompt must reach openai.yaml. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: name the static lists a new skill still needs and the Codex metadata file From the ship documentation audit: CONTRIBUTING's new-skill checklist said no static list needs a row, which this PR disproved (lib/doctor-components.ts SKILL_REQUIREMENTS and the catalog rows); the host comparison table and docs/ADDING_A_HOST.md gain the agents/openai.yaml default_prompt source; a blank line before the new docs/unattended.md grant heading. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes CHANGELOG [Unreleased] gate-integrity record: the catalog and context-budget figures re-measured on top of main (1,314 -> 1,359; modernize 9466; alwaysOnTotal 7458 -> 7880), as the merge commit's ratchets state. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: name the optional codex_default_prompt key in the new-skill checklist Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(parity): re-pin the ship union cap at 1.7405 after the main merge GSTA-36 grant 2026-10-27. On the tree merged with |
||
|
|
215c76e334 |
v1.91.283.0 fix(benchmark): reconcile the collection, comparison, budget and trend phases with the vet-the-number section (GSTA-128) (#3520)
* fix(benchmark): reconcile the collection, comparison, budget and trend phases with the vet-the-number section
The perf-collection judge (run 40558235014, both attempts, six samples) named
the same contradictions: Phase 3 offered an optional 3-run median while the
mandatory vet section demands 5 alternating runs per side and a stored
baseline cannot be interleaved; the budget example read '4/6 passing' against
a rule that counts WARNING as below budget; the trend table showed Grade and
Bundle columns no stored file defined; Phase 9 named two files with no
contents. Phase 3 now runs 5 per page with median and range and names
--quick as the one-run ballpark; the baseline schema carries runs and
range_ms; Phase 5 says how the seven questions apply against a stored
baseline (compare the delta with both spreads, name the limiter from Phase 6,
inconclusive when either side is one run); the grade example counts 3 PASS,
1 WARNING, 2 FAIL; Phase 8 reads the benchmark and baseline JSON files by
timestamp; Phase 9 defines the JSON as the Phase 4 object plus grade, verdict
and per-metric status. Nearby prose tightened so the skeleton stays under its
31,300-byte cap (31,290). Judge after the repair: clarity, completeness and
actionability 4/4/4 on all three samples, twice.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* changelog: /benchmark phases reconciled with the vet-the-number section (GSTA-128)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: /benchmark runs five times per page in docs/skills.md
Step 14.5 of /ship on #3520: the /benchmark section said 'Multiple runs averaged' and
'3 runs each'; it now matches Phase 3 (five runs per page, median with range, --quick a
single-run ballpark). GSTA-128.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* RESTAMP: 1.91.282.0 -> 1.91.283.0 (stamped; queue_mode=stamp-at-merge base=origin/main@9ccb5233f309 policy=base origin/main@9ccb5233f309:.gstack/ship-policy.json)
ship, next in queue at 1.91.283.0
STAMP_VERSION: 1.91.283.0
claims: ignored (stamp-at-merge)
stage version: done (wrote 1.91.283.0)
stage release_tool: done (bun scripts/gen-agents-digest.ts)
stage changelog: done (Unreleased -> 1.91.283.0)
stage stamp_paths: skipped (no tentative mention newer than the fork version 1.91.281.0 and none of base 1.91.282.0 on a line this branch added)
stage mirror: skipped (no mirror in policy)
stage apply: done (4 file(s))
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 695e20bd5..15162a5d0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,6 @@
# Changelog
-## [Unreleased]
+## [1.91.283.0] - 2026-10-27
**/benchmark's collection, comparison, budget and trend phases now agree with its vet-the-number section.** The 2026-10-27 flaky pass (GSTA-128) read the `benchmark/SKILL.md perf collection` judge's six samples from run 40558235014: every sample named the same contradictions, so the prose was repaired and no threshold moved.
diff --git a/VERSION b/VERSION
index 269b6e89c..0b68a0506 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.91.282.0
+1.91.283.0
diff --git a/agents-digest/gstack-AGENTS.md b/agents-digest/gstack-AGENTS.md
index 583844b7e..894898db8 100644
--- a/agents-digest/gstack-AGENTS.md
+++ b/agents-digest/gstack-AGENTS.md
@@ -1,4 +1,4 @@
-# gstack digest v1.91.282.0 — regenerate/re-copy after upgrading gstack
+# gstack digest v1.91.283.0 — regenerate/re-copy after upgrading gstack
Behavioral rules from gstack (https://github.com/garrytan/gstack), compressed
for agent hosts without a full skill install. The full skills add workflows,
diff --git a/node_modules b/node_modules
new file mode 120000
index 000000000..858ae29ce
--- /dev/null
+++ b/node_modules
@@ -0,0 +1 @@
+/workspace/gstack/node_modules
\ No newline at end of file
diff --git a/package.json b/package.json
index 66ec462ee..da0b87294 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "gstack",
- "version": "1.91.282",
+ "version": "1.91.283",
"description": "Garry's Stack — Claude Code skills + fast headless browser. One repo, one install, entire AI engineering workflow.",
"license": "MIT",
"type": "module",
FILES: CHANGELOG.md VERSION agents-digest/gstack-AGENTS.md package.json
MERGE_CONDITION: sha=aa8c07b76935d91ec548fb5a32fd429392f88460
next: NEW_VERSION=1.91.283.0; commit and push only the stamp diff above (FILES), with no edit of your own: the train's verify accepts the CHANGELOG only as the base's plus this PR's entry re-headed; merge with the expected head
|
||
|
|
b3e94a3f8d |
v1.91.279.0 eval:select exemptions and ETHOS.md registration (#3499), below-floor review rulings (#3504, #3485), Windows curation, GSTA-121 follow-ups (#3515)
* Eval selection exemptions, review-floor rulings and the GSTA-121 follow-ups Release metadata (NOTICE.md, LICENSE, licenses/**) no longer restores the full paid gate and ETHOS.md is registered under the two prompts that read it (#3499). docs/review-policy.md records the six finding classes #3485 and #3504 ruled below the floor and the review army's lead judgment applies the table; the floor itself is unchanged. The Windows curation moves test/pregate-remote-stamp-only.test.ts to KNOWN_WINDOWS_INCOMPATIBLE (#3485). From GSTA-121: Blast radius in docs/skills.md and the merge-ask template, the 11-digit run-id exemption from pii.phone.e164 after a run word, relative string literals as import-graph edges, and a ubi-runner pack that never tars the live .git. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes Red Team pass 1 (all below the floor): an 11-digit span with a leading 1 after a run word is a US or Chinese national number, not a run id, and reports again; ubi-runner pack removes its temporary repository when it fails and replays branch.* with remote.* so a branch's upstream resolves on the VM; the conservative-refusal example in docs/review-policy.md reads in the refusing direction; the touchfiles header names why ETHOS.md sits only under the two prompts that quote it. Step 6's selection found captain/templates/merge-ask.md as the one unknown dependency of this PR and registered captain/templates/** in FREE_ONLY_PR_FILES (#3499). Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes (pass 2) The cmd_pack EXIT trap bakes the temp path in: a set -e failure unwinds the function before the trap runs and a local $tmp is unset there, so the old form leaked the snapshot. The leak test creates TMPDIR where the pack reads it and asserts the failure is the missing index. CHANGELOG examples no longer spell a full national number. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: adversarial review fixes The pack snapshot carries the index's staged blobs as a pack of their own, so a VM write-tree (gstack-wtree) can read a staged file the way the old .git tar allowed; git init runs with --template= and gc.auto=0 and a valueless remote/branch key replays as true. scripts/harness-version.json re-pins scripts/test-pr-profile.ts after the captain/templates/** entry. The run-id exemption reads the same way in the scanner and gstack-post: an 11-digit span after a run word is a run id (the leading-1 exclusion from the Red Team pass contradicted gstack-post's tested contract and the ruling that a run id is not a phone number), with the residual named in the comment, the docs and the CHANGELOG. The #3499 pins move to their own test so the boundary test stays under its default budget. Docs audit: TESTING_INTERNALS names RELEASE_METADATA_FILES and captain/templates/**, docs/captain.md names Blast radius. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes (pass 4) The pack's staged-blob list comes from the copied index, holds only blobs staged against HEAD (not every tracked blob), skips gitlinks whose commit the superproject lacks, and dies with its own message when pack-objects fails. The live-checkout test covers a gitlink entry and a valueless remote key replayed as true. CHANGELOG names the staged-blob carry. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes (pass 5) The pack's blob list is the copied index's blobs that HEAD's tree lacks, so an intent-to-add entry's empty blob and the stages of an unmerged entry travel too (the HEAD-only diff list dropped both); gitlinks still skip. The live-checkout test adds an intent-to-add entry, which the VM fsck assertion covers. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
c2e01e4ba7 |
v1.91.264.0 feat(design-motion): new /design-motion skill for showcase loops, adapted from Elaya's design-to-motion (GSTA-92 phase 2) (#3430)
* feat(design-html): craft section and free craft check, adapted from Elaya design skills (GSTA-92) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(GSTA-92): restore the full CHANGELOG under the Unreleased entry; drop a $-digit literal from craft.md; count only craft-check executions in design-html-slop-gate Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * feat(design-motion): new /design-motion skill: showcase MP4 and GIF loops from a design, adapted from Elaya design-to-motion (GSTA-92 phase 2) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(design-motion): run design-motion-showcase in the marathon tier; the periodic census is at its 38-slice cap (GSTA-92) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(design-motion): review and QA fixes before ship - encode: refuse unknown options and --formats tokens, validate --pad (#RRGGBB[AA]) and --crop (compare too) so nothing but a colour or crop reaches ffmpeg's filter graph - encode: export refuses a capture with missing window frames; check prints MOTION_SETTINGS for any threshold/phase override; contact sheet drops -fps_mode - capture: portrait-aware scale, --cycle must be whole 60 fps frames, stills with CSS animations disabled, pauseAt tolerates slow loads, clears stale manifest/stills - skill: <motion-dir> placeholder instead of a cross-block shell variable, GSTACK_FFMPEG-aware probe, stop points before the first capture, doctrine fixes - tests: refusal rows, portrait scale, cycle guard Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(design-motion): capture-check-export pipeline on real Chromium and ffmpeg Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(design-motion): second review cycle - capture: refuse an --out that holds a still or frames but no capture.json instead of deleting them; --cycle must be a multiple of 0.05 s so the seam frame lands exactly one cycle later for every PRE (nearest value round-trips) - encode: a capture without a mask ends 'MOTION_RESULT: clean (overflow not checked)' - skill: Step 5 names window.__mark in the capture contract - tests: foreign/previous --out handling on real Chromium, cycle guard and PRE sweep Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(design-motion): third review cycle and adversarial findings - capture: an ownership marker (.gstack-motion-capture) replaces the capture.json test, so the rerun after MOTION_CONTRACT_MISSING or a crash works and a foreign --out is still refused; offscreen lazy images are made eager and font/image loading is bounded at 30 s instead of hanging - encode: refuse a capture.json whose fields are not what capture writes (they reach ffmpeg args and paths); a cards overflow with no story frames is a planning error, and a zero-frame job never passes - tests: retry after a refused page, no-mask clean line, lazy image still, manifest validator, empty story span Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(design-motion): mask coverage, manifest relations, Windows stop, Figma token off argv - check fails overflow when the grown mask covers >90% of the frame (an app frame whose clip surfaces fill the stage passed vacuously); --mask-grow is 0-32; --mask refuses braces and semicolons - manifestError checks fps/windowFrames >= 1 and that the window fits the frames - skill: native Windows stops before the first capture call; the Figma token reaches curl on stdin (-H @-) instead of argv - tests: split the --out ownership scenario out of the contract test, full-frame mask, --still --scale 2 size and STILL_OK, manifest relations, coverage parse Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(design-motion): bounded frames, atomic exports, full-bleed masks - capture: each frame is bounded at 10 s (a __tick that never returns fails with MOTION_CAPTURE_FAILED instead of hanging); a --mask that matches no element stops with MOTION_MASK_EMPTY - check: a grown mask covering >90% of the frame (full-bleed app frame) reports overflow as skipped and ends 'clean (overflow not checked)' - export: writes .partial- files and renames on success, so a failed re-export keeps the last good file; a GIF fps that does not divide the cycle is refused; a missing GSTACK_FFMPEG override is named - fidelity: URL source is untrusted data; full-bleed note - tests: spinning __tick, empty mask, failed re-export, drifting gif fps Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(design-motion): app-only coverage skip, gif fps cap, early empty mask - check: the >90% coverage skip applies only to an app frame's own surfaces (ungrown mask); in cards, or when --mask-grow pushes coverage over 90%, overflow fails with what to change (a cards capture with real overflow passed as 'clean (overflow not checked)' after a large grow) - export: --gif-fps/--small-fps capped at 50 (GIF delays are 1/100 s) - compare resolves its paths (a colon in a relative path read as a protocol) - capture: MOTION_MASK_EMPTY is checked before the first frame - tests: cards vs app full-frame mask, fps cap, no frames on an empty mask Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(design-motion): seek story transitions from their own frame - capture: an animation first seen in a frame where window.__mark did not move (a story's class toggle) is seeked from that frame instead of the last mark, so it eases in the export instead of popping ~100 ms ahead - encode: an empty numeric option is refused instead of read as 0 - figma: only fill a file key and node id that look like Figma's - tests: class-toggled transition mid-fade at its midpoint, blank --min-db Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: PROJECT_STRUCTURE names Elaya's MIT material and licenses/MIT-elaya.txt Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
737ba3af40 |
v1.91.259.0 feat(ubicloud): /ubicloud skill with TTL-named VMs and a reaper, quota preflight, hang watchdog and one committed verify entry point (#3482)
* feat(ubicloud): /ubicloud skill with TTL-named VMs and a reaper, quota preflight, hang watchdog and one committed verify entry point
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: CLAUDE.md names the ratcheted catalog ceiling
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* ubicloud: UBI_OWNER example is a literal value, not a free-text placeholder (INV-3 fence lint)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* ubicloud: the UBI_OWNER example is a neutral value (no thread codes in product prose)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* ubicloud: verify trusts the checkout only, watched commands keep stdin and end the remote session, quota and reap outcomes
verify: .gstack/ubicloud.json is repository content, so its setup script and
pull destinations must resolve inside --src (absolute, ~ and .. refused before
any API call) and a name it lists under pass is forwarded only when the command
line grants it (--pass NAME or --trust-config); --pass never forwards UBICLOUD_*
and refuses non-names. watched: the caller's stdin reaches the remote command,
a command that finished while the clock was read is not a timeout, a hung setup
exits 124, INT/TERM take the ssh session down, and the watchdog ends the
command's session on the VM (setsid + ~/.ubirun-<phase>.sid + pkill -s). Quota:
a cached refusal maximum is trusted for a day, the refusal names its source and
uses the 'vCPU quota exhausted' marker pregate-remote.sh retries on. reap:
returns 1 on a failed list or destroy; TTL suffixes read in base 10 and
UBI_TTL_HOURS takes 0-999. Tests: a fake API that creates plus a fake ssh run
'run' and 'verify' end to end.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* ubicloud: the remote session file is per runner invocation and setsid is optional on the image
Two watched commands on one VM wrote the same ~/.ubirun-<phase>.sid, so a cancel
could end the other's session; the file now carries the runner's pid and is
removed when the command ends. An image without setsid runs the command through
plain bash instead of failing with exit 127.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* ubicloud: pull destinations are rechecked at pull time, verify parses options by arity, a finished command keeps its status, the remote sid outlives the wrapper; docs audit
Pass-2 (Codex adversarial on the delta): an earlier pull could plant a symlink
where a later config pull lands, so under verify every destination is resolved
again (symlinks followed) right before its pull and a refused pull exits 1;
'--dest --trust-config' made an option value act as the trust flag, so verify
parses by arity; a command that finished in the instant before the watchdog's
kill exited 0 and was still reported as 124; the wrapper removed the sid file
while a background child kept the channel open, so the file now stays until
remote_cancel reads it. Docs audit (document-release, edit mode): TTL suffix and
owner rule in TESTING_INTERNALS, the reaper as the exception to 'no sweep', the
docs/skills.md transcript uses a neutral owner; CHANGELOG and the runner header
corrected on the two points it deferred.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* ubicloud: a refused pull destination creates no directory, inside or outside the checkout
inside_dir checked containment after mkdir -p, so a destination under a planted
symlink (escape/new/sub) created the outside directories before being refused.
The nearest existing ancestor is checked first; only an accepted destination is
created, and it is checked again after.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test: bin/gstack-ubi has a test lane (it execs the runner and forwards arguments)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* ubicloud: pack ships a linked worktree with a self-contained .git
A worktree's .git is a gitdir pointer into the main repository; on the VM git
could not run, so the remote pregate refused with PREGATE_VM_TREE_MISMATCH
vm=unavailable. pack now replaces it with a bare --single-branch clone of the
checked-out branch (core.bare false, the worktree's index copied in), ~45 MB for
gstack; a detached worktree is refused with the fix named.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test: take main's host-conformance C3 fix (#3479) so the remote gate can run on this tree
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* ubicloud: pack skips a split index (its shared half stays in the original git dir)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* CHANGELOG: restore main's released history under the [Unreleased] block (the merge resolution kept only the conflicted span)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* RESTAMP: 1.91.258.0 -> 1.91.259.0 (stamped; queue_mode=stamp-at-merge base=origin/main@7dc2f23192b7 policy=base origin/main@7dc2f23192b7:.gstack/ship-policy.json)
ship, next in queue at 1.91.259.0
STAMP_VERSION: 1.91.259.0
claims: ignored (stamp-at-merge)
stage version: done (wrote 1.91.259.0)
stage release_tool: done (bun scripts/gen-agents-digest.ts)
stage changelog: done (Unreleased -> 1.91.259.0)
stage stamp_paths: skipped (no stamp_paths in policy)
stage mirror: skipped (no mirror in policy)
stage apply: done (4 file(s))
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3c91fdaf8..e4f4d63ec 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,6 @@
# Changelog
-## [Unreleased]
+## [1.91.259.0] - 2026-10-26
**New `/ubicloud` skill: the Ubicloud runner moves into gstack with the discipline a shared vCPU quota needs.** Crews ran heavy suites on Ubicloud through a user-scope skill and per-lane wrappers, and paid for it in stray VMs after a machine slept, a project quota at 528 of 512 vCPUs when lanes verified in parallel, verifies that hung for an hour before anyone noticed, and a stale wrapper that skipped a service start. `scripts/ubicloud/ubi-runner.sh` now carries the fixes and `ubicloud/SKILL.md` (entry point `bin/gstack-ubi`) teaches the watched launch; `bun run test:ubicloud` and the remote pregate are unchanged.
diff --git a/VERSION b/VERSION
index c67e9e442..08528ff87 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.91.258.0
+1.91.259.0
diff --git a/agents-digest/gstack-AGENTS.md b/agents-digest/gstack-AGENTS.md
index 4bd43c922..203312cf5 100644
--- a/agents-digest/gstack-AGENTS.md
+++ b/agents-digest/gstack-AGENTS.md
@@ -1,4 +1,4 @@
-# gstack digest v1.91.258.0 — regenerate/re-copy after upgrading gstack
+# gstack digest v1.91.259.0 — regenerate/re-copy after upgrading gstack
Behavioral rules from gstack (https://github.com/garrytan/gstack), compressed
for agent hosts without a full skill install. The full skills add workflows,
diff --git a/node_modules b/node_modules
new file mode 120000
index 000000000..c7990ad12
--- /dev/null
+++ b/node_modules
@@ -0,0 +1 @@
+/workspace/gstack-ubi/node_modules
\ No newline at end of file
diff --git a/package.json b/package.json
index 5e6d56827..0eca459a0 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "gstack",
- "version": "1.91.258",
+ "version": "1.91.259",
"description": "Garry's Stack — Claude Code skills + fast headless browser. One repo, one install, entire AI engineering workflow.",
"license": "MIT",
"type": "module",
FILES: CHANGELOG.md VERSION agents-digest/gstack-AGENTS.md package.json
MERGE_CONDITION: sha=76e86e08a851fb1a19bef9a947bdf0abeb87956d
next: NEW_VERSION=1.91.259.0; commit and push only the stamp diff above (FILES), with no edit of your own: the train's verify accepts the CHANGELOG only as the base's plus this PR's entry re-headed; merge with the expected head
|
||
|
|
4d48d39e51 |
v1.91.253.0 feat(captain): /captain skill (also /crew), crew templates and docs/captain.md for running a crew from one controller (#3473)
* feat(captain): /captain skill (also /crew), crew templates and docs/captain.md for running a crew from one controller Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * chore(captain): regenerate SKILL.md at main's version Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * feat(captain): AGENTS.md and NOTES.md templates, roles, ship lane sequence, owner device and lessons loop in docs/captain.md; owner-brief closes with the do-it reply Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(captain): review pass 1: 'do it' parses as rec, READY template matches the tool's lines, slot-2 and freeze wording, mergeChangelogs named, parameter lists and doc numbers aligned Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(captain): align the slot-call BASE merge, freeze repair and severe-race wording across skill, CREW.md and docs; router routes on phrases; receipt head width as printed Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * feat(captain): CREW.md template becomes pointers plus parameters; every crew rule gets a canonical home in gstack (lane discipline, outside contributions, stale READYs, standing spend, the lane side of flaky reruns in docs/captain.md; the rule-to-home map) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
021d817c36 |
v1.91.240.0 feat(proactive): default to the four core skills (core | all | off), with docs, prompt and tests (GSTA-99) (#3432)
* feat(proactive): default to the four core skills (core | all | off); docs, prompt and tests (GSTA-99) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(proactive): gstack-skill-start falls back to core, not true, when gstack-config is missing The PROACTIVE status line's fallback literal still said true (= all) after the default moved to core. Found by /ship's coverage audit; the regression test fails at the previous head and passes at main. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(proactive): STATUS line carries the stored value; every surface names the same core four and three values Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(proactive): off gates the office-hours handoff; the preamble and router scope the setting to unasked suggestions The office-hours next-review handoff gated on the legacy false only, so an off user was still asked to launch /plan-eng-review. The per-skill preamble now says the setting governs unasked suggestions and this skill's own steps still run (a handoff, a review gate, a dispatched /document-release is not a suggestion), at exactly the previous length, so the 89 size pins return to main's values; the router says the same in full. Found by /ship's specialist and red-team review. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(skill-start): unknown proactive values read as core; first-run tips name core skills and stay quiet under off A hand-edited config can hold any value and only set validates, so STATUS normalizes anything but core|all|off|true|false to core. The first-run and first-loop tips named /spec, /investigate and /plan-eng-review whatever the setting; they now name the core four and are skipped under off. The fallback regression test folds into test/proactive-skill-start.test.ts, the duplicate header assertion leaves proactive-config, and the frozen-length preamble test is retired (the size guard enforces it). Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(proactive): scope note, the unknown-value rule, and the CLAUDE.md routing follow-up; CHANGELOG Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(skill-start): no CLAUDE.md routing offer under proactive off The one-time offer to append ## Skill routing to the project's CLAUDE.md fired whatever the proactive value, and its rules are the auto-invocation an off user turned off. The offer is skipped under off and the legacy false; a section already in CLAUDE.md is left alone. Under core the offered section still routes every skill, which docs/proactive.md records as the follow-up. Found by /ship's red team. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(proactive): STATUS says only core | all | off, and the preamble carves out only named skills gstack-skill-start reads the legacy true/false as all/off and tolerates a quoted, upper-case or commented hand edit (proactive: OFF # mine read as core before), so every surface sees one of three values and the off gating lives in one flag. The per-skill preamble drops the legacy spellings and replaces 'This skill's steps still run', which licensed any in-skill offer under off, with 'Skills the user or this skill's steps name run', at the same length, so the 89 size pins stay at main's. Tests run the script for the tips and the routing offer under core and off instead of grepping the source. Found by /ship's fix-range repeat (red team, testing, maintainability). Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(config): set proactive is case-insensitive; follow-up #3446 cited; test hygiene set proactive OFF warned and stored core, the opposite of the opt-out typed; the value is lowercased first, as gstack-skill-start does for a hand edit. The fixture git init carries the tripwire timeout, the source-shape assertion on the private _PROACTIVE_OFF line goes (the routing-offer test proves the behavior), and the CHANGELOG Tests bullets collapse to one per file with the known gap pointing at #3446. Found by /ship's full repeat pass and its tests lane. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(proactive): a stored off answers the one-time prompt; the router names /browse and /investigate under core instead of invoking them Red team, full repeat pass: with proactive: off stored before the prompt, skill-start still emitted the opt-in prompt; it now writes the marker and asks nothing. The router's Route-first browser step and the Failures branches invoked non-core skills under core while the core block said to answer directly; one sentence in the core block resolves it, pinned by the core-set tests. CHANGELOG and docs/proactive.md say both. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(proactive): the full-catalog skill descriptions are the second surface that still routes every skill under core (#3446) From /ship's document-release audit: a --catalog-mode=full build and the non-Claude hosts keep the "Proactively suggest when ..." description sentences, which do not follow the setting; the default Claude build trims them. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(proactive): the tips test runs skill-start as an interactive session GitHub CI sets CI/GITHUB_ACTIONS, which gstack-session-kind reads as headless, and a headless start skips first-task detection, so the first-run tip never fires there (Free Tests shard 16 red at 0d7dbe6; green locally and on the Ubicloud pregate, which have no CI marker). The fixture now sets CLAUDE_CODE_ENTRYPOINT=cli, the positive interactive signal; reproduced locally with CI=1 and fixed. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(proactive): an opt-out never fails open; the preamble carves out invocations, not offers The YAML yes/no family (yes/on/1, no/none/0/disabled/never) reads as all/off in both gstack-skill-start and gstack-config set, so a typed or hand-edited opt-out cannot land on core. The per-skill preamble says "Skills the user names or this one invokes run" (same 168-char length, pins unchanged): a skill dispatching another is not a suggestion, an in-skill offer to run one still is under off. The stored-off prompt marker is written before STATUS prints PROACTIVE_PROMPTED, so the line is true. docs/proactive.md's table row carves out in-skill handoffs. Fourth /ship fix cycle, past the skill's three-cycle cap by GStack Minder's decision (2026-10-26) under Garry's "do it" on the proactive core set; items from the Step 11 adversarial pass. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * v1.91.240.0 stamp Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
4814b3d8a4 |
v1.91.230.0 feat(design-shotgun,design-html): archetype handoff and persisted craft exceptions (GSTA-92 phase 2) (#3422)
* feat(design-html): craft section and free craft check, adapted from Elaya design skills (GSTA-92) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(GSTA-92): restore the full CHANGELOG under the Unreleased entry; drop a $-digit literal from craft.md; count only craft-check executions in design-html-slop-gate Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * feat(design-shotgun,design-html): carry the chosen archetype into approved.json; persist accepted craft exceptions in finalized.json (GSTA-92 phase 2) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(touchfiles): design-html-slop-gate selects on the craft check it runs (GSTA-92) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: pre-landing review fixes (GSTA-92) A malformed or missing --accepted exceptions file now gets the full craft check with nothing accepted, after a warning, still exiting 2. Before, it printed nothing, and the craft section treats a missing CRAFT_RESULT as 'check unavailable', so one bad finalized.json switched the gate off (found by both adversarial passes). The header comment and the craft section now document the accepted-count suffix on CRAFT_RESULT. Tests cover duplicate carried-forward exception ids and the slop-gate touchfiles selection. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix: scope --accepted to the same page; record current counts (GSTA-92) The craft section passed --accepted whenever a finalized.json sat beside the page, so a same-day Start fresh build inherited the old page's exceptions. It now passes them only when evolving or rerunning a page it finalized, records the count the check reports now, and writes [] when nothing was accepted instead of the template's placeholder entry. A test pins exit 2 for a clean page with a broken exceptions file. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: note the archetype handoff in the shotgun and design-html loops (GSTA-92) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
71b007ae7c |
v1.91.160.0 fix(scope,review,ship): recognise Dart and Flutter in diff scope and test detection (#3284) (#3300)
* fix(scope,review,ship): recognise Dart and Flutter in diff scope and test detection (#3284) Port of arlophoenix's #3284 onto current main, squashed: - gstack-diff-scope: .dart is frontend and backend; pubspec.lock is config. - lib/frontend-scope.ts mirrors the frontend half; gstack-design-detect never sends .dart to the impeccable engine. - Test bootstrap, coverage audits and review-army detect Dart/Flutter (RUNTIME:dart, FRAMEWORK:flutter, dart_test.yaml, *_test.dart). - Adversarial DIFF_SIZE sums git diff --numstat. On top of the contributor's diff: shorten the bootstrap's ecosystem-marker comment so /design-review stays at its SKILL.md size pin, lower the 31 pins that shrank, and add the CHANGELOG entry. Co-authored-by: arlophoenix <arlo.phoenix@gmail.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * v1.91.160.0 fix(scope,review,ship): recognise Dart and Flutter in diff scope and test detection (#3300) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: arlophoenix <arlo.phoenix@gmail.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
afac8dfd87 |
v1.91.151.0 fix: contributor ports — plan-eng-review structure id, context checkpoint gaps, first-deploy how-to (#3299)
* fix(plan-eng-review): register the structure question id so never-ask can fire The complexity gate's Original/Smaller arrangement question had no registered question_id, so each run invented a per-plan slug (one install logged ten different ids for it). --check matches ids exactly, so a stored never-ask could never fire and the question was asked every time. - Register plan-eng-review-structure as a two-way routing question. - The template names that exact id and says AUTO_DECIDE picks the recommended arrangement; the preamble's check-first rule does the rest. Wording is byte-neutral against the parity budget and the per-host pins. - --check falls back to $GSTACK_HOME/global-question-preferences.json, the file the question-preference hook already reads, when the project file has no entry for the id, so one setting covers every repo and both layers agree. A project entry still wins, the one-way and split-chain guards run first, a malformed or non-object global file is ignored with a NOTE, and --write stays per-project. - Tests for the fallback and the template contract; two wording pins updated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> (cherry picked from commit |
||
|
|
bc2ed0cee7 |
v1.91.114.0 feat(dx): score every error for an AI agent reader (agent-ready error contract + gstack-error-capture) (#3226)
* feat(dx): agent-ready error contract for the DevEx review skills Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * feat(dx): gstack-error-capture runs a CLI with no terminal and prints a redacted record Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(dx): CI-clean fences, runtime-root-safe contract location, path-agnostic launch-check test Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(dx): preregistered behavior case for the agent-ready error contract; README skill rows Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(dx): grader items come from the contract; paid-file count includes the new case Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * feat(dx): outside DX voice uses the agent-ready contract; DX_CAPTURE_* codes join RESULT_CODES with troubleshooting anchors Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(dx): review fixes for gstack-error-capture and the paid grader - every helper diagnostic passes the record's redaction, fail-closed - forwarded values are masked before and after sanitizing, plus JSON-escaped forms - the final secret check reads the record's string fields with byte-based scan limits - mise/asdf config, trust and env-loading variables need --pass-env; only data locations pass by default - launch reports whether the target started; --launch-check's probe result is exit_code - Step 3 captures --help first; help states the containment lifetime limit - the paid grader validates the bound result with parseReviewResult Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(dx): mask forwarded values before argument validation; protocol strings never match literals; Step 3 captures stay read-only Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * v1.91.114.0 feat(dx): score every error for an AI agent reader (agent-ready error contract + gstack-error-capture) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
70fab3e246 |
v1.91.94.0 feat(codex): --effort <level> overrides reasoning effort for one run (#3146) (#3151)
* feat(codex): --effort <level> sets GSTACK_CODEX_EFFORT for one run /codex review --effort medium (or --effort=medium) prefixes each run-with-timeout dispatch with GSTACK_CODEX_EFFORT=<level>, which outranks codex_effort and the per-mode default; --xhigh becomes shorthand for --effort xhigh. The probe keeps owning validation. A missing value, a value that is not one lowercase word, or conflicting flags stop instead of falling back. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(codex): per-run effort prefix reaches the rendered /codex review dispatch Runs the rendered review fence against the fake codex: no prefix uses codex_effort, GSTACK_CODEX_EFFORT=medium|xhigh wins over it, an unknown level never reaches codex. Step 1 check pins --effort tokens and the stop rule. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(codex): document codex_effort and --effort; Challenge runs at high, not xhigh Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(changelog): [Unreleased] entry for /codex --effort Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(codex): --effort reaches the probe as an allowlisted request level, parsed before the mode and checked before the paid probe The level now travels as run-with-timeout --request-effort '<effort-level>' (placeholder grammar ^[a-z]*$) instead of an agent-built env prefix, and the probe names /codex --effort when it rejects one. Effort flags count only right after /codex or its mode word and are removed before mode detection. Step 0.5 runs check-effort before probe-model, so a bad level makes no Codex call even on a cold cache. Tests cover all five dispatch fences and the zero-call cases. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(codex): per-request --effort in model-policy, CHANGELOG behavior changes, TODOS follow-ups Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * chore: stamp v1.91.93.0 Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(codex): effort flags sit among /codex's leading flags; the probe names an unfilled '<effort-level>' placeholder Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs(codex): per-request row in the effort precedence table, in-tool help names /codex --effort, late-flag notice Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(codex): binding tripwire sees the request-effort dispatch; valid and unfilled levels through Step 0.5 and every fence; doc accuracy Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: John Nunemaker <nunemaker@gmail.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
5d647455f2 |
v1.91.79.0 feat(eval-plan): /eval-plan tier 1, lane-check, evidence verify, coordinator contract, owner brief, contributor-PR mode, banned terms (multi-agent wave PR E) (#3123)
* v1.91.79.0 feat(eval-plan): /eval-plan tier 1, lane-check, evidence verify, coordinator contract, owner brief, contributor-PR mode, banned terms (multi-agent wave PR E) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(spec,review): fail closed when the coordinator contract cannot be read; restore the omitted-Army sentence The spec --execute spawn captures `gstack-autoplan contract` before piping the archive, so a lane never starts without the contract; the C9 fixture installs its gstack-like checkout (bin, lib, a contract stub) at every host's global root. Review Step 5.8 keeps the pinned 'without claiming specialist coverage' wording. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
c7edf46bcf |
v1.91.47.0 fix(careful,freeze): safety hooks cover PowerShell and NotebookEdit (#3077)
* fix(careful): check PowerShell tool commands and nested pwsh/cmd (#3067) /careful and /guard matched only the Bash tool, so on Windows, where Claude Code's PowerShell tool is the primary shell, the guard never ran. check-careful.sh also had no PowerShell or cmd patterns. - careful/guard register a PowerShell matcher beside Bash. - hook-extract.sh gains gstack_hook_extract_tool: one parser call reads tool_name with the field, so dispatch adds no fork. - check-careful.sh runs one PowerShell/cmd pattern table on PowerShell tool commands and on the tail of any Bash command that launches pwsh/powershell/cmd: Remove-Item and aliases with -Recurse/-Force prefixes, rd/rmdir/del/erase /s, Format-Volume, Clear-Disk, Clear-Content, [IO.Directory]/[IO.File]::Delete, and asks with an explanation for -EncodedCommand, iex, Start-Process of a shell and & $cmd. Command-position anchors keep Bash negative controls allowed. - /careful documents the coverage as best-effort and points to Claude Code permission deny rules. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(freeze): NotebookEdit respects the freeze boundary (#3067) NotebookEdit was in no freeze/guard/investigate matcher, and check-freeze.sh read only file_path, so notebook edits ignored /freeze on every platform. NotebookEdit carries tool_input.notebook_path. - freeze, guard and investigate register a NotebookEdit matcher beside Edit and Write. - check-freeze.sh reads file_path, then notebook_path, through the shared extractor; denials name the tool, the field, the boundary and /unfreeze. A helper without the combined reader denies as out of date. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test: run hook-scripts on the Windows lane (#3067) The careful/freeze hooks are Windows coverage, but test/hook-scripts.test.ts was excluded from windows-free-tests by the raw /tmp/ pattern; its /tmp/ literals are payload strings that are never opened. Admit it by name and gate the three cases Windows runners cannot host: a symlink (no Developer Mode), a newline in a directory name, and a POSIX ':' PATH prefix. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * chore(evals): check-careful.sh is free-only for PR selection No paid fixture copies or runs careful/bin/check-careful.sh (the investigate boundary fixture copies hook-extract.sh and check-freeze.sh only); test/hook-scripts.test.ts covers it. As an unknown dependency it restored the full paid gate on every /careful hook change. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * test(careful): pin the #3067 Invoke-Sqlcmd DROP TABLE example on the PowerShell tool Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * chore(evals): record the check-careful.sh selection change as non-behavioral Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * docs: /careful covers PowerShell (best-effort), /freeze covers NotebookEdit (#3067) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * chore: release v1.91.37.0 (CHANGELOG, TODOS for deferred hook follow-ups) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * chore: re-slot release to v1.91.39.0 (v1.91.37.0 and v1.91.38.0 claimed by #3075, #3076) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * chore: re-slot release to v1.91.41.0 (merge-queue reservation) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(careful): hook payload reader survives Windows text-mode Python and backslash source paths windows-free-tests (run 37739845723) showed every PowerShell-tool case falling through: Python's text-mode stdout on Windows wrote tool_name as "PowerShell\r", so dispatch never matched, and freeze denials carried stray CRs. gstack_hook_extract_tool now reads and writes bytes. hook-extract.sh also located gstack-state-root.sh with ${BASH_SOURCE%/*}, which strips nothing when the file is sourced through a C:\... path, so gstack_hook_state_root vanished (state-root parity case on the same run). Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * fix(evals): PR lane selects office-hours-auto-mode by its real test name The PR paid lane filters audited files with -t built from CASE_TEST_NAMES[id] ?? id. office-hours-auto-mode's Bun test is named 'AskUserQuestion surfaces when --disallowedTools AskUserQuestion is set', so the filter matched 0 tests and the shard failed (#3077 eval-slices (6), run 37741434771). Map the label, and check every audited PR-profile case is addressable by name. Recorded as non-behavioral for HARNESS_VERSION. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * chore: CHANGELOG notes for the Windows CRLF and PR-lane name fixes Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * chore: re-slot release to v1.91.47.0 (merge-queue assignment) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> |
||
|
|
92cfd07a79 |
v1.91.45.0 feat: configurable model tiers and advisory freshness (#3073)
* feat: add configurable model tiers and advisory freshness * fix: disclose role selections before Claude review execution * fix: reject malformed model policies and keep model pins portable * fix: separate readiness diagnostics and bound version checks * fix: preserve actionable model failures and validate review inputs before probes * fix: retry released probe locks and retain late-rejection repair context * feat: finalize configurable model tiers and verified release repairs * fix: preserve strict model policy reads on Windows * fix: keep fixture probes read-only and clarify pending CEO decisions * fix: verify native terminal closure before bounded descriptor settlement |
||
|
|
c7554824cb |
v1.91.38.0 fix(ios-qa): iPads work, a dropped route no longer relaunches the app, loud boot-token write (#3076)
* fix(ios-qa): allow physical iPad devices in tunnel bootstrap (#2743)
(cherry picked from commit
|
||
|
|
55fbe77195 |
v1.91.24.0 test: audit wave — PR evals keep finished work, honest ceilings, EVAL_POLICY v2, faster free suite (#3031)
* 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 at |
||
|
+44 |
2db0b3adc8 |
v1.91.19.0 fix: severe fix wave (truthful gates, no lost memory, every host finds gstack) (#3025)
* docs: approved severe fix wave plan (Oct 2026) * D0: keep a project's .env and bunfig.toml out of compiled binaries and daemon children Compiled binaries are built with --no-compile-autoload-dotenv and --no-compile-autoload-bunfig; the browse server and terminal agent are spawned with --no-env-file and an empty config, so a repo's .env cannot set GSTACK_CHROMIUM_NO_SANDBOX and a bunfig preload cannot run code in them. Verified on Bun 1.4.0. * A9: --no-write is a dry run and leaves ingest state untouched --no-write stamped every prepared page ingested_at and saved state, so a later real run skipped those pages forever. It now prepares and reports pages without importing or changing the state file. Tests that used GSTACK_MEMORY_INGEST_NO_WRITE / --no-write to seed state move to an explicit seam (a fake gbrain that accepts every staged page), because the --no-write contract deliberately changes. * H #2885 #2827: vector geometry is not phone or card PII pii.phone.e164 accepts "." as a group separator, so a single float (viewBox="0 0 581.66796875 ...") and a run of path coordinates ("37.6188 101.694") read as phone numbers. pii.cc's \b stops at a decimal point, so the long fraction of an .excalidraw float is a Luhn candidate. Excalidraw's seed/versionNonce/updated integers read as bare phone numbers. A rendered /diagram triplet raised 18 (svg) and 97 (excalidraw) MEDIUM findings on main; it now raises none. - looksLikeDecimalCoordinates (ported from #2885, extended to a single decimal and refusing a leading "+", the E.164 marker) - insideDecimalNumber: a cc span glued to "<digit>." or ".<digit>" - isNumericMetadataValue: an unquoted JSON value under a seed, nonce or timestamp key; the same digits under "phone" still report Controls: E.164 in prose, dotted and spaced phones, "+"-prefixed runs, "phone"/"contact" JSON numbers, Luhn-valid cards in prose and at sentence end. Co-authored-by: Lewis <lewispeel@hotmail.com> * D1: pin the terminal-agent /ws Origin to the gstack extension (#1324) GSTACK_EXTENSION_ID moves to browse/src/extension-id.ts, shared by /extension-token and the terminal agent's /ws gate. /ws now returns 403 for every origin except the pinned extension. Forks override the ID with gstack-config set browse_extension_id <id>, honored by both routes; the BROWSE_EXTENSION_ID env var is no longer read. Test sites that used fake extension IDs now use the pinned origin. * H #2899: env.kv skips a function call assigned to a credential name `session = _FlakySession(...)`, `token = make_token(user, ...)` and `password = getpass.getpass()` raised env.kv MEDIUM, which blocks the fail-closed decision log. The exemption needs the line's evidence, not the span's shape: the value is unquoted, is an identifier or dotted path followed by "(", and the call closes on the line or opens a multi-line argument list. Quoted values, unclosed "(" inside an unquoted secret (API_SECRET=Abc123xyz(9Qm) and calls carrying a high-entropy literal argument still report. The literal check is shared with the #2912 env-read exemption. Co-authored-by: Yugz <yannduzelier@gmail.com> * H #2962: per-machine config filenames are not internal hostnames `CLAUDE.local.md` and `settings.local.json` reported internal.hostname MEDIUM (the pattern's \b stops at the dot before the extension), which fails closed in the decision log. A span immediately followed by a known config extension (.md .json .jsonc .yaml .yml .toml .ini .conf .txt) and a word boundary is a filename. Controls: `ssh build.local`, `printer.local.` at a sentence end, `printer.local/md`, `printer.local.mdx`, a host with a port, `api.corp`, `build-7.internal`. The `.env.local` vectors (#2740) pass on main already via isDotenvFilename and are pinned here as regressions. Co-authored-by: Florian <florian.cleyetmerle@gmail.com> * H #2784: four-part versions need a version declaration, not a shape `"version": "1.128.1.0"`, `<Version>`, `AssemblyVersion("1.0.0.0")` and Keep a Changelog headings raised pii.ip_public MEDIUM on every release, because a four-part version is byte-for-byte a dotted quad. Exempt only when the same line declares it a version immediately before the value (a version key or word, an XML tag, an attribute call, or a `## [x]` heading). The same digits after host:/server =/"upstream", bare on a line, or after prose that merely mentions a version still report. Unlike #2784, this does not exempt a value because the same string is declared a version elsewhere in the text: that let a real address sharing a diff with a matching version slip. The pre-push hook's VERSION-file rule (#2856) is unchanged. Co-authored-by: cdecook23 <decook23@gmail.com> * H #2913: postgres:postgres is exempt only on a loopback host The postgres image's default pair in compose files and CI DATABASE_URLs blocked pushes as db.url_with_password HIGH. It is now exempt only for postgres/postgresql URLs with exactly postgres:postgres on localhost or 127.0.0.1 (optional port). A bare single-label host (`db`, `postgres`), any other host, a host that merely starts with localhost (`localhost.evil...`, `localhost@prod-db`), any other user or password, and other schemes still block. #2913 exempted the pair on any host; this keeps the plan's narrower rule. Co-authored-by: mb1810 <michael.berger1810@gmail.com> * G1: ship without a version when no version source is configured Resolve the version source to four outcomes (valid, absent, ambiguous, broken) in lib/version-source.ts and read that one signal in gstack-version-bump (new NO_VERSION state; write refuses to invent a VERSION), gstack-next-version (no_version, no slot), /ship's bump, CHANGELOG and title steps, /land-and-deploy's drift check and /document-release. A configured version file that is missing, empty, unreadable or malformed stops with its path; 0.0.0.0 is never substituted. docs/skills.md documents .gstack/version-path. Migrates two tests that pinned the old fabricated-0.0.0.0 behavior. Co-authored-by: Koda <koda@edgeviewfinance.com.au> Co-authored-by: Merit Blake <merit@newsprint.com> * H #2949: eval credential screen checks every name segment The hermetic eval env admits GITHUB_* and EVALS_* metadata but rejects credential-shaped names, judged only by the last underscore segment. A trailing qualifier carried a credential through: GITHUB_APP_PRIVATE_KEY_BASE64, GITHUB_TOKEN_1, EVALS_API_KEY_FALLBACK reached eval children. The screen now rejects a name when any segment is a credential word; segments, not substrings, so GITHUB_PATH / GITHUB_TOKENIZER / GITHUB_KEYRING stay metadata, and explicit runner admissions still win. Co-authored-by: Nguyen Thanh Dat <ntdat812@gmail.com> * H #2915: cover chunked scanning of large multi-file push diffs Test-only coverage for behavior already on main: a clean two-file pushed diff over the engine's 1 MiB cap passes without engine.input_too_large, and a credential at the end of the second file (a later scan chunk) still blocks the push. Co-authored-by: pneumorea-ai <pneumorea@gmail.com> * A3: keep a project's DATABASE_URL away from a PGLite brain With a PGLite config, buildGbrainEnv returned the caller env unchanged, so a project's .env DATABASE_URL (autoloaded by Bun) reached gbrain: a false broken-db at best, gbrain talking to the app's own Postgres at worst. Inherited DATABASE_URL and GBRAIN_DATABASE_URL are now blanked for PGLite configs (GSTACK_RESPECT_ENV_DATABASE_URL=1 still keeps them), and every gbrain child runs from gbrain's config dir instead of the user's project, so it cannot reload the project's .env / .env.local. The old test that pinned pass-through for an engine:pglite config is migrated: pass-through now applies only to configs that name neither a database_url nor PGLite. Co-authored-by: maxpetrusenkoagent <max.petrusenko.agent@gmail.com> * C9: guard destructive gstack-upgrade and spec fences against unset or wrong paths Fresh-shell hosts (and Claude Code, which keeps cwd but not shell variables) ran cd "$INSTALL_DIR" with an empty variable, so git checkout/stash/reset targeted the user's project. Step 2 now prints an absolute path; every destructive fence starts with cd -- "${VAR:?...}" || exit 1 and checks it is gstack's own checkout before any git command. /spec's worktree and spawn fences get the same guard. * F4: keep every paid design variant across regenerate rounds $D variants now reserves a collision-safe round-<N>/ directory per run (atomic mkdir) and writes a manifest.json of what each round saved. The paid image request and the local write retry separately: a write failure retries the write (temp + rename) and, if the path stays unwritable, keeps the bytes in the temp dir instead of buying the image again. Responsive variants land in their round directory too. Readers updated: design-shotgun reserves a round dir and a private temp dir for its parallel agents and records approved_path/round in approved.json; design-html resolves approved_path (legacy letters still work) and finds round-dir variants; design-consultation checks the printed paths; the gallery shows round-dir variants. Variants that were already overwritten before this change cannot be recovered. Migrates the consultation contract test that pinned the flat path. Co-authored-by: Matt Van Horn <mvanhorn@gmail.com> * A2: stage dot-leading slugs gbrain can collect; network errors are db-unreachable A page slug segment starting with a dot (a .claude project) staged a file gbrain's import walker prunes, so the batch was refused on every run. Leading dots become "dot-" per segment, and slugs recorded in state under the old name map through the same function so no page is duplicated. A DNS or connection failure (ENOTFOUND, EAI_AGAIN, ECONNREFUSED, ...) no longer classifies as broken-db, which routed users to move a working config aside. The new db-unreachable status carries the reason "database host unreachable (<code> <host>); your gbrain config is unchanged. Fix: check network or VPN, then re-run /sync-gbrain.", skips local sync stages with that reason, and counts as usable for gstack-gbrain-detect --is-ok like timeout. Co-authored-by: Infiniteyieldai <infiniteyield.ai@gmail.com> * D2: one address classifier for navigation literals, DNS answers, redirects and page-driven navigations (#2811) classifyAddress() in url-validation.ts blocks 169.254.0.0/16 (metadata and container credential endpoints), 100.100.100.200, fe80::/10 and fc00::/7, including IPv4-mapped, IPv4-compatible and NAT64 spellings and decimal, octal and hex IPv4. validateNavigationUrl, the A/AAAA answer check and session-persist's cookie-domain guard all use it. BrowserManager now checks every navigation request (redirect hops, link clicks, scripted navigations): a blocked target resets the tab to about:blank and the write command fails with the reason. Connection-time DNS rebinding remains out of scope. Co-authored-by: Gabriel Rondon <grondon@gmail.com> * C4: external hosts point at carved sections relative to the installed skill Publishes the pointer form setup matches: on every non-Claude host a carved section is `sections/<file>` relative to the installed gstack-<skill> SKILL.md directory (QA's existing form), never $GSTACK_ROOT/<skill>/sections/, which does not exist in external runtime roots. No render changes yet: only QA is carved on external hosts today. * INV-1: gate outcome contract for outside reviews classifyOutsideReview() returns separate execution, findings and verdict fields from text, stderr and exit status; reason codes, anchors and fix actions live in lib/gate-outcomes.ts. validateOutsideReview() stays as the text-only wrapper and the two-argument CLI keeps exit 0/1/2 for importers and installed skills that predate a re-render. The --verdict form (implied by --stderr/--exit) prints VERDICT/FINDINGS/REASON and exits 0/3/4/1; the generated outside-voice caller moves to it and branches on each status (unverified prints OUTSIDE_STATUS: unverified, never completed). Adds docs/troubleshooting.md with one anchored section per reason code, the anchor test, and the gate-tail lint (query scripts may not swallow failures, gate calls may not end in || true, other best-effort tails say why). * G1: quote the base placeholder in document-release title sync The title-sync block is checked with bash -n; an unquoted <base> parses as a redirection. Migrates the test that pinned the old root VERSION read to the shared classifier call. * G3: give every logging-bin mktemp a ${TMPDIR:-/tmp} template Bare mktemp, mktemp -t and literal /tmp templates in the learnings, question and preference logs (plus jsonl-merge, distill, the two dashboards, /ship's PR body and /document-release's run dir) now use "${TMPDIR:-/tmp}/<name>.XXXXXX", the form the INV-3 lint accepts. When the temp file cannot be created, the learnings, question and preference logs now say the entry was not recorded and how to fix TMPDIR instead of exiting with only mktemp's own error. Three tests that pinned the bare PR_BODY_FILE=$(mktemp) and one that pinned the /tmp run dir migrate. GNU and BSD mktemp already honor TMPDIR without a template, so the macOS-sandbox drop in #2952 is unverified here; the template makes the temp location explicit on every mktemp. Co-authored-by: Davon Johnson <d.johnson@dayofshow.net> * B1b: structured outside-review gate fails on P0 as well as P1 validateOutsideReview() derived its structured pass/fail from a [P1] match, so a review reporting only [P0] findings passed. The wrapper now reads the classifier's findings verdict (P0 or P1), and the /review and /ship structured-gate prose requests [P0]-[P3] tags and fails on P0/P1; untagged output (OUTSIDE_STATUS: unverified) is missing coverage. The ship clarity pin moves from 'structured P1' to 'structured P0/P1' with the behavior. * E1: freeze normalizes boundary and target the same way on Windows; hooks spawn through cmd.exe (#2876, #2354) gstack_hook_normalize_path (careful/bin/hook-extract.sh) maps C:\..., c:/..., UNC \\server\share (leading // kept) and /cygdrive/c to one form; check-freeze runs both the saved boundary and file_path through it before the absolute test, after symlink resolution, and compares case-insensitively on Windows bash. freeze, guard and careful register hooks as bash -c "exec bash \"$HOME/...\"" so cmd.exe, which never expands $HOME, no longer turns the hook into a silent exit 127. Co-authored-by: Kevin Grasso <kevin@biblingo.com> Co-authored-by: Xuan-Ce Wang <261591073+xwang4-svg@users.noreply.github.com> * G4: keep CLI-to-daemon loopback calls off HTTP_PROXY (#494) The CLI appends 127.0.0.1, localhost and ::1 to the user's NO_PROXY (and no_proxy), keeping existing entries, before its first fetch. Verified on Bun 1.4.0: fetch honors NO_PROXY when it is set before the first request and ignores later changes, so it is set at the top of main(). * F1: bind the plan audit to this branch's plan, never the newest file Plan File Discovery now prefers an explicit binding (the plan-mode file or /autoplan ACTIVE_PLAN from the conversation, then a "Plan: <path>" line in the PR body), then lists candidates: repo-committed docs/designs/ files this branch changed or that name it, and personal plan files that name the branch. Candidates are offered, never picked silently. The repo-name match and the newest-file-of-the-day fallback, which audited PRs against unrelated plans, are gone. With nothing bound or chosen it prints the exact line 'Plan completion audit: not run (...). Fix: add "Plan: <path>" to the PR body, or run /autoplan.' /ship's parent now binds the plan before dispatching the audit subagent ({{PLAN_COMPLETION_GATE_SHIP:discovery}}), so the child never searches. Migrates three tests that pinned the old markers and notice. Co-authored-by: loulanyue <260355617@qq.com> * G5: browse type --selector <sel> <text> (#2936) --selector focuses the element (sel or @ref) and types into it. The bare form still types its text literally into the focused element; text that starts with -- goes after a -- separator. When the first word looks like a CSS selector, the result adds a hint to use --selector without echoing the typed text, and never refuses based on page contents. Help and command usage updated. Co-authored-by: Thomas Reuser <thomasreuser@gmail.com> * F2: design-doc discovery reads docs/designs, never a root DESIGN.md A root DESIGN.md is the design system /design-consultation writes, so preferring it unconditionally reviewed plans against a token file while printing "Design doc found" and never looked at docs/designs/ feature docs. Discovery now considers only docs/designs/*.md as the repo-local design doc (still freshness-compared with the private ~/.gstack copy). The CEO finding fixture seeds its supplied design as a docs/designs doc and its test follows. Co-authored-by: Bit0ps <alex.dreamscaper@gmail.com> * C4: rename the external carve test (typecheck:test union-order artifact) tsc prints a union's members in type-creation order; a test file sorting before ceo-mode-option.test.ts reordered one baseline diagnostic's text. * C1: every env-var host fence resolves its own gstack root Codex and the other env-var hosts run each block in a fresh shell, so GSTACK_ROOT/BIN, B and D set by the preamble were empty in later blocks (/bin/gstack-slug, B=/browse). scripts/resolvers/runtime-root.ts now owns root resolution: a valid exported GSTACK_ROOT (bin/ and lib/), else the per-install literal root (no git call), else repo-local, else the global root (CODEX_HOME on Codex); no root prints the setup fix line and exits. One post-render pass inserts it (<=400 bytes) into every fence that uses these variables without assigning them; B/D come from the same helper as BROWSE and DESIGN SETUP. Claude output is byte-identical. Migrated pins of the old preamble lines (gen-skill-docs.test.ts) and a fixture whose exported GSTACK_ROOT lacked lib/ (skill-positional-literals). * E8: headless browse honors GSTACK_CHROMIUM_PATH; extensions load in new headless mode (#2771, #1968, #2281) The headless launch passes GSTACK_CHROMIUM_PATH as executablePath, scopes the XProtect self-heal out for that bundle, and names the path in a launch failure with the fix. BROWSE_EXTENSIONS_DIR now launches a persistent context under the project state dir with --headless=new, so the extension runs and no window appears (the off-screen window was visible on macOS and the extension never ran in an isolated newContext). The GPU source guard test moves from the removed useHeadless flag to launch() vs launchHeaded(). Co-authored-by: oli548 <312288720+oli548@users.noreply.github.com> Co-authored-by: Slava <slava.istomin@tuta.io> Co-authored-by: ryanlaiwy <129729476+ryanlaiwy@users.noreply.github.com> Co-authored-by: 李翊楠 <yinanli1917@gmail.com> * C2: link design/dist and make-pdf/dist into every host runtime root and the agents sidecar Codex design and make-pdf skills fall back to $GSTACK_DESIGN and $GSTACK_MAKE_PDF under the runtime root, but setup linked only browse/dist, so both preflights reported NOT_AVAILABLE on a fresh install. One helper links dist/ only (make-pdf/ ships a Claude SKILL.md) into the Codex, Factory, OpenCode, Cursor, Copilot and Kiro roots, the .agents sidecar and the Cursor sidecar. Co-authored-by: Mammad M. <mammad@digit.az> * C3: install router and nested SKILL.md files as real copies; back up hand edits; --status checks Codex skips a symlinked SKILL.md file, so the gstack router linked into ~/.codex/skills/gstack was invisible. Every host runtime root (Codex, Factory, OpenCode, Cursor, Copilot, Kiro) and Kiro's per-skill installs now get real copies, rewritten on every run (the auto-update path runs setup --refresh-registered, so it refreshes them too). setup records each copy's hash in <state root>/skill-copies.tsv; a copy that no longer matches is saved to a uniquely named backup under <state root>/backups/skill-copies/ before _activate_runtime_root replaces the tree, and a failed backup keeps the old tree. setup prints what it refreshed or removed. ./setup --status now prints, per registered install, whether the router is a real file and whether every section pointer resolves, with the fix command. Test migration: setup-codex-model pinned the Kiro router/upgrade links as _link_or_copy; C3 deliberately changes them to copies. * INV-3: install-level host conformance checks (no symlinked SKILL.md, dist present, section pointers resolve) For codex, kiro, factory, opencode, cursor and copilot, the real-setup conformance kit now fails when an installed SKILL.md is a symlink, when design/dist or make-pdf/dist is missing from the runtime root, or when a 'Read `.../sections/<f>.md`' pointer in an installed SKILL.md does not resolve (bare pointers in carved skills, relative-to-installed-skill pointers, and $GSTACK_ROOT/~/absolute/../ pointers everywhere), and ./setup --status must report 'all resolve'. No new setup runs. Expected red until the generator lane lands: design-html's install-offer pointer and plan-eng-review's review-sections pointer name $GSTACK_ROOT/<skill>/sections/... on every external host. * B11: auto-update tracks pull, setup and migrations; announces only on success; retries with backoff gstack-session-update wrote the 'just upgraded' marker after SETUP_FAILED or SETUP_SKIPPED bun_missing, and re-ran setup only when HEAD moved, so a failed install was announced as an upgrade and never retried. Stages are now persisted in <state root>/session-update-pending; the marker is written only when every stage succeeded; a pending setup or migrations stage is retried even with HEAD unchanged after the update-check interval, then 6h, then 24h; and each session start prints one line naming the stage, the reason and the repair command while it is pending. Best-effort tails carry a same-line reason. * D1: gstack-config key browse_extension_id for forks and self-built extensions The browse daemon trusts one Chrome extension ID on /extension-token and the terminal-agent /ws. The override now lives only in gstack-config (never an env var a project .env could set): empty by default (gstack's published extension), a 32-letter a-p Chrome ID when set, "" clears it, and anything else is rejected with the stored value kept. The browse lane reads it. gstack-config-defaults: browse/src counts as a reader directory; the key is listed prose-only until the browse lane's reader lands (the stale-entry check then asks for the entry's removal). * G2: key the sticky slug cache on the git common dir A linked worktree used to resolve its slug fresh from the remote while the main checkout kept its sticky pre-remote identity, so learnings, checkpoints and timelines split into two buckets. gstack-slug and its TS twin in lib/bin-context.ts now key the cache on the git common dir (read from .git files, no git spawn, so cache hits stay git-free) and read entries in one deterministic order: the repository entry, then the main checkout's pre-upgrade entry, then this directory's own. Both the repository and per-path entries are written. When a worktree's own old entry named a different bucket that still holds data, that slug is recorded in projects/<slug>/.former-slugs and reported by --get FORMER_SLUGS. New --adopt-legacy --from <slug> merges it: JSONL logs append missing lines with de-duplication, missing files copy, differing files are listed as conflicts and never overwritten, the source bucket is kept, and it prints migrated/pending/conflicting counts; reruns are idempotent. --adopt-legacy --dismiss <slug> drops the reminder. Co-authored-by: loulanyue <260355617@qq.com> * C5: OpenCode /gstack-* commands load the skill by its frontmatter name OpenCode's skill tool knows gstack-review as `review` (its frontmatter name), and OpenCode's builtin /review shadows that name as a command. The managed /gstack-review command told the agent to load `gstack-review`, a name the skill tool does not list. Every managed command now names the frontmatter name. OpenCode's AskUserQuestion/ExitPlanMode mapping (#2759) already shipped in v1.91.16.0. Test migration: the #2629 commands test pinned the directory name. Co-authored-by: Lockyer <135391289+Lockyer228@users.noreply.github.com> * E4: Windows node-server bundle keeps sharp and socks external; CLI resolves its server script lazily (#2260, #2439) build-node-server.sh passes --external sharp and --external socks (Bun on Windows refuses to inline them; on Linux they were silently inlined). The CLI no longer resolves server.ts or server-node.mjs at module load: resolveServerLaunch() runs when a server starts, so a Windows minimal runtime with only server-node.mjs works and a missing script is reported only when one is needed. Co-authored-by: Spooks444 <193448029+Spooks444@users.noreply.github.com> Co-authored-by: punksterlabs <77217235+punksterlabs@users.noreply.github.com> * B1: Codex reviews whose sandbox could not start are unavailable, not a pass In containers without unprivileged user namespaces every Codex command fails, yet the review exits 0 and concludes 'no findings' (captured in test/fixtures/codex-sandbox/). The validator now takes execution evidence: 'codex exec --json' command events and the 'codex review' stderr transcript (a command that succeeded proves execution); sandbox failure lines on stderr or in failed command output return unavailable(sandbox_unavailable); exact 'could not run commands / read the diff' phrases are the last fallback. Review text that merely discusses bwrap or namespaces still passes. A free 'codex sandbox ... true' preflight (Linux, 10 s) runs before the paid model probe and every automatic outside review; CODEX_MODE gains sandbox_unavailable, and an inconclusive model probe reports unverified instead of ready (exit code kept for stale callers). Every Codex site (outside-voice resolver, /codex review, challenge, consult) takes its sandbox from _GSTACK_CODEX_SANDBOX and pipes its result through the validator; a static test parses rendered command positions for both. GSTACK_CODEX_NO_SANDBOX=1 (exactly 1, shell env only) switches to danger-full-access with a warning on every use. Sandbox pins in existing tests move from the literal read-only to the selected-sandbox variable; captured autoplan probes are judged against the probe block they executed. * C6: gstack-relink discovers skills structurally, so /browse survives a skill_prefix toggle relink skipped a hardcoded list of support-directory names that included browse, a real skill, so toggling skill_prefix removed /browse. A top-level directory is now a skill exactly when it carries a SKILL.md. Co-authored-by: Jonathan Zhang <topcoder1@Mac-Studio.local> * C4: carve ship and plan-ceo-review on every host; enforce the 160 KB byte gate The generated ship skill was 202-241 KB on all 10 non-Claude hosts (and Factory plan-ceo-review 160,039 bytes), over the 160,000-byte ceiling, because section carving ran only for Claude. Both skills now carve on every host, pointing at sections relative to the installed skill directory (literal $GSTACK_ROOT/<skill>/sections refs are rewritten the same way). The ceiling is measured in UTF-8 bytes and fails generation in repo mode; under --install-root it warns so setup never leaves a user without skills. qa-lazy-sections.test.ts pinned ship as inline-on-external-hosts; migrated to the carved policy and kept the inline check on review (Claude-only carve). * B5: learnings and timeline reads fail loudly when bun is missing gstack-learnings-search and gstack-timeline-read ended in '2>/dev/null || exit 0', so a missing bun or a crashed embedded script printed nothing and exited 0, identical to 'nothing recorded'. Both now exit 127 with '<script>: bun not found on PATH, so ... could not be read. Fix: install Bun (https://bun.sh), then re-run ./setup.' and let an embedded-script failure exit non-zero with its stderr. A successful run with no matches still exits 0 with empty output. The generated callers that print 'LEARNINGS: unavailable (...)' belong to the generator lane. Co-authored-by: loulanyue <260355617@qq.com> * B2: a retired-model 404 reports MODEL_UNUSABLE, not CODEX_MODE: ready The model probe matched only 400 / 'is not supported', so a retired model's 404 ('does not exist or you do not have access to it') and a custom provider's bare 404 fell through to the inconclusive branch and reported ready. Both now classify as MODEL_UNUSABLE with a hint naming the two causes (retired model, or a wrong base_url) and log codex_model_retired; a 'requires a newer version of Codex' 400 points at upgrading the CLI and logs codex_cli_outdated. Ported from #2843 onto the current probe. Co-authored-by: Marek Cermak <marek.cermak@strv.com> * B6: rank learnings by matched query tokens and disclose truncation A more specific query used to drop the exact match: the token-OR filter recalled every entry sharing one token, the sort used confidence alone, and the default --limit cut silently. Entries now rank by how many distinct query tokens they match, then confidence, then recency, and a query that matched more than fit says '-- N more matched, raise --limit to see them'. The hit count lives in a local map so a field stored on disk can never become a sort key, and the type grouping uses a null-prototype map so a row typed 'constructor' or '__proto__' cannot crash the run. Ranking code ported from #2796; regression vectors adapted from #2799 (its stemmer is not needed). Co-authored-by: loulanyue <260355617@qq.com> Co-authored-by: y$un_ <forrest.sun527@gmail.com> * C7: required team mode also blocks Copilot CLI's lowercase skill tool Copilot CLI applies Claude-format matchers by tool name; its skill tool is `skill`, which no Claude tool name maps to, so the 'Skill' matcher never fired and Copilot ran protected skills without gstack. The hook entry now matches 'Skill|skill', an entry an older team-init wrote is upgraded in place, and the deny is emitted in both decision formats (Copilot reads the top-level permissionDecision, Claude Code reads hookSpecificOutput) with exit 0 so both parse it. Test migration: the settings test pinned matcher 'Skill'. Co-authored-by: neallee <neallee@gmail.com> * B3: Codex auth probe accepts custom providers' env_key credentials The auth probe only knew CODEX_API_KEY, OPENAI_API_KEY and auth.json, so a working self-hosted or OpenAI-compatible provider configured with [model_providers.<id>] env_key = "X" reported AUTH_FAILED and /codex stopped. The probe now reads env_key from model_providers tables only (comments ignored, the name must be a shell identifier before it is dereferenced) and accepts a set variable; when none is set it names the missing key on stderr. Ported from #2192 with the table scoping added. Co-authored-by: hardy <932821449@qq.com> * E8: keep the extensions profile under the state dir at a path lock cleanup accepts cleanSingletonLocks only cleans directories named chromium-profile, so the BROWSE_EXTENSIONS_DIR profile moves to <state>/extensions/chromium-profile. * B10: plan-tune never reports CALIBRATED with zero signal events Stats printed CALIBRATED: true from logged-answer counts alone, while every answer could miss SIGNAL_MAP and leave each dimension at its 0.5 seed (#2623). --derive now records inferred.signal_events, the answers that actually moved a dimension; calibration requires at least one, and the summary prints 'not calibrated: no recorded signals' verbatim when there are none (or says the count is unknown for a profile derived before this change). The psychographic redesign stays out of scope. * A1: verify gbrain landing before stamping transcripts, plus --reconcile gbrain import exits 0 while skipping pages (returned per-file failures, malformed filenames, managed-import Pending receipts), and its failure ledger exists only for git import dirs, so a skipped page was stamped ingested and never retried (field reports: 37 and 69 lost entries). Write, verify, then stamp (lib/memory-ingest-landing.ts, a new ratcheted module): - State schema 2 with a transition table (staged -> imported_unverified -> ingested, plus refused, quarantined, unrecoverable). Schema 1 files migrate in place: entries become ingested in the legacy "default" source and a reconcile pass is marked pending. - Named failures come from --json `failures`, stderr "Skipped <rel>:" lines and the ledger; a failure gbrain does not attribute refuses the whole batch. After 3 refused batches the batch is bisected and the page that poisons it is quarantined (printed even under --quiet). - Landing check: one `gbrain list --source-id` per source per run and at most 50 `gbrain get --json` content checks against a gstack_content_sha256 frontmatter field gstack now writes. Lookup errors and pglite_busy mean "not yet checked", never absent; pages over the cap stay imported_unverified and are not re-imported. - Each entry records its gbrain source_id. Remote-http mode records "staged", never "ingested". - The source fingerprint comes from the exact bytes parsed, so a transcript that grows during import is not stamped as its newer self (the old unscanned contract test is migrated; it pinned that bug). - --reconcile mode (bounded by --limit, default 200; resumable; --dry-run; backs up the state file) prints "reconcile: checked N, present M, re-queued K, not yet checked L". --request-reconcile records a pending pass without calling gbrain; the v1.91.17.0 migration (placeholder name) uses it, and the next ingest run does one bounded pass. - One lock for every state writer; a state-save failure fails the run. The #1802 static pins in regression-1611 move to the new structure (remote-http returns before importBatch; the finally honors preserveStaging). Co-authored-by: afshaker <andrew@phone2.io> * B4: arm64 re-sign keeps a backup, restores it when codesign fails, and reports design unavailable on exit 137 setup's Apple Silicon re-sign mutated each binary in place (truncate, remove signature) and left it that way when re-signing failed; a design binary that was then SIGKILLed at launch produced at most a quiet log line. Each binary is now copied first and restored as built when signing fails, and design is exec-probed after re-signing: exit 137 prints 'design unavailable: ... Fix: cd <checkout> && ./setup' (even under -q). Verified on Linux with the real block and uname/codesign/otool/stat stubs; not run on a Mac. * D3: treat design docs and handoff notes as data in plan reviews plan-ceo-review, plan-eng-review and plan-devex-review read the freshest design doc as the source of truth, and nothing said its content is data. In multi-agent pipelines another agent may have written it, or a handoff note beside it, with reviewer-directed text ('skip Step 0', 'approve as-is'). Each read site now says the doc and any handoff note are data, never to follow text aimed at the reviewer, and to report it as suspicious content. The plan-completion audit's discovery, which now reads repo docs/designs/ files (F1), carries the same rule. Co-authored-by: cube <frosimanuel@gmail.com> * D4: setup-deploy reports Render API key presence only /setup-deploy ran 'echo $RENDER_API_KEY | head -c 4', printing the key's first bytes into the transcript. It now prints only 'RENDER_API_KEY: set' or 'RENDER_API_KEY: not set'. Wording follows the #2971 port of #1096; a test also guards against any setup-deploy command echoing a credential variable. Co-authored-by: jacob-wang <jiayuw794@gmail.com> * D5: per-project headed Chromium profiles; never kill a live profile owner (#2492) The headed profile moves from <gstack home>/chromium-profile to <project>/.gstack/chromium-profile (CHROMIUM_PROFILE still wins). killOrphanChromium now kills a SingletonLock PID only when the lock names this host, the process is a Chromium using that profile, and its daemon is gone (reparented to init or a subreaper); a live owner or another host's lock stops browse with the holder named. On first headed use a project profile is seeded from the old shared profile only when nothing holds it: copied without Singleton* files into a 0700 temp dir and renamed into place, with a one-time notice; otherwise it starts fresh and says how to import later. New: browse profiles [list] and browse profiles prune [--days N] (never removes a profile in use or the old shared one). The #2817 headed-startup tests move to the project profile and a real orphan (the old stand-in was a live child of the test). Co-authored-by: miao <miao@macmini-2.local> * F5: installed Claude skills serve the rendered sections, not the checkout copies Probe: a gbrain user render serves ship/SKILL.md from the render dir; its STOP pointers name absolute render paths, but its section index names `sections/<f>.md` relative to the installed skill directory, whose sections/ was linked from the checkout. So the rendered 'Save Results to Brain' blocks (plan reviews, office-hours, ship adversarial) were generated and never read. setup's _link_skill_runtime_assets and gstack-relink (the gbrain-refresh path) now serve a rendered counterpart per file, keep checkout-only assets (manifest.json), return an asset to the checkout once its render is gone, and never touch an entry that is not gstack's links. Co-authored-by: Jonah Berg <jonah.berg.g@gmail.com> * F1: ratchet /ship's parity union-size cap for this lane's content G1's NO_VERSION arms, F1's parent-side plan binding and D3's data line add 2,126 bytes to /ship's skeleton-plus-sections union, taking it from 1.4022x to 1.4135x of the v1.64.1.0 baseline (cap was 1.405). The cap moves to 1.414 with the measurement recorded, as earlier growth did; no other invariant changes. * E5: feed every Codex prompt on stdin instead of argv Prompts went to Codex as one argv string ('codex exec "$(cat file)"'), which fails over 32 KB on Windows (and over 128 KB on Linux, E2BIG) and mangles quotes. Every codex exec site (outside-voice resolver, /codex review custom instructions, challenge, consult new and resume) now runs 'codex exec -' with the prepared prompt file on stdin; challenge and consult write the prompt with a quoted heredoc so it is never shell-parsed. The bash-native timeout watchdog (stock macOS) started the command in the background, which gives it /dev/null as stdin; it now passes the caller's stdin through. The 'byte for byte' dispatch test drops its old argv trailing-LF exception, the consultation and autoplan fixtures follow the stdin form, and the static site test requires stdin at every rendered codex exec. * G6: prettyscreenshot --hide keeps a trailing image path as the output path (#1419) --hide collected every following non-flag argument as a selector, so the output path was hidden instead of written to. A trailing argument that looks like a path or ends in .png/.jpg/.jpeg/.webp is now the output path. Co-authored-by: Jayesh Betala <jayesh.betala7@gmail.com> * INV-3: render-level host conformance and generated-bash lint on every host One render per host checks every fence of every SKILL.md and section file: bash -n with angle-bracket placeholders normalized; the env-var host prelude and its B/D consumers run under env -i and set -u with stub binaries (no empty value, no /bin/, /browse, /design or /gstack- path); and a quote-aware lint (test/helpers/generated-bash-lint.ts) fails on a ~/ word inside double quotes, mktemp without a TMPDIR-respecting template, and cd/rm -r/mv/git -C on a variable the fence never assigned unless written ${VAR:?...} (cd must also handle failure). Negative controls plant each failure. Templated the bare mktemp calls in generator-owned resolvers and the upgrade fence; migrated the two tests that pinned the bare form. * G6: analytics averages quoted duration_s values (#1728) gstack-skill-end writes duration_s as a quoted string, and the per-skill average stripped everything from the leading quote, so every average read 0s. The awk now drops a leading quote before extracting digits. Co-authored-by: Ryan Alberts <ryan.a.alberts@gmail.com> * G6: gstack-ios-qa-daemon --help prints usage instead of starting the daemon (#1932) Co-authored-by: maxpetrusenkoagent <max.petrusenko.agent@gmail.com> * G1: tighten /ship's NO_VERSION wording to fit the union-size cap Same behavior in fewer bytes: the NO_VERSION arm, the broken-source exit, the unprefixed-title rule, the Step 20 null and the CHANGELOG skip. The cap ratchet commit measured this wording. * G6: rejected taste preferences gain confidence (#1777) bumpPref computed every entry's confidence from approved_count, so a rejected entry, which never gains approvals, stayed at 0: show ranked rejections by insertion order and the taste-drift warning could not fire from real use. Confidence now uses the entry's own bucket count. Also salvaged by Garry's #2971. Co-authored-by: Jayesh Betala <jayesh.betala7@gmail.com> * E2: Windows /cso build disables only C5105, and a failed MSVC compile is not reported as a missing toolchain The Windows SDK's winbase.h raises C5105, which /W4 /WX promotes to error C2220, so every MSVC build of the native /cso helper failed, and setup mapped every probe failure to 'install Visual Studio 2022 Build Tools'. Both compile lines add /wd5105 (only that diagnostic), and setup keeps the probe's output: a probe that found MSVC but failed to compile reports windows-msvc-compile with the compiler's first error. Not run on Windows: the mapping test stubs powershell.exe; the ps1 assertion runs everywhere. Co-authored-by: AlinValentin7 <AlinValentin7@users.noreply.github.com> * E6: gbrain-refresh hands the detection file to Python on stdin Under Git Bash, a native Windows Python first on PATH cannot open an MSYS /c/... path, so gbrain-refresh always summarized the detection as 'local-status: unknown' and brain-aware blocks were suppressed. bash now opens the file and Python reads stdin; the grep fallback without Python is unchanged. Verified on Linux with a stub Python that refuses path opens; not run on Windows. Co-authored-by: maxpetrusenkoagent <max.petrusenko.agent@gmail.com> * G6: context-save computes session duration on Linux (#2704) The duration step parsed 'ps -o lstart=' with BSD-only 'date -jf', so on Linux session_duration_s was always unknown. It now falls back to GNU 'date -d', and never parses an empty start (GNU reads that as midnight). Ported onto the current block instead of #2704's ~/.gstack/sessions mtime, which bypassed the state root. Co-authored-by: Evgenii Lopatin <e75533@gmail.com> * Q2: one-time notice naming the Codex provider and account for outside reviews Outside reviews are on by default and use whatever Codex login exists (#965). The first automatic Codex review on a machine now prints one non-blocking notice: the provider (config.toml model_provider, else openai), where the credential comes from (CODEX_API_KEY, OPENAI_API_KEY, the ChatGPT login or the key saved by codex login; never the value), that reviews stay on, and how to turn them off (gstack-config set codex_reviews disabled). A marker in the gstack state root keeps it to once per machine. Tests that run the generated command now use private state roots. Also shortens the no-sandbox provenance line. * Q1: validate browser output paths the way the kernel resolves them (#2971 salvage) validateOutputPath walks the destination one component at a time, resolving each existing component before the next, so link/../x, a dangling symlink and a dangling symlinked parent can no longer route a write outside the safe directories, while a new multi-level directory inside them is allowed. scrape validates its manifest and every downloaded file, not only --dir. Ported from PR #2971 onto current code. * G6: retro test census counts non-JS suites, skips generated output The census recognized only JS/TS-style names, so pytest and minitest (test_*.py|rb), XCTest (Tests/ dirs, FooTests.swift), Terraform (*.tftest.hcl) and Bats (*.bats) suites counted as zero, and a committed build directory counted as authored code (and its Test/ subdirs as test LOC). is_test now knows those conventions and never treats prose as a test, generated output is skipped in the numstat pass, TEST_FILES_CHANGED uses is_test, and TEST_FILES_TOTAL uses the same filename conventions minus generated paths. Merges #2812, #2809 and #2037's patterns (#2037's retro template edits target a block the metrics bin replaced). Co-authored-by: Jino <dgfrty00@gmail.com> Co-authored-by: snig-17 <santosh.m.tiwari@gmail.com> Co-authored-by: Sholto McNeilage <sholto@nodenarrative.com.au> * Q3: setup stops auto-installing the AskUserQuestion preference hook in Conductor and removes one it added The PreToolUse question-preference hook breaks Conductor's native AskUserQuestion round-trip even when it only defers (#2207), and setup auto-installed it on every Conductor workspace setup. Now a Conductor setup without an explicit opt-in never installs it and removes an existing one (the question-log and AUQ-error hooks stay), printing how to keep it (gstack-config set plan_tune_hooks yes). An explicit opt-in still installs it. gstack-settings-hook remove-source gains --event to scope the removal. Test migration: setup-plan-tune-hooks-noninteractive pinned the retired Conductor auto-opt-in. Co-authored-by: Phil Hie <philhie@outlook.com> * E5: watchdog stdin test feeds the wrapper through a redirect Callers run '_gstack_codex_timeout_wrapper ... codex exec - < file'. Bash keeps stdin for a backgrounded command inside a pipeline but not behind a redirect, so the pipe form passed on the old watchdog; the redirect form reproduces the lost prompt. * F4: type the variant-round fetch stub like the existing stubs The test-typecheck ratchet flagged the zero-argument stub cast to typeof fetch; it now takes the fetch arguments like variants-retry-after's stub. Test behavior unchanged. * A4: import transcripts into per-repository, non-federated gbrain sources `gbrain import` ran without --source-id, so transcripts from every project landed in the shared (often federated) default source. - Each transcript partition imports with --source-id into its originating repository's own source (gstack-transcripts-<repo>, built with constrainSourceId, now exported from lib/gbrain-sources.ts). The source is registered machine-local and --no-federated before its first import, and the registration is cached in state. Partitions import one after another (PGLite is a single writer); a failing source no longer blocks the others, except a timeout, whose checkpoint must survive. - If gbrain cannot register the source, that partition stays local and unstamped, and the run says why (even under --quiet). - --include-unattributed sends repo-less transcripts only to the machine-local gstack-transcripts-unattributed source, keeps them on the machine when the brain is remote (Postgres, Supabase or remote-HTTP), and never writes them to the publishable ~/.gstack/transcripts staging. - A page's recorded source is sticky: pages stamped before this release ("default") keep importing there, so no source gains a duplicate. - The staging dir name carries -src-<id> so a resumed import keeps its source. Test fakes that recorded only the last import now record every import of one run, and answer `gbrain sources`; remote-http scan tests use an attributed transcript, since unattributed ones no longer stage there. Co-authored-by: Sinabina <sinabina@Sinabinas-MacBook-Pro-4.local> * F3: load the taste profile, and report a failed slug lookup The taste-profile probe double-quoted ~/.claude/.../gstack-slug, so the tilde never expanded and /design-consultation and /design-shotgun always printed NO_TASTE_PROFILE. Use quoteSafePath(); stop hiding gstack-slug's stderr and print TASTE_PROFILE_UNAVAILABLE with the fix when the slug cannot be resolved. * B4: DESIGN_READY only when the design binary actually starts DESIGN SETUP (and office-hours' visual exploration) printed DESIGN_READY for any executable binary, so one SIGKILLed at launch by an invalid macOS code signature still passed. Launch it under the portable 10-second deadline (gtimeout, timeout, or perl alarm); otherwise print DESIGN_NOT_AVAILABLE with the exit code, 'timed out after 10s', or on 137 the code-signature hint and 'Fix: cd <checkout> && ./setup'. A success is cached by inode and mtime under the state root so Gatekeeper's first-launch scan is paid once. The probe launches the binary with no arguments (usage, exit 0): the design CLI has no --version command today. * C2: name the runtime root every way a generated preflight may read it in the dist test The generator lane's C1 resolves D from $GSTACK_ROOT instead of $GSTACK_DESIGN, so the test now exports GSTACK_ROOT as well; it still fails on main (no dist in the roots) and passes with and without the C1 change. * A5: brain-sync stage fails loud when the artifacts source indexed zero pages The stage reported "curated artifacts pushed" whenever gstack-brain-sync exited 0, but a git push is not gbrain indexing. After a successful push the stage now reads the maintained artifacts source's page count (GSTACK_BRAIN_SOURCE_ID, else the source whose path is the artifacts worktree or state root): zero pages is ERR with the fix command; a missing source or an unavailable count says so instead of claiming indexing. Co-authored-by: Jimmy Zeisweiss <4261258+jzeisweiss@users.noreply.github.com> * B1: state the effective read-only sandbox in /codex review prose The codex parity invariant requires the skill to state sandbox_mode="read-only"; the command now takes it from _GSTACK_CODEX_SANDBOX, so the prose names the effective default explicitly. * A6: report deleted-worktree gbrain sources; prune only with proof, on request A deleted Conductor worktree leaves its gstack-code-<hash> source behind and gbrain's autopilot fails on it forever. Local absence is not proof a source is dead (machines sharing a federated brain register their own paths, and its pages may be the only copy of uncommitted work), so gstack never removes one automatically. - Each sync counts consecutive misses for gstack code sources whose path is missing, prints "path unavailable" once per source with the review command, and records which repository each synced source belongs to. - New gstack-gbrain-sync --prune-gone-worktrees (with --dry-run, whose plan it always prints first) removes a source only when its path was missing on two consecutive syncs, its parent is readable, recomputing deriveCodeSourceId() for that path on this host yields its id, and the repository's git common dir still exists and no longer lists the worktree. It re-checks the path right before removing (through the #1734-guarded safeSourcesRemove) and logs each removal. * D0: pass the Bun child flags after 'run' so wrappers that rewrite 'bun run' argv keep working bun run --no-env-file --config=/dev/null <script> has the same effect (verified on Bun 1.4.0) and keeps argv[1] === 'run', which the publication-lock fixture's preload injection relies on. The sidebar-tabs source guard now expects the flags in the terminal-agent spawn. * E8: count the BROWSE_EXTENSIONS_DIR persistent launch in the signal-flags guard The new launch site carries handleSIGINT/SIGTERM/SIGHUP false like the other three, so the guard's expected count moves from 3 to 4. * D2: give the memory-leak reproducer's fake request isNavigationRequest() wirePageEvents now runs the navigation guard on every request event; the fake request adapter supplies the method real Playwright requests have. * A7: run only the resolve_symbol_edges dream phase, detected first /sync-gbrain --dream and the --full auto-build ran gbrain's full dream cycle (~35 minutes, LLM phases) when the call graph needs only the resolve_symbol_edges phase. The stage now runs gbrain dream [--source <id>] --phase resolve_symbol_edges when the installed gbrain accepts that phase (detected by behavior: gbrain validates --phase before printing --help). Otherwise it skips the forced dream and says the full cycle costs about 35 minutes and how to run it, instead of starting it. Co-authored-by: liutiming <timingliu@outlook.com> * D0: keep the dotenv isolation test runnable on the Windows lane The compiled probe gets its .exe name on Windows, and the terminal-agent case (owner identity comes from ps) is skipped there. * B9: read cycle_freshness from a doctor run that includes it /sync-gbrain Step 3.5 and the --full auto-dream decision read CYCLE from gbrain doctor --json --fast, which skips the DB checks that carry cycle_freshness, so the answer was always "unknown". Both now read gbrain doctor --json --scope=brain (DB checks, no skill-file walk), parse its JSON even when doctor exits 1 for a failing check, and match the issue that names this source: "never completed" is never, "last cycled Nh ago" is completed. When the installed gbrain does not report the check, they say "unknown: installed gbrain does not expose cycle_freshness" (lib readCycleStatus carries the reason to the --full SKIP row). The source-probe fixture that pinned the --fast call and a made-up message format now answers --scope=brain with gbrain's real message. * B4: compact the launch probe (cache keyed on inode, valid while newer than the binary) Keeps design-consultation inside its parity size budget. * C4: migrate the ship docs-dispatch test to the carved external ship On Codex and Factory the documentation dispatch now lives in sections/documentation.md behind a pointer relative to the installed skill, like Claude; the test pinned the old inlined layout. * B5: learnings callers report a failed search instead of reading as empty Every generated gstack-learnings-search caller ended in 2>/dev/null || true, so a missing bun or a failed search looked like 'nothing recorded'. Callers now keep stdout, capture stderr and the exit status, and print 'LEARNINGS: unavailable (<first stderr line>)' on failure (resolver callers in learnings.ts and review-army.ts, plus investigate, qa and ship's adversarial section). * F1: ship and review count unverified/unavailable outside reviews as missing coverage INV-1 consumers in this lane's templates: /ship's readiness note, its PR body Pre-Landing Review section and /review's completion rule now say an outside review reporting unverified or unavailable is missing coverage, never a pass. The PR body's Plan Completion section prints F1's not-run line instead of the old 'No plan file detected.' The /ship union-size cap moves to 1.415 for these lines (measured 1.4148). * A8: rename the artifacts repo with OWNER/REPO, rewrite the remote only after it The v1.27.0.0 migration passed a bare repo name to gh repo rename / gh repo edit, which always fails (gh wants [HOST/]OWNER/REPO), then step 2 rewrote ~/.gstack-artifacts-remote.txt to the never-renamed repository. - Qualify both names with the owner from the recorded remote URL (else the signed-in gh user) and surface gh's error. - Step 2 moves the remote file but rewrites the URL only once the rename is confirmed; a later successful retry rewrites it then. - A pending journal now counts as state to migrate, so the #1383 retry actually re-runs step 1 (it used to see no legacy file and declare the migration done). - The v1.91.17.0 migration (placeholder name) repairs installs already hit: when the remote names gstack-artifacts-<user> that does not exist but gstack-brain-<user> does, it restores the old URL in the remote file and ~/.gstack's origin and says so. It only calls gh for such a remote and never fails the upgrade. Co-authored-by: Brandon Pugsley <aibpaem@gmail.com> * B8: read gbrain JSON with bun instead of jq in install and wireup gstack-gbrain-install read package.json with jq but never checked for it, so on a machine without jq a successful install failed with "cannot read version". gstack-gbrain-source-wireup hard-failed without jq ("brew install jq" is not actionable on git-bash), so the wireup was skipped on every run. Both now read the JSON with bun, which they already require. Co-authored-by: benjamin beres <benjamin.beres@bienpreter.com> * B4: shorter probe messages (design-consultation parity budget) * B5: shorter capture variable names (parity budget) * E7: find the Aside CLI in ~/.local/bin when it is not on PATH (#2902) The installer puts aside in ~/.local/bin, which is not on the default macOS login PATH, so the probe said NEEDS_ASIDE ('download Aside') for a healthy install. The probe now falls back to ~/.local/bin/aside, drives the resolved binary, and prints READY: <path> when it is off PATH so later blocks run that path. Ported from PR #2965 onto the current _gs_d probe. Co-authored-by: Som Samantray <som.samantray@gmail.com> * A2: key the dot-slug catalog entry on the message users actually saw * E1: cmd.exe-safe investigate freeze hook On Windows Claude Code runs hook commands through cmd.exe, which cannot parse the single-quoted bash -c argument, so /investigate's scope-lock hook never ran. Use one double-quoted bash -c script that names the hook path directly (no S= variable: POSIX sh would expand $S to empty and skip the hook). * F4: design resolver reads per-round variant paths $D variants now writes $_DESIGN_DIR/round-<N>/variant-*.png and prints JSON with roundDir, manifest and paths. The mockup flow and comparison-board loops build the board from those printed paths instead of hardcoded variant-{A,B,C}.png, and approved.json records approved_path and round so a round-1 choice made after round 2 still resolves. * E4: generators tolerate Bun's spurious EEXIST on Windows (#2329) Bun on Windows throws EEXIST from a recursive mkdir of an existing directory, so gen:skill-docs and the llms.txt writer crashed once a second file landed in a directory. Both now use lib/fs-utils' mkdirpSync (ported from PR #2329 onto the existing helper instead of a new scripts/fs-utils.ts). Co-authored-by: Vaughan <vaughan@cairnsitguy.com.au> * C7: keep the required-mode hook's exit-2 deny Copilot CLI treats a preToolUse exit 2 as deny (its hooks reference), and #2413 established exit 2 plus hookSpecificOutput as the shape Claude Code enforces, so the deny output stays as on main; only the matcher and the in-place upgrade of older 'Skill' entries change. * C3: guard Kiro's router copies on a present source; give the QA pointer adapter the copy and dist helpers A copy fails where a symlink dangled, so the Kiro router and upgrade copies are written only when their render exists (as every other runtime root already does). test/qa-lazy-sections' extracted Kiro installer now supplies _link_runtime_dists (C2) and the SKILL.md copy helpers (C3). * Q3: office-hours asks open-ended questions in a Q<N> prose form (#2719) In Conductor, and whenever AskUserQuestion fails, prose is the only channel, and the prose fallback defined only the D<N> decision brief. Phase 2A/2B diagnostic questions have no option set, so the model dropped the phase. Office-hours' preamble now defines the Q<N> open-question form (question, why I'm asking, what a strong answer sounds like) and routes free-text replies to it; the diagnostic sections name it. Scoped to office-hours so every other skill's preamble is unchanged. Ported from PR #2729. Co-authored-by: Bharadwaj Mittapelli <bharadwajmittapelli@gmail.com> * A2: render db-unreachable like timeout gbrain's new db-unreachable status is a transient network failure; a setup run while offline must not strip brain-aware blocks from every skill. * A2: treat db-unreachable like timeout in gbrain-refresh The memory lane's new db-unreachable status (network or DNS failure, config intact) is transient, so gbrain-refresh keeps rendering brain-aware blocks for it exactly as it does for timeout instead of suppressing them. * C8: a render given disabled skills drops them from the router (#3018) The root router named every skill and ends 'When in doubt, invoke the skill', so it routed to skills the user disabled. gen-skill-docs takes --disabled-skills (runGeneration disabledSkills): the router drops their routing rules, keeps the other side of an 'A or B' rule, and names them as disabled. The router and gstack-upgrade cannot be disabled. With no disabled skills the render is byte-identical. * G2/G3/INV-1: skill-start former-bucket notice and visible learnings failure; TMPDIR mktemp in gbrain bins; best-effort reasons * C9: Step 2 falls back to the install registry's source checkout (DX-7) Codex users who installed from the README's ~/gstack clone got 'ERROR: gstack not found' from /gstack-upgrade: Step 2 only looked under host skill directories. It now falls back to the source checkout the install registry recorded for the current host. * B4: design --version prints the version, and the probe uses it The design CLI treated --version as an unknown command (exit 1), so the probe launched the binary with no arguments instead. Add --version (prints the gstack version, exit 0, before auth or network) and probe with it, so messages read '<path> --version exited <code>' as planned. * C4: no external render points at a section file that is not installed design-html's detector install offer and plan-eng-review's self-check pointed at $GSTACK_ROOT/<skill>/sections/<file> on every external host, where neither skill is carved and no section tree exists. design-html now inlines the offer off Claude, and a skill's pointer to its own {{SECTION}}-inlined section names the inlined text. * C1: skillify finds the browse SDK under its own host's install root The template hardcoded ~/.claude/skills/gstack for the canonical browse-client.ts, so external hosts read another host's install or nothing. A new INSTALLED_ROOT resolver (sibling of INSTALLED_BIN_DIR) names the host's global root, or the per-install root when setup renders for one. * C4: rewrite section refs on hosts whose root stays a literal ~/<globalRoot> Kiro, OpenCode, Cursor and Copilot render ~/.claude/skills/gstack as their own literal root, not $GSTACK_ROOT, so plan-eng-review's self-check pointer escaped the rewrite (found by the setup lane's installed-pointer check). * Integrator: outside-voice fences use the shared runtime prelude; TMPDIR mktemp and per-round variant paths in design templates * Integrator: C8 router omits disabled skills on every render (relink renders the served Claude router in place); Windows-safe E4/E6 entries; investigate hooks under the cmd.exe check; browse_extension_id reader; order-insensitive test typecheck identities tsc printed one unchanged ceo-mode-option diagnostic's object members in a different order (content?/isError?) once lib/fs-utils joined the generator's import graph; identities now sort object-type members, and old baselines normalize on read. * Q1 (#2971 salvage): bound iOS proxy responses One wall-clock deadline covers headers and body (stalled and dribbling bodies time out), the whole body is capped at 64 MiB (upstream_response_too_large), every terminal path clears its timer, removes listeners and destroys the request, and the daemon threads the deadline through both listeners. Ambiguous mutations are still never replayed after a timeout or abort. Ported from #2971's proxy-transport work plus the size bound. * I1: grade the AUQ matrix's (recommended) marker on option labels, the field the auto-decide hook reads The decision-brief format puts a Pros / cons block with 'A) ... (recommended)' in the question text and the same marker on the option label. The matrix counted both and failed all six skills in periodic run 37151477069 with 'expected exactly one (recommended) option, found 2'. The question-preference hook reads labels only, so the gate now checks the native question: a Recommendation line in the question text and exactly one label ending in (recommended). Fixtures move to the native question shape and add the real spec capture plus a marker-only-in-text negative control. * Q1: type the proxy-transport test doubles (typecheck:test ratchet) * INV-1: gate outcome rows and troubleshooting sections for every lane's new messages * Release v1.91.19.0 (next free patch in the queue: #3022 holds 1.91.17.0, #3023 holds 1.91.18.0); migration renamed; engines.bun >=1.4.0 to match the CI pin (#2815) * v1.91.19.0 docs and metadata: CHANGELOG, TODOS, README troubleshooting/upgrade/type --selector, BROWSER.md type and profiles, AGENTS.md conventions, CONTRIBUTING #2949, touchfiles for the wave's new lib/bin files * I1: give hermetic Codex runs a temp dir beside CODEX_HOME so Codex can create its PATH aliases Codex 0.160 refuses to create its helper aliases (codex-linux-sandbox among them) when CODEX_HOME sits under its temp dir, and the runner put the hermetic home under the shard TMPDIR. Periodic run 37151477069 shows the warning and 'Unable to spawn codex-linux-sandbox ... No viable candidates found in PATH' for every exec_command in codex-sol-scope-termination. * I1: Codex evals fail a review whose commands never ran and stop reading tool errors as skill-load problems validateCodexReview accepted codex-review-findings in periodic run 37151477069 although its only command failed in bwrap ('I couldn't run the review'); it now requires execution evidence from classifyOutsideReview (B1's INV-1 classifier). codex-sol-scope-termination failed on 'apply_patch verification failed: invalid hunk' because the skill-load check matched any 'invalid'; it now matches Codex 0.160's skill-loader diagnostics only. * I1: run paid eval containers with seccomp unconfined so Codex's sandbox can start Docker's default seccomp profile blocks the user namespaces bubblewrap needs, so every Codex command in a paid eval failed with 'bwrap: No permissions to create a new namespace' (codex-review-findings, run 37151477069). Reproduced in the CI image locally: default profile fails, seccomp=unconfined runs the command. The runner stays non-root. * I1: shared-libs plan actor reads one exclusion grammar for scope lists Periodic run 37151477069 refused 'Existing-caller migration and helper hardening stay out of scope' as a hardening proposal: the actor had two partial exclusion rules (unanchored is/are/remains outside, and an anchored list that only stays unchanged), the third refusal at this boundary after 36633323521 and 36776104571. One anchored predicate now covers a bare list of scope nouns (hyphenated compounds included) with is/are/stays/remains and unchanged/untouched/excluded/out of scope/outside/not part; any other verb in the clause is still read as a proposal. Adds the real capture and two adversarial controls. * Parity caps: measured v1.91.19.0 union/skeleton sizes for ship, review, design-consultation, office-hours and design-shotgun, with the reason beside each * Regenerate generated output for v1.91.19.0 (gen:skill-docs --host all, goldens, llms.txt, context-budget fixture) * I1: plan-eng-review writes the Test Plan Artifact even while test choices are pending Periodic run 37151477069 (plan-eng-review-artifact): a non-interactive review recorded every Test review choice as pending and never wrote the QA test plan, because Step 5 said to write the artifact 'when these test and eval choices are resolved' while the artifact section says to list unresolved choices as pending. Both now say to write it after the decision gate, with unanswered choices under Pending Decisions. The pinned sentence becomes a meaning-level check. * I3: plan-eng-review states when findings first enter the report and that the scope menu's recommendation needs no repo probe Judge rationales for 'plan-eng-review/SKILL.md sections' (actionability 3.67 in periodic run 37151477069, clarity 3 in 36385945043 and 35567915613) cite two concrete tensions: 'do not add findings before Scope Challenge C' versus the ledger saves C itself performs, and 'Recommendation: A when a branch diff exists' versus 'do not probe for session state'. The write policy now says findings first enter through Scope Challenge C's ledger saves; the selector says its Recommendation line advises the user and needs no repository inspection. The pinned sentence becomes the new meaning-level regex. * I3: plan-ceo-review defines the closing sequence's cleanup step Two of three judge samples for 'plan-ceo-review/SKILL.md modes' in periodic run 37151477069 (actionability at the 4.0 gate) flag 'perform permitted cleanup' as never defined. The only cleanup the skill has is archiving old CEO plans, which needs approval; step 5 now says so. * I3: /qa-only's value-card rule names only its own card location qa-only rendered the /qa line 'Put it in the 8e.5 record (/qa) or under each proposed test (/qa-only)'; judge samples for 'qa-only/SKILL.md workflow' (actionability at the 4.0 gate in run 37151477069, 3.67 in 36907895813) flag the /qa-only-irrelevant 8e.5 record. The qa-mode bar now renders the invoking skill's location; both skills get shorter. * test-of-test ratchet: a repo script or setup read by path counts as product code codex-invocation-sites (runs scripts/gen-skill-docs.ts), gstack-config-gbrain-refresh (copies bin/<name> through a variable) and setup-cso-windows-probe (reads setup and scripts/build-cso-windows.ps1) exercise product code the detector could not see. * I1: DX floor actor strips the editor hint from the footer line only (from #2971) The custom-field reply normalization removed 'ctrl+g to edit in <editor>' from every line, so question text that resembled the menu footer could be rewritten and still authenticate. Only the last non-empty line is the footer. Ported from Garry's #2971 with its negative control. * I4: attribute every census testcase; deselections never count as SKIPPED The paid report counted every skipped JUnit testcase as SKIPPED and every testcase whose name was not a registry id as unattributed. On the 2026-10-03 census (run 37151477069) that was SKIPPED 82 / unattributed 72 (periodic) and SKIPPED 282 / unattributed 24 (gate), and every case-shard sibling also wrote a skipped history record that reset its pass-rate series. - attributeJUnitCase: a name is its registry id or CASE_TEST_NAMES label, else the only id its file registers, else the keyless file itself. Skipped other-tier cases, case-shard siblings, isolated or unselected cases and Bun's '(unnamed)' hook placeholders are zero-credit deselections with a reason and write no history record. Anything else is listed by name as unattributed. - One result and one history record per case per shard; a genuinely skipped selected case counts as SKIPPED and is listed with its reason, also in report-summary.md and collector-outcomes.json. SKIPPED panels show their reason and skipped trials are no longer called assertions. - CASE_TEST_NAMES labels for the three /cso cases. - tierSkipReason: a computed registration whose lane-tier ids are all registered to other test files is excluded at plan time, so the four gate and two periodic files that ran with every test skipped no longer take a runner. Census rerun: periodic SKIPPED 0 / unattributed 0, gate SKIPPED 0 / unattributed 0; verdicts unchanged. * I5: split the deploy file per case; guard PR-lane shard walls at 600 s test/skill-e2e-deploy.test.ts ran 668 s as one gate shard in the 2026-10-03 census (six sequential cases, 51-201 s each). It is now case-sharded, so each case is its own shard with its own (smaller) supervision budget; no timeout or budget was raised. - CASE_SHARDED_FILES gains the deploy file (names already equal ids). - Gate duration seeds for the six case keys from the census JUnit walls, so packing stays at 12 gate-census slices (CI cap 230m -> 200m). - shardDurationViolations + PR_LANE_SHARD_LIMIT_MS: a free test fails when a planned gate shard's recorded wall (committed seed, and the last gate census in test/fixtures/paid-report-census/gate-census-durations.json) exceeds 600 s. - Tests that pinned deploy as one shard follow the split (cookie planner keys, reuse fixture key, release/PR floors). * TODOS: /review fingerprint under Codex's read-only .git sandbox (found by the live Codex check) * Free-suite repairs from the first integrated Ubicloud run Product: - Outside-voice fences carry runtimeRootPrelude(ctx) explicitly again, so the resolver output runs on its own (the post-render pass skips fences that already assign GSTACK_ROOT); outsideVoiceRuntime stays deleted. - D5: an explicit CHROMIUM_PROFILE (gbrowser's per-workspace gbd) is never seeded from the shared profile or registered for `browse profiles prune`; this was also the free suite's write to the real ~/.gstack/browse-profiles.json. - gstack-ios-qa-daemon: BASH_COMPAT=50 for its >512-byte --help heredoc. Tests migrated to the wave's deliberate contract changes: - B1 heading admits `unverified`; sandbox flag is ${_GSTACK_CODEX_SANDBOX:?}; verdict-form output (VERDICT/FINDINGS/REASON); fake codex follows the preflight + stdin + -o form; Q2 notice marked shown in a private state root. - C1: an exported root needs bin/ and lib/; a lone GSTACK_BIN is not honored. - C4: plan-ceo-review is carved on every host (carrier, discovery and methodology fixtures read sections/ when the render has it). - E7: READY prints the resolved Aside path. - INV-3: the cookie-approval reconstruction reverses the bun-install mktemp template. - F1's `Plan:` binding read gets a reasoned tracker-guard exemption. - Browse stubs stop their server instead of scheduling process.exit; the headless launch check only counts browsers its own launch started. * Regenerate generated output after the outside-voice prelude repair * I1: revert the seccomp-only eval container option; it does not let Codex's sandbox start Run 37158847998 on this branch and a stock Ubicloud VM both show that seccomp=unconfined only moves bubblewrap's failure from 'No permissions to create a new namespace' to 'Failed to make / slave: Permission denied'. Codex's sandbox started only with the host sysctl kernel.apparmor_restrict_unprivileged_userns=0 plus seccomp and AppArmor unconfined on the container, which a container job cannot set from its steps. The relaxation bought nothing, so it goes; the fix is filed as a TODO for the integrator. This reverts commit |
||
|
|
96764e80a6 | v1.91.9.0 feat: test value bar in plan-eng-review, review, qa and ship, plus /test-audit (#2998) | ||
|
|
dcaea52800 |
v1.91.7.0 feat: add functional QA and pre-publication docs checks (#2983)
* feat: add surface-aware exploratory QA and ship documentation gates * test: preserve delegated QA setup authority after main integration * fix(qa): clarify exploration order and preserve report artifacts * test(qa): follow the shared setup reference directly * refactor(ship): make verification and recovery routes explicit * test(ship): align evidence and review guards with explicit routes * fix(workflows): clarify ship recovery and functional QA evidence * fix(workflows): clarify approval recovery and full QA coverage * refactor(workflows): order review transactions and clarify ship state * fix(ship): clarify final verification and fail closed at publication * fix(evals): attribute native atomic documentation writes * fix(ship): clarify recovery and documentation lifecycle guidance * fix(test): preserve observed native placeholder styling in CI * fix(codex): report watchdog timeouts without a process-exit race * Checkpoint functional QA implementation and workflow validation repairs * Fix documentation and shared-review fixture contracts * docs: clarify judge reuse and evaluation supervision * test: align review evidence and selected case contracts * test: verify append-only documentation checkpoints and recovery * fix: qualify QA workflows and CI validation repairs * fix: launch shared-libs fixture scripts on Windows * fix: qualify QA deadlines, fixture isolation, and shard cleanup * fix: preserve qualified QA and cancellation repairs * fix: enforce functional fixture authority and share strict event decoding * fix: retain free-test evidence and explain recovery * fix: reject malformed native evidence after decoder consolidation * test: use reliable capture for telemetry privacy filters * test: refresh measured quick coverage and document validation costs * Fix native fixture receipts and preserve VM validation evidence * Align negative judge controls with upstream clarity policy * Fix report-only QA preparation and public evidence handling * Clarify QA-only preparation and current-report preservation * Stream Ship quality judgments with an explicit 64k response contract * Validate compact judge reasoning locally with supported wire schema * Align functional QA fixture instructions with evidence acceptance * Bind native browser diagnostics to execution evidence and align review verdicts * Preserve native diagnostic line boundaries * Serialize functional QA evidence from native captures * Keep large QA evidence fixture payload out of Windows argv |
||
|
|
d2a0bbcf4c |
v1.91.4.0 fix: Windows Opera cookie import wave (#2980, refs #2957) (#2987)
* fix: support Windows Opera and Opera GX cookie imports Fixes #2957 * fix: repair Windows cookie decryption and make Opera import failures actionable - strip the SHA-256(host_key) prefix Chromium adds to v10 values (DB meta v24+) on Windows - keep receipts and name `$B handoff` recovery for App-Bound rows in browsers without native extraction - explain missing browsers, missing profiles and ambiguous profile selection with next steps - add windowsNative/resolveBrowserInfo, the operagx alias and sorted failure reasons in CLI output - cover the Node server runtime with a real-DPAPI Windows test * docs: document Windows Opera cookie import and guard browser lists against drift * chore: file cookie-import follow-ups from the Opera fix wave review * test: keep Opera receipt tests independent of the shared key cache * test: declare generated gstack/llms.txt as a command-reference input for PR selection * chore: release v1.91.4.0 * test: reconstruct the historical cookie-workflow approval after the Opera BROWSER.md additions * test: run the real-DPAPI Windows check with the runner's environment PowerShell launched with a stripped environment took ~18-21s on the Windows runner (measured on a throwaway diagnostics run), past dpapiDecrypt's 10s deadline; with the full environment it returns in ~0.3s. Only APPDATA is redirected to the fixture's Opera root. --------- Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com> |
||
|
|
7b534d3e90 |
v1.90.2.0 perf: halve local free-suite time and preserve coverage (#2972)
* perf: remove repeated test work and preserve AUQ execution budgets * fix: validate native evaluation fixture evidence at its actual boundaries * fix: clarify deployment approval and recovery state transitions * chore: document coverage and release v1.90.2.0 * test: preserve Windows scheduling and native no-change consent * test: recognize verified reads through fixture symlinks * test: isolate alias-name installation from runtime assets |
||
|
|
a84b0b5b6d |
v1.90.0.0 feat: make browser cookie imports explicit and safe (#2964)
* fix(browse): prepare reliable cookie import wave for validation * ci: sequence quality and behavior for validation branch * fix(browse): isolate Windows qualification and preserve native diagnostics * test(browse): cover cookie workflow quality and isolate Windows user paths * test(browse): trace native member startup and initialize fresh folders * fix(browse): keep Windows member stdin alive through EOF * fix(browse): latch native timeouts and compare contained Edge startup * test(browse): verify native version metadata and actual Windows argv * test(browse): qualify Dia import on isolated macOS CI * fix(browse): require picker origin for session mutations * fix(browse): bound credential reads through stream completion * test(browse): inspect owned Windows process arguments natively * test(evals): preserve passing coverage during cookie repair reruns * test(browse): isolate Dia qualification in a fresh macOS account * test(browse): pass bounded integer timeouts to native Mac probes * test(browse): distinguish Windows profile initialization from containment * test(browse): await descendant pipe readiness before parent exit * test(browse): initialize and restore isolated macOS Keychain state * test(browse): initialize Windows fixture folders before qualification * test(ci): pin the same Node runtime across Windows checks * test(browse): distinguish native macOS browser preflight stages * test(browse): isolate Windows descendant console lifetime * test(browse): preserve native receipts and identify fixture lock holders * test(browse): prepare dependency resolution before native Mac worker startup * test(ci): include lock and close checks in native diagnostics * test(browse): preserve native owner probe stages and subprocess deadlines * fix(browse): classify Chromium profile-in-use exit precisely * test(browse): retain Mac qualification evidence through cleanup failures * test(browse): bound Mac fixture paths and retire its owned user domain * test(browse): accept vanished fixture entries without weakening cleanup * test(browse): identify probe-created macOS user domains safely * test(browse): observe Mac user domains without targeting them first * test(browse): use passive fresh-user ownership throughout Mac qualification * test(browse): distinguish profile and registered-home Keychain lookups * test(browse): qualify Dia under one registered account home * test(browse): identify Dia startup and owned process-group failures * test(browse): classify bounded Dia startup diagnostics without leaking output * fix(test): preserve native Mac sandboxing and reap owned browser children * fix(browse): preserve Chromium sandboxing for native profile imports * test(browse): inspect signed Mach-O architecture without launching Xcode tools * test(browse): sample pending Dia startup and reap on all cleanup paths * test(browse): compare protected Dia launches in fresh Bun and Node accounts * test(browse): inspect isolated Mac GUI readiness without browser access * v1.90.0.0 fix: bind cookie picker actions to their document * test: validate cookie guards and fit nested launch fixtures * ci: configure the bundled Chromium sandbox helper * fix(browse): classify Playwright authentication timeouts * test: retain bounded Windows lifecycle diagnostics * test(cso): reuse bounded NTFS precision candidates * test(review): handle explicit preservation choices safely * test(browse): remove owned fixture directories with explicit primitives * test(review): distinguish descriptive reuse from edit commitments * test: admit only the approved unscored cookie workflow refusal * test: keep the Office Hours judge mock export-complete * fix: keep dependency-free CI planners independent of the model SDK * test: observe the exact holder after a native fixture unlink failure * fix: start seeded PTY observations at owned readiness * test: acquire identity-bound Windows deletion admission before profile resets * test: preserve qualified Git index bits without authorizing mutations |
||
|
|
06ed920a97 |
v1.89.0.0 feat: add shared-code extraction audit (#2925)
* feat: bind shared-code review advice to source and branch * feat: add shared-code extraction audit and scoped review checks * test: recognize complete source reads and explicit coverage legends * chore: bump version and changelog (v1.88.0.0) Co-Authored-By: OpenAI Codex <noreply@openai.com> * test: capture native review questions and retain public evidence Capture the actual first public native question with strict ownership and display matching. Preserve terminal failures and raw evidence, and retain SDK completion checks. * test: recognize verified review evidence and complete fixtures Recognize complete source and diagram evidence, concrete design and developer-experience decisions, and the complete planted scenario contracts. Preserve negative controls and grading thresholds. * fix: preserve decision brief structure in native questions Keep the required pros-and-cons heading and final Net field in native question text. Regenerate host outputs and document the release and evaluation repairs. Co-Authored-By: OpenAI Codex <noreply@openai.com> * docs: update project documentation for v1.88.0.0 Co-Authored-By: OpenAI Codex <noreply@openai.com> * fix: correct eval retry accounting and ship workflow gates * fix: capture native eval evidence and stabilize CI fixtures * fix: keep shared-code eval skips read-only Choose explicit no-change answers instead of mixed fix/preservation options. Reuse the bounded revalidation prompt for path fixtures so required review metadata is available without repeated discovery. Preserve source checks, retry limits, and failed native terminal outcomes. Add captured-question and callback regressions, plus evaluation selection coverage for the affected fixtures. --------- Co-authored-by: OpenAI Codex <noreply@openai.com> |
||
|
|
85b8c038fc |
v1.87.3.0 fix: bind review evidence to the reviewed tree (#2875)
* fix(review): bind evidence to completed unchanged review passes * fix(review): keep unresolved Codex findings unverified * docs: update review evidence documentation for v1.87.3.0 * test(cso): let Windows integration finish within subprocess budgets * docs: update project documentation for v1.87.3.0 --------- Co-authored-by: garrytan <19957+garrytan@users.noreply.github.com> |