* fix(ship): record-ci reuses its own CI row at the same tree, run and selection (GST-1795)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(windows): curate ship-record-ci-reuse like its ship-bin-fixture siblings (run 42382484796)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
record-ci reuse: the tamper table gains a row for a CI row whose clean flag is false, so dropping reusableCiRow's dirty guard fails a test.
Review-Finding: bin/gstack-evidence:730:completeness-gaps reader=core
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
record-ci reuse stands only on the remainder runs its CI row was written from: a <lane>.skipped row newer than the CI row (a zero-test rerun record-ci refused) vetoes reuse instead of passing on exit 0 alone.
Review-Finding: p1/outside-voice#1 reader=outside-voice
Review-Finding: p1/adversarial-native#1 reader=adversarial-native
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>
* feat: crew PRs carry their brief's Plan line; ship-queue ready and land check it (GST-1751)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat: /ship finish and train ready/land check the Plan line (GST-1751)
finish --plan resolves the brief's Plan line before stage 1; train ready,
base-red ready, train land and stamp land read and write the READY note's
plan record like direct ready and land. Review fixes: grant and exception
rows never pass as plan approvals, render --plan stays short when redacted,
no explicit changelog-only exemption, off mode still records a resolved line.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
Review-Finding: p1/red-team#2 reader=red-team
Review-Finding: p1/red-team#3 reader=red-team
Review-Finding: p1/specialist-batched#1 reader=testing
Review-Finding: bin/gstack-approvals:56:functional-contract reader=qa
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test: cover the plan check at ready, train ready, land-direct, finish and the policy key (GST-1751)
Review-Finding: p1/specialist-batched#3 reader=testing
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: the Plan line stands for the gate's real state, and a broken store never throws (GST-1751)
A row id from an autoplan run resolves to that run's newest gate revision; a
run id needs the plan approval answered and no decision left unanswered.
readStore skips malformed rows and unreadable files; with the key off the
check never throws or prints. Train land rechecks the Plan line before its
merge on every path. /ship's Step 19-C renders Approvals with --plan;
DRIVER.md back under its size limit.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test: train land refuses a slot with no plan record under require (GST-1751)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
Step 8 plan discovery (lib/ship-audit.ts and the plan-completion sections) skips the Plan record line, so a later Plan: <path> binding is still found; render --plan refuses a line it cannot parse. The review skill's pins drop by 4 bytes.
Review-Finding: p1/red-team#1 reader=red-team
Review-Finding: scripts/resolvers/plan-gates.ts:206:functional-contract reader=qa
Review-Finding: p1/red-team#3 reader=red-team
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: changelog fragment passes the prose lint (GST-1751)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: captain.md describes the READY PLAN: line (GST-1751)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: plan discovery splits the Plan line on whitespace and skips record kinds in any case (GST-1751)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test: lower the gstack-review size pins after the Step 8 binding shrank 4 bytes (GST-1751)
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>
* Require the daemon secret and loopback Host/Origin on the design and iOS QA daemons (GST-1747)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* Name the changelog fragment after the branch (GST-1747)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
Review-Finding: p1/red-team#2 reader=red-team
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: refuse cross-site browser requests on the iOS QA loopback, show the expired page for a stale board secret, refuse requests without a Host (GST-1747)
Review-Finding: v1/outside-voice#1 reader=outside-voice
Review-Finding: v1/adversarial-native#2 reader=adversarial-native
Review-Finding: v1/adversarial-native#5 reader=adversarial-native
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: show the secret segment in the documented design board URL (GST-1747)
Review-Finding: v1/adversarial-native#1 reader=adversarial-native
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test: keep the daemon token fixtures on one line so the credential scan reads them as code (GST-1747)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: cover the Sec-Fetch-Site refusal, the expired board page and the no-Host 403 in the changelog fragment (GST-1747)
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>
* fix: keep the gbrain database URL off argv; redact more credential formats (GST-1747)
/setup-gbrain runs gstack-gbrain-source-wireup without --database-url; the
helper reads ~/.gbrain/config.json once at startup and pins the URL. A new
guard test keeps setup-gbrain docs from passing the URL on argv.
lib/redact-patterns.ts adds HIGH patterns for OpenRouter keys, GitHub App
ghu_/ghr_ tokens, Stripe live restricted keys, Supabase sb_secret_ and sbp_
tokens, and matches temporary ASIA AWS key IDs in aws.access_key.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* chore: name the changelog fragment after the branch (GST-1747)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
Clear GBRAIN_DATABASE_URL and DATABASE_URL for the setup-gbrain source wireup call so the helper pins the ~/.gbrain/config.json URL, as the --database-url flag did before. Guard test added; changelog fragment scoped to the wireup step.
Review-Finding: p1/specialist-batched#1 reader=security
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: match full-length GitHub refresh tokens in the redaction gate
github.refresh now accepts a body of 36 or more characters, so the 76-character refresh tokens GitHub issues match and are masked whole. Test samples use a 76-character body; the 35-character near-miss stays negative.
Review-Finding: p3/adversarial-native#1 reader=adversarial-native
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>
* feat: retire /investigate after a no-gain eval (GST-1717)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(skill-start): core routing offer drops every non-core rule line (GST-1717)
The retired /investigate rule became 'Bugs/errors → fix them directly', which no
longer matches '→ invoke /', so proactive=core leaked it into the offered section.
Match any '- … → ' rule line.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* revert(review): keep review/checklist.md at its no-loss-pinned bytes (GST-1717)
The pin names replay GSTA-224 H1; a reviewer checklist edit merges only after a
passing no-loss replay (crew rule 15). The /investigate flake line stays until a
replayed repin.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test: repair free-suite fallout from retiring /investigate (GST-1717)
CI run 42340956269 at 83a8a9a: drop fixtures, ledger rows, allowlist entries and
counts for the retired skill and its deleted paid files; record the harness
change as non-behavioral; the test-of-test detector accepts path.join(ROOT, 'bin');
uncovered-prompt fixtures use a tracked prompt, since an untracked path now
reads as a deleted one.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(relink): back up a retired skill's real SKILL.md before cleaning it (GST-1717)
With the skill's source gone, the customized-file check never ran, so a
banner-carrying local copy of investigate/SKILL.md was deleted instead of moved
to the backup root (red-team review, pass 1).
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(qm): restore the review checklist's flake-line rewrite (GST-1717)
review/checklist.md keeps its pinned /investigate line, so the QM edition needs
its replaceText rule back; qm/ stays fresh against the generator.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(changelog): name the setup flag break, the relink backup and the pinned checklist line (GST-1717)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(setup,relink): back up a retired skill's real SKILL.md instead of deleting it (GST-1717)
Scoped fix round under grant a-360dd62bd46a (outside-voice blocking finding and
adversarial #1, #4). setup's prune compares a copied host entry with the render
before removing that render, and backs up a copy that differs or whose render is
gone; relink no longer takes the marker's rm -rf for a skill whose source is
gone, so a real SKILL.md is backed up and the user's files stay. setup reports a
failed remove-source of the retired gate hooks on stderr.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(pr-profile): a changed prompt counts as deleted only when it is gone from disk (GST-1717)
An untracked prompt file on disk still needs prompt validation (targeted review
finding); harness change recorded as non-behavioral.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(changelog): exact backup wording, the hook-removal warning and GST-1744 (GST-1717)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(setup): one backup folder per host for a retired skill's copies (GST-1717)
Under grant a-c95576b8b1f9 (fix-check#1): every copy host moved its
gstack-investigate/SKILL.md to the same backup path, so a later host's copy
overwrote an earlier host's edits. A sandboxed ./setup --host factory run showed
gen-skill-docs removes the retired render before the prune, so every real copy
is backed up; each host now gets its own folder.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(changelog): say exactly what setup backs up for a retired skill (GST-1717)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(changelog): end the two colon sentences prose-lint flagged (GST-1717)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(retired-skills): name plan-eng-review once behind a pregate-literal waiver (GST-1717)
pregate's literals check read the GSTACK_RETIRED_SKILLS change as an old
value still in the tests. plan-eng-review is still retired; investigate was
appended. The fixture names it once, with the waiver.
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>
* test: leftover test fixtures must not quarantine a /ship review pass (GST-1695)
Failing first: a marked fixture root and ship-bin's insteadOf-local clone are
printed as ignored and never block the rerun, an unmarked network clone still
does, and every test process keeps its temp paths under one marked root that
is removed after a timeout.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: test fixtures live under a marked per-process root and the fetch sweep ignores them (GST-1695)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
The macOS named regressions re-host a captured 120-column Claude screen at the run's temp path; under the per-process marked root that path is 11 characters longer, so the permission row overran 120 columns, the PTY split '(shift+tab)' mid-word and the guard never granted (CI run 42326005642). The fake now word-wraps an overlong row at its last space, as Claude Code's renderer does. test-setup.ts, the changelog fragment and docs/review-policy.md now say a Bun.spawn child given no env keeps the original temp dir, and the policy names the exemptions a reader could forge.
Review-Finding: test/plan-count-file-permission.test.ts:101:functional-contract reader=qa
Review-Finding: p1/red-team#1 reader=red-team
Review-Finding: p1/specialist-batched#1 reader=security
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: shard sandboxes carry the fixture marker so a runner-provided TMPDIR stays as handed (GST-1695)
The narrow screen (evals run 42333856900) went red on qa-bootstrap: the preload
nested gst-XXXXXX under the paid shard's private TMPDIR, so the case's
mkdtemp(os.tmpdir()) landed below the bootstrap retention scope's temporary
dir and registerBootstrapRetention refused it. createShardSandbox now writes
the marker into the shard state dir beside tmp/, and the preload keeps any
TMPDIR under a marked directory. Harness pin recorded as non-behavioral.
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>
* fix: gstack's GitHub waits poll REST at most once a minute and wait out rate limits (GST-1713)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test: register the gh-poll REST fixtures as free fixtures (GST-1713)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes (GST-1713)
ci-gate --registration-wait re-polls while time is left in the window; a rate-limited gh pr merge fails at once under the land lock; a bot PR author reads without its [bot] suffix; ci-carry wait documents its one-poll overrun.
Review-Finding: p1/specialist-batched#1 reader=testing
Review-Finding: p1/specialist-batched#2 reader=testing
Review-Finding: p1/specialist-batched#3 reader=testing
Review-Finding: p1/red-team#1 reader=red-team
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: the GST-1713 changelog fragment names the gh pr merge exception
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>
* test: failing-first cases for the skill contract Stop hook reading a transcript before Claude Code flushes it (GST-1703)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: the skill contract Stop hook waits for the transcript flush through the shared settle loop (GST-1703)
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>
* test: failing-first cases for the CEO review gate reading a transcript before Claude Code flushes it (GST-1701)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: the CEO review gate waits for the transcript flush through #4100's shared settle helper (GST-1701)
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>
* test: failing-first cases for the opt-in /autoplan stop gate (GST-1666)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat: opt-in /autoplan stop gate with GSTACK_GATE markers (GST-1666)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: keep the ceo-only section name out of lib/autoplan-stop-gate.ts (carve guard)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
Anchor the runner match to a command position, treat a failed background launch as not pending, and read --ceo-only from a Skill call's command/skill fields and from the prompt before a Read load.
Review-Finding: p1/outside-voice#1 reader=outside-voice
Review-Finding: p1/outside-voice#2 reader=outside-voice
Review-Finding: p1/outside-voice#3 reader=outside-voice
Review-Finding: p1/adversarial-native#1 reader=adversarial-native
Review-Finding: p1/red-team#1 reader=red-team
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: name the /autoplan gate in skill-routing and the smoke section
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>
* fix(ship): a cleared remote gate for HEAD's exact tree satisfies a lane whose inventory refuses that tree (GST-1688)
When a ship_lanes_from inventory refuses HEAD's tree (inventory_failed) and
.gstack/tmp/pregate.json verifies for that exact tree with the remote gate's own
report for it, record-ci --remote-gate-stands-in records the lane as
source=remote_gate and accept prints a CI_CARRY: remote_gate line naming the
receipt. A gate for any other tree still stops, with a CARRY_DIAGNOSIS line.
A run whose tree.json lists no files now says to dispatch a fresh full run.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test: keep ship-accept-remote-gate-lanes off the Windows scoped shard (bin shebang spawns; run 42302497169)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
Review-Finding: p2/specialist-batched#1 reader=red-team
Review-Finding: p2/specialist-batched#2 reader=testing
Review-Finding: p2/specialist-batched#3 reader=testing
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: remote-gate stand-in requires origin/<base> provenance and a clear within 24h (review fix-check)
Review-Finding: p4/outside-voice#2 reader=outside-voice
Review-Finding: p4/adversarial-native#4 reader=adversarial-native
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>
* fix: the receipt and the review plan agree on stamp and docs carry for review_targeted (GST-1689)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
A restamp after a base merge now carries the targeted record: the CHANGELOG is read against the read commit's merged with the base's, so a sibling release's section is not counted as the PR's docs change. Adds the stamps-only and base-merge restamp cases.
Review-Finding: p1/red-team#1 reader=red-team
Review-Finding: p1/specialist-batched#1 reader=testing
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>
* fix: a granted fix-check after a fix-check plans in the loop (GST-1681)
In the loop, a new review_loop_grant naming the last fix-check's commit
(--range-base, the stop it answers) plans one more scoped fix-check, the
next link of the fix-check chain finish counts (GEVA-363, gstack-evals#254).
Replay: GST-1681 (repins lib/review-depth.ts)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
In the loop, a grant recorded before a later logged fix-check already bought a link of the fix-check chain, so gstack-review-plan refuses it (exit 3): a post-review link's grant names the commit its fix-check read, and a stale --range-base names an earlier link. A CLI regression covers both, and a grant recorded after the newest fix-check still plans.
Review-Finding: p1/red-team#1 reader=red-team
Review-Finding: p1/specialist-batched#1 reader=testing
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>
* setup: new installs default to the stable channel; Capy crews stay on main (GST-1642)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* capy: threads run gstack's latest main at least daily; review fixes (GST-1642, R75)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test: raise the capy skill's eager context ceiling for the R75 stale-pin prose (GST-1642)
The R75 rules grew capy/skill/gstack/SKILL.md to 5491 tokens, past its 5315 ceiling; free-tests run 42251052228 failed test/context-budget-ratchet.test.ts. Per the ratchet protocol this records the capture's value (actual x 1.10 = 6041) for this skill only; every other ceiling is unchanged. Gate disposition left open for the owner.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
A review-voice --check no longer prints the run-the-fix-before-the-first-workflow stale note (its fix would move the lane's shared checkout); a refused fast-forward after the pin-override switch is now tested to restore the pin.
Review-Finding: p1/red-team#2 reader=red-team
Review-Finding: p1/specialist-batched#1 reader=testing
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: new installs follow stable in the recommended harness (GST-1642)
Step 14.5 documentation audit gst1642-docs-1.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* chore: regenerate bin/gstack-doctor-components.sh for PIN_UNREASONED (GST-1642)
bun run gen:skill-docs --host all adds the pin-unreasoned anchor row the new result code needs.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* capy skill: tighten step 2 to fit the 5315-token ceiling; restore the ceiling (reverts 943ff5d) (GST-1642)
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>
* ship-budget resume opens a new meter epoch for a successor thread's counter (GST-1655)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test: ship-budget successor cases exercise lib/ship-budget directly (test-of-test ratchet, GST-1655)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
Review-Finding: p1/red-team#1 reader=red-team
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: refuse a successor epoch while a handoff child is open (pre-landing review)
Review-Finding: p1/outside-voice#1 reader=outside-voice
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: successor refusal points at reconcile --return; a reconcile without it writes the child off (GST-1655 fix-check#1)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: refuse a successor epoch while a dispatch reservation still has readers on the previous counter (pre-landing review)
Review-Finding: p1/outside-voice#1 reader=outside-voice
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: changelog fragment names the successor refusals (GST-1655)
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>
* review collect: a 'Finding N' lead keeps its own Severity and Blocks lines (GST-1657)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
A located line right under a 'Finding N' lead is another finding, not that lead's fields: the inline-field join now refuses a file:line, as the blank-line branch does, so judge() cannot lower the lead with a second finding's Blocks: no (red-team#1, GST-1657).
Review-Finding: p1/red-team#1 reader=red-team
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
A heading that names CRITICAL or P0 itself keeps its blocker: the no-gap inline-field join no longer attaches another paragraph's Blocks: no to it, so ledgerBlockers() still counts it, as on main (outside-voice#3, GST-1657).
Review-Finding: v1/outside-voice#3 reader=outside-voice
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: GST-1657 release note names the located-line and CRITICAL-heading guards
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>
* release: daily stable check cuts important gated changes after 24 h and forces a cut at 7 days (GST-1646, R74)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* release-cut: no release PR is NO_RELEASE_PR, a warning on a dry run, so the PR dry run against main stays green between cuts
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
release-cut --daily: a plan that clears the 24 h floor while the daily check cannot date stable is held as FLOOR_UNKNOWN, so a null decision never reaches a cut (red-team p1#1).
Review-Finding: p1/red-team#1 reader=red-team
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: name the important: fragment field in changelog.d/README.md and CHANGELOG_FRAGMENT_INVALID
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>
* ship-policy: refuse a min_gstack_version floor above the newest stable release; doctor floor row compares runningGstackVersion and offers no no-op fast-forward (GST-1637)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(policy-floor-stable): build the expected doctor row from the project path, not a forward-slash join (Windows)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test: keep fixtures off the live stable release (GSTACK_STABLE_REPO in test-setup); pregate-invalidation counts the policy-floor check
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
A vendored gstack copy (no .git of its own, inside a project) no longer resolves the newest stable release from the enclosing project's release tags: newestStableRelease and the doctor's _dc_newest_stable resolve only when the root is the top of its own git checkout, else the floor is not compared (STABLE_RELEASE_UNKNOWN) and the doctor keeps the real upgrade fix.
Review-Finding: p1/red-team#1 reader=red-team
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
The newest stable release is the highest release tag at origin's stable commit (a tag a half-way cut left behind no longer counts), and locally the VERSION at the stable ref wins over local tags. The doctor skips the remote lookup where timeout is missing (stock macOS) instead of running it unbounded.
Review-Finding: p1/outside-voice#1 reader=outside-voice
Review-Finding: p1/outside-voice#2 reader=outside-voice
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: the newest stable release is the tag at origin's stable commit
Review-Finding: p3/fix-check#2 reader=fix-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>
* skill contract: Bash writes to repo files count as edits for check_after_last_edit (GST-1633)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
perl and sed option clusters stop at the first option that takes an attached value, so perl -Ilib t/basic.t, perl -MList::Util and sed -fscript.sed are no longer in-place writes (GST-1633).
Review-Finding: p1/red-team#1 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>
* review collect: a rating verb denies a severity like "is" does (GST-1628)
A reader closing sentence such as "None of these rises to CRITICAL." (gstack-evals#247) or "Nothing reaches the CRITICAL floor." (#4055) collected as CRITICAL because the denial grammar only knew copulas. Rating verbs now deny in closingSummary and summaryCandidate; a regression corpus of 12 captured reader outputs pins 16 real CRITICALs and both phantoms.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
A rating verb no longer denies a severity it takes as its object ("Neither fix clears the P0."): "the <label>" rates only with a floor noun after it, and clear is no rating verb. The floor nouns apply only after a rating verb and end at a word boundary, so "no CRITICAL barrier" keeps its label and the pre-GST-1628 denial branch is unchanged.
Review-Finding: v1/adversarial-native#1 reader=adversarial-native
Review-Finding: v1/outside-voice#1 reader=outside-voice
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>
* fix(ship-receipt): write honors every docs audit in one /ship run (GST-1616)
When Step 14.5 audits twice in one /ship run (an audit, then a base merge and
restamp, then the re-audit), receipt write reset only the last audit's files,
so a file the first audit edited and committed stayed in the review_exclude
selection and write refused the reviewed digest (gbrain #8678).
gstack-docs-candidate snapshot now takes --run (the invocation record), --pre
on a post snapshot (records the files the audit edited, before and after) and
--carry (the run's earlier post snapshot, refused from another run). Write
resets every file the run's audits edited to its content before them when HEAD
holds what the last of them left; a file no audit edited, an edit after an
audit and a carried audit of another run still refuse.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(docs-candidate): cover --run/--pre/--carry refusals and a three-audit chain (Step 7 coverage, GST-1616)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
Review-Finding: review-p1r/specialist-batched#1 reader=testing
Review-Finding: review-p1r/red-team#1 reader=red-team
Review-Finding: review-p1r/red-team#2 reader=red-team
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(ship-receipt): a carried-audit retry never drops an integrity refusal (GST-1616)
918ab93 retried writeExcludeBinds with shorter carried-audit lists on any
failure, so an unreviewed edit to a file a carried audit edited (one code
names, so the selection digest did not move) bound once that audit was
dropped (outside voice on #4071). Only the reconstruction digest mismatch
retries now; an edit after an audit, a file changed between audits and a
foreign HEAD end the check. The repro is a test that must refuse.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* review: record the outside-voice finding b9c5fa8 fixed (GST-1616)
Review-Finding: review-p2/outside-voice#1 reader=outside-voice
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>
* runaway: warm-wait check-ins are not empty wakes (GST-1597)
lib/runaway.ts counted each 240-second warm-wait check-in (docs/captain.md,
#4060) as an empty wake, so /runaway-stopper could flag a lane that follows
the rule. A turn whose only call re-issues the wait on the same operation, or
a 240-second timer, within 30 minutes of the wait that started the run is
now left out of the rate.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
Review-Finding: p1/specialist-batched#1 reader=red-team
Review-Finding: p1/specialist-batched#2 reader=testing
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: note the warm-wait exclusion in the /runaway-stopper summary; rewrap captain.md (GST-1597 docs audit)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* runaway: keep wait input in the skill collector; 240 s timers chain only on the run's operations; status reads keep the warm window (GST-1597)
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>
* test: failing-first FIX_CHECK names the covering grant with two grants at different heads (GST-1610)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(ship): finish names the grant whose stop head is newest in the fix-check range (GST-1610)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: FIX_CHECK grant attribution (GST-1610)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: changelog fragment prose lint (GST-1610)
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>
* test: failing-first accept record-ci timeout from base policy and no-carry pregate line (GST-1606)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat(ship): accept bounds record-ci by base ci_record_timeout_s and says when the final pregate ran tests here (GST-1606)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: ci_record_timeout_s and accept-local-tests (GST-1606)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
The accept record-ci timeout test's run profile, tree.json os and workflow runner follow the host, so the accepted-carry case holds on macOS too (fromRunProfiles matches the profile os to the host; a runner for another OS is a platform lane).
Review-Finding: v1/outside-voice#1 reader=outside-voice
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>
* review-plan: a granted fix round after the targeted read plans one targeted-only reader (GST-1607)
After the owner granted a fix round past the loop cap, the granted round's
fix moved the product patch the targeted record names, so the receipt asked
for a fresh targeted read while the plan printed done (harness-evals #271).
With that --grant (checked against the approval record as before), any
change since the read except plain docs now plans NEXT: targeted on the
GST-1598 route: one targeted reader on HEAD for the head classes. A head
with no targeted class adds no reader; no grant keeps done.
The Capy pass program now runs a targeted manifest's voices stage, so a
NEXT: targeted pass driven through it creates its reader (it activated
voices only for fix-check).
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: changelog fragment for GST-1607
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: review-policy names the granted case in the targeted-only skip list (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>
* test: failing-first repro for GST-1598 (post-review docs money delta has no targeted-only reader)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* review-plan: a docs claim added after the loop plans one targeted-only reader (GST-1598)
After a finished review loop, a docs change with a money, security or numeric
claim left the receipt unable to carry the targeted record and the plan at
done, so nothing could dispatch the reader the receipt asks for (harness-evals
#225). With --range-base naming the commit the targeted reader read and
--targeted-ran its patch, a docs-only change since then now plans NEXT:
targeted: one targeted reader on HEAD for the head classes, with
TARGETED_DELTA printed. Code changes keep done; --force targeted refuses and
names the route; gstack-review-dispatch pass builds the one-reader manifest.
Repins lib/review-depth.ts under replay GST-1598 (one Step union member;
the GST-967 and GST-972 grids hash unchanged).
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* review-targeted-delta: pass the base to plainDocsSince (GST-1598 after #4058)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
targetedDelta counts a path whose branch hunks are unchanged and only the base moved lines beside them (comparePath context) as unchanged, so a main merge next to a reviewed hunk no longer hides the targeted-only read (GST-1598).
Review-Finding: p1/outside-voice#1 reader=outside-voice
Review-Finding: p1/adversarial-native#2 reader=adversarial-native
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* changelog: GST-1598 targeted-only read fragment
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>
* ship-receipt write: the targeted record survives a main merge; classes since the read cover the PR's own change (GST-1593)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: the targeted record's change since the read is the PR's own (GST-1593)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* ship-receipt depth: a branch edit to a path whose base did not move always voids the targeted record; isolate the GST-1593 tests' gate scan from the real home (GST-1593)
ownChangeSince compared the PR's per-path hunks with line numbers stripped even when main had not moved the
path's base content, so a branch commit after the targeted read that relocated the PR's money line to an
identical-context block read as unchanged and the record bound (red-team, /ship #4058 pass 1). Hunk
comparison now applies only when the base blob moved. The four direct targetedClassesSince calls in the
GST-1593 tests now run with the fixture's env, so gstack-gate-diff no longer writes under the real
~/.gstack (CI run 42179129702, free-suite (4): FREE_SUBSHARD_REJECTED real home changed).
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes (GST-1593)
ownChangeSince: a path whose base content main also changed now moves unless replaying main's change onto
the read's content (git merge-file) gives HEAD's content exactly, so relocating the PR's money hunk to an
identical context after a main merge voids the targeted record; position-free hunk comparison is gone. The
built commit carries the branch's first-parent messages since the read, so a [skip ci] commit stays RH-14
gate class. Two red-first tests cover both.
Review-Finding: v1/outside-voice#1 reader=outside-voice
Review-Finding: v1/adversarial-native#1 reader=adversarial-native
Review-Finding: v1/outside-voice#2 reader=outside-voice
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* ci: run the checks at the review-fix head (GST-1593)
The previous commit's message quoted a CI skip marker, so no workflow ran at c462483. This commit changes
no file; the tree is c462483's.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes, fix-check round (GST-1593)
The built commit now carries the message of every commit since the read that origin/main does not hold,
so a CI-skip marker on a side-branch commit merged with --no-ff still tags RH-14. A path whose mode at
HEAD is not the replayed mode now moves, so a mode-only change after a main merge to the PR's own file
voids the record. Two red-first tests cover both.
Review-Finding: fc1/fix-check#1 reader=fix-check
Review-Finding: fc1/fix-check#2 reader=fix-check
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* changelog.d: plain-sentence wording for the GST-1593 fragment (prose lint)
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>
* ship accept: a lanes-only head policy gates the final tree; name bun-hidden JUnit suites; owner-granted test-lane exception (GST-1595)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
Each excepted file is preflighted on its own and must run a counted test; the preflighted files count toward the lane's tests_ran; grants are kept per head and file set; lanesOnlyHeadPolicy compares .gstack/generated.json with the fork copy.
Review-Finding: v1/outside-voice#1 reader=outside-voice
Review-Finding: v1/outside-voice#2 reader=outside-voice
Review-Finding: v1/outside-voice#3 reader=outside-voice
Review-Finding: v1/adversarial-native#2 reader=adversarial-native
Review-Finding: v1/adversarial-native#4 reader=adversarial-native
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: lanesOnlyHeadPolicy compares generated.json with the base tip again
A --policy-from head run loads the regen registry from the branch (lib/pregate/context.ts), so a branch whose .gstack/generated.json differs from main's tip keeps the base policy; comparing with the fork copy would gate under a stale registry.
Review-Finding: p2/red-team#1 reader=red-team
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: troubleshooting entries for the accept head policy and test-lane exceptions (GST-1595)
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>
* test: failing-first repro for the changed+context carry deadlock (GST-1561)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* ship-receipt carry: a changed path plus moved base context compose into one bounded re-check, and a base-side removed line joins the scoped review (GST-1561)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
baseEditOnly refuses a hunk whose range holds a line the base inserted without replacing any, so a merge that drops base code stays changed. Curates the new test out of the Windows scoped shard like ship-mechanical-retake.
Review-Finding: p1/specialist-batched#1 reader=testing
Review-Finding: p1/red-team#1 reader=red-team
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
baseEditOnly refuses any base hunk at the reviewed range that adds more lines than it removes, so a merge that drops a line the base added beside its own edit stays changed.
Review-Finding: p2/red-team#1 reader=red-team
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: ship-policy names the base-added-line case that stays a changed path (GST-1561)
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>
* test: failing-first founderstar#563 retake shape, refusals and planner agreement at the cap (GST-1560)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* feat(ship): finish routes a declared mechanical retake with no review; --post-review plans the inserted Step 9 (GST-1560)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(ship): mechanical_retake, ROUTE_MECHANICAL_REFUSED and the Step 16 planner line (GST-1560)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test: keep ship-mechanical-retake.test.ts off the Windows scoped lane (bin shebang spawns) (GST-1560)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
finish dropped a post-review path named like an Object.prototype key (constructor, toString, __proto__) from behavior through 'p in proven' on a plain object; proven is now a null-prototype map read with Object.hasOwn, with a regression test.
Review-Finding: v1/outside-voice#1 reader=outside-voice
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: changelog fragment prose lint (GST-1560)
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>
* fix(review-exclude): standalone render reads the base policy's selection and excerpts (GST-1476)
The plan, buildManifest and gstack-review-dispatch render share lib/review-selection.ts, so a first render, a re-render after a failed dispatch and a late stage read the same diff.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* chore: name the changelog fragment after the branch (GST-1476)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: read a reader's selection from the checkout root, not the caller's directory (GST-1476)
Review-Finding: p1v/outside-voice#1 reader=outside-voice
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: name the checkout-root read in the changelog fragment (GST-1476)
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>
* investigate: opt-in gate that holds root cause before fix, through Bash too (GST-1461)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* investigate gate: posix paths in edit blocks, CI fixes (GST-1461)
- hook: the edit branch computes the repo-relative path once in posix form, so
the marker and deny text read src/total.ts on Windows too
- lib/review-depth.ts is back to main's pinned bytes; lib/investigate-gate.ts
keeps its own copy of TEST_PATH
- gstack-skill-gates report: destructure session_id (the pregate secrets scan
read the old line as a secret-named assignment)
- tests: pin core.autocrlf=false in the git fixtures, skip the symlink swap on
Windows, give setup-hook-syntax-gate's fixture the shared TypeScript entry a
shim runs, unit-test excludedReason, and check the smoke's pinned Claude Code
version against docs/skill-gates.md
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes (GST-1461)
- checkTree saves the bytes a restore replaces in the session directory and
the block names the copy, so a concurrent editor save is never lost
- a new commit is undone to its newest ancestor that existed before the
baseline or that a remote-tracking ref holds, not to the baseline HEAD: a
fix committed on another branch moves that branch back to its own tip,
and pull/merge of fetched upstream commits is not undone; the block lists
the commit's other changes left staged
- runGateHook takes the switch reading from its caller, so the
investigate_gate config key has a literal reader (gstack-config-defaults)
- the slow checkout case gets an explicit 30 s test timeout
Review-Finding: p1/specialist-batched#1 reader=security
Review-Finding: p1/red-team#1 reader=red-team
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes, round 2 (GST-1461)
- an amend or rebase of commits from before the baseline on the same branch
is undone to the baseline HEAD, not to its parent; on a different branch
the gate blocks but leaves the commit in place
- existedBefore answers reachability with one rev-list call instead of one
merge-base per ref, so a fix commit in a repo with hundreds of refs is
still undone inside the 5 s hook deadline
Review-Finding: p2/specialist-batched#1 reader=testing
Review-Finding: p2/red-team#1 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>
* fix(review-exclude): files kept only for a secret line go to pass readers as excerpts (GST-1447)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(review-exclude): keep the pinned depth rules untouched; the plan adds each dispatch's excerpt (GST-1447)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(review-exclude): split secret-excerpt sections only at real line starts (GST-1447)
A CR, U+2028 or U+2029 followed by 'diff --git ' inside a changed line cut the
file's section short, so the secret lines after it left the excerpt while the
file stayed excluded from the reader's own diff.
Review-Finding: p1/red-team#1 reader=red-team
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(review-exclude): scan secret-excerpt lines with their context and overlapping chunks (GST-1447)
The scanner read changed lines alone, in chunks with no overlap, so a secret it
detects only beside its label (an AWS secret key under an unchanged
aws_secret_access_key line, or a label at the end of one 512 KiB chunk) left
every excerpt. Scan every hunk line, repeat 1 KiB between chunks, and count
findings on changed lines only.
Review-Finding: p11/outside-voice#1 reader=outside-voice
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(changelog): split the excerpt sentence (GST-1447)
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>
* fix(review-exclude): write, ready and carry bind a digest whose policy gives the PR's files the same selection (GST-1446)
harness-evals #222's reviewers read 7cf39a7e1150, which excludes 1,260 of its files under #272's
three globs. After #278 added six globs that match none of them, main's digest became
dde43b124877 and gstack-ship-receipt write refused the reviewed digest: write compared digests
only, and the shared carryExcludeBinds rule bound a moved digest only when both selections
were empty.
carryExcludeBinds now binds when the recorded selection and HEAD's give the PR's files the same
list hash (applied patterns, excluded files, kept files with their reasons); the empty-selection
rule is the case where both lists are empty. ready, train build, land and carry pick it up
through the same predicate. Write gets only the reviewed digest, so it rebuilds the record from
the review_exclude_paths the base held at each commit that changed the policy file, and binds
when one of them with HEAD's list builds the digest (REVIEW_EXCLUDE_POLICY_MOVED:). A digest no
such policy builds, an omitted --review-exclude, a selection that differs and an unreadable base
policy still refuse; --docs-post keeps its path.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
reviewedRecord walks the policy file's full history, so a merge that restores an earlier policy no longer hides the reviewed one (GST-1446).
Review-Finding: p1/outside-voice#1 reader=outside-voice
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>
* fix(redact): a property read in code is not an internal hostname (#3987)
internal.hostname matched any name ending in .local/.prod/.staging/.internal/.corp/.lan,
so server.local('/x'), if (config.prod) and if settings.internal: reported as leaked
hosts, and the pregate secrets stage warned on each. With a code file's path, a span
outside every string and comment on its line, with code syntax on both sides, is now
a property read. Real hosts in strings, comments, URLs, ports, prose and config still
report. Each line is read once, so scan time stays linear.
Co-authored-by: nazarli-shabnam <shabnamnezerli@gmail.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
In JS, a span after a bare key and ':' or '=' (YAML or dotenv text inside a template literal) and any span after a '/' in code on its line (a regex literal can hold a quote) are no longer exempt from internal.hostname.
Review-Finding: p1/specialist-batched#1 reader=security
Review-Finding: p1/red-team#1 reader=red-team
Review-Finding: p1/red-team#2 reader=red-team
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: review fix-check fixes
In JS, template literals and block comments come from one pass over the whole input (jsSpans), so a span inside either is never exempt from internal.hostname; in .tsx and .jsx, a span in JSX text is never exempt.
Review-Finding: v2/outside-voice#1 reader=outside-voice
Review-Finding: v2/outside-voice#2 reader=outside-voice
Review-Finding: v2/adversarial-native#1 reader=adversarial-native
Review-Finding: v2/adversarial-native#2 reader=adversarial-native
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(redact): .tsx and .jsx files keep reporting internal hostnames
JSX text can hold a host on any line, so the property-read exemption now applies to TS, Dart and Python only, and the '>' JSX rule is gone. Recorded as the PR's review_loop_exception (a-57e88a238e8b).
Review-Finding: fc/fix-check#1 reader=fix-check
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
---------
Co-authored-by: nazarli-shabnam <shabnamnezerli@gmail.com>
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(review-exclude): one git grep per tree through a scratch index, batched blob reads; dispatch prints REVIEW_PLAN_STOPPED (GST-1442)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(review-dispatch): the plan limit lives beside the scan deadline it must stay a minute above (GST-1442)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
Batched blob prefixes are copied, so each 64 MB cat-file --batch buffer is released after its group instead of staying alive until every blob is read.
Review-Finding: v1/outside-voice#1 reader=outside-voice
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(review-policy): a plan past the pass limit stops with REVIEW_PLAN_STOPPED (GST-1442)
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>