Skip to content

test(cli): pin the five cluster-driver diagnosis branches at boot, silence included - #15381

Merged
os-litant merged 2 commits into
mainfrom
claude/issue-14054-serve-cluster-driver-diagnosis-pins
Sep 4, 2026
Merged

test(cli): pin the five cluster-driver diagnosis branches at boot, silence included#15381
os-litant merged 2 commits into
mainfrom
claude/issue-14054-serve-cluster-driver-diagnosis-pins

Conversation

@os-litant

Copy link
Copy Markdown
Collaborator

Fixes #14054

The four cluster-driver diagnosis branches added by #14042, plus the fifth deliberately-silent case, are now asserted at boot against the real os serve process. This is the follow-up the at-tier contract review on #14042 required to exist: a disclosed coverage gap, not a defect. Nothing about what any branch prints changes here.

Route: booted serve. serve.ts is untouched.

The card offered two routes and preferred the boot; the boot was measured before it was chosen rather than assumed tractable. A temp host app carrying a fixture @objectstack/service-cluster reaches the block in ~7.5s per case, and runServe() already resolves a boot that DIES — which is what all six boots here do. So no seam was extracted, packages/cli/src/commands/serve.ts has zero changed bytes, and the PR is one new file.

What is pinned

case fixture asserted
registered registry reports ['custom'] silence — no [cluster] output of any kind
loaded-but-invisible registry reports ['redis'] the split warning, verbatim, including the one-line remedy
not-resolvable / undeclared driver neither declared nor installed the kind token, and createHostImporter's own remedy immediately after it
not-resolvable / declared-unresolvable declared, not installed the same framing, the other kind's remedy, and not the first one's
resolved-then-crashed driver throws while evaluating the driver package's own error and the frame naming its own file — never a registration problem
no listClusterDrivers accessor accessor absent silence — declines to claim either answer

Both resolution kinds are pinned because the site interpolates only the kind TOKEN and defers every word of remedy to the importer. The pair is what keeps a per-kind branch from growing here — the #14270 shape the sibling i18n site is deliberately not in.

Why the two silences are measurements rather than empty buffers

Two things stop a silence pin from being vacuous, and both are asserted rather than assumed:

  1. A positive control in every case, silent ones included. Every boot asserts defineCluster()'s documented error, raised from the framework's real registry one statement past the diagnosis. It can only print if the block ran to its end and set clusterConfig, so it is the child's own proof that the reading happened.
  2. The three registry cases are one fixture family varying one slot — what the app's @objectstack/service-cluster answers when asked for its driver list. A separate (boot-free) guard pins that isolation on the generated sources. If the accessor were never read, the middle case would be silent too. It is not: it warns.

Ablation

Both mutations were applied to serve.ts in the working tree, run, and reverted with git checkout HEAD --, byte-identity re-checked against the HEAD blob (b3ab2e36…) after each. No rebuild was needed or done, and that is a property of this harness rather than a skipped step: runServe() spawns bin/run-dev.js, which runs the command from src/ through tsx — the crash case's own stack frame names packages/cli/src/commands/serve.ts, so the file the ablation edits is the file the child executes.

  • Inverting the visibility test (indexOf(...) >= 0 becomes < 0) reds five of the six boots, the registered silence among them. no-accessor stays green, correctly — its silence is not bought by visibility.
  • Making the absent accessor claim an empty registry (: undefined becomes : []) reds exactly one, no-accessor, and nothing else.

Not duplicated

serve-cluster-host-resolution.test.ts pins the block's SHAPE by source scan (host-anchored loads, module-scope importFromHost); packages/services/service-cluster/src/cluster-driver-registry.test.ts pins the accessor invariant in both directions. Neither is restated. What is only here is the boot-level fact that each branch fires on its own condition. The new file lands in the derived integration tier automatically (runServe( is a SPAWN signal).

Verification, at bc0c47f1

  • pnpm --filter @objectstack/cli exec vitest run test/serve-cluster-driver-diagnosis.e2e.test.ts test/vitest-tiers-partition.test.ts — 30 passed.
  • pnpm --filter @objectstack/cli typechecktsc --noEmit clean, check:test-typecheck: OK.
  • Gate union derived with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands at this HEAD on a clean tree: 35 commands, each exit code captured before any pipe. 34 exit 0. pnpm check:dual-build-cjs-loads exits 3 with PREREQUISITE NOT MET — this gate reads built output and its own line ⛔ This is NOT a pass: nothing was measured — recorded as NOT MEASURED, neither pass nor red; only the CLI dependency closure was built locally, and CI builds the workspace.
  • The four artifact-roster gates whose roster sits under packages/ (check:authz-resolver, check:error-code-casing, check:filter-alias-parity, check:swallow-census-controls) were run rather than read off their silence: all exit 0.
  • pnpm lint (eslint . --no-inline-config, whole repo) — exit 0. No narrowing was needed, so none is claimed.
  • dispatch-gates warned the tree is behind origin/main and that one file it derives from changed there, scripts/pm/check-skill-line-ratchet.mjs. That file's surface is a closed ENUMERATION of .claude/skills/** and skills/** paths; both copies were diffed and the change is a ceiling raise plus comments. It cannot match this PR's single path either way, so the derived union stands.

No changeset: this PR adds one test file and packages/cli publishes files: ["dist", "README.md", "CHANGELOG.md"], so nothing is released from any package. skip-changeset is applied.


Generated by Claude Code

WIP: first full draft of the boot-level suite for #14054.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D47qPfEWVPmhguWgBZCi5N
The two mutations, what each one turns red, and why no rebuild is involved
(the harness runs `serve.ts` from source through tsx).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D47qPfEWVPmhguWgBZCi5N
@github-actions github-actions Bot added the size/m label Sep 4, 2026
@os-litant os-litant added skip-changeset PR has no user-facing published change; bypasses the changeset gate and removed size/m labels Sep 4, 2026 — with Claude
@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

Nothing 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
  • 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 — 0 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 27875fc7ec7c7e25f032f2417784ce6b923f3c7apackageMentionDocs.

@github-actions github-actions Bot added the tests label Sep 4, 2026
@os-litant
os-litant marked this pull request as ready for review September 4, 2026 14:14
@os-litant
os-litant enabled auto-merge September 4, 2026 14:14
@os-litant
os-litant added this pull request to the merge queue Sep 4, 2026
Merged via the queue into main with commit 097a01c Sep 4, 2026
42 checks passed
@os-litant
os-litant deleted the claude/issue-14054-serve-cluster-driver-diagnosis-pins branch September 4, 2026 14:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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.

test(cli): no test boots serve and asserts the four cluster-driver diagnosis branches (follow-up promised in #14042)

2 participants