Repository navigation
feat(spec)!: retirement kits whose conversion retired at or below 16.x age out; the strict unknown-key refusal names the protocol upgrade guide - #26599
Conversation
…the upgrade guide (#25767) [wip] Work in progress, paused on maintainer instruction (token budget); not yet gate-green. Done so far: - conversions/registry.ts: the 50 retiredAfter-≤16.x conversions and their retired-key / retired-def tables are removed; chain floor rises 16 → 17 (MIGRATION_SUPPORT_FLOOR), MigrationFloorError names the upgrade guide. - 55 ≤16.x tombstones on strict containers deleted; retiredKey() tombstones on non-strict containers kept (a delete would strip silently). - shared/protocol-upgrade-guide.ts: RETIRED_KEY_UPGRADE_GUIDE_SENTENCE, emitted by the strict unknown-key refusal after its fix channels and ahead of the history sentence (#5955 order). - build-schemas.ts tombstone-age gate (registry row or previous-major tag proof); migrations registry.ts.template permanence docblock. - ADR-0087 amendment, upgrade guide page, changeset; cli migrate meta support floor. - Test pins rewritten for ai, automation, conversions, data, kernel, migrations, shared, security and most of ui. Left: ui/view*, ui/dashboard*, scripts liveness pins; full spec test run; cli floor-17 pins; dispatch gates; PR body and report. Claude-Session: https://claude.ai/code/session_01H37vtTJRVBf1LkyYNW5yfo Co-authored-by: Claude <noreply@anthropic.com>
…-key refusal names the protocol upgrade guide Maintainer ruling on #25767 (D2 = A): a retirement kit lives through the protocol major after the one it retired in and leaves when the next major is cut. At 18 that removes everything retired at or below 16.x — 50 D2 conversions and their fixtures, 55 tombstones on strict containers, the 159 major-17 migration entries and the chain's step 17 — and keeps the 17.x and 18.x kits for 19 to repeat the move. - A removed key meets the strict unknown-key refusal, which now carries one more sentence after its fix channels and before the history sentence: keys retired before the previous major are no longer prescribed here — see the protocol upgrade guide (`RETIRED_KEY_UPGRADE_GUIDE_SENTENCE`, `PROTOCOL_UPGRADE_GUIDE_URL`). - `MIGRATION_SUPPORT_FLOOR` is 17: `os migrate meta --from 16` and below answer `MigrationFloorError`, naming the floor and the guide; the chain is one hop (18). The 17.7.0 load-path conversions stay registered for the data-at-rest seams but have no replayable step; the three protocol-18 entries that linked one drop the link and name the hand edit (the F4/F5 shape). - `check:authorable-surface` ages a tombstone one major, dating a deleted `[RETIRED]` line by a registry row or by the previous major's release tag; no gate is added. - ADR-0087 amended in place; the template, the upgrade guide, the retirement skill and one changeset follow. Spec, cli, lint and metadata-core tests re-pinned to the refusal or to surviving kits. Claude-Session: https://claude.ai/code/session_01H37vtTJRVBf1LkyYNW5yfo Co-authored-by: Claude <noreply@anthropic.com>
Brings in the 84 commits main gained since the branch base. Source files merged without a text conflict; the merge driver deferred eleven generator-owned artifacts (authorable-surface ui/security, the permission liveness state-counts page, eight reference pages), regenerated here from the merged tree with the spec generators, not by hand. Claude-Session: https://claude.ai/code/session_01H37vtTJRVBf1LkyYNW5yfo Co-authored-by: Claude <noreply@anthropic.com>
…e 17.x kits, not the retired ≤16.x ones The ≤16.x retirement kits left the registry in the previous commit, and two suites still rode them as fixtures: - packages/metadata-protocol's stored-row seams (migrateStoredMetadata, getMetaItem(s), loadMetaFromDb, the residue re-save and the non-canonical-type control) used the `conditionalRequired` → `requiredWhen` field rename and the action `execute` → `target` alias as the legacy shape the stored seam keeps lowering. Those conversions are gone, so the rows now carry the 17.2.0 `reference_to` → `reference` rename (`field-reference-to-alias`) and the 17.4.0 `aria` removal (`action-aria-removed`), both still registered for the data-at-rest seams; the pins read the same notices, rewrites, checksums and report lines as before, on the surviving kit. - packages/lint's object-door field-rule test listed `conditionalRequired` among the slots the build's expression walk judges; the walk no longer reads it (its tombstone aged out of `FieldSchema`, so the key is a strict unknown key), and the row is dropped with the docblock saying why. Claude-Session: https://claude.ai/code/session_01H37vtTJRVBf1LkyYNW5yfo Co-authored-by: Claude <noreply@anthropic.com>
…ns on the retired ≤16.x kits ride 17.x kits or the strict refusal Running every package whose sources read the conversion registry in full found the rest of the pins that rode a kit the previous commits removed: - packages/metadata-protocol: the served-schema property counts (#17501) move down by exactly the top-level tombstones that left each shape (action 3, agent 2, app 8, dashboard 2, field 1, flow 2, skill 1); the #17502 repeater-row pin moves from the dashboard widget row, which has no tombstone left, to the page component row (`visibility`, `responsive`, 17.x kits), with the dashboard keeping its depth pin through `refreshInterval` and the widget `chartConfig`; the aged-out widget column is pinned as the strict refusal it is now; the #21982 fallback pin rides `errorHandling.retryDelayMs` (`retry-policy-converged`, 17.7.0) instead of `flow.active`, and `flow.active` is pinned refused on both hosts, naming the upgrade guide. - packages/services/service-automation: the script `actionType` stubs are refused at registration as unknown keys naming the guide (nothing strips them on rehydration any more), the fault-edge guard rides the bare contract, and the wait-node round trip holds the `timeout` guidance channel, with the aged-out `timeoutMs` pinned as the strict refusal. - packages/objectql: the rule validator pin shows the chain no longer lowers the aged-out `conditionalRequired` alias and enforces the rule on the canonical `requiredWhen` only. Claude-Session: https://claude.ai/code/session_01H37vtTJRVBf1LkyYNW5yfo Co-authored-by: Claude <noreply@anthropic.com>
…-seam pins ride the 17.x kits; the aged-out ≤16.x spellings are pinned as strict refusals The two remaining consumer suites of the conversion registry carried fixtures in the ≤16.x dialect the previous commits retired: - packages/runtime: the #12892 two-reader harness and the two real-boot files (the security registrar, the #14491 seeder declaration copy) wrote the stack's `roles`, an RLS `priority` and a `sharedWith.type: 'role'` recipient, each governed by a kit that left the registry. The fixtures now write `positions`, no `priority` and a `position` recipient; the conversion axis is measured on the 17.x kits that still reach the security collections (the `allowRestore` / `allowPurge` grant bits, `accessLevel: 'full'`); and a new harness pin shows the door refusing each aged-out spelling outright — a strict unknown key naming the upgrade guide, an invalid recipient option. The #3878 analytics-entry pins expect `query` refused as a strict unknown key naming the guide instead of the envelope's per-key prescription. - packages/services/service-datasource: the #4456 restore-seam pin shows what the seam replays now — the 17.7.0 `mongo` → `mongodb` driver alias — and that a row still in the ≤16.x config spelling (`file`, `connectionString` / `user`, `uri`) is served as stored: the row the ruling sends through `os migrate meta --stored --apply` on 18.1 or earlier. Claude-Session: https://claude.ai/code/session_01H37vtTJRVBf1LkyYNW5yfo Co-authored-by: Claude <noreply@anthropic.com>
…6 or earlier" — one major at a time, stored rows before the runtime moves The maintainer's ruling relayed on the PR (B, ships in 18.2): make the path a ≤16.x project takes prominent, text only. One block, in the two places the ruling names — the changeset, because the 18.2.0 release notes are cut from it, and the top of docs/protocol-upgrade-guide.md: - the default, one major at a time: `@objectstack/cli@17.7.0 migrate meta --from 16 --apply`, its `--stored --apply` for the sys_metadata rows, then the move to 18.2 and `os migrate meta --from 17 --apply`, `os validate`, `os build` — and the rule it follows, each major's CLI in turn, which holds at 19; - the one-shot alternative on `@objectstack/cli@18.1.0`, the last release whose floor is 16; - stored rows are migrated before the deployment's image or dependencies move to 18.2, since 18.2 no longer rewrites a ≤16.x row at read; - what 18.2 does when the first hop is skipped: `--from 16` refuses with MigrationFloorError and rewrites nothing, and a ≤16.x key meets the strict unknown-key refusal with the guide link. No code and no generated file changes; content/docs/upgrading.mdx keeps its floor callout, which names the 18.1 path as the alternative does. Claude-Session: https://claude.ai/code/session_01H37vtTJRVBf1LkyYNW5yfo Co-authored-by: Claude <noreply@anthropic.com>
Brings in the 40 commits main gained since the previous merge. One text conflict, in the #17501 served-schema property-count pin: main moved `object` 47 → 48 for the `sharing` block (#25760) while this branch had re-derived every count without the top-level tombstones that left each shape; resolved as the branch's counts with `object` at 48. The merge driver deferred four generator-owned artifacts (the data authorable surface and three reference pages), regenerated here from the merged tree with the spec generators, not by hand. Claude-Session: https://claude.ai/code/session_01H37vtTJRVBf1LkyYNW5yfo Co-authored-by: Claude <noreply@anthropic.com>
…a site route into the generated directory CI's Check Documentation Links (lychee, offline, --root-dir content) went red on the merged head: content/docs/upgrading.mdx linked the guide as `/docs/protocol-upgrade`, a site route into content/docs/protocol-upgrade/, which is generated by `gen:upgrade-guide` and git-ignored, so a checkout has no file for it. The link now carries the guide's address, the spelling the backward-compatibility page and the refusal text already use, and the one the offline lane excludes by scheme. No other link-checked page on the branch targets an untracked path (resolved against `git ls-files`). Claude-Session: https://claude.ai/code/session_01H37vtTJRVBf1LkyYNW5yfo Co-authored-by: Claude <noreply@anthropic.com>
…bulkEnabled` action keys
CI's Build Core went red on the merged head in ui/packages/core: `ActionDef`
declared `shortcut?: SpecActionInput['shortcut']` and `bulkEnabled?:
SpecActionInput['bulkEnabled']`, two mirrors of spec-17 `retiredKey()`
tombstones that resolved to `undefined` for as long as the tombstones
stood. The ≤16.x kits left the schema one major on, so the indexed access
has nothing to name and tsc refuses it. The two members leave `ActionDef`
with their rows in `ACTION_DEF_KEYS` and `SPEC_ACTION_KEYS` (the key
inventories the pin tests hold against the spec's `ActionSchema` shape),
and `SPEC_ACTION_KEYS` drops its `execute` row for the same reason: the
pin that walks the spec shape reported it stale once that tombstone aged
out. `RETIRED_ACTION_KEYS` keeps the console's own `execute` rename
prescription (a stored row can reach the runner unparsed), and
`ActionEngine.registerAction(action, { shortcut, bulkEnabled })` keeps
both as host-passed options, as before; the closed-surface pin's comment
and the tombstone test's title say what refuses the key now.
Claude-Session: https://claude.ai/code/session_01H37vtTJRVBf1LkyYNW5yfo
Co-authored-by: Claude <noreply@anthropic.com>
…ys on their own; the kits' readers follow the one-major rule The contract review of 93505c9 found the readers of the removed 16.x kits that the removal had not been shipped with: the spec package's own repo tests, the console's derived twins and their pins, and a react test pin on the ActionDef mirror. Spec repo tests (`test:repo`, Test Core 1/8): - Three surviving-kit tests asserted a major-17 ledger row this change deletes (`integration/ConnectorFieldMapping:transform`, `ui/PageHeaderProps:icon`); they now assert the one-major rule — the 17 table is gone and the row with it. - The check-mode leaf-collision fixtures lost their premise: the `data.query.distinct` clause left with the 16.x conversions and the `data/Index:type` tombstone with the 16.x tombstones. Re-picked to `api/PackageInstallManifest:capabilities` against the registered `manifest.capabilities` (kernel/Manifest's row, inherited through `ManifestSchema.extend`) and `system/BookGroup:translations` against `manifest.contributes.translations`. - Five tree-scoped absence kits found the fixtures this change moved onto surviving 17.x keys (migrate-meta-write, migrations.test, view-union-retirement-prescription, lint-liveness-properties); each kit's EXCLUDED set names the file with its reason. Console twins (`@object-ui/types`): `AppComponentSchema` and `DashboardComponentSchema` derive from the spec shapes by reference over a `.passthrough()` base, so the ten tombstones that aged out of `AppSchema` / `DashboardSchema` (version, homePageId, objects, apis, sharing, embed, mobileNavigation, aria; aria, performance) stopped being refused and were kept in silence. A new `agedOutSpecKeyRefusal` helper (`zod/tombstone.zod.ts`) declares each as the console's own refusal: `invalid_type` at the key's path, opening with the spec's unknown-key sentence and the guide sentence (a copy pinned equal to the spec's export, since the mirrors' import boundary admits no spec string), then where the value went. The TS twins carry `?: never`; the parity, twins-by-reference and dashboard-aria pins assert the refusal on both faces with the spec's unknown-key verdict as the control. The strict `DashboardWidgetSchema` needs no arm: its five aged-out keys meet the `.strict()` door, and the report-chart pins now read zod's `unrecognized_keys` there with the spec's guide-naming refusal as the contract leg. driver-sql: the storage/presentation classification of FieldSchema keys drops its `conditionalRequired` row (the test beside it refuses a classification the spec no longer declares). Console pins: the layout conversion-coverage row for `page:card → properties.body[]` is gone with the conversion; the react useActionEngine fixture keeps its stale `shortcut` on an entry of its own (an object literal with a mistyped member is not also checked for excess members, so the directive reported unused once `shortcut` left the mirror). The SDUI manifest is re-recorded for the moved source digests. Claude-Session: https://claude.ai/code/session_01H37vtTJRVBf1LkyYNW5yfo Co-authored-by: Claude <noreply@anthropic.com>
Brings in the 29 commits main gained since the previous merge, among them the re-pointed ObjectSchema corpus guards (#26231) this branch's console pins were waiting on. One text conflict: the sdui core source record (scripts/sdui-manifest.sources/core.json), re-recorded on both sides, is taken from main and then re-recorded from the merged tree by the manifest generator. Generator-owned artifacts are regenerated from the merged tree with the spec generators, not by hand. Claude-Session: https://claude.ai/code/session_01H37vtTJRVBf1LkyYNW5yfo Co-authored-by: Claude <noreply@anthropic.com>
…sentence; the guidance floor follows the one-major rule CI on 6d80aba stopped twice on readers of the removed kits. Type Check UI stopped at `check:spec-symbols` (before tsc): the console's own refusal of an aged-out spec key (`agedOutSpecKeyRefusal`, zod/tombstone.zod.ts) carried a hand-written const under the spec's own export name, `RETIRED_KEY_UPGRADE_GUIDE_SENTENCE`, and the gate refuses a declaration that shadows a spec export (a reader takes it for the spec's definition) and the alignment claim its docblock made. The sentence is now imported from `@objectstack/spec/shared`. The mirrors' import boundary (imported-defaults-8317) gains the fourth declared kind of read it enumerates — a spec TEXT, held name → binding with its own assertion that each entry is a non-empty string the mirrors read raw and not a schema — beside vocabularies, type positions and refinements; a string has no Zod graph and no default, so it cannot write a value into a parsed document, which is all the boundary polices. The parity test keeps asserting the refusal carries the spec's sentence; its comment no longer describes a copy. The SDUI manifest's types record is re-recorded for the moved source digest. Test Core 4/8 and 6/8 (packages/cli): migrate-meta-engine-guidance pins an anti-vacuity floor of the entries whose guidance was rewritten, 244 ids, and asserts the chain's family still holds each. 75 of them are major-17 entries this change retired one major on, so the family lost each by name. The floor is the rewritten entries the registry still holds — the 75 rows leave with their guidance, 169 remain — and the file says the rule: an entry retired one major on leaves both the chain and this list. Claude-Session: https://claude.ai/code/session_01H37vtTJRVBf1LkyYNW5yfo Co-authored-by: Claude <noreply@anthropic.com>
Brings in the 28 commits main gained since the previous merge. Three text conflicts: the sdui core and types source records (scripts/sdui-manifest.sources/), re-recorded on both sides, are taken from main and then re-recorded from the merged tree by the manifest generator; the types test object-view-unmirrored-keys-7779 takes main's membership assertions (#26238) with this branch's aged-out legs kept beside them. The six generator-owned artifacts the merge driver deferred (the data authorable surface and five reference pages) are regenerated from the merged tree with the spec generators, not by hand. Claude-Session: https://claude.ai/code/session_01H37vtTJRVBf1LkyYNW5yfo Co-authored-by: Claude <noreply@anthropic.com>
…s `username` Test Core's cli slice 2/4 (the 4/8 shard; 3/8 at the previous head) failed audit-mail-bodies.archive case 7: the fixture's declared postgres archive carried `user`, the pre-17 spelling of `username`, which the `user` → `username` conversion rewrote at artifact load until that kit aged out of the chain one major on (ADR-0087). The strict config door now refuses the key by name — the command exits 1 with the refusal as its whole JSON and no `archive` entry, which is not the case the test pins (a declared archive this boot cannot CONNECT, reported `not-connected` and `failed-degraded`). The fixture spells the live key; the case's reading is unchanged and the file is green alone. Claude-Session: https://claude.ai/code/session_01H37vtTJRVBf1LkyYNW5yfo Co-authored-by: Claude <noreply@anthropic.com>
Brings in the 28 commits main gained since the previous merge (the PR had gone un-mergeable against main before CI could start on 1331519). Two text conflicts: the sdui core source record is taken from main and re-recorded from the merged tree by the manifest generator; the visibility-alias-keys absence kit keeps both EXCLUDED entries — this branch's view-union prescription pin and #25712's sdui-parser base-props pin. The one generator-owned artifact the merge driver deferred (the automation-api reference page) is regenerated from the merged tree with the spec generators, not by hand. Claude-Session: https://claude.ai/code/session_01H37vtTJRVBf1LkyYNW5yfo Co-authored-by: Claude <noreply@anthropic.com>
…the spec keys that aged out at 18.2 The re-review of 2718c3c found the console's `ListViewSchema` twin built like the App and Dashboard twins this PR already fixed: `BaseSchema` (`.passthrough()`) plus the spec list view's members by reference. The five list view tombstones that aged out of the spec at 18.2 (`striped`, `bordered`, `virtualScroll`, `responsive`, `performance`) left the projection with no refusal of their own, so an authored `striped: true` parsed green and was kept. Each is now an `agedOutSpecKeyRefusal` arm on the twin. The TS face is derived from the twin (`ListViewInferred`), so each key is `?: undefined` there with no hand-kept member; the page `list-view` node's `properties` bag reads the twin's shape and refuses the five too, and its flat spelling gets the row's own retirement. A parse census of the other removed component tombstones found three more flat spellings kept in silence on public-block arms: `page:header` `icon`, `page:card` `actions` and `record:details` `layout`. `flatPropRefusals` reads the spec row's key set, and the row no longer carries the name, so `BaseSchema` kept a flat value. Each arm now declares the console's own refusal; the bag spelling was already refused by the strict row. Pins: list-view-aged-out-spec-keys-25767 (twin, bag, flat, TS face) and public-block-aged-out-spec-keys-25767 (flat, bag), each with the spec's own unknown-key verdict as the control. Claude-Session: https://claude.ai/code/session_018wdyGVjfpxCUwq2UMrZkwi Co-authored-by: Claude <noreply@anthropic.com>
… as their own category `list-view-spec-parity`'s rogue-key check read the five new `agedOutSpecKeyRefusal` arms as objectui-only fields. They are neither a sanctioned local extension nor a spec member: a fifth category, `AGED_OUT_SPEC_REFUSALS`, checked like `HANDLER_KEY_REFUSALS` — each member must be declared on the arm, refuse every value, and be undeclared by the spec, so the set cannot park a live field. Claude-Session: https://claude.ai/code/session_018wdyGVjfpxCUwq2UMrZkwi Co-authored-by: Claude <noreply@anthropic.com>
…rge of main `node scripts/gen-sdui-manifest-node.mjs` over the merged tree: the manifest itself is unchanged (sha256 1f6e1ccb925a…, 106 components); the core and types records move with main's sources and this round's ui/packages/types edits. Claude-Session: https://claude.ai/code/session_018wdyGVjfpxCUwq2UMrZkwi Co-authored-by: Claude <noreply@anthropic.com>
…w keys again `ObjectView.relayRungCensus-7559` reads every `ListViewSchema` member and asks for a relay rung or a declared absence. The five list view keys whose spec tombstones aged out at 18.2 had left that shape, so their `unread` rows were dropped; the twin now declares each as its own refusal (`agedOutSpecKeyRefusal`), which makes them members again. They return as `unread`, each reason naming the age-out and the refusal: an authored value never parses, so there is nothing for a rung to relay. CI's Test UI (15/16) on 045298a was red on exactly this. Claude-Session: https://claude.ai/code/session_018wdyGVjfpxCUwq2UMrZkwi Co-authored-by: Claude <noreply@anthropic.com>
# Conflicts: # scripts/sdui-manifest.sources/core.json # scripts/sdui-manifest.sources/types.json
…ide; the branch's aged-out data.json lines stay deleted Main moved packages/spec/authorable-surface/data.json (Seed files rows) and two reference pages; the merge took main's side and these are the regenerated results. Field:conditionalRequired, Index:partial and Index:type stay deleted: they aged out on this branch (objectstack#25767). Claude-Session: https://claude.ai/code/session_018wdyGVjfpxCUwq2UMrZkwi Co-authored-by: Claude <noreply@anthropic.com>
# Conflicts: # docs/adr/0087-metadata-protocol-upgrade-contract.md
…ide; the branch's aged-out RetryPolicy.retryDelayMs line stays deleted Claude-Session: https://claude.ai/code/session_018wdyGVjfpxCUwq2UMrZkwi Co-authored-by: Claude <noreply@anthropic.com>
…etirement kits age out (#25767 ruling 6434038284) The maintainer's 2026-10-27 ruling keeps kit aging (tombstones and their D2 conversions retired at or below 16.x leave; the strict refusal names the upgrade guide) and withdraws the chain cut. Restored to origin/main: the migration entries (159 major-17 files and the conversionIds links in the three protocol-18 entries), registry.ts.template with MIGRATION_SUPPORT_FLOOR = 16, chain.ts, migrations.test.ts, semantic-relevance.test.ts, the cli migrate meta command and its twelve tests, ADR-0142, and the floor prose in the upgrade guide and the upgrading page. The retirement sentences follow the conversion, not the floor: an edit whose toMajor-17 conversion survives (the twelve retiredAfter 17.7.0 ones) goes back to the house 'Run os migrate meta --from 16' sentence; an edit whose 16.x conversion left says it left with the 16.x conversions and links the guide. ADR-0087's kit-aging amendments are reworded (the kit ages out, the step stays) and its chain amendments are withdrawn; the changeset is rewritten. The release-tag dating source in build-schemas.ts stays: 46 of the 61 deleted [RETIRED] lines predate RETIRED_KEYS_BY_MAJOR, so the registry alone cannot date them. Claude-Session: https://claude.ai/code/session_018wdyGVjfpxCUwq2UMrZkwi Co-authored-by: Claude <noreply@anthropic.com>
…ent sentences Claude-Session: https://claude.ai/code/session_018wdyGVjfpxCUwq2UMrZkwi Co-authored-by: Claude <noreply@anthropic.com>
…re-point the pins that replayed them Restoring registry.ts.template to main brought back step 17's graduated conversionIds list, which named the 45 conversions retired at 16.1.0 that left the registry with their kits; the chain's integrity pins refused the dangling ids. Those ids leave the list (the step and its semantic entries stay, the floor stays 16). The replay pin in migrations.test.ts, the cli cross-hop pin, the --from 16 protocol-range shape and the --write fixture now replay conversions step 17 still graduates (sharing-rule full to edit, the CRUD flow-node object alias) or protocol-18 ones. The three repo-project pins on RETIRED_KEYS_BY_MAJOR[17] go back to main with the restored rows. ADR-0087's addendum and the changeset say the step-17 list lost those ids. Claude-Session: https://claude.ai/code/session_018wdyGVjfpxCUwq2UMrZkwi Co-authored-by: Claude <noreply@anthropic.com>
…ide; the branch's five aged-out api.json lines stay deleted Claude-Session: https://claude.ai/code/session_018wdyGVjfpxCUwq2UMrZkwi Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 4 package(s): 106 hand-written doc(s) name something this change touched — list omitted above 15 rows. Re-derive on the tree named below: ⛔ 18 release-owned page(s) also affected — read-only, see AGENTS.md Documentation Guardrails. What this run could not see
Coarse fallback — 149 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 839b466eb9f1dc2402b888d6ba21c4593c34f619 && git checkout 839b466eb9f1dc2402b888d6ba21c4593c34f619
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 7c34e5dc211fd54f86db04a650916950301ddfd8 a0e848fb6e69a29cbe48b2820b2c7a9ffd3d3bb4 && git checkout -B drift-repro 7c34e5dc211fd54f86db04a650916950301ddfd8 && git merge --no-ff a0e848fb6e69a29cbe48b2820b2c7a9ffd3d3bb4
node scripts/docs-audit/affected-docs.mjs --json 7c34e5dc211fd54f86db04a650916950301ddfd8
|
…s `username` again The rework restored this file to main and lost #26138's c61ede6. Test Core 4/8 failed audit-mail-bodies.archive case 7 at cd60de5: the fixture's postgres archive carried `user`, the pre-17 spelling of `username`. The `datasource-config-driver-key-aliases` conversion that rewrote it at artifact load aged out with its kit, so the strict config door refuses the key and the command never reaches the not-connected archive the case pins. The fixture spells the live key. A census of packages/cli for the other spellings that conversion and the removed datasource conversions carried (sqlite file/database, postgres and mysql connectionString, mongo uri, inert blocks, capabilities, readReplicas, connector rateLimit) finds no other datasource declaration that uses one. Claude-Session: https://claude.ai/code/session_018wdyGVjfpxCUwq2UMrZkwi Co-authored-by: Claude <noreply@anthropic.com>
⛔ merge queue 构建失败 — 先分诊,再决定要不要重排队列构建 40493270857 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集), 分类: 失败的 job(日志抽取,best effort):
跨 PR 相同签名(24h,按失败测试文件聚合):
历史信号:
分诊清单:
Generated by Claude Code · merge-queue-triage workflow (#4859) |
#26599 retired the conditionalRequired row, so the shipped field ledger's warned set is externalId alone; the lint pin and the regenerated field count shard say so. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibvE77Ed7MKdzPxJTQQ
Conflicts were counts only, resolved on main's side plus this branch's additions: the type-alias isomorphic pins (792 on main, 796 here) and the dropped-refinements baseline totals (248 / 869 on main, 251 / 887 here). The authorable-surface baselines keep main's retirements (#26599) and this branch's Queue and AssignmentRule keys. Generated references regenerated from the merged tree. Claude-Session: https://claude.ai/code/session_01GTntg542RUmmRRbMY6wMZD Co-authored-by: Claude <noreply@anthropic.com>
…26599 aged out (#27015) `ui/PageCardProps:body` left the live authorable surface in #26599 and stayed authorable in the self-test only through the stale anchor. With the anchor re-anchored, the case named a key neither side carries. The specimen is now `ui/Dashboard:refreshInterval`, a 18.x tombstone that is on the live ratchet until major 20. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QUs3Bshfmr8srPY21BVS4u
Fixes #25767
Supersedes #26138
Clause-②: no (narrowing)
Metadata-protocol: narrowed
Skills-docs: follow-up #26303
Release: 18.3
维护者速读(草稿)
[RETIRED])从代码里删掉。被删的键由 strict schema 当未知键拒绝,错误里多一句话,指向协议升级指南。迁移链不动:支持底线仍是 16,第 17 步和它的 159 个条目文件都在,os migrate meta --from 16照常从 16 重放到 18。sys_metadata里仍是这种形状的行,读取时不再被改写,要在 18.2 或更早版本上用os migrate meta --stored --apply规范化一次(裁决把这条一次性提示放进 18.2 的 release notes)。③ 第 17 步的 graduated 列表少了 45 个已删 conversion 的 id,所以--from 16不再替你改这 45 类写法;步本身和它的语义条目都还在。回滚就是 revert 本 PR,不写数据,没有不可逆动作。packages/spec/src/migrations/registry.ts.template第 17 步的conversionIds(删掉 45 个 id 的那一段);②docs/adr/0087-metadata-protocol-upgrade-contract.md末尾的 2026-10-26 addendum 和 D2 窗口那条修订;③packages/spec/scripts/build-schemas.ts的 proof 1(一个 major 的时钟和 release-tag 定日期)。cd packages/spec && pnpm exec vitest run src/migrations/ src/shared/retired-key-migrate-sentence.test.ts,预期全部通过:链的完整性钉子(每个 id 都是真 conversion)、从底线 16 的重放,以及新旧两种处方句式。GOVERNED_APPROVERS身份批准本 PR(Tier H:docs/adr/**原地修订)。What changes
Maintainer ruling 6434038284 on #25767 (2026-10-27, 「同意」) scopes the D2 = A ruling of 2026-10-25. It keeps kit aging and withdraws the chain cut, and the release target is 18.3. This PR is #26138's branch reworked to that scope. #26138 is closed as superseded (6434144688).
Kept from #26138 (the kit ages out):
retiredAfterat or below 16.x (5 at 15.0.0, 45 at 16.1.0) are removed, with their fixtures.[RETIRED]at@objectstack/spec@17.0.0are removed, along with 61[RETIRED]lines of the authorable surface and their liveness rows.RETIRED_KEY_UPGRADE_GUIDE_SENTENCE(shared/protocol-upgrade-guide.ts) after its fix channels, keeping the strictObject 的 history 句夹在「哪个键错了」与「该写什么」之间,在单行 error 显示位上把修法推到 222 字符之后(#5762 实测) #5955 order.RETIRED_KEYS_BY_MAJORrow or by the previous major's release tag.ui/packages/typescover the keys it used to inherit as tombstones: the five ListView keys and the three flat public-block spellings.ui/**test follow-ups are kept.Restored to
origin/main(the step stays):packages/spec/src/migrations/entries/**, including the 159 major-17 files, the README and theconversionIdslinks of the three protocol-18 entries.registry.ts.templatewithMIGRATION_SUPPORT_FLOOR = 16,chain.ts,migrations.test.tsandsemantic-relevance.test.ts.packages/cli/src/commands/migrate/meta.tsand its twelve tests, anddocs/adr/0142.docs/protocol-upgrade-guide.mdandcontent/docs/upgrading.mdx. The guide pointer gains one sentence saying where an aged-out kit's prescription lives.Reworded:
minorfor spec,patchfor lint and metadata-core. The cli is no longer touched in published code.toMajor: 17,retiredAfter: 17.7.0ones: the flow-node aliases and lifts, the mongo alias, the retry default, the sharing-rulefull→editrewrite, the header subtitle alias and the inline action params) goes back to main's "Runos migrate meta --from 16…" sentence.os migrate metawith the protocol-16.x conversions: apply it by hand, or run the tool on a release that still carries the conversion", followed by the guide link.Acceptance notes
conversionIdslist inregistry.ts.template, however, named the 45 conversions retired at 16.1.0, so restoring it verbatim failed the chain's integrity pin ("every step references only real conversion ids").--from 16still replays 16 → 18, but it no longer applies those 45 edits. Each one's tombstone or guide entry names the hand edit.migrations.test.tsnow usessharing-rule-access-level-full-to-editandflow-node-crud-object-alias.meta.report-order.test.tsnow uses the sharing-rule conversion.--from 16shape inmigrate-meta-protocol-range.test.tsis now a sharing rule.migrate-meta-write.test.tstakes feat(spec,cli)!: retire the ≤16.x retirement kits; the strict unknown-key refusal names the protocol upgrade guide #26138's protocol-18 fixtures at--from 16. Its aged-outcompareTocontrol now says the conversion left, not the floor.RETIRED_KEYS_BY_MAJOR[17]go back to main.[RETIRED]lines predateRETIRED_KEYS_BY_MAJOR, and no row names them. The tag source and its fourSKILL.mdlines stay, at net zero lines (337 → 337).sys_metadatarow carrying a spelling whose conversion aged out is no longer rewritten at read. Canonicalize it with--stored --applyon 18.2 or earlier.app-hidden-to-unpublishedis among the removed conversions, so the artifact door's refusal of it by id is removed as moot. The 18.2 release-notes notice is the ruling's part 3 and is not in this diff:content/docs/releases/is release-owned.pendingDataMigrationsis moot again while the chain still crosses into 17.Verification
All readings are at head
393c768582, which carries a merge oforigin/mainatadd806c5a6.Suites (local, under the verify lock)
pnpm --filter @objectstack/spec test: 728 files and 21889 tests passed, 1 todo.pnpm --filter @objectstack/spec test:repo: 80 files and 1295 tests passed.pnpm --filter @objectstack/cli exec vitest run --project unit: 337 files and 4904 tests passed. The integration tier is declared to CI.76dad1ceeb. lint (7389 passed) and metadata-core (823 passed) ran at002710c1dc. The later commits touch none of their files.pnpm --filter @object-ui/types test: 393 files and 10696 tests passed.cd ui && pnpm exec vitest run scripts/: 177 files passed and 1 failed. The failure ischeck-i18n-dead-keys"keeps every key it makes reachable OUT of both tiers", a 15 s timeout on the real-tree scan under full-suite load, the same on three runs. It passes when its file runs alone (check-i18n-dead-keyspluscheck-vi-mock-inherit: 217 tests passed), and the diff touches no i18n source.pnpm --filter @objectstack/dogfood test, the full battery at the final head: 300 files passed, 3 skipped. 2494 tests passed, 18 skipped. Lock verdictcommand-exit 0.Generated artifacts and gates
pnpm --filter @objectstack/spec check:generated: all 14 artifacts current.node scripts/check-regen-pending.mjs: exit 0.node scripts/gen-sdui-manifest-node.mjsthencheck-sdui-manifest:sdui.manifest.jsonbyte-identical (sha2561f6e1ccb925a…, 106 components).uicheck:spec-symbols: exit 0.dispatch-gates.mjs --commands): 150 derived, 150 run, 0 NOT-MEASURED. 149 exit 0, and 1 exit 1, which ispnpm --dir ui exec vitest run scripts/with the timeout named above. Reconciled with--ran.origin/mainwent throughscripts/pm/os-regen-merge.sh. Each time the driver took main's side of a generated surface, the branch's own aged-out[RETIRED]lines were deleted again beforegen:schema: three indata.json, one insystem.jsonand five inapi.json.Generated by Claude Code