Found while measuring #15041 (the FILE_REFERENCE_TYPES column fork). Out of scope there: #15041 is a measurement card and does not edit field-value.zod.ts. Filed unassigned; observation class, no severity asserted.
The stale sentence
Measured on origin/main 8e500f23e (2026-09-05T06:58Z), packages/spec/src/data/field-value.zod.ts:
:177-181 — the docblock over FILE_REFERENCE_TYPES still reads: "Stored form TODAY is the legacy inline metadata object ({url, name?, size?, ...}) or an opaque file-id/url string; ADR-0104 D3 (file-as-reference) narrows this to a sys_file id. The stored schema below deliberately admits both until D3 lands."
:515-522 — the classifier branch if (FILE_REFERENCE_TYPES.has(t)) returns FileReferenceIdValueSchema for form === 'stored' and the [FileReferenceIdValueSchema, FileValueSchema] union only for 'expanded'.
:411 — FileReferenceIdValueSchema is z.string().regex(...) (id-shaped, 1-64 word characters or hyphen).
valueSchemaFor({ type: 'file' }, 'stored').safeParse(...) on the same ref, run through both the source and the built dist/data/index.mjs (verdicts byte-identical): an inline {url, name, size} object is REJECTED ("Invalid input: expected string, received object"), a bare URL is REJECTED ("Expected an opaque sys_file id"), a sys_file id is OK. Same verdicts for all five members. The spec's own pin says so too: field-value.test.ts "D3 wave 2: the STORED media form is an opaque sys_file id" (bad({ type: 'file' }, { url: ..., name: ..., size: 1024 })).
So "deliberately admits both until D3 lands" has been false since D3 wave 2 PR-5a (fe67e34, spec 17.0.0, changelog: "The stored form of a media field narrows to an opaque sys_file id"). What the stored schema admits is the id; the object is the expanded READ form. The sentence is load-bearing prose: #15041 was filed on it ("the spec's own class doc states both at once"), and its triage quoted it as current.
Sibling: FileLikeValueSchema (:425, "the TRANSITIONAL union that was the stored contract before wave 2", @deprecated) has zero consumers outside this file (git grep FileLikeValueSchema -- 'packages/**/src/**' hits only its definition; the same grep for FileValueSchema finds objectql/src/engine.ts and spec/src/contracts/approval-service.ts, so the zero is a reading).
What a fix looks like
Rewrite the :177-181 docblock to state the shipped contract (stored = FileReferenceIdValueSchema; expanded = the union; the runtime admission of legacy values is the warn-first posture in objectql/src/validation/record-validator.ts, not the schema), and decide whether the unconsumed FileLikeValueSchema stays exported. packages/spec docblocks land in content/docs/references/, so gen:schema && gen:docs ride along.
Not a behaviour change; the classifier is correct as shipped.
Generated by Claude Code
Found while measuring #15041 (the FILE_REFERENCE_TYPES column fork). Out of scope there: #15041 is a measurement card and does not edit
field-value.zod.ts. Filed unassigned; observation class, no severity asserted.The stale sentence
Measured on
origin/main8e500f23e(2026-09-05T06:58Z),packages/spec/src/data/field-value.zod.ts::177-181— the docblock overFILE_REFERENCE_TYPESstill reads: "Stored form TODAY is the legacy inline metadata object ({url, name?, size?, ...}) or an opaque file-id/url string; ADR-0104 D3 (file-as-reference) narrows this to asys_fileid. The stored schema below deliberately admits both until D3 lands.":515-522— the classifier branchif (FILE_REFERENCE_TYPES.has(t))returnsFileReferenceIdValueSchemaforform === 'stored'and the[FileReferenceIdValueSchema, FileValueSchema]union only for'expanded'.:411—FileReferenceIdValueSchemaisz.string().regex(...)(id-shaped, 1-64 word characters or hyphen).valueSchemaFor({ type: 'file' }, 'stored').safeParse(...)on the same ref, run through both the source and the builtdist/data/index.mjs(verdicts byte-identical): an inline{url, name, size}object is REJECTED ("Invalid input: expected string, received object"), a bare URL is REJECTED ("Expected an opaque sys_file id"), asys_fileid is OK. Same verdicts for all five members. The spec's own pin says so too:field-value.test.ts"D3 wave 2: the STORED media form is an opaque sys_file id" (bad({ type: 'file' }, { url: ..., name: ..., size: 1024 })).So "deliberately admits both until D3 lands" has been false since D3 wave 2 PR-5a (
fe67e34, spec17.0.0, changelog: "The stored form of a media field narrows to an opaque sys_file id"). What the stored schema admits is the id; the object is the expanded READ form. The sentence is load-bearing prose: #15041 was filed on it ("the spec's own class doc states both at once"), and its triage quoted it as current.Sibling:
FileLikeValueSchema(:425, "the TRANSITIONAL union that was the stored contract before wave 2",@deprecated) has zero consumers outside this file (git grep FileLikeValueSchema -- 'packages/**/src/**'hits only its definition; the same grep forFileValueSchemafindsobjectql/src/engine.tsandspec/src/contracts/approval-service.ts, so the zero is a reading).What a fix looks like
Rewrite the
:177-181docblock to state the shipped contract (stored =FileReferenceIdValueSchema; expanded = the union; the runtime admission of legacy values is the warn-first posture inobjectql/src/validation/record-validator.ts, not the schema), and decide whether the unconsumedFileLikeValueSchemastays exported.packages/specdocblocks land incontent/docs/references/, sogen:schema && gen:docsride along.Not a behaviour change; the classifier is correct as shipped.
Generated by Claude Code