feat(spec): adr-0030-notification-event joins CREATION_ATTESTED_MIGRATION_IDS; its docblock states the ledger-claim matrix (#15710 ruling) - #16068
Conversation
…TION_IDS; docblock states the ledger-claim matrix The maintainer ruled the three questions the registration reserved: last_run_at on every completed non-error run, applied_at only on migrated, verified_at never (no self-check); receipt, not gate; and the id is creation-attested. The docblock states the matrix in place of "silence is not an answer"; the array gains the member; the pins that read the array literally move with it, and a spec pin holds the literal membership, the docblock relations and the arbiter's answer to the receipt shape. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01M59rPZZFzqhfMUPFqqZTkf
…ation-attested id The timing and deferral cases in plugin.test.ts assert the attested set as a sorted literal list or a literal count; both move with the new member, and the contradicted-gate case now attests the other two ids in array order. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01M59rPZZFzqhfMUPFqqZTkf
📓 Docs Drift Check1 anchor(s) derived from 1 changed package(s); no hand-written page names any of them, so this run has nothing to list — not a clean bill of health. This check sees only pages that NAME a derived anchor: one that documents this change in prose, or enumerates it in an authoring dialect, names none and stays invisible to it on every run. What this run could not see
Coarse fallback — 129 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 01d03d5f7fd3e71fc77dafa72324683b7094994b && git checkout 01d03d5f7fd3e71fc77dafa72324683b7094994b
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin c463d03e07912ffa32f446d8fd03aa32cd406091 35819dff25579a60a24f6fe3a65f339e0a1ccccd && git checkout -B drift-repro c463d03e07912ffa32f446d8fd03aa32cd406091 && git merge --no-ff 35819dff25579a60a24f6fe3a65f339e0a1ccccd
node scripts/docs-audit/affected-docs.mjs --json c463d03e07912ffa32f446d8fd03aa32cd406091 |
Fixes #15710
Ruling executed
Director seat, comment 5550131736 on #15710 — maintainer verbatim 「同意」 to decision batch #47 item 5, the question batch #21 had reserved (
5491064532, item 3: 「注册进台账时其applied状态语义要写清」). Quoted verbatim:Not reopened: #13998 stands on its historical answer. #14025 is not addressed here — PR #15450 landed the registration, and this card was the successor carrier of the question that registration reserved.
What landed
1. The docblock matrix —
NOTIFICATION_EVENT_MIGRATION_IDinpackages/spec/src/system/migration.zod.tsThe registration-era paragraph ("silence is not an answer") is replaced by the ruled matrix, written as bullets on the constant (no
.describe()text changed; symbols and files cited, never line numbers; provenance in one line — batch #47 item 5, the reserved question from batch #21):last_run_aterrorrun —migrated,already_done,not_applicablealikeapplied_atmigratedverified_atverified_atmeans one passedblocking0by constructiondetails.outcomeerrorrunThen "Receipt, not gate" — nothing reads the row as a precondition and nothing may; the shape is the one
sys-migration.object.tsdocuments for the seed-tenancy repair (verified_at: null,blocking: 0), whichisDataMigrationFlagVerifiedanswersfalseto — then the creation-attested paragraph, then one line deferring the run-receipt writer to the runner's lane.2.
CREATION_ATTESTED_MIGRATION_IDSgainsNOTIFICATION_EVENT_MIGRATION_ID(third member; existing members and order kept)The array's docblock now argues the third fact — no legacy
sys_notificationinbox row here — exactly as it argues the two ADR-0104 facts, and says the attestation row is the same uniform shape as theirs.verified_at: null.attestFreshDatastore(packages/platform-objects/src/system/migration-flag.ts) writes ONE shape for every member —verified_atset at birth,applied_at: null,blocking: 0,details.attested: 'datastore-created-empty'— and the pin the ruling names (migration-flag.test.tslines 137-141 on main) assertsisDataMigrationVerifiedistruefor every member. So on a fresh store this id's row reads verified BY BIRTH — never by a run, and gating nothing — exactly as the two ADR-0104 rows do. Ruling item 1 governs runs ("never set by this migration"); item 3 puts the id in the array and explicitly moves that pin with it. No runtime writer was changed: a per-id attestation shape would be new contract the ruling does not state (raised as an open question in the report, recommendation: keep the uniform shape).3. Pins
packages/spec/src/system/notification-event-migration-ledger.pin.test.ts(14 cases), in the style ofui/action-requires-confirmation-docblock.pin.test.ts(a source-text docblock pin): the literal three-member list in order; the docblock matrix read as bullets — each column's relation, not its wording — plus the retired sentence absent; a self-test feeding the registration-era paragraph to the same readers; and the arbiter: each run receipt (migrated/already_done/not_applicable,verified_at: null) answersfalsetoisDataMigrationFlagVerified, with a control showing the same row withverified_atset answerstrue.packages/platform-objects/src/system/migration-flag.test.ts: the by-construction iterations (lines 137-139, 190, 258, 267, 276) needed no edit; one symbol-named case added — the id is attested at birth in the uniform shape — because an iterating pin stays green with the member gone (the ablation below shows exactly that).packages/platform-objects/src/plugin.test.ts: the boot-attestation pins are literal by design — four sorted lists, threetoHaveLength(2), and the contradicted-gate case — all moved to three members (adr-0030-notification-eventsorts first; the contradicted-gate case now attests the other two ids in array order).packages/objectql/src/adr0104-attestation-evidence.test.ts: measured, NOT moved — it never reads the array (it hand-builds attestation rows for the two ADR-0104 gates and asserts the engine's gate reads, which are keyed to those two ids); 19/19 green unchanged. The ruling's "moves with it" did not hold for this file.4. Changeset
.changeset/notification-event-migration-ledger-claims.md—@objectstack/specminor, additive: no authorable key, export or accept-set narrows, so the launch-window BREAKING banner does not apply;check:adr-0087-registrationjudges only declared-breaking changesets (breakingDeclaration:major/**BREAKING/feat!:), so no disposition marker is owed.check:changeset-no-majorandcheck:empty-changesetgreen.Runtime side — measured, not changed
The runtime writer of the receipt row is a follow-on card in the runner's lane, filed by the seat on landing. For this PR: no code path writes a
sys_migrationrow foradr-0030-notification-eventtoday (packages/metadata/src/migrations/has nosys_migration/recordDataMigrationRun/applied_atreference; the threeapplied_atwriters repo-wide arerecordDataMigrationRun,attestFreshDatastoreand the seed-tenancy backfill, none keyed to this id). No reader gates on it:NOTIFICATION_EVENT_MIGRATION_IDand its literal have zero readers outsidepackages/spec, and the engine's two ledger gate reads are keyed to the ADR-0104 ids — the stop condition did not trigger.CREATION_ATTESTED_MIGRATION_IDShas exactly one runtime reader,attestFreshDatastore;packages/clidoes not read it (the dispatch's M1 was half true).Verification
Tree
35819dff2(branch head); specdistrebuilt from that source (preflight: marker present in 2 built files). Every build/test ran underscripts/pm/os-verify-lock.shon a shared box; the wrapper's verdict lines are quoted.vitest run src/system/migration.test.ts src/system/notification-event-migration-ledger.pin.test.ts—Test Files 2 passed (2),Tests 39 passed (39).vitest run src/plugin.test.ts src/system/migration-flag.test.ts—Tests 42 passed (42).vitest run src/adr0104-attestation-evidence.test.ts src/adr0104-lax-deviation-marker.test.ts—Tests 19 passed (19)....@objectstack/spec, the four packages the seat named plus spec itself):turbo run typecheckover spec, platform-objects, objectql, cli, metadata at--concurrency=2—Tasks: 61 successful, 61 total(5m40s, shared box; includes speccheck:test-typecheckandcheck:scripts-typecheck, so the new pin file type-checks).check:generated—✓ All 15 generated artifacts are up to date: no artifact moved (the const already existed; const TSDoc is not part of the generated docs).node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack(5 paths vs merge-base53cbad9f7):Run reconciliation — 74 derived, 74 run, 0 NOT-MEASURED, 0 UNRUN, every family exit 0.check:doc-authoring(M4) green in both runs.git checkout HEAD -- path, proven each leg byhash-object == HEAD bloband an emptygit diff HEAD;trapon EXIT/INT/TERM; absolute paths:ablation-dist-preflight --absent:marker absent from all 217 built files. Spec pin:2 failed | 12 passed(the literal list; the type/includes case). platform-objects:9 failed | 33 passed(the 8 literal pins inplugin.test.tsand the new symbol-named case; the iterating loop stayed green — which is why the literal pins exist).verified_atbullet loses its negation (src-only, on-disk proven): spec pin1 failed | 13 passed, exactly theverified_atcase.preflight: marker present in 2 built files, spec pin14 passed (14), platform-objects42 passed (42), tree clean.Declared to CI:
turbo ls --affectedagainst53cbad9f7lists 75 packages (everything depends on spec); locally this diff can move only the consumer tests over the migration-flag / attestation files and the typecheck of spec's named consumers, which is what ran. The rest of the farm is CI's.Out of scope
finding,attestFreshDatastorenamesos migrate value-shapesas the remedy for every contradicted id that is notfiles-to-references— with a third creation-attested id the ternary is a wrong remedy on a path nothing reaches yet #16067:attestFreshDatastore's contradiction warning namesos migrate value-shapesfor every id that is notfiles-to-references; unreachable for the third member today (the engine keys admitted violations by the two ADR-0104 ids only), so not touched here.🤖 Generated with Claude Code
Generated by Claude Code