* capy session: defer the upgrade while a /ship or review run is open; upgrade-path fixes (GST-1677, GST-1658)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
The pin override releases .setup-lock before an older gstack-upgrade on the local default branch runs, so that copy takes the lock itself instead of refusing against the session's own pid; the no-flock eval-lock test skips visibly instead of returning.
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>
* docs: troubleshooting names an open /ship or review run as an UPGRADE_BUSY cause
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* changelog: note the older-gstack-upgrade lock release (GST-1658)
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>
shardOverruns compared a shard's wall-clock elapsedMs with predictedMs, the
shard's serial seed sum. free-tests.yml plans every shard at --shard-jobs 4,
so the 1.5x warning only fired after about a 6x slowdown. The prediction is
now divided by the plan shard's jobs, ciHealthSummary carries jobs through,
and the warning names the parallel job count. k=1 output is unchanged.
Rewritten on main from #4051, which fixes#3851.
Co-authored-by: Indra Prasetya <indraoverflow@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>
* paid screens: narrow screens derive setup; modules/loadouts.json derives through its reader (GST-1575)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* changelog: name the fragment after the branch (GST-1575)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* harness pins: test-pr-profile.ts change is non-behavioral (case selection only) (GST-1575)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* changelog: setup reaches its cases through touchfiles; loadouts-only edits wait for the train census (GST-1575)
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>
* QM edition: three gstack skills QM loads on demand (GST-1492)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test: name the QM edition's manifest and shipped script
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* paid lane: classify the QM edition as free-only (no paid case reads qm/)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
diff-base.sh names the untracked files past the first 30 (UNTRACKED_MORE) instead of dropping them silently; the gstack-review first step tells QM to read every untracked file.
Review-Finding: p1/outside-voice#1 reader=outside-voice
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: point the QM row in docs/hosts.md at the QM edition
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test: record the non-behavioral HARNESS_VERSION decision for the qm/** free-only row
CI run 42135033713 failed test/harness-version.test.ts: scripts/test-pr-profile.ts is a pinned shared-harness file and 87ed675 changed it without a decision. The row only classifies qm/ as free-only; no paid case reads qm/.
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(ubi-runner): an ambiguous create arms teardown only once this call's ssh key opens the VM (GST-1463)
With an explicit -n name a second caller can take the name between the 404
name check and the create; if our create's 409 was lost (000), the by-name
lookup adopted that caller's VM and teardown destroyed it. Teardown is now
off from an ambiguous create answer on and armed only when this call's key
opens the VM within UBI_SSH_WAIT; otherwise up keeps the record and bundle,
exits UBI_CREATE_UNKNOWN and leaves the VM to its TTL, and run reports
left=unknown.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: ubi-runner ssh proof offers only this call's key (IdentitiesOnly=yes)
The ownership proof after an ambiguous create counted any ssh success, and ssh also offered agent and default ~/.ssh keys beside -i, so a holder VM that accepted one of them was armed and destroyed. Failing-first test: the fake agent holds the holder's key.
Review-Finding: p1/specialist-batched#1 reader=specialist-batched
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: ubi-runner ownership proof ignores ssh config identities (-F /dev/null)
IdentitiesOnly=yes still offers IdentityFile and CertificateFile entries from ssh config, so the proof after an ambiguous create could pass on a holder VM that accepts a configured key. The unproven proof now runs with -F /dev/null; the normal path keeps the user's config. Failing-first: the fake ssh config holds the holder's key.
Review-Finding: p2/red-team#1 reader=red-team
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: ubicloud skill says to list before down after UBI_CREATE_UNKNOWN
left=unknown can now mean another caller's VM; the runner prints list, not down, for that case. The changelog fragment notes that agent and config keys don't count for the proof.
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(ubi-runner): an API error is never read as success on the money path (GST-1441)
A refused create disarms teardown, a 5xx/unanswered create is looked up by
name, down counts a VM gone only on a readable list, pull fails on ssh
failure, gc reports failed destroys, an unanswerable run record refuses
instead of starting a second VM, and the API key leaves curl's argv.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
A 5xx or unanswered create no longer adopts a VM another caller already holds under that name: up refuses a name that already answers show before any create is sent, and adopts after an ambiguous create only when the name was free just before it. Regression test reproduces the adopt-then-destroy on 6a61206.
Review-Finding: v1/outside-voice#1 reader=outside-voice
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(troubleshooting): UBI_CREATE_UNKNOWN and UBI_ATTACH_UNKNOWN (GST-1441)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(ubi-runner): create only after the name check answers 404 (GST-1441 fix-check)
An unanswered name check let the create go out; a 5xx create whose lookup
then stayed unanswered left teardown armed on a VM whose owner was never
established, and one whose lookup answered 200 was disarmed and left to its
TTL. up now refuses before any request unless the check answers 404, so a
VM found after an ambiguous create is always this call's. The 409 test
again lists the holder (landing between check and create) and proves it is
not destroyed.
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): 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>
* fix(review-exclude): ready binds an older digest when no selection holds a PR file; the name scan greps consumers only (GST-1434, GST-1435)
GST-1434: gstack-ship-queue ready (and train build, land) refused any receipt whose
recorded review_exclude digest differed from the base policy's, so a policy edit on
main voided every receipted PR even when no PR file fell under a pattern
(harness-evals #274, #276 after #278). excludeMismatch now uses carryExcludeBinds,
the predicate carry uses since #4030: a digest change binds when neither the recorded
selection nor HEAD's holds a file the PR changed; anything else still refuses.
GST-1435: the named-by-code scan ran git grep over the whole tree, so on
harness-evals #269 it searched 30 MB of receipts for 4,354 candidate paths, ran
278 s past its 120 s limit and kept every file. It now lists each tree, keeps the
consumer files (code and tests outside the candidates) and greps only those through
literal pathspecs in 24 KB chunks. A git failure or timeout still keeps every
candidate.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
grepFixed keeps every candidate when a consumer's name does not survive UTF-8 decoding, since its literal pathspec would match nothing.
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>
* docs: the queue's review_exclude check follows carry's rule (GST-1434)
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): a docs audit after the review no longer voids the review_exclude binding (GST-1429)
Step 14.5's docs audit runs after the review. When it edits, adds or removes a
file under review_exclude_paths, HEAD's selection digest moves and receipt
write refused the reviewed digest. write --docs-post <audit-id>-post.json now
binds the reviewed digest when it is HEAD's selection with the files under a
pattern that changed since the snapshot's HEAD reset to it, each named by the
snapshot with the content HEAD holds and excluded or kept only because code
names it, and every other file selected alike. Anything else still refuses.
The ship driver's Step 19 write omitted --review-exclude, so gbrain #8627
wrote recorded=none; it now passes it, and the refusal says when the flag was
left out.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(review-exclude): keep the GST-1429 in-process receipt read off the real state root
The #8627-shape test called receiptReviewAtHead in-process with the runner's
GSTACK_STATE_ROOT, so its gate scan wrote gate-diff and slug-cache entries
under the real ~/.gstack and CI rejected free-suite shard 9
(FREE_SUBSHARD_REJECTED, run 42017628509). It now points GSTACK_STATE_ROOT at
the fixture like the docs-only gate-tagged test does.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: pre-landing review fixes
The docs-audit exception reset every changed file under review_exclude_paths
to the post snapshot's HEAD, so a docs edit the review read while it was still
uncommitted was reverted and write refused a normal /ship run. --docs-pre
<Prepare snapshot> now narrows the reset to the files the audit changed, back
to their Prepare content. Snapshot hashes of working-tree bytes also compare
against HEAD's content as it checks out, so autocrlf or a clean filter no
longer reads as an edit after the audit.
Review-Finding: s11/outside-voice#1 reader=outside-voice
Review-Finding: s11/outside-voice#2 reader=outside-voice
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* chore: changelog and TODOS
gstack: ok 1.96.0.0 for=ship
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(land): close land's /proc environment to merged_checks (GST-1421)
A merged check could read land's exec-time environment (GitHub token
included) through /proc/$PPID/environ or a /proc scan. On Linux land now
makes itself non-dumpable before the first check and refuses to run them
when it cannot. macOS (ps -E) is documented as still readable.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(changelog): GST-1421 fragment
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(land): kill what a merged check leaves running before land's git and gh calls (GST-1421)
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(changelog): GST-1421 fragment names the stray kill
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(ship-policy): adopt the release gate; a backstop freeze only warns land once release_gate is set (GST-1133)
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=state-machines
Review-Finding: p1/red-team#2.1 reader=red-team
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix: bisect follows the current policy cap and resumes when it is raised; docs say the cap prices trials at the reservation
Review-Finding: p2/outside-voice#1 reader=outside-voice
Review-Finding: p2/outside-voice#2 reader=outside-voice
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs(changelog): GST-1133 fragment covers release-cut and the bisect cap
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* docs: land table and QUEUE_TRAIN_FROZEN note the release_gate stand-down (Step 14.5 audit g2a1)
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): finish takes a landed stack parent as the reviewed base, fail-closed on metadata and never bounded (GST-1399)
Ported from #4013 onto #4020's route: the stacked-parent path judges every
shipped path's metadata class against main, counts stamp_paths and
release_outputs only while stamp-only, and never feeds the bounded route.
The receipt carry's landed-parent search finds a squash main edited since.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(ship): a loop exception starts at the landed parent; a conflicted base commit never holds a parent (GST-1399)
Review-Finding: p1/red-team#1 reader=red-team
Review-Finding: v1/outside-voice#1 reader=outside-voice
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(ship): a metadata-only conflict still holds a landed parent; a post-merge loop head starts at its own fork (GST-1399)
heldBy counts a merge as conflicted only when a conflicted path is inside its pathspec, so a train's VERSION restamp
in the squash no longer hides the landed parent. The review-loop exception's atHead uses patchBase, so a fix-check head
after the child merged main starts at its own merge base, not at the parent.
Review-Finding: p2/specialist-batched#1 reader=specialist-batched
Review-Finding: p2/red-team#1 reader=red-team
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* test(ship): stacked-parent loop-exception matrix over merge order, parent state and fix-check head (GST-1399)
28 cells: the child merged main before the parent landed, after, or never; the parent landed by squash, by squash
with a later main edit of its lines, with a release fold, or not at all; the fix-check head is before any merge, the
merge, or after it. Every cell runs the postinstall and stamp_paths probes (parent changes main never took, edited
after the fix-check) and a control run (the child's own file and a main-only file edited after the fix-check).
Red at 3f4c47c (4): merged before or after the landing × parent edited × fix-check head merge or post; the
exception accepts package.json and src/policy.ts. The other 24 cells pass.
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
* fix(ship): a loop exception's fix-check paths are the head's own patch from both forks; heldBy reads merge-tree with -z (GST-1399)
The "touched at the fix-check head" set is the intersection of the head's patch from its merge base and from the
landed parent, so neither a parent change main never took nor a main-only file counts as reviewed, whatever order
the child merged main in. heldBy reads conflicted names NUL-separated, so a C-quoted name still counts as a conflict.
The stacked-parent matrix (28 cells) is green.
Review-Finding: fc1/fix-check#1 reader=fix-check
Review-Finding: fc1/fix-check#3 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>