Uh oh!
There was an error while loading. Please reload this page.
feat(spec): type IObjectQLEngine.getSchema and declare IDataEngine.syncObjectSchema (#12481, #12482) - #12986
Conversation
…ed (#12481) One member over from #12248 (the #11833 ruling's fork 3, applied by inheritance): ObjectQL.getObject is literally getSchema's alias, the class has always answered ServiceObject | undefined, and ServiceObject lives in spec — so the contract's engine-local-type rationale for unknown did not apply here either. Pin block mirrors the getObject pins (exact type, alias non-drift, write-guard slice substitutability). plugin-security's engine-owned write guard drops its now-redundant 'as EngineOwnedSchemaLike | undefined' cast (typecheck-proven). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LpRNHxWZgSUgVnFT9mQQo4
The member #12010's inventory left 'not verified', verified and adopted under the 2026-08-25 #11833 ruling's item-4 precedent as executed by #12248: implemented on ObjectQL (on-demand single-object schema sync, ADR-0015 s18 federated read-metadata registration included), consumed cross-package by service-datasource (ConnectionEngineLike, per bound external object after connect) and service-messaging (system-table provisioning), both through consumer-local structural recovery until now. Declared optional next to the datasource-lifecycle trio; pin block mirrors theirs (optionality, exact signature, consumer-substitutability, async refusal). service-messaging drops its now-redundant 'as unknown as' recovery (typecheck-proven). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LpRNHxWZgSUgVnFT9mQQo4
…jectql-engine-member-adoption
…jectql-engine-member-adoption
📓 Docs Drift CheckThis PR changes 3 package(s): 11 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 2 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 129 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 10e134dcbc83c7d5758f963cede3598600b6b442 && git checkout 10e134dcbc83c7d5758f963cede3598600b6b442
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 2b4178aa53ca62089f43e2cfae0b7838cf340dd1 5d7b7caba9060fadce9a521b958c1460cdb63317 && git checkout -B drift-repro 2b4178aa53ca62089f43e2cfae0b7838cf340dd1 && git merge --no-ff 5d7b7caba9060fadce9a521b958c1460cdb63317
node scripts/docs-audit/affected-docs.mjs --json 2b4178aa53ca62089f43e2cfae0b7838cf340dd1
|
Uh oh!
There was an error while loading. Please reload this page.
Fixes#12481
Fixes#12482
Family dispatch (fold): two member cards, one commit per member, both ruled by inheritance from the 2026-08-25 #11833 ruling as executed by #12248 (triage comments 5421199436 / 5421181965). Premise verification found no semantic divergence on either member — no fork to report. Exclusion list honoured: every other unknown-typed or undeclared engine member (including the rest of #12010's "not verified" rows) is out of this fold.
Member 1 — #12481:
IObjectQLEngine.getSchematyped (commit d047d5b)Premise verified on
origin/mainatfc8a33935(branch base):getSchema(objectName: string): unknown(packages/spec/src/contracts/objectql-engine.ts, the schema-access block).ServiceObject | undefined(packages/objectql/src/engine.ts:6525), andgetObjectis literally its alias —return this.getSchema(name)atengine.ts:12847— so the mother ruling's fork-3 reason (the type lives in spec atdata/object.zod.ts; the "engine-local type" rationale is void) transfers whole. Alias relation confirmed on the current ref: no fork.Change: the member now returns
ServiceObject | undefined(authored state, ADR-0122, exactly asgetObject). Named pin block added tocontracts/objectql-engine.test.ts: exact-type pin (mutual extends), alias non-drift pin (getSchemaandgetObjectanswer one type), and a write-guard-slice substitutability pin (the plugin-security repair depends on it).Reverse verification (direction as observed): reverting the contract member to the base state turned
pnpm --filter @objectstack/spec typecheckred with 5 type errors named insrc/contracts/objectql-engine.test.ts— the gate's own output names the pin file, which also proves the pins sit inside the measured tsc program. Restore proven: HEAD blob hash equals on-disk blob hash,git diff HEADempty. Note for reviewers: the vitest leg alone stays GREEN on the mutated tree (vitest transpiles without type checking), so the guarding gate for these type-level pins is the package typecheck — which CI runs.Member 2 — #12482:
IDataEngine.syncObjectSchemadeclared (commit 5979769)Premise re-verified on the same base — all three cited sites live:
packages/objectql/src/engine.ts:12974— async, idempotent, ADR-0015 §18 (federated read-metadata registration without DDL; managed objects get create/alter on demand).service-datasource:ConnectionEngineLikedeclares the member (datasource-connection-service.ts:104) and the live call runs per bound external object after its driver connects (line 620).service-messaging:messaging-service-plugin.ts:353-355recovered the member through anas unknown asone-member structural slice, its own comment recording that the member lived on the concrete ObjectQL engine, not the contract.Placement measurement (which contract file): declared on
IDataEngineincontracts/data-engine.ts, directly after the #12248 datasource-lifecycle trio. Evidence: both measured consumers reach the member throughIDataEngine-typed values —ConnectionEngineLikedocuments itself as the surface of the ObjectQL data-engine slot (the same population as the #12248 trio, which #12248 placed indata-engine.ts), and messaging'sprovisionSystemTablestakesengine: IDataEnginedirectly. Declaring it onIObjectQLEngineinstead would leave the messaging call site still needing a cast — the outcome the ruling forbids. The member is datasource-lifecycle-shaped (driven per bound external object after connect) even though implemented on the ObjectQL engine; the #12248 precedent places exactly that shape onIDataEngineas optional members. Named pin block added tocontracts/data-engine.test.ts: optionality, exact signature (string parameter, async answering nothing), substitutability against both verbatim consumer-local shapes, and a refusal pin for a synchronous implementation.contracts/data-engine.tsis also touched by the gated draft PR #12949 (EngineDatasourceDef + listDatasourceDefs). Landing order: #12949 first; this PR merges main after it lands and regenerates. This branch is based onorigin/main, never on #12949's branch; #12949's diff was read via its PR ref, and this member is added afterclearDatasourceUnavailable, textually clear of #12949's edit region.Reverse verification: reverting
data-engine.tsto base turned spec typecheck red —data-engine.test.tsreported 6 errors where the debt ledger records 1 pre-existing (the 5 new are the pin block). Restore proven by blob-hash equality and emptygit diff HEAD.Consumer-compat verification (acceptance, both cards)
Direction stated: the sweep is DOWNSTREAM of spec (the prefix filter form selects consumers); each named consumer package was typechecked individually on the merged head. All named cast sites verified:
security-plugin.ts:1685(contract-typedql)this.qltypedany— unaffected; greensql-http-outbox.ts:274getSchemathrough its own IDataEngine-based local structural declaration (line 47), not the changed contract — unaffected; its cast still narrows a localunknownand staysrecord-organization.ts:79 / 229unknownengine parameter (deliberate test-double tolerance) — stay; typecheck greenaction-execution.ts:1596qlisanyin that scope — unaffected; typecheck greenConnectionEngineLike+ live call (line 620)messaging-service-plugin.ts:355No consumer broke — consistent with the mother ruling's implementor/consumer source-compatibility precedent.
Mechanical cast drops, each provably redundant, before/after:
packages/plugins/plugin-security/src/security-plugin.ts:1685— BEFORE: thegetSchemaanswer (thenunknown) was cast withasto the guard's EngineOwnedSchemaLike-or-undefined slice; AFTER: passed directly — the contract answer is assignable to that slice (pinned inobjectql-engine.test.ts), and the package tsc is green with the cast removed; the now-unused type import was dropped in the same edit. The runtimetypeofprobe stays (double tolerance).packages/services/service-messaging/src/messaging-service-plugin.ts:355— BEFORE: the engine was cast viaas unknown asto a one-member structural slice to reachsyncObjectSchema; AFTER:engine.syncObjectSchemaread directly off the contract (assignability pinned indata-engine.test.ts; package tsc green). The runtimetypeofprobe stays.Gates
Derived with
node scripts/pm/dispatch-gates.mjs(no hand-fed paths; derivation header names this repo at commit5d7b7caba— re-derived after each of the two same-day main merges, family set unchanged). Gate results quote the gates' own verdict lines; exit codes captured before any pipe.Green at final head
5d7b7caba: contract pin tests 37/37 (both files), spec typecheck,check:engine-double-contract,check:where-matcher,check:query-options-erasure,check:objectql-double-limit,check:nul-bytes,check:dev-prereqs,check-adr-0087-registration.Green at
82a25cd8cwith a declared narrowing for the delta to5d7b7caba(that delta contains onlyscripts/pm/,.claude/,content/docs/files — no package source, no changeset — so these measurements stand): full workspace build (turbo 70/70), spec full suite 440 files / 11653 tests,check:generated"All 14 generated artifacts are up to date" (api-surface unchanged — no new named export from either member),check:type-check-coverageOK (65/78 + ledger) and its--re-measureratchet "none above its recorded number", all six consumer typechecks (objectql · metadata-core · runtime · service-datasource · service-messaging · plugin-security, each invocation echoed),check:i18n,check:i18n-stale-fill,check:cross-package-test-inputs,check:test-source-alias,check:type-source-resolution,check:spec-parsed-alias,check:slot-lookup,check:published-files,check:page-declaration-shape,check:merge-driver,check:doc-authoring,check:changeset-gate-self-tests,check:objectui-changeset,check:undeclared-dep-imports,check-ci-filter-parity,check-comment-mask-adoption,check-plugin-teardown-shape,check-changeset-no-major,check-empty-changeset, docs-audit affected-docs, release-rehearsal self-test, speccheck:empty-state/check:variant-docs/check:liveness/check:strictness-ledger/check:docs/check:skill-refs/check:authorable-surface.NOT MEASURED (neither green nor red):
check:pm-half-states— exits 3 PREREQUISITE NOT MET from this container (the environment token is the proxy placeholder, not a GitHub credential; the gate's own text: "Nothing was swept … it is no reading at all"). CI runs it with its own credential.Changesets
Two, one per member:
@objectstack/specminor +@objectstack/plugin-securitypatch (#12481);@objectstack/specminor +@objectstack/service-messagingpatch (#12482). FROM/TO prose per member in each body.check-adr-0087-registrationgreen — no declared-breaking changeset (the #12248/#12949 additive precedent).Clause-② holds on both members: opened as draft — the review chain owns enqueue; this seat does not flip ready or arm anything.
Session: https://claude.ai/code/session_01LpRNHxWZgSUgVnFT9mQQo4
Generated by Claude Code
Generated by Claude Code