Shape ledger steps 1-4 + direct-minting Systems bootstrap (milestone 294, #2798) #115

Merged
bvandeusen merged 7 commits from dev into main 2026-08-19 21:24:40 -04:00
Owner

The accounting half of the pattern system (governing note 2786): canon stays small, accounting is total, unclassified is the todo.

  • Step 1 — code_shapes table (migration 0079): identity (project, repo, path, symbol, kind), five-status classification vocabulary, judgment provenance, vanish-as-history; backups v7 carry it with snippet-target-aware restore.
  • Step 2 — every coverage refresh syncs the ledger; snippet reference locations self-stamp canonical (self-healing, never touching agent judgments); the readout inverts to "N/M shapes accounted for ... K unclassified" on the card, enter_project, and the refresh route. Cache key bumps to v2.
  • Step 3 — classify_shapes (all-or-nothing batch, via restricted to agent|audit|import) + list_shapes (the todo query, read-scoped for API keys); get_snippet carries the structured instances/variants consumer map, caller-read-filtered.
  • Step 4 — instruction surfaces carry the rows-never-prose contract (verify_snippet, _INSTRUCTIONS at 1,998/2,000, reusing-code skill with derive-one-first); plugin 0.1.32. The Forge P7 backfill (101 enumerated instance rows) fires post-deploy.
  • #2798 — the Systems bootstrap mints directly (no operator approval), guided by the standard cross-app vocabulary (CI & Release, Auth & Access, ...).

CI: runs 4034, 4041, 4045, 4047, 4053 green across the steps (integration lane includes migrations 0079 + the new ledger/classify suites).

Post-deploy: Refresh coverage on each project to seed its ledger (pre-ledger cache blobs read "not measured yet" by design), then the Forge backfill runs from task #2790's payload.

🤖 Generated with Claude Code

The accounting half of the pattern system (governing note 2786): canon stays small, accounting is total, unclassified is the todo. - **Step 1** — code_shapes table (migration 0079): identity (project, repo, path, symbol, kind), five-status classification vocabulary, judgment provenance, vanish-as-history; backups v7 carry it with snippet-target-aware restore. - **Step 2** — every coverage refresh syncs the ledger; snippet reference locations self-stamp canonical (self-healing, never touching agent judgments); the readout inverts to "N/M shapes accounted for ... K unclassified" on the card, enter_project, and the refresh route. Cache key bumps to v2. - **Step 3** — classify_shapes (all-or-nothing batch, via restricted to agent|audit|import) + list_shapes (the todo query, read-scoped for API keys); get_snippet carries the structured instances/variants consumer map, caller-read-filtered. - **Step 4** — instruction surfaces carry the rows-never-prose contract (verify_snippet, _INSTRUCTIONS at 1,998/2,000, reusing-code skill with derive-one-first); plugin 0.1.32. The Forge P7 backfill (101 enumerated instance rows) fires post-deploy. - **#2798** — the Systems bootstrap mints directly (no operator approval), guided by the standard cross-app vocabulary (CI & Release, Auth & Access, ...). CI: runs 4034, 4041, 4045, 4047, 4053 green across the steps (integration lane includes migrations 0079 + the new ledger/classify suites). Post-deploy: Refresh coverage on each project to seed its ledger (pre-ledger cache blobs read "not measured yet" by design), then the Forge backfill runs from task #2790's payload. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
bvandeusen added 7 commits 2026-08-19 21:24:30 -04:00
feat(ledger): code_shapes — the shape ledger schema (#2787, milestone 294 step 1)
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 9s
CI & Build / TypeScript typecheck (push) Successful in 13s
CI & Build / integration (push) Successful in 25s
CI & Build / Python tests (push) Successful in 54s
CI & Build / Build & push image (push) Successful in 45s
19fdc9aa89
The accounting half of the pattern system (governing note 2786): the snippet
library records canon (small), this table accounts for EVERY extracted shape
(total). Identity is (project, repo_key, path, symbol, kind) — kind included
because one file can define '.foo' (css) and 'foo' (sym) as distinct shapes.
Status vocabulary: canonical / instance / variant / exempt / unclassified,
with unclassified as the default and THE todo state; classifications carry
who judged (agent|audit|hook|mechanical|import), when, and the why for
variants/exemptions. first/last-seen commits + vanished_at keep history
instead of deleting it; a rename reads as vanish+new (accepted for v1).

snippet_id is SET NULL on snippet deletion so accounting rows outlive their
target and rejoin the todo via the step-2 sync, never dangle silently.

Backups: v7 carries code_shapes (judgment data, worth moving) — full and
per-user export sections, and a restore that keeps a judgment only when its
snippet survives the id re-mapping, downgrading to unclassified otherwise.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
feat(ledger): coverage refresh feeds the shape ledger; the readout inverts to accounting (#2788, milestone 294 step 2)
CI & Build / Python lint (push) Successful in 5s
CI & Build / Plugin hooks (push) Successful in 8s
CI & Build / integration (push) Failing after 27s
CI & Build / TypeScript typecheck (push) Successful in 33s
CI & Build / Python tests (push) Successful in 1m4s
CI & Build / Build & push image (push) Successful in 44s
9b1597a3c9
compute_coverage is now the ledger's sync point: every walk upserts the
extracted shapes (new → unclassified, the todo state; surviving → last-seen
bump; vanished → stamped, kept as history), re-files judgments whose snippet
target went away, and mechanically stamps snippet reference locations as
canonical — the one always-safe rule, self-healing only for its own stamps
(an agent's judgment is never unwound by machinery).

The covering predicate moves to shape_ledger.location_covers as the single
home (match_shapes retired with its consumer); coverage's payload and line
invert from 'N/M shapes recorded' to shape ACCOUNTING per note 2786:
accounted/total with a canonical·instance·variant·exempt breakdown, and
unclassified — THE todo — with its largest directories. Cache key bumps to
v2 so pre-ledger blobs honestly read 'not measured yet' instead of rendering
in a shape no longer spoken.

Readout is deliberately project-wide (all repos' live rows), while the walk
serves whichever repos the owner's keyring reaches this refresh.

Integration tests pin the new contract: rows for every extracted shape,
mechanical canonical stamps carrying snippet ids, idempotent recompute,
agent judgments surviving recompute AND vanish/return, vanished rows leaving
the readout but keeping their history.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
fix(tests): drop the pre-ledger line-ending assertion the step-2 edit missed
CI & Build / Python lint (push) Successful in 4s
CI & Build / Build & push image (push) Successful in 22s
CI & Build / Plugin hooks (push) Successful in 9s
CI & Build / TypeScript typecheck (push) Successful in 37s
CI & Build / integration (push) Successful in 33s
CI & Build / Python tests (push) Successful in 1m1s
9d92df2825
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
feat(ledger): classify_shapes + list_shapes MCP tools; get_snippet carries the consumer map (#2789, milestone 294 step 3)
CI & Build / Python lint (push) Successful in 4s
CI & Build / Plugin hooks (push) Successful in 12s
CI & Build / integration (push) Successful in 27s
CI & Build / TypeScript typecheck (push) Successful in 35s
CI & Build / Python tests (push) Failing after 42s
CI & Build / Build & push image (push) Skipped
942edd1eb5
The judgment write path. classify_shapes applies a batch of classifications
to a project's live ledger rows — all-or-nothing (#2709's lesson: the whole
batch is validated, write-ACL'd, and every snippet target proven readable
before any row is touched); rows match by exact (path, symbol), kind narrows,
and shapes no live row matches come back as 'unmatched' rather than errors.
variant/exempt REQUIRE the reason — the why is the record (note 2786) — and
'unclassified' deliberately withdraws a judgment back to the todo. The 'via'
channel is caller-restricted to agent|audit|import; hook and mechanical stay
server-internal so a caller can't launder judgment as machinery.

list_shapes is the todo query (status=unclassified) with composable filters:
path is exact-or-under like recorded locations, snippet_id reads a consumer
map, include_vanished reads history; paged with the true total.

get_snippet now attaches  and  — the structured consumer
map, filtered to projects the CALLER can read so a shared snippet never side-
channels another project's file layout; attached only when non-empty (#2483).

Integration tests pin the batch atomicity, ACL gates, filter composition, the
consumer map on the MCP pull, and the SET NULL companion: a judgment whose
snippet was purged rejoins the todo on the next sync.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
fix(mcp): classify list_shapes as read-only for read-scoped API keys
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 8s
CI & Build / integration (push) Successful in 20s
CI & Build / TypeScript typecheck (push) Successful in 24s
CI & Build / Python tests (push) Successful in 1m4s
CI & Build / Build & push image (push) Successful in 32s
d50ebbad66
The auth guard test caught it: a read-shaped tool in neither set fails
closed for read keys, silently. list_shapes reads the ledger and writes
nothing; classify_shapes stays write-scoped.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
feat(systems): bootstrap mints directly — the standard vocabulary replaces operator approval (#2798)
CI & Build / Python lint (push) Successful in 5s
CI & Build / Plugin hooks (push) Successful in 15s
CI & Build / TypeScript typecheck (push) Successful in 34s
CI & Build / integration (push) Successful in 40s
CI & Build / Python tests (push) Successful in 1m5s
CI & Build / Build & push image (push) Successful in 59s
5265d11a6a
Operator directive: creating Systems is the agent's call, not an approval
flow — "propose to the operator, create each confirmed one" made the
operator a permission gate. The bootstrap ask now says create_system 3-6
directly, in-session, and the consistency that approval was covering moves
to a standard cross-project vocabulary (CI & Release, Auth & Access, Data
Model & Storage, API Surface, UI & Design, Import & Export, Background
Jobs, Observability): use the standard name verbatim where the area fits,
mint freely beyond it, the duplicate gate guards sprawl. create_system and
enter_project docstrings carry the same contract.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
feat(ledger): audits write rows, not prose — instruction surfaces carry the classification duty (#2790, milestone 294 step 4)
CI & Build / Plugin hooks (push) Successful in 8s
CI & Build / integration (push) Successful in 26s
CI & Build / TypeScript typecheck (push) Successful in 33s
CI & Build / Python lint (push) Successful in 4s
CI & Build / Python tests (push) Successful in 56s
CI & Build / Build & push image (push) Successful in 27s
9f1a52a035
verify_snippet docstring: consumers enumerated while checking are
classify_shapes instance rows; detail keeps the WHY and what changed,
nothing that belongs in a row. The MCP _INSTRUCTIONS REUSE bullet gains
"classify shapes against canon — a consumer map is rows, never prose"
(budget rebalanced to 1,998/2,000: the rules bullet lost its historical
push-optimisation clause, the task-note line tightened). The reusing-code
skill gains the full contract: instance/variant/exempt with required
reasons, list_shapes(status=unclassified) as the standing todo, and the
derive-one-first rule for repeating shapes with no canon. Plugin 0.1.32.

The operator-side halves of this step live outside the repo: the Drift
Audit process gained step 7 (classify what the walk proved) and the DRY
Pass s9 now sends consumer maps to the ledger with the note keeping only
the narrative. The Forge P7 backfill payload is enumerated and parked on
task 2790 — it fires after the next deploy + coverage refresh.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
bvandeusen merged commit fd101d24ae into main 2026-08-19 21:24:40 -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#115