Skip to content

feat(spec): remove the dangling postgres and nats values from ClusterDriverSchema - #14128

Merged
os-support-ai merged 4 commits into
mainfrom
claude/issue-13393-cluster-dangling-drivers
Sep 1, 2026
Merged

feat(spec): remove the dangling postgres and nats values from ClusterDriverSchema#14128
os-support-ai merged 4 commits into
mainfrom
claude/issue-13393-cluster-dangling-drivers

Conversation

@os-support-ai

Copy link
Copy Markdown
Collaborator

Fixes #13393

Removes the two dangling values from ClusterDriverSchema (packages/spec/src/kernel/cluster.zod.ts): postgres and nats. Both validated at parse time while no package implemented them — the only non-test registerClusterDriver() caller is @objectstack/service-cluster-redis — so a schema-valid cluster.driver passed validation and then reached the unconditional runtime throw in defineCluster() (the error text names the driver and says it is not registered). Direction fixed by the maintainer ruling on objectstack-ai/cloud#1626 (2026-08-24, option B adopted; its principle rider: a schema-valid value must not be an unconditional runtime throw — 声明即强制). Scope per this card's triage ruling (comment 5478753337): both dangling values, one card, one PR.

Clause-②: yes — this diff narrows the accept set of a contract schema under packages/spec/src/**.

Derived judgments — every accept/reject behaviour change, enumerated

  1. ClusterDriverSchema.parse('postgres'): ACCEPTED before → REJECTED now (zod v4 invalid_value issue; the issue's values roster is memory, redis, custom). Pinned by name in cluster.test.ts.
  2. ClusterDriverSchema.parse('nats'): same flip, same by-name pin.
  3. ClusterCapabilityConfigSchema with driver: 'postgres' or driver: 'nats': rejected at parse time; previously parsed clean and threw at defineCluster() boot. The rejection moves from an unconditional runtime throw to the schema, where it carries the accept set.
  4. Everything else is byte-identical accept/reject behaviour: memory, redis, custom all still accept (the exact roster is pinned via ClusterDriverSchema.options), defaults unchanged, every other ClusterCapabilityConfig field untouched.
  5. useExistingPool is NOT removed (triage prohibition: ledgered authorable-surface field). Only its postgres-only prose was corrected — field, type, and default true are unchanged, so zero accept-set change. The field's own retirement, if ever, is a separate card with its own ruling.
  6. Prose-only corrections with zero behaviour change: packages/spec/src/contracts/cluster-service.ts driver doc line, @objectstack/service-cluster doc comments (defineCluster example now instructs redis, per the issue title's second half), content/docs/kernel/cluster.mdx §8.1 and Phase 5 (the claim that the schema accepts postgres/nats was corrected; the deferred-driver design sketches stay recorded for whoever builds one under the ruling's reversal condition).
  7. Migration prescription registered as semantic entry cluster-driver-dangling-values-removed under protocol major 18 (accept-set narrowing is major-gated; matches the existing 18.* semantic-entry precedents), regenerated into registry.ts via gen:migration-registry. spec-changes.json and the upgrade guide show no delta — their gates pass green, and the pre-existing major-18 semantic entry is likewise unprojected, so the projections cover shipped majors only.
  8. Generated artifacts: content/docs/references/kernel/cluster.mdx regenerated via gen:docs (never hand-edited). api-surface/, declaration-map/, export-origins/, authorable-surface/: no delta, as predicted — the export set and the authorable key set are unchanged (enum values are not ledgered keys); check:authorable-surface and check:api-surface pass green with nothing to commit.

Semver

Verification — all readings at merged HEAD b34b9e48

Merged origin/main (clean merge, no conflicts, no generated-artifact drift: check:generated reports every artifact current on the merged tree) before the final gate union.

Tests (via the shared verify lock):

  • pnpm --filter @objectstack/spec test — 448 files / 12043 tests passed pre-merge; re-run on the merged head: 449 files / 12057 tests, all passed.
  • pnpm --filter @objectstack/service-cluster test — 4 files, 66 tests, all passed (re-run on merged head).
  • pnpm --filter @objectstack/service-cluster-redis test — 1 file, 28 tests, all passed (re-run on merged head).
  • pnpm --filter @objectstack/spec typecheck — green (tsc, scripts, and the test layer under tsconfig.test.json; tsc --listFiles confirms cluster.test.ts is inside the test program and cluster.zod.ts plus the new migration entry are inside the source program, so neither reading is a phantom).

Gates: the full dispatched list plus the families scripts/pm/dispatch-gates.mjs derives from the actual diff (derivation re-run on the merged head; command set identical) — all green, including check:adr-0087-registration, check:authorable-surface, check:docs, check:spec-changes, check:upgrade-guide, check:merge-driver, check:dual-build-cjs-loads (full 71-task workspace build performed locally), check:dev-prereqs, check:changeset-no-major, check:empty-changeset, and the changeset gate self-tests. Two readings are NOT MEASURED locally by the gates' own design, left to CI: check-test-completeness.mjs (grades a saved CI turbo test log; exit 3 with its own "record as NOT MEASURED" text) and pr-labels.mjs (needs PR context).

Fixture census (authored driver: 'postgres' / driver: 'nats')

  • In scope (ClusterDriver surface) — all corrected in this PR: cluster.test.ts (the postgres-driver fixture pinned exactly the deleted branch; replaced with a custom parse fixture plus by-name rejection pins for both removed spellings and a roster pin), cluster.zod.ts example, service-cluster doc comments, content/docs/kernel/cluster.mdx, regenerated references/kernel/cluster.mdx.
  • Out of scope, verified to be a different surface: every other hit (about 130 across tests/docs/examples) spells the datasource driver: 'postgres' (DatasourceSchema — a real shipped datasource driver, unrelated enum), plus one opaque ServiceMetadataSchema.metadata record in service-registry.test.ts and the datasource example in skills/objectstack-api/SKILL.md. Deliberately untouched.
  • No authored driver: 'nats' fixture existed anywhere in the repo.

Boundary flags / open questions

  • None requiring a decision. The one judgment call taken: the semantic migration entry lands under major 18 (not 17) because the narrowing ships after the v17 cut — consistent with every 18.* precedent in entries/; flagging here so review can confirm.

Session: https://claude.ai/code/session_01Mciyv38maJ6HYVMiaM26T1

Generated by Claude Code


Generated by Claude Code

…hema

Both values validated in ClusterDriverSchema while no package implemented
them — the only non-test registerClusterDriver() caller is
service-cluster-redis — so a schema-valid driver value reached
defineCluster()'s unconditional "not registered" throw at runtime. Removes
the two enum values, corrects the now-false postgres-only prose around
useExistingPool/url (the ledgered field itself stays), replaces the
postgres doc examples with redis, registers the semantic migration entry
under protocol major 18, and pins the shipped roster plus the by-name
rejection of the two removed spellings.

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Mciyv38maJ6HYVMiaM26T1
@github-actions github-actions Bot added size/m documentation Improvements or additions to documentation tests tooling labels Sep 1, 2026
@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 2 package(s): @objectstack/service-cluster, @objectstack/spec, touching 4 documentable anchor(s). ⚠️ 4 changed file(s) yielded no anchor (packages/services/service-cluster/src/cluster.ts, packages/services/service-cluster/src/memory/counter.ts, packages/services/service-cluster/src/memory/pubsub.ts, …), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files.

1 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:

  • content/docs/kernel/cluster.mdx (via ClusterDriverSchema (symbol, a top-level const object), IClusterService (symbol, a top-level interface))
What this run could not see
  • 4 changed file(s) yielded no anchor (packages/services/service-cluster/src/cluster.ts, packages/services/service-cluster/src/memory/counter.ts, packages/services/service-cluster/src/memory/pubsub.ts, …) — pages documenting those are invisible to this run
  • 4 name(s) were too generic to anchor anything (single lowercase words)
  • the SDK route bridge reached 47 of 219 client-bound route-ledger rows — the other 172 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 172: 14 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 56 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 102 are undecided (no in-repo declaration, on a ledger that has other in-repo registrars — absence and an unreadable spelling are not distinguishable here). The rows themselves: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • 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 — 130 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 ec0c6c20f9920223205ab0ddeed49b85b1b52b72packageMentionDocs.

Which tree this was computed on

This run read content/docs from 2536090521c1992a84b473b9414d783a75dc29ad — the merge of head 33d5649661e0f8cfbdd434c7f3d0b31da60bf902 into base ec0c6c20f9920223205ab0ddeed49b85b1b52b72, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 2536090521c1992a84b473b9414d783a75dc29ad && git checkout 2536090521c1992a84b473b9414d783a75dc29ad
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin ec0c6c20f9920223205ab0ddeed49b85b1b52b72 33d5649661e0f8cfbdd434c7f3d0b31da60bf902 && git checkout -B drift-repro ec0c6c20f9920223205ab0ddeed49b85b1b52b72 && git merge --no-ff 33d5649661e0f8cfbdd434c7f3d0b31da60bf902

node scripts/docs-audit/affected-docs.mjs --json ec0c6c20f9920223205ab0ddeed49b85b1b52b72

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs ec0c6c20f9920223205ab0ddeed49b85b1b52b72 → pass the list as
args.docs, on the commit named under Which tree this was computed on.

… registry pin

The registry read-vs-throw agreement pin used postgres as its schema-valid
but never-registered sample; with postgres removed from ClusterDriverSchema
the config now fails parse before the registry is consulted, so the expected
"not registered" throw is unreachable. redis keeps the pin's exact intent:
in the enum, but this suite never imports the package whose load-time side
effect registers it, so in this module instance it is the requested-but-not-
registered case — the same shape as the EE boot the suite's header records.

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Mciyv38maJ6HYVMiaM26T1

Copy link
Copy Markdown
Collaborator Author

Integration fix for the Test Core red (pushed as 33d56496, on top of a fresh origin/main merge, 8a561418).

What conflicted: after this branch's previous merge point (3795c5f5), #14042 (commit bfe13c86, the #13330 fix — #13330 is not addressed here) landed packages/services/service-cluster/src/cluster-driver-registry.test.ts on main. Its fourth pin, "unlisted means the documented throw", used postgres as its schema-valid-but-never-registered sample value. With postgres removed from ClusterDriverSchema by this PR, that config now fails zod parse inside defineCluster() before the registry is consulted, so the expected "not registered" throw became unreachable on the CI merge ref — 1 failed of 70 in service-cluster; the same +1 over the frozen ledger number showed up in Type Check - debt ledger (--re-measure), because driver: 'postgres' no longer satisfies the ClusterDriver type in that new file.

The fix (test sample value only): the sample is now redis — still in the enum, but this suite never imports @objectstack/service-cluster-redis, whose load-time side effect is the only thing that registers it, so in that module instance it is exactly the requested-but-not-registered case the pin exists for (the same shape as the EE boot recorded in the suite's own header). Comment and regex updated to match; the file's other three pins and the defineCluster()/registry implementation are untouched.

Local readings on the patched merged head 33d56496:

  • pnpm --filter @objectstack/service-cluster test — 5 files / 70 tests, all passed (previously 1 failed of 70 on the CI merge ref).
  • pnpm --filter @objectstack/spec test — 449 files / 12057 tests, all passed.
  • pnpm --filter @objectstack/spec check:generated — every artifact current, zero drift after the merge.
  • pnpm check:type-check-debt (full workspace built first) — "28 ledger entr(ies) re-measured ... none above its recorded number": service-cluster is back at its frozen count; no ledger number was raised.

Generated by Claude Code


Generated by Claude Code

@os-support-ai
os-support-ai added this pull request to the merge queue Sep 1, 2026
Merged via the queue into main with commit c85a265 Sep 1, 2026
34 checks passed
@os-support-ai
os-support-ai deleted the claude/issue-13393-cluster-dangling-drivers branch September 1, 2026 07:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tests tooling

Projects

None yet

2 participants