Self-surfacing DRY — duplicate families named at the write and on arrival, tool-agnostic (milestone 299 steps 1–4) #125

Merged
bvandeusen merged 5 commits from dev into main 2026-08-22 13:41:24 -04:00
Owner

Closes the loop the shape catalogue was built for (#2280): a duplicate family is named at the moment a copy is written, whichever tool writes it, and on arrival — instead of waiting for an audit.

  • Step 1 (#2899) — the coverage line shows standing work even with 0 unclassified (; standing: …), and derive_new names copies that joined a family since the previous refresh ("+2 new copies since last refresh: .error-msg in InceptionCard.vue").
  • Step 2 (#2900) — write-path derive arm: shape_ledger.write_time_derive + _derive_line in the prior-art hint name a duplicate family (no canon) or a canon elsewhere for the names being written; exclude_derive dedup channel (hook .derive.ids).
  • Step 3 (#2901)scribe_after_write.sh, a PostToolUse hook on Bash: diffs the working tree per session (path+blob snapshot) and runs the same arms on what sed/heredocs/scripts just wrote, through the same endpoint and dedup channels. Shared scribe_defs.sh; plugin 0.1.39.
  • Step 4 (#2902) — shape-accounting + reusing-code skills, static floor, plugin README, api-reference.

CI green on head 1068712 (run 4241). Pay-down of the derive backlog (steps 5–6) follows after deploy, as the live verification.

🤖 Generated with Claude Code

Closes the loop the shape catalogue was built for (#2280): a duplicate family is named at the moment a copy is written, whichever tool writes it, and on arrival — instead of waiting for an audit. - **Step 1 (#2899)** — the coverage line shows standing work even with 0 unclassified (`; standing: …`), and `derive_new` names copies that joined a family since the previous refresh ("+2 new copies since last refresh: .error-msg in InceptionCard.vue"). - **Step 2 (#2900)** — write-path derive arm: `shape_ledger.write_time_derive` + `_derive_line` in the prior-art hint name a duplicate family (no canon) or a canon elsewhere for the names being written; `exclude_derive` dedup channel (hook `.derive.ids`). - **Step 3 (#2901)** — `scribe_after_write.sh`, a PostToolUse hook on Bash: diffs the working tree per session (path+blob snapshot) and runs the same arms on what sed/heredocs/scripts just wrote, through the same endpoint and dedup channels. Shared `scribe_defs.sh`; plugin 0.1.39. - **Step 4 (#2902)** — shape-accounting + reusing-code skills, static floor, plugin README, api-reference. CI green on head 1068712 (run 4241). Pay-down of the derive backlog (steps 5–6) follows after deploy, as the live verification. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
bvandeusen added 5 commits 2026-08-22 13:41:18 -04:00
feat(coverage): the line names standing work with 0 unclassified + derive_new, copies that joined a family since the previous refresh (#2899, milestone 299 step 1)
CI & Build / TypeScript typecheck (push) Successful in 40s
CI & Build / Python lint (push) Successful in 6s
CI & Build / Plugin hooks (push) Successful in 12s
CI & Build / integration (push) Successful in 33s
CI & Build / Python tests (push) Successful in 1m7s
CI & Build / Build & push image (push) Successful in 24s
bb242ca566
Since the scoped bucket (#2869) the ledger reads 100% accounted while 439
derive rows stand; the standing block was gated on unclassified > 0 and so
went silent. Build it whatever the todo count ("; standing: ..."), and add
derive_new — derive-grouped rows first seen after the previous refresh
stamp — so entering a project names the drift ("+2 new copies since last
refresh: .error-msg in InceptionCard.vue") instead of waiting for an audit.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
feat(write-path): the derive arm — the hint names a duplicate family (no canon) or a canon elsewhere for the shapes being written; exclude_derive channel (#2900, milestone 299 step 2)
CI & Build / Python lint (push) Successful in 4s
CI & Build / Plugin hooks (push) Failing after 9s
CI & Build / integration (push) Successful in 25s
CI & Build / TypeScript typecheck (push) Successful in 32s
CI & Build / Python tests (push) Successful in 58s
CI & Build / Build & push image (push) Successful in 23s
2324c15418
shape_ledger.write_time_derive asks the ledger what it knows about each
named (kind, symbol): a derive-grouped family (identical body / same name
in N other files) -> "derive it now, do not add a copy"; a canonical row
at another path -> "canon #N at <path>, reuse". Judged rows at the path and
the canon own file stay silent. Rendered by _derive_line beside the
divergence line; keyed (group id / canon:<id>) on a third per-session dedup
channel in the hook (.derive.ids -> exclude_derive=).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
feat(plugin): after-write hook — PostToolUse on Bash diffs the working tree and runs the prior-art + ledger arms on what was just written; shared scribe_defs.sh; plugin 0.1.39 (#2901, milestone 299 step 3)
CI & Build / Python lint (push) Successful in 4s
CI & Build / Plugin hooks (push) Successful in 8s
CI & Build / integration (push) Successful in 25s
CI & Build / TypeScript typecheck (push) Successful in 32s
CI & Build / Python tests (push) Failing after 40s
CI & Build / Build & push image (push) Skipped
5925335ca0
Edits made through sed/heredocs/scripts never reached the PreToolUse
Write|Edit hook, so a whole class of writes got no prior-art hint, no
ledger feed and no duplicate-family warning. scribe_after_write.sh asks git
what changed since it last looked (per-session path+blob snapshot; first
call = files touched in the last minute), extracts the definitions in the
added lines and calls /api/plugin/prior-art with the same three dedup
channels the pre hook keeps. Never blocks; silent on any failure. The
extractor, the prose/data skip list and the local by-name arm move to
scribe_defs.sh, sourced by both hooks. Version bump covers the step-2 hook
change too (run 4239 failed only on the bump check).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Run 4240: two pre-write hook tests pinned the skip case and scribe_defs()
inside scribe_prior_art.sh, which moved to the shared library; the after-write
test saw the same derive key appended once per changed file. Keep each token
once (sort -u after the appends) and point the pins at the library.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
docs(self-surfacing): derive groups are drift not audit material — shape-accounting + reusing-code skills, static floor, plugin README (after-write hook), api-reference rows (#2902, milestone 299 step 4)
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 13s
CI & Build / integration (push) Successful in 28s
CI & Build / TypeScript typecheck (push) Successful in 37s
CI & Build / Python tests (push) Successful in 1m7s
CI & Build / Build & push image (push) Successful in 34s
10687120a5
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
bvandeusen merged commit 4fa8158329 into main 2026-08-22 13:41:24 -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#125