Shape ledger steps 5–7: write-path stamping, mechanical proposer, divergence readout (#2791, #2792, #2793) #117

Merged
bvandeusen merged 6 commits from dev into main 2026-08-21 07:32:23 -04:00
Owner

Milestone 294 (shape ledger — total accounting of code shapes), the three remaining steps. dev head efc6503, CI run 4116 green.

Step 5 — write-path stamping (#2791). The prior-art hook names the shapes being written (shapes=kind:name, incl. the definition enclosing an Edit); the server stamps them instance (classified_by=hook, evidence in reason) when the session PULLED a snippet within 6h that the payload references by symbol or that the semantic arm scored for this payload. Offered-but-unopened stamps nothing; read-scoped keys get the hint, never a stamp; provisional rows for not-yet-synced shapes settle at the next sync. Plugin 0.1.34.

Step 6 — mechanical proposer (#2792). Shapes gain a content fingerprint (signature + comment/whitespace-insensitive body_sha; migration 0080). Every coverage refresh matches changed unclassified rows against canon — symbol elsewhere → textual containment → body references the canon → signature resemblance → semantic (capped) — and records proposals on the rows; same-project canon beats family canon on a tie. Rows with no canon group by the derive-first rule (dup:<sha> ≥2 places, name:<kind>:<symbol> ≥3 files). list_shapes(proposal=…), confirm_shape_proposals (scoped batches), readout proposed + derive_groups. Plugin 0.1.35.

Step 7 — divergence readout (#2793). One judgment path writes code_shape_events history (classified / vanished / reappeared / drifted; migration 0081) — shape_history answers what was used where, when, why. Judged instances/variants whose body moves get recheck_at. Shapes new since the previous refresh, in a directory+kind where one canon dominates the judged siblings and not proposed as that canon, get diverges_from — on the coverage line/card, list_shapes(flag=divergence), and in-band at write time. Backup v8 carries the history. Plugin 0.1.36.

Migrations 0080 + 0081 apply on boot.

🤖 Generated with Claude Code

Milestone 294 (shape ledger — total accounting of code shapes), the three remaining steps. dev head `efc6503`, CI run 4116 green. **Step 5 — write-path stamping (#2791).** The prior-art hook names the shapes being written (`shapes=kind:name`, incl. the definition enclosing an Edit); the server stamps them `instance` (classified_by=hook, evidence in reason) when the session PULLED a snippet within 6h that the payload references by symbol or that the semantic arm scored for this payload. Offered-but-unopened stamps nothing; read-scoped keys get the hint, never a stamp; provisional rows for not-yet-synced shapes settle at the next sync. Plugin 0.1.34. **Step 6 — mechanical proposer (#2792).** Shapes gain a content fingerprint (signature + comment/whitespace-insensitive body_sha; migration 0080). Every coverage refresh matches changed unclassified rows against canon — symbol elsewhere → textual containment → body references the canon → signature resemblance → semantic (capped) — and records proposals on the rows; same-project canon beats family canon on a tie. Rows with no canon group by the derive-first rule (`dup:<sha>` ≥2 places, `name:<kind>:<symbol>` ≥3 files). `list_shapes(proposal=…)`, `confirm_shape_proposals` (scoped batches), readout `proposed` + `derive_groups`. Plugin 0.1.35. **Step 7 — divergence readout (#2793).** One judgment path writes `code_shape_events` history (classified / vanished / reappeared / drifted; migration 0081) — `shape_history` answers what was used where, when, why. Judged instances/variants whose body moves get `recheck_at`. Shapes new since the previous refresh, in a directory+kind where one canon dominates the judged siblings and not proposed as that canon, get `diverges_from` — on the coverage line/card, `list_shapes(flag=divergence)`, and in-band at write time. Backup v8 carries the history. Plugin 0.1.36. Migrations 0080 + 0081 apply on boot. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
bvandeusen added 6 commits 2026-08-21 07:32:17 -04:00
feat(ledger): write-path stamping — a pulled canon the session then instantiates lands as a hook instance row (#2791, milestone 294 step 5)
CI & Build / Plugin hooks (push) Failing after 2s
CI & Build / Python lint (push) Successful in 4s
CI & Build / integration (push) Failing after 28s
CI & Build / TypeScript typecheck (push) Successful in 36s
CI & Build / Python tests (push) Successful in 1m5s
CI & Build / Build & push image (push) Successful in 39s
475f0857c9
The prior-art hook now names the shapes being written (shapes=kind:name —
every definition in the payload, or the one enclosing an Edit found by
walking the file upward) and the server stamps them as instance rows when
the session PULLED a snippet inside PULL_WINDOW that the payload references
by symbol or that the semantic arm scored for this very payload.
classified_by=hook, evidence in reason; never overrides a judgment or a
canonical row, overridable by classify_shapes. Offered-but-unopened stamps
nothing. Pulled-and-already-seen snippets stay in the semantic query as
evidence without re-entering the deduped menu. A brand-new shape gets a
provisional row the next sync confirms or vanishes. Read-scoped keys get
the hint, never the stamp. Plugin 0.1.34.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
fix(tests): provisional ledger rows carry the empty seen-marker default, not NULL
CI & Build / Python lint (push) Successful in 4s
CI & Build / Plugin hooks (push) Successful in 13s
CI & Build / integration (push) Successful in 31s
CI & Build / TypeScript typecheck (push) Successful in 39s
CI & Build / Python tests (push) Successful in 1m1s
CI & Build / Build & push image (push) Successful in 25s
a9e1cddba7
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
feat(ledger): mechanical proposer — every refresh proposes instances against canon and groups derive-first candidates; agents confirm in batches (#2792, milestone 294 step 6)
CI & Build / Python lint (push) Successful in 5s
CI & Build / Plugin hooks (push) Successful in 13s
CI & Build / integration (push) Failing after 34s
CI & Build / TypeScript typecheck (push) Successful in 35s
CI & Build / Python tests (push) Successful in 1m17s
CI & Build / Build & push image (push) Successful in 48s
ba0030e51d
Shapes now carry a content fingerprint (signature + whitespace/comment-
insensitive body_sha; migration 0080) and the proposer runs inside the
coverage refresh, the one moment bodies exist: symbol elsewhere → textual
containment → body references the canon → signature resemblance → semantic
(capped per refresh, unreached rows stay unexamined for the next). A hit is
a proposal on the row (proposed_snippet_id/basis/score), never a
classification; rows with no canon hit group by the derive-first rule
(identical body in ≥2 places, same name in ≥3 files) as proposal_basis=
derive + a group key. list_shapes(proposal=any|canon|derive|<basis>) is the
queue; confirm_shape_proposals(project_id, snippet_id|path|basis) confirms
in batches as agent instances; any classify_shapes/hook stamp retires the
proposal. Readout carries proposed + derive_groups (line, payload, card).
Plugin 0.1.35 (skill: the machine proposes, judgment classifies).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
fix(ledger): the proposer prefers a same-project canon on a tie — family canon elsewhere is the fallback, not the first hit
CI & Build / Plugin hooks (push) Successful in 9s
CI & Build / Python tests (push) Successful in 1m17s
CI & Build / Python lint (push) Successful in 5s
CI & Build / integration (push) Successful in 35s
CI & Build / TypeScript typecheck (push) Successful in 37s
CI & Build / Build & push image (push) Successful in 40s
386b27e422
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
feat(ledger): divergence readout — button B where button A is canon, shape history, and judged-shape recheck (#2793, milestone 294 step 7)
CI & Build / TypeScript typecheck (push) Failing after 2s
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 8s
CI & Build / integration (push) Successful in 28s
CI & Build / Python tests (push) Failing after 37s
CI & Build / Build & push image (push) Skipped
d74a244b3a
Every judgment now goes through one helper that remembers the fingerprint
judged (classified_sha) and writes a code_shape_events row; the sync writes
vanished / reappeared / drifted events and flags recheck_at when a body
moves under an instance/variant. The refresh flags diverges_from on shapes
new since the previous computation that sit where one canon dominates the
judged siblings of their directory+kind and were not proposed as that canon
(a first seed flags nothing); the write-path hint asks the same question
in-band for the shapes the hook names. list_shapes(flag=divergence|recheck),
shape_history(project_id, path, symbol) (read-only), coverage line/payload/
card carry divergent + recheck. Backup v8 carries the history. Plugin 0.1.36.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
fix(plugin-context): the empty write-path payload carries the divergence key too
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 7s
CI & Build / integration (push) Successful in 19s
CI & Build / TypeScript typecheck (push) Successful in 22s
CI & Build / Python tests (push) Successful in 1m3s
CI & Build / Build & push image (push) Successful in 42s
efc650390e
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
bvandeusen merged commit 79f0283608 into main 2026-08-21 07:32:23 -04:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: bvandeusen/FabledScribe#117