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

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-22 13:38:06 -04:00
co-authored by Claude Fable 5
parent b88225eeb3
commit 10687120a5
5 changed files with 52 additions and 2 deletions
+2
View File
@@ -172,6 +172,8 @@ endpoint at `/mcp`, not these REST routes.
| GET | `/api/plugin/context` | SessionStart context payload (rules + active-project) | | GET | `/api/plugin/context` | SessionStart context payload (rules + active-project) |
| GET | `/api/plugin/retrieve` | Title-first knowledge-injection candidates | | GET | `/api/plugin/retrieve` | Title-first knowledge-injection candidates |
| GET | `/api/plugin/processes` | Stored Processes for skill-stub sync | | 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/<id>/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 | | GET / PUT | `/api/plugin/marketplace-url` | Read / set the plugin marketplace URL |
## Dashboard, Export, Trash, Users ## Dashboard, Export, Trash, Users
+11 -1
View File
@@ -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. 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 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 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**. 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. - `skills/` → the universal process-skills, surfaced by description match.
- `hooks/scribe_sync_processes.sh` (a 2nd SessionStart hook) + the `/scribe:sync` - `hooks/scribe_sync_processes.sh` (a 2nd SessionStart hook) + the `/scribe:sync`
command → generate `~/.claude/skills/scribe-proc-*` stubs from your Scribe command → generate `~/.claude/skills/scribe-proc-*` stubs from your Scribe
+4 -1
View File
@@ -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: 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 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 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 - 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. memory / CLAUDE.md in parallel with Scribe — Scribe holds the single copy.
- **Compact at clean seams** — because you record as you go, a context - **Compact at clean seams** — because you record as you go, a context
+7
View File
@@ -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 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 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. 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 - **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 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, YOUR edit's responsibility: if the edit changes the recorded shape,
+28
View File
@@ -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 the rest as instances. Canon is determined from the code; consistency comes
from the derivation, not from asking permission. 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 <path>` 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 <path> — 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 <path>") 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 ## The divergence readout — button B where button A is canon
Three questions the ledger answers mechanically (#2793): Three questions the ledger answers mechanically (#2793):