Skip to content

spec: the genuine duration rows adopt a declaration — DurationMs/DurationSeconds or a unit-suffixed name (census #18078 classes A-true ×6, B ×2, D ×≥2) — step ③ of ruling A on #18115 #18124

Description

@os-elon-musk

Blocked-by: #18669

⏱️ PM 改写本行(巡检 H28 的处方,2026-09-17T14:02Z;原行 Blocked-by: #18122 留在编辑历史里)。 #18122 已于 2026-09-15 关闭,本卡等的早已不是它:步骤③的十行里八行已随 PR #18657 落地(c049e74679 单亲),余下两行等的是决策卡 #18669 的裁定。⇒ 按 H28「把正文那行改写成点名活着的那个阻塞源」,让下一个读者(人或巡检)在正文这个正典位置读到当前的等待。

⚠️ 本阻塞按构造是无限期的(巡检 H26):解锁谓词是「Blocked-by: 目标关闭」,而 #18669needs-user-decision —— 那是一张开着的时候才待在那个状态的卡。⇒ 释放只能来自目标自身状态的改变(裁定被答),⛔ 不会有任何机制自动放行,得有人想要它。⭐ 裁 A(改名)之后还有第二道:两条 ADR-0087 转换层条目落 packages/spec/src/migrations/registry.ts,该文件由席 1 的 #17534 持有 —— 那一张关,所以那半程是有机制的。

ℹ️ 巡检 H52 的处置记录在此,免得下一轮重问:终报的三个 open_questions 已在 5714587850 逐条答 A;而执行裁决时长出的两条残留按 H52 的 RESIDUAL 分支另立 #18669,⛔ 未在本卡重挂 needs-user-decision

Filed by the director seat (objectstack #12708, summon #23, session_01WCEaPsmKY4UyoivKkkaUHt) executing decision batch #134 item 1 — maintainer 「决裁批 #134 同意」 to A on #18115, 2026-09-14T03:44Z. Step ③ of three: the genuine duration rows adopt a declaration. domain:spec; p2; pm:blocked until step ① is on origin/main. Foldable by file family (five-gate fold: same defect shape, same fix, all rows ruled, each row independently checkable, exclusions named below).

The population — census #18078 @ fb29f62cee; re-verify each row on today's origin/main (lines drift, key + file is the identity)

Genuine durations, unit in no channel (class A-true, 6):

file:line key reading likely unit (dev measures the producer, ⛔ not this table)
packages/spec/src/api/contract.zod.ts:311 duration BaseResponseSchema.meta.duration, beside a string timestamp, no describe/JSDoc ms (measure the REST server's writer)
packages/spec/src/data/field-value.zod.ts:424 duration FileValueSchema, media length seconds? (measure the upload/metadata writer)
packages/spec/src/kernel/plugin-lifecycle-advanced.zod.ts:413 shutdownTimeout .default(30000), "Graceful shutdown timeout" ms
packages/spec/src/kernel/plugin-security-advanced.zod.ts:623 maxAge CORS Access-Control-Max-Age mirror seconds by RFC — consider externalVocabulary like its sibling expiresIn
packages/spec/src/system/auth-config.zod.ts:563 updateAge .default(60 * 60 * 24), "Session update frequency"; sibling expiresIn carries externalVocabulary: 'better-auth session' seconds (better-auth) — same externalVocabulary route as its sibling is legitimate
packages/spec/src/system/metrics.zod.ts:412 slideInterval sibling durationSeconds in the same window object seconds

Unit only in JSDoc (class B, 2): packages/spec/src/kernel/plugin-versioning.zod.ts:191 estimatedMigrationTime · packages/spec/src/system/metrics.zod.ts:847 resolution (sibling afterSeconds).

Unit nowhere, outside the census (class D durations, ≥2): packages/spec/src/system/metadata-persistence.zod.ts:259 loadTime, :287 saveTime — bare z.number().optional(), no describe, no JSDoc, beside size and etag.

Plus any genuine duration step ②'s widened detector surfaces (that card routes them here, ⛔ does not convert them).

What each row does — one of two declarations, per the ruling

⚠️ The unit of each row is a measurement of its producer/consumer (who writes the number, in what unit), ⛔ never a guess from the name — a wrong unit declaration is the exact silent ×1000 error this whole program exists to prevent. Print the reading per row in the PR body.

Exclusions (named so the fold is honest)

Acceptance

  • After this PR and step ②, --list shows zero undeclared time-shaped refusals on packages/spec/src; the summary line's declared-duration count equals the rows converted by type.
  • Each renamed key carries its ADR-0087 entry, tombstone pin and form/docs/baseline updates per the retirement skill; each typed key carries a pin that a non-integer / negative literal is refused.
  • Clause-②: the seat derives at claim — a type adoption narrows acceptance (no); a rename retires an authorable key (no, a published surface shrinks) — both carry the BREAKING banner where a producer is measured writing what is now refused.
  • Changeset minor with **BREAKING** banner and ADR-0087 disposition for any renamed or newly-refusing row (pre-GA convention).

Fences

  • ⛔ No gate change (step ②); ⛔ no new type (step ①; if a row needs a unit neither type covers, STOP and report — the ruling adds units only on a measured need); ⛔ content/docs/releases/** untouched.

Re-check before claiming

git fetch origin main
git grep -n -E 'export const (DurationMs|DurationSeconds)' origin/main -- packages/spec/src   # step ① landed? must be ≥1
cd packages/spec && tsx scripts/check-duration-unit-keys.ts --list | grep -c '\[name: -\] \[prose: -\]'   # A-class count today (23; 22 after #18114)

Refs

#18115 (ruling A) · #18080 (ruling C) · #18078 (census §A-true, §B, §D) · #15939 (the parent epic that renamed 21 sibling rows — the precedent for the rename route) · step ① / step ② cards · .claude/skills/spec-property-retirement

Dedup terms: shutdownTimeout DurationMs, loadTime saveTime unit, estimatedMigrationTime, slideInterval, genuine duration conversion, unit-nowhere durations


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

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions