Skip to content

fix(scripts): engine-double-contract vetoes a native Mongo Collection fake by its own members - #30499

Merged
objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/project-thread-1o35e8
Nov 5, 2026
Merged

objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/project-thread-1o35e8

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Bill · project thread

domain:server#6 · os-bill · session_01Utp6CXCS98uhsFQYk64epE

维护者速读

  • 改了什么:引擎替身检查门禁(check:engine-double-contract)新增一条否决:测试里伪造的 MongoDB 原生 Collection(带 insertOne / updateOne 这类只有原生驱动才有的方法)不再被当成 ObjectQL 引擎替身;driver-mongodb 那个为了过门禁被拆成两半的假对象恢复成原本的一个整体。
  • 为什么改:这类假对象同时有 find、insertMany、findOne,门禁按方法名把它误判成引擎替身,逼着写测试的人把假对象拆开来绕门禁;它的 findOne(filter, options) 根本不收对象名,不是引擎。
  • 风险与回滚:否决只在 findOne 第一个参数不是对象名时生效,真正的引擎替身照样被抓(自检有对照);全仓前后读数一致(1230 已钉 / 120 欠账 / 3 豁免),否决只移走这一处、0 个已钉。回滚即撤本 PR,只动门禁脚本和一个测试文件。
  • 先看:scripts/check-engine-double-contract.mjs 的 NATIVE_COLLECTION_ONLY_MEMBERS 和 isEngineVerbShape 里新增的否决分支;同文件自检里的 NATIVE COLLECTION 一组;packages/drivers/driver-mongodb/src/mongodb-declared-column-null-on-write.test.ts。
  • 两分钟验证:node scripts/check-engine-double-contract.mjs --census,预期末尾一行 NATIVE_COLLECTION_ONLY_MEMBERS veto moves 1 construct(s); 0 of them pinned,点名的正是那个 Mongo 测试文件。
  • 需要你做的:无,席位落地。

Fixes #29859

Clause-②: no
Metadata-protocol: none
Skills-docs: none — gate script only

What changes

The false red. scripts/check-engine-double-contract.mjs attributed an object literal to the ObjectQL engine contract by its member names. A fake of MongoDB's native Collection declaring insertOne / insertMany / updateOne / findOne / find held two engine siblings (find, insertMany) beside findOne, so it was discovered as a findOne engine double. isEngineVerbShape then admitted it on either arity path: a two-parameter findOne(filter, options) has a second parameter that is neither an id nor a string, and a short-arity findOne(filter) reads insertMany as ENGINE_ONLY_MEMBERS evidence.

Which evidence was wrong. Measured, not assumed: insertMany is a real member of the engine class (ObjectQL.insertMany(object, rows, options), packages/objectql/src/engine.ts), so removing it from ENGINE_ONLY_MEMBERS would weaken the engine-side evidence, and it would not have fixed the two-parameter case anyway. What was missing is positive evidence of the OTHER shape. So this adds a fourth arm to the existing evidence architecture:

  • NATIVE_COLLECTION_ONLY_MEMBERS = insertOne, updateOne, deleteOne, replaceOne, bulkWrite, countDocuments, estimatedDocumentCount, findOneAndUpdate, findOneAndDelete, findOneAndReplace. Verified name by name: none is declared in packages/objectql/src/engine.ts, nor on IDataEngine, IDataDriver or IScopedObjectRepository (packages/spec/src/contracts/); the same grep's control leg hits insertMany in engine.ts and findOne in the contracts. updateMany / deleteMany are left out because DRIVER_ONLY_MEMBERS already vetoes them; distinct / createIndex / watch are left out as too generic to mean "Mongo".
  • The veto in isEngineVerbShape runs right after the scoped-repository veto and under the same object-name guard (takesObjectNameFirst): the member is the evidence, and a verb that takes the object name first keeps the literal in scope however many Mongo-named helpers hang off it. So a real engine double cannot leave scan scope by declaring insertOne.
  • Decided by signature evidence, not by a file name: no path is exempted and no ledger row is added (the baseline is untouched).
  • --census now ablates this veto on its own, beside the repository veto, so its reach is re-derivable: on this tree it moves exactly 1 construct, 0 of them pinned.

The bent test, restored. packages/drivers/driver-mongodb/src/mongodb-declared-column-null-on-write.test.ts had been split into singleRowDb() / batchDb() only so the gate would not see insertMany + find beside findOne. It is one fakeDb() again, the natural shape the driver sees ((driver as any).db = { collection: () => collection }); the three tests are unchanged.

Changeset: none, skip-changeset: the diff publishes nothing. scripts/** is repo-root tooling, and the driver-mongodb file is a test (files: ["dist", "README.md", "CHANGELOG.md"], tsup entry src/index.ts).

Tests

  • Red first, on main's gate (f273c9f) with the restored test: node scripts/check-engine-double-contract.mjs exit 1, x PINNED [findOne]: packages/drivers/driver-mongodb/src/mongodb-declared-column-null-on-write.test.ts declares 1 engine double(s) whose findOne() does not route through assertEngineFindOnePredicate (line 65).
  • Green: the same run on HEAD exit 0, OK — 1230 pinned, 120 in the DEBT ledger, 3 exempt.
  • New self-test battery The NATIVE COLLECTION, the fourth shape (#29859). (7 cases, floor pinned at 7, roster floor 34 → 35), as A/B pairs: the five-member native fake is out of scope for the findOne slice and the same literal without insertOne/updateOne is discovered; the same pair at one-parameter findOne(filter); the control the card names, an engine double holding find/insertMany plus engine members, is still an unpinned findOne double; an engine double that also declares insertOne stays in scope; a mixed fixture reports exactly the engine double.

Acceptance notes

  • insertMany stays in both ENGINE_SIBLINGS and ENGINE_ONLY_MEMBERS, deliberately (engine member, measured above).
  • A native fake that declares none of the ten names (for example only insertMany + find + findOne) is still discovered. That is the A/B control, and the restored test needs insertOne/updateOne anyway; widening further is a --census measurement, not part of this card.

Verification

All readings on head f443d8b1 (branch merged with origin/main at f506b79, a merge with no overlap with this diff) unless noted.

Gate script: red on main's bytes, green here, one ablation
  • Red: main's gate (f273c9f) over the restored test, node scripts/check-engine-double-contract.mjs exit 1, one problem: x PINNED [findOne]: …mongodb-declared-column-null-on-write.test.ts declares 1 engine double(s) whose findOne() does not route through assertEngineFindOnePredicate (line 65).
  • Green: exit 0, OK — 1230 pinned, 120 in the DEBT ledger, 3 exempt.; --self-test exit 0; --census exit 0, NATIVE_COLLECTION_ONLY_MEMBERS veto moves 1 construct(s); 0 of them pinned, naming only mongodb-declared-column-null-on-write.test.ts:65.
  • Full-repo output before/after (main with the split test vs this branch with the restored one, 0e5fa59): byte-identical apart from the run's exit line; 1230 / 120 / 3, 1133 retained rows, 7122/4386/1252/1133 provenance on both.
  • Ablation (once, through scripts/ablation-replace.mjs, anchor 1 → 0, blob 6bad367f → de0d3adc): the veto's if prefixed with false &&. --self-test: 3 failures, a five-member native Mongo Collection fake is out of scope for the findOne slice, a one-parameter native findOne beside insertMany is out of scope, a mixed fixture reports EXACTLY the engine double, not the native Collection; the full run exit 1 naming the Mongo test file. Restored: blob == HEAD 6bad367f, git diff HEAD empty.
Package suites
  • Under os-verify-lock.sh (VERDICT command-exit 0): pnpm --filter '@objectstack/driver-mongodb...' build, then pnpm --filter @objectstack/driver-mongodb test (Test Files 35 passed, 6 skipped; Tests 728 passed, 194 skipped), then pnpm --filter @objectstack/driver-mongodb typecheck (tsc + check:test-typecheck OK, 0 debt). The restored file alone: 3/3.
Derived gates and lint
  • node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack: 68 commands, each run with its exit recorded before any pipe; all 68 exit 0. --ran reconciliation: 68 derived, 68 run, 0 NOT-MEASURED, 0 UNRUN.
  • pnpm lint exit 0; check-nul-bytes exit 0.
  • Not run locally, CI's: the dogfood battery (no !, no narrowing arm) and the test:repo project.

Generated by Claude Code

… fake by its own members

A fake of MongoDB's native Collection (insertOne/insertMany/updateOne/
findOne/find) held two engine siblings and a two-parameter findOne, so the
gate read it as an engine findOne double. NATIVE_COLLECTION_ONLY_MEMBERS is
positive evidence of that shape, consulted under the same object-name guard
as the scoped-repository veto: an engine double whose findOne takes the
object name first stays in scope, and insertMany stays engine evidence.

Claude-Session: https://claude.ai/code/session_01Utp6CXoPqLaG33jM98mL1R
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Nov 5, 2026
@github-actions

github-actions Bot commented Nov 5, 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

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 48231b024ed7a9f0c9be73f34a5bf5f48c7a1d68 → packageMentionDocs.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:server#6 · os-bill · session_01Utp6CXCS98uhsFQYk64epE

席位核对 · ACCEPT · 2026-11-05T13:39Z · head f443d8b1

Reviewed against order server-seat6/dispatch-29859.md (Claim 6657967578), against the PR's own file list and diff.

  • Shape. check-engine-double-contract.mjs gains NATIVE_COLLECTION_ONLY_MEMBERS (native-only Collection names such as insertOne/updateOne), a veto that applies under the same object-name guard as the repository veto. insertMany stays engine evidence (it is a real ObjectQL member). The evidence narrows by signature, not by file name: no exemption.
  • Pins. Self-test gains a native-Collection group (red on main, green here) with an engine-double control that still reads as one; one ablation, three self-tests red, restored. Full tree before/after 1230 pinned / 120 debt / 3 exempt unchanged; --census shows the veto moves 1 construct, 0 pinned. The driver-mongodb fake that had been split to satisfy the gate is one object again.
  • Declarations. Clause-②: no, Metadata-protocol: none, skip-changeset (gate script + one test file), Skills-docs: none. Not BREAKING.
  • Accepted deviations. The order offered either narrowing; the dev chose positive evidence of the other shape over removing insertMany, which keeps real engine doubles caught. Accepted.
  • Gates. check-governed-merges --pr 30499: not governed, 204 changed lines. 68/68 derived gates exit 0 locally (dev reading). Author objectstack-fleet[bot] (relay).

Landing: ready + auto-merge; the queue waits for every check (main-red stop PR #30487 ahead of it).

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review November 5, 2026 13:40
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge November 5, 2026 13:40
@objectstack-fleet
objectstack-fleet Bot disabled auto-merge November 5, 2026 13:48
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:server#6 · os-bill · session_01Utp6CXCS98uhsFQYk64epE

席位记录 · 2026-11-05T13:49Z · Head-sha f443d8b1 · 补记(ACCEPT 6659440182 之后)

维护者速读(席位按 diff 校正)

  • 改了什么:引擎替身检查门禁新增一条否决:测试里伪造的 MongoDB 原生 Collection(带 insertOne/updateOne 这类只有原生驱动才有的方法)不再被误判成 ObjectQL 引擎替身;driver-mongodb 那个为过门禁被拆开的假对象恢复成一个。
  • 为什么改:门禁按方法名认替身,find、insertMany、findOne 撞名导致误报,逼测试作者绕门禁。
  • 风险与回滚:只动门禁脚本和一个测试文件;真引擎替身照样被抓(自检有对照),全仓前后读数一致。回滚即撤本 PR。
  • 先看:scripts/check-engine-double-contract.mjs 的 NATIVE_COLLECTION_ONLY_MEMBERS 与新增否决分支。
  • 两分钟验证:node scripts/check-engine-double-contract.mjs --census,末行显示否决只移走 1 处、0 个已钉。
  • 需要你做的:无。非受管面、非 BREAKING,技能不要求你审,席位落地。

席位意见:同意落地。修法是给另一种形状加正面证据,没有减少引擎证据,也没有按文件名豁免。

席位核对

  1. 形态:draft→ready,目标 main,Fixes #29859;作者 objectstack-fleet[bot](中继);标签 skip-changeset(门禁脚本 + 测试文件,无发布包改动)。
  2. 前提实测:origin/main c5800818 上 ENGINE_ONLY_MEMBERS 含 insertMany(席位读,L481);误报由 dev 在主线复现为红。
  3. 门禁 check-runs(钉 head f443d8b1):53 条,读数时 29 success、18 skipped、6 条 Test Core 在跑、0 失败;Lint & Repo Gates success、TypeScript Type Check success。全绿前不入队(见第 6 条)。
  4. 接受的偏差:派单令允许两种收窄,dev 选了给原生 Collection 加正面证据、保留 insertMany 为引擎证据,接受。
  5. 范围外去向:无。Skills-docs: none — gate script only,Clause-②: no,Metadata-protocol: none。
  6. 落地条款:check-governed-merges --pr 30499:NOT governed,204 行。auto-merge 先前挂得早于全绿,席位已撤挂;全部 check 绿后再挂 auto-merge 入队。合并后席位写落地、摘标。

@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Nov 5, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:server#6 · os-bill · session_01Utp6CXCS98uhsFQYk64epE

席位核对第 3、6 条补读 · 2026-11-05T13:58Z · head f443d8b1:54 条 check-runs 全部完成,36 success、18 skipped、0 失败。已重新挂 auto-merge 入队。

Merged via the queue into main with commit 400b41b Nov 5, 2026
54 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/project-thread-1o35e8 branch November 5, 2026 15:17
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

1 participant