Skip to content

ADR-0049 enforce-or-remove: targetVariable on element:text_input / element:record_picker — a declarative hint with zero readers in any repo and no liveness-ledger entry #9198

Description

@os-project-manager

Filed by the triage seat (scheduled round 2026-08-17) as the enforce-or-remove channel for objectstack-ai/objectui#3834, whose grading history reached this route after its sibling card resolved by retirement.

The declared-but-unenforced shape

packages/spec declares targetVariable on two elements (packages/spec/src/ui/component.zod.ts:1635/:1743/:1810 at 2026-08-17 origin/main; also listed in authorable-surface.base.json and authorable-surface/ui.json). Its own describe text says it is a declarative hint: "Page variable this input writes to. Declarative hint; the live binding resolves via the variable whose source equals this component id (see PageVariableSchema)."

Measured (objectui#3834, re-verified 2026-08-17 against objectui origin/main):

  • Zero production readers in objectui — the only hits are the reverse-parity gate's exemption block (apps/console/src/__tests__/registry-inputs-spec-parity.test.ts:545-556, citing objectui#3834) and CHANGELOG lines. The live binding runs the other direction (usePageVariableBinding(schema?.id) reverse-looks-up PageVariableSchema.source), which works and matches the spec's own description.
  • No entry for it in any liveness ledger / ADR-0087 registry (grep across packages/spec, docs/adr, docs/audits — zero hits outside the schema and generated surface files).

Why this card, and why now

The hazard was written on objectui#3834: an author (human or AI) who reads the manifest will write targetVariable, skip the variable's source, and get an input that writes nothing, with zero diagnostics. The card sat as a hold pending a publish-vs-retire pick; the deciding precedent has since landed — objectui#3829, the paired inert-hint card, resolved via the retirement route (objectui PR #4794, commit 183d09b).

The work

Run the ADR-0049 enforce-or-remove flow for these two keys (both shapes identical — one disposition covers both):

  1. Establish the liveness verdict properly (the spec-property-retirement playbook's ledger discipline — the measurement above is a lead, not a ledger row).
  2. If the verdict is dead: retire via the standard route (ADR-0087 conversion, tombstone, generated baselines/forms/docs, pin tests) — the removal decision inside that flow follows its own maintainer gates as usual.
  3. If instead the disposition is "publish as intent metadata": the describe text must state explicitly that authoring it alone binds nothing (objectui#3834 records why the silent-no-op risk makes this the weaker option).
  4. objectui follow-through rides the outcome: drop the parity-gate exemption block either way (objectui#3834 is pm:blocked on this card).

Backlinks: objectui#3834 (origin, full analysis and grading history) · objectui#3829 → objectui PR #4794 (the sibling settled by retirement) · ADR-0049 · ADR-0087.

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions