Found during the spec review on #55's branch. Deferred from #55 with an owner
rather than swept there: converting it ripples through three callers, each
needing its own post-fault decision, and #55 already converts nine sites.
Problem
tracked_in_index (.github/scripts/check-records.sh:371) is a two-valued
predicate over a git query:
tracked_in_index() {
local path=$1
git ls-files --error-unmatch -- "$path" >/dev/null 2>&1
}
git ls-files --error-unmatch exits 1 when the path is not tracked — the
ordinary negative — and non-zero for a real fault, with stdout and stderr both
discarded so the status is the only signal. The two collapse, which is the defect
class ADR 0005 (landing with #55) records: a scan that could not run is reported
as one that ran and found nothing.
Three callers treat the collapsed result as authoritative:
renumbered_elsewhere:415 — tracked_in_index "$candidate" || continue, a
literal in-charter cmd || continue. A fault silently drops a candidate from
the renumber search, so a genuinely renumbered record reports E-GONE.
check_no_disappearances:581 — decides whether a record is present as a real
tracked file, and so whether the anti-erasure rules run against it at all.
check_gate_files:739 — decides whether a renamed gate file's successor is
really tracked, which is what separates an exempted rename from E-GATE-GONE.
Expected
Per ADR 0005: tracked_in_index becomes three-valued — 0 tracked, 1 not
tracked, 2 fault — capturing git ls-files' status rather than discarding it,
and each of the three callers cases on the result and reports the fault instead
of its ordinary negative verdict.
Each caller needs its own decision about what the fault means, which is the work
here and the reason it is not folded into #55:
renumbered_elsewhere — a fault on one candidate must not outrank a positive
match on another; it is remembered and returned only if the loop exhausts.
check_no_disappearances — a fault must not let a record skip the
append-only rules silently.
check_gate_files — a fault must not exempt a rename it could not verify.
A regression test per caller, using the PATH-stubbed git shape #55 introduces.
Note the callers are reached through different fixtures, and a stub keyed only on
ls-files will fire for whichever caller runs first — the stub needs to key on
the path argument as well.
Notes
.github/scripts/check-records.sh has a byte-identical mirror under
skills/tome-of-lore/assets/; the fix lands twice. just records compares them.
Best done after #55 lands, which introduces the three-valued predicate
convention and the git stub harness this would reuse.
Related: #25 (PR #54), #55, #63, #64, #66. ADR 0005 states the rule.
Found during the spec review on #55's branch. Deferred from #55 with an owner
rather than swept there: converting it ripples through three callers, each
needing its own post-fault decision, and #55 already converts nine sites.
Problem
tracked_in_index(.github/scripts/check-records.sh:371) is a two-valuedpredicate over a git query:
git ls-files --error-unmatchexits 1 when the path is not tracked — theordinary negative — and non-zero for a real fault, with stdout and stderr both
discarded so the status is the only signal. The two collapse, which is the defect
class ADR 0005 (landing with #55) records: a scan that could not run is reported
as one that ran and found nothing.
Three callers treat the collapsed result as authoritative:
renumbered_elsewhere:415—tracked_in_index "$candidate" || continue, aliteral in-charter
cmd || continue. A fault silently drops a candidate fromthe renumber search, so a genuinely renumbered record reports
E-GONE.check_no_disappearances:581— decides whether a record is present as a realtracked file, and so whether the anti-erasure rules run against it at all.
check_gate_files:739— decides whether a renamed gate file's successor isreally tracked, which is what separates an exempted rename from
E-GATE-GONE.Expected
Per ADR 0005:
tracked_in_indexbecomes three-valued —0tracked,1nottracked,
2fault — capturinggit ls-files' status rather than discarding it,and each of the three callers
cases on the result and reports the fault insteadof its ordinary negative verdict.
Each caller needs its own decision about what the fault means, which is the work
here and the reason it is not folded into #55:
renumbered_elsewhere— a fault on one candidate must not outrank a positivematch on another; it is remembered and returned only if the loop exhausts.
check_no_disappearances— a fault must not let a record skip theappend-only rules silently.
check_gate_files— a fault must not exempt a rename it could not verify.A regression test per caller, using the PATH-stubbed
gitshape #55 introduces.Note the callers are reached through different fixtures, and a stub keyed only on
ls-fileswill fire for whichever caller runs first — the stub needs to key onthe path argument as well.
Notes
.github/scripts/check-records.shhas a byte-identical mirror underskills/tome-of-lore/assets/; the fix lands twice.just recordscompares them.Best done after #55 lands, which introduces the three-valued predicate
convention and the
gitstub harness this would reuse.Related: #25 (PR #54), #55, #63, #64, #66. ADR 0005 states the rule.