You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(devx): gate the "startup registry verdict" class — read the registry all you like, never record the "no" (#4777) (#4833)
One showcase cold start on 2026-08-03 produced three instances of one shape in
three unrelated subsystems, written by three people at three times: ask a
registry "is X there?" while the boot is still filling it, treat the "no" as
final, and RECORD it — cached on the instance (#4772 plugin-auth), asserted in
a warn (#4771 service-automation), or written to the database (#4769 objectql).
The provider registers a moment later; nothing undoes the record.
All three are fixed. This is what stops the class from coming back, built on
the #4632 machinery (declared vocabulary + AST + shrink-only baseline +
--self-test) rather than a parallel one.
The gate matches the three-part shape, and part 3 is what makes it a rule and
not noise:
1. a read of a registry still filling — the service registry during
init()/constructor, or an ADR-0018 open capability registry before its
seal;
2. a terminal conclusion drawn from "absent";
3. that conclusion recorded — cached in an instance field / module binding,
asserted in a warn, or persisted.
A read-only probe stays completely legal, and every cure passes untouched: a
probe deferred into a lazy accessor or a kernel:ready hook (nested bodies are
not descended into), a probe whose ordering an ADR-0116 declaration already
made final (dependencies / optionalDependencies / requiresServices — tolerance
lives in the plugin, never in a checker ledger), and a verdict drawn at a
declared seal (sealNodeTypeVocabulary). Rule B counts only registry
ENUMERATION, so a keyed has()/get() on a runtime path is not mistaken for a
boot-time membership verdict.
Proven in both directions, because a gate that has only ever been green cannot
be told apart from one that matches nothing (#4690):
f2eb850^ (both defects live) → 2 violations (auth-plugin, engine.ts)
25784cf^ (#4772 fixed only) → 1 violation (engine.ts)
main → clean, 47 seams seen, 41 read-only
Coverage is stated, not implied: it under-matches on purpose. #4769 is a
fixture, not a catch — its "registry" is the sys_migration table.
Claude-Session: https://claude.ai/code/session_018iARDqtrhQgz6fVHDeDkbQ
Co-authored-by: Claude <noreply@anthropic.com>
Tooling-only: `pnpm check:startup-registry-verdict` — startup registry reads may not record a verdict the boot can still contradict (#4777). Adds `scripts/check-startup-registry-verdict.mjs` + the shrink-only `scripts/startup-registry-verdict.baseline.json` (empty on landing), a `Lint & Type Check` step, and an AGENTS.md section. Releases nothing — no package changes.
5
+
6
+
One showcase cold start on 2026-08-03 produced three instances of one shape in three unrelated subsystems written by three people at three times: ask a registry "is X there?" while the boot is still filling it, treat the "no" as final, and **record** it — cached on the instance (#4772 plugin-auth), asserted in a `warn` (#4771 service-automation), or written to the database (#4769 objectql). The provider registers a moment later and nothing undoes the record. All three are fixed; this is what stops the class from coming back.
7
+
8
+
The gate matches the three-part shape, and part 3 is what makes it a rule rather than noise — a read-only probe stays completely legal, and the cures are never flagged: a probe deferred into a lazy accessor or a `kernel:ready` hook, a probe whose ordering an ADR-0116 declaration (`dependencies` / `optionalDependencies` / `requiresServices`) has already made final, and a verdict drawn at a declared seal (`sealNodeTypeVocabulary()`) all pass.
9
+
10
+
Its reach is stated rather than implied: it under-matches on purpose. `getService('cache')` is visible, a `resolveCacheOrFallback()` three layers down another package is not, and #4769 is invisible to it entirely — that "registry" is the `sys_migration` table in a database. This stops the bleeding; it does not cure. Whether the kernel contract should be tightened further is #4776.
0 commit comments