Skip to content

feat(spec): register the ask agent's draft_record tool, with its chatbot label in all ten packs (cloud#3383) - #28131

Merged
objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/project-thread-y92ji9
Oct 30, 2026
Merged

objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/project-thread-y92ji9

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Requested by Sam · project thread

Registry half of objectstack-ai/cloud#3383 (no objectstack card of its own; the same shape as #27011 for cloud#3335). Related: #28104 (the console card that renders this tool's result).

What changes

  • PLATFORM_TOOLS_BY_PACKAGE['service-ai-studio'] lists draft_record, in alphabetical order. The group's TSDoc now also names the ask agent's hand-off signals.
  • chatbot.tool.draft_record in all ten locale packs ("Draft the new record", 「起草新记录」, …).
  • packages/lint: a pin that a skill naming draft_record resolves, with a control name that does not.
  • Two changesets: @objectstack/spec minor (widening), @object-ui/i18n patch.

Why

cloud#3383 (Sam's ruling on #27286, 2026-10-30: 「同意开发 S1 粘贴即建单」, then 「其实不只是粘贴吧,任何内容我都可以让他创建和更新记录是吗?通过聊天的方式。」) adds draft_record to cloud service-ai-studio: the ask agent drafts a new record from chat content, validated server-side, and the user saves it. Cloud's conformance test holds the package to exactly this registry, so the cloud PR stays red on that one test until this lands and a cloud pin round passes it. The chatbot label-parity tests read the same registry, so the label lands with the name.

Verification

  • packages/lint validate-ai-tool-references.test.ts: 22 passed.
  • ui: pnpm exec vitest run packages/plugin-chatbot/src/__tests__/toolLabels-locale-parity-7481.test.ts packages/plugin-chatbot/src/__tests__/toolLabels-sentences-12724.test.ts packages/i18n/: 94 files, 1,431 passed.
  • pnpm --filter @objectstack/spec build && pnpm --filter @objectstack/spec check:generated: all 14 generated artifacts up to date.

Clause-②: yes (widening)
Metadata-protocol: added

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 was not run locally (CI runs it).
  • 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.

Generated by Claude Code

…bot label in all ten packs (cloud#3383)

The cloud ask agent gains `draft_record`, a signal tool that turns chat
content into a validated new-record draft the user saves (cloud#3383; the
console card is #28104). PLATFORM_TOOLS_BY_PACKAGE['service-ai-studio']
now lists it, so a skill naming it resolves under ADR-0109 reference
integrity and cloud's conformance test can hold the package to the list.
Each locale pack gets its `chatbot.tool.draft_record` step label.

Claude-Session: https://claude.ai/code/session_01QUs3BsR8MWGg1ZtMACGG7y
Co-authored-by: Claude <noreply@anthropic.com>
@os-zhuang os-zhuang self-assigned this Oct 30, 2026
@github-actions github-actions Bot added size/s documentation Improvements or additions to documentation protocol:system tests tooling labels Oct 30, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

2 anchor(s) derived from 1 changed package(s); no hand-written page names any of them, so this run has nothing to list — not a clean bill of health. This check sees only pages that NAME a derived anchor: one that documents this change in prose, or enumerates it in an authoring dialect, names none and stays invisible to it on every run.

What this run could not see

Coarse fallback — 168 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 47a8b588207621724d85647576c4277979c253f7 → packageMentionDocs.

Which tree this was computed on

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

node scripts/docs-audit/affected-docs.mjs --json 47a8b588207621724d85647576c4277979c253f7

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

@objectstack-fleet

Copy link
Copy Markdown
Contributor

triage#1 · os-sales · session_01L6bhgV4fMGJHSdSdx3u9mK

Contract-review-claim: session_01L6bhgV4fMGJHSdSdx3u9mK · head 87e98178acf4f8fa1037a53f438a3891d50f07c5 · 2026-10-30T15:08Z


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor

triage#1 · os-sales · session_01L6bhgV4fMGJHSdSdx3u9mK

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 87e98178acf4f8fa1037a53f438a3891d50f07c5
Local-runs: none
Scope: packages/spec/src/system/constants/platform-tool-names.ts + packages/spec/src/system/constants/platform-tool-names.test.ts, packages/lint/src/validate-ai-tool-references.ts, packages/lint/src/validate-ai-tool-references.test.ts, packages/mcp/src/mcp-server-runtime.ts, ui/packages/plugin-chatbot/src/tests/toolLabels-locale-parity-7481.test.ts, ui/packages/plugin-chatbot/src/tests/toolLabels-sentences-12724.test.ts, ui/packages/i18n/src/locales/{ar,de,en,es,fr,ja,ko,pt,ru,zh}.ts

Source of the work: the PR names no in-repo card. Its source is the cloud repository's issue cloud#3383, which is not readable from this seat; the ruling it carries is judged from the PR body and from in-repo issue #28104 (the console card for the same hand-off, which restates the ruling and the "AI drafts, a person saves, never auto-submitted" scope). The rest of the diff outside Scope: (the two changesets) is the lane seat's ACCEPT at TIER_DEFAULT; ② below reads them only to judge the semver level.

① Derived judgments

  • PLATFORM_TOOLS_BY_PACKAGE['service-ai-studio'] gains draft_record, inserted between describe_object and get_active_package. Right: the group's sort invariant (platform-tool-names.test.ts, "each group is sorted") holds, the name is snake_case, collides with no other group and sits in no action_ family namespace, so every invariant pin in the spec's own test holds on the head. Test Core is green on the head.
  • PLATFORM_PROVIDED_TOOL_NAMES (the flattened set, a published const) gains one member. Right: this is the only public-surface change; no export is added or removed, so api-surface/system.json and export-origins/system.json are unchanged and the TypeScript Type Check job (which runs every generated-artifact gate) is green.
  • Accept set of skill.tools[] under ADR-0109 widens by one name: validateAiToolReferences resolves against PLATFORM_PROVIDED_TOOL_NAMES at ladder step 2 (collectToolUniverse), so a skill naming draft_record stops being reported as ai-skill-tool-unresolved. Right, and pinned in the diff: the new lint case resolves draft_record and keeps reporting the control draft_records at skills[0].tools[1], the same shape as the PLATFORM_TOOLS_BY_PACKAGE['service-ai-studio'] is missing five registered tools, so a skill naming any of them reads as fictional to validate/lint #16512 and spec: PLATFORM_TOOLS_BY_PACKAGE['service-ai'] lists read_package_doc and search_package_docs, the two package-doc tools cloud#3335 adds to the Ask agent #27002 pins beside it. Lint and Test Core are green.
  • MCP bridge: worldAnnotation() in packages/mcp/src/mcp-server-runtime.ts now answers openWorldHint: false for a bridged tool named draft_record. Right: the registry is the ownership source by design (a platform tool acts on the environment's own records and metadata; a record draft of this stack's object is exactly that). The partial safety sets PLATFORM_READ_ONLY_TOOL_NAMES and PLATFORM_DESTRUCTIVE_TOOL_NAMES are untouched, so draft_record gets no readOnly or destructive hint, the protocol's "unknown" default; this matches its siblings suggest_builder and open_record, which are also absent from both sets, and the registry-driven pin ("no tool outside PLATFORM_PROVIDED_TOOL_NAMES receives a hint it did not declare") iterates the widened set and stays green.
  • Chatbot step label: toolLabels-locale-parity-7481 reads PLATFORM_TOOLS_BY_PACKAGE from the workspace spec (@objectstack/spec: workspace:^ in ui/packages/plugin-chatbot/package.json), so the coverage set grows by draft_record the moment the registry does, and every one of the ten packs must carry chatbot.tool.draft_record. Right: at the head all ten packs carry the key once, inside chatbot.tool (confirmed by reading each pack at the head, not the hunk context alone). toolLabels-sentences-12724 requires every value to differ from the id and from the title-caser's output (Draft record for this id): Draft the new record and its nine siblings all differ, and the key set is identical across packs. Test UI is green on all 16 shards.
  • No other consumer enumerates the group by hand: ui/scripts/check-i18n-call-site-keys.mjs declares chatbot.tool. as external vocabulary pinned by the parity test; mapMessages.ts names only visualize_data; skills/objectstack-ai/SKILL.md and ADR-0109 point at the file rather than listing names; no content/docs page lists the service-ai-studio tools. Nothing drifts.
  • The group's TSDoc now says the ask agent's hand-off signals (suggest_builder, open_record, draft_record) live in this group and "write nothing". Right as a correction: the two older signals were already listed here and the previous sentence did not account for them. The "write nothing" claim for draft_record is held against the PR body and ai chat: a record_draft card opens a prefilled new-record form (values via router state, marked AI 建议, never auto-submitted) #28104 (the draft is validated server-side and saved by the person; never auto-submitted); its enforcement is the cloud conformance test and the cloud tool itself, not this repo (see ③).

② Semver level

  • .changeset/cloud-3383-draft-record-tool-name.md: @objectstack/spec minor, body carries Clause-②: yes (widening) and Metadata-protocol: added, both line-initial. Right: a new accepted skill.tools[] value is added under AGENTS.md's declaration rule, and a kind takes at least minor on the package the diff moves. The same reading landed in feat(spec): PLATFORM_TOOLS_BY_PACKAGE['service-ai'] lists read_package_doc and search_package_docs (#27002) #27011 for cloud#3335 (the precedent the PR names). The lint rule is advisory, so the alternative reading (none, patch) is arguable, but it would under-declare a change whose whole purpose is to widen the accept set the lint rule enforces; minor is the direction that cannot under-publish. Consequence to note: @objectstack/spec is in the fixed group, so the whole @objectstack/* group takes a minor bump.
  • .changeset/cloud-3383-chatbot-tool-label-draft-record.md: @object-ui/i18n patch, Clause-②: no, Metadata-protocol: none. Right: a display string in each pack, nothing an author writes; @object-ui/i18n is in the root .changeset/config.json fixed group, so the root changeset dir is the correct home.
  • PR body carries the same two declaration lines, line-initial, matching the spec changeset. Check Changeset and the PR-body guards are green.

Clause-②: yes (widening)

③ Boundary flags

  • Author login is os-zhuang (the implementation claim is the project thread named in the PR body; Implemented-by below carries the branch).
  • Human Minimum item 3 is unchecked (no local pnpm lint): answered by the head's check-runs, where Lint & Repo Gates, every scoped Lint lane, ESLint and Lint UI are green.
  • No dev flag and no open_questions entry in the PR body. The Docs Drift Check's "checkout carried uncommitted changes" note describes the CI runner's merge checkout, not this diff; no action.
  • Escalated, not blocking: the exact spelling draft_record and the "writes nothing" characterisation are facts about cloud#3383's registration, which this seat cannot read. The contract's enforcement for the name is the cloud conformance test (platform-tool-names-conformance.test.ts, per the registry header and ADR-0109): if cloud registers a different name, that test goes red in the cloud pin round, not here. ai chat: a record_draft card opens a prefilled new-record form (values via router state, marked AI 建议, never auto-submitted) #28104 names the RESULT status record_draft while the TOOL is draft_record; these are different things (a status value inside the tool result versus the tool name), not a contradiction, but the cloud pin round should confirm both spellings against the landed cloud tool.
  • check-runs on the head: 64 runs, every required job success; the skipped ones (Temporal Conformance, Dogfood matrix lanes, UI Published Artifacts, Build Docs, opt-in harnesses, schedule gate) are path- or opt-in-filtered and owe nothing to this diff. Governed Surface Queue Guard and Spec property liveness are green.

④ Design judgment

packages/spec/src/system/constants/platform-tool-names.ts, judged against ADR-0109 (the ruling it implements) and its first consumer validateAiToolReferences, with the chatbot parity test and the MCP bridge as the other two readers.

  • Against ADR-0109 decision 2 ("platform tool names are facts, not guesses; the owning cloud packages carry conformance tests"): the maintenance contract in the file header says registering a tool in a cloud AI package means adding its name here, plus a chatbot.tool.NAME label in every pack. The diff does exactly those two things and nothing more. The registry stays a curated fact list; no runtime logic enters packages/spec.
  • Against the first consumer: the resolution ladder reads the flattened set, so the one-line addition is the entire behaviour change, and the PR pins it with a positive case and a near-miss control in the rule's own test file, where "resolves" and "refused" are decided, not beside the constant. Tried to break it: a universe widened too far would pass the positive case and fail the control; a misplaced (unsorted) entry would fail the spec's sort pin; a missing pack entry would fail the parity test per pack. Each failure mode has a red gate on the head's file set.
  • Against the scenario it is accepted for (cloud#3383 via the PR body and ai chat: a record_draft card opens a prefilled new-record form (values via router state, marked AI 建议, never auto-submitted) #28104): the ask agent emits a validated new-record draft the person saves. Registering a hand-off signal in service-ai-studio alongside suggest_builder and open_record follows the group these signals already live in; the PR body states cloud#3383 registers it in that package, and the cloud conformance test holds that package to exactly this group, so a wrong group would red the cloud side rather than pass silently.
  • MCP side effect considered and found right (① above): openWorldHint: false for a tool that drafts a record of this stack's own object is the known answer the bridge wants; no safety hint is asserted without a source.
  • Label texts: each pack's value is a sentence in its language, none equals the id or Draft record; alphabetical beside its neighbours in every pack. The ja, ko and zh values read as instructions to the user ("make a draft of the new record"), matching the ruled style (todo_write's sentence form).

Findings: no must-fix. No should-fix. The design holds against the code it cites and the gates that enforce it.

Implemented-by: claude/project-thread-y92ji9
Reviewed-by: session_01L6bhgV4fMGJHSdSdx3u9mK

VERDICT: PASS


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Seat ACCEPT · repo:cloud#2 · 2026-10-30T15:15Z · head 87e98178ac · not governed

The contract review at CONTRACT_REVIEW_TIER is PASS on this head (the record above, with no must-fix and no should-fix). Every check run on the head has concluded: 56 success, 8 skipped by path filter, 0 failed. The spellings match the producer, objectstack-ai/cloud#3385: the tool is registered as draft_record in service-ai-studio, and its result status is record_draft.

Landing: ready + auto-merge. Next, a cloud pin round past this commit turns cloud#3385's conformance test green.


Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 30, 2026 15:16
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 30, 2026 15:16
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 30, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Oct 30, 2026
@github-actions

Copy link
Copy Markdown
Contributor

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

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

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

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

  • Test UI (9/16) — 失败步骤: Run the ui tests (shard 9/16)

    × offers the envelope on exactly the six hand-table key/value maps the ledger names 9ms
    FAIL   unit  packages/app-shell/src/views/metadata-admin/inspectors/flow-value-envelope.test.ts > isValueEnvelopeSlot — read off the spec expression ledger (objectui#7588) > offers the envelope on exa
      ↳ 失败原因: AssertionError: expected [ 'assignment:assignments.*', …(18) ] to deeply equal [ 'assignment:assignments.*', …(17) ]
    

↳ 失败原因 是判读的关键:超时(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 无队列失败记录(首次)。
  • 过去 24h 队列共有 2 个失败构建(不含本次)。

分诊清单:

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

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

@github-actions

Copy link
Copy Markdown
Contributor

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

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

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

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

  • Test UI (1/16) — 失败步骤: (无步骤级结论)

    × the node cell and the Problems list both name the blank expression, in the same words 2634ms
    FAIL   dom  packages/app-shell/src/views/studio-design/AutomationsPillar.problemsAgree-27799.test.tsx > Automations page — Problems and the node agree on a blank expression (objectstack#27799) > the n
      ↳ 失败原因: AssertionError: expected 'flows[0].nodes[1].config.fields.id' to contain 'node \'write\''
    
  • Test UI — 失败步骤: (无步骤级结论)(日志不可读,点进 job 看)

↳ 失败原因 是判读的关键:超时(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 已在队列失败 2 次(不含本次)。 内容未变而反复失败 ⇒ 高度怀疑 flaky 测试或与同组 PR 的语义冲突,重排不解决。
  • 过去 24h 队列共有 15 个失败构建(不含本次)。

分诊清单:

  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 Oct 30, 2026
@github-actions

Copy link
Copy Markdown
Contributor

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

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

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

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

  • Test UI (1/16) — 失败步骤: (无步骤级结论)

    × the node cell and the Problems list both name the blank expression, in the same words 2572ms
    FAIL   dom  packages/app-shell/src/views/studio-design/AutomationsPillar.problemsAgree-27799.test.tsx > Automations page — Problems and the node agree on a blank expression (objectstack#27799) > the n
      ↳ 失败原因: AssertionError: expected 'flows[0].nodes[1].config.fields.id' to contain 'node \'write\''
    
  • Test UI — 失败步骤: (无步骤级结论)(日志不可读,点进 job 看)

↳ 失败原因 是判读的关键:超时(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 已在队列失败 3 次(不含本次)。 内容未变而反复失败 ⇒ 高度怀疑 flaky 测试或与同组 PR 的语义冲突,重排不解决。
  • 过去 24h 队列共有 15 个失败构建(不含本次)。

分诊清单:

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

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

@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 30, 2026
Merged via the queue into main with commit 99a6a78 Oct 30, 2026
65 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/project-thread-y92ji9 branch October 30, 2026 20:57
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 protocol:system size/s tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants