Skip to content

[finding] field.conditionalRequired is ledgered live citing a .transform that protocol 17 removed — and the rule-validator fallback its note relies on is gone too #13043

Description

@os-trump

Found while re-anchoring packages/spec/liveness/field.json for #13003 batch 4. Same class as #13036 (action.execute), and reported rather than executed for the same reason: the repair is an ADR-0049 re-classification, not a citation fix.

What the ledger says

packages/spec/liveness/field.json, prop conditionalRequired:

  • status: "live"
  • evidence: "packages/spec/src/data/field.zod.ts:639 — the FieldSchema .transform lowers conditionalRequired -> requiredWhen and DROPS the alias, so authoring it changes what the validator enforces"
  • the note adds: "objectql rule-validator.ts keeps its requiredWhen ?? conditionalRequired fallback on purpose: raw (unparsed) metadata still reaches evaluateValidationRules."

What the tree says (measured at 8cb96ec)

  1. The cited .transform is gone. The key was REMOVED in protocol 17 ([P3] Retire the three deprecated aliases — via the ADR-0087 D2 conversion layer, not by deleting the keys #3855) and is a tombstone: packages/spec/src/data/field.zod.ts declares conditionalRequired: retiredKey('...was removed in @objectstack/spec 17 — use requiredWhen...'). requiredWhen's own describe() says so out loud: "The only slot; the conditionalRequired alias was removed in protocol 17." Authoring the key is a tsc error and a parse error, not a lowering.
  2. The rule-validator fallback the note relies on is gone too. packages/objectql/src/validation/rule-validator.ts says at the requiredWhen declaration: "The ONLY predicate slot. The retired conditionalRequired alias ([P2] field.conditionalRequired is the same alias-drift shape #3713 just fixed — and the spec pins the alias to SURVIVE parse #3754 / ...)". The absence is pinned by a test in packages/objectql/src/validation/rule-validator.test.ts — "does NOT read the retired conditionalRequired alias (PD Add comprehensive test suite for Zod schema validation #12 — no dialect fallback)".
  3. The only surviving references are the close-out machinery, not consumers: the ADR-0087 conversion field-conditionalRequired-to-requiredWhen in packages/spec/src/conversions/registry.ts, its migration-registry row, and packages/spec/src/data/authoring-key-lint.ts's explicit "NOTE: no entry for conditionalRequired".

So the live verdict is falsified in both halves of its evidence, and the citation is one of the two survivors that kept #13003's line-citation counter off zero.

Why the line never rotted, and no check saw it

field.zod.ts:639 is in range in a 2,133-line file, and the file names conditionalRequired five times, so the existence check, the line bound and the key-mention check all pass. The line itself has drifted onto ])); inside FieldMaskingRuleSchema — but that is beside the point: even a perfectly-placed line would not have told anyone the key is retired.

Suggested disposition (not executed)

dead, matching the already-tombstoned siblings action.shortcut / action.bulkEnabled in this repo, with the row STAYING — retiredKey keeps the key in the walked shape (the rls.priority precedent, and orphans.mts's tombstone rule). The note would record the protocol-17 removal, the conversion id, and the pin test. That is an ADR-0049 re-classification with its own card shape, which is why #13003 batch 4 left the entry byte-for-byte untouched and un-restamped rather than dressing a dead entry as freshly verified.

Filed unassigned, bare for triage. Dedup searched 2026-08-28: #13036 covers action.execute only; #7133 / #7142 were the objectui-side citation-repair sweeps; no open card covers this key. Channel note: repo-scoped REST reads return HTTP 403 from this dev seat (probed this session; gh absent), so the REST-first dedup rule could not be followed — this used one targeted MCP semantic search, which returned a non-empty result set and is therefore self-validating.

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions