Repository navigation
Commit 98bd798
feat(spec)!: the three
Fixes #17780
Clause-②: yes
Executes director-seat **ruling A on #15939** (2026-09-11, maintainer
「同意」, decision batch #115) for
`packages/spec/src/kernel/plugin-lifecycle-advanced.zod.ts` — 3 rows of
the 21-row delta, following the #15678 / #15679 shape. The declaration
above reads the affirmative: the rename puts three spellings on a
published payload no author could write before. `check-clause2-carriers
--pair 17986` reads **exit 0** — declaration readable in the fixed
spelling, both carriers agree.
## The three rows, re-located by symbol
Each key was confirmed to be the **only** key-position declaration of
that name in the file (`interval` 1, `timeout` 1, `debounceDelay` 1; lit
control `z.number` 12, dark control 0), and each JSDoc was read rather
than inferred from the default:
| key | JSDoc, as read | published `.describe()`, before | new spelling
|
|:--|:--|:--|:--|
| `PluginHealthCheck.interval` | "Health check interval in
**milliseconds**" | "How often to perform health checks (default: 30s)"
| `intervalMs` |
| `PluginHealthCheck.timeout` | "Timeout for health check in
**milliseconds**" | "Maximum time to wait for health check response" |
`timeoutMs` |
| `HotReloadConfig.debounceDelay` | "Debounce delay before reloading
(**milliseconds**)" | "Wait time after change detection before reload" |
`debounceDelayMs` |
All three are milliseconds. The `check:duration-unit-keys` census reads
all three `[name: -] [prose: -]` on `origin/main` — no unit in the name
and none the gate recognises in the published prose. `interval` is the
sharpest: its one unit-shaped token was the parenthetical `(default:
30s)`, naming SECONDS for a value the schema bounds at `min(1000)` and
defaults to `30000` milliseconds.
## Why these spellings
Counted on this tree, not assumed from the card: 100 key-position `*Ms`
declarations across `packages/spec/src`, of which `timeoutMs` is 29 and
`intervalMs` is 3 — both renames land on names the surface already uses.
The analogous question to the sibling round's `Ttl`-versus-`TTL` was
asked for `debounceDelay` and answered the other way: it is the only
debounce-shaped key spelling in the repo (5 key-position occurrences,
all this key and its fixtures; no `debounceMs` variant anywhere), while
the Delay-plus-`Ms` pairing is already attested (`maxDelayMs`,
`initialDelayMs`, `retryDelayMs`, `delayMs`). There was no competing
family spelling to choose between, so it takes the plain suffix.
## The kit
- `retiredKey()` tombstone on each old spelling. Neither
`PluginHealthCheckSchema` nor `HotReloadConfigSchema` is `.strict()`, so
a bare deletion would be a silent strip — and here the stripped value
lands on a `setInterval` period, a race deadline and a `setTimeout`
delay.
- ADR-0087 D3 semantic entry
`kernel-health-check-and-hot-reload-durations-unit-in-key` **and** three
`RETIRED_KEYS_BY_MAJOR[18]` rows — both, per the PM's settlement on
#15939. No D2 conversion: neither def is an authorable surface (both are
library parameters a host passes to `PluginHealthMonitor` /
`HotReloadManager` in TypeScript), the same disposition
`plugin-auto-restart-never-reinitialised` and
`hot-reload-watch-placeholder-retired` recorded for keys on these two
defs. `registry.ts` is **generated** — `gen:migration-registry`, never
hand-merged.
- `@objectstack/core` moves with the rename (it is the only in-repo
reader): both classes read the suffixed keys, and each registration-time
refusal table gains a row so a host still passing an old spelling gets
an ADR-0112 `VALIDATION_ERROR` / 400 naming the rename instead of
`undefined` where a duration belongs. Those two runtime strings carry
**no tracker id** — a runtime string reaches operators who cannot
resolve one; the anchor sits in an adjacent `//` comment
(`check:doc-authoring`).
- Generated artifacts regenerated, never hand-edited:
`authorable-surface/kernel.json`, `authorable-defaults/kernel.json`,
`content/docs/references/kernel/plugin-lifecycle-advanced.mdx`. `pnpm
--filter @objectstack/spec check:generated` reports 15 of 15 up to date.
- Hand-written `content/docs/protocol/kernel/lifecycle.mdx` updated
where it names the keys (+8 / −6).
## The authorable-surface ratchet MOVES here, and that is correct
`authorable-surface/kernel.json` records **top-level keys per def**. All
three of these keys are top level, so the rename must move the ledger —
three `[RETIRED]` markers added beside three new suffixed rows, plus the
matching `authorable-defaults` moves. This is the opposite reading from
sibling PR #17954, whose key was **nested**
(`performance.schemaCacheTTL`) and correctly moved nothing: different
readings, same rule, both right. Regenerated by `gen:schema`, never
hand-edited.
## Pin tests replaced, not deleted
Two minimum-bound pins are the ones worth calling out. Spelled through
the bare keys, `PluginHealthCheckSchema.parse({ interval: 500 })` would
have kept throwing — off the **tombstone's refusal**, not the
`min(1000)` bound, a pin that can no longer fail. They now assert the
`too_small` issue code on the suffixed keys plus an accepting control at
the boundary. The default and fixture pins were re-pointed at the new
spellings with `not.toHaveProperty` on the old ones; nothing was
deleted, weakened or skipped.
New pins: the refusal carries the rename prescription (asserting the
issue is not `unrecognized_keys`), the suffixed keys parse at the
magnitude the retired ones carried with the same defaults, the describes
publish the unit, and both core classes refuse an old spelling at
`registerPlugin` before the plugin is stored, with an accepting control
beside each.
## Consumer sweep — `@objectstack/core` is the only reader
| subject, outside `packages/spec` and `packages/core` | occurrences |
|:--|--:|
| `PluginHealthCheckParsed` / `HotReloadConfigParsed` | 0 / 0 |
| `PluginHealthCheck` · `HotReloadConfig` · `PluginHealthMonitor` ·
`HotReloadManager` | 4 · 6 · 2 · 7 — **all prose**: changesets, the
generated upgrade guide, a `//` comment in a `packages/rest` pin test,
and two CHANGELOG lines. Zero code readers. |
| the three keys in a health-check / hot-reload context | 0 |
Lit controls on the same corpus: `@objectstack/spec` 14580,
`PluginContext` 973, `ObjectKernel` 588. Dark control `zzqqxx` 0.
## Pinned objectui: 0, with controls
`.objectui-sha` = `53ded82bf7a494f54e344e19099dbf00854b8694` — this IS
the pin we build against (checked here). Grepped at that sha across its
6409 tracked files: all **thirteen** exports of
`plugin-lifecycle-advanced.zod.ts` occur 0 times, and `debounceDelay`
occurs 0 times. Lit controls on the same corpus: `objectstack` 10171,
`@objectstack/spec` 3479, `timeout` 832, `interval` 156. Dark control
`zzqqxx` 0. Console Pin Gate is unaffected.
## Verification
| command | verdict |
|:--|:--|
| `pnpm --filter @objectstack/spec build` | `VERDICT command-exit 0` |
| `pnpm --filter @objectstack/spec check:generated` | exit 0 — 15 of 15
artifacts current |
| `pnpm --filter '@objectstack/core^...' build` | `VERDICT command-exit
0` |
| `pnpm --filter @objectstack/core build` | `VERDICT command-exit 0` |
| `pnpm --filter @objectstack/core test` | `VERDICT command-exit 0` — 51
files, 1316 tests |
| `pnpm --filter @objectstack/spec test` | `VERDICT command-exit 0` —
475 files, 13517 tests |
| `pnpm --filter @objectstack/spec --filter @objectstack/core typecheck`
| `VERDICT command-exit 0` |
| `dispatch-gates --commands` → all 110, reconciled with `--ran … ::
exit N` | **104 exit 0 · 0 red · 6 exit 3** |
The six exit-3s are `PREREQUISITE NOT MET` on unbuilt sibling workspace
packages outside this change's build closure (`@objectstack/lint`,
`@objectstack/formula`) — NOT MEASURED by the gates' own classification,
and built by CI. `check:skill-examples` initially refused with **exit
1** on an unbuilt `@objectstack/client-react` — the refusal shape that a
`--ran` reconciler counts as run; it was measured properly after
building that closure and reads exit 0 (258 prose examples across 3
surfaces).
## Acceptance notes
- **`HotReloadConfig.shutdownTimeout` is deliberately not renamed with
these three.** Its JSDoc reads "Graceful shutdown timeout" and names no
unit anywhere — it is the unit-nowhere shape the #14478 gate leaves
outside its verdict by measurement, and it is not one of the 21 rows PR
#17635 enumerates. Noted, not filed: the gate's own `--list` census
already keeps it visible, and its header records that closing that class
is a describe-by-describe decision rather than a defect.
- `check-widening-tells` raising T1 on the `retiredKey()` tombstone
lines is the known inverted false positive (#17955) — the lines it fires
on make the accept set strictly narrower. The diff is not reshaped and
the checker is not weakened.
- **Docs Drift Check named six pages; five are false positives.** Its
anchor is a bare `timeoutMs` string literal inside the new retirement
constant, so it listed every page using that generic word:
`automation/jobs.mdx`, `automation/webhooks.mdx`,
`automation/flows.mdx`, `deployment/environment-variables.mdx` and
`automation/hook-bodies.mdx` — job scheduling, webhook retry backoff and
the ADR-0102 sandbox CPU budget, none of them `PluginHealthCheck` or
`HotReloadConfig` (0 plugin-health mentions each; `hook-bodies.mdx`'s
two "hot-reload" hits are Studio in-browser editing). The sixth,
`protocol/kernel/lifecycle.mdx`, is the genuine hit and is edited here.
The three `content/docs/releases/` pages are release-owned and
untouched. Recorded because the four remaining rename cards in this epic
will trip the same anchor.
⛔ Draft on purpose: the in-seat clause-② review at tier is owed first,
and landing is the PM's step.
---
_Generated by [Claude
Code](https://claude.ai/code/session_015c5G6TmpMKgnusmTpD7Ntt)_
Co-authored-by: Claude <noreply@anthropic.com>kernel/plugin-lifecycle-advanced.zod.ts duration keys carry their unit in the key name (#17986)1 parent c45ea8c commit 98bd798
16 files changed
Lines changed: 683 additions & 76 deletions
File tree
- .changeset
- content/docs
- protocol/kernel
- references/kernel
- packages
- core/src
- spec
- authorable-defaults
- authorable-surface
- src
- kernel
- migrations
- entries
- retired-keys
- semantic
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
693 | 693 | | |
694 | 694 | | |
695 | 695 | | |
696 | | - | |
| 696 | + | |
697 | 697 | | |
698 | 698 | | |
699 | 699 | | |
| |||
702 | 702 | | |
703 | 703 | | |
704 | 704 | | |
705 | | - | |
706 | | - | |
707 | | - | |
| 705 | + | |
| 706 | + | |
| 707 | + | |
| 708 | + | |
| 709 | + | |
708 | 710 | | |
709 | 711 | | |
710 | 712 | | |
| |||
713 | 715 | | |
714 | 716 | | |
715 | 717 | | |
716 | | - | |
| 718 | + | |
717 | 719 | | |
718 | 720 | | |
719 | 721 | | |
| |||
787 | 789 | | |
788 | 790 | | |
789 | 791 | | |
790 | | - | |
| 792 | + | |
791 | 793 | | |
792 | 794 | | |
793 | 795 | | |
| |||
Lines changed: 6 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
42 | 42 | | |
43 | 43 | | |
44 | 44 | | |
45 | | - | |
| 45 | + | |
| 46 | + | |
46 | 47 | | |
47 | 48 | | |
48 | 49 | | |
| |||
58 | 59 | | |
59 | 60 | | |
60 | 61 | | |
61 | | - | |
62 | | - | |
| 62 | + | |
| 63 | + | |
63 | 64 | | |
64 | 65 | | |
65 | 66 | | |
66 | 67 | | |
67 | 68 | | |
68 | 69 | | |
| 70 | + | |
| 71 | + | |
69 | 72 | | |
70 | 73 | | |
71 | 74 | | |
| |||
0 commit comments