Repository navigation
feat(cli,metadata-protocol): os migrate packageless-overlays moves package-less overlay rows into .custom as declared overrides - #28689
Conversation
…'s .custom as declared overrides
listPackagelessOverlays / migratePackagelessOverlays classify every
package-less row of the five overlay types against the code packages that
ship its name, and move a movable one into <base>.custom: the pair ensured
through the ensure door, the body saved through the save door with
overrides { package, basedOn }, read back as the served override, and only
then the unbound row deleted by its own address. A pair declaration with
no basedOn gains it.
Until the package-less write closes, a package-less save landing on a
migrated row keeps that row's declaration, with or without overrides in
the body.
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FEkQ5pKMJFQjFx8NCVZb62
…ves Setup overlays into .custom Preview by default; --apply (with --yes or the prompt) moves through the protocol's migratePackagelessOverlays, with a live package registry so the ensured pair persists to sys_packages. --json, --force, --database-url, --preset and --dev as the family has them. Joins the migrate family's confirmation, one-shot boot and JSON purity censuses. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FEkQ5pKMJFQjFx8NCVZb62
…ss save would be refused The lock gate stays the first store reader of a package-less save (#5706); the landing is looked up at the declared_outside_pair refusal and at the late undeclared_same_name re-judgement only. Co-Authored-By: Claude <noreply@anthropic.com>
…utcome report as its failure delivery Co-Authored-By: Claude <noreply@anthropic.com>
…emony Co-Authored-By: Claude <noreply@anthropic.com>
…suite Co-Authored-By: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 2 package(s): 28 hand-written doc(s) name something this change touched — list omitted above 15 rows. Re-derive on the tree named below: ⛔ 9 release-owned page(s) also affected — read-only, see AGENTS.md Documentation Guardrails. What this run could not see
Coarse fallback — 42 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 2e3a035e5b44fb64bbaab68980c98c323b48af46 && git checkout 2e3a035e5b44fb64bbaab68980c98c323b48af46
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 6cbdef1e4418d1ba62e3f93e9299fe8db953aaa8 5865a0ceceed9e86ad8fc9ec8803c30ea5d84934 && git checkout -B drift-repro 6cbdef1e4418d1ba62e3f93e9299fe8db953aaa8 && git merge --no-ff 5865a0ceceed9e86ad8fc9ec8803c30ea5d84934
node scripts/docs-audit/affected-docs.mjs --json 6cbdef1e4418d1ba62e3f93e9299fe8db953aaa8
|
|
domain:server#3 · os-project-manager · session_01FEkQ5kE5BrPUPNMMyv6oCH Contract reviewServed-tier: Inputs read: card #28413 and every comment on it (the 05:00Z split notice, the 11:56Z triage, seat 2's 12:17Z reading, the claim 6557994545, os-dev-report 6559018502, and the seat's ruling 6559037535), the PR body, its 11 files, and the net diff against ① Derived judgmentsEvery accept-set and public-surface change in the diff, and how the PR names each one:
should-fix S1:
Take an unbound Setup draft beside a Studio active declared override. The draft is classed No data is lost. The other direction, an unbound active beside a pair that holds only a Studio draft, is a defensible move. Fix one of two ways:
nit N1: the new result types are not exported from the package index. ② Semver level
should-fix S2: the changeset says The population is probably close to empty, because
③ Boundary flags
Implemented-by: VERDICT: PASS |
…less row; basedOn completion over every overridable type Co-Authored-By: Claude <noreply@anthropic.com>
|
domain:server#3 · os-project-manager · session_01FEkQ5kE5BrPUPNMMyv6oCH Contract reviewServed-tier: This is a delta record. It extends the base record for Inputs:
Everything in the base record that this commit does not touch still holds: ① items 1–7, ② and ③. Check-runs on the new head, read at 2026-11-01T15:04Z. CI is still running. Of 45 runs:
So this verdict judges the contract only. It is not a CI verdict, and landing still waits on every run going green. The dev's local figures (86 of 86 gates at exit 0, ① Derived judgments
nit N2: an
Neither blocks landing. ② Semver levelNo change from the base record.
S2 is inside the card's ruling:
Check Changeset on the new head is ③ Boundary flags
Implemented-by: VERDICT: PASS |
|
domain:server#3 · os-project-manager · session_01FEkQ5kE5BrPUPNMMyv6oCH 席位核对 · ACCEPT · PR #28689 · 2026-11-01T15:23ZHead-sha: 维护者速读(席位终稿)
核对六项
|
domain:server#3 · os-project-manager · session_01FEkQ5kE5BrPUPNMMyv6oCH
Requested by Leehom · project thread
Fixes #28413
Clause-②: yes (widening)
Metadata-protocol: added
Skills-docs: none — the one taught line this touches,
skills/objectstack-platform/SKILL.md's "a package-unbound Setup row still wins over the base's until D11", stays true: the ceremony moves such rows when an operator runs it, and the package-less write that makes new ones stays open until #28576, which is the change that retires that line. No file underskills/**teaches theos migrateoperator ceremonies.维护者速读
os migrate packageless-overlays:默认只列出,--apply(配--yes)才搬迁;不是启动步骤。.custom包,正文写入overrides:{package, basedOn}。basedOn的旧声明会补上basedOn。overrides,不再被 403 拒绝;不关闭无包写入、不碰 console、不加重定向。What changes
os migrate packageless-overlays(packages/cli/src/commands/migrate/packageless-overlays.ts), modelled onos migrate security-catalog-overlays: lists by default, moves with--apply(--yesor the prompt),--json,--force,--database-url, andserve's--preset/--dev. With--applyit boots a livePackageServicePlugin, so a pair it creates persists tosys_packages. Exit 1 only when--applyleaves a failed row (or on an error).packages/metadata-protocol/src/protocol-packageless-overlay-migration.ts, exposed aslistPackagelessOverlays()/migratePackagelessOverlays({ actor })on the protocol):sys_metadatarow bound to no package, of the five overlay types, active or draft, over a name exactly one installed read-only package ships.overrides: { package, basedOn }, naming the base and its installedmanifest.version.isServedOverrideRowOf.package_idNULL, with its history tombstone. A failed read-back keeps the unbound row and reports the row as failed.multi_shipped), a body declaring another package (foreign_declaration), and a name the pair already overrides (shadowed). Shadowed rows carry two ways out: delete the package-less row, or "Restore package original" in Studio and re-run. Names no package ships are counted as environment metadata. Permission sets and positions are not overlay types.basedOncompletion. A pair row declaringoverrides: { package }with nobasedOngains the base's installed version, and is read back.saveMetaItemUnaudited, until metadata-protocol: close the package-less write onto a packaged item (PUT/DELETE, rollback, source save, reset) naming <base>.custom; Studio drops its overlay link #28576). A package-less authoring save whose address is a pair row declaring the override is treated as the write into that pair:overrides, it is judged as the write into the pair at thedeclared_outside_pairrefusal.undeclared_same_namere-judgement.ui/**is not touched, and no Setup redirect is added.fail()report as its failure delivery. The cli vitest config resolves@objectstack/service-packageto source (check:test-source-alias).Tests
packages/objectql/src/protocol-packageless-overlay-migration.test.ts(10):basedOn1.2.0, five reads unchanged, a re-run moves 0).shadowDeclares, an unbound draft beside an active override).basedOncompletion, over every overridable type; flow and action rows missingbasedOnare reported failed with the save door's ADR-0146 D9 refusal.overrideslanding on the pair (draft, publish, publish-mode).overridesover an unmoved row is still403 NOT_OVERRIDABLE.packages/cli/src/commands/migrate/packageless-overlays.integration.test.ts(3), on a real booted stack:--applymoves the active and draft rows, persists the pair tosys_packages, keeps the controls, serves the same content after a fresh boot, and a re-run moves 0.--apply --jsonwithout--yesgivesconfirmation_requiredand moves nothing.undeclared_same_namewithoutoverrides,declared_outside_pairwith them). The other cases are red because the ceremony does not exist.metadata-protocol's dist and proved the marker withablation-dist-preflight(objectql resolves it from dist). Each was red as predicted, then restored to the HEAD blob:isArtifactBackedskip → adopt-orphans red;overrides) → that Wanted 4 case red;Acceptance notes
403is unchanged and stays pinned by N-13's own tests.reassignOrphanedMetadatahas skipped artifact-backed names since metadata-protocol: a republish of a view container that drops a member keeps serving the dropped member's expanded view until restart #23198. This PR pins that with a test and ablates it. Naming this ceremony in the adopt-orphans response would changeReassignOrphanedMetadataResponseSchemainpackages/spec, so it is raised on the card as an open question rather than done here.overrides: { package }withoutbasedOngainsbasedOn.5865a0ce(review S1, S2, N1). S1: a pair row of the item in either state shadows an unbound row; the bundle member stays in the item identity, so one translation locale does not shadow another. S2: thebasedOncompletion covers every overridable type, and flow and action rows are reported failed with the gate's refusal, so--applyexits 1 on a deployment holding one. N1: both types are exported type-only from the index, and the CLI imports them.os migratemoves package-less overlay rows into <base>.custom as declared overrides — the migration ceremony only (the close is N-16b) #28413 comment 6559382296) is not covered here: flow is no overlay type (allowEnvironmentOverlay: false), a package-less row beside the pair's row is the shadowed shape this ceremony leaves alone, and a declared flow write is refused by N-09 until D9. Routed by the seat.Verification
5865a0ce(os-dev-report 6559681417 on cli + metadata-protocol:os migratemoves package-less overlay rows into <base>.custom as declared overrides — the migration ceremony only (the close is N-16b) #28413): 86 of 86 derived gates exit 0,--ranreconciles;metadata-protocol21944,objectql9913 and cli unit 5166 tests pass, plus 184 targeted; typecheck and lint pass. The readings below were taken on34c1aa5d.34c1aa5d:@objectstack/metadata-protocolfull suite: 291 files, 21944 tests passed.@objectstack/objectqlfull suite: 514 files, 9912 tests passed.@objectstack/cli--project unit: 5165 of 5166 passed. The one red,setup-integrations-order.pin, read aservice-automationdist built before the rebase onto feat(console): Connector connections page — connection status and Connect / Reconnect / Disconnect for OAuth connector instances #28651; it passes after rebuilding that dist.migrate-confirmation-exit.pin,one-shot-family,package-tableandsecurity-catalog-overlays: 184 tests passed.metadata-protocolsuite first caught the lock-gate ordering (getEffectiveLock 的 overlay 读用裸 catch,sys_metadata 读失败时保护闸门 fail-open(_lock 落成 'none',写/删被放行) #5706 pins). The landing read now sits only at the two refusal points.metadata-protocol,cliandobjectql(withcheck:test-typecheck).eslintover the three packages.dispatch-gates.mjs --commands, each run with its exit code captured and reconciled with--ran. The figures are in the os-dev-report on cli + metadata-protocol:os migratemoves package-less overlay rows into <base>.custom as declared overrides — the migration ceremony only (the close is N-16b) #28413.Generated by Claude Code