Uh oh!
There was an error while loading. Please reload this page.
test(triggers,approvals): pin expected read-refusal noise instead of muting it - #11570
Conversation
…muting it The two SqlDriver-backed fixtures of #11081 blanket-silenced their kernel, so the 109 expected authz/organization read refusals they provoke were suppressed along with every unexpected frame, and nothing asserted the expected reads still happen. Both now carry `@objectstack/runtime`'s shared expected-noise capture (#10629 / #10630): it withholds only a line naming a declared table AND carrying that same table's `no such table` reason, forwards every other driver fault to the real console, and counts what it withheld so `afterAll` can assert each channel fired. `logger: { level: 'silent' }` stays (#10984) -- it is the key ObjectKernelConfig reads, and it is what keeps ~1000 INFO/WARN frames out of the shared shard log. The import escapes the package on purpose, so it is DECLARED rather than left for CI to find: one file (the helper imports nothing) in CROSS_PACKAGE_TEST_INPUTS plus a matching `#test` inputs entry in turbo.json for each package. trigger-record-change's test program needs `rootDir` widened as a consequence, the same shape plugin-approvals already records for #10101. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015ahemw8RcTgqtxrj15PEZx
📓 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. |
os-steve
commented
Aug 24, 2026
CI triage — the one red is not this PR's, and it is not simply "a flake" eitherDispatching PM seat (
Why "not this PR's" is a measurement and not a shrugThis diff touches two test fixtures, one
|
Uh oh!
There was an error while loading. Please reload this page.
Part of #11081
Verified at
e3c28458.What landed
The two SqlDriver-backed fixtures of the five now carry
@objectstack/runtime'sexpected-noise capture pin (#10629 / #10630) instead of relying on a blanket
mute:
packages/triggers/trigger-record-change/src/record-change-integration.test.tspackages/plugins/plugin-approvals/src/status-mirror-cascade.integration.test.tslogger: { level: 'silent' }stays (#10984 is not reverted) — it is the keyObjectKernelConfigactually reads, and it is what keeps ~1000 INFO/WARN framesout of the shared shard log. The capture is layered on top: it withholds only a
line naming a declared table and carrying that same table's
no such tablereason, forwards every other driver fault to the real console, counts what it
withheld, and asserts in
afterAllthat each channel fired.The card's central non-claim was "Nothing unexpected was silenced on the day",
resting on a frame table where both these fixtures go to 0 frames after
#10984. Measured on today's
origin/main, as-is, with no mutation:[sql-driver] DATABASE_ERROR … refused a read ononorigin/mainrecord-change-integration.test.tsstatus-mirror-cascade.integration.test.tsSqlDriverowns its ownlogger(a protected field with aconsoledefault),and the kernel's
logger: { level: 'silent' }never reaches it. So the driverchannel was never silenced at all — 109 refusal envelopes have been printing
into the shared shard log on
mainthis whole time. Only the engine channel(
ERROR Find operation failed) was silenced, and that half of the card's tableis correct.
Those 109 lines are the exact shape the helper's own header records as having
been "lifted VERBATIM into a p1 flake signature (#10293) and sent a whole
dispatch cycle at the wrong mechanism".
The pin works in BOTH directions (both demonstrated)
Every leg ran under
trap restore EXIT INT TERM, with the mutation proven ondisk by grepping the injected anchor and comparing
git hash-objectbefore andafter, and every restore proven byte-identical.
Half 2 — an expected refusal that stops being emitted REDs the test.
Suppressed exactly one recognised refusal (
sys_organization) before thecapture could see it. Result:
Test Files 1 failed (1), failing in theafterAllpin, with the diff naming both channels:Half 1 — an unexpected ERROR frame reaches the log. Injected a fault on a
declared table (
sys_user) carrying a reason that is notno such table,so the predicate must refuse to withhold it. Measured on the driver channel:
origin/main(blanket mute)The unexpected frame surfaces in both — but on
mainit arrives buried in 84expected lines, and with the pin it is the only thing on the channel.
⛔ Stated honestly: the first attempt at this control was invalid — it
injected before
registerDriver, where the driver's logger is still its ownconsoledefault, so the marker appeared in both arms and the comparison provednothing. Both arms above inject after
registerDriver. Finding that is whatturned up the falsified premise above.
⛔ Residual gap, not fixed here: on the engine channel an unexpected ERROR
is still invisible.
captureEngineforwards unrecognised frames to the engine'sown logger, which the kernel's
silentlevel drops. The pin's engine half buysthe
afterAllassertion, not loudness.Why only two of the five
Re-measured per fixture at
level: 'info'. The other three drive memory/fakedrivers, not
SqlDriver, so they emit norefused a read online and noFind operation failedframe —captureExpectedReadRefusalsrecognisesnothing in them:
record-change-integrationstatus-mirror-cascadebulk-write-per-row-contextformula-contextmultilookup-contextTheir entire ERROR surface is one boot-without-a-datasource trio (
sys_metadata could NOT be read at boot,[wait] suspended wait-timer re-arm ABORTED,[Automation] sys_automation_run could not be read at startup), which neitherof the helper's two predicates covers. Pinning it needs a new predicate on a
different seam — those frames come from the kernel logger, which is built in the
constructor and captured by reference by the plugin loader and the service
context, so a post-construction swap propagates only partially. A capture that
silently misses frames is the phantom-check failure mode, so it is left for a
decision rather than guessed at.
Declared, not left for CI to discover
Importing the helper across the package boundary is a cross-package test input.
Measured both options:
CROSS_PACKAGE_TEST_INPUTS+ 2#testinputsentries in
turbo.json. Precedent already in the repo:@objectstack/plugin-auth#testand
@objectstack/dogfood#testboth declarepackages/runtime/src/**.shared home plus devDeps in 3 packages.
Took declaring. The radius is the one file rather than
packages/runtime/src/**, because the helper imports nothing — that single pathis the whole escaping read.
Two consequences worth review:
roster, including three paths that pre-existing prose already named
(
scripts/slot-lookup-baseline.json,packages/core/src/kernel.ts, and thisgate's own path). They were invisible only because a package with no escaping
test is never rostered. Declared, per the gate's own doctrine that declaring a
mentioned file beats rewording prose to dodge the scanner.
trigger-record-change's test program neededrootDirwidened topackages/(TS6059 — enforced over every program file even under--noEmit).Same consequence-of-an-import that
plugin-approvalsalready records forPromote
resolveRecordOrganizationFieldto the shared platform-row resolver (approvals + automation runs), per the ruled cloud#1395 Option A #10101. Emit is unaffected: that config assertsnoEmit, and tsup builds fromtsconfig.jsonwhose entry issrc/index.tsalone. The config's own note wasrewritten rather than just its value — its old text argued rootDir should stay
./srcon a measurement this PR moved.Verification
All at
e3c28458.trigger-record-change78 → 78,plugin-approvals585 → 585,runtime2732 → 2732.plugin-approvals536 → 585,
runtime2692 → 2732,trigger-record-change78 unchanged.record-change-integration's own frame total moved 672 → 987.scripts/pm/dispatch-gates.mjs --repo, exitcodes captured before any pipe):
cross-package-test-inputs("OK: 16package(s) read outside themselves, all declared, and turbo.json hashes every
declared glob"),
entry-guard,parse-guard,pnpm-filter-targets,published-files,slot-lookup,test-source-alias,type-source-resolution,ci-filter-parity,plugin-teardown-shape,affected-docs,query-options-erasure,type-check-coverage,engine-double-contract,where-matcher,nul-bytes,i18n.check:i18nfirst returned PREREQUISITE NOT MET (CLI not built) — recordedas NOT MEASURED, not green; built
@objectstack/cliand re-ran to a real"OK (9 package(s) — all bundles in sync)".
check:type-check-debt --re-measureon the fully built closure: "32 ledgerentr(ies) re-measured, 1897 raw tsc error(s) total, none above its recorded
number."
pnpm lint(full repo,eslint . --no-inline-config): exit 0. No narrowing.skip-changeset: verified againstscripts/pr-labels.mjs's own rule —"
skip-changesetis the exemption for a PR that publishes nothing". This diffis two test files, a
noEmittest config, and repo tooling; no publisheddistchanges.
Follow-ups filed
captureEngine's pass-through lands in a silenced logger, so its documented "unrecognised frames still reach the log" does not hold under a silent kernel #11569 —captureEngine's pass-through lands in a silenced logger, so thehelper's documented "unrecognised frames still reach the log" holds on the
driver channel but not the engine one. Filed unassigned,
finding; it is theresidual gap noted above and it spans all 18 fixtures using the helper.
trio, which is why this is
Part ofand notFixes— [finding] Five fixtures now blanket-silence their kernel, hiding unexpected ERROR output — the expected-noise capture pin is the strictly better shape #11081 stays open forthat remainder and for the decision it needs.
Generated by Claude Code
Generated by Claude Code