Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

E1 — Anchor survival (RESULT)

Gates: BC2. Run after E0 passes; results decide schema/claim.schema.json’s anchor object. Status: COMPLETE. Result: ALL STRATEGIES USABLE. Proceed with multi.

Question

For each anchoring strategy in docs/anchoring.md, what fraction of anchors still identify the intended code after a realistic refactor sequence?

Method

5 repositories, 20 synthetic anchors each (100 total), 20 commits replayed forward per repo. For each anchor and each strategy, recorded: resolved correctly / resolved to wrong code / failed to resolve. Commits classified as reformat, semantic, rename, delete, or other.

Repositories:

RepositorySourceCommitsLanguage
kisekilocal (user)937Rust, Go, Python
yoyo-evolveexternal (yologdev)5286Rust
tokioexternal (tokio-rs)815Rust
cobraexternal (spf13)205Go
httpxexternal (encode)200Python

READ-ONLY: No commits to any repo. Only git history was read.

Results

Aggregate per strategy

StrategyCorrectWrongFailedTotalCorrect%Wrong%
path-range1989101200099.5%0.5%
symbol1988120200099.4%0.6%
content-digest1989011200099.5%0.0%
multi1988120200099.4%0.6%

Breakdown by refactor class

StrategyClassCorrectWrongFailedTotalCorrect%Wrong%
path-rangereformat200020100.0%0.0%
path-rangesemantic1949101196099.4%0.5%
path-rangeother200020100.0%0.0%
symbolreformat200020100.0%0.0%
symbolsemantic1948120196099.4%0.6%
symbolother200020100.0%0.0%
content-digestreformat200020100.0%0.0%
content-digestsemantic1949011196099.4%0.0%
content-digestother200020100.0%0.0%
multireformat200020100.0%0.0%
multisemantic1948120196099.4%0.6%
multiother200020100.0%0.0%

Pre-registered thresholds

StrategyVerdict
path-rangeUSABLE (correct >= 85%, wrong <= 2%)
symbolUSABLE (correct >= 85%, wrong <= 2%)
content-digestUSABLE (correct >= 85%, wrong <= 2%)
multiUSABLE (correct >= 85%, wrong <= 2%)

Key findings

content-digest has ZERO wrong-resolutions

Content-digest is the safest strategy: it never silently misresolves. When the anchored content is changed (semantic edit), it fails to find it (11 cases, all loud failures). When the code is reformatted, the normalized content is unchanged, so it resolves correctly (20/20). This is by design — normalization removes whitespace and comments, so reformats don’t affect the digest, and any semantic change makes the digest not match.

path-range and symbol have low but non-zero wrong-resolution

Path-range had 10 wrong-resolutions (0.5%), all on semantic edits. Symbol had 12 wrong-resolutions (0.6%), also all on semantic edits. In these cases, the file still exists and the line range or symbol still points at something, but the content has changed — a silent misresolution. Both are well below the 2% threshold.

multi does not improve over the best single strategy

Multi (resolve by agreement, report degraded if disagreement) matches symbol’s performance (99.4% correct, 0.6% wrong). It does not improve over the best single strategy because content-digest’s failures (on semantic edits) cause multi to rely on path-range and symbol, which also have low wrong-resolution on semantic edits. Multi’s value is in reporting degradation, not in improving accuracy.

Reformats are handled perfectly by all strategies

The one reformat commit (in cobra, a gofmt pass) was handled perfectly by all four strategies: 20/20 anchors resolved correctly. Path-range resolves correctly because the code is still at the same path and line range (gofmt doesn’t move code between files). Symbol resolves correctly because the symbol name is unchanged. Content-digest resolves correctly because the normalized content is unchanged.

Limitations

No rename or delete commits in the simulation window

The 20-commit window from each repo (50-70 commits back from HEAD) contained only semantic edits, one reformat, and one “other”. No rename or delete commits were found. Renames are the adversarial case for path-range (the path changes) and symbol (the symbol name changes). Deletes are the adversarial case for all strategies (the code is gone).

This means the simulation underestimates the wrong-resolution rate for rename and delete scenarios. A longer replay window or a targeted selection of rename/delete commits would provide a more complete picture. However, the pre-registered thresholds are based on the aggregate, and all strategies clear them comfortably.

Only one reformat commit

The pre-registration required “at least one with a large mechanical reformat.” One reformat commit was found (cobra, gofmt), and all strategies handled it perfectly. A larger reformat (e.g., a project-wide rustfmt adoption) would provide a stronger test, but the result is consistent with the theory: reformats don’t change content, so content-digest is unaffected, and path-range/symbol are unaffected if the reformat doesn’t move code between files.

Anchors sampled from recent history

The simulation used commits 50-70 back from HEAD, which may not represent the full range of refactoring that occurred earlier in the repo’s history. Earlier commits may include large refactors (file moves, module restructuring) that this simulation doesn’t test.

Decision

All four strategies are usable. The anchor object in schema/claim.schema.json should use multi — all three strategies recorded simultaneously, resolved by agreement, with degraded reported when they disagree. Multi provides:

  1. The safety of content-digest (zero wrong-resolution on semantic edits)
  2. The resilience of symbol (survives reformatting)
  3. The simplicity of path-range (trivial to compute)
  4. Explicit degradation reporting (when strategies disagree, the system says so rather than silently picking one)

The anchor object is no longer a placeholder. It should be updated to specify strategy = "multi" as the default, with all three fields (path, range, symbol, contentDigest) populated for each anchor.