Skip to content

refactor(stage): stage a pinned commit - #135

Merged
cabljac merged 1 commit into
mainfrom
gate/01-stage-source
Oct 19, 2026
Merged

cabljac merged 1 commit into
mainfrom
gate/01-stage-source

Conversation

@cabljac

@cabljac cabljac commented Oct 19, 2026 •

Copy link
Copy Markdown
Owner

The approval gate (0.15.0) needs stage to ship one exact commit: the mirror PR head that was approved, not whatever the local branch points at later. This is #122 rebased onto main, minus its cwd option, which only the parked venfork watch needed.

stageCommand gains the in-process option source: { sha }. It stages that full commit id under the branch name without reading refs/heads/<branch>; a short id, a bad branch name or a missing commit is a precondition refusal before any fetch. Without source, stage now reads the branch tip once, before the fetches, so a branch that moves during a fetch can no longer ship a tip other than the one recorded. The PR step records shippedBranches[branch].sourceHead. The CLI never sets source.

Tests, red first: sourceHead cases in tests/unit/commands.test.ts and tests/unit/config.test.ts, and pinned-commit and moved-branch cases in tests/integration/stage.test.ts. bun run verify exits 0. Counts: unit 1258 to 1260, integration 469 to 474.

Not verified: e2e tiers and live GitHub. Part of the 0.15.0 approval gate stack; supersedes #122.

stageCommand gains an in-process option `source: { sha }`. It stages
that full commit id under the branch name without reading
refs/heads/<branch>; a short id, an invalid branch name or a commit
missing from the clone is a PreconditionError before any fetch. Every
gate, the deny-list scans, redaction and the confirm stay on the same
path. The approval gate uses it so the approved commit is exactly what
ships. getDefaultBranch('upstream') now gets the clone directory instead
of falling back to process.cwd().

Without `source`, stage now reads the local branch tip once, before the
fetches, and the merge-base check, the merge scan and the rebuild all
use that commit id. Before, they re-read refs/heads/<branch> after the
fetches, so a branch moved during the fetch shipped the new tip while
sourceHead named the old one.

The PR step now records shippedBranches[branch].sourceHead, the mirror
commit that was staged (head is the rebuilt commit). Normalization keeps
it when it is a string. The CLI never sets `source`.
@cabljac
cabljac force-pushed the gate/01-stage-source branch from 52fa887 to 413f4e6 Compare October 19, 2026 17:26
@cabljac
cabljac marked this pull request as ready for review October 19, 2026 17:28
@cabljac
cabljac added this pull request to stack #142 October 19, 2026 17:29
@cabljac
cabljac merged commit dc56345 into main Oct 19, 2026
4 checks passed
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