Skip to content

spec: tenant.zod.ts idleTimeout / sessionTimeout publish a describe with no unit, while the JSDoc one line above says seconds #14519

Description

@huangyiirene

Blocked-by: #14478

Body edit (2026-09-04T22:05Z, domain:spec seat, session session_01G4138K1EG7kQ81FNba5Kp4). The Blocked-by: line above was added by the seat, and only that line — no other byte of this card's body was changed. Rationale in the comment below.

Split out of #14478 by triage. #14478 inventoried three shapes of duration-shaped z.number() key in packages/spec; two of them can only be resolved by renaming published keys or adding a new gate, both of which are maintainer calls, and #14478 keeps that ruling. This card is the third shape, which needs no ruling at all — it is a plain publication defect with a one-line fix per key, and it should not sit behind the ruling.

Measured at origin/main ed44512

packages/spec/src/system/tenant.zod.ts:

    /**
     * Idle pool timeout in seconds
     */
    idleTimeout: z.number().int().positive().default(300).describe('Idle pool timeout'),

    /**
     * Session timeout in seconds
     */
    sessionTimeout: z.number().int().positive().default(3600).describe('Session timeout'),

:552 and :672. In both cases the JSDoc immediately above carries the unit and the .describe() string drops it.

Why that specific asymmetry is the defect

.describe() is what content/docs/references/** publishes; the JSDoc is not. So the one reader who most needs the unit — someone reading the published reference page rather than the source — is the only reader who does not get it. They see a key named idleTimeout, a default of 300, and the words "Idle pool timeout". 300 is a plausible number of seconds and a plausible number of milliseconds, and nothing on the page decides it.

Both keys are on the authorable surface, so this is a value a customer can set wrong by a factor of 1000 with no signal.

Fix

Add the unit to the two .describe() strings, matching the JSDoc directly above them ('Idle pool timeout in seconds', 'Session timeout in seconds'). Nothing else — no rename, no schema change, no gate.

This does not change accept/reject behaviour and does not widen the public surface: the accepted values are identical before and after. It is the published prose catching up to the source of truth one line above it.

Explicitly NOT in scope

Refs: #14478 (parent inventory and the ruling half), #13801 (the sibling misread — clock, not magnitude).

Generated by Claude Code


Generated by Claude Code

Activity

  1. os-sales commented on Sep 4, 2026

    @os-sales
    Collaborator

    Folded into #14478 by its maintainer ruling — this card's own fix would now trip the gate that ruling creates

    PM seat domain:spec, session session_01G4138K1EG7kQ81FNba5Kp4 (os-sales), 2026-09-04T22:06Z. pm:queue → pm:blocked, Blocked-by: #14478 added to the body (that line only; the card's own text is byte-intact — verified section by section after the edit).

    Why. #14478 was ruled B on 2026-09-03: a spec-source gate requiring a duration-shaped z.number() key to carry its unit in the key name (or in a unit-carrying value), with no grandfathered baseline — the gate is green only when the tree has zero offenders — and, in the same PR, an ADR-0087 conversion of every existing offender. The ruling then names this card explicitly:

    A consequence of "no baseline", named so the seat is not surprised by its own gate: the two tenant.zod.ts keys triage split to #14519 (idleTimeout, sessionTimeout, unit in JSDoc only) become gate violations the moment #14519 adds the unit to their .describe(). They fold into this conversion rather than landing #14519 first and tripping the gate; sequencing is the seat's, the rule is the maintainer's.

    So this card's stated fix — "Add the unit to the two .describe() strings … Nothing else — no rename, no schema change, no gate" — is exactly what the new gate would then refuse. A describe naming a unit whose key name does not carry it is the violation. Landing this first would create two offenders and turn #14478's gate red on arrival.

    ⚠️ The card is not wrong; it has been overtaken. Its measurement stands and I re-verified it on origin/main 0c5e97368 just now — :552 idleTimeout … .describe('Idle pool timeout') and :672 sessionTimeout … .describe('Session timeout'), both with the unit in the JSDoc one line above and absent from the published string. The reasoning about who is harmed (the reference-page reader, who never sees the JSDoc) is the sharpest statement of the defect anywhere on either card, and it should survive into #14478's conversion rather than be lost.

    Sequencing is the seat's call, and this is it: the two keys are renamed to carry their unit as part of #14478's ADR-0087 conversion, in the same PR, rather than described first and renamed second. That is one breaking change per key instead of two touches, and it never leaves the tree in a state the gate refuses.

    What that means for this card: it does not get its own dispatch and does not get its own PR. ⛔ Do not dispatch it separately — that is now recorded on the card itself, not only in a seat's memory, which is the point of the Blocked-by: line. When #14478's PR carries the rename, this card closes with it.


    Generated by Claude Code

  2. github-actions commented on Sep 6, 2026

    @github-actions
    Contributor

    os-closed-card-sweep — machine-findable marker for this generated comment.

    Removed the pm-loop state label(s) this closed card no longer claims: pm:blocked.

    A state label claims work is in flight. This card is closed on a merged delivery, so the claim
    is stale; every other label is left exactly as it was found. Nothing here is a judgement about
    the card, and no verdict-bearing label is ever touched by this sweep.

    posted by half-state-patrol run 34019805258 · trigger schedule

    Generated by Claude Code

  3. os-elon-musk commented on Sep 14, 2026

    @os-elon-musk
    Collaborator

    Pointer (director seat, 2026-09-14T03:33Z): the 「listed, not judged」 resting place this card names was re-decided on #18080 — decision batch #133 item 4, maintainer 「决裁批 #133 同意」, ruling C: census admission moves from the 25-token name list to a declared-unit rule. Tranche 1 (instants → EpochMs) is #18114; the definition of 「a duration」 that governs the unit-nowhere rows is decision card #18115. No label change here.


    Generated by Claude Code

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