Part of #14478 — follow-on card 4 of 6, filed by the domain:spec seat (session_01M59rPZZFzqhfMUPFqqZTkf, 2026-09-05T02:55Z) under the maintainer ruling B on #14478 (5548763981, batch #43, 「同意」). Dispatched after stack cards 1/6–3/6 have PRs to stack on.
Ruling text this card executes (verbatim)
Convert the ~30 authored config durations and the ~16 runtime-emitted measurements […]. Exempt by declaration, not by list: […] the ~12 external-vocabulary keys (marker on the key […]).
(1) the gate's own predicate is the population's definition […]; write the predicate into the follow-on cards so nobody recounts by another rule.
The predicate
Run pnpm --filter @objectstack/spec check:duration-unit-keys on the stacked head; a property whose value is a z.number() / z.int() / z.coerce.number() chain and whose .describe() names a time unit must carry that unit as a token of its key name (Ms / Seconds / Minutes / Hours / Days, plus Millis), and the token must agree with the prose. ⛔ The list below is the gate's own output on e68ae2b58, filtered to src/system/** minus card 1/6's marked keys (auth-config.zod.ts:308/:330/:550, object-storage.zod.ts:197/:258, disaster-recovery.zod.ts:127); re-derive on the stacked head before editing.
site (e68ae2b58) |
key |
describe unit |
gate's suggested name |
note |
src/system/cache.zod.ts:55 |
ttl |
seconds |
ttlSeconds |
authored |
src/system/cache.zod.ts:130 |
resetTimeout |
seconds |
resetTimeoutSeconds |
authored |
src/system/collaboration.zod.ts:469 |
idleTimeout |
ms |
idleTimeoutMs |
⚠️ the live 1000× name collision with the tenant idleTimeout (seconds) that #15626 already renamed — the reason the population was ruled, on the authorable surface |
src/system/collaboration.zod.ts:474 |
interval |
ms |
intervalMs |
authored |
src/system/disaster-recovery.zod.ts:115 |
healthCheckInterval |
seconds |
healthCheckIntervalSeconds |
authored |
src/system/metrics.zod.ts:335 |
size |
seconds |
sizeSeconds |
⚠️ the mechanical prescription reads wrong on its face: a window size in seconds is a duration, but sizeSeconds names a byte count's unit; the dev proposes the honest name (e.g. windowSeconds) and states why in the PR |
src/system/metrics.zod.ts:420 |
size |
seconds |
sizeSeconds |
same as above |
src/system/metrics.zod.ts:481 |
duration |
seconds |
durationSeconds |
emitted |
src/system/object-storage.zod.ts:447 |
timeout |
ms |
timeoutMs |
authored |
src/system/registry-config.zod.ts:42 |
syncInterval |
seconds |
syncIntervalSeconds |
authored |
src/system/registry-config.zod.ts:69 |
timeout |
ms |
timeoutMs |
authored |
src/system/registry-config.zod.ts:164 |
ttl |
seconds |
ttlSeconds |
authored |
src/system/tracing.zod.ts:214 |
duration |
ms |
durationMs |
emitted (TraceSpan.duration) |
src/system/worker.zod.ts:277 |
duration |
ms |
durationMs |
emitted |
(14 rows; the seat's "13" in the title is corroboration only — the gate's count on the stacked head is the reading.)
Execution notes
- Per key: authored ⇒ D2 conversion with a
retiredKey() tombstone and a RETIRED_KEYS_BY_MAJOR row where on the authorable surface; emitted ⇒ semantic ADR-0087 entry, emitter and every reader renamed in the same PR at the same magnitude. Readers by TYPE across every workspace package; liveness ledgers, forms, i18n bundles, docs and skills/** prose where they name a key (a skills/** hit makes the PR governed: keep it).
- Stacked on card 3/6's head; draft PR, base = that branch; body first line
Part of #14478, this card named without a closing keyword. ⛔ Never Fixes #14478.
Clause-②: yes ⇒ needs:contract-review on PR and card at creation. Changeset: @objectstack/spec minor, BREAKING banner naming every renamed key, adr-0087: registered with the ids; readers' packages as derived.
packages/spec/src/migrations/registry.ts is written by this stack only; serial order 2 → 3 → 4 → 5 → 6.
Related: #14478 · PR #15626 · stack 1/6 · #14519 (the tenant keys, already in #15626).
Part of #14478 — follow-on card 4 of 6, filed by the
domain:specseat (session_01M59rPZZFzqhfMUPFqqZTkf, 2026-09-05T02:55Z) under the maintainer ruling B on #14478 (5548763981, batch #43, 「同意」). Dispatched after stack cards 1/6–3/6 have PRs to stack on.Ruling text this card executes (verbatim)
The predicate
Run
pnpm --filter @objectstack/spec check:duration-unit-keyson the stacked head; a property whose value is az.number()/z.int()/z.coerce.number()chain and whose.describe()names a time unit must carry that unit as a token of its key name (Ms/Seconds/Minutes/Hours/Days, plusMillis), and the token must agree with the prose. ⛔ The list below is the gate's own output one68ae2b58, filtered tosrc/system/**minus card 1/6's marked keys (auth-config.zod.ts:308/:330/:550,object-storage.zod.ts:197/:258,disaster-recovery.zod.ts:127); re-derive on the stacked head before editing.e68ae2b58)src/system/cache.zod.ts:55ttlttlSecondssrc/system/cache.zod.ts:130resetTimeoutresetTimeoutSecondssrc/system/collaboration.zod.ts:469idleTimeoutidleTimeoutMsidleTimeout(seconds) that #15626 already renamed — the reason the population was ruled, on the authorable surfacesrc/system/collaboration.zod.ts:474intervalintervalMssrc/system/disaster-recovery.zod.ts:115healthCheckIntervalhealthCheckIntervalSecondssrc/system/metrics.zod.ts:335sizesizeSecondssizein seconds is a duration, butsizeSecondsnames a byte count's unit; the dev proposes the honest name (e.g.windowSeconds) and states why in the PRsrc/system/metrics.zod.ts:420sizesizeSecondssrc/system/metrics.zod.ts:481durationdurationSecondssrc/system/object-storage.zod.ts:447timeouttimeoutMssrc/system/registry-config.zod.ts:42syncIntervalsyncIntervalSecondssrc/system/registry-config.zod.ts:69timeouttimeoutMssrc/system/registry-config.zod.ts:164ttlttlSecondssrc/system/tracing.zod.ts:214durationdurationMsTraceSpan.duration)src/system/worker.zod.ts:277durationdurationMs(14 rows; the seat's "13" in the title is corroboration only — the gate's count on the stacked head is the reading.)
Execution notes
retiredKey()tombstone and aRETIRED_KEYS_BY_MAJORrow where on the authorable surface; emitted ⇒ semantic ADR-0087 entry, emitter and every reader renamed in the same PR at the same magnitude. Readers by TYPE across every workspace package; liveness ledgers, forms, i18n bundles, docs andskills/**prose where they name a key (askills/**hit makes the PR governed: keep it).Part of #14478, this card named without a closing keyword. ⛔ NeverFixes #14478.Clause-②: yes⇒needs:contract-reviewon PR and card at creation. Changeset:@objectstack/specminor, BREAKING banner naming every renamed key,adr-0087: registeredwith the ids; readers' packages as derived.packages/spec/src/migrations/registry.tsis written by this stack only; serial order 2 → 3 → 4 → 5 → 6.Related: #14478 · PR #15626 · stack 1/6 · #14519 (the tenant keys, already in #15626).