pgc_ledger.py orphan-scan reports a ledger row that no record in its own part matches. A row whose check was ADDED after the log was written produces exactly that signal, and nothing in a RESULT record — suite, part, name, verdict, major — dates it against a tree.
So a stale log and a genuinely deleted check are indistinguishable, and the tool cannot close the gap from inside.
Measured, not hypothetical
Replaying a log from #1070's tree against the ledger one commit later:
orphan scan: parts in the run=46, rows in those parts=967,
orphans=2 (0 carrying history), unprunable=0, not checked=263
Both "orphans" were the part-400 checks that tree had just gained. Against a log from the same tree: orphans=0, rc=0.
I was one step from reporting a defect in a tool merged an hour earlier. The failure mode reads exactly like the defect the subcommand exists to find, which is what makes it worth a guard rather than a note.
Today's caller is safe by construction; that is the reason to act, not to wait
run_all_versions.sh passes the logs from the run it has just finished, so freshness is structural — nobody chooses it. #1072 documents that. A caller supplying a log by hand has no such guarantee, and the difference is invisible at the call site.
The shape of a fix
A log should carry something that identifies the tree it came from, and orphan-scan should refuse a log whose identifier does not match what it was told to expect.
The harness already computes a suitable one: the .so fingerprint in test/pgc_fingerprint.py, which part 340 exercises at length. Nothing new needs inventing; it needs emitting into the log and reading back.
Two things to decide rather than assume:
- Where the expectation comes from. Refusing a mismatch needs a value to compare against. The runner knows its own build; a hand caller may not, so the flag probably has to be opt-in rather than the default, or the tool refuses every hand invocation.
- Whether other subcommands want it.
gate, merge and rename-scan all read the same logs. merge stamping a stale log into the ledger is arguably worse than orphan-scan misreporting one, because it persists.
Not urgent
One caller today and it is safe by construction. This is worth doing when a second caller appears, or when someone is next in pgc_ledger.py anyway — filed so the reasoning is not lost in a merged PR's commit message.
Raised with @OffgridwithJD, whose framing this is: a precondition the tool cannot check belongs to the caller, and should be named rather than assumed.
🤖 Generated with Claude Code
https://claude.ai/code/session_01NhwXKAgSmYDUjteWkfajHK
pgc_ledger.py orphan-scanreports a ledger row that no record in its own part matches. A row whose check was ADDED after the log was written produces exactly that signal, and nothing in a RESULT record — suite, part, name, verdict, major — dates it against a tree.So a stale log and a genuinely deleted check are indistinguishable, and the tool cannot close the gap from inside.
Measured, not hypothetical
Replaying a log from #1070's tree against the ledger one commit later:
Both "orphans" were the part-400 checks that tree had just gained. Against a log from the same tree:
orphans=0, rc=0.I was one step from reporting a defect in a tool merged an hour earlier. The failure mode reads exactly like the defect the subcommand exists to find, which is what makes it worth a guard rather than a note.
Today's caller is safe by construction; that is the reason to act, not to wait
run_all_versions.shpasses the logs from the run it has just finished, so freshness is structural — nobody chooses it. #1072 documents that. A caller supplying a log by hand has no such guarantee, and the difference is invisible at the call site.The shape of a fix
A log should carry something that identifies the tree it came from, and
orphan-scanshould refuse a log whose identifier does not match what it was told to expect.The harness already computes a suitable one: the
.sofingerprint intest/pgc_fingerprint.py, which part 340 exercises at length. Nothing new needs inventing; it needs emitting into the log and reading back.Two things to decide rather than assume:
gate,mergeandrename-scanall read the same logs.mergestamping a stale log into the ledger is arguably worse thanorphan-scanmisreporting one, because it persists.Not urgent
One caller today and it is safe by construction. This is worth doing when a second caller appears, or when someone is next in
pgc_ledger.pyanyway — filed so the reasoning is not lost in a merged PR's commit message.Raised with @OffgridwithJD, whose framing this is: a precondition the tool cannot check belongs to the caller, and should be named rather than assumed.
🤖 Generated with Claude Code
https://claude.ai/code/session_01NhwXKAgSmYDUjteWkfajHK