Skip to content

refactor(objectql): generate the engine.ts section split with a deterministic codemod - #30012

Merged
objectstack-fleet[bot] merged 14 commits into
mainfrom
claude/project-thread-xwdm5r
Nov 4, 2026
Merged

objectstack-fleet[bot] merged 14 commits into
mainfrom
claude/project-thread-xwdm5r

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

Requested by Yibo Wang · project thread

Part of #29986

维护者速读

  • 改了什么:codemod scripts/codemod-split-engine.mjs 按裁决 6624345766 的门面形态拆分 engine.ts。ObjectQL 的 161/278 个方法体(未修改)移进 16 个无状态 facet 类(每个分节模块一个类,类里是静态方法)。146/146 个顶层声明移进叶子模块 engine-top-level.ts。类上留下签名和一个调用 facet 的 stub。私有方法的 docblock 随方法体移走,公开方法和受保护方法的 docblock 留在类上。方法体读私有静态成员时经 ObjectQLStatics 转发。状态仍在 ObjectQL 上。生成的文件没有手改。按路径读 engine.ts 的读者跟着代码读新模块。
  • 为什么改:[Decision] Large source files: replace the hand-cut split with a script-generated split per file, so the remaining monoliths split in days, not months #29465 大文件拆分;裁决 6624345766 把 13,000 行门槛换成结构门禁(门面文件里不留方法体,例外具名列出,见 tooling: a structural gate that refuses any method body in a facade file once protocol.ts and engine.ts land in facade form (ruling 6624258595) #30019)。
  • 风险与回滚:只是搬移。161/161 个方法体、146/146 个顶层声明逐字节相同。撤销拆分会逐字节还原 base 的 engine.ts。objectql 测试 base 10,829 = head 10,829,typecheck 0 错。打包后的 .d.ts 公开面相等(裁决 6624345766 第 1 条)。回滚方式是 revert。
  • 先看:① 下方「例外」表(31 个方法体留在类上,以及原因);② ObjectQLStatics 和类末尾的 static 块;③ 下方「按路径读的读者」表。
  • 两分钟验证:pnpm install --frozen-lockfile 之后运行 node scripts/codemod-split-engine.mjs --verify --base 0b99c2b1,应输出 161/161 moved bodies identical、146/146 moved top-level declarations identical、23245 -> 14140 lines,退出码 0;node scripts/codemod-split-engine.mjs --self-test 应通过 62 例。
  • 需要你做的:改动超过 3,000 行,需要您批准,并在您定的窗口里落地;本 PR 保持草稿。

Clause-②: no
Metadata-protocol: none

What changes

  • scripts/codemod-split-engine.mjs (new). It plans the split, writes it and proves it. It follows the pilot's form (refactor(driver-sql): codemod pilot — generated, byte-identity-proved section split of sql-driver.ts (#29520) #29598) and these rulings: 6591753301 A (levers (a) and (b)), 6597555122 A (by-path readers widen in the same PR) and 6624345766 (the facade shape, below).
    • Stateless facets. Each section module holds one class, <Section>Facet, whose static methods are the moved bodies, unedited (static name(this: Pick<SectionHost, …>, …)). A class member can take any name, so a reserved word (delete) or a name an import already takes no longer keeps a body on the class.
    • Host pattern. The stub hands the body one literal holding the members it reads. Methods go as closures called on the engine at call time, so spies and overrides still work. Fields and accessors go as getters. A field a body assigns also gets a setter (31 stubs).
    • Docblock ownership. A private method's docblock moves with its body (87 moved). A public or protected method keeps its docblock on the class, and the facet member carries a one-line placeholder that points there.
    • Private-static-through-host. engine.ts declares ObjectQLStaticsHost (each member typed (typeof ObjectQL)['x']) and ObjectQLStatics. A static block at the end of the class fills the object with forwarders: a method is called on the class, a field is read when read. A facet module whose bodies read a private static imports ObjectQLStatics AS ObjectQL, so the body text does not change (4 modules, 12 statics). index.ts re-exports neither.
    • Generic methods call their body instantiated with their own type parameters, (Facet.name<T>).call(host, …). A defaulted parameter forwards the value the stub's default produced. A static method whose body reads no this moves too.
    • The no-yield rule is dropped, because the structural gate counts bodies, not lines.
    • PATH_READER_PINS keeps six methods that carry a lint 规则:禁止对引擎/驱动查询选项做 as any / : any 擦除(#4721 的顺带项,已实测残余量) #4918 opts as any site on the class. The guard grandfathers by file, and its baseline may only shrink.
    • --self-test: 62 cases in 6 batteries (stay rules 20; facets, statics and docblocks 11; top-level moves 11; byte-identity proof 10; import prune 4; refusals 6). Each proof is fed an input it must refuse.
  • The generated split. --write on main 9d1a465f (its engine.ts is the base 0b99c2b1 one), unedited. New files: engine-compatibility-section.ts, engine-migration-state.ts, engine-transactions-section.ts. Changed: the 13 earlier section modules and engine.ts.

Facets

Module Facet Bodies
engine-hooks-and-functions.ts HooksAndFunctionsFacet 14
engine-actions.ts ActionsFacet 11
engine-security-resolvers.ts SecurityResolversFacet 13
engine-middleware-and-context.ts MiddlewareAndContextFacet 11
engine-defaults-and-autonumbers.ts DefaultsAndAutonumbersFacet 10
engine-registration.ts RegistrationFacet 12
engine-references-and-master-detail.ts ReferencesAndMasterDetailFacet 11
engine-secrets-and-routing.ts SecretsAndRoutingFacet 11
engine-migration-state.ts MigrationStateFacet 12
engine-summaries-and-expansion.ts SummariesAndExpansionFacet 8
engine-find.ts FindFacet 7
engine-insert.ts InsertFacet 5
engine-cascade-planning.ts CascadePlanningFacet 20
engine-delete-and-aggregate.ts DeleteAndAggregateFacet 2
engine-transactions-section.ts TransactionsSectionFacet 5
engine-compatibility-section.ts CompatibilitySectionFacet 9

Another 86 methods were already stubs from the hand series (#25522). Their docblocks stay on the class, because this codemod does not edit the hand-series modules.

Exceptions: bodies that stay on the class (31, for the #30019 allow-list)

Reason Methods (body lines)
bare this (16) update 2099, insert 1384, delete 690, find 225, findOne 191, recomputeSummaries 99, resolveReadableIdsSecurity 35, bindHooks 32, readMigrationFlagRowMemoized 27, createContext 18, ownershipQueueService 14, buildHookApi 10, setHookMetricsRecorder 9, setStrictHookBinding 8, setWarnLegacyHandler 4, getHookMetricsRecorder 4
inferred public return type (8) registerApp 149, registerHook 89, registerDriver 82, init 68, triggerHooks 52, destroy 22, setDatasourceMapping 17, getStatus 12
#4918 erasure pin (6) seedAutonumber 152, probeReferencingRows 116, resolveMasterDetailParent 110, resolveMasterDetailParents 75, inspectDanglingReferences 67, referenceExists 35
field call (1) homeAmountServing 54 (it calls the field homeLocalizationResolver, and the host would change the receiver)

ObjectRepository and ScopedContext (696 lines) are not facaded by this codemod.

Tests

Reading Base Head
objectql test (local) 547 files, 10,829 passed 547 files, 10,829 passed
objectql test:repo 5 passed 5 passed
objectql typecheck (tsc + check:test-typecheck) exit 0 exit 0
core test:repo 94 passed

Readers of engine.ts by path

Reader Now
engine-middleware-operation-vocabulary.test.ts (#7809 weld) reads engine.ts and engine-top-level.ts
federated-injected-column-readers.test.ts (#21918) rows keyed to the facet module holding each site; ENGINE_SPLIT_FILES names all 16 modules and the leaf, and a via resolves across them
scripts/check-stack-collection-maps.mjs the METADATA_ARRAY_KEYS row reads engine-top-level.ts
core second-object-read-exposure.pin.test.ts the executes row names engine-summaries-and-expansion.ts; two not-a-served-read rows for engine-security-resolvers.ts and engine-top-level.ts
check:liveness field/summaryOperations, field/autonumberFormat and datasource/external.rowCap cite the facet modules
check-system-context-census site register regenerated with --write; no row changed
check-adr-anchors, functional-completeness.ts anchors name engine-top-level.ts
eslint query-options/no-any-erasure, check:query-options-erasure unchanged: the six sites stay in engine.ts

Ablations, each red and then restored: a federated row re-keyed back to engine.ts (3 tests red); the core executes row put back on engine.ts (2 red); 'purge' added to OperationContext in the leaf (both weld tests red); 'ablatedCollection' added to METADATA_ARRAY_KEYS (check-stack-collection-maps red). The liveness and census reds were observed before their fixes.

.d.ts: public surface (ruling 6624345766 item 1)

The reading is /mnt/project-files/issue-29986/pubsurface.mjs. It applies dtsnorm's second normalisation (ruling 6441032442 B) after removing each private class member, with its leading docblock. Built dist: main 1 = main 2 and head 1 = head 2, byte for byte.

File statements private members public surface exported names
core.d.ts, core.d.mts 16 / 16 0 / 0 equal equal
index.d.ts, index.d.mts 168 / 168 94 / 94 equal equal
util-HASH.d.ts, util-HASH.d.mts 190 / 190 332 / 332 equal equal

Controls: a private member made public is caught; a public member's printed type changed is caught; a private docblock edit is not caught. Strict 6441032442 B, for reference: util-HASH differs in one statement (the ObjectQL class, by its moved private docblocks), and its surface digest is equal. ObjectQLStatics and the facets appear in no .d.ts.

Verification

Reading Result
Byte-identity (--verify --base 0b99c2b1) exit 0: 161/161 bodies and 146/146 declarations identical; the moved docblocks and the placeholders are checked, the statics block is rebuilt from the base class, and the undo rebuilds the base engine.ts once the 107 pruned bindings are re-derived
Determinism two generations from the same input are identical; tree sha256 2723df98712b1831ad01067458bcfaa3695ff9a3eb8a7e0c46e1566f007c8e73 (input dc5677f3ef529f5272d95855361202d9948cb802a89fc3df80dca16dea3e1384), the same as the tree on disk
pnpm build, pnpm lint, check-nul-bytes exit 0
dispatch-gates --commands 126 derived, 126 run, all exit 0; --ran: 0 NOT-MEASURED, 0 UNRUN

No changeset: the pilot #29598 shipped none (skip-changeset), and this PR follows it.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WGufzhfKpcY1cmybduYBcp

scripts/codemod-split-engine.mjs is the large-file programme's codemod for
packages/objectql/src/engine.ts, modelled on the sql-driver pilot: whole
sections of ObjectQL's method bodies move to section modules behind the
hand series' host pattern, the top-level declarations ahead of the class
move whole into a leaf, and the script proves byte-identity, determinism
and the declaration-file bar. Sections are named by anchor member, and
the import bindings only moved text read are pruned (noUnusedLocals),
with the prune recomputed from the head in the proof.

Claude-Session: https://claude.ai/code/session_01WGufzhfKpcY1cmybduYBcp
Co-authored-by: Claude <noreply@anthropic.com>
Output of `node scripts/codemod-split-engine.mjs --write` on main 0b99c2b,
not edited by hand: 39 ObjectQL method bodies move into 13 section
modules, the 146 top-level declarations ahead of the class move whole into
engine-top-level.ts, and engine.ts drops the 85 import bindings only the
moved text read. engine.ts goes from 23,245 to 16,869 lines.

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

objectql's bundled declarations live in a hashed shared chunk that
index.d.ts re-exports, so the pilot's index-only --dts check cannot read
the bar here. Ruling 6441032442 item 3 keeps the second normalisation out
of scripts/, so the PR reports it on two built dists instead, as the
protocol.ts codemod does.

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

The #4918 erasure guard grandfathers its pre-existing sites by file
(eslint QUERY_OPTIONS_UNSWEPT plus a per-file count in
scripts/query-options-erasure-baseline.json, which may only shrink).
seedAutonumber and inspectDanglingReferences each carry one site, so
moving their bodies redded `pnpm lint` and check:query-options-erasure.
They become PATH_READER_PINS and stay.

Claude-Session: https://claude.ai/code/session_01WGufzhfKpcY1cmybduYBcp
Co-authored-by: Claude <noreply@anthropic.com>
…thods kept

`node scripts/codemod-split-engine.mjs --write` on base 0b99c2b,
unedited. 37 of 278 methods and 146 of 146 top-level declarations move;
engine.ts 23245 -> 16933 lines. `--verify --base 0b99c2b` exits 0.

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

Ruling 6597555122 A: a test or gate that reads engine.ts by path gains
the new modules in its reading list.

- engine-middleware-operation-vocabulary.test.ts reads engine.ts and
  engine-top-level.ts, where OperationContext now lives.
- federated-injected-column-readers.test.ts re-keys the 13 seam rows
  whose sites moved, and resolves a `via` helper across engine.ts and
  its split modules.
- check-stack-collection-maps reads METADATA_ARRAY_KEYS from the leaf.

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

The second-object-read exposure pin keys CALLERS by file. The engine.ts
split moved resolveFormulaRelated into engine-security-resolvers.ts and
deleteWalkTargetOf into engine-top-level.ts; neither serves a field of
the target, so both are `not-a-served-read` rows.

Claude-Session: https://claude.ai/code/session_01WGufzhfKpcY1cmybduYBcp
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 4, 2026
@github-actions

github-actions Bot commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 2 package(s): @objectstack/objectql, @objectstack/spec, touching 668 documentable anchor(s). ⚠️ 3 changed file(s) yielded no anchor (packages/spec/liveness/datasource.json, packages/spec/liveness/field.json, packages/spec/src/kernel/functional-completeness.ts), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files.

118 hand-written doc(s) name something this change touched — list omitted above 15 rows. Re-derive on the tree named below: node scripts/docs-audit/affected-docs.mjs --json 140d8ce805dc55245d9841a6ece6dfb956d9e071.

⛔ 18 release-owned page(s) also affected — read-only, see AGENTS.md Documentation Guardrails.

What this run could not see
  • 3 changed file(s) yielded no anchor (packages/spec/liveness/datasource.json, packages/spec/liveness/field.json, packages/spec/src/kernel/functional-completeness.ts) — pages documenting those are invisible to this run
  • 1 cross-cutting symbol(s) contributed no route anchor: packageId (4 routes)
  • 5 anchor(s) matched too much of the corpus to be a work list: ObjectQL (symbol, 80 pages), current_user (literal, 44 pages), master_detail (literal, 40 pages), organization_id (literal, 38 pages), /data/:object (route, 76 pages)
  • 54 name(s) were too generic to anchor anything (single lowercase words)
  • the SDK route bridge reached 61 of 219 client-bound route-ledger rows — the other 158 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 158: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 55 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 103 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 — 171 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 140d8ce805dc55245d9841a6ece6dfb956d9e071 → packageMentionDocs.

Which tree this was computed on

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

node scripts/docs-audit/affected-docs.mjs --json 140d8ce805dc55245d9841a6ece6dfb956d9e071

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

The codemod split moved FormulaPlanEntry (whose `expression` member
ADR-0072's evaluator table anchors) and planFormulaProjection into
engine-top-level.ts, so check:adr-symbol-anchors and
check:spec-docblock-symbol-anchors found no declaration in engine.ts.
Both anchors now name engine-top-level.ts, where the declarations are.

Claude-Session: https://claude.ai/code/session_01WGufzhfKpcY1cmybduYBcp
Co-authored-by: Claude <noreply@anthropic.com>
check:liveness's key-mention anchoring found field/summaryOperations and
datasource/external.rowCap citing engine.ts, which no longer names
either key: buildSummaryIndex's body moved to
engine-summaries-and-expansion.ts and applyExternalDriverFloor's to
engine-registration.ts. Both citations name those files now.

Claude-Session: https://claude.ai/code/session_01WGufzhfKpcY1cmybduYBcp
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added the documentation Improvements or additions to documentation label Nov 4, 2026
… shape

Ruling 6624345766 (on #29465) set the shape for engine.ts: docblock
ownership, private-static-through-host and stateless facet classes over
the host, with state staying on ObjectQL. The codemod now writes it:

- Each section module holds one stateless class, `<Section>Facet`, whose
  static methods are the moved bodies, unedited. Class members may take
  any name, so a reserved word (`delete`) or a name an import takes no
  longer keeps a body on the class.
- A private method's docblock moves with its body; a public or protected
  one stays on the class, which keeps the public surface as it was.
- A body that reads a private static goes through `ObjectQLStatics`, a
  forwarder object engine.ts declares (typed by indexed access on the
  class) and a static block fills. The facet module imports it AS
  `ObjectQL`, so the body text does not change.
- A field a body assigns goes through a host setter.
- Generic methods call their body instantiated with their own type
  parameters, defaulted identifier parameters forward their value, and a
  static method whose body reads no `this` moves too.
- The no-yield rule is gone: the 13,000-line bar is replaced by the
  structural gate, which counts bodies, not lines.
- Four more methods carrying a #4918 `as any` site are pinned on the
  class, as seedAutonumber and inspectDanglingReferences were.

verify now also restores the moved docblocks, checks each placeholder,
and rebuilds the forwarder declarations and static block from the base
class. The self-test has 62 cases in 6 batteries.

Claude-Session: https://claude.ai/code/session_01WGufzhfKpcY1cmybduYBcp
Co-authored-by: Claude <noreply@anthropic.com>
`node scripts/codemod-split-engine.mjs --write` on main 9d1a465, whose
engine.ts is the base 0b99c2b one. Unedited. 161 of 278 method bodies
move into 16 stateless facet classes, and the 146 top-level declarations
stay in engine-top-level.ts. engine.ts goes from 23,245 to 14,140 lines.
Three new modules: engine-compatibility-section.ts,
engine-migration-state.ts and engine-transactions-section.ts.

`--verify --base 0b99c2b` proves 161/161 bodies and 146/146
declarations byte-identical, and the undo rebuilds the base engine.ts.

Claude-Session: https://claude.ai/code/session_01WGufzhfKpcY1cmybduYBcp
Co-authored-by: Claude <noreply@anthropic.com>
The regenerated split moved more bodies out of engine.ts, so two by-path
readers follow them (ruling 6597555122 A):

- federated-injected-column-readers.test.ts: 8 rows re-keyed to the
  facet modules that now hold their sites (planCascadeAtomicity,
  organizationOwnedRowCounts, keepsOrganizationReference,
  expandRelatedRecords, recordObservedDeviation,
  retractCreationAttestation), and ENGINE_SPLIT_FILES names the three new
  modules.
- core second-object-read-exposure.pin.test.ts: the `executes` row for
  `ObjectQL.expandRelatedRecords` names engine-summaries-and-expansion.ts,
  where its referenceTargetOf call now is.

Claude-Session: https://claude.ai/code/session_01WGufzhfKpcY1cmybduYBcp
Co-authored-by: Claude <noreply@anthropic.com>
…acade split

Two more by-path readers follow the regenerated split:

- check:liveness: field/autonumberFormat cited engine.ts#applyAutonumbers,
  whose body is now in engine-defaults-and-autonumbers.ts. The evidence
  names that file.
- check-system-context-census: `--write` regenerated the site register,
  which moves the dependentCountIsDisclosable read from engine.ts to
  engine-cascade-planning.ts. No row changed.

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

Copy link
Copy Markdown
Contributor Author

domain:server#6 · os-support-ai · session_01WGufzibcN9oHa8kDbTTnL5

席位核对

Verdict: ACCEPT at head f48078bb671eee96feaac7f33c281416dd25f0dc · 2026-11-04T10:05Z

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review November 4, 2026 10:06
@objectstack-fleet
objectstack-fleet Bot requested a review from hotlong as a code owner November 4, 2026 10:06
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge November 4, 2026 10:06
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Nov 4, 2026
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/xl 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.

2 participants