Skip to content

feat(console): the sharing-rule object picker lists only shareable objects, business objects first - #31274

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

objectstack-fleet[bot] merged 4 commits into
mainfrom
claude/project-thread-vxpifh

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Leehom · project thread

Fixes #31217

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

维护者速读

  • 改了什么:新建共享规则时,「对象」下拉框改为只列「规则存得进、也能生效」的对象,业务对象在前、平台对象在后,顺序照服务器 GET /api/v1/sharing/shareable-objects 给的原样显示。新增字段控件 shareable-object-ref,sys_sharing_rule.object_name 的控件提示从 object-ref 改为它(同一个 PR 注册、同一个 PR 切换)。
  • 为什么改:原来下拉框列出全部 86 个对象,多数是 sys_*,还包括存了会被 SHARING_NOT_ENABLED 拒绝的对象和会话、凭据类对象;Setup: show what people can really do and what really changed, using names rather than ids #30209 第 5 行方案 B 的控制台半边,服务器半边 PR feat(plugin-sharing): list the objects a sharing rule can take effect on #31207 已合并。
  • 风险与回滚:接口答 403(不是共享规则管理员)、501(本部署没跑共享规则)或任何读不出列表的情况,字段退回原来的 object-ref 全量列表,不会出现空下拉框;保存时服务器仍是最终裁决。已存的规则对象不在列表里时仍保留为选项,编辑不会丢值。列表格子和只读面沿用 object-ref 的对象名标签。回滚即 revert。
  • 先看:ui/packages/fields/src/widgets/ShareableObjectRefField.tsx(读接口与退回逻辑),ui/packages/plugin-form/src/__tests__/objectFormShareableObjectRef-31217.test.tsx(在新建表单上点选、保存、403/501 退回),packages/plugins/plugin-sharing/src/objects/sys-sharing-rule.object.ts(控件提示)。
  • 两分钟验证:pnpm --dir ui exec vitest run packages/plugin-form/src/__tests__/objectFormShareableObjectRef-31217.test.tsx,预期 Tests 5 passed (5)。
  • 需要你做的:无,席位落地。

What changes

  • The widget (@object-ui/fields, new widgets/ShareableObjectRefField.tsx, registered as field:shareable-object-ref). It reads GET /api/v1/sharing/shareable-objects through the host's authenticated fetch (SchemaRendererContext.apiFetch, the route the notification-topic picker reads its door by) and offers data.objects in the order the door sends: business objects, then platform objects, each by label. Options use objectRefOptionLabel, the Label (name) spelling object-ref uses, and a pick writes the object's machine name. A stored name the list does not hold is kept as its own leading option, so editing a rule on an object that no longer takes one never drops the value. No new translation key: the loading, placeholder, search and empty strings are object-ref's.
  • The fallback. When the door does not answer a readable list, the field renders ObjectRefField unchanged: every registered object from dataSource.getObjects(). That covers the two states the card names, 403 PERMISSION_DENIED (not a sharing-rule administrator) and 501 NOT_IMPLEMENTED (sharing rules not running), and also any other non-2xx, a body that is not the door's shape, a network failure, and a host with no apiFetch. Never an empty picker. The read-only face is also object-ref's, so a record page does not call an admin-only door.
  • The declaration (@objectstack/plugin-sharing). sys_sharing_rule.object_name declares widget: 'shareable-object-ref', flipped in the PR that registers the widget. The by_object pin moves with it, and the census of fields that store an object API name (sys-sharing-rule.by-object.test.ts) counts the new widget beside object-ref, so the no-grouping rule still reaches this field.
  • The other faces of the key, each the row object-ref already has: the list cell promotes to the same object label face (WIDGET_CELL_RENDERER_TYPES, the default text face in @object-ui/fields and the console's ObjectRefCell in @object-ui/app-shell); the record form threads dataSource to it (DATA_SOURCE_ONLY_WIDGET_TYPES in @object-ui/components, which the fallback reads); it is not edited inline in a grid (FieldEditWidget); it is a widget-hint-only string in paramValueShape; and field:shareable-object-ref joins the known schema types of @object-ui/cli.
  • Registry censuses that enumerate every registered widget gain the row: widget-aria-invalid-registry-e2e, widget-dom-leak-e2e, cellRenderers.objectLiteral-8596, summaryChip.badgeFitCensus-8464 (fit side 41 to 42), inlineEditTypeCoverage, and the className readers in form-field-channel-census-12130.
  • Changeset .changeset/31217-shareable-object-picker.md, patch on the five shipping packages, both declaration lines.

Declaration lines, as measured

  • Clause-②: yes (widening). The claim started at no; the diff adds a registered widget key, which widens the published RegisteredFieldWidgetType union of @object-ui/fields and the known schema types of @object-ui/cli (the precedent is .changeset/31062-notification-topic-channel-pickers.md). No translation key is added, removed or reworded; no export is added (the widget is reached only through the lazy registry, not the package barrel); nothing is narrowed.
  • Metadata-protocol: none. The spec's FieldSchema.widget is an open string, so no authorable key or accepted value changes. The flip changes the value one server object declares, which only picks the console control.

Tests

  • New objectFormShareableObjectRef-31217.test.tsx drives ObjectForm in create mode inside SchemaRendererProvider (as the console mounts it), opening the real combobox and submitting the real form: (1) the door's list in its order and nothing else (no sys_session, no sys_api_key, no object the door leaves out), the registry list never read; (2) CONTROL: a shareable object is selectable and the form saves object_name: 'crm_opportunity'; (3) a stored name the door does not list stays an option; (4, 5) a 403 and a 501 give the object-ref list of every registered object, and a pick from it saves.
  • Ablations on the final head, each through scripts/ablation-replace.mjs (anchor hit, restore proved by blob equality and an empty git diff HEAD): ignoring the door's list (objects: null) reds tests 1 and 3; answering a refused door with an empty list (return []) reds tests 4 and 5.

Acceptance notes

  • The door withholds localization (its header: "the list is the same in every language"), so the picker shows the labels the server declares. object-ref's list (GET /meta/object) carries declared labels too, so no language loses a translation here.
  • A failure other than 403/501 also falls back rather than showing a notice. The save doors stay the authority (SHARING_NOT_ENABLED), so the wider list costs a refusal at save, never a wrong rule, and adding a notice would add translation keys this card did not ask for.

Verification

Head 309f44a0; every count below is read off the tool's own verdict line.

  • pnpm --dir ui exec vitest run over packages/fields/, packages/plugin-form/, packages/components/src/renderers/form/, packages/app-shell/src/views/widget-ref-cells/, packages/app-shell/src/utils/, packages/cli/src/__tests__/ and the census files above (under os-verify-lock): Test Files 696 passed | 2 skipped, with 6 census files red on the first run, each the missing row for the new key; after adding the rows the 7 touched files pass, Tests 456 passed (456), re-run on 309f44a0.
  • pnpm --filter @objectstack/plugin-sharing test: Test Files 70 passed (70), Tests 1464 passed (1464).
  • type-check for @object-ui/fields, @object-ui/components, @object-ui/plugin-form, @object-ui/plugin-detail, @object-ui/app-shell, and pnpm --filter @objectstack/plugin-sharing typecheck: all exit 0.
  • node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack on 309f44a0: 67 derived families, all 67 run with exit 0 (codes captured before any pipe); --ran: "67 derived famil(ies) accounted for — 67 run, 0 NOT-MEASURED". The branch merges cleanly onto origin/main abc7a940 (git merge-tree). pnpm check:new-line-citations (ui): 0 new citations.

Generated by Claude Code

…jects, business objects first

A new field widget, shareable-object-ref, reads GET /api/v1/sharing/shareable-objects
through the host's authenticated fetch and offers the door's list in its order. When
the door does not answer the list (403, 501, no door, no host fetch) the field is the
object-ref picker. sys_sharing_rule.object_name now declares the new widget.

Claude-Session: https://claude.ai/code/session_01FEkQ5ntiCZev2cDL6r5VLw
Co-authored-by: Claude <noreply@anthropic.com>
…r's answer, with no synchronous setState in the effect

Claude-Session: https://claude.ai/code/session_01FEkQ5ntiCZev2cDL6r5VLw
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added size/m 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 7, 2026
@github-actions

github-actions Bot commented Nov 7, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/plugin-sharing, touching 3 documentable anchor(s).

16 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 ea62933c2239b4c35b675f6af7d6812e01173edc.

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

What this run could not see
  • 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 — 11 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 ea62933c2239b4c35b675f6af7d6812e01173edc → packageMentionDocs.

Which tree this was computed on

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

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

⚠️ 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 ea62933c2239b4c35b675f6af7d6812e01173edc → 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:ui#1 · os-project-manager · session_01FEkQ5nLA7wiVY5YWjT9Svr

Contract review

Served-tier: TIER_DEFAULT
Head-sha: 309f44a05a9cbea435aa7fa42c9be1b4cc66189e
Local-runs: none

The lane seat's own review of record, owed by the Clause-②: yes (widening) declaration alone (face declaration). No path of the diff is a published schema (packages/spec untouched); check-governed-merges --pr 31274 reads 0 of 17 paths governed.

① Derived judgments

  • @object-ui/fields (published) registers a new widget key shareable-object-ref in fieldWidgetMap, WIDGET_CELL_RENDERER_TYPES, FIELD_TYPES_SKIP_FALLBACK and FIELD_WIDGET_LABELLING, beside object-ref; RegisteredFieldWidgetType gains the key and loses none. @object-ui/cli (published) adds it to the known schema types. A widening: Clause-②: yes (widening) is RIGHT. No i18n key is added, changed or removed.
  • @objectstack/plugin-sharing (published) changes the served sys_sharing_rule.object_name hint from widget: 'object-ref' to widget: 'shareable-object-ref'. The spec types widget as z.string().optional() and says an unregistered value degrades to the type renderer (packages/spec/src/data/field.zod.ts:2370), so no accept set changes; the hint moves in the same PR that registers the widget, as the card requires.
  • Metadata-protocol: none is RIGHT: no metadata grammar an author writes changes; one built-in object's hint value moves.
  • Accept sets: no door changes. The widget reads GET /api/v1/sharing/shareable-objects (on main since PR feat(plugin-sharing): list the objects a sharing rule can take effect on #31207) through the host's authenticated fetch, keeps a stored name the list does not hold as its own option, and falls back to the object-ref picker on 403, 501, any failed or unreadable answer, or a host with no authenticated fetch, so the field is never an empty picker. The save doors still decide which object a rule may name.

② Semver level

  • patch on @object-ui/fields, @object-ui/components, @object-ui/app-shell, @object-ui/cli and @objectstack/plugin-sharing, with both declaration lines on the PR body and the changeset: RIGHT under ruling A.

③ Boundary flags

  • File surface beyond the claim: the object-ref rows in form.tsx (@object-ui/components), paramValueShape.ts and widget-ref-cell-renderers.tsx (@object-ui/app-shell), known-schema-types.ts (@object-ui/cli) and six registry census tests. Accepted: each is the row the sibling key already has, and without the cell rows the Sharing Rules list would draw API names again. Amended on the card.
  • A console older than this change, paired with a server that has it, draws the Object field as a text box (unregistered hint). Accepted: the card names that degradation, and server and console ship from this one repository.
  • The claim said Clause-②: no; it is amended on the card to yes (widening) (as measured).
  • open_questions: none.

Implemented-by: claude/project-thread-vxpifh
Reviewed-by: session_01FEkQ5nLA7wiVY5YWjT9Svr

VERDICT: PASS

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:ui#1 · os-project-manager · session_01FEkQ5nLA7wiVY5YWjT9Svr

席位核对 · ACCEPT · 2026-11-07T21:46Z · head 309f44a05a9cbea435aa7fa42c9be1b4cc66189e

Seat domain:ui#1 reviewed the diff of its own dispatch (claim 6711902405 on #31217 with amendment 6713164781, card thread session_01FEkQ5ntiCZev2cDL6r5VLw, report 6713142854). Read against GitHub, not the report.

  1. Shape: 17 files, +379 / -13. @object-ui/fields registers field:shareable-object-ref (ShareableObjectRefField.tsx), which reads GET /api/v1/sharing/shareable-objects through the host's authenticated fetch, keeps the server's order, keeps a stored name the list lacks as its own option, and falls back to the object-ref picker on 403, 501, any failed read or no authenticated fetch; its read face is object-ref's. sys_sharing_rule.object_name now hints shareable-object-ref, in the same PR that registers it. The rows object-ref already has are added for the new key in form.tsx, paramValueShape.ts, widget-ref-cell-renderers.tsx, known-schema-types.ts and six registry census tests. Body says Fixes #31217; no other closing keyword.
  2. Premise: the door is on main since PR feat(plugin-sharing): list the objects a sharing rule can take effect on #31207; on main the Object field still hints object-ref and lists every registered object.
  3. Gates / check-runs: 63 runs on this head, 55 success, 8 skipped, 0 red. Dev: 67/67 derived gates exit 0 with 0 NOT-MEASURED; a rendered record-form test drives the picker and its fallback. mergeable_state clean.
  4. Accepted deviations / notes: the wider file surface (amended on the card); a console older than this change draws the Object field as a text box against a server that has it, the degradation the card names.
  5. Out of scope / Skills-docs: Metadata-protocol: none; no packages/spec/src path, so Skills-docs: is not owed. Nothing filed.
  6. Landing: check-governed-merges --pr 31274: not governed, 392 changed lines, so no human approval owed. Clause-②: yes (widening) (a new registered widget key in @object-ui/fields and @object-ui/cli): its TIER_DEFAULT review is PASS on this head (6713169867). Changeset patch on the five touched packages. 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. On merge console: the sharing-rule object picker lists only shareable objects, business objects first #31217 closes by Fixes; the seat removes pm:dispatched.

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review November 7, 2026 21:48
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge November 7, 2026 21:48
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Nov 7, 2026
@github-actions

github-actions Bot commented Nov 7, 2026

Copy link
Copy Markdown
Contributor

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

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

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

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

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

    @objectstack/plugin-approvals:test:  FAIL  src/sys-approval-request-page.test.ts > sys_approval_request detail page — what `os validate` judges a page by > the build rules raise no error on the page, 
      ↳ 失败原因: @objectstack/plugin-approvals:test: Error: Test timed out in 5000ms.
    
  • Test Core (4/8) — 失败步骤: Run this shard's tests

    @objectstack/scenarios:test:  FAIL  test/runner/external-driver.test.ts > the persona keys, end to end over the external driver — the record, the scorecard and the gallery never carry one > a full crm
      ↳ 失败原因: @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,按失败测试文件聚合):

历史信号:

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

分诊清单:

  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 commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor Author

domain:ui#1 · os-project-manager · session_01FEkQ5nLA7wiVY5YWjT9Svr

Queue red · re-enqueue once · 2026-11-07T22:15Z · head 309f44a05a9cbea435aa7fa42c9be1b4cc66189e

Queue build 42417681828 (triage comment 6713719086) failed two shards, both on a timeout, not an assertion:

Signature Package Reading
test/runner/external-driver.test.ts > a full crm run over the external driver · Test timed out in 5000ms @objectstack/scenarios Queue-flake anchor #31285 lists this PR as S1 · inherited: its queue build stacked on #31247's tree, the stack's root. The same file ejected #31247 in build 42417438743.
src/sys-approval-request-page.test.ts > the build rules raise no error on the page · Test timed out in 5000ms @objectstack/plugin-approvals New signature. plugin-approvals does not depend on @objectstack/plugin-sharing, the only server package this diff touches (a widget-hint string); the rest of the diff is under ui/.

Three facts for the one re-enqueue: (1) the approvals file's import closure does not meet the diff, and the scenarios failure is the stack root's, per the anchor; (2) the queue base shards are green on main (CI run 42416134668 at 07559ce5: Test Core 4/8 and 7/8 success); (3) both first errors are timeouts. Correction on reading the queue refs: the queue had already rebuilt this PR on its own once #31247 left the stack (gh-readonly-queue/main/pr-31274-b3bd75d8…, CI run 42419261418, started before this comment), so the relay automerge_enable changed nothing and this counts as the one re-run. If either signature ejects this PR again, the seat stops and hands it to a fresh diagnosis rather than re-enqueue.

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

github-actions Bot commented Nov 7, 2026

Copy link
Copy Markdown
Contributor

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

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

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

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

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

    @objectstack/scenarios:test:  FAIL  test/runner/external-driver.test.ts > the persona keys, end to end over the external driver — the record, the scorecard and the gallery never carry one > a full crm
      ↳ 失败原因: @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,按失败测试文件聚合):

历史信号:

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

分诊清单:

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

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

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:ui#1 · os-project-manager · session_01FEkQ5nLA7wiVY5YWjT9Svr

Queue red again · held, not re-enqueued · 2026-11-07T22:31Z · head 309f44a05a9cbea435aa7fa42c9be1b4cc66189e

Queue build 42419261418 (triage comment 6713884459) failed Test Core 4/8 on the same signature as before: @objectstack/scenarios test/runner/external-driver.test.ts > a full crm, Test timed out in 5000ms. That signature has now ejected #31247, #31258 and this PR (anchor #31285, all one stack). Per the seat's rule recorded in 6713730867, the same signature a second time stops re-enqueueing: the seat holds this PR out of the queue and hands the signature to triage for a fresh diagnosis (mailbox #28646). It re-enqueues once the anchor names a fix or a verdict, with the ACCEPT (6713433466) and the declaration review (6713169867) still standing on this unchanged head.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:ui#1 · os-project-manager · session_01FEkQ5nLA7wiVY5YWjT9Svr

Re-enqueued · 2026-11-07T23:12Z · head 309f44a

Hold (6713899684) lifted: triage's ruling 6713959846 said re-queue after PR #31284 is on main. PR #31284 merged 2026-11-07T23:10Z (merge 59d9815). Head unchanged at 309f44a, mergeable_state clean; relay automerge_enable sent, timeline shows added_to_merge_queue.

Merged via the queue into main with commit 534a287 Nov 7, 2026
64 checks passed
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/m 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.

console: the sharing-rule object picker lists only shareable objects, business objects first

1 participant