Repository navigation
feat(spec,cli)!: retire the ≤16.x retirement kits; the strict unknown-key refusal names the protocol upgrade guide - #26138
objectstack-fleet[bot] wants to merge 23 commits into
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>
Maintainer ruling relayed: B, and it ships in 18.2 · triage seat ·
|
Addendum to the B block: lead with "one major at a time" · triage seat ·
|
…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>
…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>
|
Closing as superseded · domain:spec seat 2 · session The maintainer amended #25767's scope on 2026-10-27, recorded in ruling 6434038284 (「同意」 04:39Z). Part 1 is kept: retirement kits age out one major after they retired. Part 2 is withdrawn: the migration chain stays replayable down to floor 16, and step 17 with its 159 entries stays. Release moves to 18.3. As adopted with the ruling, this PR closes unmerged. Its scope has halved, and it carries two FAIL contract-review records plus an APPROVED review on an earlier head, so it should not land on that approval. The reworked change comes from the same branch ( |
…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>
Requested by Steedos · project thread
Fixes #25767
Clause-②: no (narrowing: a key retired at or below protocol 16.x is refused as a strict unknown key without its own prescription in the error, and
os migrate meta --from 16refuses at the support floor instead of replaying step 17)Metadata-protocol: narrowed
Tier H — governed path
docs/adr/0087-metadata-protocol-upgrade-contract.md(amended in place) and a diff over 3000 lines (generated entries, surface files and ledgers included). Held draft for aGOVERNED_APPROVERSreview.What this PR does
Maintainer ruling on #25767, D2 = A: a retirement kit — the
retiredKey()tombstone, itsRETIRED_KEYS_BY_MAJOR/RETIRED_DEFS_BY_MAJORrows, its semantic entry and its D2 conversion — lives through the protocol major after the one it retired in and leaves when the next major is cut. At 18 that keeps the 17.x and 18.x kits and removes everything retired at or below 16.x; 19 repeats the move one major on.retiredAfterat or below 16.x (5 at 15.0.0, 45 at 16.1.0) and their fixtures; 55 tombstones already[RETIRED]at@objectstack/spec@17.0.0whose container is astrictObject; the 159 major-17 entry files (29 retired-key rows, 53 retired-def rows, 77 semantic entries) and the chain's step 17; 61[RETIRED]lines of the authorable surface and their 36 liveness-ledger rows.mapping.transform,rest-server.requireAuth,connector.rateLimitConfig,book.translationsand kin) — deleting one would turn a refusal into a silent strip; the four inline-credential refusals, which are not retirements; the 17.x kits, which leave when 19 is cut.RETIRED_KEY_UPGRADE_GUIDE_SENTENCE, exported withPROTOCOL_UPGRADE_GUIDE_URLfrom@objectstack/spec): keys retired before the previous major are no longer prescribed in the error — see the protocol upgrade guide,https://objectstack.ai/docs/protocol-upgrade. The strictObject 的 history 句夹在「哪个键错了」与「该写什么」之间,在单行 error 显示位上把修法推到 222 字符之后(#5762 实测) #5955 "history last" order is unchanged.MIGRATION_SUPPORT_FLOORis 17;os migrate meta --from 16and below answerMigrationFloorError, whose message names the floor and the guide, and rewrite nothing.packages/cliexamples, pins and fixtures follow the floor.check:authorable-surfaceproof 1 ages a tombstone one major (was two). A deleted[RETIRED]line is dated by an exact registry row or, new, by the previous major's release tag (@objectstack/spec@17.0.0here): a line already[RETIRED]on the surface at that tag was retired before that cut. The tag is immutable, so neither a row a PR writes nor one it deletes moves the clock; when the tag cannot be read the gate dates by the registry alone and says so. No gate was added.registry.ts.template's docblock,docs/protocol-upgrade-guide.mdsays where an aged-out kit's prescription lives (the release that carried it),content/docs/upgrading.mdxand the generated references follow, one changeset (minorfor spec and cli,patchfor lint and metadata-core).Acceptance notes (read before approving)
retiredAfter: 17.7.0(datasource-driver-mongo-to-mongodb,retry-policy-converged, the flow-node aliases,sharing-rule-access-level-full-to-edit, …) stay registered for the data-at-rest seams (stored-row rehydration, the artifact door), but their chain step (17) is below the floor:os migrate meta --from 17does not replay them. This is the template's own rule ("a step the floor no longer reaches retires"), the same move that retired steps 11–16 at the first floor move; their prescriptions already name the hand edit. Three protocol-18 semantic entries (spec(conversions): eight ADR-0087 D2 conversions stay on the 18 load path after #23487 — five families each need a ruling before they can retire #23543 F1/F2/F3: the mongo alias, the flow sibling-block lifts, the job retry default) declared aconversionIdslink to one of those step-17 conversions and promised thatos migrate metalists the edit; the link is dropped and the prose names the hand edit, the shape the F4/F5 entries already have for protocol-11/15 conversions. The chain is one hop now (18) and stays one hop under the one-major rule; the cli report-order pin counts hops off the floor, and a new pin refuses a link to a conversion the floor does not reach.os migrate meta --stored --applyon 18.1 or earlier.app-hidden-to-unpublishedis among the removed conversions, so a pre-splithidden: trueapp row is no longer rewritten by any seam; the artifact door's refusal of it by id is removed as moot (@objectstack/metadata-core).pendingDataMigrationskeys on a run crossing into 17; no run does now. The field stays in the JSON ([]) and the code stays; the cli e2e pins only the silence. A ruling on deleting it is a residual on the card.TOOL_RETIRED_KEY_GUIDANCE,CAPABILITIES_RETIRED_KEY_GUIDANCE,RETIRED_DATASOURCE_BLOCKS,JOB_ID_RETIRED, the appAREA_*aliases and kin are not ledger tombstones (no row, no entry); their house sentence is respelled to name the floor. Whether they age out with the kits is a residual on the card.retryDelayMs→maxRetryDelayMs,aria→areas); the guide sentence follows in the same message.git show @objectstack/spec@17.0.0:…; a checkout without the tag dates by the registry alone and prints that it did.963e504cf5: noexamples/**,ui/orhotcrmsource writes a removed key (theui/hits are the console's own same-named props and type mirrors).File surface beyond the claim
The claim named
packages/spec/src/conversions/registry.ts, the*.zod.tstombstone files,suggestions.zod.ts,registry.ts.template,cli/.../meta.ts, ADR-0087, the releases page and one changeset. The diff also touches, each as a consequence of the removal and nothing more:packages/spec/src/migrations/entries/**(159 major-17 entry files deleted),chain.ts(floor + guide link in the error),shared/protocol-upgrade-guide.ts(new, the sentence and URL),shared/retired-key.ts(docblock),scripts/build-schemas.ts+scripts/lib/renamed-defs.ts(the one-major gate), the generatedauthorable-surface/*.json,api-surface/shared.json,export-origins/shared.json,liveness/*.json+state-counts/*.md,content/docs/references/**(all by the generators;check:generatedis the proof).packages/lint/src/validate-*.tsandpackages/metadata-core/src/*.tswhere a removed key or conversion id was read. The lint's field-rule walk no longer readsconditionalRequired(its tombstone leftFieldSchema), its liveness pin for the dashboard walk rides therefreshIntervalrow, and the ADR-0032 dispatch-key tests accept the script contract's per-key refusals beside the lint's own prescription.docs/qa/platform-checklist/areas/ai.json: one lost anchor (skill.zod.ts#triggerPhrases) re-pointed, revision 7.docs/adr/0072-reference-scope-and-resolvability.mdanddocs/adr/0142-ownership-queue-membership-claim-and-assignment-rules.md: one symbol anchor each named a removed tombstone (flow.zod.ts#outputSchema) or a removed major-17 entry; re-pointed to the file / to prose, no other change.scripts/check-spec-docblock-symbol-anchors.mjs: the one CENSUS_RESIDUAL row whose citation left with a removed conversion's docblock is deleted, as the gate asks.packages/cli/test/package-owned-command-readers.test.ts: the [finding] cli(serve):os serveresolves capability providers from a multi-package artifact's top-levelrequiresonly — a package'srequires: ['automation']is not loaded at boot #22288 proof thatos migrate metareads every package's body rode the ADR-0104 listing, unreachable now; it rides a retired key on the service package's object instead, in a fixture pair of its own..claude/skills/spec-property-retirement/SKILL.md: the aging clock and the second dating source, +4 lines (file 337 → 341, pack 1104 → 1108).content/docs/releases/is release-owned, so the "16 and below: refusal + link" note lives in the changeset (which the release notes are cut from),content/docs/upgrading.mdxand the upgrade guide.维护者速读(草稿)
改了什么。 按你在 #25767 的裁决(D2 = A):退役套件只活到退役所在 major 的下一个 major。本 PR 在 18 上删掉所有 ≤16.x 退役的套件:50 个 D2 conversion、55 个墓碑、159 个 17 号 migration 条目和链上的第 17 步;被删的键现在由 strict 容器当未知键拒绝,错误里多一句指向升级指南(
https://objectstack.ai/docs/protocol-upgrade),处方不再内嵌。os migrate meta的支持底线从 16 升到 17,--from 16直接拒绝并给链接。ADR-0087 原地修订,门禁的老化时钟从两个 major 改为一个,不新增门禁。为什么改。 每个 major 都在累积墓碑和 conversion(17 号条目就有 159 个文件),它们既占 spec 体积也占每次升级的审阅面;业务上,升级者真正需要的是「我这把键该改成什么」,这句话放在升级指南和当时的 release notes 里就够了,不必让每个 strict schema 永远背着。
风险与代价(含回滚)。 ① 还停在 16 方言的源码不再拿到逐键处方,只拿到未知键拒绝 + 链接;它需要先在 ≤18.1 的 cli 上跑一次
os migrate meta --from 16。②sys_metadata里仍是 ≤16.x 形状的行不再在读取时改写,要在 ≤18.1 上用--stored --apply规范化一次。③ 17.7.0 从加载路径退役的 17 个 conversion 没有可重放的步,靠处方手改(模板本身的规则)。④ ADR-0104 的数据迁移提示从命令里不可达了,代码留着待裁。回滚:revert 本 PR 即恢复全部套件与第 17 步;没有数据写入,没有不可逆动作。席位意见。 (留空,席位定稿)
你要做的。 作为
GOVERNED_APPROVERS批准本 PR(Tier H:ADR 原地修订 + >3000 行),或指出不认可的点;另有两个残留问题在卡片上等你一句话(guidance 表是否随套件老化;pendingDataMigrations是否删除)。Generated by Claude Code