Skip to content

feat(scripts): codemod-split-protocol --members moves the bodies E1 refuses, unedited, and retires nineteen protocol.ts facade rows - #30954

Queued
objectstack-fleet[bot] wants to merge 5 commits into
mainfrom
claude/project-thread-to5pdz
Queued

objectstack-fleet[bot] wants to merge 5 commits into
mainfrom
claude/project-thread-to5pdz

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Elon · project thread

Part of #30147

Clause-②: no
Metadata-protocol: none

维护者速读

  • 改了什么:scripts/codemod-split-protocol.mjs --members 新增三种不改写方法体的搬移形式(.call(host) 接收者、statics 转发器、无接收者的 plain 形式)外加静态表搬到叶子模块,并用它把 protocol.ts 上 19 个还留着方法体的成员搬进各自的 facet。
  • 为什么改:这 19 个成员是 facade 门禁登记里引用 Facade codemods: retire the codemod-limit exception rows in the facade gate registry (protocol.ts, engine.ts, sql-driver.ts) #30147 的例外行;E1 改写(this.x → host.x)搬不了它们,只能当例外留在类上。
  • 风险与回滚:纯搬移,方法体逐字节不变(撤销证明重建 base 树);公开 index.d.ts 的表面不变,只有 14 个 private 成员的 docblock 随方法体搬走;回滚即 revert 本 PR。
  • 先看:packages/metadata-protocol/src/protocol.ts 顶部新增的 ObjectStackProtocolImplementationStatics 与类尾的 static block;scripts/codemod-split-protocol.mjs 的 receiver forms 一节;scripts/check-durability-degradation-log-level.mjs 的 stub 解析。
  • 两分钟验证:node scripts/codemod-split-protocol.mjs --members --verify --base 616311c126,预期输出 forms: e1 2, plain 5, statics 5, receiver 3, table 4 与 undoing the moves does rebuild … byte-for-byte,退出码 0。
  • 需要你做的:无,席位落地。

What changes

The tool. The members pass (#30518) moved a member only when E1's
rewrite could carry it, so it refused a local named host, a body that
reads no member, and every private static that reads the class. It now
ports the two mechanisms the sql-driver codemod grew (#30249, #30306), for
those reasons only (RECEIVER_SOLVES), and moves the body unedited:

  • receiver: the facet member's this is typed as the Pick of ProtocolHost
    it reads, and the stub runs it on the host: return FACET.x.call(protocolHost(this), …).
  • statics: ObjectStackProtocolImplementationStatics, declared ahead of
    the class and filled by a static block at its end, forwards each static a
    moved body reads. A facet module imports it AS the class name, so a body
    that names the class reads it unedited; a private static that reads
    this runs on it: FACET.x.call(ObjectStackProtocolImplementationStatics, …).
  • plain: a body that reads nothing of the class: return FACET.x(…).
  • table: a private static readonly field's initializer moves to its
    section's leaf, protocol-write-gates-tables.ts, which imports no
    relative module (an initializer runs while the class is evaluated).
  • A predicate a moved body reaches through the host gets a host entry typed
    as the predicate, so the narrowing survives the hop.

The undo proof covers every form: from the head alone each stub, facet
member, forwarder entry, host entry and leaf is undone and the result is
the base tree byte for byte.

The moves. Nineteen members, all in sections that already have a facet:
reconcileViewExpansions, packagelessOverlayWriteRefusal,
namedBaseOverlayWriteRefusal, mergesOverlayAtRead,
registryAllowsOverlay, isOverlayAllowed, isRuntimeCreateAllowed,
codeOnlySourceHint, codeOnlyCreateError, codeOnlyOverrideError,
refuseOrganizationScopedWrite, overlayPackageMismatchError,
rethrowUnlessMetadataStoreUnprovisioned, objectExtensionItemRefusal,
packagedBaseRefusal and the four tables OVERLAY_ALLOWED_TYPES,
STATIC_REGISTRY_TYPES, RUNTIME_CREATE_ALLOWED_TYPES,
OVERLAY_CAPABLE_TYPES. Forms: e1 2, plain 5, statics 5, receiver 3,
table 4. protocol.ts goes from 13,007 to 12,577 lines.

The registry. The nineteen rows are deleted (46 to 27 exceptions).
triggerAutomation stays, its reason rewritten as an accepted exception:
its body is one throw, and its section has no facet module, which this
pass never starts. getDiscovery (a hand move) and the engine.ts and
sql-driver.ts rows are the later PRs of this card.

Followers of the moved bodies.

  • check-durability-degradation-log-level.mjs resolved a stub only in the
    E1 and facade-host shapes, so three read seams whose catch delegates to
    the moved rethrowUnlessMetadataStoreUnprovisioned read as inventing an
    answer. Its resolver now follows the receiver, statics and plain stubs to
    the facet member, and a facet member's this.x() through the imported
    host or forwarder interface. Its output on this tree is byte-identical to
    the base's.
  • Three source-reading pins in packages/metadata-protocol follow the moved
    bodies: the bracketed-opener scan's producer floors, the registerItem(
    call site's file, and the view-expansion record's forwarder read.
  • One platform-checklist citation (protocol.ts#refusal) points at
    protocol-write-gates.ts.

Why

Ruling 6624345766 item 3 wants every facade-gate exception row to name the
card that moves it, and #30147 phase 3 measured that one codemod port would
retire about 19 of its 21 protocol.ts rows (comment 6653253380). The rows
that stay are named in this card's report.

Tests

  • node scripts/codemod-split-protocol.mjs --self-test: 112 cases in 13
    batteries pass (85 in 10 before). The three new batteries generate each
    form on a fixture, fail ten mutations of the proof, and refuse seven
    inputs no form carries.
  • check-durability-degradation-log-level.mjs --self-test: 86 read-seam
    cases pass (81 before). Ablation: the five new cases against the base
    resolver fail the three positive ones; the two negative controls pass on
    both.
  • @objectstack/metadata-protocol vitest: base 4d56914aaa 320 files
    passed, 4 skipped; 22,487 tests passed, 26 skipped. Head ae519e3e99: 320
    files and 22,489 tests pass, 26 skipped (the two new producer rows of the
    bracketed-opener pin are the +2; one file first read a spec dist built
    before the rebase onto 616311c126 and passes, 18/18, once rebuilt).
  • packages/rest vitest at 7d49cfc21 (this branch before its rebase onto four unrelated main commits): 398 files, 7,752 tests passed, 354
    skipped. At base the local worktree loaded 383 of 398 files (15 import a
    sibling package's src that the worktree had no node_modules for), all
    of them passing. discovery-search-capability-agreement.test.ts 4/4 at base and
    head.

Acceptance notes

  • The .d.ts bar. The public surface of dist/index.d.ts and
    dist/index.d.cts is equal. The files are not byte-equal: 14 private
    members' docblocks changed, because a private member's docblock moves with
    its body (docblock ownership, as in Codemod split: generate the rest of the metadata-protocol protocol.ts split with a deterministic script, verified byte-identical #29985). Stripped of docblocks the two
    sides are identical (sha256 5cf3216a10daa533… base, 9cab7eb90040d456…
    head).
  • The one difference a body could see. A static reached through the
    forwarder runs with the class as this, never a subclass; every static
    it forwards is private, so no subclass reaches one.
  • Doc hover. {@link ObjectStackProtocolImplementation.x} in a facet
    module that imports the forwarder now resolves to the forwarder.
  • No open pull request touches packages/metadata-protocol/src/protocol*.ts
    (checked against all open pulls at the time of writing).

Verification

Undo proof

node scripts/codemod-split-protocol.mjs --members --verify --base 616311c126 at ae519e3e99: exit 0.

undo proof (#30518, #30147): 19 moved member(s) (objectExtensionItemRefusal, rethrowUnlessMetadataStoreUnprovisioned, mergesOverlayAtRead, registryAllowsOverlay, isOverlayAllowed, isRuntimeCreateAllowed, codeOnlySourceHint, codeOnlyCreateError, codeOnlyOverrideError, refuseOrganizationScopedWrite, packagedBaseRefusal, packagelessOverlayWriteRefusal, namedBaseOverlayWriteRefusal, overlayPackageMismatchError, reconcileViewExpansions, OVERLAY_ALLOWED_TYPES, STATIC_REGISTRY_TYPES, RUNTIME_CREATE_ALLOWED_TYPES, OVERLAY_CAPABLE_TYPES); forms: e1 2, plain 5, statics 5, receiver 3, table 4; host-split check: 2/2 E1 move(s) pass (the receiver forms move bodies unedited, proved byte-equal); protocol.ts 13007 -> 12577 lines; undoing the moves does rebuild the base protocol.ts, protocol-host.ts and section modules byte-for-byte once the 9 import binding(s) only moved bodies read are pruned from the base (OBJECT_EXTENSION_TYPE, ObjectExtensionRegistry, SINGULAR_TO_PLURAL, metadataReadFailureError, namedBaseCloseSubject, objectExtensionItemRefusal, packagedBaseRegimeRow, packagelessCloseSubject, packagelessOverlayWriteRefusal)
Facade gate and companions

node scripts/check-facade-delegation-only.mjs: exit 0, 27 named
exceptions. pnpm --filter @objectstack/metadata-protocol typecheck exit 0,
build exit 0. pnpm check:platform-checklist exit 0.
pnpm --filter @objectstack/spec check:liveness exit 0. eslint on the
changed files: clean.

dispatch-gates

node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack at ae519e3e99: 86 families derived, all 86 run, all exit 0 (codes captured before any pipe). --ran: 86 derived, 86 run, 0 NOT-MEASURED, 0 UNRUN. Four gates first answered PREREQUISITE NOT MET or red on a partial build or a shallow clone (check-plugin-teardown-shape --self-test, check:dual-build-cjs-loads, check:lean-entry-closure) or before the durability resolver fix (check:durability-log-level); each exit 0 on the re-run after a full pnpm build.

Changed lines

2,459 changed lines (+1,720 / −739, 15 files, changeset included), under the 3,000 budget.

Human Minimum

  • 1. Schemas start as Zod; packages/spec holds no runtime logic.
  • 2. Every name I added uses the casing for its kind.
  • 3. No formatter ran; pnpm lint passes.
  • 4. One issue, one branch off an up-to-date main, one pull request.
  • 5. A change that publishes carries a changeset, and both declaration lines are filled in here and in the changeset.
  • 6. packages/spec touched: its generated artifacts are regenerated and committed.
  • 7. No hand edits to content/docs/references/, packages/*/CHANGELOG.md or content/docs/releases/.
  • 8. Title, body and comments are in English.
  • The Before Submitting list in CONTRIBUTING.md is done.

🤖 Generated with Claude Code

https://claude.ai/code/session_016WV4cxm997Tr9c3JFQTKGj

… receiver and the statics forwarder, and moves nineteen protocol.ts bodies

The members pass now moves, unedited, the members E1's rewrite refuses:
an instance body run on the class's host as `this` (`.call(host)`), a
private static run on a forwarder of the class's statics, a body that
reads nothing of the class (plain), and a private static table moved to
its section's leaf. The undo proof covers every form byte for byte, and
the self-test gains three batteries for them.

Nineteen facade-gate exceptions retire; triggerAutomation stays as an
accepted exception with its reason rewritten. Three source-reading pins
follow the moved bodies.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016WV4cxm997Tr9c3JFQTKGj
…eceiver forms

A guard or read wrapper whose body moved by the receiver forms is reached
through a stub that runs its facet member on the host (`.call(protocolHost(this))`),
on the statics forwarder, or with no receiver (an instance method's plain
form). The resolver follows those stubs to the facet member, and a facet
member's `this.x()` to the class member through the imported host or
forwarder interface, so the three read seams that delegate to the moved
`rethrowUnlessMetadataStoreUnprovisioned` are judged on its discriminated
branch again. The checker's output on the tree is byte-identical to the base.

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

github-actions Bot commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/metadata-protocol, touching 65 documentable anchor(s).

28 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 c77dd17f2671f35e8f194ca1e63d8cc75bfb861a.

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

What this run could not see
  • 1 anchor(s) matched too much of the corpus to be a work list: /api/v1/meta (route, 48 pages)
  • the SDK route bridge reached 63 of 222 client-bound route-ledger rows — the other 159 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 159: 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; 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 — 10 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 c77dd17f2671f35e8f194ca1e63d8cc75bfb861a → packageMentionDocs.

Which tree this was computed on

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

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

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

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:devx#1 · os-elon-musk · session_016WV4cymvo9YoyLwKCXXBNw

席位核对 · ACCEPT · #30147 (phase 3a) · 2026-11-06T14:15Z

Head-sha: ae519e3e996af7fc08c601dc420447e05ba4ba09

  • Shape: 15 files (+1,720/−739, 2,459 lines, under 3,000). Part of #30147: phase 3b (getDiscovery) opens from fresh main after this lands. @objectstack/metadata-protocol patch changeset, no behaviour change.
  • Measured by the seat:
    • codemod-split-protocol.mjs --members gains the receiver forms ported from the sql-driver codemod: .call(host) receiver, statics forwarder, plain form, static tables to the new leaf protocol-write-gates-tables.ts, and predicate host entries. It moves 19 members, and the registry goes from 46 to 27 rows (Facade codemods: retire the codemod-limit exception rows in the facade gate registry (protocol.ts, engine.ts, sql-driver.ts) #30147: 27 to 8).
    • protocol-host.ts gains two host entries (isPackagedBaseRefusal, overlayBaseShippers).
    • One checklist citation follows its moved body (platform-core.json, protocol-write-gates.ts#refusal). Three source-reading pins follow theirs.
    • check-durability-degradation-log-level.mjs gains resolver support for the new stub shapes. It has no rule change, its output on the tree is byte-identical to base, and the new cases are ablation-proven.
  • Proofs (dev):
    • --members --verify --base 616311c126 exits 0, and undo rebuilds the base byte for byte.
    • The public index.d.ts / .d.cts surface is equal. Only private docblocks move with their bodies, and with docblocks stripped the files are identical.
    • metadata-protocol suite: 22,487 tests at base, 22,489 at head (+2 new rows). The rest suite passes 7,752 tests, including discovery-search-capability-agreement 4/4.
    • Facade gate, typecheck, build, check:platform-checklist and spec check:liveness all exit 0. 86 derived gates of 86 at exit 0.
  • Open, not blocking this PR: the card's two open questions (terminal exceptions against ruling 6624345766 item 3, and the engine.ts rows while fix(objectql)!: a non-system write may name, in a lookup or user field, only a record the caller can read #30747 is open) are with the maintainer. This PR records triggerAutomation as an accepted exception. If the ruling goes another way, a later PR on this card re-points that row.
  • check-governed-merges --pr 30954: NOT governed. CI is still running, so auto-merge lands it on green.

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review November 6, 2026 14:15
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge November 6, 2026 14:16
…ALLOWED_TYPES initializer in its leaf module

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016WV4cxm997Tr9c3JFQTKGj
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:devx#1 · os-elon-musk · session_016WV4cymvo9YoyLwKCXXBNw

席位核对 · ACCEPT (delta) · #30147 (phase 3a) · 2026-11-06T14:36Z

Head-sha: bc2ee6c161b9ad3a86d1a45cbdbb76b86b2bf576

  • Delta from ae519e3e: one spec test pin. metadata-type-registry-allow-org-override-absence.test.ts lists the files that read allowOrgOverride. Its NEW_READERS entry now names protocol-write-gates-tables.ts, because that is where OVERLAY_ALLOWED_TYPES's initializer moved. That pin made the spec repo tier red on the previous head (job 127940769860). The radius already covers the file, and the offenders assertion is unchanged.
  • Measured by the dev: every test file outside metadata-protocol that reads metadata-protocol/src (70 files in 13 packages) was run by path, which includes the repo tier, and all pass. The rest suite passed in full. No other pin cites a moved name. Auto-merge stays armed.

@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Nov 6, 2026
Any commits made after this event will not be merged.
@github-actions

github-actions Bot commented Nov 6, 2026

Copy link
Copy Markdown
Contributor

⛔ merge queue 构建失败 — 先分诊,再决定要不要重排

队列构建 42243079369 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集),
所以失败的测试可能在本 PR 没碰过的包里 —— 那不是重排能修的。每次盲目重排都会让排在后面的所有 PR 重建一轮。

分类:failure —— 按下面的日志分诊。

失败的 job(日志抽取,best effort):

  • Test Core (5/8) — 失败步骤: Run this shard's tests

    @objectstack/scenarios:test:  FAIL  test/build/built-consumer.test.ts > a tsup-built consumer of @objectstack/scenarios/score > loads under plain Node (CJS) and reaches neither objectql nor plugin-sha
      ↳ 失败原因: @objectstack/scenarios:test: Error: Test timed out in 5000ms.
    

↳ 失败原因 是判读的关键:超时(Test timed out in … / Hook timed out in …)多半是负载/时序,不是本 PR 的回归;
断言(AssertionError: …)才指向真实的行为改变。两者的 FAIL 行长得一模一样,只有这一行能区分。

⚠️ 断言这一侧有一类例外,判据是断言在测什么,不是它是不是 AssertionError。 断言的对象是产品行为(一个值、一个形状、一次拒收)⇒ 照上面读:真实的行为改变,去查,⛔ 不要重排掉;
断言的对象是这次实验自身的有效性前提(跑完的耗时、负载下的先后、任何只在时间预算内才成立的条件)⇒ 它跟超时是同一类,同样对负载敏感,重排一次是合法的判别手段。
识别是机械的:断言的消息或它比较的值本身点名了一段时长、一个时间戳、一个耗时计数。实测过的一对 —— AssertionError: SecurityPlugin.init() ran: expected false to be true 测的是产品行为(真回归);
AssertionError: this run took over a second, so second-precision stamps could have differed too: expected 1006 to be less than 1000 测的是实验前提:它守护的那条不变式当时是绿的,同一个 head 原样重排一次即成功。
穿着 AssertionError 外衣的时间测量,仍然是时间测量。(⛔ 这只改「怎么读一次红」,不改「哪些测试可以重排」——后者由别处管。)

跨 PR 相同签名(24h,按失败测试文件聚合):

  • test/build/built-consumer.test.ts — 24h 窗口内只有本 PR 撞到过,暂不汇总(再有一个不同 PR 撞到就会自动开汇总 issue)。
  • ⚠️ 24h 评论账本没读完(超过 5 页仍未读到窗口尽头),所以上面的「不同 PR 数」是下界,不是全量。

历史信号:

  • 本 PR 过去 24h 无队列失败记录(首次)。
  • 过去 24h 队列共有 23 个失败构建(不含本次)。

分诊清单:

  1. 失败测试在本 PR 改动的包里 → 真回归,修 PR。
  2. 失败测试与本 PR 无关 → 看上面的「跨 PR 相同签名」;已有汇总 issue ⇒ flaky/环境问题实锤,去那张 issue 上谈,修好前重排只会再烧一轮全队列。
  3. 两者都不是 → 可能与同组 PR 语义冲突;等前面的 PR 落地或失败出队后再重排一次即可,不要连续重排。

Generated by Claude Code · merge-queue-triage workflow (#4859)

@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Nov 6, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:devx#1 · os-elon-musk · session_016WV4cymvo9YoyLwKCXXBNw

席位核对 · ACCEPT (delta) · #30147 · 2026-11-06T16:48Z

Head-sha: 6a6b307eab78ba32366dff8123ce4d2dffd63356

  • Delta from bc2ee6c161: a plain merge of main c77dd17f2 (as 2dc9a86ec), then one commit. That commit adds 2 lines to packages/metadata-protocol/src/protocol.bracketed-refusal-opener-absence.test.ts: a module-top import './lint-root-preload.testkit.js';, which is the package's own wrapper around import '@objectstack/lint'; and is already used by its sibling tests, plus the standard one-line comment. The source, the assertions and the timeouts are unchanged.
  • Why: the queue's lint job (build 42245768570, job 127987461131) failed on the Test-source alias gate's source-reach half (ci(test-source-alias): follow a changed test into the source it loads, and red a cold literal import() paid there #30969). Line 53 of this file reached import('@objectstack/lint') at metadata-diagnostics.ts:494, with no load at module scope. The gate prescribes exactly this fix.
  • Gates: the dev ran check-test-source-alias.mjs, which exited 1 before the change and 0 after. The file passes 23/23, eslint is clean, typecheck is 0, and the facade gate is 0 (27). CI on this head: skipped 9, success 56, no failure.
  • The prior ACCEPT stands for the rest of the PR. check-governed-merges: not governed. Auto-merge is re-armed.

@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Nov 6, 2026
Any commits made after this event will not be merged.
@github-actions

github-actions Bot commented Nov 6, 2026

Copy link
Copy Markdown
Contributor

⛔ merge queue 构建失败 — 先分诊,再决定要不要重排

队列构建 42257643045 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集),
所以失败的测试可能在本 PR 没碰过的包里 —— 那不是重排能修的。每次盲目重排都会让排在后面的所有 PR 重建一轮。

分类:failure —— 按下面的日志分诊。

失败的 job(日志抽取,best effort):

  • Dogfood Regression Gate (3/3) — 失败步骤: Boot example apps and exercise real user flows

    @objectstack/dogfood:test:  FAIL   isolated  test/admin-platform-admin-standing.dogfood.test.ts > #9482: what an ObjectStack platform admin gets from every /admin/ route > no /admin/ route refuses the
      ↳ 失败原因: @objectstack/dogfood:test: AssertionError: the stack serves /admin/ route(s) this file neither admits, refuses-by-design, nor classifies as answering for a non-authorization reason. A new admin route 
    

↳ 失败原因 是判读的关键:超时(Test timed out in … / Hook timed out in …)多半是负载/时序,不是本 PR 的回归;
断言(AssertionError: …)才指向真实的行为改变。两者的 FAIL 行长得一模一样,只有这一行能区分。

⚠️ 断言这一侧有一类例外,判据是断言在测什么,不是它是不是 AssertionError。 断言的对象是产品行为(一个值、一个形状、一次拒收)⇒ 照上面读:真实的行为改变,去查,⛔ 不要重排掉;
断言的对象是这次实验自身的有效性前提(跑完的耗时、负载下的先后、任何只在时间预算内才成立的条件)⇒ 它跟超时是同一类,同样对负载敏感,重排一次是合法的判别手段。
识别是机械的:断言的消息或它比较的值本身点名了一段时长、一个时间戳、一个耗时计数。实测过的一对 —— AssertionError: SecurityPlugin.init() ran: expected false to be true 测的是产品行为(真回归);
AssertionError: this run took over a second, so second-precision stamps could have differed too: expected 1006 to be less than 1000 测的是实验前提:它守护的那条不变式当时是绿的,同一个 head 原样重排一次即成功。
穿着 AssertionError 外衣的时间测量,仍然是时间测量。(⛔ 这只改「怎么读一次红」,不改「哪些测试可以重排」——后者由别处管。)

跨 PR 相同签名(24h,按失败测试文件聚合):

历史信号:

  • ⚠️ 本 PR 过去 24h 已在队列失败 1 次(不含本次)。 内容未变而反复失败 ⇒ 高度怀疑 flaky 测试或与同组 PR 的语义冲突,重排不解决。
  • 过去 24h 队列共有 14 个失败构建(不含本次)。

分诊清单:

  1. 失败测试在本 PR 改动的包里 → 真回归,修 PR。
  2. 失败测试与本 PR 无关 → 看上面的「跨 PR 相同签名」;已有汇总 issue ⇒ flaky/环境问题实锤,去那张 issue 上谈,修好前重排只会再烧一轮全队列。
  3. 两者都不是 → 可能与同组 PR 语义冲突;等前面的 PR 落地或失败出队后再重排一次即可,不要连续重排。

Generated by Claude Code · merge-queue-triage workflow (#4859)

This branch has not been deployed

No deployments
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 tests 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.

2 participants