f1fbdf746ad358cb1618c0c62f6d2e54b1a47b5d
29
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
f1fbdf746a |
feat(shapes): the agent judges what it wrote, at the end of the turn (milestone 439 steps 1-3)
CI & Build / Python lint (push) Successful in 5s
CI & Build / Plugin hooks (push) Successful in 18s
CI & Build / TypeScript typecheck (push) Successful in 54s
CI & Build / integration (push) Successful in 52s
CI & Build / Python tests (push) Successful in 1m38s
CI & Build / Build & push image (push) Successful in 33s
Recording used to be decided by machinery — the only "record it" prompt fired when a same-named copy already existed (#2664), so a first instance of a reusable piece was never asked about, and judgment arrived only through audits. Now the question is asked where the knowledge is: the end of the turn that wrote the code, of the agent that wrote it. - Write hooks keep `<sid>.written.ids` (path, kind, name) for every definition a write names; a new file adds a `file` line for its stem — a candidate in any language without a framework rule (scribe_written_append). - Stop hook scribe_shape_check.sh sends the ledger to GET /api/plugin/shape-check and blocks once, in the server's words, when anything is unjudged. Same discipline as the report check: never twice, never without a recorded check, another hook's loop left alone; the ledger is kept when the instance cannot be reached. - shape_ledger.unjudged_shapes: no row, unclassified, scoped and hook stamps are unjudged; an agent/audit/import verdict is not. A snippet recorded at the shape answers for it until the refresh stamps it canonical. - services/shape_check owns the reason text and records every outcome in app_logs (passed / blocked / judged_after_block / left_after_block). - classify_shapes(repo=…) judges a shape the ledger has not synced yet via a provisional row under a bound repo; the sync confirms it, or vanishes and revives it with the verdict intact. An unbound repo is refused. Plugin version minted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
eb5cc6d3a7 |
fix(shapes): weak stamps elect no canon; the arrival line names the review; Svelte scopes by default (#4608)
CI & Build / Python lint (push) Successful in 8s
CI & Build / Plugin hooks (push) Successful in 16s
CI & Build / TypeScript typecheck (push) Successful in 54s
CI & Build / integration (push) Successful in 1m3s
CI & Build / Python tests (push) Successful in 1m44s
CI & Build / Build & push image (push) Successful in 1m5s
Librarian and Stash had 132 and 488 write-path stamps written at 0.68-0.72, before the 0.80 floor (#4204). Nothing re-judged them, and dominant_canon counted them, so a YAML CI snippet (#3410) "dominated" Librarian's web directory and every write there was told it diverged from it — 1408 flags on one project, 902 on the other, all skimmed past. - is_weak_stamp: one predicate for "hook-stamped below today's floor". dominant_canon and canon_form skip such rows; stamps_to_review lists them by the same predicate. No stored row changes — they stay for judgment. - flag_divergence withdraws a standing flag whose canon no longer dominates its directory. A flag is a mechanical prompt, not a judgment. - The coverage line ends "N weak stamps · M incoherent canons to judge — stamps_to_review" when either is nonzero, so a project's own session sees the queue on arrival. The shape-accounting skill says what to do with it. - scoped_definitions handles .svelte: every <style> is component-scoped unless <style global> or :global(...); instance-script syms are scoped, module-script ones stay ordinary. Plugin version minted for the skill change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
312dc9f6f7 |
fix(shapes): the semantic arm proposes at the write-path floor, not a private 0.8 (#4208)
CI & Build / Plugin hooks (push) Successful in 12s
CI & Build / Python lint (push) Successful in 3s
CI & Build / TypeScript typecheck (push) Successful in 53s
CI & Build / integration (push) Successful in 56s
CI & Build / Python tests (push) Successful in 1m34s
CI & Build / Build & push image (push) Successful in 22s
0.8 was sized for proposals nobody reads; every semantic proposal is read by a judge before it is confirmed. Measured, it proposed 0 of 150 while judged instances of a canon score 0.68-0.71 - the write-path hint's own floor asks the same question of the same documents at 0.68. The arm now uses that floor, scans 8 hits instead of 3 (a true instance ranked 4th behind snippets of other language families), and the proposer version bumps to 5 so rows examined under the old floor are read again. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01821k5B3Ysecp9fNYs92Kuy |
||
|
|
a875a1b2ee |
fix(shapes): a semantic miss is not evidence — the divergence check stops reading it (#4208)
CI & Build / Python lint (push) Successful in 2s
CI & Build / integration (push) Successful in 53s
CI & Build / TypeScript typecheck (push) Successful in 54s
CI & Build / Plugin hooks (push) Successful in 11s
CI & Build / Python tests (push) Successful in 1m32s
CI & Build / Build & push image (push) Successful in 24s
Measured live: true instances of the service-unit canon score 0.68-0.71 against it at best, helpers 0.66-0.75 against unrelated snippets, and nothing reaches the 0.8 floor. The "conclusive miss" fired for nearly every body and silenced real divergences exactly as it silenced helpers. The stored miss basis, its flag withdrawal and the report plumbing are removed; the floor stays at 0.8 and the new-shapes-first ordering stays. False prompts are answered by judgment (exempt with a reason). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01821k5B3Ysecp9fNYs92Kuy |
||
|
|
e2197ac799 |
fix(tests): assert the withdrawn flag on its row, not on a count the skew margin inflates (#4208)
CI & Build / Python lint (push) Successful in 2s
CI & Build / Plugin hooks (push) Successful in 9s
CI & Build / TypeScript typecheck (push) Successful in 52s
CI & Build / integration (push) Successful in 1m1s
CI & Build / Python tests (push) Successful in 1m34s
CI & Build / Build & push image (push) Successful in 14s
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01821k5B3Ysecp9fNYs92Kuy |
||
|
|
19438cc894 |
fix(shapes): the capped meaning pass reads new shapes first, and its miss withdraws an early flag (#4208)
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 12s
CI & Build / integration (push) Failing after 51s
CI & Build / TypeScript typecheck (push) Successful in 53s
CI & Build / Python tests (push) Successful in 1m33s
CI & Build / Build & push image (push) Successful in 21s
Measured on the first live refresh after
|
||
|
|
91cde6c3e4 |
fix(shapes): let a measured meaning-miss silence a divergence prompt (#4208)
CI & Build / Python lint (push) Successful in 2s
CI & Build / Plugin hooks (push) Successful in 9s
CI & Build / Python tests (push) Successful in 1m33s
CI & Build / TypeScript typecheck (push) Successful in 52s
CI & Build / integration (push) Successful in 52s
CI & Build / Build & push image (push) Successful in 28s
#4204 gave the divergence check a structural gate, which silenced one of the five false prompts it was filed for. The other four are `def` helpers in a directory whose canon is an `async def` service unit. No refinement of `shape_form` reaches them: they differ from #2793's acceptance case — a hand-rolled sync `confirmDanger` where an async confirm helper is canon — only by the JOB they do, and a signature does not carry a job. The proposer's semantic arm already reads bodies per symbol, which is the comparison option 2 asked for and was thought to be missing. What it did not do was record its MISSES: a hit became `proposal_basis = "semantic"`, a miss left the row indistinguishable from one nobody had looked at. So `flag_divergence` could ask the proposer "do you agree this is the canon?" but never "did you check, and is it not?". `_semantic_canon` now reports whether an empty answer is evidence, and `flag_divergence` withholds the prompt when it is. The whole risk is in the negative, so only a conclusive miss is stored. A body too thin to embed, a row the per-refresh cap never reached, an arm that threw, and a result set that came back full — and may therefore have hidden the canon behind the limit — all stay "cannot tell" and still ask the question. That is the discipline `FORM_UNKNOWN` already enforces here: not knowing must make a check quieter, never more confident. `_SEMANTIC_LIMIT` is named for that reason; the number is load-bearing, not a tuning knob. No migration: `proposal_basis` is nullable Text with no CHECK constraint (verified in the model and across alembic/versions), so rule 36 does not bite. Nothing can mistake the miss for a proposal either — every reader keys on `proposed_snippet_id` or `proposal_group`, and `confirm_shape_proposals` requires the id non-NULL before it will confirm anything. `_PROPOSER_VERSION` 3 -> 4, per its own contract: rows remember the ruleset they were examined under, and without the bump no already-examined row would ever acquire a miss. Option 1 (widening `kind`) stays closed, on the merits rather than on cost: bucketing density by exact form takes the async canon out of a sync candidate's denominator and silences #2793's acceptance case by the identical mechanism, one layer down. The reasoning is on #4208. Tests: tests/test_divergence_meaning_gate.py pins the report contract, with the truncation case tested hardest — reading a cut-off as a negative would weaken the guard in proportion to how many snippets the operator has. The end-to-end discrimination is in test_integration_shape_classify.py on deliberately the SAME fixture as #2793's acceptance case, so the two runs differ in exactly one thing: whether the arm claims to have looked. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01821k5B3Ysecp9fNYs92Kuy |
||
|
|
57f6982f56 |
test(ledger): the transition/prefix references clear the flag end to end; plugin 0.1.45 (#2970)
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) Successful in 1m3s
CI & Build / Python lint (push) Successful in 4s
CI & Build / Build & push image (push) Successful in 14s
Integration cover for the seam the unit tests only meet at either end: a
template that names no class at all (`<transition-group name="toast">`) and
one that builds its class (`` `status-${s}` ``) run through the real
extractor, through resolve_consumers, into `flag="unused-css"` — and the
rules they reach stop being reported, while a rule nothing can reach stays
listed. The prefix credits BOTH status rows, which is the documented
reading: the template does not say which one it built.
The manifest bump is what the last commit owed — it edited the
shape-accounting skill, and the installer compares versions to decide
whether to refresh the cache that actually executes (#2209), so plugin
edits that ship without a bump reach the repo and stop there. CI caught it
on 4323; 0.1.44 -> 0.1.45.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
||
|
|
c28c87c39e |
test(ledger): the consumer-map integration test owns its unreferenced rule — the seeded button.css row vanishes under the test's own tree (#2936)
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 12s
CI & Build / integration (push) Successful in 27s
CI & Build / TypeScript typecheck (push) Successful in 32s
CI & Build / Python tests (push) Successful in 1m6s
CI & Build / Build & push image (push) Successful in 15s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
8664d8ad14 |
feat(ledger): the consumer map surfaces — every css row carries used_by on list_shapes, flag="unused-css" (the map's negative space, surfaced never deleted), derive groups and the write-path family carry consumers, the derive line says "used by N template(s)", coverage payload unused_css + the standing block; docs, SKILL, plugin 0.1.44; the two step-2 tests expected 5 edges where fan-out makes 6 (milestone 302 step 3, #2936)
CI & Build / Plugin hooks (push) Successful in 9s
CI & Build / Python lint (push) Successful in 4s
CI & Build / TypeScript typecheck (push) Successful in 38s
CI & Build / integration (push) Failing after 44s
CI & Build / Python tests (push) Successful in 1m26s
CI & Build / Build & push image (push) Successful in 31s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
ffbdf19116 |
feat(ledger): the CSS consumer map — code_shape_consumers edges (shape → file whose markup names the class, count), migration 0086, resolve_consumers (own-file row when the template defines the class, else every other definition), sync_repo_consumers rebuilt from the archive on every refresh, consumers_of; derived, so not backed up (milestone 302 step 2, #2935)
CI & Build / Plugin hooks (push) Successful in 11s
CI & Build / Python lint (push) Successful in 4s
CI & Build / integration (push) Failing after 29s
CI & Build / TypeScript typecheck (push) Successful in 33s
CI & Build / Python tests (push) Failing after 52s
CI & Build / Build & push image (push) Skipped
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
85111442a6 |
feat(ledger): CSS derive families are names, never bodies — name floor 2 for css, dup: grouping sym-only; derive line says "repeated name" and dismisses scoped-css; plugin 0.1.41 (note #2917)
CI & Build / Python lint (push) Successful in 4s
CI & Build / Plugin hooks (push) Successful in 10s
CI & Build / integration (push) Successful in 25s
CI & Build / TypeScript typecheck (push) Successful in 32s
CI & Build / Python tests (push) Successful in 1m0s
CI & Build / Build & push image (push) Successful in 25s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
2324c15418 |
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
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> |
||
|
|
bb242ca566 |
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
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> |
||
|
|
aba16583ab |
fix(ledger): one-line CSS rules fingerprint their own declarations; the proposer writes uses edges for judged rows too (#2872, #2870)
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) Successful in 59s
CI & Build / Build & push image (push) Successful in 22s
First deploy of v26.08.21.1 showed two gaps:
- Every one-line CSS rule followed by a blank line hashed to sha1("") — the
declarations live on the selector line, which the #2872 "declarations only"
fingerprint dropped — so 68 unrelated one-liners across 17 files read as
one body-identical copy at the top of the derive readout. The selector
line's tail after "{" is now part of the hash; an all-blank remainder falls
back to the whole block.
- The proposer only examined unjudged rows, so consumers that were already
classified (auth.create_invitation → hash_token) never got a uses edge: 3
edges for hash_token after the first refresh. Judged rows are now scanned
for references (once per body), no proposal is made on them.
- 0084 migration docstring reworded: "function that …" at a line start parsed
as a definition (extractor false positive).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
||
|
|
6a0f8ad328 |
feat(backup): code_shape_uses travels (v9); consumer-map test expects uses (#2870)
CI & Build / Plugin hooks (push) Successful in 7s
CI & Build / Python lint (push) Successful in 3s
CI & Build / integration (push) Successful in 22s
CI & Build / TypeScript typecheck (push) Successful in 33s
CI & Build / Python tests (push) Successful in 55s
CI & Build / Build & push image (push) Successful in 25s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
d4c7b0e48d |
feat(ledger): uses edges — consumption is its own relation, conformance keeps one snippet_id (#2870, milestone 294)
CI & Build / Python lint (push) Successful in 5s
CI & Build / Plugin hooks (push) Successful in 9s
CI & Build / integration (push) Failing after 29s
CI & Build / TypeScript typecheck (push) Successful in 36s
CI & Build / Python tests (push) Failing after 39s
CI & Build / Build & push image (push) Skipped
A shape can follow one convention canon AND call several helper canons; the row's single snippet_id made the 2026-08 audit pick (hash_token won, the service-function convention lost), and hook evidence — pulled a snippet, then wrote code naming it — was stamped as instance when it is a uses fact. - code_shape_uses (migration 0084): shape → snippet, basis, evidence; unique per pair; cascades with both ends. USE_BASES: reference | hook | agent | audit | import. A judgment-grade basis overwrites a mechanical one, never the reverse. - classify_shapes items and classify_shapes_by_rule take uses=[snippet ids] (targets validated like snippet_id; all-or-nothing). - The write-path hook writes a uses edge for every pulled canon the payload names (the instance stamp is unchanged); the proposer writes a uses edge for every canon a body names (reference_canons: kind + language family + stoplist, same rules as the reference basis) — the mechanical form of "auto-confirm own-import references" deferred from #2871. - list_shapes(uses=N) lists the consumers of a canon; get_snippet's consumer map gains `uses` beside instances/variants. Operator decision on #2870 (2026-08-21): keep one snippet_id, add uses edges. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
bfe5a461b4 |
test(ledger): derive group sizes follow the #2872 order
CI & Build / Plugin hooks (push) Successful in 7s
CI & Build / integration (push) Successful in 19s
CI & Build / TypeScript typecheck (push) Successful in 33s
CI & Build / Python lint (push) Successful in 3s
CI & Build / Python tests (push) Successful in 56s
CI & Build / Build & push image (push) Successful in 21s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
3849c6fff3 |
test(ledger): derive label order follows #2872; binding-ref test imports compute_coverage
CI & Build / Plugin hooks (push) Successful in 7s
CI & Build / TypeScript typecheck (push) Canceled after 22s
CI & Build / Python tests (push) Canceled after 22s
CI & Build / integration (push) Canceled after 21s
CI & Build / Build & push image (push) Canceled after 0s
CI & Build / Python lint (push) Successful in 4s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
d01201539b |
test(ledger): derive summary expectation follows #2872 — dup group before name group
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 6s
CI & Build / Python tests (push) Successful in 58s
CI & Build / integration (push) Failing after 20s
CI & Build / TypeScript typecheck (push) Successful in 32s
CI & Build / Build & push image (push) Successful in 22s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
1126bbe84f |
test(ledger): the divergence acceptance case uses TS canon — proposer v3 gates sym bases by language family (#2871)
CI & Build / Python lint (push) Successful in 5s
CI & Build / Plugin hooks (push) Successful in 9s
CI & Build / TypeScript typecheck (push) Successful in 11s
CI & Build / integration (push) Successful in 22s
CI & Build / Python tests (push) Successful in 55s
CI & Build / Build & push image (push) Canceled after 4s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
1ab614bfbe |
feat(ledger): the scoped bucket — by-construction one-offs are stamped by the sync, not judged by a person (#2869, milestone 294)
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 9s
CI & Build / TypeScript typecheck (push) Successful in 23s
CI & Build / integration (push) Failing after 25s
CI & Build / Python tests (push) Canceled after 51s
CI & Build / Build & push image (push) Canceled after 0s
The 2026-08 audit left 77% of Scribe's ledger `exempt`, most of it a Vue component's scoped <style> rules and <script setup> functions — one-offs by construction (unreachable from any other file) that add nothing when judged one by one and bury the rows a person should look at. - coverage: Definition carries its line; scoped_definitions() names, per .vue file, every sym and every css rule inside <style scoped>; ArchiveShape carries the flag. - sync: such rows are stamped status=scoped / classified_by=mechanical with the by-construction reason (history event recorded); un-stamped back to unclassified if a later tree makes them ordinary; a judgment overrides. - The machine still sees them: proposer, derive grouping, divergence, hook evidence, canonical stamping and classify_shapes_by_rule's default all treat unclassified + scoped as the unjudged set (_MECHANICAL_TODO). Only the human todo (status=unclassified) and largest_gaps exclude them. - accounting counts `scoped`; coverage line and the project card legend show it; SHAPE_STATUSES gains it (no DB CHECK on status — no migration). - shape-accounting skill documents the bucket; plugin 0.1.37. Operator decision on #2869 (2026-08-21): keep extracting everything, stamp mechanically, keep `exempt` a human judgment. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
9abc4443fb |
feat(ledger): audit surfaces — list_shapes(compact=True) and classify_shapes_by_rule, the sweep form of a judgment (#2868, milestone 294)
CI & Build / Python lint (push) Successful in 4s
CI & Build / Plugin hooks (push) Successful in 10s
CI & Build / integration (push) Failing after 25s
CI & Build / TypeScript typecheck (push) Successful in 34s
CI & Build / Python tests (push) Successful in 1m0s
CI & Build / Build & push image (push) Successful in 26s
The 2026-08 audit judged 3,427 rows in 14 hand-driven batches through a raw MCP client because a list_shapes page overflowed the tool budget and every row had to be sent back one by one. Now: - list_shapes(compact=True): path · symbol · kind · status · signature, plus snippet_id / by / proposal / diverges_from / recheck only when set. A full 500-row page fits. CodeShape.to_compact() is the row shape. - classify_shapes_by_rule(project_id, path, status, pattern=, kind=, snippet_id=, reason=, via=, include_judged=): ONE judgment over every unclassified live row under a directory whose symbol matches a glob; judged rows are untouched unless include_judged; canonical is refused; same gates as the row form; one transaction; returns count + sample. shape_ledger.classify_shapes_where / rule_matches (pure) carry it. Tests: compact row pinned, rule_matches directory/glob/kind semantics, the tool mount, and an integration sweep (unclassified-only, include_judged, gates). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
bbee0d0db1 |
refactor(tests): one definition each for the copied fixtures and fakes (#2825, milestone 296 area 1)
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 8s
CI & Build / integration (push) Successful in 24s
CI & Build / TypeScript typecheck (push) Successful in 32s
CI & Build / Python tests (push) Successful in 54s
CI & Build / Build & push image (push) Successful in 18s
The shape ledger showed the same test scaffolding defined over and over: _bind_user x12 (byte-identical), _dispose_engine x10 in three wordings, _no_supersession x3, _make_mock_session x7 in three subsets, a get-or-create User helper x2 (+3 inlined), and fifteen hand-rolled MagicMock note factories each re-explaining the same "an auto-MagicMock attribute is truthy" hazard (note 2109). Now: conftest.py carries _bind_user / _dispose_engine / _no_supersession as opt-in fixtures (pytestmark = usefixtures(...) per module, so unit tests pay nothing), and tests/helpers.py carries make_mock_session(), ensure_user() and fake_note(**attrs) — the hazard documented once, real values on every attribute the product reads. Call sites were rewritten by AST so titles with dashes and commas survived; the three SimpleNamespace _note stand-ins that only feed a single function stay local. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
d74a244b3a |
feat(ledger): divergence readout — button B where button A is canon, shape history, and judged-shape recheck (#2793, milestone 294 step 7)
CI & Build / TypeScript typecheck (push) Failing after 2s
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 8s
CI & Build / integration (push) Successful in 28s
CI & Build / Python tests (push) Failing after 37s
CI & Build / Build & push image (push) Skipped
Every judgment now goes through one helper that remembers the fingerprint judged (classified_sha) and writes a code_shape_events row; the sync writes vanished / reappeared / drifted events and flags recheck_at when a body moves under an instance/variant. The refresh flags diverges_from on shapes new since the previous computation that sit where one canon dominates the judged siblings of their directory+kind and were not proposed as that canon (a first seed flags nothing); the write-path hint asks the same question in-band for the shapes the hook names. list_shapes(flag=divergence|recheck), shape_history(project_id, path, symbol) (read-only), coverage line/payload/ card carry divergent + recheck. Backup v8 carries the history. Plugin 0.1.36. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
ba0030e51d |
feat(ledger): mechanical proposer — every refresh proposes instances against canon and groups derive-first candidates; agents confirm in batches (#2792, milestone 294 step 6)
CI & Build / Python lint (push) Successful in 5s
CI & Build / Plugin hooks (push) Successful in 13s
CI & Build / integration (push) Failing after 34s
CI & Build / TypeScript typecheck (push) Successful in 35s
CI & Build / Python tests (push) Successful in 1m17s
CI & Build / Build & push image (push) Successful in 48s
Shapes now carry a content fingerprint (signature + whitespace/comment- insensitive body_sha; migration 0080) and the proposer runs inside the coverage refresh, the one moment bodies exist: symbol elsewhere → textual containment → body references the canon → signature resemblance → semantic (capped per refresh, unreached rows stay unexamined for the next). A hit is a proposal on the row (proposed_snippet_id/basis/score), never a classification; rows with no canon hit group by the derive-first rule (identical body in ≥2 places, same name in ≥3 files) as proposal_basis= derive + a group key. list_shapes(proposal=any|canon|derive|<basis>) is the queue; confirm_shape_proposals(project_id, snippet_id|path|basis) confirms in batches as agent instances; any classify_shapes/hook stamp retires the proposal. Readout carries proposed + derive_groups (line, payload, card). Plugin 0.1.35 (skill: the machine proposes, judgment classifies). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
a9e1cddba7 |
fix(tests): provisional ledger rows carry the empty seen-marker default, not NULL
CI & Build / Python lint (push) Successful in 4s
CI & Build / Plugin hooks (push) Successful in 13s
CI & Build / integration (push) Successful in 31s
CI & Build / TypeScript typecheck (push) Successful in 39s
CI & Build / Python tests (push) Successful in 1m1s
CI & Build / Build & push image (push) Successful in 25s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
475f0857c9 |
feat(ledger): write-path stamping — a pulled canon the session then instantiates lands as a hook instance row (#2791, milestone 294 step 5)
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
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> |
||
|
|
942edd1eb5 |
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
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> |