Skip to content

v1.91.306.0 ship-receipt: carry across regenerated outputs and onto a reviewed tree after a rebase - #3564

Merged
capy-ai[bot] merged 6 commits into
mainfrom
gsta147-carry-rules
Oct 29, 2026
Merged

capy-ai[bot] merged 6 commits into
mainfrom
gsta147-carry-rules

Conversation

@garrytan

@garrytan garrytan commented Oct 28, 2026 •

Copy link
Copy Markdown
Owner
{
  "schema_version": 1,
  "pr": 3564,
  "head": "3b90122ef2ef1b3b4319e182d55e77a2d86e73a4",
  "version": "1.91.299.0",
  "base": "main",
  "gate": {
    "focused": {
      "pass": 496,
      "fail": 0,
      "skip": 0
    }
  },
  "session_kind": "unattended",
  "pregate": "requires-remote cleared @038eb3e4c86e (1 checks, current for 3b90122ef2ef)",
  "requires_remote": [
    "free-tests.yml/cso-macos-launcher: https://github.com/garrytan/gstack/actions/runs/40791649755",
    "free-tests.yml/macos-named-regressions: https://github.com/garrytan/gstack/actions/runs/40791649755",
    "windows-free-tests.yml/windows-free-shard: https://github.com/garrytan/gstack/actions/runs/40791654341",
    "pregate.json/remote_gate: remote-gate tree=038eb3e4c86e tests=23351"
  ],
  "issues": {
    "fixes": [],
    "refs": [
      3564
    ],
    "flakes": []
  },
  "docs": {
    "status": "updated",
    "scope": "docs/ship-policy.md, docs/troubleshooting.md, docs/unattended.md, docs/captain.md, docs/pregate.md, captain/templates/CREW.md, ship/SKILL.md.tmpl, CHANGELOG.md (read only)"
  },
  "review_loop": {
    "passes": 2,
    "blocking_found": 3,
    "deferred": 0,
    "noted": 10,
    "fixed": 6,
    "scope": "frozen",
    "fix_checks": 1,
    "dispatches": {
      "specialist": 8,
      "red-team": 2
    }
  }
}

What changed

Receipt carry: merge main and keep the receipt when only proven regenerated outputs changed; a rebase carries only onto a reviewed tree with the reviewed product diff

docs/ship-policy.md's receipt-carry section now opens with "merge main, never rebase" and a four-row table of what happens to a receipt when the base moves, because the carry rules below it changed.

Before/after as text: Receipt carry: merge main and keep the receipt when only proven regenerated outputs changed; a rebase carries only onto a reviewed tree with the reviewed product diff
--- Before · docs/ship-policy.md § Carrying a receipt across a base merge or a test-only fix at 4c745ee · source text
+++ After · docs/ship-policy.md § Carrying a receipt across a base merge or a test-only fix on this branch · source text
 ## Carrying a receipt across a base merge or a test-only fix
+**Merge main into a reviewed branch; never rebase it.** What happens to the
+receipt when the base moves:
+
+| What changed since /ship | The receipt |
+|---|---|
+| a merge of the base, product diff unchanged (tests, release metadata, registered outputs the pregate's regen check proved) | carries; no review reruns |
+| a merge of the base whose resolution changed product code | a fresh /ship (`RECEIPT_CARRY_PRODUCT_CHANGED`) |
+| a rebase or force-push onto a tree the receipt covers, product diff against the new base unchanged | carries (`carry.ancestry: rewritten`) |
+| any other rebase or force-push | a fresh /ship (`RECEIPT_CARRY_TREE_MISMATCH`) |
+
 Since the release that added `review_scope`. A `/ship` receipt names the head it
 reviewed, so a conflict-only merge of the base or a test-only fix used to
 invalidate it and cost a full re-run on identical product code.
@@ ⋯ 24 unchanged ⋯ @@
 minor, #3512; a version older than the old one or of another width is a hand
 edit). A logic change in a
 stamped source file is product. Lockfiles are product unless the policy names
+them. An output of an entry with a `command` in origin/<base>'s
+`.gstack/generated.json` is `generated`, not product, only when the
+`--pregate` result passed for HEAD lists it under the `regen` check's
+`proven` paths (the check deleted the touched output in its scratch worktree
+and the command recreated it byte-identically) and that check ran the same
+registry, origin/<base> at the commit the carry reads. A file that matches an
+output glob but that the command never writes is not proven. Without that
+evidence, or for an entry with no command or one only the branch registers,
+the output is product (U1 on gstack-evals paid a
+full rerun because a merge changed its generated index's diff). A base merge
+contributes no product change of its own. A receipt carried twice keeps the reviewed head as
-them. A base merge contributes no product
-change of its own. A receipt carried twice keeps the reviewed head as
 `carry.from` and adds up the merges and paths. The carried receipt records
 `carry: { from, reason, product_patch_id, changed_paths, merge_commits,
+range_diff, covers, reruns, ancestry, trees }` (`ancestry` is `linear`
+along the receipt's own history, `rewritten` once any hop was a rebase;
+`trees` lists the earlier covered trees) with the `git range-diff` evidence, prints
-range_diff, covers, reruns }` with the `git range-diff` evidence, prints
 `CARRY: carried from <old> to <new> (<reason>)` and the `GSTACK_RESULT:
 skill=ship status=complete` line, and its summary line ends with
 `carried_from=<old12>`. `CARRY: current` means the receipt already names HEAD;
@@ ⋯ 1 unchanged ⋯ @@
 
 A changed product path, or a product patch-id that differs, is
 [`RECEIPT_CARRY_PRODUCT_CHANGED`](troubleshooting.md#receipt-carry-product-changed)
+(exit 3; the refusal names the paths), and a working tree with uncommitted
+changes is [`RECEIPT_CARRY_REFUSED`](troubleshooting.md#receipt-carry-refused).
+
+**Rewritten history.** `write` records `head_tree` (the reviewed head's tree)
+and `product_patch_id` (its product patch against the base), and every carry
+rebinds both to the new head and keeps the earlier trees in `carry.trees`.
+When the receipt's head is no longer in HEAD's history, the carry follows only
+when HEAD's tree is one of those trees and HEAD's product patch-id against the
+current base equals the recorded one; it records `carry.ancestry: rewritten`
+and `range_diff: tree-equal`, and needs neither the old commit nor its
+history, so a fresh clone carries too. The tree alone is not enough: a stacked
+branch rebased onto main after its base closed unmerged keeps its tree while
+its diff grows by the base's code, and that is `RECEIPT_CARRY_PRODUCT_CHANGED`.
+Any other tree is
+[`RECEIPT_CARRY_TREE_MISMATCH`](troubleshooting.md#receipt-carry-tree-mismatch),
+which names HEAD's tree and the covered trees. A receipt from before
+`head_tree` existed, whose head is not in this clone, is
+`RECEIPT_CARRY_REFUSED`: run `/ship` on the new head. A refusal never
+rewrites the body. The queue's `ready`, `train build` and `verify --train` read the
-(exit 3; the refusal names the paths), and a receipt whose head is not in HEAD's
-history (a rebase or force-push) or a working tree with uncommitted changes is
-[`RECEIPT_CARRY_REFUSED`](troubleshooting.md#receipt-carry-refused): run `/ship`
-on the new head. The queue's `ready`, `train build` and `verify --train` read the
 carried receipt like any other.
 
 **Delta /ship: eligibility, then checks, then publication.** `/ship` Step 1 runs
  • Carry across regenerated outputs. gstack-ship-receipt carry treats an output of an entry with a command in origin/'s .gstack/generated.json as generated, not product, only when the --pregate result for HEAD lists that path under the regen check's proven paths and the check ran the same registry as origin/. To prove a path, the regen check deletes it in a scratch worktree, reruns the command in a second run apart from the verdict, and requires a byte-identical rewrite. A path matching an output glob that the command never writes stays product, as do head-only registry entries, command: null entries, vendored code and lockfiles.
  • Carry across rewritten history. write records head_tree and product_patch_id. A head that is no longer a descendant of the receipt's head carries only when its tree is one the receipt covers and its product patch-id against the current base matches. It records carry.ancestry: rewritten and needs no old commit, so a fresh clone can carry. A different tree refuses with the new RECEIPT_CARRY_TREE_MISMATCH; the reviewed tree on a base that moved under it refuses with RECEIPT_CARRY_PRODUCT_CHANGED. A dirty tree refuses before any of this.
  • Docs. docs/ship-policy.md, docs/pregate.md, docs/troubleshooting.md, docs/captain.md, docs/unattended.md and captain/templates/CREW.md (rule 14) follow the new rules.

Why

On gstack-evals, two full /ship reruns came from a merge of main that only changed a generated file's diff, and one came from a rebase whose tree was byte-identical to the reviewed one. Each rerun re-reviewed code the receipt already covered, so a lane paid for a second review loop on identical product code. Now a merge that only touches proven regenerated outputs, or a rebase back onto a reviewed tree, keeps the receipt. This is PR 1 of the GSTA-147 plan (approved by Garry, gate_rev 2, reply "rec"); PR 2 stacks proportional review depth on it.

Blast radius

The change touches receipt carry and the regen pregate check. write adds two keys to new receipts, and old receipts without them carry through the existing patch-id path but refuse a rewritten head because they record no tree. The regen check's verdict is unchanged. Its new proven list comes from a second run in the scratch worktree, and a failed proof proves nothing (test/gstack-regen.test.ts covers the self-reading generator at scripts/gen-skill-docs.ts:1038, script ran). Review, queue and pregate behaviour are otherwise unchanged.

Approvals

Date Asked Exact words Outcome Covers Still pending
2026-10-28 Approve the plan "Proportional /ship review depth (GSTA-147)" (autoplan run autoplan-20261028203249, gate_rev 2); this PR is PR 1 of its split (receipt carry) “Garry: rec” (Garry, relayed by agent:gstack-minder (re-recorded on this branch from main-0d6e4079e3 a-9844d7951828)) approved the reviewed plan (sha256 cc00c1e94eb7), every recommendation taken none

Source: gstack-approvals record for gsta147-carry-rules (display only; not an approval citation).

Summary

Lanes kept paying for a full /ship after a base merge or a rebase that left the reviewed code alone. The receipt now carries across both when the evidence shows the product diff is unchanged. A regenerated output counts as generated only when the pregate proved the generator writes it, and a rebase carries only onto a tree the receipt already covers. Review found a gate bypass in the first version (any output glob was exempt once regen said fresh), so the proof step and the registry check were added before shipping.

Test Coverage

New tests: test/ship-receipt-carry-rewrite.test.ts (rebase onto a covered tree from a fresh clone, rebase onto a different tree, the reviewed tree on a moved base, and a base merge that changes a registered output with and without a proving pregate, including a tampered pregate), and a test/gstack-regen.test.ts case for a self-reading generator. The rebase and registered-output cases fail on e97b857 and pass after the fixes. Known gaps are listed under Review notes (legacy receipts on a rebase, the "no registered input or output touched" negative case, eight dry-run state cells).

Tests ran: focused 496

Pre-Landing Review

Three blocking findings, all fixed:

  • CRITICAL bin/gstack-ship-receipt:396 gate bypass: verifiedOutputs exempted every base-registry output glob once regen said fresh. Found by the red team, the native adversarial pass and the GPT outside voice, and confirmed by state-machines. Fixed in f47aba6: regen proves each touched output, and the carry checks the registry label.
  • CRITICAL lib/regen.ts:248 the prove step deleted a source that scripts/gen-skill-docs.ts:1038 reads (its own output). Fixed in bf9a417: the proof is a second run apart from the verdict, and a failed proof proves nothing.
  • CRITICAL bin/gstack-ship-receipt:401 proven names were used as pathspec globs. Fixed in bf9a417: names containing * ? [ ] or a backslash are dropped.

REVIEW_LOOP: passes=2 blocking_found=3 deferred=0 noted=10 fixed=6 scope=frozen fix_checks=1 dispatches=10

Gate edits: 2 listed, 1 read, 0 findings — 0 kept, 0 restored, 0 open

Outside review: openai/gpt-6.1-sol on pass 1, verdict: one blocking finding (the gate bypass above), fixed.

Review notes

Below the blocking floor (advisory, informational, test-gap or wording items); recorded here and not fixed in this PR.

  • INFORMATIONAL lib/ship-receipt.ts:201 classifyCarryPath docstring omits extra.outputs / 'generated'
  • INFORMATIONAL bin/gstack-ship-receipt:522 no test for legacy receipts without head_tree/product_patch_id on a rebase
  • INFORMATIONAL bin/gstack-ship-receipt:396 no negative test for regen pass 'no registered input or output touched'
  • INFORMATIONAL test/ship-receipt-carry-rewrite.test.ts:115 registered-output test ignores the merge exit status
  • INFORMATIONAL bin/gstack-ship-receipt:394 /ship Step 1.4 dry-run without --pregate cannot reach the generated carry (fails closed)
  • INFORMATIONAL bin/gstack-ship-receipt 8 untested state-matrix cells (dry-run variants)
  • INFORMATIONAL bin/gstack-ship-receipt:146 write and a rebase carry compute product_patch_id under different regen evidence or stamp demotion, so an exact tree can be refused RECEIPT_CARRY_PRODUCT_CHANGED (fails closed)
  • INFORMATIONAL bin/gstack-ship-receipt:504 covered trees trust receipt.head_tree from the PR body without cross-checking from^{tree}
  • INFORMATIONAL bin/gstack-ship-receipt:507 carry --base override lets the caller pick the base for both patch-ids (predates this PR)
  • INFORMATIONAL lib/regen.ts:254 a verdict-run command failure skips the scratch reset, so later entries in the same check can print misleading lines (the verdict is already REGEN_COMMAND_FAILED; predates this PR)

Exploratory QA

Not run as a separate charter: the surface is a CLI exercised end to end by the carry tests above (real git repos, a fresh clone, real merges and rebases).

Design Review

No frontend files changed — design review skipped.

Eval Results

No prompt-related files changed — evals skipped.

Greptile Review

No Greptile comments.

Plan Completion

GSTA-147 PR 1 (receipt carry): both items delivered, carry across proven regenerated outputs and carry across rewritten history. Proportional review depth is PR 2.

Issues

Refs #3564

Verification Results

3 PASS, 0 FAIL, 0 BLOCKED, 0 NOT RUN: a rebase onto a covered tree carries from a fresh clone; any other tree refuses; a registered output carries only with a proving pregate from the same registry.

TODOS

No TODO items completed in this PR.

Documentation

Status: updated. Four factual corrections in three docs about receipt carry; no blockers.

Scope: the committed diff of gsta147-carry-rules against 4c745ee, head bf9a417 (17 files; nothing staged, unstaged or untracked). Docs audited: docs/ship-policy.md (receipt and receipt-carry sections), docs/troubleshooting.md (carry entries), docs/unattended.md, docs/captain.md, docs/pregate.md, captain/templates/CREW.md, ship/SKILL.md.tmpl (Step 1 carry check). CHANGELOG.md was read and not edited.

Documentation health

File Status
docs/ship-policy.md Updated: the receipt evidence list adds head_tree and product_patch_id; the carry record lists ancestry and trees
docs/troubleshooting.md Updated: the RECEIPT_CARRY_PRODUCT_CHANGED Fix names proven regenerated outputs and the rebase onto a covered tree
docs/unattended.md Updated: a stray leading comma in the carry paragraph moved
docs/pregate.md Current: the regen proven bullet matches lib/regen.ts
docs/captain.md Current
captain/templates/CREW.md Current
ship/SKILL.md.tmpl Current (minor: Step 1.4 does not mention rebases; see debt)
CHANGELOG.md Not edited (parent owns it)

Coverage debt: the carry's generated class, the regen proven field, head_tree/product_patch_id and RECEIPT_CARRY_TREE_MISMATCH have reference and explanation coverage (ship-policy.md, pregate.md, troubleshooting.md), and the delta /ship sequence covers the how-to. No tutorial walks through recovering a receipt after a rebase (common gap). ship/SKILL.md.tmpl Step 1.4 and two section headings still describe only the merge and test-only cases.

Diagram drift: none; no diagrams reference the changed modules.

Test plan

🤖 Generated with Claude Code

…wed tree after a rebase

A base merge whose only product-side change is a registered output the
pregate regen check proved fresh now carries the receipt. A rebased head
carries when its tree is one the receipt covers and its product patch-id
against the current base matches (RECEIPT_CARRY_TREE_MISMATCH otherwise).
Docs: merge main into a reviewed branch, never rebase it.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
@trunk-io

trunk-io Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

😎 This pull request was merged.

garrytan and others added 2 commits October 28, 2026 23:03
Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
The regen check deletes each touched output in its scratch worktree before
the command runs and records the ones recreated byte-identically as proven.
gstack-ship-receipt carry exempts only those paths, and only when the check
ran origin/<base>'s registry at the commit the carry reads. A file under an
output glob that the generator never writes stays product (pre-landing
review, #3564 pass 1).

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
garrytan and others added 2 commits October 28, 2026 23:54
The regen verdict comes from the unmodified run again, so a generator that
reads its own registered output (gen-skill-docs and
qa/templates/functional-report-template.md) passes as before; the proof is a
second run with the touched outputs deleted, and its failure only means not
proven. The carry ignores a proven path with glob syntax, since it uses the
paths as pathspec globs (pre-landing review, #3564 pass 2).

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
…x line

Documentation audit for #3564 (/document-release, audit ship3564-docs-1).

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>
@github-actions github-actions Bot changed the title ship-receipt: carry across regenerated outputs and onto a reviewed tree after a rebase v1.91.306.0 ship-receipt: carry across regenerated outputs and onto a reviewed tree after a rebase Oct 29, 2026
@capy-ai
capy-ai Bot merged commit de4c694 into main Oct 29, 2026
63 checks passed
capy-ai Bot added a commit that referenced this pull request Oct 29, 2026
…ith depth-checked receipts (#3567)

* feat(ship-receipt): carry across regenerated outputs and onto a reviewed tree after a rebase

A base merge whose only product-side change is a registered output the
pregate regen check proved fresh now carries the receipt. A rebased head
carries when its tree is one the receipt covers and its product patch-id
against the current base matches (RECEIPT_CARRY_TREE_MISMATCH otherwise).
Docs: merge main into a reviewed branch, never rebase it.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: regenerate doctor anchors; type the head_tree assert

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(review): proportional /ship review depth (light, standard, full)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: carry sets aside only outputs the regen check proved it recreates

The regen check deletes each touched output in its scratch worktree before
the command runs and records the ones recreated byte-identically as proven.
gstack-ship-receipt carry exempts only those paths, and only when the check
ran origin/<base>'s registry at the commit the carry reads. A file under an
output glob that the generator never writes stays product (pre-landing
review, #3564 pass 1).

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(ship-receipt): record review depth, check it in the queue, structured review-loop exception (#3559)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: prove generated outputs in a second regen run; literal names only

The regen verdict comes from the unmodified run again, so a generator that
reads its own registered output (gen-skill-docs and
qa/templates/functional-report-template.md) passes as before; the proof is a
second run with the touched outputs deleted, and its failure only means not
proven. The carry ignores a proven path with glob syntax, since it uses the
paths as pathspec globs (pre-landing review, #3564 pass 2).

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: receipt evidence keys and carry record fields; carry refusal fix line

Documentation audit for #3564 (/document-release, audit ship3564-docs-1).

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: pre-landing review fixes (depth scan binding, queue scope, carry checks)

- carry refuses a --head other than the checked-out HEAD, a receipt with
  gstack_version but no review_depth, and an owner exception that no longer
  stands; a dirty or foreign checkout makes the write-time gate scan
  unavailable (full)
- the queue binds a gate scan only to the full bound commit and recomputes
  the scope signals with gstack-diff-scope <base> --head <sha>, the same
  range the writer uses
- the queue checks the review-loop exception's fix-check ancestry
- a package.json version line counts as stamp-only only when it is a bare
  version key
- docs and help name what review_depth is and which registry the queue reads

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: CHANGELOG for the review fixes; defer two plan items to TODOS

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: queue and carry refusal lists name the depth and exception codes

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: approval-classes summary-line regexes allow the receipt's depth field

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(ship-receipt): summary line prints depth before approval

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* Revert "test: approval-classes summary-line regexes allow the receipt's depth field"

This reverts commit e9ec264.

---------

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
capy-ai Bot added a commit that referenced this pull request Oct 29, 2026
#3572)

* feat(ship-receipt): carry across regenerated outputs and onto a reviewed tree after a rebase

A base merge whose only product-side change is a registered output the
pregate regen check proved fresh now carries the receipt. A rebased head
carries when its tree is one the receipt covers and its product patch-id
against the current base matches (RECEIPT_CARRY_TREE_MISMATCH otherwise).
Docs: merge main into a reviewed branch, never rebase it.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: regenerate doctor anchors; type the head_tree assert

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(review): proportional /ship review depth (light, standard, full)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: carry sets aside only outputs the regen check proved it recreates

The regen check deletes each touched output in its scratch worktree before
the command runs and records the ones recreated byte-identically as proven.
gstack-ship-receipt carry exempts only those paths, and only when the check
ran origin/<base>'s registry at the commit the carry reads. A file under an
output glob that the generator never writes stays product (pre-landing
review, #3564 pass 1).

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(ship-receipt): record review depth, check it in the queue, structured review-loop exception (#3559)

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: prove generated outputs in a second regen run; literal names only

The regen verdict comes from the unmodified run again, so a generator that
reads its own registered output (gen-skill-docs and
qa/templates/functional-report-template.md) passes as before; the proof is a
second run with the touched outputs deleted, and its failure only means not
proven. The carry ignores a proven path with glob syntax, since it uses the
paths as pathspec globs (pre-landing review, #3564 pass 2).

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: receipt evidence keys and carry record fields; carry refusal fix line

Documentation audit for #3564 (/document-release, audit ship3564-docs-1).

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: pre-landing review fixes (depth scan binding, queue scope, carry checks)

- carry refuses a --head other than the checked-out HEAD, a receipt with
  gstack_version but no review_depth, and an owner exception that no longer
  stands; a dirty or foreign checkout makes the write-time gate scan
  unavailable (full)
- the queue binds a gate scan only to the full bound commit and recomputes
  the scope signals with gstack-diff-scope <base> --head <sha>, the same
  range the writer uses
- the queue checks the review-loop exception's fix-check ancestry
- a package.json version line counts as stamp-only only when it is a bare
  version key
- docs and help name what review_depth is and which registry the queue reads

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: CHANGELOG for the review fixes; defer two plan items to TODOS

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* feat(ship-receipt): carry a stacked child after its parent lands (#3570)

When the carry base differs from the receipt's (a stack parent landed and
the PR was retargeted), the receipt carries only when HEAD's product diff
against the base equals the range reviewed against the parent branch.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: queue and carry refusal lists name the depth and exception codes

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix: pre-landing review fixes

A retargeted carry compared the reviewed range with a patch-id whose pathspec
came from the reviewed head..HEAD range, so a parent's package.json change
that never reached the base dropped out and the receipt carried. Compare with
HEAD's whole product patch-id against the base (the one write records), rebind
the receipt's base on a retarget carry, and cover the parent-metadata, landed-
with-changes and test-only-child cases.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* test: approval-classes summary-line regexes allow the receipt's depth field

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* docs: troubleshooting names the stacked-retarget carry refusals

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* fix(ship-receipt): summary line prints depth before approval

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* Revert "test: approval-classes summary-line regexes allow the receipt's depth field"

This reverts commit e9ec264.

* test: assert a retarget carry rebinds review_depth to the new base and binds at the queue; docs: split the --head carry advice

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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant