Files
dotfiles/claude/skills/field-divergence-sweep/SKILL.md
T
David F GliddenandClaude Opus 4.8 84a23d8550 skills: build both authorized harvest proposals (2026-07-27)
/wake-up PATCH — substrate-check the briefing's backlog section. REVIEWED.md's
"If AUTHORIZED: build X" clauses record what was AUTHORIZED, never what was
DONE; the same holds for a PENDING item's Awaiting line and any tracker's next
steps. Earned: the wake reported REVIEWED-72/73/74 as authorized-but-unbuilt
when TWO were already built and landed, and the wave reported as blocked was
already unblocked. The patch requires verifying against the substrate (code,
spec header, repo CLAUDE.md) and marking each item verified/unverified —
because the wake briefing is the highest-leverage place a false claim can land:
it shapes the steward's picture of their own project before any work begins,
and arrives with the authority of a status report.

/field-divergence-sweep CREATE — the standing probe for one value computed in
more than one place. Core: derive the rule from what a CONSUMER must do, never
by picking the surviving implementation (comparison is selection, not
derivation); enumerate and test the shapes where each candidate happens to be
right (complementary-correctness defeats sampling); collapse to one imported
implementation; migrations RECOMPUTE rather than adjust; land
producer-then-consumers in one change-set with a byte-diff proof.

Grounded in the proven source_lines run rather than recall, including the
failure the skill exists to prevent — it found the field computed two ways,
then both ways wrong, then the third wrongness inside a fix committed an hour
earlier (lintott off by 308 lines).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xefg5EXwcpd9RMAr63dWrD
2026-07-27 19:39:35 +02:00

9.4 KiB

name, description
name description
field-divergence-sweep Sweep a codebase for one field/value computed in more than one place, then derive the correct rule from what a CONSUMER of the value must do — never by picking the surviving implementation. Use when two implementations of the same field disagree, when a value crosses a producer/consumer or cross-repo boundary, after a shared-name collision surfaces, or as a standing audit ("check the fleet for fields computed twice"). Collapses to one imported implementation and makes migrations recompute rather than adjust.

Field-divergence sweep — one value, one definition, derived from its consumer

A value computed in two places is not a style problem. It is a latent divergence with a delivery date — it stays invisible until the two computations meet, and they meet at the worst moment: a gate refusing valid work, a migration corrupting a subset, a coordinate pointing at the wrong page.

This skill is the standing probe for that class. It is the same shape as a no-op/orphan sweep, aimed at values instead of stages.

The one idea, stated first

When two implementations of one field disagree, do not pick the survivor. Derive the rule from what a consumer of the value must be able to do — then test the shapes where each candidate happens to be right.

Comparing A against B tells you they differ. It tells you nothing about whether either is correct. Choosing between them feels like derivation and is selection — it silently inherits the assumption that the right answer is already in the room. Often it is not.

Procedure

1. Find the multi-site computations

Grep for the same value being derived in more than one place. Productive shapes:

# the field's own name, at assignment sites
grep -rn '"<field>"\]\s*=\|<field>\s*=' --include=*.py .
# the computation idiom, not the field name (catches renamed locals)
grep -rn 'sha256(\|len(.*splitlines()\|count("\\n")\|findall(r"\\w+"' --include=*.py .

Cast wider than the field that prompted the sweep. The yield is usually a family: hashes, line/offset counts, tokenizations, slug/ID derivations, normalizations, timestamps.

For each hit, record what exactly is fed in — read_text() vs read_bytes(), pre-stripped vs raw, lowercased vs not. Two identical-looking formulas over different inputs are still two definitions.

2. Ask the consumer question — before looking at either implementation

For each multi-site value: what must a consumer be able to DO with this? Derive the rule from that answer alone. Write it down before comparing the implementations, so the existing code cannot anchor you.

  • A line coordinate must resolve the same way for the curator who writes it, the gate that checks it, and every consumer that follows it — an editor, wc -l, sed -n 'Np', the chunker. That question decides the rule; neither candidate implementation gets a vote.
  • A binding hash must change exactly when the bound content changes — which rules out any basis that normalizes on read.
  • A token must be the unit the guarantee is stated over, not the unit that was convenient to compute.

If the derived rule matches neither implementation, that is the expected outcome, not a surprise.

3. Enumerate the shapes where each candidate is right — and test all of them

This is the step that cannot be skipped, and the reason a casual sample is worthless:

Complementary-correctness defeats sampling. Each wrong candidate is right on some subset of inputs. If your sample happens to sit inside one candidate's correct region, it confirms the wrong rule with a clean run.

So: name the input shapes that discriminate — the edge that makes A right and B wrong, and the edge that flips it — and test every one. Then census the real population for each shape, so you know how many artifacts sit in each region.

The steward's formulation for this: confirm the rule, not the sample.

4. Collapse to ONE implementation

Fixing the value without fixing the multiplicity leaves the door open — a third formula arrives the same way the second did.

  • Put the definition where the semantics live (the gate/module that owns the contract), and have producers import it.
  • Make an unknown/unsupported variant raise, never silently fall back. A wrong convention here is a wrong coordinate.
  • If the convention is governed, declare it as data (with the reasoning and the rejected candidates), not as a tool default.

5. Migrate: recompute, never adjust

A migration must RECOMPUTE per artifact. Arithmetic on the stored value (-= 1, * 2, a uniform offset) assumes the discrepancy is uniform — and step 3 usually proves it is not.

An adjustment corrupts exactly the artifacts that were already correct.

6. Land producer-then-consumers in ONE change-set

The change-impact clause: fixing the producer while N consumers hold the old value is the orphan pattern. One change-set: producer fix + all consumer artifacts re-stamped + the byte-diff proof that only the intended field moved.

git diff --stat -- <artifact-dir>
git diff -U0 -- <artifact-dir> | grep -E '^[+-]' | grep -vE '^(\+\+\+|---)' | sort | uniq -c

Every changed line should be the field. If anything else moved, the change is not bounded.

7. Pin it so it cannot silently reopen

Tests that pin all the discriminating shapes from step 3 — including the shape where the rejected candidate happens to agree — plus:

  • the one-definition invariant (the producer delegates; assert it),
  • the cross-tool invariant (producer's stamp == what the consumer/gate measures),
  • refuse-unknown-convention behaviour.

8. Report what agreed, not only what diverged

A site checked and found consistent is a real result — record it, with the evidence. Where two computations differ by design (different inputs, different purposes), state the difference and account for it numerically, so the next sweep doesn't re-open a closed question.

Load-bearing disciplines (each earned)

  • Comparison is selection, not derivation. Verifying A ≠ B never establishes that A or B is right. (feedback-derive-the-rule-from-the-consumer-not-from-the-survivor)
  • Confirm the rule, not the sample. Especially when one producer generated the whole sample — its output shares a shape, so the sample cannot see the rule.
  • Check what your primitive actually does. str.splitlines() also breaks on \v \f \x1c \x1d \x1e \x85 U+2028 U+2029; read_text() applies universal-newline translation. A convention adopted without reading its primitive's semantics is an assumption wearing a standard's clothes.
  • Sixth-instance rule. When shared-name / two-senses collisions reach a count, they are no longer a pattern but a base rate — the sweep becomes standing maintenance, not incident response.
  • A latent divergence with zero live instances still gets named, not silently fixed in passing, when the fix would touch a producer with landed consumers. Name it for its own cycle.

The proven run (2026-07-27, chamber-library source_lines)

Kept because it demonstrates every step, including the failure this skill exists to prevent:

  1. Two implementations found: len(splitlines()) (engine-side) vs count("\n") + 1 (chamber-side write_sidecar).
  2. Skipped step 2 — ratified splitlines() because it was the engine-side convention. Selection, not derivation. Landed it.
  3. Steward: "confirm the rule rather than the sample — the formulas disagree only when the file ends in a trailing newline." Census: 36 of 1,297 canonicals lack one, so a blanket -= 1 would have corrupted exactly those 36. The 11-file sample (one producer, all newline-terminated) could never have shown it.
  4. The sweep then hit the just-landed fix: splitlines() also breaks on \f/U+2028 — 4 canonicals, and the-constitution-of-the-roman-republic-lintott.md off by 308 lines. wc -l confirmed the consumer-derived rule.
  5. Both candidates were wrong, on complementary subsets. The correct rule was a third thing: count("\n") + (0 if trailing newline else 1), empty = 0.
  6. Collapsed to one imported implementation; migration recomputed; producer + 11 consumers in one change-set; byte-diff showed 11 files / 11 insertions / 11 deletions, every changed line the field.
  7. Same sweep cleared sha256 (one latent CRLF-only basis divergence, 0 live instances — named, not silently changed) and the tokenizers (identical across five sites; the 20-token delta on a real file was exactly the footnote-marker digits one strips by design — consistent, fully accounted).

What this skill is not

  • Not a linter for duplicated code. It targets one value with two definitions, which is a correctness problem, not a tidiness one.
  • Not a licence to unify by fiat. A producer with landed consumers gets its own FIX/PROPOSAL cycle.
  • Not complete when the value is fixed. It is complete when there is one implementation, the discriminating shapes are pinned, and the artifacts carry a bounded-diff proof.