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
This commit is contained in:
David F Glidden
2026-07-27 19:39:35 +02:00
co-authored by Claude Opus 4.8
parent ffb9b09b48
commit 84a23d8550
3 changed files with 125 additions and 3 deletions
+3 -3
View File
@@ -52,10 +52,10 @@ The single place proposed skills live so they don't evaporate between sessions.
| Skill | Kind | One-line | Origin | Status |
|---|---|---|---|---|
| `/wake-up` | patch | **Substrate-check the briefing's backlog section.** §3's "What's unresolved" currently lets REVIEWED.md's *"If AUTHORIZED: build …"* clauses be read as *status*. They are **forward instructions, not status** — I told the steward at wake that REVIEWED-72/73/74 were all authorized-but-unbuilt; **2 of 3 were already built and landed** (v2.6.0), and the wave I reported as blocked was already unblocked. Proposed patch: before listing an authorized item as outstanding, verify against the substrate (code / spec header / repo CLAUDE.md), and say "verified against substrate" or "unverified" in the briefing. The wake briefing is a claim surface like any other, and it is the **highest-leverage place** for a false claim to land — it shapes the steward's picture of their own project before any work begins. | 2026-07-27 (steward-visible error, self-caught within the same turn) | **PROPOSED** |
| `/field-divergence-sweep` | create | **Sweep for one field computed in more than one place, then derive the rule from the consumer.** Method proven this session at steward direction, and the yield was not zero on the first run: grep the fleet for multi-site computations of the same field → for each, ask *what must a consumer be able to DO with this value* and derive the rule from that (never pick the surviving implementation — that is selection, not derivation) → enumerate the shapes where each existing candidate happens to be right and test **all** of them (complementary-correctness defeats sampling) → collapse to ONE imported implementation → any migration RECOMPUTES, never does arithmetic on the stored value. Found `source_lines` wrong **twice** (including in a fix committed an hour earlier; lintott off by **308 lines**), and cleared `sha256` + the tokenizers with an empirical cross-check. Same probe as the no-op orphan sweep, aimed at **values** instead of stages. Steward: *"this instance says the yield won't be zero."* | 2026-07-27 (steward-directed; grounded in [[feedback-derive-the-rule-from-the-consumer-not-from-the-survivor]]) | **PROPOSED** |
| `/wake-up` | patch | **Substrate-check the briefing's backlog section.** §3's "What's unresolved" currently lets REVIEWED.md's *"If AUTHORIZED: build …"* clauses be read as *status*. They are **forward instructions, not status** — I told the steward at wake that REVIEWED-72/73/74 were all authorized-but-unbuilt; **2 of 3 were already built and landed** (v2.6.0), and the wave I reported as blocked was already unblocked. Proposed patch: before listing an authorized item as outstanding, verify against the substrate (code / spec header / repo CLAUDE.md), and say "verified against substrate" or "unverified" in the briefing. The wake briefing is a claim surface like any other, and it is the **highest-leverage place** for a false claim to land — it shapes the steward's picture of their own project before any work begins. | 2026-07-27 (steward-visible error, self-caught within the same turn) | **BUILT 2026-07-27** (steward-authorized; provenance comment in SKILL.md §3) |
| `/field-divergence-sweep` | create | **Sweep for one field computed in more than one place, then derive the rule from the consumer.** Method proven this session at steward direction, and the yield was not zero on the first run: grep the fleet for multi-site computations of the same field → for each, ask *what must a consumer be able to DO with this value* and derive the rule from that (never pick the surviving implementation — that is selection, not derivation) → enumerate the shapes where each existing candidate happens to be right and test **all** of them (complementary-correctness defeats sampling) → collapse to ONE imported implementation → any migration RECOMPUTES, never does arithmetic on the stored value. Found `source_lines` wrong **twice** (including in a fix committed an hour earlier; lintott off by **308 lines**), and cleared `sha256` + the tokenizers with an empirical cross-check. Same probe as the no-op orphan sweep, aimed at **values** instead of stages. Steward: *"this instance says the yield won't be zero."* | 2026-07-27 (steward-directed; grounded in [[feedback-derive-the-rule-from-the-consumer-not-from-the-survivor]]) | **BUILT 2026-07-27** — `~/dotfiles/claude/skills/field-divergence-sweep/SKILL.md`, symlinked into `~/.claude/skills/` (authored-skill convention); grounded in the proven `source_lines` run, not recall |
*(Both are load-bearing rather than tidy-up: the first is a correction to a briefing surface that misled the steward, the second is a method that found a live 308-line coordinate error on its first run. No other harvest — the session's other lessons are banked as feedback memories, not skills.)*
**BOTH AUTHORIZED + BUILT 2026-07-27 (same sitting).** *(Both are load-bearing rather than tidy-up: the first is a correction to a briefing surface that misled the steward, the second is a method that found a live 308-line coordinate error on its first run. No other harvest — the session's other lessons are banked as feedback memories, not skills.)*
## Open proposals
@@ -0,0 +1,118 @@
---
name: field-divergence-sweep
description: 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
<!-- 2026-07-27: created, steward-authorized. Grounded in the proven run of this method on chamber-library `source_lines` (session 2026-07-25→27), NOT recall: it found the field computed two ways, then found BOTH ways wrong, then found the third-wrongness in a fix committed an hour earlier. Steward: "this instance says the yield won't be zero." -->
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:
```bash
# 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.
```bash
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**.
+4
View File
@@ -111,6 +111,10 @@ Then combine all sources into a single reconstruction. Use this structure but wr
**What's unresolved** — fourth. Open horizons from the previous wrap, ranked by load-bearing weight. PENDING items awaiting steward attention. Be specific: *"L1 amendment for ProjectionChain drafted in concept only, not yet written; reshapes given multi-mode retention frame from #145"* not *"L1 amendments pending."* Surface, too, any **skill-harvest proposals** the last wrap raised (§1.6) that the steward did not yet authorize — so improvements to our own tools don't evaporate across the pause.
> **Substrate-check anything you call outstanding — a disposition clause is not a status.** `REVIEWED.md`'s *"**If AUTHORIZED:** build X → then Y"* records what was **authorized**, never what was **done**; the same is true of a PENDING item's `**Awaiting:**` line and any tracker's "next steps." Before listing an authorized item as unbuilt, check the **substrate** — the code, the spec header, the repo's `CLAUDE.md`, the fleet test count — and mark each item *verified against substrate* or *unverified*. Cheap: usually one `grep` for the named function or declared-data key. <!-- 2026-07-27: steward-authorized. Earned: the wake reported REVIEWED-72/73/74 as authorized-but-unbuilt; TWO of the three were already built and landed (spec v2.6.0), and the 47-file wave reported as blocked was already unblocked — read straight off their "If AUTHORIZED: build…" lines. -->
>
> This matters more here than anywhere else in the briefing: **the wake 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 it arrives with the authority of a status report. An unverified backlog reads as fact, and the steward has no reason to doubt it. If a check is genuinely too expensive, say *"unverified — last confirmed [when]"* rather than stating it flat; an honest gap is inheritable, a confident error is not.
**Mood signal from the previous ledger** — if a Symmetria ledger existed for the previous session, surface 1–2 patterns from its "Returns" or "Confidence to recalibrate" sections. *"Last session you returned three times from synthesis-urge; that pattern is worth holding today."* Stimmung carries across pause.
**Next move** — the previous /wrap-up should have left an **actionable resumption point** (the concrete state + candidate first step, as of wrap). Lead with it: confirm it still holds against the thread-validity gate and what changed, or revise it — do not re-derive from cold. If the wrap left none, say so plainly (the link wasn't pure) and derive the starting point now. Suggest, with reasoning visible; don't prescribe.