Files
FabledScribe/plugin/skills/shape-accounting/SKILL.md
T
bvandeusenandClaude Fable 5 475f0857c9
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
feat(ledger): write-path stamping — a pulled canon the session then instantiates lands as a hook instance row (#2791, milestone 294 step 5)
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>
2026-08-20 20:19:45 -04:00

69 lines
3.8 KiB
Markdown

---
name: shape-accounting
description: Use when a project's shape accounting needs attention — the pattern_coverage line from enter_project shows unclassified shapes or is missing on a forge-served project, the operator asks about coverage/accounting/canon, or you just proved a code-to-canon relationship (an audit enumerated call sites, a consolidation repointed consumers, a verify pass confirmed a helper's users). Triggers on "coverage", "accounted", "unclassified", "classify shapes", "what uses this", or finishing any consolidation.
---
# Shape accounting — every shape classified against canon
The snippet library records **canon** (small); the shape ledger accounts for
**every extracted definition** in a project's bound repos (total). Each ledger
row carries a status:
- `canonical` — IS a snippet's reference (the coverage sync stamps these
mechanically; you rarely set it).
- `instance` of snippet N — conforms to recorded canon. Canon in another
project counts (a family-level button shape fully accounts for a local use).
- `variant` of snippet N — a deliberate, named departure. **Reason required**
— the why IS the record.
- `exempt` — judged genuinely one-off. **Reason required.** A recorded
judgment, not silence — it stops the next pass re-litigating it.
- `unclassified` — nobody has judged it yet. **This is the todo list.**
## The loop
1. **Seed / refresh** — the ledger fills from coverage computation. Entering a
project triggers a background seed automatically; when you need it current
*now* (before a classification batch, or when the line is missing on a
forge-served project), call `refresh_pattern_coverage(project_id)` — it
returns the fresh accounting line. Takes seconds; it moves repo archives.
2. **Read the todo**`list_shapes(project_id, status="unclassified")`,
optionally scoped by `path` to the directories the coverage line names as
largest. `snippet_id=N` reads a consumer map.
3. **Judge in batches** — `classify_shapes(project_id, [{path, symbol,
status, snippet_id?, reason?}])`. All-or-nothing: a bad item applies
nothing. Rows, never prose — a consumer list in a note or verification
detail cannot be sorted, queried, or diffed.
## Rows that arrive on their own
Two feeds keep the ledger current between your batches, so most shapes never
need a hand judgment:
- **The sync** stamps a snippet's own reference location `canonical`
(`classified_by: mechanical`).
- **The write path** stamps instances as you work: when you `get_snippet` a
canon and then Write/Edit code that references or resembles it, the
definitions being written land as `instance` rows (`classified_by: hook`,
the evidence in `reason`), and the prior-art hook tells you what landed
("Shape accounting: recorded at … → instance of #N"). Offered-but-unopened
snippets stamp nothing — so *pull the canon you are instantiating*; that
pull is what turns your reuse into accounting. A hook row is evidence, not
judgment: it never overrides a classification you made, and a
`classify_shapes` call overrides it.
## The derive-first rule
N same-shaped occurrences matching **no** recorded canon is never N loose
classifications — it is a consolidation candidate: derive one reference from
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.
## What this buys
Divergence becomes mechanical: when button B appears where button A is canon,
the ledger says *unintended divergence* or *justified variant with its
reason* — nobody re-derives the history. `get_snippet` shows each snippet's
`instances` and `variants`, so "what uses this?" is answered from rows before
any contract change lands on its consumers.