Skip to content

Commit b6471ba

Browse files
fix(metadata): close out the adr-0030-notification-event retirement residue (#18389)
Fixes #17281 Clause-②: no — this PR puts no new key on a published payload. It adds one changeset row, removes a dead workspace dependency (a narrowing, never a widening) and corrects stale prose; triage's grading `5692961190` states it directly: "nothing widens an accept set or a public surface". Declared by the dispatching seat in claim `5693760798`. Residue from the `adr-0030-notification-event` retirement (#16194 / PR #17194, merged `d64bcb6377`). Four items, four commits, item 1 first and alone as the triage grading `5692961190` directed, then re-cut on the maintainer's ruling `5698965201`. ## Item 1 — the `platform-objects` release note (re-cut on ruling `5698965201`) `797caf0c` first put `'@objectstack/platform-objects': minor` on the **existing** `.changeset/retire-adr-0030-notification-event-migration.md`. `d2544585` undoes that and takes route B instead. Two acts, one commit: - **The base note is restored byte-for-byte.** Measured, not asserted: `git rev-parse 8b81ab6:.changeset/retire-adr-0030-notification-event-migration.md` and `git hash-object` on the restored working-tree file both read `2ae652749b40dec974fdfb5fcf5fe0990267fe53`, and `git diff 8b81ab6 HEAD` on that path prints nothing. The file is no longer in this PR's diff at all. - **The bump moves to a new, issue-scoped changeset** — `.changeset/17281-platform-objects-attest-fresh-datastore.md`, declaring exactly `'@objectstack/platform-objects': minor`, named the way the gate itself prescribes (`.changeset/{issue}-{slug}.md`). The note is written for a release reader rather than for this PR: a datastore created from empty now attests **two** creation-attested migration ids instead of three, because `attestFreshDatastore` (`packages/platform-objects/src/system/migration-flag.ts`) defaults to `CREATION_ATTESTED_MIGRATION_IDS` and that tuple lost `'adr-0030-notification-event'` in the retirement. No row is written under the retired id any more; a deployment that already holds one keeps it, and `NOTIFICATION_EVENT_MIGRATION_ID` survives as that row's name. The bump is owed at all because that operator-visible half lives in `@objectstack/platform-objects`, a package with no `private: true`, and the retirement's own release note never declared it. ### The ruling, and its one declared cost Maintainer ruling `5698965201` chose **B**: open a new changeset file for `platform-objects`, and do not touch the release note that already exists on the merge base. That is the `confirmed` which `check:empty-changeset`'s DELIBERATE CORRECTION class asks for — and what it authorises is this route, not an edit in place. ⚠️ The cost, named rather than hidden: the CHANGELOG will carry a **separate `platform-objects` entry** instead of a row under the adr-0030 retirement note. The same release semantics, told in two places instead of one. ### Two premises the ruling asked to be falsified before acting Both were put to a measurement that could have come out the other way. Neither broke. 1. **"Restoring the base note republishes a sentence that is now false."** It does not. Every claim in that note is about the retirement itself — the deleted runner, its three types, `CREATION_ATTESTED_MIGRATION_IDS` going from three members to two, `NOTIFICATION_EVENT_MIGRATION_ID` being kept. This PR's diff touches `packages/metadata` and `packages/plugins/plugin-audit` and **no** file under `packages/platform-objects`, `packages/spec` or `packages/metadata/src/migrations`'s deleted runner. The control that could have falsified it: grepping the base note for this PR's own subject matter — `platform-objects`, `dependen`, `vitest`, `tsconfig`, `package.json`, `alias`, `paths` — returns **zero** hits, so there is no sentence in it that this diff could have made false. The note is **under-declared**, not false: the `platform-objects` half moved in the original retirement (`d64bcb6377`, PR #17194), whose file list carries `packages/platform-objects/src/system/migration-flag.ts`, `migration-flag.test.ts` and `plugin.test.ts`. 2. **"A changeset naming a package this diff does not move is refused by another gate."** It is not — measured for `minor` specifically, not inferred from the `patch` assertion. `check-changeset-no-major.mjs` run against a synthesised `pull_request` payload carrying this PR's real `Clause-②: no` exits **0**, printing `✓ LEVEL AXIS: this PR declares clause-② 'no'`. The firing control, the same command on the same tree with the payload flipped to `Clause-②: yes`, exits **1** — so the axis was live and capable of failing, and what it then prints is the sharper reading: the only package it lists is `@objectstack/metadata: patch`, because `packages/platform-objects/src/**` is not in this diff. A `minor` on a package the diff does not move is invisible to that gate in both directions — never refused, and never credited either. ## ⚠️ Item 2 — the dead dependency (`bccdf6c1b`) `@objectstack/metadata` no longer declares `@objectstack/platform-objects`. Three files, removed together because all three exist only to serve one dead edge: the `dependencies` entry, the `@objectstack/platform-objects/system` alias in `vitest.config.ts`, and — **not named in the card, found while measuring** — the matching `paths` mapping in `tsconfig.json`, which pointed at the same dead specifier. The card required that no consumer resolving the dependency transitively be established **before** removing it. Established, not assumed: | reading | result | |:---|:---| | `@objectstack/platform-objects` specifiers under `packages/metadata` | **zero** in `src`, tests and scripts — only the three config/manifest sites removed here | | occurrences of `platform-objects` in `@objectstack/metadata`'s built `dist/` (30 files, 10 declaration files) | **zero** | | positive control: the nine other declared deps, same `dist/` | present in **4–12 files each** | | workspace packages carrying a real `platform-objects` module specifier | **23**, and **all 23 declare it themselves** | | of those, resolving it transitively | **zero** | | example apps referencing it | **zero** | ⇒ No runtime import and no type reference reaches `platform-objects` through anything `@objectstack/metadata` publishes, so no consumer can arrive at it via this package. `check:undeclared-dep-imports` is the standing gate that keeps the in-repo half true for non-test `src/**`, and it is green here. **Residual, declared rather than hidden:** an external consumer that installs `@objectstack/metadata`, imports `@objectstack/platform-objects` without declaring it, and relies on npm's flat hoist would lose that accidental resolution. That is unmeasurable from here; it is also the class this repo's own gate treats as a defect, and `@objectstack/platform-objects` publishes on its own, so the supported spelling exists. The changeset states the one-line fix. **`pnpm-lock.yaml` travels in the same commit**, regenerated with `pnpm install --lockfile-only` and never hand-edited. Its entire diff is the three lines of the one removed edge under the `packages/metadata` importer. An earlier push carried the manifest edit without it and failed `ERR_PNPM_OUTDATED_LOCKFILE` at every job's install step; that is fixed here, and it is ⛔ not evidence about whether the removal itself is safe — the readings above are. Graded `patch` — no export moves, no accept-set widens, no behaviour changes — and deliberately not `skip-changeset`: `package.json` is shipped by `npm pack`, and a consumer's install tree is what changes. ## Items 3 and 4 — the two stale prose lines (`466593dc0`) Comment-only; no assertion, harness or gate input moves. - `plugin-audit/src/read-audit-view-instant-preservation.integration.test.ts` cited `migrate-sys-notification-to-event.test.ts` and `packages/runtime/src/notification-migration-audit-preservation.integration.test.ts` as files a reader could open. Both measured absent, with a sibling that IS present as the positive control. Marked retired; the first citation is kept because the SHAPE it demonstrated is the paragraph's point. - `metadata/src/migrations/raw-exec-operator-detail-16657.test.ts` said "at the three `err?.message ?? String(err)` sites". **Two**, measured rather than carried: the directory holds two `catch (err: any)` sites recording through `operatorFacingErrorText` and one `catch (error)` site, matching the docblock's own two-expression split. The third is visible in the pre-merge tree of `d64bcb6377`, in the deleted runner, as `{ outcome: 'failed', reason: err?.message ?? String(err) }`. ⚠️ **Commit shas corrected after the fact.** This body cited `063efde2` and `fd28ee6f`, and `git merge-base --is-ancestor` puts NEITHER on this branch (control: the merge base `8b81ab60d` exits 0 in the same checkout, so the negative is real). The branch was re-cut after that text was written. The live commits are `bccdf6c1b` (item 2) and `466593dc0` (items 3 and 4), each mapped by its own file list. Found by the delivering agent and corrected by the dispatching seat. ## Gates Derived from the actual changed files with `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` on head `d2544585e`, each run with its exit code written to disk **before** anything read it, then reconciled by feeding the codes back: ``` Run reconciliation — 75 derived, 75 run, 0 NOT-MEASURED, 0 UNRUN. ✓ dispatch-gates --ran: 75 derived famil(ies) accounted for — 75 run, 0 NOT-MEASURED (a DERIVED zero — all 75 recorded an exit code and none of them is 3). ``` **74 of 75 green**, plus `pnpm lint` — the full repo-wide union, which the derivation does not name and therefore never asks for — at **exit 0** on `d2544585e`. ⭐ **`check:empty-changeset` is the point of this commit, and it has turned over.** On `466593dc0` it exited **1**: ``` This PR changes a changeset it did not add: .changeset/retire-adr-0030-notification-event-migration.md present on the merge base and CHANGED by this PR ``` On `d2544585e` it exits **0**: ``` ✓ No empty-frontmatter changeset introduced by this diff (2 declaring changeset(s) added). ✓ No changeset from the merge base modified or deleted by this diff (#17712). ``` `check-changeset-no-major.mjs` exits **0** on the same head, on both of its axes. The one family that is not green is not a defect introduced here: - **`check:cross-package-test-inputs` — exit 1, pre-existing (#18353 / #18348).** It names `@objectstack/cli` descending `packages/spec/dist/` from `packages/cli/test/init-created-files-summary.e2e.test.ts`; neither package is in this diff. Both readings were taken on this head: exit **0** before the build (that tree has no `packages/spec/dist`, so the walk had nothing to descend — a vacuous green) and exit **1** after it. The exit 1 is the reading that counts, and it is somebody else's card. ⚠️ Six gates first read `exit 3` `PREREQUISITE NOT MET` — neither pass nor failure — because they load built output. After `turbo run build --filter=!@objectstack/docs` all six are green: `check:dts-closure`, `check:dual-build-cjs-loads`, `check:i18n`, `check:lean-entry-closure`, `check:sourcemap-no-sources-content`, `check:type-check-debt`. ⚠️ The derivation printed a **STALE TREE** warning: this branch is at least 31 commits behind `origin/main`, and 10 of the files the families are derived from moved across that range. Discharged by measurement rather than by argument — the same derivation, run in a throwaway worktree checked out **at `origin/main` (`8fe5cb8e5`)** with this branch merged in uncommitted, derives the same 8 paths and a **byte-identical** 75-command list (`diff` exit 0). The staleness does not move the family set for these paths. Package-level test and typecheck readings are unchanged from `466593dc0` (`@objectstack/metadata` 53 files / 788 tests, `@objectstack/plugin-audit` 24 files / 346 tests, `typecheck` green for both): `d2544585e` adds nothing on top of that head but two `.changeset/*.md` files, which no test or typecheck program reads. ## Acceptance notes - `packages/metadata/vitest.config.ts` keeps one `platform-objects` mention, deliberately: the comment on the `@objectstack/spec` namespace rule contrasts spec's uniform export map with the FILE-shaped `@objectstack/platform-objects/plugin` subpath. That prose is still accurate and load-bearing about *spec*, and is not residue. - `.changeset/operator-facing-raw-exec-cause-text.md` is untouched — another PR's changeset, as the card directs. - `docs/adr/0052-audit-is-not-the-activity-feed.md:327` is untouched — governed surface, and #17193 is its route. - Neither changeset this PR adds carries a `Clause-②` line, and the restored base note does not carry one either; 4 of the 334 changesets in the tree do. Noted, not filed — out of scope here. Claim: `5693760798`. Triage: `5692961190`. --- _Generated by [Claude Code](https://claude.ai/code)_ --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 85c6d76 commit b6471ba

8 files changed

Lines changed: 82 additions & 25 deletions
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
---
2+
'@objectstack/metadata': patch
3+
---
4+
5+
`@objectstack/metadata` no longer declares `@objectstack/platform-objects`.
6+
7+
The dependency was the retired `adr-0030-notification-event` migration runner's,
8+
and that runner was its only consumer. Nothing under `packages/metadata/src`
9+
carries a `@objectstack/platform-objects` specifier any more, so the declaration
10+
described an edge the package no longer has. The two test-tooling entries that
11+
existed only to serve it go with it: the `@objectstack/platform-objects/system`
12+
alias in `vitest.config.ts` (whose comment still cited the retired migration's
13+
receipt cases as its reason) and the matching `paths` mapping in `tsconfig.json`.
14+
15+
## What an installing consumer should check
16+
17+
⚠️ This is a **published** package dropping a declared dependency, so it changes
18+
what an install tree contains, not just what this repo builds. If you import
19+
`@objectstack/platform-objects` **without declaring it**, and it resolved for you
20+
only because `@objectstack/metadata` hoisted it, that resolution is gone — the
21+
fix is one line, and it is the supported spelling either way:
22+
23+
```
24+
pnpm add @objectstack/platform-objects # or npm/yarn equivalent
25+
```
26+
27+
`@objectstack/platform-objects` is published on its own and is unchanged by this;
28+
nothing is renamed, removed or re-exported.
29+
30+
⛔ Nothing `@objectstack/metadata` itself ships is affected. Measured rather than
31+
asserted: its built `dist/` (30 files, 10 declaration files) carries **zero**
32+
occurrences of `platform-objects`, against a positive control in which all nine
33+
of its other declared dependencies appear in four to twelve dist files each. No
34+
runtime import and no type reference reaches it, so no consumer can arrive at it
35+
through anything this package publishes.
36+
37+
Grade `patch`, measured rather than defaulted: no export moves, no accept-set
38+
widens, no runtime behaviour changes. Not `skip-changeset` either — `package.json`
39+
is shipped by `npm pack`, and a consumer's install tree is what changes.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
---
2+
'@objectstack/platform-objects': minor
3+
---
4+
5+
A datastore created from empty now attests **two** creation-attested migration ids, not
6+
three.
7+
8+
`attestFreshDatastore` (`@objectstack/platform-objects/system`) writes one `sys_migration`
9+
row per id in `CREATION_ATTESTED_MIGRATION_IDS` (`@objectstack/spec/system`) at the moment
10+
a store is created from empty. That tuple lost `'adr-0030-notification-event'` when the
11+
ADR-0030 notification cut-over was retired, so a store born on this version is attested for
12+
`'adr-0104-file-references'` and `'adr-0104-value-shapes'` alone.
13+
14+
## What an operator sees
15+
16+
- A fresh deployment's `sys_migration` table holds **two** creation-attested rows where it
17+
held three. Nothing else about them moves: both carry the same
18+
`attested: 'datastore-created-empty'` marker in `details`, and both ADR-0104 gates are
19+
enabled from birth exactly as before.
20+
- **No row is written under `'adr-0030-notification-event'` any more, and nothing reads
21+
one.** A deployment that already holds such a row keeps it, untouched —
22+
`NOTIFICATION_EVENT_MIGRATION_ID` (`@objectstack/spec/system`) survives as that row's
23+
name so the table stays readable by an operator. The id gates nothing, and never did.
24+
- Nothing this package exports is renamed, removed or re-signed. `attestFreshDatastore`
25+
takes the same arguments and answers the same shape; a caller passing its own
26+
`migrationIds` is unaffected, because only the default moved.
27+
28+
There is nothing to adopt and no command to run. Pre-ADR-0030 `sys_notification` rows are
29+
not carried by the platform on this line, so a store created from empty has nothing the
30+
retired id could have attested.

packages/metadata/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@
8383
"@objectstack/core": "workspace:*",
8484
"@objectstack/metadata-core": "workspace:*",
8585
"@objectstack/metadata-fs": "workspace:*",
86-
"@objectstack/platform-objects": "workspace:*",
8786
"@objectstack/spec": "workspace:*",
8887
"@objectstack/types": "workspace:*",
8988
"chokidar": "^5.0.0",

packages/metadata/src/migrations/raw-exec-operator-detail-16657.test.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,16 @@
2323
* ⚠️ That channel is a RULE, not byte-identity with what these `catch` blocks
2424
* used to compute, and the negative pins below do not claim otherwise: each
2525
* throws a NON-EMPTY `new Error(…)`, the shape for which the rule and the old
26-
* expression agree. They differ elsewhere — at the three `err?.message ??
26+
* expression agree. They differ elsewhere — at the two `err?.message ??
2727
* String(err)` sites `new Error('')` recorded `''` and now records `'Error'`,
2828
* and `{message:42}` recorded the number where it now records
2929
* `'[object Object]'`; at the `error instanceof Error ? … : String(error)` site
3030
* `{message:'x'}` recorded `'[object Object]'` and now records `'x'`.
3131
*
32+
* ⚠️ Two, not the three this said when it was written. The third was
33+
* `migrateSysNotificationToEvent`, and it went with that runner when the
34+
* adr-0030-notification-event migration was retired.
35+
*
3236
* ⚠️ The composed sentence is the producer's, copied; `driver-sql`'s
3337
* `sql-driver-16657-operator-facing-cause-text.test.ts` pins the copy against a
3438
* real `SqlDriver.execute()` refusal.

packages/metadata/tsconfig.json

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,6 @@
1313
"types": [
1414
"node",
1515
"js-yaml"
16-
],
17-
"paths": {
18-
"@objectstack/platform-objects/system": ["../platform-objects/src/system/index.ts"]
19-
}
16+
]
2017
}
2118
}

packages/metadata/vitest.config.ts

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,18 +43,6 @@ export default defineConfig({
4343
replacement: path.join(path.resolve(__dirname, '..'), 'spec/src/$1/index.ts'),
4444
},
4545
{ find: /^@objectstack\/spec$/, replacement: path.resolve(__dirname, '../spec/src/index.ts') },
46-
// [#16100] The deployment-ledger writer/reader pair the notification-event
47-
// migration's receipt cases drive (`attestFreshDatastore` seeds the
48-
// fresh-store row, `isDataMigrationVerified` reads the verdict back). The
49-
// entry is ANCHORED on the subpath rather than spelled bare: this package
50-
// publishes a FILE-shaped subpath (`./plugin`), so a bare prefix rule with
51-
// a file replacement would resolve `…/system` to
52-
// `…/platform-objects/src/index.ts/system` — ENOTDIR at run time, from a
53-
// config that reads as correct.
54-
{
55-
find: /^@objectstack\/platform-objects\/system$/,
56-
replacement: path.resolve(__dirname, '../platform-objects/src/system/index.ts'),
57-
},
5846
// Subpath BEFORE the bare package, same prefix-match reason: `./node` is a
5947
// published subpath served by a FILE (`types/src/node.ts` — the node-only slice
6048
// the root export deliberately excludes), so the bare entry would resolve it to

packages/plugins/plugin-audit/src/read-audit-view-instant-preservation.integration.test.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,21 @@
1515
* the driver stores, on BOTH sides of any change to the write's context. The
1616
* case is green today, was green before #15964 flattened the ordinary insert
1717
* branch, and stays green after this card's fix. An instrument that cannot fail
18-
* is indistinguishable from a pass — the same shape that let
18+
* is indistinguishable from a pass — the same shape that let the since-retired
1919
* `migrate-sys-notification-to-event.test.ts` read `23 passed` for #16312 while
20-
* the rows it described were being restamped.
20+
* the rows it described were being restamped. That file went with the
21+
* adr-0030-notification-event migration it covered; it is named here for the
22+
* SHAPE it demonstrated, not as a file to go read.
2123
*
2224
* ⇒ this file is the instrument that CAN fail. It boots a real
2325
* {@link ObjectKernel} with the real {@link ObjectQLPlugin} (so the shipped
2426
* audit stamp hooks are registered) over a real {@link SqliteWasmDriver}, and
2527
* reads the persisted row back through the driver's own SQL surface.
2628
*
2729
* ⚠️ Unlike #16312's equivalent (`packages/runtime/src/notification-migration-
28-
* audit-preservation.integration.test.ts`), this one lives beside the code it
29-
* tests. That file had to leave `packages/metadata` because
30+
* audit-preservation.integration.test.ts`, retired together with the migration
31+
* it covered and no longer in the tree), this one lives beside the code it
32+
* tests. That file had had to leave `packages/metadata` because
3033
* `@objectstack/objectql` depends on it and the test-only import would have
3134
* closed a cycle. Here the edge already runs the other way —
3235
* `@objectstack/plugin-audit` depends on `@objectstack/objectql` — and

pnpm-lock.yaml

Lines changed: 0 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)