test(publish-smoke): judge the boot before the probes run - #16976
Conversation
The registry canary could not name a WARN-level boot failure. Two properties
of the server-log scan combined:
* SEVERITY - a plugin that fails to load logs at WARN, and the scan matched
error|fatal only.
* ORDER - the scan is the last thing in the script, after the probes, so
even at a matching severity a boot defect was reported as a probe failure
first.
Measured on the specimen (run 34084559243): the pre-fix pattern matches ZERO
lines in that boot window, after which the job probed every auth and CRUD
route against a server with no auth and failed on a probe, naming nothing.
A boot-load failure and an auth regression have different owners and produced
the same job output.
Adds a boot gate between sections 2 and 3 - the same shape the audience-posture
assertion already uses, which fails before the behaviour probes for the same
reason. Section 4 is NOT hoisted: it stays after the probes and keeps catching
what they provoke.
The predicate is severity-blind and keys on the sentence: a unit of the
composition did not arrive. Widening to WARN was rejected against a measured
healthy baseline - pack run 34276056630 boots healthily while emitting
`Console dist not found` behind the same warn glyph the specimen uses.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012GKcPZbMoGq7WPzKLfRBTU
…ontrol The pack-mode healthy fixture could not catch the mistake the predicate exists to avoid. Measured, not foreseen: under a deliberately wrong `WARN|warn` predicate the firing control stayed GREEN, because that fixture's only warn-shaped line carries the glyph and never the word. Registry mode installs the last published release, so a protocol-floor conversion warning is normal there and arrives as a full `<ISO>Z WARN ...` line. Asserting a healthy boot that spells WARN in full is what turns "do not widen the severity set wholesale" into something this file can redden on. The fixture is reconstructed rather than verbatim - the specimen's own boot window with the four lines attributable to the defect removed - and its docblock says so. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012GKcPZbMoGq7WPzKLfRBTU
📓 Docs Drift Check
What this run could not see
Coarse fallback — 131 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
ACCEPT in substance — PR #16976, reviewed against the tree, ⛔ not against the reportFlip + arm withheld until the sixteen running legs report. The ordering, verified from the CALL SITE
⇒
⭐ The predicate is not a severity rule, and that is the whole answerSeverity-blind, and stated as "a unit of the composition did not arrive" in two legs: the load site naming the unit (one alternative per real emit site in ⭐ Leg B is the part I would not have specified and it is the better half. It is by construction never benign: a core service that did get a fallback takes the sibling warn ⭐ And A1's tail guard — ⭐ The healthy baseline was measured, in TWO modes, and it disqualified both naive optionsI asked for the healthy-boot WARN baseline before the predicate was chosen. It came from real CI runs, not fixtures:
⇒ Wholesale-WARN reds a healthy boot in both modes. ⭐ And the sharper disqualification: the healthy pack-mode line carries the same warn glyph as the specimen, so the glyph is out too. A bare ⇒ Every cheap answer was excluded by measurement, which is the only way that exclusion is worth anything. ⭐ Two unexpected measurements, reported rather than smoothed over — the best thing in this report1. The WARN-wholesale ablation FAILED to red the firing control, the opposite of the prediction. Cause: the healthy pack fixture's only warn-shaped line uses the glyph and never the literal word, so it could not discriminate against a ⭐ That is the discipline turned on itself: a control that cannot fail on the mutation it exists to catch is decoration, and finding that out by running the ablation you expected to pass is exactly why ablations are run. 2. Mid-span and edge ANSI decoration are NOT equivalent. With decoration at the edges the unanchored pattern matches even unscrubbed ⇒ a decorated-line test built on that shape proves nothing about the scrubber. Only mid-span shows what scrubbing buys — and the measured answer is precise: unscrubbed, leg B still detects the failed boot but the plugin's NAME is lost; scrubbed, all three hits survive. ⇒ the scrubber buys attribution, which is this card's entire subject.
⭐ The process incident — read this one
Detected immediately (an anchor assertion found no ⭐ A restore-from-HEAD is only a restore if HEAD carries the thing being restored — and a blob-hash equality check does not notice, because it compares against the wrong reference by construction. That is a platform reading worth more than the card, and it was volunteered. File surface — one declared extension, accepted
Residuals, correctly named
Four gates NOT MEASURED, declared
Generated by Claude Code |
Part of #16793
The registry canary could not name a WARN-level boot failure. Two properties of the
server-log scan combined, and fixing either alone leaves the other:
error|fatalonly.matching severity a boot defect was reported as a probe failure first.
The cost is not a false green (CI went red either way) but ownership attribution: a
boot-load failure and a genuine auth regression are different owners and produced the
same job output.
Following the pattern this script already endorses
This is not a new idea in this file. ~140 lines below the boot, the audience-posture
assertion already refuses early, and its comment states this card's principle outright:
The new gate is the same refusal applied to the case that assertion missed, sited between
sections 2 and 3. ⛔ Section 4 was not hoisted — it stays after the probes and keeps
catching what they provoke; hoisting it would drop exactly that.
check:...-style pin:the
ORDERtest asserts gate before probes before section 4 by byte offset.The predicate, and the healthy baseline it was chosen against
⛔ Severity is deliberately not the predicate.
warnis where this repo puts functionaldegradation on purpose (AGENTS.md → Degradation log levels), so a healthy boot has
warn lines and a canary that reds on them stops being read.
Measured, not assumed — the warn-shaped lines a healthy boot emits:
34276056630(all auth+CRUD probes green,Plugins: 34 loaded)⚠ Console dist not found — install @object-ui/console …TIMESTAMP WARN [MetadataPlugin] artifact … predates this runtime's spec … ADR-0087 conversionThe first carries the same
⚠glyph as the specimen. So⚠,warn, and "a plugin wordappears" are all disqualified. So is a bare
failed to loadgrep — it matches the benigncontent-load degradations of plugins that did load (
SettingsServicePlugin: failed to load translations for 'fr',[platform-objects] failed to load … translations,Loader … failed to load TYPE:NAME).The predicate is a unit of the composition did not arrive, in two legs:
alternative per real emit site in
packages/cli/src/commands/serve.ts::3917(
AuthPlugin failed to load:, warn),:3958(Failed to load plugin:),:4338(
[Capability:CAP] failed to load). A1 carries a tail guard — "load" must not befollowed by another WORD — which is the whole difference from the benign family above.
packages/core/src/kernel.ts:354/:370).This is the answer to "the next boot defect will be worded differently": it never reads
the cause, so it fires whatever the load site said, or said nothing. By construction never
benign — a core service that did get a fallback takes the sibling warn
Service '…' not provided — using in-memory fallback, which the pattern does not match.What it would not have caught: a boot defect that costs no core service and whose load
site says nothing at all — leg B is keyed to the kernel's
corecriticality, so an optionalplugin failing silently still slips through. That is stated rather than papered over.
Before / after, with every control
Driven through the real gate block, extracted from the script by text marker:
OLD_PATTERN_HITS.⚠lines.WARNin full also passes. ⭐ This one wasadded because a measurement contradicted my expectation: under a deliberately wrong
WARN|warnpredicate the pack-mode firing control stayed green, since its only warn-shaped line uses the glyph
and never the word. Without this second fixture the file could not redden on the mistake it exists to prevent.
NO_COLORnote at:719-721): ANSI placed mid-span(
⚠ {bold}AuthPlugin{/bold} failed to load:), not at the edges — edge decoration leaves thespan contiguous and would prove nothing. Measured: unscrubbed the run still detects a failed
boot (leg B survives) but loses the plugin's name; scrubbed it keeps all three hits. That is
the measured reason the gate scrubs first rather than trusting
NO_COLOR.failed to loadfamily plus the in-memory-fallback warn → no match.Ablations (each mutation proven on disk by grepping the changed text, each restore proven by
blob hash and
git diff HEADempty):WARN|warnwholesaleAlso corrected
Section 4's comment asserted a premise that no longer holds alone — "the #3091 breakage …
would have been caught by ANY error-level line". True of #3091, which logged at error level;
the reason it did not generalise is this card's whole subject. Updated in place.
⛔ The
Failed to register OIDC discovery routesspecial case in the error pattern iskept — nothing here generalises it.
Not in this PR
Server is readyon a degraded boot (#16630), the declared-range half (#16634, onmain),the guidance half (#16500).
Verification
pnpm lint(whole repo,eslint . --no-inline-config) exit 0 · 68/68 derived gatefamilies run, 64 exit 0 and 4 exit 3 (
PREREQUISITE NOT MET— all four need a full closurebuild; read as NOT MEASURED, not green, not red) ·
dispatch-gates --ranreconciles68 derived / 68 run / 0 unrun ·
@objectstack/spectest:repo403 passed,test13098 passed,
typecheckexit 0 (coverage of the new file confirmed with--listFilesunder
tsconfig.scripts.json, since the roottsc --noEmitdoes not reachscripts/*.test.ts). All atf2af98a45a.⚠ The end-to-end
publish-smoke.shrun is not executed locally — it packs everypublishable package, installs from a registry and boots a server;
publish-smoke.ymlowns it.What is executed locally is the real gate block against real boot logs, above.
No changeset: measured with
npm pack --dry-run --jsoninpackages/spec— 276 publishedentries, none of this PR's paths among them (positive control: 207
README.md/*.zod.tsentries do ship);
scripts/publish-smoke.shsits under aprivate: trueroot.skip-changesetlabel applied.
🤖 Generated with Claude Code
Generated by Claude Code