Skip to content

spec: closed duration types DurationMs / DurationSeconds beside EpochMs — step ① of ruling A on #18115 (declared shape for the unit-in-key census) #18122

Description

@os-elon-musk

Filed by the director seat (objectstack #12708, summon #23, session_01WCEaPsmKY4UyoivKkkaUHt) executing decision batch #134 item 1 — maintainer 「决裁批 #134 同意」 to the recommended A on #18115 (declared shape: closed duration types + unit-in-name; the 25-token name list retires from judge to detector), 2026-09-14T03:44Z. This is step ① of three; #18114 (instants → EpochMs) is independent and already queued. domain:spec by landing site; p2; triage may re-rank.

The ruling this card executes (verbatim from #18115, batch #134 item 1)

A 声明式:引入与 EpochMs 同款的闭合时长类型(DurationMs / DurationSeconds,单位集合由 6 个真时长行决定);体检只认「用了时长类型,或键名带单位」的键;17 个无单位数自然出列,6+2+≥2 个真时长各取类型或改名;名字表退为提示。

What to build

Closed duration types beside EpochMs in packages/spec/src/shared/epoch.zod.ts (or a sibling duration.zod.ts re-exported the same way — the dev chooses; both must be reachable from the package entry exactly as EpochMs is):

  • DurationMsz.number().int().nonnegative() (or the least-surprising refinement the six genuine rows tolerate; measure their defaults: shutdownTimeout .default(30000), updateAge .default(60*60*24)), .describe('Duration in milliseconds').
  • DurationSeconds — same shape, seconds.
  • ⛔ No speculative third unit: DurationMinutes/Hours/Days are added only when a real row in step ③ needs one, in that step's PR. The unit set is derived from the conversion population, ⛔ not declared ahead of it.

Mirror EpochMs's discipline verbatim: author state and parsed state coincide (no default, no transform), so there is deliberately no *Parsed synonym; the docblock states the naming convention the gate will read (a Duration* type is one of the two declaration channels — the other is a unit token in the key name).

Acceptance

  • Clause-②: yes — new exported symbols on the published spec entry; changeset minor.
  • A pin that both types accept the six genuine rows' current defaults and refuse a non-integer / negative literal (loud at authoring, ZodError), with the EpochMs isomorphism pin pattern copied (input type = output type).
  • tsx scripts/check-duration-unit-keys.ts --self-test still exit 0 (this step changes no gate behaviour; the gate learns to READ the new types in step ②).
  • Nothing else moves: ⛔ no key converted here (step ③), ⛔ no gate change here (step ②).

Fences

  • content/docs/releases/** untouched; ⛔ no key renames; ⛔ no admission-rule change.

Re-check before claiming

git fetch origin main
git grep -n -E 'export const (DurationMs|DurationSeconds)' origin/main -- packages/spec/src   # expected 0 today
git grep -n -E 'export const EpochMs' origin/main -- packages/spec/src/shared/epoch.zod.ts    # the precedent, expected 1

Downstream (filed alongside, pm:blocked on this card)

Step ② — the gate's admission rule; step ③ — conversion of the genuine duration rows. Both carry Blocked-by: this card; the unlock scan returns them to pm:queue when this lands on origin/main (same repo ⇒ merge is the criterion, no pin lag).

Refs

#18115 (ruling A, batch #134 item 1) · #18080 (ruling C, batch #133 item 4) · #18078 (census) · #18114 (instants tranche, independent) · packages/spec/src/shared/epoch.zod.ts

Dedup terms: DurationMs, DurationSeconds, closed duration type, epoch.zod.ts sibling, unit-in-key declared shape


Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions