From 10687120a5d4497d979d1193e97649d3085dab2a Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Sat, 22 Aug 2026 13:38:06 -0400 Subject: [PATCH] =?UTF-8?q?docs(self-surfacing):=20derive=20groups=20are?= =?UTF-8?q?=20drift=20not=20audit=20material=20=E2=80=94=20shape-accountin?= =?UTF-8?q?g=20+=20reusing-code=20skills,=20static=20floor,=20plugin=20REA?= =?UTF-8?q?DME=20(after-write=20hook),=20api-reference=20rows=20(#2902,=20?= =?UTF-8?q?milestone=20299=20step=204)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- docs/api-reference.md | 2 ++ plugin/README.md | 12 ++++++++++- plugin/hooks/scribe_static_context.md | 5 ++++- plugin/skills/reusing-code/SKILL.md | 7 +++++++ plugin/skills/shape-accounting/SKILL.md | 28 +++++++++++++++++++++++++ 5 files changed, 52 insertions(+), 2 deletions(-) diff --git a/docs/api-reference.md b/docs/api-reference.md index bc79aae..0fe3b15 100644 --- a/docs/api-reference.md +++ b/docs/api-reference.md @@ -172,6 +172,8 @@ endpoint at `/mcp`, not these REST routes. | GET | `/api/plugin/context` | SessionStart context payload (rules + active-project) | | GET | `/api/plugin/retrieve` | Title-first knowledge-injection candidates | | GET | `/api/plugin/processes` | Stored Processes for skill-stub sync | +| GET | `/api/plugin/prior-art` | Write-path hint for the plugin hooks (params: `path`, `code`, `repo`, `shapes`, `exclude_ids`, `exclude_sync_ids`, `exclude_derive`); returns `context`, `note_ids`, `sync_note_ids`, `stamped`, `divergence`, `derive`, `derive_keys` | +| GET / POST | `/api/projects//coverage`, `…/coverage/refresh` | Shape-ledger accounting (`pattern_coverage` line, counts, `derive_groups`, `derive_new`, `divergence`, `recheck`) | | GET / PUT | `/api/plugin/marketplace-url` | Read / set the plugin marketplace URL | ## Dashboard, Export, Trash, Users diff --git a/plugin/README.md b/plugin/README.md index 6b56599..49e0008 100644 --- a/plugin/README.md +++ b/plugin/README.md @@ -52,8 +52,18 @@ On install you'll be asked for: but never stop it; silent when nothing is recorded, which is most of the time. Two framings: a REUSE menu (similar/nearby records), and a SYNC nudge when a snippet records the exact file being edited — "updating the record is part of - the edit" — each with its own once-per-session dedup. + the edit" — each with its own once-per-session dedup. A third, ledger-fed + line names a duplicate family (no canon) or a canon recorded elsewhere for + the names being written (its own dedup channel, `exclude_derive`). Toggle in **Settings → Knowledge auto-inject**. +- `hooks/hooks.json` → PostToolUse hook on `Bash` + (`hooks/scribe_after_write.sh`): code written through sed/heredocs/scripts + never reaches the PreToolUse hook, so this one diffs the working tree after + every Bash call (per-session path+blob snapshot; one `git status` when + nothing changed) and runs the same arms on the definitions just written, + through the same endpoint and the same dedup channels. `additionalContext` + only; silent on any failure. The extractor, the prose/data skip list and the + local by-name duplicate arm are shared in `hooks/scribe_defs.sh`. - `skills/` → the universal process-skills, surfaced by description match. - `hooks/scribe_sync_processes.sh` (a 2nd SessionStart hook) + the `/scribe:sync` command → generate `~/.claude/skills/scribe-proc-*` stubs from your Scribe diff --git a/plugin/hooks/scribe_static_context.md b/plugin/hooks/scribe_static_context.md index 32ddf3d..9a42c8c 100644 --- a/plugin/hooks/scribe_static_context.md +++ b/plugin/hooks/scribe_static_context.md @@ -66,7 +66,10 @@ for the operator's work, and as your own working memory across sessions. should read as a map of every shape in it. The backstop still holds: noticing the second copy of anything, or consolidating copies into a shared X, means X gets recorded before that work is finished — which is how a - codebase is kept from growing four `.btn-primary` definitions. + codebase is kept from growing four `.btn-primary` definitions. The write-path + hooks (before a Write/Edit, and after any Bash call that changed the tree) + name a known duplicate family or a canon elsewhere for what was just + written — act on that line at the write, not at the next audit. - Do **not** keep the operator's rules, plans, or project notes in local memory / CLAUDE.md in parallel with Scribe — Scribe holds the single copy. - **Compact at clean seams** — because you record as you go, a context diff --git a/plugin/skills/reusing-code/SKILL.md b/plugin/skills/reusing-code/SKILL.md index 2a00166..08db67d 100644 --- a/plugin/skills/reusing-code/SKILL.md +++ b/plugin/skills/reusing-code/SKILL.md @@ -44,6 +44,13 @@ through recall/auto-inject; this skill is the active reflex around that. it before you go any further. Either it's the helper you were about to duplicate — reuse it and drop yours — or it isn't, and the record needs the new location adding. Both are cheaper now than after the duplicate settles in. +- **A `Shape ledger at …` line is the ledger speaking, not the record.** It + names a duplicate family ("identical body in N other files, no canon") or a + canon elsewhere for a name you just wrote — for edits made through Bash + (sed, heredocs, scripts) as much as through Write/Edit. Derive the family or + reuse the canon *now*; a family that is convention rather than copies is + dismissed with `classify_shapes(..., status="exempt", + reason_code="convention-plumbing")`, never ignored. - **A `[records this file]` hint is a duty, not a menu.** When the hint says a snippet records the very file you're editing, the record's freshness is now YOUR edit's responsibility: if the edit changes the recorded shape, diff --git a/plugin/skills/shape-accounting/SKILL.md b/plugin/skills/shape-accounting/SKILL.md index 6105faf..c62025b 100644 --- a/plugin/skills/shape-accounting/SKILL.md +++ b/plugin/skills/shape-accounting/SKILL.md @@ -85,6 +85,34 @@ the dominant form, `create_snippet` it, migrate the outliers, then classify the rest as instances. Canon is determined from the code; consistency comes from the derivation, not from asking permission. +## Derive groups are drift, not audit material + +The catalogue exists so the codebase is DRY **from inception**, not as DRY as +the last sweep left it. Three surfaces say so without anyone running an audit +(milestone 299): + +- **At the write** — the prior-art hint (the Write/Edit hook, and since + 0.1.39 the after-write hook on Bash, so sed/heredoc/script edits count too) + carries a `Shape ledger at ` line when a name just written is a known + **duplicate family** ("identical body in N other files, no canon") or a + **canon elsewhere** ("snippet #N at — reuse, don't redefine"). Act + on it *then*: pull the canon and build from it, or derive the family now — + `create_snippet` the dominant form, repoint the copies, `classify_shapes` + them `instance`. A family is named once per session. +- **On arrival** — the coverage line's `standing:` block (shown even when + nothing is unclassified) and `derive_new` ("+N new copies since last + refresh: .x in ") name what drifted since the previous refresh. That + is the todo of the moment, sized to the last batch — not a backlog. +- **A family that is convention, not copies** — component-local `load` / + `toggle` / `save` that happen to share a name — is dismissed, not + consolidated: `classify_shapes(..., status="exempt", + reason_code="convention-plumbing", reason=…)` (or `classify_shapes_by_rule` + for a whole family) removes it from the queue. Dismissal is a judgment and + it is recorded; silence is not. + +After the one-time pay-down the derive queue reads empty; anything in it +afterwards is drift of the moment, and the hint already said so at the write. + ## The divergence readout — button B where button A is canon Three questions the ledger answers mechanically (#2793):