Skip to content

refactor(objectql): retire the four engine.ts facade-gate exception rows the protocol.ts split handed over - #31343

Merged
objectstack-fleet[bot] merged 5 commits into
mainfrom
claude/project-thread-20kprd
Nov 8, 2026
Merged

objectstack-fleet[bot] merged 5 commits into
mainfrom
claude/project-thread-20kprd

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Leehom · project thread

Fixes #30975

Clause-②: no
Metadata-protocol: none

维护者速读

  • 改了什么:Facade codemods: retire the codemod-limit exception rows in the facade gate registry (protocol.ts, engine.ts, sql-driver.ts) #30147 交过来的四个 engine.ts facade 门禁例外行全部退役。homeAmountServing 的方法体用 codemod 搬进 references facet;projectHomeAmountsOntoPatch 类上存根不再算默认值,改由 facet 算;ScopedContext 的 derive 与 [APP_AUTHORED_HOOK_API] 的方法体搬进 ScopedContextFacet,对新实例私有字段 appAuthored 的那一次写改走该实例自己的内部 host setter。
  • 为什么改:facade 门禁要求 engine.ts 里的类只剩一行委托;这四行是登记在案的欠账,登记表里 card: #30975 的行现在为零。
  • 风险与回滚:纯内部搬移,行为不变(objectql 全量 vitest 基线与 head 都是 565 文件 / 11,428 测试全绿);公开声明不变(.d.ts 只少了两个私有成员的注释块,声明行零差异);回滚即 revert 本 PR。
  • 附带:content/docs/permissions/system-context.mdx 第 1b 行的 Symbol 键由 inheritsElevation 改为 appAuthoredHookApi,站点登记表用 --write 重新生成(check:system-context-census 按符号定位 isSystem 读点,方法体搬家后键随之移动)。
  • 先看:packages/objectql/src/engine-scoped-context.ts 新增的 derive / appAuthoredHookApi(scopedContextHost.of(child).appAuthored = … 那两行);engine.ts 中 ScopedContext static block 新增的 set appAuthored;engine-references-and-master-detail.ts 的 homeAmountServing。
  • 两分钟验证:pnpm check:facade-delegation-only,预期末行 5 facade class(es) in 3 file(s) hold delegations only, 11 named exception(s).,退出码 0。
  • 需要你做的:无,席位落地。

What changes

All four exception rows that #30147's ruling (6687801899, option A) handed to this card retire, and scripts/facade-delegation-registry.json now holds no row with card: "#30975" (15 → 11 exceptions).

Row 1, ObjectQL.homeAmountServing. The body moves into ReferencesAndMasterDetailFacet by the codemod's own --members pass, unedited. On main the pass refuses it with field-call: homeLocalizationResolver. For this move only, that one stay reason was lifted for that one field in a local, uncommitted copy of scripts/codemod-split-engine.mjs (a one-line condition; the committed script is unchanged and no general field-forwarding rule is added). That run's own undo proof rebuilds the base engine.ts and the facet module byte for byte. The host already carried homeLocalizationResolver (getter and setter), find and _registry, so the host factory does not grow. Three import bindings move from engine.ts to the facet with the body (EXCHANGE_RATE_OBJECT, memoizeHomeAmountServing, HomeLocalization).

The one runtime difference is the resolver's receiver: this.homeLocalizationResolver?.(organizationId) now calls it with the host as this, not the engine. HomeLocalizationResolver is a plain function type of organizationId with no this parameter, and all 14 installations in the tree (one in plugin.ts, the rest in tests) are arrow functions, so nothing reads it.

Row 2, ObjectQL.projectHomeAmountsOntoPatch. The body already lived in the facet (#29986), and its facet signature already defaults serving to this.homeAmountServing(context). The class stub's parameter is now serving?: HomeAmountServing and is passed through as given, so the facet computes the default when the caller passes none. It still reaches the engine's homeAmountServing through the host closure, so an instance spy or a subclass override is still the one called. The only caller (the update path) passes none.

Rows 3 and 4, ScopedContext.derive and ScopedContext[APP_AUTHORED_HOOK_API]. The order asked first whether a design moves the foreign-private appAuthored write off the class without widening anything public. One does, and it is small:

  • Both bodies move into ScopedContextFacet (as derive and appAuthoredHookApi). Each builds a ScopedContext and writes the new instance's private appAuthored through that instance's own host: scopedContextHost.of(child).appAuthored = this.appAuthored and scopedContextHost.of(api).appAuthored = true.
  • The host is the port the class's static block already fills for every facet body. It gains one setter, set appAuthored(v) { instance.appAuthored = v; }, which is the codemod's own shape for a field a body assigns, and ScopedContextHost.appAuthored loses readonly. derive is private, so its docblock moves with its body; [APP_AUTHORED_HOOK_API] is public and keeps its docblock on the class.
  • Where the setter lives and who can reach it. The setter is one getter/setter pair inside the host object literal that ScopedContext's static block hands to scopedContextHost.install(...) (packages/objectql/src/engine.ts, the [#30052 codemod] Installs the host of ScopedContextFacet block). The only way to get a host is scopedContextHost.of(instance), and scopedContextHost is exported only from packages/objectql/src/engine-scoped-hosts.ts. Measured with git grep -n "engine-scoped-hosts" -- packages examples apps: exactly two modules import it, engine.ts (line 426) and engine-scoped-context.ts (line 44); the other four hits are comments. Neither packages/objectql/src/index.ts nor src/core.ts re-exports either module, the package's exports map has only . and ./core, and scopedContextHost, InstanceHost and ScopedContextHost appear 0 times in the built index.d.ts, core.d.ts and the shared chunk. So nothing outside the engine*.ts modules can reach the setter through the package.
  • Nothing public widens: no new class member, no new constructor parameter, no exported setter, and the built declarations are unchanged (see Acceptance notes). TypeScript's private was never a runtime barrier, so the setter grants no capability that in-process code lacked.
  • engine.ts no longer reads appAutomationElevationOf or markAppAutomationElevation, so those two import bindings move to the facet module, which already imported them.

Rows 3 and 4 therefore do not need an accepted-exception ruling, and this PR writes no exception reason.

One docs cell and the generated register. check:system-context-census keys every isSystem read by the symbol that holds it. On main the app-authored api's read (const inheritsElevation = ctx.isSystem && …) sat in a symbol-keyed method, so the census keyed it engine.ts#inheritsElevation, and row 1b of content/docs/permissions/system-context.mdx named inheritsElevation. In the facet the read lives in appAuthoredHookApi, so the gate went red with [row-key-no-read] and [read-without-a-row]. Row 1b's Symbol cell now names appAuthoredHookApi (elevationSource kept), and node scripts/check-system-context-census.mjs --write regenerated the site register (one line out, one line in). No prose changes. The claim amendment 6716417615 covers this file.

A patch changeset for @objectstack/objectql: the package's built JavaScript moves between modules inside the bundle, while its declarations do not.

engine.ts goes from 10,712 to 10,653 lines. 6 files, +118 / -104.

Tests

No test file changes; this is a move, and the existing suites pin the moved behaviour. Measured on b2ef226ef; the two commits after it (the changeset and the docs page) touch no source:

  • @objectstack/objectql vitest (--project local): base 604a2b3b9 565 files / 11,428 tests passed; head 565 files / 11,428 tests passed. pnpm --filter @objectstack/objectql typecheck (tsc plus check:test-typecheck) exit 0.
  • Ablation, derive's write (ablation-replace.mjs, anchor scopedContextHost.of(child).appAuthored = this.appAuthored; replaced by … = !1 && this.appAuthored;; mutation landed, anchor 1 → 0): recycle-bin/purge.test.ts + hook-run-as.test.ts went 6 failed / 62 passed, among them "is refused the same way on the api sudo() derives" and the four runAs permanent-delete refusals. Restored: blob equal to HEAD, git diff HEAD empty.
  • Ablation, the app-authored mark (anchor scopedContextHost.of(api).appAuthored = true; replaced by … = !1;): the same two files went 9 failed / 59 passed. Restored the same way. The head control run of both files: 68/68.
  • Those suites import src/ (../engine.js), so the ablations needed no rebuild.

Acceptance notes

  • The .d.ts bar. @objectstack/objectql built at base and at head: index.d.ts, index.d.mts, core.d.ts and core.d.mts have zero differing lines once the shared chunk's file name is normalised. The chunk itself (util-*.d.ts / .d.mts) differs only by 16 comment lines and 0 declaration lines: the JSDoc blocks of the two private members whose bodies moved (homeAmountServing's 15 lines and derive's one line), which leave with their bodies under the codemod's private-docblock rule (the same rule refactor: move the private docblocks of the hand-series stubs into their hand modules — about 1,900 lines off engine.ts (86 stubs) and about 4,000 off protocol.ts (157 stubs) #30053 applied). private homeAmountServing;, private projectHomeAmountsOntoPatch;, private appAuthored;, private derive; and [APP_AUTHORED_HOOK_API](): ScopedContext; are printed as before. Because the chunk's content changed, its hashed file name changed too (util-DGHGF_i8 → util-BfmsHmSX). So the public surface is unchanged, but the declaration files are not byte-identical: they differ by those two private comments and the chunk name. This is stated here, not hidden; keeping the comments on the class would break the codemod's undo proof for row 1.
  • Control for the gate. check-facade-delegation-only.mjs --root BASE_TREE --registry HEAD_REGISTRY exits 1 with exactly four problems, one per retired member, so each row was load-bearing and each move is what turns it green.
  • Reproducing the codemod move. With the one-line lift applied locally, node scripts/codemod-split-engine.mjs --members --verify --base 604a2b3b9 on aba639da1 exits 0. Without the lift it exits 1 with exactly one failure, the stay rule itself (homeAmountServing: a stay rule holds it at base (field-call: homeLocalizationResolver)).
  • Serial check. Open pulls touching packages/objectql/src/engine*.ts at 02:13Z: only feat(objectql): restore a recycle-bin entry under its original ids and emit data.record.restored (#30237 PR 3) #31220 (engine.ts hunks at about lines 86, 2443 and 8360). git merge-tree --write-tree HEAD pr/31220 exits 0, with no conflict.

Verification

Codemod move and undo proof (row 1)

The one-off lift, applied only for the run (not committed):

-          if (called) add('field-call', member);
+          if (called && member !== 'homeLocalizationResolver') add('field-call', member);

node scripts/codemod-split-engine.mjs --members homeAmountServing --write: exit 0.

- engine-references-and-master-detail.ts: homeAmountServing (39 body lines, its docblock with it)
output tree sha256: 9d3b18d56488bab56bbfca02ff673ac4ee1eb6f1f9615d5202b285b0c71f065d (input sha256 b612db91716697a245085be30d0cdbc41870c0c215519421dbc5b0bd34067f0b)
undo proof: 1 moved method(s) (homeAmountServing); engine.ts 10712 -> 10659 lines; undoing the moves does rebuild the base engine.ts and its modules byte-for-byte once the 3 import binding(s) only moved bodies read are pruned from the base (EXCHANGE_RATE_OBJECT, HomeLocalization, memoizeHomeAmountServing)

--members --verify --base 604a2b3b9 with the lift: exit 0, the same proof line. Without the lift (the committed script): exit 1, the one stay-rule failure only.

Facade gate

node scripts/check-facade-delegation-only.mjs at head: exit 0, ✓ check-facade-delegation-only: 5 facade class(es) in 3 file(s) hold delegations only, 11 named exception(s).

Control, base code with the head registry: exit 1, four problems:

✗ packages/objectql/src/engine.ts:2563 ObjectQL.homeAmountServing holds a body, not a delegation: statement 1 of 3 (VariableStatement) is not a forwarding declaration (3 statement(s)).
✗ packages/objectql/src/engine.ts:2625 ObjectQL.projectHomeAmountsOntoPatch holds a body, not a delegation: parameter `serving` computes its default.
✗ packages/objectql/src/engine.ts:10270 ScopedContext.derive holds a body, not a delegation: statement 1 of 3 (VariableStatement) is not a forwarding declaration (3 statement(s)).
✗ packages/objectql/src/engine.ts:10316 ScopedContext.[APP_AUTHORED_HOOK_API] holds a body, not a delegation: statement 2 of 5 (VariableStatement) is not a forwarding declaration (5 statement(s)).
Suites

Under the shared lock: base vitest run --project local --maxWorkers=2 VERDICT exit 0, Test Files 565 passed (565), Tests 11428 passed (11428). Head: VERDICT exit 0, Test Files 565 passed (565), Tests 11428 passed (11428). pnpm --filter @objectstack/objectql typecheck VERDICT exit 0. pnpm --filter @objectstack/objectql build exit 0 at base and at head (after --filter '@objectstack/objectql^...' build, exit 0). eslint --no-inline-config on the three changed source files: exit 0.

.d.ts base vs head

pnpm --filter @objectstack/objectql build at 604a2b3b9 and at b2ef226ef. With the shared chunk's hashed name normalised: index.d.ts, index.d.mts, core.d.ts, core.d.mts diff exit 0. The chunk (util-DGHGF_i8.d.ts → util-BfmsHmSX.d.ts, and the same for .d.mts): 16 changed lines, 0 of them outside a comment. The whole diff (normal diff output, its < markers spelled - here):

7471,7485d7470
-     /**
-      * [ADR-0144 D5, Open item 2] What one write's home projection reads, memoized
-      * for that write: each organization's home currency once, and each
-      * (organization, currency, document date) rate once, however many rows ask.
-      *
-      * The rate is the `sys_exchange_rate` row of that currency with the latest
-      * `effective_date` on or before the document date, in the organization the
-      * row lands in. Read `sudo()`-shaped (`{ ...context, isSystem: true }`): a
-      * rank-and-file writer cannot read the rate table (parameter 2 makes it an
-      * administrator's object), yet every write of theirs is converted through
-      * it; the caller's transaction rides along, and `tenantId` is the row's own
-      * organization, so one organization's rate never converts another's
-      * amount. An install without the rate object registered has no rate for any
-      * currency.
-      */
9072d9056
-     /** A child over `executionContext` that keeps this api's provenance. */
Derived gates

node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack, derived three times as the diff grew (source, then the changeset, then the docs page). Every family run with stdin closed and its exit code captured before any pipe; the source-only families ran at 15827c138, the changeset and docs families and the two reruns at 7d5f631fc (the docs commit touches only the .mdx page). Reconciliation at 7d5f631fc: node scripts/pm/dispatch-gates.mjs --ran 30975-gates-ran.txt, exit 0, "103 derived, 101 run, 2 NOT-MEASURED, 0 UNRUN".

  • NOT MEASURED (exit 3, prerequisite not met in a card worktree, which lacks every package's dist/): pnpm check:dual-build-cjs-loads, pnpm check:published-readme-exports. CI runs both.
  • node scripts/check-plugin-teardown-shape.mjs --self-test first answered exit 3 on the shallow clone; after git fetch --depth=1 origin 621a487607881c66b2899b7e3477115229a156b4 it exits 0.
  • pnpm check:system-context-census was exit 1 before the row 1b re-key (above) and is exit 0 after it.
  • pnpm --filter @objectstack/spec run check:skill-examples first answered exit 3 (no client SDK dist/); after building @objectstack/client-react and its closure it exits 0.
node scripts/check-closing-keyword-parity.mjs :: exit 0
node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0
node scripts/check-comment-mask-adoption.mjs :: exit 0
node scripts/check-comment-mask-adoption.mjs --self-test :: exit 0
node scripts/check-comment-mask-corpus.mjs :: exit 0
node scripts/check-dts-emitted.mjs --self-test :: exit 0
node scripts/check-engine-split-ratio.mjs --self-test :: exit 0
node scripts/check-issue-citations.mjs :: exit 0
node scripts/check-plugin-teardown-shape.mjs :: exit 0
node scripts/check-plugin-teardown-shape.mjs --self-test :: exit 0
node scripts/ci/assert-turbo-remote-cache.mjs --self-test :: exit 0
node scripts/ci/plan-test-core-shards.mjs --self-test :: exit 0
node scripts/ci/prune-turbo-cache.mjs --self-test :: exit 0
node scripts/docs-audit/check-affected-docs.mjs :: exit 0
node scripts/docs-audit/check-drift-comment.mjs :: exit 0
pnpm --filter @objectstack/spec run check:duration-unit-keys :: exit 0
pnpm --filter @objectstack/spec run check:error-code-provenance :: exit 0
pnpm check:adr-symbol-anchors :: exit 0
pnpm check:agent-test-spelling :: exit 0
pnpm check:bash32-floor :: exit 0
pnpm check:ci-filter-parity :: exit 0
pnpm check:cli-command-ids :: exit 0
pnpm check:closed-ceremony-text :: exit 0
pnpm check:cross-package-test-inputs :: exit 0
pnpm check:dispatcher-error-vocabulary :: exit 0
pnpm check:doc-authoring :: exit 0
pnpm check:driver-memory-census :: exit 0
pnpm check:dts-closure :: exit 0
pnpm check:dual-build-cjs-loads :: exit 3
pnpm check:durability-log-level :: exit 0
pnpm check:entry-guard :: exit 0
pnpm check:error-status-conformance :: exit 0
pnpm check:facade-delegation-only :: exit 0
pnpm check:gitlink-declared :: exit 0
pnpm check:issue-citations :: exit 0
pnpm check:keyed-text-bounds :: exit 0
pnpm check:lean-entry-closure :: exit 0
pnpm check:logger-receiver-detach :: exit 0
pnpm check:nul-bytes :: exit 0
pnpm check:object-def-param-keys :: exit 0
pnpm check:optional-error-sink :: exit 0
pnpm check:org-identifier :: exit 0
pnpm check:page-declaration-shape :: exit 0
pnpm check:parse-guard :: exit 0
pnpm check:platform-object-tenancy-census :: exit 0
pnpm check:pnpm-filter-targets :: exit 0
pnpm check:pnpm-flag-spellings :: exit 0
pnpm check:published-files :: exit 0
pnpm check:published-readme-exports :: exit 3
pnpm check:refd-timer-probe :: exit 0
pnpm check:registry-log-declared :: exit 0
pnpm check:rest-log-spy-declared :: exit 0
pnpm check:scripts-symbol-anchors :: exit 0
pnpm check:settings-bind-window :: exit 0
pnpm check:slot-lookup :: exit 0
pnpm check:sourcemap-no-sources-content :: exit 0
pnpm check:swallow-census-controls :: exit 0
pnpm check:system-context-census :: exit 0
pnpm check:test-source-alias :: exit 0
pnpm check:tier-file-adoption :: exit 0
pnpm check:undeclared-dep-imports :: exit 0
pnpm check:vouch-for-reference-callers :: exit 0
pnpm check:watch-hint-literal :: exit 0
node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0
node scripts/check-adr-0087-registration.mjs --self-test :: exit 0
node scripts/check-changeset-no-major.mjs --base origin/main :: exit 0
node scripts/check-empty-changeset.mjs --base origin/main :: exit 0
node scripts/check-empty-changeset.mjs --self-test :: exit 0
node scripts/ci/snapshot-next.mjs --self-test :: exit 0
node scripts/pm/release-rehearsal-clone.mjs --self-test :: exit 0
node scripts/release-pending-publish.mjs --self-test :: exit 0
pnpm check:changeset-gate-self-tests :: exit 0
node scripts/check-adr-links.mjs :: exit 0
node scripts/check-adr-links.mjs --self-test :: exit 0
node scripts/check-doc-route-spelling.mjs --advisory :: exit 0
node scripts/check-doc-route-spelling.mjs --self-test :: exit 0
node scripts/check-docs-section-name.mjs :: exit 0
node scripts/check-docs-section-name.mjs --self-test :: exit 0
node scripts/check-section-landing-index.mjs :: exit 0
node scripts/check-section-landing-index.mjs --self-test :: exit 0
pnpm --filter @objectstack/lint run check:doc-formula-expressions :: exit 0
pnpm --filter @objectstack/lint run check:doc-security-posture :: exit 0
pnpm --filter @objectstack/spec run check:docs :: exit 0
pnpm --filter @objectstack/spec run check:empty-state :: exit 0
pnpm --filter @objectstack/spec run check:liveness :: exit 0
pnpm --filter @objectstack/spec run check:skill-examples :: exit 0
pnpm --filter @objectstack/spec run check:strictness-ledger :: exit 0
pnpm --filter @objectstack/spec run check:variant-docs :: exit 0
pnpm --filter @objectstack/spec run check:yaml-examples :: exit 0
pnpm check:corpus-claim-drift :: exit 0
pnpm check:doc-anchors :: exit 0
pnpm check:doc-frontmatter :: exit 0
pnpm check:docs-audit-scope :: exit 0
pnpm check:docs-redirects :: exit 0
pnpm check:docs-single-h1 :: exit 0
pnpm check:docs-spec-enumerations :: exit 0
pnpm check:docs-transcript-drift :: exit 0
pnpm check:merge-driver :: exit 0
pnpm check:published-readme-links :: exit 0
pnpm check:react-page-adapter-contract :: exit 0
pnpm check:role-word :: exit 0
pnpm check:skill-identifier-liveness :: exit 0
pnpm check:vendor-version-stamps :: exit 0

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

🤖 Generated with Claude Code

… facet

The codemod's --members pass moved it, with its field-call stay reason
lifted for homeLocalizationResolver alone in a one-off local run (the
script is unchanged). Its undo proof rebuilds the base engine.ts and the
facet module byte for byte.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FEkQ5kF4yD4vMatZJ2chQM
… through; retire the two home-amount facade exception rows

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FEkQ5kF4yD4vMatZJ2chQM
…te appAuthored through the new instance's host

Their bodies move into ScopedContextFacet. Each builds a ScopedContext and
writes its private appAuthored through that instance's own host setter (the
port the class's static block fills), so the facade keeps delegations only.
The class surface and its .d.ts are unchanged. The two facade exception rows
retire.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FEkQ5kF4yD4vMatZJ2chQM
…e facet method that now holds it

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FEkQ5kF4yD4vMatZJ2chQM
@github-actions github-actions Bot added size/m documentation Improvements or additions to documentation tooling Fix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surface labels Nov 8, 2026
@github-actions

github-actions Bot commented Nov 8, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/objectql, touching 13 documentable anchor(s).

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

  • content/docs/ai/knowledge-rag.mdx (via executionContext (literal, a string literal in appAuthoredHookApi))
  • content/docs/api/error-handling-server.mdx (via ScopedContext (symbol, a top-level class))
  • content/docs/automation/hook-bodies.mdx (via ScopedContext (symbol, a top-level class))
  • content/docs/automation/jobs.mdx (via executionContext (literal, a string literal in appAuthoredHookApi))
  • content/docs/data-modeling/currency.mdx (via effective_date (literal, a string literal in homeAmountServing))
  • content/docs/permissions/system-context.mdx (via ScopedContext (symbol, a top-level class), appAuthoredHookApi (symbol, a method of class ScopedContextFacet))
  • content/docs/protocol/knowledge.mdx (via executionContext (literal, a string literal in appAuthoredHookApi))
What this run could not see
  • 1 anchor(s) matched too much of the corpus to be a work list: ObjectQL (symbol, 80 pages)
  • 2 name(s) were too generic to anchor anything (single lowercase words)
  • the SDK route bridge reached 63 of 226 client-bound route-ledger rows — the other 163 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 163: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 59 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 104 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.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 21 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 30e0bd160ee2afc1557746df0b6806625f37a408 → packageMentionDocs.

Which tree this was computed on

This run read content/docs from aeeb5540bb565e3ce7515fcb5db604671a0dc1f3 — the merge of head 7d5f631fc499bee9a4ac560361d3857a683e82a5 into base 30e0bd160ee2afc1557746df0b6806625f37a408, 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 aeeb5540bb565e3ce7515fcb5db604671a0dc1f3 && git checkout aeeb5540bb565e3ce7515fcb5db604671a0dc1f3
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 30e0bd160ee2afc1557746df0b6806625f37a408 7d5f631fc499bee9a4ac560361d3857a683e82a5 && git checkout -B drift-repro 30e0bd160ee2afc1557746df0b6806625f37a408 && git merge --no-ff 7d5f631fc499bee9a4ac560361d3857a683e82a5

node scripts/docs-audit/affected-docs.mjs --json 30e0bd160ee2afc1557746df0b6806625f37a408

⚠️ 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 30e0bd160ee2afc1557746df0b6806625f37a408 → pass the list as
args.docs, on the commit named under Which tree this was computed on.

@objectstack-fleet objectstack-fleet Bot added the domain:server Domain lane — seat card indexed by label:pm:seat label Nov 8, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:server#6 · os-project-manager · session_01FEkQ5p3T5YWhLjurajudnQ

席位核对 · ACCEPT · 2026-11-08T03:32Z · head 7d5f631fc499bee9a4ac560361d3857a683e82a5

Seat domain:server#6 reviewed the diff of its own dispatch (claim 6716015993 and amendment 6716417615 on #30975, card thread session_01FEkQ5kF4yD4vMatZJ2chQM, report 6716510884). Read against GitHub, not the report.

  1. Shape: 6 files, +118 / -104. All four engine.ts exception rows that Facade codemods: retire the codemod-limit exception rows in the facade gate registry (protocol.ts, engine.ts, sql-driver.ts) #30147's ruling handed to this card are retired, and their registry rows are deleted.
    • ObjectQL#homeAmountServing moves into ReferencesAndMasterDetailFacet by the codemod's --members move, with its undo proof. Its one call of the home-localization resolver now goes through the facet host; the resolver type takes no this, and the one the platform installs is an arrow function.
    • projectHomeAmountsOntoPatch's stub passes serving through, and the facet computes the default when none is given.
    • ScopedContext.derive and [APP_AUTHORED_HOOK_API] move into ScopedContextFacet. Each writes the new instance's private appAuthored through that instance's own host, scopedContextHost.of(child). The host gains one setter in the class's static block. scopedContextHost is imported only by engine.ts and engine-scoped-context.ts, and the package entry does not re-export it. So nothing outside the engine can reach the setter.
    • Body says Fixes #30975; no other closing keyword.
  2. Public surface: the built .d.ts base-vs-head diff has 0 declaration lines. The 16 comment lines are the two private members' JSDoc that left with their bodies, plus a chunk hash rename. Accepted as a deviation from "byte-identical": no type a consumer reads moves.
  3. Tests: objectql vitest base 604a2b3b and head both 565 files / 11428 tests; typecheck exit 0. Two ablations on the new host write went red (6 and 9 failed in purge.test.ts + hook-run-as.test.ts), each restored to HEAD. That proves a derived api keeps the app-authored mark and an app-authored hook's api still refuses a permanent delete.
  4. Fallout in the amended surface: content/docs/permissions/system-context.mdx row 1b's Symbol cell is re-keyed from inheritsElevation to appAuthoredHookApi, and the census register is regenerated, because the elevation read now lives in the facet. No prose on the page changed.
  5. Gates / check-runs: 103 derived gates, 103 run, 0 NOT-MEASURED (30975-gates-ran-r2.txt). check:dual-build-cjs-loads and check:published-readme-exports exited 0 after a full workspace build. The report's first record listed them as NOT MEASURED; r2 replaces it. CI on 7d5f631f: 55 runs, 39 success, 16 skipped, 0 red; mergeable_state clean. check-facade-delegation-only is green in CI.
  6. Contract review: Clause-②: no (private members move, and the public .d.ts is unchanged in declarations), no packages/spec/src path, and check-owed-reviews lists no owed review for this PR: none owed.
  7. Out of scope: nothing. Metadata-protocol: none; Skills-docs: not owed. Changeset patch for @objectstack/objectql.
  8. Landing: check-governed-merges --pr 31343: not governed, 222 changed lines. Landing on the maintainer's standing words 「按照 pm-dispatch 规则复核过的都授权」 (2026-10-25T11:35Z) and 「你应该使用 pm-dispatch 技能审核和落地pr」 (2026-11-07T16:59Z). Relay pr_ready, then automerge_enable.

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review November 8, 2026 03:33
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge November 8, 2026 03:33
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Nov 8, 2026
Merged via the queue into main with commit f6199a8 Nov 8, 2026
56 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/project-thread-20kprd branch November 8, 2026 03:56
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 domain:server Domain lane — seat card indexed by label:pm:seat size/m tooling Fix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surface

Projects

None yet

Development

Successfully merging this pull request may close these issues.

objectql engine.ts: retire the four facade-gate exception rows #30147 hands over

1 participant