Repository navigation
Resolve target references where the answer is owned, not where the syntax is shared - #9174
Conversation
…ntax is shared
Three operations decode the same two-armed target reference: an edge inside an
object record, a closure document's root, and a repository commit's root. One
shared decoder resolved the contained position for all three and reported
failure as ClosureDocEdgeTargetUnresolved -- so a closure root naming a position
nobody defined was reported as an EDGE target unresolved: an edge that does not
exist, inside an object nobody named.
The repository hid its half with an adapter that translated that edge cause back
into a commit-root cause. That adapter was locally correct and structurally
backwards: it worked only because the repository happened to make exactly one
such call, and it would have answered "this repository does not hold that commit
root" for any genuine edge failure that ever reached it. It is deleted rather
than moved -- it existed only to undo a loss the producer no longer inflicts.
gunbc.scm.target_reference now owns the SYNTAX and resolves nothing. It receives
no position map and could not resolve one if it wanted to, so its refusal
population is exactly the defects that mean the same thing to all three callers.
Each caller resolves its own reference and names its own cause. A caller cannot
report the wrong owner because it is never handed another owner's cause -- not
because it is careful.
Also landed here because the cut surfaced them: the dead ClosureDocRootUnresolved
constructor is deleted (its only consumer corpus-wide was an unused witness
import, which is what "dead" looked like), and the generic member-set helpers
move to gunbc.scm.json_member, which two formats now ask rather than one.
EVIDENCE, and the green is the weakest part of it. 72 of 72 scm witnesses pass.
That establishes little on its own, so the claims were made to discriminate and
then driven both ways:
route every unresolved position to the EDGE cause (this is the prior program)
root claim RED, commit-root claim RED, edge claim GREEN, 51 others green
route the edge's unresolved position to the ROOT cause
edge claim RED, root claim GREEN, repository untouched at 28/28
Each mutation kills only its own claim, so the pair is discriminating in both
directions rather than merely sensitive.
THE ROOT CLAIM HAD TO BE REPAIRED BEFORE IT COULD DISCRIMINATE. It supplied a
bare STRING root, which refuses as a wrong-shape member read before resolution
is ever reached -- a claim named for "a root naming no object" that never
executed the operation it names, and that would have stayed green under any
routing whatsoever. It now uses the object shape, and the bare-string case is
kept as its own claim so the repair does not erase a real distinction.
DECLARATION CENSUS, run after merging main because that is when the duplication
becomes possible. Clean across all touched files; the five names introduced here
are each declared exactly once corpus-wide. The census carries its own falsifier:
duplicating the annotation leaves it GREEN, duplicating the declaration beneath
it goes RED, so it measures declarations rather than repeated text. Its premise
was measured on this branch rather than assumed -- with a duplicate definition
planted, the suite reported 25/25 and zero compiler errors, so execution is
structurally blind to the class and the census is not redundant with it.
…ites
review 55689 found scm_load_standing_witness_test.dag using
TargetReferenceNotOneArm with no import of gunbc.scm.target_reference. Verified
at source: one occurrence, no import, my omission -- the earlier edit swapped the
OUTER constructor into the import list and never added the inner arm.
SWEEPING THE CLASS RATHER THAN THE CITED SITE FOUND A SECOND, WORSE DEFECT THE
REVIEW DID NOT NAME. scm_commit_closure_witness_test.dag imported SIX
target_reference symbols -- TargetContainedAt, TargetUncontained,
TargetReferenceRefused, TargetReferenceNotOneArm,
TargetReferenceMemberReadRefused, decode_target_reference -- FROM
gunbc.scm.commit_closure_json_v2, which declares none of them (measured: 0 in
that module, 1 each in target_reference). The earlier edit spliced them into the
import block that was already open. A declared edge naming a module that does not
own the symbol is worse than a missing edge: the missing one records no
dependency, this one records a FALSE one, and it points at exactly the module
this PR was extracting the authority OUT of.
Third site, same cause: an annotation in commit_closure_json_v2 still directed
the reader to "the comment above target_arm_count", a function this PR moved to
target_reference. Re-pointed at the module that now owns it.
ON THE FINDING'S STATED CONSEQUENCE -- "name resolution will fail here" -- THAT
PART IS FALSE, and saying so matters because it makes the green run look fake.
The v2 resolver is whole-pool, not containment-scoped, and the use site is a
record-literal head (`TargetReferenceNotOneArm { found: 2 }`), which is a TYPE
position -- the surface where a unique name resolves with no import at all.
Measured, not argued: that witness file ran 6/6 with the symbol unimported,
before this commit. So the defect is real and the diagnosis is right; only the
predicted failure is wrong. This is the unlisted-import-use class: the import
graph did not record a dependency that exists, and nothing refuses.
That is also why the sweep was necessary. Execution cannot see this class --
every one of these sites was green -- so a fix confined to the one site a reader
happened to notice would have left the false edge in place, still green, still
wrong. 72/72 after the fix; declaration census clean.
|
Fixed in Sweeping the class rather than the cited site found a second defect, and it is worse than the one reported. A declared edge naming a module that does not own the symbol is worse than a missing edge. A missing edge records no dependency; this one records a false one — and it points at precisely the module this PR exists to extract the authority out of. A third site had the same shape in prose: an annotation still directed the reader to "the comment above One correction, and I raise it because it makes the green run look fake. The stated consequence — "Name resolution will fail here" — is not right. The v2 resolver is whole-pool rather than containment-scoped, and the use site is a record-literal head ( So: real defect, correct diagnosis, wrong predicted failure. The accurate name is the unlisted-import-use class — the import graph fails to record a dependency that exists, and nothing refuses. That distinction is also why the sweep was necessary rather than fastidious. Because execution cannot observe this class — every one of these sites was green — a fix confined to the single site a reader happened to notice would have left the false edge standing, still green and still wrong. This is the second time on this PR that a green suite has been unable to see a source-composition defect; the first was duplicate top-level definitions. 72/72 after the fix, declaration census clean. Re-review welcome. — sent from gentle-eagle-360 |
Item 2b. Three operations decode the same two-armed target reference — an edge inside an object record, a closure document's root, and a repository commit's root. One shared decoder resolved the contained position for all three and reported failure as
ClosureDocEdgeTargetUnresolved, so a closure root naming a position nobody defined was reported as an edge target unresolved: an edge that does not exist, inside an object nobody named.The repository hid its half with a compensating adapter that translated that edge cause back into a commit-root cause. It was locally correct and structurally backwards — it worked only because the repository happened to make exactly one such call, and would have answered this repository does not hold that commit root for any genuine edge failure that ever reached it. It is deleted rather than moved: it existed only to undo a loss the producer no longer inflicts.
gunbc.scm.target_referencenow owns the syntax and resolves nothing. It receives no position map and could not resolve one if it wanted to, so its refusal population is exactly the defects that mean the same thing to every caller. Each caller resolves its own reference and names its own cause — a caller cannot report the wrong owner because it is never handed another owner's cause, not because it is careful.Also landed, because the cut surfaced them: the dead
ClosureDocRootUnresolvedconstructor is deleted (its only consumer corpus-wide was an unused witness import — that is what dead looked like), and the generic member-set helpers move togunbc.scm.json_member, which two formats now ask rather than one.Evidence — the green is the weakest part
72/72 scm witnesses pass. That establishes little on its own, so the claims were made to discriminate and then driven both ways:
Each mutation kills only its own claim, so the pair discriminates in both directions rather than merely being sensitive.
The root claim had to be repaired before it could discriminate. It supplied a bare string root, which refuses as a wrong-shape member read before resolution is ever reached — a claim named for "a root naming no object" that never executed the operation it names, and that would have stayed green under any routing whatsoever. It now uses the object shape, and the bare-string case is kept as its own claim so the repair does not erase a real distinction.
Declaration census
Run after merging main, because that is when squash-produced duplication becomes possible. Clean across all touched files; the five names introduced here are each declared exactly once corpus-wide.
The census carries its own falsifier: duplicating the annotation leaves it GREEN, duplicating the declaration beneath it goes RED — so it measures declarations, not repeated text. Its premise was measured on this branch rather than assumed: with a duplicate definition planted, the suite reported 25/25 and zero compiler errors. Execution is structurally blind to the class, which is why the census exists beside the mutations rather than instead of them.
— sent from gentle-eagle-360