test(publish-smoke): judge the boot by predicate and by name, and scan the probe window for error level - #17051
Conversation
…ow for error level The boot-window error-level scan failed a healthy release candidate: the better-auth oauth-provider seeder uses its UNIQUE constraint as its documented race-safety mechanism and catches the violation, but our query engine logs the exception at ERROR on the way out. Judge the boot by whether a unit of the composition arrived, plus the boot-time error signatures this gate asserts by name; report the rest. Section 4 now scans the probe window it was already documented to be about. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019wtfW1ZxGnP1XKGc9uZVms
…y boot, the named signature, and the slice Adds the ERROR-level counterpart to the WARN firing controls: a verbatim healthy boot window that carries an error-level line, the #3091 signature asserted by name, and a split log whose probe half is the only half section 4 reports — with a boundary control so the slice cannot pass vacuously. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019wtfW1ZxGnP1XKGc9uZVms
📓 Docs Drift CheckNothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs. What this run could not see
Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
Patrol reading: this PR's only red is not this PR's, and it has had no re-run in 9½ hours while
|
| PR | draft, last updated 04:43Z — 9½ h ago |
| CI | one failing check: Test Core (aggregate) via Test Core (6/6). Shards 1–5 green, Build Core, Dogfood ×3, Dogfood Verify CLI, Temporal Conformance, TypeScript Type Check all green; Check Changeset skipped under the skip-changeset label already applied |
Test Core is red on GitHub. Recording the distinction rather than the discrepancy: both statements are true about different things, and only the CI one gates the merge.
⭐ What failed, and why it is not yours
Failed: @objectstack/service-messaging#test
##[error]command (…/packages/services/service-messaging) pnpm run test exited (1)
Tasks: 40 successful, 44 total
This PR's diff is scripts/publish-smoke.sh plus packages/spec/scripts/publish-smoke-boot-failure.test.ts. It touches service-messaging zero times.
And the package has not moved since:
git diff --stat 513c495560 origin/main -- packages/services/service-messaging/ → EMPTY
control: main has moved 50 commits / 257 files / +27,400 −7,288 since that base
⇒ The failure was neither introduced by this diff nor fixed by a later one. Meanwhile PRs have kept landing through the merge queue all day — and the queue runs the full suite — so service-messaging is not persistently red on main.
⛔ I am not calling it a flake. "Flake" is not a root cause, and I have not run it. What is established is narrower and sufficient: the red is in a package this PR does not touch, on a 9½-hour-old run, against a base 50 commits behind. By the standing rule for a CI failure that is not the PR's, the next step is one re-run — and this PR has had none.
service-messaging is byte-identical between that base and today's main, so there is nothing newer to pick up. The cheap step is re-running the job.
Why this is worth interrupting for
publish-smoke / packed-tarballs has now failed six consecutive times on main — 12:15 · 12:25 · 13:06 · 13:32 · 13:46 · 13:57Z — unbroken since ~01:07Z, i.e. ~13 hours, across ≥12 distinct heads, still posting failure as a commit status. It blocks the release that is #16500's only open action, and the published on-ramp stays broken for new users meanwhile.
⇒ A finished, well-evidenced fix has been sitting in draft for 9½ hours behind a red that is not its own. ⭐ That gap — nobody re-ran it and nobody noticed — is the expensive part, more than either the boot-scan defect or the messaging test.
⛔ What I am NOT doing, and what I would do on request
⛔ I have not re-run the job, updated the branch, undrafted, armed auto-merge, or touched a label. os-bill holds #17027 and authored this; my standing note for this card is watch, do not take, and I am keeping it.
⇒ If the maintainer or os-bill wants it, the unblock looks like: re-run Test Core (6/6) → if green, undraft and land. I can do that immediately on a word. main (the body's measurements are from a base 50 commits back), and whether service-messaging has an open card of its own that this failure belongs to.
Generated by Claude Code
Fixes #17027
publish-smoke / packed-tarballshas been red onmainsince ~01:07Z, blocking the release that #16500 is waiting on. The boot-window gate added five hours earlier failed a healthy release candidate.What was measured, before anything was changed
1. The diagnosis in the card holds at
:879, and only there. Job102317840267of run34304339043: between== Checking the boot for a composition that did not loadand the##[error], the only output is one grep hit, and the failure text iserror-level log lines during BOOT, before any probe ran.smoke_boot_failure_lines(SMOKE_BOOT_FAILURE_PATTERN) matched nothing. The composition-arrival predicate was correct and passed; the blunt error-level scan beside it fired.2. The vendor docblock, re-read from the installed 1.7.2 tarball (
@better-auth/oauth-provider,dist/introspect-C6P1zrTr.mjs, overseedResources):The code matches the docblock: the
catchtests the message forunique|duplicate|UNIQUE, logs the collision at debug, andcontinues. Our query engine logs the same exception at ERROR on its way out, before that caller ever sees it.3. ⭐ The card's suggested route 1 was FALSIFIED — deleting or narrowing the boot gate alone does NOT unblock the release.
SMOKE_ERROR_LOG_PATTERNwas applied in two places: the boot window, and section 4's whole-log re-scan after the probes. The boot window is a prefix of that whole log, so the same line fires in both. Measured rather than argued — a local pack smoke with only the boot check neutered:Still red, just later and now blaming the probes. So the repair has to answer both windows.
4.⚠️ The probes DO pass. That run is also the answer to the question the card left NOT MEASURED. Every declared first-run assertion is green against the packed candidate: anonymous
get-session200,/auth/config200, seeded-admin sign-in 200, uninvited second sign-up refused 403, invite-member 200, invitee sign-up 200, sign-in 200, session 200, and REST create 201 / read 200 / update 200 / delete 200. The boot log readsPlugins: 34 loadedwithAuthin the roster. Run locally in pack mode against this branch, not inferred.The repair
The boot window is judged by predicate plus name, never by level; section 4 scans the window it was already documented to be about.
SMOKE_BOOT_FAILURE_PATTERN(:879) is untouched. It is the careful predicate and it was already correct.SMOKE_BOOT_ERROR_PATTERN— an allow-list of the boot-time error signatures this gate asserts by name, not a deny-list of specimens it excuses. One entry today:Failed to register OIDC discovery routes, the Fresh projects: every auth endpoint returns 500 "Cannot set properties of undefined (setting 'modelName')" — fixed in 15.1.1 #3091 signature this whole workflow exists for. ⭐ This is the class:882caught that:879misses: the composition arrived and then failed to publish part of its surface, so nofailed to loadleg matches, and every auth probe below would report the absence as a behaviour failure with a different owner. Proved still red by ablation, below.smoke_scrub_ansioutput of the same append-only$SERVER_LOGand the scrub is a per-line substitution, so line N of the boot snapshot is line N of the full scrub.awk 'END { print NR }'is used rather thanwc -lso a line the snapshot caught mid-write counts as looked-at.Nothing was added to an ignore list; no severity was widened to WARN.
Ablation — every specimen still reds, proved by mutation
Each case: mutate
scripts/publish-smoke.shon disk, prove the mutation landed by occurrence counts on the anchored text, run the real self-test, restore fromHEAD, prove the restore by blob hash and a cleangit status.AuthPlugin failed to load:SPECIMEN_FIRSTno longer containsAuthPlugin, hits 3 to 2Failed to load plugin:the other two load-failure sites, hits 2 to 1[Capability:cap] failed to load pkg:the #3091 signature still reds the boot, by NAMEAll five restores verified: on-disk blob equals the
HEADblob,git statusclean.Tests
packages/spec/scripts/publish-smoke-boot-failure.test.tsgains three fixtures and five assertions, all driven by sourcing the real script rather than grepping it:VENDOR_RACE_BOOT— the ERROR-level counterpart to the file's existing WARN firing controls: a verbatim healthy boot window that carries an error-level line. Asserted not-a-failed-boot, not-a-named-signature, and still matched by the general pattern, so "not fatal" reads as a decision about a matched line rather than a pattern that quietly stopped matching.OIDC_BOOT— both halves: the named pattern fires, the composition-arrival predicate does not.SPLIT_LOG— a log with error-level lines on both sides of the boundary, plus a boundary control at the end of the file with the opposite expectation, so the slice cannot pass vacuously.24 tests pass (this file plus its port-collision sibling).
Gates
node scripts/pm/dispatch-gates.mjs --commandsderived 69 families for these two paths; all 69 run with exit codes captured to disk before any pipe, all 69 exit 0, reconciled with--ran:69 derived, 69 run, 0 NOT-MEASURED, 0 UNRUN. Re-derived and re-run in full after mergingorigin/main(the first derivation printed aSTALE TREEbanner); the second derivation is byte-identical to the first and carries no banner.Two gates were
NOT MEASUREDon the first pass and are green on the second, neither for a reason in this diff:check-plugin-teardown-shape.mjs --self-testrefused to run on a shallow clone (fixed bygit fetch --unshallow), andcheck:type-check-debtexited 3 —PREREQUISITE NOT MET,@objectstack/spechad no built type entry point — which is neither a pass nor a finding.pnpm --filter @objectstack/spec typecheckgreen, test-typecheck ledger unchanged at 54 files / 261 errors.Lint, narrowed and proved narrow — at
e3c2add99: (1) population read from ESLint's own config, not guessed:eslint --print-configon the changed test file resolves 4 rules, so it is in the population; (2)--format json: 1 file linted, 0 errors, 0 warnings, exit 0; (3) invariance: this repo's singleeslint.config.mjsenables no type-aware linting for any file —parserOptions.projectandparserOptions.projectServiceare both null on this file, and the config states it repo-wide with its own positive control — so this diff cannot move the verdict on any untouched file. The other changed path is a shell script and is outside ESLint's population entirely.Changeset —
skip-changeset, measuredNothing published moves.
npm packof@objectstack/spec: 2073 entries, 0 underscripts/, 0 matchingpublish-smoke; positive control in the same listing, 218package/dist/and 17package/api-surface/entries, so the search works and the absence is real.@objectstack/spec'sfiles[]isdist,json-schema,liveness,prompts,llms.txt,README.md,src/**/*.zod.ts,CHANGELOG.md,api-surface,spec-changes.json— noscripts/. A walk of every non-private workspace manifest found no published package whosefiles[]names anyscripts/path, and repo-rootscripts/belongs to no package at all.Acceptance notes
Insert operation failedat ERROR inside a catch that rethrows — the case AGENTS.md names as "not a degradation at all" #17052: the root cause of the specimen line is ours, not the vendor's —packages/objectql/src/engine.tslogsInsert operation failedat ERROR inside acatchwhose next statement isthrow e. AGENTS.md's Degradation log levels section names that case explicitly: "a failure handed to the CALLER is not a degradation at all … Do not bolt alogger.erroronto such a site; declare how it delivers instead". Out of this card's file surface and it reverses nothing recorded — Undeclared fields still reach the driver: beforeInsert hooks run and an auto-number is consumed before the request is refused, and the whole INSERT with its values is logged at ERROR (17.0.0 GA) #8682 and An application told to rely on a unique index cannot recognise the violation: ObjectQL rethrows the raw driver error andisUniqueViolationErroris not reachable from an app #14095 decided the message content, never the level — so it is a card, not a rider.betterAuth():dist/authorize-BmTe2VYG.mjscallsseedResourcesdirectly at init, whiledist/introspect-C6P1zrTr.mjscallsseedResourcesOnce, whose coalescing is keyed per adapter. The eager path does not participate in that coalescing, so the two overlap and the UNIQUE constraint arbitrates — exactly the mechanism the docblock describes, one process instead of two. Successor: whoever reads this card next; there is no repo file to carry it.scripts/publish-smoke.shleaks one empty work dir.SMOKE_ROOTis assigned withmktemp -dat line 121, above the sourcing guard, whiletrap cleanup EXITsits below it — so the two self-tests, which source the script by design, each leave an empty$TMPDIR/objectstack-publish-smoke.XXXXXXbehind. Measured: 8 self-test runs in this session, 8 empty directories, removed. Harmless (4K, no contents) and outside this card, so it is a note rather than a card.packages/spec/dist/*.d.tsdisappeared at some point during the first local gate sweep, turningcheck:type-check-debtinto aPREREQUISITE NOT METexit 3. Cause not established — it did not reproduce on the second sweep — so this is an observation, not an attribution.Authored in Claude Code session
session_019wtfW1ZxGnP1XKGc9uZVms(durable attribution in prose: a REST PATCH of a PR body appends its own footer here, so this PR body deliberately sends none).Generated by Claude Code