Skip to content

feat(spec): declare record:approval_decision, the approval decision panel, with an empty strict ComponentPropsMap row - #22532

Merged
objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/issue-22472-approval-decision-component
Oct 9, 2026
Merged

objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/issue-22472-approval-decision-component

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #22472
Clause-②: yes

What this declares

record:approval_decision, the approval decision panel of a sys_approval_request record page, is now a declared page component type in @objectstack/spec. One node shows the request's decision progress and its declared decision actions. This is the spec-lane half of the maintainer's ruling on objectstack-ai/objectui#12045 (6079807016, letter 乙, answered 「同意」): a type with no ComponentPropsMap row passes any props bag, so the ruling asks for a row that os validate checks. It is an ordinary v18 widening (「17.x 不会发新版」).

File Change
packages/spec/src/ui/page.zod.ts record:approval_decision joins PageComponentType (Record Context group), and PRINT_REFUSED_PAGE_COMPONENT_TYPES gets its print reason
packages/spec/src/ui/component.zod.ts the ComponentPropsMap row emptyProps('record:approval_decision'); the emptyProps docblock lists it
content/docs/references/ui/page.mdx regenerated (gen:docs): the PageComponentType list and the type column
packages/spec/src/ui/component-record-approval-decision-22472.test.ts pins at the row, the node, the page, the vocabulary and the print classification
packages/lint/src/validate-record-approval-decision-22472.test.ts pins at the two authoring rules and the shared pipeline os validate runs
.changeset/22472-spec-record-approval-decision.md @objectstack/spec minor, Clause-②: yes (widening)

Contract decisions (the spec seat's; relayed to objectui#12045)

  1. Name: record:approval_decision, as proposed. record is a reserved namespace (derived from the enum), so a misspelling there is a component-type-unknown error that offers the declared spelling. objectui already uses this name in its module-internal renderer and its tests, so no rename is needed on their side.
  2. Props: an empty strict object, as proposed. I measured this from the renderer's read points on objectui main at d03b022 (packages/app-shell/src/views/approval-decision/ApprovalDecisionPanel.tsx, landed in objectui a368ccb). ApprovalDecisionRenderer discards the schema node (schema: _schema). It draws from the record context (the bound request row, with its viewer and decision_progress) and from sys_approval_request's own declared actions. className and the designer attributes it reads are node-level keys, never properties. The file is not at this repo's .objectui-sha pin f0268ad78: git cat-file -e at the pin answers 128, with record-approvals-renderer.tsx at the same pin as the control answering 0. That is why the citation names objectui main, not the pin. The row reuses the existing emptyProps(type) factory, the spelling of the nine other zero-prop rows (nav:menu, element:divider, mcp:connect-agent, …), so the refusal names the component.
  3. An enum member, not a row-only type. record:line_items, element:definition-list and the other row-only types entered the vocabulary through the open string arm. The vocabulary admits a type that way only on measured registration, publication and authorship (component-type-vocabulary.ts; the #20371 rows write all three down). This type has none of the three yet. objectui keeps its renderer unregistered until this declaration exists (its docblock says so), and plugin-approvals authors the page after it (plugin-approvals: serve sys_approval_request's detail page as a slotted page through the manifest pages, and declare the thread reply as approval_comment (objectui#12045 B1, ruling 乙) #22473). A spec-first declaration is therefore an enum member. One consequence for objectui: its palette-coverage test (block-config.test.ts, derived from PageComponentType.options) asks for an offer-or-exclude decision for the new member once objectui moves to next (objectui#12030).

Measured hypotheses

  • H1 holds. record:approval_decison → one component-type-unknown finding, severity error, message offering 'record:approval_decision'. The declared spelling in the same position → no finding. Both are pinned in the lint test, through validateComponentTypes and through runAuthoringRules('validate', …).

  • H2: every table the member must appear in. Grep for record:history / record:line_items / record:reference_rail across packages/spec, packages/lint, content, scripts:

    • PageComponentType (page.zod.ts): added.
    • ComponentPropsMap (component.zod.ts): added.
    • PRINTABLE_PAGE_COMPONENT_TYPES / PRINT_REFUSED_PAGE_COMPONENT_TYPES (page.zod.ts): added to the refused map. page-print.test.ts requires every live known type to be classified exactly once, and it passes.
    • content/docs/references/ui/page.mdx: regenerated.
    • Derived, not edited: KNOWN_COMPONENT_TYPES, KNOWN_COMPONENT_TYPE_CANDIDATES and RESERVED_COMPONENT_TYPE_NAMESPACES (unchanged: record was already reserved). The lint print gate and its it.each iterate the map. The record:*-on-react-page refusal in validate-react-page-props.ts is prefix-based.
    • Not a table of members: scripts/format-type.test.ts (a static fixture that still lists the retired types), validate-page-field-bindings.ts (rows for field-binding props only; this type has none), sdui.manifest.json (objectui's build output).
  • H3 holds. A no-props row is spelled emptyProps(type), a strictObject with no keys. Any key → unrecognized_keys naming `record:approval_decision` and the key, and through lint one component-props-unknown-key warning at properties.KEY. A node-level key written inside properties (className) gets the "belongs on the component NODE" prescription.

  • H4, measured and not fixed. I ran validateComponentTypes / validateComponentProps from this branch on a record page:

    • record:approvals → component-type-unknown/error, no props finding.
    • record:attachments → component-type-unknown/error, no props finding.
    • Controls: record:approval_decision and record:details → no type finding, one props finding each.

    Both are refused outright. objectui synthesizes both nodes at render time (buildDefaultPageSchema); no authored producer exists in this repo.

Verification

Tests at b101db36c7 (the final commit), all under scripts/pm/os-verify-lock.sh:

  • pnpm --filter @objectstack/spec exec vitest run --maxWorkers=2 src/ui/component-record-approval-decision-22472.test.ts src/ui/page-print.test.ts src/ui/component-type-vocabulary.test.ts: 3 files, 54 tests passed.
  • pnpm --filter @objectstack/lint exec vitest run --maxWorkers=2 src/validate-record-approval-decision-22472.test.ts src/validate-print-page-blocks.test.ts src/validate-component-types.test.ts: 3 files, 94 tests passed, against a spec dist rebuilt from this branch. On a stale dist the declared type would read as component-type-unknown, so the green lint pins also show that the rebuilt dist was read.
  • Full suites, one locked batch joined with &&, VERDICT command-exit 0: pnpm --filter @objectstack/spec typecheck (incl. check:test-typecheck OK) · pnpm --filter @objectstack/lint typecheck (OK) · spec vitest run --project local: 632 files, 18837 passed, 1 todo · spec vitest run --project repo: 54 files, 915 passed · lint vitest run: 132 files, 6003 passed.
  • Ablation, one time and not kept: node scripts/ablation-replace.mjs deleted the row line (anchor x1 → x0, blob 583b6e1e → 908d18cc). The spec pin file went to 5 failed / 3 passed. The 3 that stayed green are the vocabulary and print pins, which the enum member alone still satisfies. Restored blob = HEAD 583b6e1e, and git diff HEAD is empty.
  • Gates: node scripts/pm/dispatch-gates.mjs --commands on this diff derived 109 commands (a superset of the dispatch list, +29 from the docs and lint-test paths). Every one ran with its exit code recorded. --ran reconciliation: 109 derived, 107 run, 2 NOT-MEASURED, 0 UNRUN. Five gates first exited 3 (unbuilt @objectstack/lint / client / objectql). They passed (exit 0) after their packages were built. NOT MEASURED: check:dual-build-cjs-loads and check:type-check-debt. Reason: both refuse unless every workspace package is built (a whole-repo build), which is left to CI. pnpm --filter @objectstack/spec check:generated is green after gen:docs. authorable-surface/ and api-surface/ did not move (the enum adds a value, not a key or an export).

Acceptance notes


Generated by Claude Code

claude added 3 commits October 9, 2026 18:38
…ponentPropsMap row

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VZqqwTj2wsihZEbfT6yyYN
…ary and the authoring doors; regenerate page reference

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VZqqwTj2wsihZEbfT6yyYN
…c's component vocabulary

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VZqqwTj2wsihZEbfT6yyYN
@github-actions

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

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

2 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:

  • content/docs/protocol/objectui/layout-dsl.mdx (via ComponentPropsMap (symbol, a top-level const object))
  • content/docs/ui/pages.mdx (via PageComponentType (symbol, a top-level const object))

⛔ 5 release-owned page(s) also name something this change touched. These are read-only:

  • content/docs/releases/v17/17-1.mdx (via ComponentPropsMap (symbol, a top-level const object))
  • content/docs/releases/v17/17-3.mdx (via ComponentPropsMap (symbol, a top-level const object))
  • content/docs/releases/v17/17-4.mdx (via ComponentPropsMap (symbol, a top-level const object))
  • content/docs/releases/v17/17-5.mdx (via ComponentPropsMap (symbol, a top-level const object))
  • content/docs/releases/v17/17-7.mdx (via ComponentPropsMap (symbol, a top-level const object), PageComponentType (symbol, a top-level const object))

content/docs/releases/ is RELEASE-OWNED (AGENTS.md "Documentation Guardrails"): release
notes are written centrally at release time, and a code PR that edits them is the exact PR
that guardrail exists to stop. They are still audited — read-only. If one of them is actually
wrong, file an issue or open a dedicated docs-only PR; do not edit it here.

What this run could not see

Coarse fallback — 139 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 ee8751d41e61a18f7819e4d3ad2c340f51ab2418 → packageMentionDocs.

Which tree this was computed on

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

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

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

@github-actions github-actions Bot added documentation Improvements or additions to documentation protocol:ui tests tooling labels Oct 9, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: b101db36c7c2f10dccaa3cad818599fc7ccfd9be
Local-runs: none

Read at 2026-10-09T20:53Z: card #22472 (body, the claim 6086901040, the dev report 6088349091); objectui#12045 (body and ruling 6079807016); PR #22532 (body, the 6-file list, the net diff of b101db36c7 against its merge-base 9411faa1ba on main, +251/-4); the 35 check-runs on the head: 35 completed, 33 success, 2 skipped (Console Pin Gate, whose console filter this diff does not match; Packed-tarball smoke (opt-in)), 0 failed, 0 in progress. All seven required contexts read success: Lint and Repo Gates, TypeScript Type Check, Test Core, Dogfood Regression Gate, Build Core, Temporal Conformance (live PG + MySQL), Governed Surface Queue Guard. No governed path in the file list; 255 changed lines; head repo is the base repo; draft, auto-merge unarmed. Source read, never run: origin/main of this repo at d303b3e7af, and the sibling objectui checkout at the commit the row cites (d03b022) and at the pin (f0268ad78), through git show / git cat-file only.

① Derived judgments

  1. PageComponentType gains record:approval_decision (page.zod.ts) — RIGHT, and the right door. The dev's reason cites the wrong rule for the right conclusion. The three-part evidence face (registration, publication, authorship) is the vocabulary's rule for STRING_ARM_REGISTERED_TYPES — row-LESS types in a reserved namespace, a ledger EMPTY since finding(showcase): project-detail's record:line_items block keys its five columns as field, while the line-items grid binds name — the Tasks grid renders empty cells #21142. Row-only map entries (record:line_items, element:metadata_viewer, element:definition-list, the object-* blocks) enter under a different premise the same file states: "the measured string-arm registrations that DID get a row" — a renderer already registered and reachable through the open arm, its key set measured at the .objectui-sha pin (the finding(showcase): project-detail's record:line_items block keys its five columns as field, while the line-items grid binds name — the Tasks grid renders empty cells #21142 row comment; the finding(spec): objectui's curated action:button/group/menu/icon and element:definition-list/element:repeater blocks have no ComponentPropsMap row, so objectui#10872 cannot arm them by reference #20371 test header). record:approval_decision fails that premise, not the ledger's: nothing registers it (objectui d03b022 pins ComponentRegistry.has('record:approval_decision') false, and the panel docblock says registration waits for this row), the file is absent at the pin f0268ad78 (verified: git cat-file -e exits 128), and no author exists. A spec-first type therefore has only the enum door, and the card itself expects one ("the tables the enum's members must appear in"). The enum comment's wording should name the map's premise rather than the ledger's face; prose, not contract — not a block.
  2. ComponentPropsMap['record:approval_decision'] = emptyProps('record:approval_decision') (component.zod.ts) — RIGHT. Read at objectui d03b022 (packages/app-shell/src/views/approval-decision/ApprovalDecisionPanel.tsx): ApprovalDecisionRenderer takes { schema: _schema, className, ...props } and discards the node; splitDesigner reads only data-obj-id, data-obj-type, style (designer-injected, node-level); the panel reads useRecordContext() and sys_approval_request's own declared actions at record_section. No authored key is read, so the accepted set is empty and emptyProps(type) is the spelling of its nine siblings. className inside properties is answered by COMPONENT_NODE_KEYS_GUIDANCE (id, events, style, className, responsiveStyles, dataSource, responsive belong on the NODE) — the spec's standing answer for every component, so the row introduces no new rule. The citation names repository and commit, which is a reading under the discipline; the pin cannot carry it (absent, verified), and check:objectui-pin-citations sits inside the green Lint and Repo Gates.
  3. PRINT_REFUSED_PAGE_COMPONENT_TYPES gains the member with its reason — RIGHT and complete. page-print.test.ts pins every live KNOWN type as printable-or-refused exactly once and the reason as the clause after "it" with no full stop; the new reason ends "with nothing to print" and the pin is in the green Test Core. Tables that must list each member and do: PageComponentType, ComponentPropsMap, the print classification, the regenerated content/docs/references/ui/page.mdx (two lines, gen:docs). Tables that derive and need no edit — RIGHT: RESERVED_COMPONENT_TYPE_NAMESPACES (unchanged, record was already claimed; the namespaces pin in component-type-vocabulary.test.ts still holds), KNOWN_COMPONENT_TYPES and KNOWN_COMPONENT_TYPE_CANDIDATES (+1 each; typo suggestions now offer the member), RECORD_CONTEXT_BLOCK_TAGS in react-blocks.ts (derived from the map's record: keys, so the react-page publish gate refuses RecordApprovalDecision with the generic prescription; REACT_RECORD_BLOCK_ALTERNATIVES is optional per type by its own docblock), the record:* prefix refusal in validate-react-page-props.ts, the lint print gate's it.each. Not member tables: validate-page-field-bindings.ts (rows only for field-binding props; this type has none), scripts/format-type.test.ts (static fixture), the validate-component-props.ts docblock, the sdui manifest (objectui's build at the pin), the v18 semantic migration entries (historical).
  4. Accept-set change at the authoring doors — RIGHT, pinned on both sides. Before: record:approval_decision was component-type-unknown (error) — reserved namespace, undeclared. After: accepted; its bag is judged — absent or {} passes, any key is component-props-unknown-key (warning) at properties.KEY naming the component and the key, a node key inside properties gets the NODE prescription; record:approval_decison stays refused and now offers the declared spelling. Pinned in packages/spec/src/ui/component-record-approval-decision-22472.test.ts (row, node, page, vocabulary, print) and packages/lint/src/validate-record-approval-decision-22472.test.ts (the two rule ids, through validateComponentTypes / validateComponentProps and through runAuthoringRules('validate', …)). The ablation the report describes (row deleted, 5 of 8 spec pins red, the 3 survivors being the enum-only pins) is consistent with that split; the check-runs are the verdict here, not the local numbers.
  5. Public surface — RIGHT as a widening. No export added or removed (api-surface/ unchanged), no authorable key (authorable-surface/ unchanged), json-schema.manifest/ and the react-blocks contract unchanged — all read off the green TypeScript Type Check job, which runs every spec gate sequentially. emptyProps docblock count nine → ten; one strictObject( call site as before. Who derives from PageComponentType.options: in this repo, everything above plus component.test.ts's safeParse loops and the Iso pin, all green. In objectui at d03b022, TWO consumers, not the one the dev named: block-config.test.ts (palette: every enum value offered or excluded with a reason) and registry-inputs-spec-parity.test.ts ("accounts for every spec-carried block — judged, propless, or ledgered", over ComponentPropsMap rows; its isRetiredUpstream reads the enum). Both fire the moment objectui resolves a spec carrying this member (objectui#12030, the switch to next); neither fires at the pin, which resolves ^17, so the skipped Console Pin Gate hides no break. Acceptable: both tests exist to force a decision on a new member, and objectui#12045's page-mount step (Blocked-by this card and Gate: an ObjectQL find double in a test must apply the caller's limit, or refuse it loudly #12030) is where the registration, the zod arm, known-schema-types.ts and the palette decision land together — the panel's own docblock says so.
  6. Hand-written content/docs/ui/pages.mdx not updated — ACCEPTED. Its "Record context" list is introduced as "include", already omits record:discussion and record:line_items, has no gate, and sits outside the dispatched surface. A docs-only follow-up, not a rider.

② Semver level

  • .changeset/22472-spec-record-approval-decision.md: '@objectstack/spec': minor, body Clause-②: yes (widening). What the diff publishes is one new enum value, one ComponentPropsMap row and one print-refusal entry — additive on the published spec; nothing retired, renamed or narrowed, no 17.x author to migrate, so no ADR-0087 disposition marker is owed; check:adr-0087-registration and check:changeset-no-major are inside the green gates and Check Changeset is success. main is in pre mode next, so this lands on the 18.0.0-next line, as the ruling and the card read it (「17.x 不会发新版」). minor is the floor a yes owes and the right level — RIGHT.
  • Only @objectstack/spec publishes: packages/lint gains a test file and no source; content/docs is not a package. No second changeset owed — RIGHT.
  • Clause-②: line: the PR body carries Clause-②: yes, bare, at the start of its own line — the gate's one carrier, read as yes; the changeset carries yes (widening). Both are well-formed; the arm adds direction, not a different value, and the gate reports the two as different declarations without requiring equality. Not a defect. Optional before landing: add (widening) to the body's line so the headline and the changeset grep to the same string.

③ Boundary flags

Dev deviations, each answered:

  1. PageComponentType lives in page.zod.ts, not component.zod.ts — that file was on the dispatched surface already (the print tables). No breach.
  2. New packages/lint/src/validate-record-approval-decision-22472.test.ts — the surface named validate-component-props.ts only if a row needed a hook; none did, and no lint source changed. A test alone, in the only package that can import the two rule ids H1 and H3 ask to pin. Accepted.
  3. Attribution: the model-free trailer pair and the session-URL PR footer, per AGENTS.md over the harness reminder — verified on all three commits (Co-authored-by: Claude, Claude-Session:) and on the PR body. AGENTS.md governs; correct.
  4. Stray /suites.pid (5 bytes, container root, outside every repo), left by a shell-scoping slip — ESCALATED to the maintainer: rm /suites.pid by hand. Nothing in any repo is affected.
  5. Enum member plus row, beyond the card's text — answered in ① item 1: right conclusion, the rule it cites is the ledger's, the premise that decides is the map's.

open_questions: none declared; none found.

out_of_scope_findings, judged:

  • A. record:approvals / record:attachments — objectui d03b022 carries both (plugin-detail/src/synth/buildDefaultPageSchema.ts, app-shell/src/utils/pageSchemaIntrospect.ts, cli known-schema-types.ts) inside the spec-reserved record namespace with no row and no member; the dev's H4 from the branch: component-type-unknown error, props never judged; no authored producer here. Honest, and correctly outside this diff — the card scoped it out itself. The disposition "noted, not filed" is ESCALATED: the finding has contract text (component.zod.ts's finding(showcase): project-detail's record:line_items block keys its five columns as field, while the line-items grid binds name — the Tasks grid renders empty cells #21142 row comment calls record:line_items "the last registered record:* renderer without a row", which these two falsify; the vocabulary's claim that the map covers the measured registrations) and a repro (H4), and Prime Directive chore: version packages #10 files a contract violation on its evidence. The adopting seat files ONE unassigned finding card naming both types, with the report's dedupe words; the remedy (a measured row each, or objectui renaming out of the namespace) is graded there. Not a block on this PR.
  • B. Placement unchecked — record:approval_decision on any other object's record page parses, validates clean, and objectui draws nothing (the renderer returns null unless the record context's object is sys_approval_request). That is the metadata-authoring-trap shape in chore: version packages #10's own words — an authored block silently dropped, the very failure the ruling cited to justify the row — and "no producer yet" is a reach argument chore: version packages #10 does not admit. ESCALATED: the adopting seat files it as an unassigned domain:spec finding (a lint rule binding the type to the page's object, with plugin-approvals: serve sys_approval_request's detail page as a slotted page through the manifest pages, and declare the thread reply as approval_comment (objectui#12045 B1, ruling 乙) #22473 as its first producer; validate-page-field-bindings.ts is the precedent for object-aware component checks). The diff states the constraint in the row comment and the changeset, so the claim is as narrow as the enforcement; the declaration is not at fault and this PR is not blocked.

Found by this review, not flagged by the dev:

  • C. The PR body says the contract decisions were "relayed to objectui#12045"; the report's api_writes lists three writes, none on objectui. The name stayed as proposed, so the card requires no comment there, but the two objectui consequences in ① item 5 are owed to objectui#12045's page-mount step. ESCALATED to the adopting seat: one comment on objectui#12045 at adoption, naming both tests.
  • D. ① item 6: the hand-written pages doc omits the member. Noted; docs-only follow-up.

Implemented-by: claude/issue-22472-approval-decision-component
Reviewed-by: session_01VZqqwTj2wsihZEbfT6yyYN

VERDICT: PASS


Generated by Claude Code

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

Copy link
Copy Markdown
Contributor Author

Standing down on a failure that is not this PR's. domain:spec seat 1 (#6017) · session session_01VZqqwTj2wsihZEbfT6yyYN · 2026-10-09T21:19Z.

@github-actions

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

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

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

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

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

↳ 失败原因 是判读的关键:超时(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,按失败测试文件聚合):

  • ⚠️ 本次没有可用的聚合签名(日志里没有能解析出测试文件名的 FAIL 行)—— 这不是「没有同签名的其他 PR」,是这一轮没测到。跨 PR 聚合本次不可用,请手工比对其他 PR 的同类评论。
  • ⚠️ 24h 评论账本没读完(超过 5 页仍未读到窗口尽头),所以上面的「不同 PR 数」是下界,不是全量。

历史信号:

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

分诊清单:

  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 deleted the claude/issue-22472-approval-decision-component branch October 9, 2026 23:09
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:ui size/m tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

spec(ui) v18: declare the approval decision panel as a page component type with a strict ComponentPropsMap row (objectui#12045 B1, ruling 乙)

2 participants