Repository navigation
Description
Part of #2643 (ADR-0087). Highest-leverage phase. A versioned, declarative load-time conversion layer so that lossless breaks (renames, moves, alias removals) require no action from a consumer for one full major — the Kubernetes storage-version / conversion model applied to metadata.
Depends on P0 (needs PROTOCOL_VERSION + the loader handshake seam).
Scope (D2)
- For each protocol major N, a versioned table
conversions/N.tsin@objectstack/spec: per renamed/moved/re-shaped surface, a transform N−1 shape → N shape, applied centrally at load (the same seamobjectstack validateuses), emitting a structured deprecation notice per applied conversion. - Scope guard: losslessly mappable changes only — renames, alias removals, field moves, enum re-spellings. A change with no lossless mapping is out of scope (→ P2 migration).
- Window: the loader applies a conversion for one major (N accepts N−1 shapes), then retires it from the load path in N+1 — but never deletes it: a retired conversion graduates into the P2 migration chain as that major's mechanical step.
- Seed with the shipped 11.0 renames as the first (retroactive) table —
http_request/http_call/webhook→http, and the client-react alias set — proving that, had this existed, protocol 11 would have needed zero consumer action. - Prove the PD Add comprehensive test suite for Zod schema validation #12 retirement path: promote one existing consumer-side executor fallback (e.g.
cfg.filter ?? cfg.filters) into a declared, expiring conversion entry, then delete the??.
Why this does NOT violate Prime Directive #12
PD #12 bans scattered, unowned consumer-side dialect fallbacks. The conversion table is the opposite on every axis PD #12 cares about: one central table (not N ??s), versioned + declared in the spec (owns its history), loud (a deprecation notice per application), tested (old→new fixture pair per entry), expiring (dropped on schedule). It is the explicit version history of one contract, not a second de-facto dialect. See ADR-0087 §"Why the conversion layer does not violate PD #12".
Acceptance criteria
- A metadata file authored with a 10.x shape covered by a conversion entry loads clean under 11.x, emits exactly one structured deprecation notice, and the runtime sees only the canonical shape.
- Each conversion entry ships with an old-shape → new-shape fixture pair; a CI check runs every entry's fixture through the load path.
- The retroactive 11.0 table converts the flow-node aliases and client-react aliases end-to-end.
- One executor
??fallback is retired through a conversion entry and deleted (PD Add comprehensive test suite for Zod schema validation #12 debt paydown demonstrated). - Removing a conversion from the load path in N+1 does not delete its history — it must appear as a P2 chain step (guarded once P2 exists; until then, tracked).
Boundaries
- Converts at load only; never rewrites the consumer's source files (that is P2's explicit
migrate meta). - Semantic (non-lossless) changes are explicitly excluded and belong to P2.
Refs: #2643, ADR-0087 (D2), AGENTS.md Prime Directive #12, ADR-0059.
Activity
fix(spec,service-automation): ADR-0087 — wire conversions into the ru…
feat(spec,cli): ADR-0087 P1+P2 — conversion layer, migration chain & …
feat(protocol): complete ADR-0087 — load-seam handshake, chain backfi…
fix(automation,spec): graduate notify's nested `source` into the conv…