Skip to content

Commit 702544e

Browse files
committed
docs(spec): the field.valueDomain liveness note stops claiming the settings door is unchanged
The `valueDomain` row's note ended on a sentence written while the settings-door re-point was still ahead of it: "The settings door (`service-settings/value-domains.ts`) re-points onto the shared predicate in its own follow-up card and is unchanged until then." Both halves of the 2026-09-02 ruling have since landed — the services half (#15434, 2026-09-04T23:39Z) and the engine half (#15316, 2026-09-05T01:43Z) — and the engine half, landing second, rewrote this note wholesale while carrying that sentence forward verbatim. It survived onto `main` describing a state that had already ended one commit earlier. The replacement is read off `packages/services/service-settings/src/value-domains.ts` on this ref rather than off a PR title: its second copy of all three definitions is deleted, it imports from `@objectstack/spec/shared` and nothing else, and `firstRejectedDomainMember` asks `isValueDomainMember` — the same call `record-validator.ts` makes at :712. What remains on that side is the door's own business (which declarations it agrees to enforce, how a multi-value carrier is walked, the fragments the env-override log line needs), and a re-added local table reddens `value-domains.shared-predicate.pin.test.ts`. Note text only, one JSON string value: the row's `status` is untouched — it tracks the engine write path — and `liveness/state-counts.md` is not adjusted from here. `check:liveness` reports the counts file current and `git status` stayed clean apart from the two files in this commit, so no generator moved a derived count under this change. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016N6xmWt5hYm94ffVEwGH8x
1 parent 2bdabe6 commit 702544e

2 files changed

Lines changed: 28 additions & 1 deletion

File tree

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
---
2+
"@objectstack/spec": patch
3+
---
4+
5+
docs(spec): the `field.valueDomain` liveness note stops claiming the settings door is "unchanged until then"
6+
7+
The `valueDomain` row of the published `liveness/field.json` ledger ended on a sentence written
8+
while the re-point was still in the future:
9+
10+
> The settings door (`service-settings/value-domains.ts`) re-points onto the shared predicate in
11+
> its own follow-up card and is unchanged until then.
12+
13+
Both halves of the 2026-09-02 ruling have since landed — the settings half (#15434) and the engine
14+
half (#15316) — and the engine half rewrote this note wholesale while carrying that sentence
15+
forward verbatim. "Unchanged until then" therefore described a state that no longer existed: the
16+
door it names had already re-pointed, one commit earlier.
17+
18+
The sentence now says what is true of that door, read off its source rather than off a PR title:
19+
its second copy of all three definitions is deleted, `firstRejectedDomainMember` asks
20+
`isValueDomainMember` — the same call `record-validator.ts` makes — and what remains on that side
21+
is the door's own business (which declarations it agrees to enforce, how a multi-value carrier is
22+
walked, the fragments the env-override log line needs). A re-added local table reddens
23+
`value-domains.shared-predicate.pin.test.ts`.
24+
25+
Ledger-note text only. The row's `status` is untouched — it tracks the engine write path, and
26+
`liveness/state-counts.md` is derived by `gen:liveness-counts` from the row states, none of which
27+
move here (`check:liveness` reports the counts file current).

packages/spec/liveness/field.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@
225225
"status": "live",
226226
"verifiedAt": "2026-09-04",
227227
"evidence": "packages/objectql/src/validation/record-validator.ts#validateOne (the write-path seam, beside `maxLength`'s: `if (def.valueDomain !== undefined && VALUE_DOMAIN_FIELD_TYPES.has(t) && !isValueDomainMember(def.valueDomain, s)) return fail('value_domain', { valueDomain: def.valueDomain }, ...)` \u2014 a non-member WRITTEN to a `text` field declaring a domain is refused with the ADR-0114 code `value_domain` and `constraint.valueDomain`); packages/spec/src/data/field.zod.ts#VALUE_DOMAIN_FIELD_TYPES (the parse-time applicability door: the key is accepted on `text` only and refused with a located `custom` issue at [valueDomain] on every other type — the same superRefine mechanism `maxLength` / `minLength` use); packages/spec/src/shared/value-domain.zod.ts#isValueDomainMember (the ONE membership predicate the write path will call — shared with the settings door)",
228-
"note": "The write path enforces it since 2026-09-04 (#15161, the engine half of the maintainer ruling 2026-09-02 option A on #14168; the spec half declared the slot, the closed vocabulary, the shared predicate, the ADR-0114 catalog member and its four-locale templates). WRITTEN VALUE ONLY, the `min`/`max`/`maxLength` transition-gate class: a stored value outside a domain declared later is never re-read and survives unrelated edits, and an absent/empty value is the field's `required` handling, not this check \u2014 both pinned in packages/objectql/src/validation/record-validator.value-domain.test.ts, together with the per-domain matrix (iso_3166_alpha2 admits CH and refuses ZZ; iana_time_zone admits UTC and refuses Mars/Olympus; iso_4217_currency admits CHF and refuses chf). The applicability door is one constant read by both seams \u2014 the schema refuses the key outside VALUE_DOMAIN_FIELD_TYPES at parse and the validator judges exactly that set, so the two cannot drift into two opinions (the #11875 discipline; the subset relation to BOUNDED_STRING_FIELD_TYPES, which the enforcement branch rides on, is pinned in the same file). The settings door (`service-settings/value-domains.ts`) re-points onto the shared predicate in its own follow-up card and is unchanged until then."
228+
"note": "The write path enforces it since 2026-09-04 (#15161, the engine half of the maintainer ruling 2026-09-02 option A on #14168; the spec half declared the slot, the closed vocabulary, the shared predicate, the ADR-0114 catalog member and its four-locale templates). WRITTEN VALUE ONLY, the `min`/`max`/`maxLength` transition-gate class: a stored value outside a domain declared later is never re-read and survives unrelated edits, and an absent/empty value is the field's `required` handling, not this check \u2014 both pinned in packages/objectql/src/validation/record-validator.value-domain.test.ts, together with the per-domain matrix (iso_3166_alpha2 admits CH and refuses ZZ; iana_time_zone admits UTC and refuses Mars/Olympus; iso_4217_currency admits CHF and refuses chf). The applicability door is one constant read by both seams \u2014 the schema refuses the key outside VALUE_DOMAIN_FIELD_TYPES at parse and the validator judges exactly that set, so the two cannot drift into two opinions (the #11875 discipline; the subset relation to BOUNDED_STRING_FIELD_TYPES, which the enforcement branch rides on, is pinned in the same file). The settings door (`service-settings/value-domains.ts`) has re-pointed onto that same predicate (#15434, the services half of the same ruling): its second copy of all three definitions is deleted and `firstRejectedDomainMember` asks `isValueDomainMember`, so a value Settings admits is the value a field admits and vice versa; what is left on that side is the door's own business (which declarations it agrees to enforce, how a multi-value carrier is walked, the fragments the env-override log line needs), and a re-added local table reddens packages/services/service-settings/src/value-domains.shared-predicate.pin.test.ts."
229229
},
230230
"rows": {
231231
"status": "live",

0 commit comments

Comments
 (0)