Uh oh!
There was an error while loading. Please reload this page.
fix(pm): governed-merge sweep family — origin identity, per-repo windows, sweep-code provenance, precondition attribution - #13945
Merged
Conversation
…tHub slug An unparseable origin (filesystem path, SSH shorthand, no origin remote at all) used to slip the wrong-origin guard — `if (seen.slug && ...)` — and fall through to `status: 'audited'` under the governed name with no evidence of identity. The checkout now refuses with a NOT MEASURED row naming the declared origin and the remedy; `audited` is reachable only through a parsed, matching slug. Identity is read from the RAW configured origin URL (`git config --get remote.origin.url`), never `remote get-url`, which applies insteadOf transport rewrites first. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Msg17tAHJ3jVTYFgHydCm2
…only in self The topological window's fallback-date derivation resolved every named --since-ref in the self checkout (objectstack) only and errored hard when none resolved there, so a sweep pinning only sibling-repo tips exited 1 `does not resolve to a commit` on refs that resolve perfectly in their own repositories. resolveWindow now takes resolveRefDate(ref, repoId): an <id>=<ref> pin resolves in that repo's own checkout, a bare ref in every governed checkout, and the hard failure survives only where it is honest — no named ref resolves in ANY repo it names. Checkout resolution moves ahead of window resolution so the per-repo resolver knows each repo's path. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Msg17tAHJ3jVTYFgHydCm2
…table
The reachability probe was never gated on --repo-root — it runs for every
resolved checkout in every window mode. The post-fix runs that still printed
the cloud false green quoted a row text ('if that tip predates your last
fetch...') that exists only in the pre-fix render: they executed a PRE-FIX
copy of this script from a stale tree, and nothing in the output said which
version ran. The sweep header now prints 'sweep code:' — the executing
tree's HEAD plus this file's own blob id, with a loud mismatch line when the
running bytes are not the copy HEAD records, and a stated UNKNOWN when the
reads fail. Attribution, not prevention: a stale tree prints a stale sha,
truthfully, and the reading becomes checkable.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Msg17tAHJ3jVTYFgHydCm2…d, and pin the shallow-clone path Two identical invocations minutes apart flipped objectui between audited (12 entries) and unaudited (zero), and the footers differed only by a slug list. Root cause by enumeration plus reproduction: for a topologically pinned repo the only per-run preconditions that can change with zero local writes are the freshness leg's — the shallow-boundary-connectivity hypothesis is structurally unreachable in that mode (the horizon guard runs only under a date window; the anchor resolves from the object store; the enumeration reads the local graph). The flip is the freshness leg failing closed on a busy remote — the safe direction — and what it owed was attribution: every unaudited row now carries a machine-readable precondition category, printed on the row, per-repo in the INCOMPLETE footer and the all-refused failure, and in --json. Self-test adds the shallow-clone path in both directions (deep-enough audits naming its floor; floor-inside-window refuses, precondition named) and reproduces the flip on real fixtures: the same argv audits, the remote takes one push, it refuses BEHIND. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Msg17tAHJ3jVTYFgHydCm2
os-sam
marked this pull request as ready for review
August 31, 2026 18:33
os-sam
enabled auto-merge
August 31, 2026 18:33
Uh oh!
There was an error while loading. Please reload this page.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes#13307
Fixes#13423
Fixes#13424
Fixes#13836
Family dispatch: four defects, one file (
scripts/pm/check-governed-merges.mjs), one fix discipline — every status measured, loud, attributable, self-tested. Per-member commits, in the family-index order; combined acceptance demonstrated in ONE run (below). Dev session: https://claude.ai/code/session_01Msg17tAHJ3jVTYFgHydCm2 (os-dev subagent seat under the dispatching skills PM).The answer the reopen demanded, in words: is the reachability probe gated on
--repo-root?NO — and it never was. In the landed fix (a40ab8d) the probe runs in the sweep loop for every repo whose checkout resolved, discovered conventionally or overridden, in every window mode; nothing keys it on
--repo-root.What actually happened to the two post-fix runs that still printed the cloud false green (16:5xZ and 19:0xZ on 2026-08-30): they executed a PRE-FIX copy of this script. Measured evidence: the row text they quoted ends with the phrase "if that tip predates your last fetch, run
git fetch origin mainthere". That render string exists in the parent commit 9268aec's quiet-row template and was REMOVED by a40ab8d, which replaced it with the MEASURED-zero / unmeasured-zero split (the only remaining occurrences in a40ab8d are docblock prose quoting the old hedge). A sweep invoked asnode scripts/pm/check-governed-merges.mjsfrom the shared checkout runs whatever version that tree's switched-around HEAD happens to hold, and nothing in the output said which — so a pre-fix reading was attributed to the landed fix.That un-attributability is the real residual defect, and it is what the #13307 commit fixes: the sweep header now prints a
sweep code:line — the executing tree's HEAD plus this file's own blob id, a loud mismatch warning when the running bytes are not the copy HEAD records, and a stated UNKNOWN when the reads fail. Attribution, not prevention: a stale tree prints a stale sha, truthfully, and the reading becomes checkable. (Also in--jsonassweepCode.)Leg 4, the decisive one — the sweep against the real
/home/user/cloudconfigurationThis container held no
/home/user/cloud(measured; the premise note on the card records the same). Per the dispatch's stated reading of leg 4's intent, the configuration was reconstructed at the conventional discovery path and removed after the run: a local git clone at/home/user/cloud, history fabricated to mimic the stale snapshot (one commit dated 2026-08-29T09:10:31Z,refs/remotes/origin/mainpointing at it),originset to the REALhttps://github.com/objectstack-ai/cloudURL — whose git channel failure is live in this container (measured immediately before the run:git ls-remote --exit-codeagainst that URL exits 128,fatal: could not read Username for github.com: terminal prompts disabled— the wire-level refusal shape this container's credential state produces for that repo; the API channel being back does not change it, and per the card: honesty first, an API probe is optional and never a substitute). No--repo-root cloud=was passed. The transient clone was deleted immediately after the run so no sibling seat can mistake it for a real checkout.The combined single run — all member controls in the SAME invocation (family-index acceptance)
Run from the committed worktree at head c62a787 (tree clean), objectui freshened first:
(SCRATCH is the session scratchpad; that fixture is a git repo whose declared origin is the local path
/srv/mirrors/objectos— a spellingslugFromRemotecannot parse. No objectstack pin. No cloud override.)Exit code: 2 (INCOMPLETE — non-zero as required). Output highlights, verbatim:
Member controls, all in this one run:
cloudrow is now a permanent false zero — the repo left the fleet's GitHub scope and the audit reads an unfetchable local snapshot instead of saying NOT MEASURED #13307 leg 4 (decisive): the conventionally discovered/home/user/cloudwith the real 404ing URL printsNOT MEASURED,[unreachable-remote], no audited row, exit non-zero. The original three legs also run: unreachable refuses (this row, live); reachable-plus-merge is reported (7 real objectui governed entries, attribution resolved: PRs 6984, 7000, 6981, 6963, 6974, 6976, 6908); reachable-plus-zero as a stated MEASURED zero is pinned end-to-end in--self-teston real bare-repo fixtures (a synthetic fixture is used only where this container cannot supply a live quiet repo — it is additional to, never a substitute for, the real-configuration leg above).[unparseable-origin] NOT MEASURED, naming the unparseable declared origin.--since-refin the SELF checkout only, so a sweep pinning only sibling-repo tips exits 1 on refs that resolve perfectly in their own repos #13424: the invocation pins ONLY a sibling tip (no objectstack pin) and produces a full report instead of the pre-fixexit 1, does not resolve to a commit(pre-fix behaviour reproduced on the unmodified base tree before the first edit: exit 1 on this same shape).Per-member deliverables
#13423 — the slug-parse hole (commit "refuse to audit a governed repo whose origin parses to no GitHub slug")
The guard
if (seen.slug and seen.slug differs)only fired when a slug WAS parsed. Now a null slug refuses with a NOT MEASURED row naming the declared origin, andauditedis reachable only through a parsed slug strictly equal to the governed one. Identity is read from the RAW configured origin URL (git config --get remote.origin.url) rather thangit remote get-url origin, which appliesinsteadOfrewrites first (measured: with a rewrite in force, get-url answers the rewrite target — a filesystem path — while the raw config still names github.com). The declared URL is the identity claim; transport (ls-remote) still resolves rewrites exactly as git does.Enumeration (the required answer): how many other "parse failure leads to a success branch" shapes existed in
resolveRepoCheckouts? Two entry points, one shape, and zero after the fix:slugFromRemotereturning null on an unparseable URL — the card's case; fell through toaudited.probeCheckout's inner catch (no origin remote at all, or unreadable config) returningexists true, slug null— the same fall-through, second entry point. Both now refuse with distinct stated reasons (unparseable URL vs no origin remote).exists falseand always refused (safe direction, not a member of the class);slugFromRemoteitself has no partial-success shape (full match or null).After the fix the enumeration is zero by construction:
auditedis the single fall-through and requires a parsed, matching slug. Non-vacuity control: pure pins for both null-slug shapes, plus an end-to-end sweep over a real clone keeping its local-path origin — refused, where the base tree audited it (reproduced on base before the first edit).#13424 — per-repo window resolution (commit "resolve every --since-ref in its own repo's checkout, never only in self")
resolveWindownow takesresolveRefDate(ref, repoId): a pin resolves in the repo it names, a bare ref across every governed checkout, oldest resolved date wins (unchanged conservative choice), and the hard failure survives only when no named ref resolves in ANY repo it names — with the per-repo semantics stated in the error text so the constraint is declared, not incidental. Checkout resolution moved ahead of window resolution so the resolver knows each repo's path (re-run in the re-exec'd child; a handful of local git reads, paid twice by design).Enumeration (the required answer): which other places resolve multi-repo input in the self checkout only? After the fix,
grep -n "git(selfRoot"over the file returns zero call sites. Reviewed each remainingselfRootuse: the self repo's own checkout path (single-repo input by definition),siblingDirderivation, and the--rootflag.topologicalBaseInwas already per-repo (resolves inrepo.path);--repo-rootoverrides are per-repo by construction; attribution is keyed by each entry's own repo slug. The window's fallback-date derivation was the only instance.Non-vacuity: base-tree control reproduced before the first edit (
--since-ref objectui=TIPexits 1does not resolve to a commitwhile the ref resolves in objectui); after the fix the identical shape reports (combined run above), the self-test pins the pure semantics (sibling-only pin resolves; a self-only resolver control still errors; a pinned ref is asked ONLY of its own repo — call-recording pin), and an end-to-end fixture sweep pins the sibling-pin invocation at exit 0.#13307 — sweep-code provenance (commit "print which sweep code ran, so a stale-script run is attributable")
Covered above. Constraints honoured:
cloudstays inGOVERNED_REPOS(zone-1 ruling; the docblock still forbids dropping it); the maintainer question "is cloud still in platform scope" remains open and unanswered in code; no--unshallowor--shallow-sincewas run on any shared checkout (the reconstruction was a fresh transient clone, deleted after the run).#13836 — precondition attribution + the flip root-caused (commit "attribute every unaudited row to the precondition that failed, and pin the shallow-clone path")
Root cause, by enumeration plus reproduction — and the card's first suspect is falsified. For a repo pinned topologically (its anchor resolving), the only preconditions evaluated per run that can change with ZERO local writes are the freshness leg's: the remote probe and the tip-identity comparison. The shallow-boundary-connectivity hypothesis is structurally unreachable in that mode: the #9902 horizon guard runs only where a DATE window is in force (the
if (!base)branch), the anchor resolves from the object store (an upstream push moves neither), and enumeration reads the local graph. The flip is the freshness-by-identity leg failing closed on a busy remote — run 2's honest answer, in the safe direction (#4690), as often as the remote moves. Reproduced in--self-teston real fixtures: the same argv audits (exit 0, a true zero), the remote receives ONE push, the identical invocation refuses BEHIND — nothing local touched the mirror. (Which freshness sub-branch fired in the production run-2 — BEHIND vs a probe timeout — is exactly what its footer could not say; both now print attributably.)The fix (triage's order): every unaudited row carries a machine-readable precondition category —
no-checkout,unparseable-origin,wrong-origin,unreachable-remote,remote-tip-unreadable,local-tip-unreadable,stale-mirror,unprobeable-ref,history-horizon,ref-unreadable— printed on the row, per-repo in the INCOMPLETE footer and in the all-refused exit-1 message, and in--json. Two footers minutes apart now differ by a stated reason, never only by a slug list. (An unresolvable pin is deliberately NOT one of these: by the #12633 route-B ruling it falls back to the date window and the row says so via the fell-back note.)Shallow-clone self-test (the defect only shows on shallow clones): real fixtures over the file transport with backdated seed commits — a depth-2 clone whose floor predates the window audits and names its floor; a depth-1 clone whose floor sits inside the window refuses with
[history-horizon]named; and the flip reproduction above.Verification
pnpm check:pm-governed-merges(the file's own suite): 255 assertions, green — up from 230 on base; every run quoted below is from head c62a787 (git rev-parse --short HEADat the union run; the working tree was clean, and the combined run's ownsweep code:line names the same head and a matching blob).node scripts/pm/dispatch-gates.mjs, no paths, derived at c62a787 — 14 path-derived families plus 2 convention-triggered pluscheck:pm-governed-proseandcheck:nul-bytes): 17 PASS.node scripts/check-test-completeness.mjsexits 3, which that gate's own verdict text defines as NOT MEASURED, nothing to fix ("pass a saved turbo run test log — or, running the family locally, record this gate as NOT MEASURED") — recorded as such, not as a pass and not as a red. The derivation printed a stale-tree warning (origin/main moved 6 commits ahead during the run; none of those commits touch this file — verified by diff), so CI's own farm run is the authority on any family added upstream today.--since-refin the SELF checkout only, so a sweep pinning only sibling-repo tips exits 1 on refs that resolve perfectly in their own repos #13424 exit 1 on the sibling-only pin; [finding] The governed-merge sweep audits a checkout whose origin does not parse to a GitHub slug — the wrong-origin refusal beside it has a hole, and reachability raises the bar without closing it #13423 null-slug fall-through toaudited(pure call).scripts/pm/only (tooling; nothing published from a package) —skip-changesetlabel applied at PR-open per the closed-list rule.Generated by Claude Code
Generated by Claude Code