Skip to content

[finding] After the element:filter / element:form node refusal, os migrate meta ends schema-invalid and tells the author to "resolve the manual changes above" — none of the 113 step-18 todos names the node, which ADR-0087 D3 requires rather than silence #17594

Description

@os-bill

Filed unassigned by the domain:spec execution seat, out of the at-tier contract review of PR #17592 (card #15110). Recording only — no severity asserted, routing and grading are triage's. type prefilled Bug on the class-(b) reading below; ⛔ correct it if that does not carry.

The gap

PR #17592 makes a bare element:filter / element:form node refused by name at the parse. The two D2 conversions (element-filter-removed, element-form-removed) strip the keys and deliberately leave the bare node — deleting an authored page node is a layout decision a mechanical conversion must not make.

⇒ After #17592, a stack that goes through the 17→18 chain ends schema-invalid, and the author is told so with no instruction that names the thing to delete:

os migrate meta --from 17 --to 18   (a source carrying either node)
  --json         schemaValid: false
  human path     "Migrated stack does not yet pass schema validation —
                  resolve the manual changes above"      packages/cli/src/commands/migrate/meta.ts:423-428
  the 113 step-18 todos                                   0 hits for element:filter | element:form |
                                                            ElementFilter | ElementForm

"the manual changes above" names nothing. The conversion summary does say "delete the component", but it reaches only specChanges.converted[].to in --json; the human path prints no summaries at all.

Why class (b), and the contract text

ADR-0087 D3 (docs/adr/0087-….md:196-199) requires a structured TODO "rather than silence" for a migration step that cannot be expressed declaratively. After #17592, deleting the node is such a step — it was optional before (the node was inert) and it is now required for a schema-valid post-chain stack. ⇒ A declared contract says a TODO is owed, and there is none.

⚠️ This is not a defect of #17592, and the review did not treat it as one. It graded it a card, not a blocker, with the mitigations measured and real: step 18 is unreachable by every default caller until PROTOCOL_MAJOR reaches 18; zero authored instances exist (re-grepped at the PR head: 43 hits, all docs, tests and comments); and the tombstones say "Delete the component" at the props door while os validate says it at the node. ⇒ There is no user hitting this today. It is owed before step 18 becomes reachable.

Suggested shape (⛔ the lane decides)

A step-18 D3 semantic todo beside packages/spec/src/migrations/registry.ts:5092 (step18):

  • surface — the bare element:filter / element:form node the two conversions leave
  • replacement — delete it; userFilters for the filter, object-form for the form
  • acceptanceos validate clean

and the PR's ADR-0087 disposition then moves from not-required (already-registered element-filter-removed, element-form-removed) to registered. ⚠️ That disposition is gate-true today but semantically thin, and the review said why: the ids it names registered the key strips, ⛔ not the node deletion this PR turned into a required step.

Conversions at packages/spec/src/conversions/registry.ts:6812 / :6964.

What this does NOT claim

Refs: #15110 / PR #17592 (the narrowing that created the requirement) · #14159 (the mechanism) · #9220 / #9249 (the element-grain retirements).

domain:spec execution seat · session_01MkQhmuuJAVDjmeWNixwDDH · filed 2026-09-11T01:40Z


Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions