Session file + ledger returns + 7 KG appends (2 drift-patterns, 3 good-direction, 2 facts) + feedback-derive-the-rule-from-the-consumer-not-from-the-survivor. MEMORY.md: prior Active Session demoted to MEMORY-reference.md, new promoted. Skill-harvest register: /wake-up backlog substrate-check patch + /field-divergence-sweep create, both PROPOSED for steward authorization. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Xefg5EXwcpd9RMAr63dWrD
28 lines
3.2 KiB
Markdown
28 lines
3.2 KiB
Markdown
---
|
|
name: feedback-derive-the-rule-from-the-consumer-not-from-the-survivor
|
|
description: "When two implementations of one field disagree, do NOT pick the survivor — derive the rule from what a CONSUMER of the value must do, then test the shapes where each candidate happens to be right. Comparison is selection, not derivation."
|
|
metadata:
|
|
node_type: memory
|
|
type: feedback
|
|
originSessionId: 954fee42-68ff-46b5-95e6-238f33e6ca80
|
|
modified: 2026-07-27T17:33:36.442Z
|
|
---
|
|
|
|
When two implementations compute the same field differently, the reflex is to decide *which one is correct* by comparing them. **That is selection, not derivation** — and it silently inherits the assumption that one of the two is right.
|
|
|
|
**Why:** verifying that A ≠ B tells you nothing about whether A or B is *correct*. The correct rule comes from **what a consumer of the value must be able to do with it** — and it may be neither candidate.
|
|
|
|
Earned hard 2026-07-27 (chamber-library `source_lines`), in two stages:
|
|
|
|
1. Two formulas disagreed: `len(splitlines())` (engine-side) vs `count("\n") + 1` (chamber-side `write_sidecar`). I ratified `splitlines()` on the strength of the engine-side convention — **without checking what `splitlines()` splits on**. It also breaks on `\v \f \x1c \x1d \x1e \x85 U+2028 U+2029`, which **no** consumer of a line coordinate treats as a break (editor · `wc -l` · `sed -n 'Np'` · the engine's chunker). Four canonicals carry them; on `lintott` the disagreement is **308 lines** — a coordinate off by 308 is a citation pointing at the wrong page.
|
|
2. **Both** candidates were wrong, on **complementary subsets**: `count+1` on the 1,261 newline-terminated files, `splitlines()` on the 4 exotic-bearing ones. The correct rule (`count("\n") + (0 if trailing newline else 1)`) was a third thing.
|
|
|
|
**Two corollaries, both load-bearing:**
|
|
|
|
- **Complementary-correctness defeats sampling.** Because each wrong candidate is *right* on some subset, **no single sample distinguishes all three** — the steward's "confirm the rule, not the sample" (which caught a live corruption risk: 36/1,297 files where a blanket `-= 1` migration would have corrupted data). Test the shapes where each candidate happens to be right, not a convenience sample from one producer.
|
|
- **Fix the root cause: ONE implementation, imported.** Two formulas for one field is *how* the divergence arose; a third arrives the same way. Put the definition where the semantics live (the gate that owns the coordinate) and have producers import it.
|
|
|
|
**How to apply:** when a field is computed in more than one place — (1) ask what a consumer must be able to DO with the value, and derive the rule from that; (2) enumerate the shapes where each existing candidate is right, and test all of them; (3) collapse to one implementation; (4) make any migration RECOMPUTE, never do arithmetic on the stored value.
|
|
|
|
Kin: [[feedback-checkable-claim-surfaces-bugs]] (the demand for verifiability as defect-detector), [[feedback-census-by-mechanism-not-proxy]] (the instrument must bear the claim), [[feedback-trust-prior-pass-frame]] (an existing implementation's correctness is not inherited by comparison). A new face of assert-from-derived-not-substrate: the *derived artifact* here is the other implementation.
|