Skip to content

test(objectql,verify,runtime): declare OS_REGISTRY_LOG=warn in each suite's own vitest harness - #14016

Merged
zhuangjianguo merged 2 commits into
mainfrom
claude/issue-13517-remaining-suite-log-levels
Sep 1, 2026
Merged

zhuangjianguo merged 2 commits into
mainfrom
claude/issue-13517-remaining-suite-log-levels

Conversation

@zhuangjianguo

Copy link
Copy Markdown
Collaborator

Part of #13517 — item 1 of the three-part remainder that card carries. It stays open: the packages/rest stack-dump residual and the deferred log-level ratchet are still on it, and the structured-logger half is #13986.

b79ddf17df quieted packages/qa/dogfood with one declarative OS_REGISTRY_LOG=warn in that suite's own vitest harness. This applies the same seam to the other three app-booting suites — packages/objectql, packages/verify, packages/runtime — each in its own config, each with its own measurement in the docblock.

Measured per suite, not inferred from dogfood

One full pnpm --filter PKG test per suite per side, all six runs through the shared verify lock. Baseline at origin/main b1b7d6088a; after-side at this branch's head 0fc8e11c18.

suite stdout lines [Registry] lines console-carried lines test outcome
objectql before 16,194 4,744 5,189 250 files / 4,322 tests passed
objectql after 11,502 65 510 250 files / 4,322 tests passed
verify before 5,670 2,323 2,551 9 files / 48 tests passed
verify after 3,347 0 228 9 files / 48 tests passed
runtime before 6,730 1,155 1,964 202 files / 3,011 tests passed
runtime after 5,584 9 818 202 files / 3,011 tests passed

"console-carried" excludes the structured logger's TIMESTAMP INFO ... lines, which never go through console and are a different question (#13986). Test outcomes are identical on both sides of every suite, and the non-[Registry] line counts are identical to the line — 445 / 228 / 809 before and after — so this key moved exactly the family it names and nothing else.

The zero in the verify row is a real reading, not an unfired grep: the same pattern on the same suite's baseline log counts 2,323, and grep -c "Test Files" on the after-side log answers 1.

Where the route does NOT do what dogfood did

⚠️ packages/runtime is not a second dogfood, and its docblock says so. [Registry] is 59% of that suite's console-carried output, not dogfood's 94.9%. The ~800 lines left are a mixed tail no log level reaches: [sql-driver] while creating/syncing table ... column reports, [HonoServerPlugin] Server stopped, Paged read of ... is NOT deterministic, [action-audit] ..., [Protocol] DB hydration skipped .... The declaration still earns its line there (1,155 lines removed), and it is also not the whole story there.

objectql (91.5%) and verify (91.3%) do behave like dogfood.

One repair the declaration made necessary, named here because it is a test edit

packages/objectql/src/registry-log-level.test.ts is the pin for how OS_REGISTRY_LOG resolves — so this package's harness key lands on that file's own subject. The file already deleted the variable in afterEach; the symmetric beforeEach was missing, so the FIRST case ran at warn under a name that says info, and stayed green, because both of its expectations are negative ("not called").

Measured, not reasoned. With a premise assertion added and the beforeEach withheld:

AssertionError: expected 'warn' to be 'info'
 Test Files  1 failed (1)
      Tests  1 failed | 6 passed (7)

With the beforeEach in place: 2 passed (2) / 19 passed (19) for that file plus registry-collision-order.test.ts. Both "default level" cases now assert the level they actually run at, so no future harness key can silently re-point them. No test was skipped, disabled or re-baselined; two assertions were added and one hook body was widened. No rebuild leg applies to that measurement — the file imports ./registry by relative path, so vitest transforms the source and no dist is in the path.

The near-miss, measured rather than trusted

registry-collision-order.test.ts asserts on [Registry] Collision lines. Those go through a bare console.warn the level never gates, and the file sets logLevel = 'silent' per registry anyway. Both sides pass identically, and the after-side logs still carry the collision lines — 16 in objectql, 2 in runtime. A real shadowing still speaks.

What this deliberately is not

The engine's shipped default is untouched — still 'info' at packages/objectql/src/registry.ts:1265 — and no library code learns what a test runner is. The request lives in each harness, declaratively, where the test author can see it. check-console-intercept-disarm.mjs is green: the disableConsoleIntercept line is untouched in all three configs and the new key sits beside it.

Verification

All gates run at 0fc8e11c18, exit codes captured before any pipe.

  • pnpm lint (repo-wide eslint . --no-inline-config) — exit 0, no narrowing claimed
  • pnpm check:nul-bytes — exit 0, 7667 text file(s) ... no raw ASCII control bytes
  • 26 of the 27 families named by node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack, plus check-console-intercept-disarm — all exit 0
  • pnpm --filter typecheck on all three packages — exit 0
  • NOT MEASURED here, owned by CI, all three exit 3 = PREREQUISITE NOT MET rather than a finding: check-test-completeness (wants a saved turbo run test log), check:dual-build-cjs-loads and check:type-check-debt (want the whole workspace built)
  • packages/objectql's tsc program excludes **/*.test.ts, so its green typecheck says nothing about the edited test file — verified with --listFiles (0 test files in the program, registry.ts present as the control). The edited file was type-checked directly instead, in a throwaway project over the package's own options: 0 errors, file present in the program.

Generated by Claude Code

claude added 2 commits August 31, 2026 23:31
…uite's own vitest harness

Measured per suite on origin/main b1b7d60, one full run each:

  objectql  16,194 stdout lines · 4,744 [Registry] · 10,984 structured-logger
  verify     5,670 stdout lines · 2,323 [Registry] ·  3,113 structured-logger
  runtime    6,730 stdout lines · 1,155 [Registry] ·  4,760 structured-logger

Against the console-carried population each suite emits (the structured
logger writes to process.stdout directly and is a separate question),
[Registry] is 91.5% in objectql, 91.3% in verify and 59.0% in runtime.

OS_REGISTRY_LOG is @objectstack/objectql's own published seam for that
verbosity (SchemaRegistryOptions.logLevel / REGISTRY_LOG_LEVELS). The
engine's shipped default stays 'info', and no library code learns what a
test runner is: the request lives in each harness, declaratively.

Claude-Session: https://claude.ai/code/session_01F3jdziLbAPGeceVNmSox5L

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… about

The package harness now declares OS_REGISTRY_LOG=warn for every worker, and
this file's subject IS that variable. Its `afterEach` already deleted the
var; the symmetric `beforeEach` was missing, so the FIRST case ran at 'warn'
under a name that says 'info' — and stayed green, because both of its
expectations are negative ("not called").

Measured rather than reasoned: with the premise assertion added and the
`beforeEach` withheld, the case fails with `expected 'warn' to be 'info'`.
Both "default level" cases now assert the level they run at, so a future
harness key cannot silently re-point them again.

Claude-Session: https://claude.ai/code/session_01F3jdziLbAPGeceVNmSox5L

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@claude claude Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Aug 31, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

⚠️ 3 changed file(s) yielded no anchor (packages/objectql/vitest.config.ts, packages/runtime/vitest.config.ts, packages/verify/vitest.config.ts), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files. Nothing else in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 3 changed package(s)).

What this run could not see
  • 3 changed file(s) yielded no anchor (packages/objectql/vitest.config.ts, packages/runtime/vitest.config.ts, packages/verify/vitest.config.ts) — pages documenting those are invisible to this run
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.

Coarse fallback — 33 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 62a137baecb75d03c028779ef5c2ed0eacad8399 → packageMentionDocs.

@github-actions github-actions Bot added the tests label Aug 31, 2026
@zhuangjianguo
zhuangjianguo marked this pull request as ready for review September 1, 2026 00:17
@zhuangjianguo
zhuangjianguo added this pull request to the merge queue Sep 1, 2026
Merged via the queue into main with commit 5e2c04d Sep 1, 2026
37 checks passed
@zhuangjianguo
zhuangjianguo deleted the claude/issue-13517-remaining-suite-log-levels branch September 1, 2026 00:48
baozhoutao pushed a commit that referenced this pull request Sep 4, 2026
`packages/rest` is the untouched CONTROL in
docs/audits/2026-09-test-log-volume-census.md: while PR #13985 and PR #14016
declared a registry log level in four harnesses, this suite got none, and the
audit measures 528 residual `[Registry]` lines here — eight times what declared
objectql still emits. Six test files in this package construct bare
`SchemaRegistry` instances, so the chatter is per registered item per case.

This declares the level in the harness only. objectql's shipped `'info'`
default is unchanged for every production reader, and no library code is made
aware of a test runner: `OS_REGISTRY_LOG` is the engine's own published seam
(`SchemaRegistryOptions.logLevel` / `REGISTRY_LOG_LEVELS`).

The ADR-0005 `[Registry] Collision` diagnostics ride a bare `console.warn` that
the level never gates, so a real shadowing still speaks here.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
baozhoutao pushed a commit that referenced this pull request Sep 4, 2026
`packages-write-envelope.test.ts` constructs bare `SchemaRegistry` instances
per case and installs a package manifest into them, so this suite pays a
`[Registry] Registered …` line per registered item at the engine's shipped
`'info'` default.

Harness-only, the same shape PR #14016 landed for three other suites:
objectql's shipped default stays `'info'` for every production reader, and no
library code learns it is under a test runner. `OS_REGISTRY_LOG` is the
engine's own published seam.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
baozhoutao pushed a commit that referenced this pull request Sep 4, 2026
…ting suites

objectql's `SchemaRegistry` logs one `[Registry] Registered <kind>: <name>`
line per registered item per construction, at its shipped `'info'` default. A
suite that boots app stacks pays items x boots of that on a CI shard log nobody
reads. PR #13985 and PR #14016 declared `OS_REGISTRY_LOG` in four harnesses and
removed ~47,900 console-carried lines — and nothing held them there. Deleting
one `env` line restored five figures of output while every assertion stayed
green and every outcome was unchanged.

This gate asserts the declaration. It reuses `check-console-intercept-disarm`'s
exported `workspacePackageDirs` walk and its verdict format, so only the
assertion and the population are new.

THE POPULATION IS DERIVED, not a roster. A vitest-running package is selected
when its OWN TEST SOURCES construct a `SchemaRegistry`, boot a stack through
`@objectstack/verify`'s `bootStack`, or import an `@objectstack/example-*` app.
On this tree that selects 8 of 72 with zero over- and zero under-selection.

A roster of the four suites that already declared would have been a hand list
this repo could show to be wrong on the day it shipped:
docs/audits/2026-09-test-log-volume-census.md measures `packages/rest` — its
own named control — at 528 residual `[Registry]` lines, eight times declared
objectql's 66. The four packages the predicate newly selects adopt the
declaration in the four commits preceding this one.

Comment masking is what makes the predicate honest rather than merely
plausible: `packages/cli` names `bootStack` and `@objectstack/verify` in eight
places, all of them prose, and would otherwise be selected while booting no
stack in any test. The registry-construction signal additionally masks string
and template content, so a spelling inside a literal is never the setting.

The level vocabulary is READ from objectql's own `REGISTRY_LOG_LEVELS` rather
than copied, because `registry.ts` resolves an unrecognised value to the
`'info'` DEFAULT silently — `OS_REGISTRY_LOG: 'quiet'` would read as a
considered choice and quiet nothing.

Out of scope and untouched: which level any suite picks, objectql's shipped
`'info'` default, and any library awareness of a test runner.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Sep 9, 2026
…t, not ~45% (objectstack-ai#14989)

* wip(qa): log-volume census instrument

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68

* wip(qa): log-volume census checkpoint — 32/72 packages measured

Extends Batch 1's ledger (23 packages, driven under the shared verify
lock) with 9 more: driver-sqlite-wasm, driver-turso, formula, lint,
mcp, metadata, metadata-core, metadata-fs, metadata-protocol.

Also: end-to-end control for the OS_LOG_LEVEL premise re-verification
(Zone 2 D) — resolveLogLevel() confirmed sensitive to its input, and a
repo-wide grep confirms it is read nowhere outside packages/cli (one
non-hit is a self-test fixture string in dispatch-gates.mjs).

Doc's method/mechanism/reproduction/premise sections carried over from
a prior attempt's draft, independently re-verified against source
(packages/core/src/logger.ts, packages/verify/src/harness.ts) before
being kept — every file:line citation checked out exactly.

Provisional structured share (console+structured) at 32/72: ~84%,
already far from the five-suite ~45%, in the direction the earlier
reading's own explanation predicts. Not the final number — continuing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68

* wip(qa): log-volume census checkpoint — 45/72 packages measured

+13 packages this batch: observability, platform-objects,
embedder-openai, knowledge-memory, knowledge-ragflow,
plugin-approvals, plugin-audit, plugin-auth, plugin-dev, plugin-email,
plugin-hono-server, plugin-pinyin-search, plugin-reports.

plugin-auth is the first non-trivial plugins/ package: 4,840 lines
(2,149 structured / 2,678 console) — most plugins so far are near-
silent (13 reporter lines only, no kernel boot in their own test
script).

Provisional structured share (console+structured) at 45/72: ~80%.
27 remain, all services/*, triggers/*, spec, sdui-parser, and the
qa/http-conformance + qa/downstream-contract pair.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68

* wip(qa): log-volume census checkpoint — 55/72 packages measured

+10 packages this batch: plugin-security, plugin-sharing,
plugin-webhooks, downstream-contract, http-conformance, sdui-parser,
service-analytics, service-automation, service-cache, service-cluster.

17 remain: service-cluster-redis, service-datasource, service-i18n,
service-job, service-knowledge, service-messaging, service-package,
service-queue, service-realtime, service-settings, service-sms,
service-storage, spec, trigger-api, trigger-record-change,
trigger-schedule, types.

Provisional structured share (console+structured) at 55/72: ~79%,
holding steady across three checkpoints now (84% -> 80% -> 79%).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68

* wip(qa): log-volume census checkpoint — 68/72 packages measured

+13 packages this batch: service-cluster-redis, service-datasource,
service-i18n, service-job, service-knowledge, service-messaging,
service-package, service-queue, service-realtime, service-settings,
service-sms, service-storage, spec.

4 remain: trigger-api, trigger-record-change, trigger-schedule, types.

packages/spec measured read-only (its own `test` script run and
stdout captured, nothing edited under it — domain:spec's package
stays untouched); 481s of the 480s budget, exit 0.

Provisional structured share (console+structured) at 68/72: ~78%.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68

* docs(qa): finalize log-volume census — 72/72 packages, ratio does not hold

All 72 workspace packages with a test script measured, all green.
Final totals: 61,980 structured / 17,428 console / 993 reporter /
80,401 total lines — structured share of total 77.1% (comparable to
the earlier five-suite framing, whose own `console` bucket absorbed
what this instrument tracks separately as `reporter`).

The five-suite ~45% figure does not hold, and not toward more noise:
it moved to 77.1% structured, decomposed in "The answer" section as
two effects — (1) two commits (objectstack-ai#13985, objectstack-ai#14016) that landed on main
between the earlier reading and this one already took the original
five suites from ~45% to 86.6% structured on their own, by cutting a
`[Registry]` debug-console population; (2) extending to the other 67
packages pulls that back down to 77.1% (not further), since that
population's own structured share (57.7%) is lower than the five
heaviest suites' but is also a minority (30.3%) of total test-run
volume, and most of it (35/72 packages under 30 lines total, 22 of
those exactly 13 -- pure reporter boilerplate) never boots a kernel at
all.

No seam added -- per triage's ruling (comment 5489397004), this
document is the measurement; which seam (if either) to build is
triage's call.

Merged origin/main (dispatch-gates warned STALE TREE, 19 commits
behind) -- no relevant file (logger.ts, harness.ts, log-level.ts,
vitest configs, package.json test scripts) changed across that range,
so the merge does not invalidate any measurement already taken.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68

* docs(qa): note 85 direct new ObjectKernel() call sites, not just harness.ts

Relevant to the fork this card hands back to triage: a BootOptions
field on packages/verify's harness would only quiet suites that boot
through that harness, not the ~60 other files (85 call sites) that
construct a kernel directly -- including packages/objectql's own
kernel-factory.ts, which alone accounts for 18.3% of the structured
lines measured. Does not choose a seam; changes what each seam would
cost to actually reach the population it's meant to quiet.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68

* docs(qa): fix three citation defects in the log-volume census

Review found three citation defects in
docs/audits/2026-09-test-log-volume-census.md — the measurement itself
(72-row table, arithmetic) was independently reproduced and is untouched.

1. `new ObjectKernel(` repo-wide count: re-ran the exact grep command on
   this branch merged with origin/main and got 78 occurrences across 55
   files, not 85/62. Corrected the number and the two downstream figures
   that depend on it (~53 remaining call sites, "all 78 call sites"),
   and stamped the ref it was verified against so a future drift is
   reproducible instead of silent.
2. `scripts/pm/dispatch-gates.mjs:14461` is blank on this tree; the real
   self-test-fixture line is 14478. Corrected and ref-stamped (this file
   is edited often).
3. `packages/core/src/logger.ts:350-395` — the quoted block actually
   starts at 349, not 350 (content verbatim-correct, only the start line
   was off by one; end line shifts by the same one to 394).

Re-resolved the other eight citations the reviewer already checked
(logger.ts:180/236, harness.ts:96-313/384, kernel.ts:87,
log-level.ts:53, kernel-factory.ts:35, and the 72/72
disableConsoleIntercept:true claim) against this branch's merged tree —
none of them moved.

Part of objectstack-ai#13986

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68

* docs(qa): bump verified-at ref stamps to the post-second-merge tree

origin/main moved again (99b4deb) between the first fix commit and the
gate sweep. Re-verified all three corrected citations plus the eight
already-checked ones against that tree — nothing moved — and updated the
inline ref stamps from 48d4422 to 0de50b8 (this branch's HEAD after
merging origin/main a second time) so they point at the tree the numbers
were actually last confirmed on.

Part of objectstack-ai#13986

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0112hMx9hjJ9BgB28X97DS68

---------

Co-authored-by: Claude <noreply@anthropic.com>
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Sep 9, 2026
…bjectstack-ai#15559)

* test(rest): declare OS_REGISTRY_LOG in the vitest harness

`packages/rest` is the untouched CONTROL in
docs/audits/2026-09-test-log-volume-census.md: while PR objectstack-ai#13985 and PR objectstack-ai#14016
declared a registry log level in four harnesses, this suite got none, and the
audit measures 528 residual `[Registry]` lines here — eight times what declared
objectql still emits. Six test files in this package construct bare
`SchemaRegistry` instances, so the chatter is per registered item per case.

This declares the level in the harness only. objectql's shipped `'info'`
default is unchanged for every production reader, and no library code is made
aware of a test runner: `OS_REGISTRY_LOG` is the engine's own published seam
(`SchemaRegistryOptions.logLevel` / `REGISTRY_LOG_LEVELS`).

The ADR-0005 `[Registry] Collision` diagnostics ride a bare `console.warn` that
the level never gates, so a real shadowing still speaks here.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk

* test(client): declare OS_REGISTRY_LOG in the vitest harness

`packages-write-envelope.test.ts` constructs bare `SchemaRegistry` instances
per case and installs a package manifest into them, so this suite pays a
`[Registry] Registered …` line per registered item at the engine's shipped
`'info'` default.

Harness-only, the same shape PR objectstack-ai#14016 landed for three other suites:
objectql's shipped default stays `'info'` for every production reader, and no
library code learns it is under a test runner. `OS_REGISTRY_LOG` is the
engine's own published seam.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk

* test(service-automation): declare OS_REGISTRY_LOG in the vitest harness

`connector-reload-reingest.test.ts` and `flow-name-shadowing.test.ts`
construct bare `SchemaRegistry` instances and register connectors and flows
into them per case, so the registration chatter is per item per case at the
engine's shipped `'info'` default.

`flow-name-shadowing.test.ts` asserts on shadowing warnings, which ride a bare
`console.warn` this level never gates — the suite is measured green with the
declaration in place. Harness-only: objectql's shipped default is untouched.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk

* test(app-showcase): declare OS_REGISTRY_LOG in the vitest harness

This config's own `disableConsoleIntercept` docblock deferred the question in
as many words: "most of it `[Registry]` registration chatter. Quieting THAT is
a separate question about `@objectstack/objectql`'s own default log level, not
about this setting."

This answers it the way the four earlier harnesses did — the level is declared
HERE, in the harness, through the engine's own `OS_REGISTRY_LOG` seam.
`gap-fill.test.ts` constructs the registry it reaches. objectql's shipped
`'info'` default is unchanged for every production reader.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk

* feat(devx): ratchet the declared registry log level across engine-booting suites

objectql's `SchemaRegistry` logs one `[Registry] Registered <kind>: <name>`
line per registered item per construction, at its shipped `'info'` default. A
suite that boots app stacks pays items x boots of that on a CI shard log nobody
reads. PR objectstack-ai#13985 and PR objectstack-ai#14016 declared `OS_REGISTRY_LOG` in four harnesses and
removed ~47,900 console-carried lines — and nothing held them there. Deleting
one `env` line restored five figures of output while every assertion stayed
green and every outcome was unchanged.

This gate asserts the declaration. It reuses `check-console-intercept-disarm`'s
exported `workspacePackageDirs` walk and its verdict format, so only the
assertion and the population are new.

THE POPULATION IS DERIVED, not a roster. A vitest-running package is selected
when its OWN TEST SOURCES construct a `SchemaRegistry`, boot a stack through
`@objectstack/verify`'s `bootStack`, or import an `@objectstack/example-*` app.
On this tree that selects 8 of 72 with zero over- and zero under-selection.

A roster of the four suites that already declared would have been a hand list
this repo could show to be wrong on the day it shipped:
docs/audits/2026-09-test-log-volume-census.md measures `packages/rest` — its
own named control — at 528 residual `[Registry]` lines, eight times declared
objectql's 66. The four packages the predicate newly selects adopt the
declaration in the four commits preceding this one.

Comment masking is what makes the predicate honest rather than merely
plausible: `packages/cli` names `bootStack` and `@objectstack/verify` in eight
places, all of them prose, and would otherwise be selected while booting no
stack in any test. The registry-construction signal additionally masks string
and template content, so a spelling inside a literal is never the setting.

The level vocabulary is READ from objectql's own `REGISTRY_LOG_LEVELS` rather
than copied, because `registry.ts` resolves an unrecognised value to the
`'info'` DEFAULT silently — `OS_REGISTRY_LOG: 'quiet'` would read as a
considered choice and quiet nothing.

Out of scope and untouched: which level any suite picks, objectql's shipped
`'info'` default, and any library awareness of a test runner.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk

---------

Co-authored-by: Claude <noreply@anthropic.com>
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Oct 7, 2026
…es' files outside src to the commits that decided them (objectstack-ai#20923)

Part of objectstack-ai#20594
Clause-②: no

## What changed

This is stage 16 of the `domain:cli` lane's dead-citation sweep: **the
17 comment sites left in eleven lane packages' files outside `src/**`**
(claim `5917064266`; the list on stage 15's landing `5916232164`). The
file surface is the one stage 14 set: `README.md`, `tsconfig*.json`,
`vitest.config.*`, `tsup.config.*` and `test/**`.

Every comment site on that surface whose tracker number answers 404 now
cites the commit that decided what the line describes, in ruling C+D's
form C (comment `5749154545` on objectstack-ai#19123). Stages 1 to 15 of this card are
the precedents; the latest are PR objectstack-ai#20883 and PR objectstack-ai#20898.

- **17 sites on 16 lines in 14 files**, covering **9 numbers**, now cite
**9 distinct commits**.
- The 14 files: 5 JSONC configs (`tsconfig.test.json` in
plugin-hono-server, plugin-dev and verify; plugin-hono-server's
`tsconfig.typecheck.json`; client's `tsconfig.json`), 6
`vitest.config.ts` (client, cloud-connection, mcp, rest, runtime, types)
and 3 test files (`qa/vitest-filter-preflight` 2,
`qa/downstream-contract` 1).
- **Comments only.** 16 lines out and 16 in, and every file keeps its
line count. A token guard (below) shows zero non-comment tokens changed.
- **String literals, `describe` / `it` titles and messages are
untouched** (they belong to objectstack-ai#20752, fold `5911936313`).
- **No tracker number is added.** The live numbers that share a changed
line stay as they were: objectstack-ai#4914, objectstack-ai#12542 and objectstack-ai#17978 all answer 200.
- **Sites left without a deciding commit: none.**
- Where an earlier stage anchored a number and the line here describes
the same decision, the same anchor is reused: 6 of the 9 numbers. The
other 3 anchors are new (marked below).

## Census

**Instrument.** The card's gate does not read these files (its declared
surface is `packages/**/src/**`), so the census is taken by hand with
the gate's own grammar, as stages 14 and 15 took it:

- **Files:** every tracked file of the eleven packages outside `src/**`,
with `CHANGELOG.md` left out: 81 files. Each is classed ON stage 14's
file list (48 files) or OFF it (33: `package.json`, `LICENSE`, ledgers,
`objectstack.config.ts` and the like). Only ON-list comment sites are
this stage's.
- **Extraction:** `extractCitations` from
`scripts/check-issue-citations.mjs`, with its comment-prose projection
for code and JSONC files and the whole file for `*.md`. The whole-file
extraction minus the comment projection gives the string sites.
- **Numbers kept:** only those naming this repository
(`namesThisRepository`).
- **Probe:** each distinct number, `GET
/repos/objectstack-ai/objectstack/issues/N`; 404 means dead.

| | tree | probe window (UTC) | numbers | answer 200 | answer 404 | dead
comment sites, on-list | comment sites | dead comment sites, off-list |
dead string sites |
|---|---|---|---|---|---|---|---|---|---|
| before | base `cb4c31dd52` | 2026-09-30 18:18:37 to 18:19:15 | 94 | 80
| 14 | **17** (9 numbers, 14 files) | 212 | 2 | 11 |
| after | head `1e3782200f` | 2026-09-30 18:23:26 to 18:24:03 | 88 | 80
| 8 | **0** | 195 | 2 | 11 |

- The before count matches the list on stage 15's landing, package by
package.
- No number present in both probes changed its answer. The 6 numbers
that left the census (objectstack-ai#8651, objectstack-ai#10485, objectstack-ai#12181, objectstack-ai#13176, objectstack-ai#15145, objectstack-ai#16917)
were only on the rewritten lines.
- Comment sites fell by exactly 17. The off-list and string counts did
not move.

**Per package, dead on-list comment sites, before to after:**

| package | before | after |
|---|---|---|
| `packages/plugins/plugin-hono-server` | 4 | 0 |
| `packages/plugins/plugin-dev` | 2 | 0 |
| `packages/client` | 2 | 0 |
| `packages/qa/vitest-filter-preflight` | 2 | 0 |
| `packages/cloud-connection` | 1 | 0 |
| `packages/mcp` | 1 | 0 |
| `packages/qa/downstream-contract` | 1 | 0 |
| `packages/rest` | 1 | 0 |
| `packages/runtime` | 1 | 0 |
| `packages/types` | 1 | 0 |
| `packages/verify` | 1 | 0 |
| **total** | **17** | **0** |

## Per-number anchors

Each anchor was checked by blame on the site and in the anchor's own
message or diff. "Reused" names earlier stages that gave the number the
same anchor.

| number | sites | anchor | what it decided | |
|---|---|---|---|---|
| `objectstack-ai#13176` | 4: plugin-hono-server and plugin-dev `tsconfig.test.json`
(:3 and :61 / :56) | `a68c61267` | plugin-security's test layer enters
tsc under a sibling `tsconfig.test.json` at zero residue, with no
`test-typecheck-debt.json`; its diff writes the number into that
config's header and into the TEST_DEBT graduation | reused
(plugin-security) |
| `objectstack-ai#11332` | 1: plugin-hono-server `tsconfig.typecheck.json:12` |
`dce5cd4f0` | retires the manifest's `capabilities` / `configuration` /
`extensions` containers as `retiredKey()` tombstones (ADR-0049); its
changeset names the number | reused (spec) |
| `objectstack-ai#10724` | 1: the same line | `be21955ba` | retires the nine dead
`contributes` members as `retiredKey()` tombstones (ADR-0049); its
subject names the number | reused (spec) |
| `objectstack-ai#12181` | 2: client `tsconfig.json:8`, `vitest.config.ts:33` |
`cf71d73f8` | `meta.deleteItem`'s reset carriers; this same commit wrote
both blocks (the `paths` rules and the alias for the real-door test),
and its changeset names the number | reused (client, cli) |
| `objectstack-ai#17853` | 5: vitest-filter-preflight's two test headers, rest /
runtime / types `vitest.config.ts` | `08f5f0e5a` | a vitest filter that
selects no test file says so; its message names the card it lands. The
sentence in the three configs is the one stage 14 and stage 15 rewrote
in cli's and dogfood's | reused (qa, cli, dogfood) |
| `objectstack-ai#16917` | 1: cloud-connection `vitest.config.ts:64` | `7ce3154e6` |
the comment-only repair of this file, which wrote the "paraphrased
rather than quoted" sentence; its message names the card it lands |
**new** |
| `objectstack-ai#8651` | 1: mcp `vitest.config.ts:18` | `8c65046e4` | pins mcp's
three engine doubles to metadata-core's dispatch predicates, adds that
devDependency and creates this config for the alias; its message names
the card it lands | **new** |
| `objectstack-ai#10485` | 1: downstream-contract `test/contract.test.ts:46` |
`35ad101bc` | retires `ThemeSchema` and the `themes` carrier key
(ADR-0049, kept beside it); its subject names the number, and it wrote
this line | reused (spec, qa, cli) |
| `objectstack-ai#15145` | 1: verify `tsconfig.test.json:1` | `45a72b0cc` | wires
verify's test layer into `typecheck` through this file; its diff writes
the number into this line and into the coverage-ledger graduation |
**new** |

**ADR and ruling records.** A grep of `docs/adr` and
`scripts/adr-anchors` for the 9 numbers finds one hit: ADR-0088 names
objectstack-ai#10724 in a correction note (history, not the ruling), so that number
stays on the commit every earlier stage anchored it to. The sentence it
sits in already names ADR-0049. The control number `7329` finds 1 file
in the same tree.

**Anchor checks:**
- **Each sha is unambiguous:** `git rev-parse --disambiguate` gives
count 1 for each of the 9.
- **Each is a plain commit** with one parent.
- **Each is on the base:** `merge-base --is-ancestor` against
`cb4c31dd52` exits 0 for all 9.
- **The history is complete:** the checkout is not shallow. Control leg:
`01218124ae`, the parent of the oldest anchor `8c65046e4` (2026-08-16),
exits 0. Negative control: the base as an ancestor of `8c65046e4` exits
1.

## Verification

All at head `1e3782200f`. Heavy runs went through
`scripts/pm/os-verify-lock.sh` with
`OS_VERIFY_LOCK_SLOT=issue-20594-outside`.

- **Build (whole workspace):** `pnpm exec turbo run build
--filter='./packages/*' --filter='./packages/*/*' --concurrency=2` → 71
successful, 71 total (9 cached), lock verdict command-exit 0.
- **Typecheck, ten packages** (cloud-connection declares no `typecheck`
script): `pnpm --workspace-concurrency=2 --filter` plugin-hono-server,
plugin-dev, client, vitest-filter-preflight, mcp, downstream-contract,
rest, runtime, types, verify `run typecheck` → 10 of 10 `Done`, 0 `error
TS`, lock verdict command-exit 0. That reads every touched JSONC config
(plugin-hono-server's runs `tsconfig.typecheck.json` by name; the
`tsconfig.test.json` files are read by `check:test-typecheck`, all at
their recorded ledgers). `--listFilesOnly` holds all 3 touched test
files in their packages' programs.
- **Tests, by name** (one lock call, verdict command-exit 0). Each
touched test file ran, and each touched `vitest.config.ts` was loaded by
a run of its own package:
- vitest-filter-preflight: `test/config-wiring-sweep.test.ts`,
`test/filter-preflight.test.ts` → 2 files, 97 tests passed.
- downstream-contract: `test/contract.test.ts` → 1 file, 13 tests
passed.
- client: `src/meta-delete-item-carriers.test.ts` (the suite the edited
alias block serves) → 20 passed.
- cloud-connection: `src/canonical-expression-envelopes.test.ts` (the
suite the alias exists for) → 16 passed.
- mcp: `src/mcp-stdio-tools.test.ts` (the engine doubles the edited
block describes) → 12 passed.
- rest, runtime, types (`--project local`):
`src/rest-exec-ctx-memo.test.ts` 4 passed,
`src/app-plugin.ordering.test.ts` 3 passed, `src/email-verified.test.ts`
2 passed.
- **Token guard**, base `cb4c31dd52` against head, 14 files, 5,764 base
tokens: **0 files differ**. TypeScript files are compared as leaf tokens
(`getChildren`, JSDoc nodes skipped), JSONC files as the scanner's
non-trivia token stream plus their parsed value (0 of 5 values differ).
Controls, in memory only: a comment inserted into each file, 0 of 14
differ; a statement appended, 14 of 14; one character flipped inside
each file's first string token, 14 of 14 (9 `StringLiteral`, 5 JSON
strings).
- **Control bytes:** a scan of the 14 files finds 0 (positive control, a
scratch file holding U+0001: 1). `pnpm check:nul-bytes` exits 0.
- **Nothing publishes.** `npm pack --dry-run` in each of the 9 public
packages packs only `dist/**`, `README.md`, `CHANGELOG.md`, `LICENSE`
and `package.json`: 0 of the 11 touched files in those packages is
packed. After the build, the first 48 characters of each of the 16 added
comment lines occur in 0 files of any package's `dist/`; control: a
`src` docblock phrase an earlier stage wrote ("Maintainer-seat ruling,
landed by commit cf71d73") occurs in
`packages/client/dist/index.d.ts`. The other two packages are private.

## Gates

All at head `1e3782200f`, exit codes captured before any pipe.

- **Derivation:** `node scripts/pm/dispatch-gates.mjs --repo
objectstack-ai/objectstack --commands`, no paths, derives **52
commands** (14 paths against merge base `cb4c31dd52`). Re-derived after
fetching `origin/main` to `4d0b9cd542`: the same 52, and none of the 4
upstream commits touches a derivation input or a file here.
- **All 52 exit 0**, each on its first run.
- **Reconciliation:** `dispatch-gates --ran` over the recorded `COMMAND
:: exit CODE` list → "52 derived, 52 run, 0 NOT-MEASURED, 0 UNRUN", exit
0.
- **Roster gates the derivation marks as keeping a roster under
`packages/`:** `pnpm check:authz-resolver`, `pnpm
check:error-code-casing` and `pnpm check:filter-alias-parity` → exit 0
each.
- **`pnpm lint`** (repo-wide `eslint . --no-inline-config`, the family
the derivation does not name) → exit 0, 2026-09-30T18:26:35Z to
18:30:31Z.
- `node scripts/check-issue-citations.mjs` (diff mode, in the 52) reads
0 files, because none of these paths is on its declared surface; the
hand census above is the measurement for this surface.
- A local `git merge-tree --write-tree` of this head against
`origin/main` `4d0b9cd542` is clean.

**The 52 derived commands:** stage 15's list with `pnpm --filter
@objectstack/spec run check:skill-examples` and `node
scripts/check-tenant-audit-census.mjs` (with its `--self-test`) in, and
`check:empty-state`, `check:liveness`, `check:strictness-ledger` and
`check:variant-docs` (spec) out:

- `node scripts/check-ci-filter-parity.mjs`
- `node scripts/check-closing-keyword-parity.mjs` and `--self-test`
- `node scripts/check-comment-mask-adoption.mjs` and `--self-test`
- `node scripts/check-comment-mask-corpus.mjs`
- `node scripts/check-issue-citations.mjs`
- `node scripts/check-keyed-text-bounds.mjs` and `--self-test`
- `node scripts/check-platform-object-tenancy-census.mjs` and
`--self-test`
- `node scripts/check-plugin-teardown-shape.mjs` and `--self-test`
- `node scripts/check-registry-log-declared.mjs` and `--self-test`
- `node scripts/check-rest-log-spy-declared.mjs` and `--self-test`
- `node scripts/check-system-context-census.mjs` and `--self-test`
- `node scripts/check-tenant-audit-census.mjs` and `--self-test`
- `node scripts/check-undeclared-dep-imports.mjs` and `--self-test`
- `node scripts/docs-audit/check-affected-docs.mjs`
- `node scripts/docs-audit/check-drift-comment.mjs`
- `pnpm --filter @objectstack/spec run check:skill-examples`
- `pnpm check:cross-package-test-inputs`,
`check:dispatcher-error-vocabulary`, `check:doc-authoring`,
`check:driver-memory-census`, `check:dts-closure`,
`check:dual-build-cjs-loads`, `check:engine-double-contract`,
`check:gitlink-declared`, `check:issue-citations`,
`check:lean-entry-closure`, `check:logger-receiver-detach`,
`check:nul-bytes`, `check:objectql-double-limit`,
`check:org-identifier`, `check:page-declaration-shape`,
`check:published-files`, `check:query-options-erasure`,
`check:refd-timer-probe`, `check:slot-lookup`,
`check:sourcemap-no-sources-content`, `check:test-source-alias`,
`check:tier-file-adoption`, `check:type-check-coverage`,
`check:type-check-debt`, `check:watch-hint-literal`,
`check:where-matcher`

## Acceptance notes

- **Changeset:** none. Nine of the eleven packages publish, but no
touched file is in any package's `files` (measured above), and
`qa/vitest-filter-preflight` and `qa/downstream-contract` are private.
The PR carries `skip-changeset`.
- **Left in these eleven packages, not this stage's:** 2 dead comment
sites off stage 14's file list, in plugin-hono-server's
`objectstack.config.ts` (:19 objectstack-ai#11332, :26 objectstack-ai#10724), and 11 dead string
sites: the `test-typecheck-debt.json` notes in client (1), mcp (1), rest
(7) and runtime (1), and vitest-filter-preflight's `package.json`
description (1). All 13 are among the 55 off-list sites stage 14 listed.
- **What remains on this card after this stage:** the 55 off-list sites
stage 14 listed, and the five `cli` sites with no deciding commit
(objectstack-ai#10149, objectstack-ai#11048, objectstack-ai#14874 x3). None of them is touched here.
- **Grammar reach, measured on this surface:** the gate's grammar does
not extract the second number of a slash-joined pair such as
`objectstack-ai#10374/objectstack-ai#13522`. On these 81 files that shape holds 4 such numbers
(objectstack-ai#3060, objectstack-ai#7778, objectstack-ai#13522, objectstack-ai#14016), and all 4 answer 200
(2026-09-30T19:04Z), so the census above misses no dead site.
- **No open PR touches these files.** The claim's serial check read all
11 open PRs' file lists at `cb4c31dd52`; objectstack-ai#20602 and objectstack-ai#20583 on this seat
stay in `packages/rest/src` and `packages/cli/src`.

---
_Generated by [Claude
Code](https://claude.ai/code/session_01VvcEokUG1tvVxkceYfR5XB)_

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/m skip-changeset PR has no user-facing published change; bypasses the changeset gate tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants