Skip to content

fix(console, data-objectstack): the report drill's definition read names the report's package as the reader, and the chart colour probe's non-2xx guard is pinned (ADR-0150 D3) - #33366

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

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

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Leehom · project thread

Fixes #32760

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

维护者速读

  • 改了什么:报表点击下钻时,如果服务端答复里没有现成的下钻过滤条件,控制台会再读一次数据集定义来拼过滤条件;这次读取现在带上报表所属包作为读者包(?callerPackage=),和报表自己的查询解析到同一个数据集。为此 MetadataClient.get 新增一个可选的 callerPackage 参数。另给图表颜色探测的「非 2xx 不解析」守卫补了一个能区分它的测试。
  • 为什么改:卡 ui: follow-ups of the dataset caller arm (#32311) — stale 32077 BREAKING line, the colour-probe guard pin, ReportView drill bare read #32760 的三项复核遗留。第 1 项(32077 changeset 的 BREAKING 句)已随 18.4.0 一起发布,无文件可改,按卡的说明撤销。第 3 项实测发现这条「旧服务端」分支在当前服务端上也会走到:按 type: 'date' 且没有 dateGranularity 的维度分组的报表,服务端只给 object 不给下钻元数据,点击就落到这里,原来按裸名读取,包里的报表可能读到别的包的同名数据集,或两包同名时 409。
  • 风险与回滚:风险低。只放宽(新增可选参数,不传时请求字节不变);无元数据、存储或 spec 变化。读取被拒时不下钻、不退回裸名重试。回滚即 revert 本 PR。
  • 先看:ui/packages/app-shell/src/views/ReportView.tsx 的 handleDatasetDrill(回退分支带读者包);ui/packages/data-objectstack/src/metadata-client.ts 的 MetadataGetOptions.callerPackage 与 readItemResponse;ui/packages/app-shell/src/views/ReportView.drillCallerPackage-32760.test.tsx(用真实报表渲染器点击行)。
  • 两分钟验证:pnpm --dir ui exec vitest run packages/app-shell/src/views/ReportView.drillCallerPackage-32760.test.tsx packages/data-objectstack/src/metadata-client.callerPackage-32760.test.ts,预期 7 个全绿。
  • 需要你做的:无,席位落地。

What changes

The card's three items, each re-measured on origin/main (71ade1ae).

  • Item 1 dropped (as the card says to when a release cuts between). .changeset/32077-dataset-query-package.md is not on origin/main: it shipped in 18.4.0 (PR chore: version packages #29963) together with fix(ui): dataset callers send the reader's package (?callerPackage=) instead of the exact qualifier, and the report date read and chart colour probe read by package (ADR-0150 D3) #32629's changeset, and both are in the 18.4.0 sections of plugin-charts, plugin-report, plugin-dashboard and data-objectstack CHANGELOG.md. fix(ui): dataset callers send the reader's package (?callerPackage=) instead of the exact qualifier, and the report date read and chart colour probe read by package (ADR-0150 D3) #32629's own 18.4.0 entry already states what happens to the 32077 BREAKING note (the dependency case is served again; outside-closure is the residual break, with its fix). No changeset is edited here.
  • Item 2, the colour probe's non-2xx guard is pinned. ObjectChart.optionColors.test.tsx gains a row in the ADR-0150 D3 describe: a 409 whose body also carries a definition naming task (beside the ADR-0112 error). Without the guard the probe parses that body, reads meta/object/task and relabels todo as To do from a dataset the server refused to resolve. With it: one request (the refused definition read), raw labels, no colours. The existing 409 row stays as it is; it cannot tell the guard apart because its envelope names no object (fix(ui): dataset callers send the reader's package (?callerPackage=) instead of the exact qualifier, and the report date read and chart colour probe read by package (ADR-0150 D3) #32629's A10).
  • Item 3, the ReportView drill fallback sends the reader's package. Measured: the branch is not old-server-only, so it is not deleted.
    • queryDataset (service-analytics) sets object on every dataset answer. It sends dimensionFields / drillRawRows only for dimensions with a field and a type other than date, and drillRanges only for a date dimension with a dateGranularity. DatasetDimensionSchema makes dateGranularity optional, so a report grouped by a type: 'date' dimension with no granularity gets object and drillScopes but no exact filter. The renderer then emits the drill with no objectFilter (DatasetReportTable's drill), and handleDatasetDrill takes the fallback, which read metadataClient.get('dataset', NAME) bare.
    • The fallback now reads it as the report's reader: { callerPackage: servedPackageId(editSchema || reportData) }, the same served package the renderer's ReportPackageContext gives every selection (the renderer receives previewReport, the same editSchema || reportData). A report authored in the environment sends none. A refusal is caught as before (ReportView: drill failed), so no drawer opens and nothing is retried bare.
    • MetadataClient.get had no caller arm: its packageId is the exact qualifier ?package= (D5), which refuses a dataset only a dependency holds. MetadataGetOptions gains an optional callerPackage, sent as ?callerPackage= (the /meta door's D3 arm, META_ITEM_CALLER_PACKAGE_PARAM in packages/rest/src/meta-item-read-gate.ts), omitted when absent or empty. Using the client keeps the console's one authenticated meta transport and its ?preview=draft overlay, which a hand-rolled fetch would lose. The door refuses callerPackage beside package (400) and on any type but dataset; the client sends what it is given and does not pick between them.
    • The comment above handleDatasetDrill now says when the fallback runs and how it reads.
  • Changeset .changeset/32760-report-drill-caller-package.md: @object-ui/data-objectstack, @object-ui/app-shell (private) and @object-ui/console (ships app-shell), patch. plugin-charts changes a test file only, which its files[] (dist) does not ship.

Tests

  • ui/packages/plugin-charts/src/ObjectChart.optionColors.test.tsx: "a refusal whose body names the object is still a refusal: no object read, theme palette kept".
  • ui/packages/app-shell/src/views/ReportView.drillCallerPackage-32760.test.tsx (new). It renders the real ReportView with the real report renderer, answers the current server's shape for a date dimension with no granularity, and clicks the dataset-drill-row, so the fallback is reached through the input pipeline a user drives:
    • READS_AS_THE_REPORTS_READER: one definition read, ('dataset', 'task_metrics', { callerPackage: 'com.acme.app' }), and the drawer opens on task with { due_date: '2026-03-01' }.
    • ENVIRONMENT_REPORT_READS_BARE: a report with no _packageId reads with {}.
    • REFUSAL_IS_NO_DRILL: a rejected read is logged once, never retried, no drawer.
    • FAST_PATH_CONTROL: an answer with dimensionFields / drillRawRows drills with no definition read.
  • ui/packages/data-objectstack/src/metadata-client.callerPackage-32760.test.ts (new): ?callerPackage= sent and never as ?package=; encoded and beside ?preview=draft; CONTROL, omitted or empty sends no parameter.
  • Ablations (one-off, scripts/ablation-replace.mjs, each restore proven blob == HEAD and git diff HEAD empty; @object-ui/* resolves to src through the vitest aliases, so no rebuild):
leg mutation pinning file(s) result
B1 probe guard if (!defRes.ok) made never-true ObjectChart.optionColors.test.tsx 1 failed / 11 (the new row: expected 'To do' to be 'todo'); the old 409 row stays green
B2 ReportView fallback passes {} whatever the package the two new files 2 failed / 7 (READS_AS_THE_REPORTS_READER, REFUSAL_IS_NO_DRILL)
B3 client never pushes callerPackage= the two new files 2 failed / 7 (the two client rows that send one)

Acceptance notes

  • Item 3 route. The order's PM hypothesis preferred deletion if no supported server reaches the branch. The measurement above shows the current server reaches it, so the ruling's other arm applies. Deleting it would leave a date-grouped report with no drill at all (the renderer emits no objectFilter for it).
  • The claim was amended for this route (comment 6880606745): Clause-②: yes (widening), the file surface plus ui/packages/data-objectstack/src/metadata-client.ts and its test. Metadata-protocol: none: no metadata shape, schema, stored row or authorable key changes.
  • Seen, not filed (read-only inference). On that fallback, a type: 'date' dimension with no granularity filters its field by the clicked group value as the answer shows it (filter[due_date] = '2026-03-01' here). Whether the server's label pass rewrites such a value before the client sees it was not measured; the drill result for those reports is therefore not claimed correct beyond the dataset it reads. The fallback still ignores the object the current server sends and takes the definition's.
  • ObjectChart.tsx is not edited; the guard was only ablated.

Verification

All readings on head c72c8a04 unless noted (base origin/main 71ade1ae). Every number is from a shared box under scripts/pm/os-verify-lock.sh.

  • build: pnpm --filter '@object-ui/app-shell^...' --filter '@object-ui/plugin-charts^...' build (plus the @objectstack spec, formula, client, lint and sdui-parser closures), lock VERDICT command-exit 0.
  • type-check: @object-ui/data-objectstack, @object-ui/app-shell (tsc --noEmit and tsconfig.test.json), @object-ui/plugin-charts (both): each VERDICT command-exit 0.
  • suites: pnpm --dir ui exec vitest run packages/data-objectstack/ packages/plugin-charts/ packages/app-shell/src/views/ReportView: 229 files passed, 2755 tests passed, 9 skipped, VERDICT command-exit 0 (head 4afe687a; the last commit only adds a module-top import to the new ReportView test, which was re-run alone on c72c8a04: 4/4).
  • derived gates: dispatch-gates --ran reads 37 derived, 37 run, each exit 0, 0 NOT-MEASURED, 0 UNRUN. The first pass (head 4afe687a) had one red, check:test-source-alias on the new ReportView test (a dynamic import('@objectstack/lint') reached through ReportConfigPanel); fixed by the module-top import, then all 37 re-run on c72c8a04.
  • check:type-check-debt: 0 ledger entries re-measured for this diff (none of the touched packages is in the ledger).
Derived gate record (c72c8a0)
node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0
node scripts/check-adr-0087-registration.mjs --self-test :: exit 0
node scripts/check-changeset-no-major.mjs --base origin/main :: exit 0
node scripts/check-closing-keyword-parity.mjs :: exit 0
node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0
node scripts/check-comment-mask-corpus.mjs :: exit 0
node scripts/check-empty-changeset.mjs --base origin/main :: exit 0
node scripts/check-empty-changeset.mjs --self-test :: exit 0
node scripts/check-sdui-manifest.mjs :: exit 0
node scripts/check-sdui-manifest.mjs --self-test :: exit 0
node scripts/ci/snapshot-next.mjs --self-test :: exit 0
node scripts/pm/release-rehearsal-clone.mjs --self-test :: exit 0
node scripts/release-pending-publish.mjs --self-test :: exit 0
pnpm --dir ui exec vitest run scripts/ :: exit 0
pnpm --filter @objectstack/spec run check:duration-unit-keys :: exit 0
pnpm --filter @objectstack/spec run check:error-code-provenance :: exit 0
pnpm check:changeset-gate-self-tests :: exit 0
pnpm check:closed-ceremony-text :: exit 0
pnpm check:cross-package-test-inputs :: exit 0
pnpm check:dispatcher-error-vocabulary :: exit 0
pnpm check:driver-memory-census :: exit 0
pnpm check:engine-double-contract :: exit 0
pnpm check:gitlink-declared :: exit 0
pnpm check:nul-bytes :: exit 0
pnpm check:published-files :: exit 0
pnpm check:query-options-erasure :: exit 0
pnpm check:refd-timer-probe :: exit 0
pnpm check:registry-log-declared :: exit 0
pnpm check:rest-log-spy-declared :: exit 0
pnpm check:skill-identifier-liveness :: exit 0
pnpm check:test-source-alias :: exit 0
pnpm check:tier-file-adoption :: exit 0
pnpm check:type-check-coverage :: exit 0
pnpm check:type-check-debt :: exit 0
pnpm check:undeclared-dep-imports :: exit 0
pnpm check:watch-hint-literal :: exit 0
pnpm check:where-matcher :: exit 0

Generated by Claude Code

…sal whose body names the object

The existing 409 pin answered an ADR-0112 envelope that names no object, so a
probe with no status guard stopped at the missing `object` anyway and the pin
stayed green. This refusal's body also carries a definition naming `task`:
without the guard the chart reads `task` and relabels from it.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FEkQ5muSKmXfKL9WVj7dKY
…mes the report's package as the reader

MetadataClient.get takes an optional callerPackage, sent as ?callerPackage=
(ADR-0150 D3), distinct from packageId (the exact qualifier). ReportView's
drill reads the dataset definition with the report's served package when no
exact drill filter arrives, which the current server answers for a report
grouped by a date dimension with no granularity, not only an older server.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FEkQ5muSKmXfKL9WVj7dKY
@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 14, 2026
@objectstack-fleet objectstack-fleet Bot added the needs:contract-review Marker only — PR awaits its at-tier Contract review PASS; no check reads it, the record decides label Nov 14, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

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

Contract review

Served-tier: TIER_DEFAULT
Head-sha: c72c8a04ca5633a6c054ffd2701350d95ed7cd8f
Local-runs: none

Read: card #32760 body and all five comments (triage 6828393064, re-grade 6837951505, claim 6880548960, amendment 6880606745, os-dev-report 6881549558); PR #33366 body and its six-file list; the net diff 71ade1ae..c72c8a04; the server door on origin/main; the check-runs on this head.

① Derived judgments

  • @object-ui/data-objectstack, MetadataGetOptions.callerPackage?: string (metadata-client.ts:494-505, sent at :1263). Right. It only widens the interface: an optional member, sent as callerPackage= and left out when absent or ''. No member is removed or narrowed, and a call that omits it sends the same bytes as before (the CONTROL row pins this). The interface is already exported from the package entry (index.ts:8411), so nothing new is exported. getDraft keeps its own narrower options type and does not forward the new member, which is correct, because the door serves the caller arm on dataset reads only.
  • The parameter is live on the server, so the fix is not inert. Right. On origin/main, packages/rest/src/meta-item-read-gate.ts defines META_ITEM_CALLER_PACKAGE_PARAM = 'callerPackage' (:2397) and lists it in META_ITEM_READ_PARAMS (:2385). It sits in the once arity set (:2492). Rule 4 of metaItemQueryRefusal refuses it with 400 when it is blank or all, when package is also present, or on any type but dataset (:2614-2633). metaCallerPackageQuery (:2665) resolves the reader's package by D3 (its own item, else the one holder in its closure plus sys, else 409) and rewrites the read to the holder's package. Both transports call it: meta-item-read-routes.ts:491 (RestServer) and runtime/src/domains/meta.ts:2062 (dispatcher). The client spelling matches the server param exactly, and the client never sends it beside packageId from this caller.
  • app-shell ReportView.handleDatasetDrill (ReportView.tsx:138-143, deps :180). Right. The fallback now reads get('dataset', NAME, { callerPackage: servedPackageId(editSchema || reportData) }), or {} when the report has no package. That is the same value the renderer's ReportPackageContext gets: previewReport is editSchema || reportData (:406), and DatasetReportRenderer provides servedPackageId(props.report). So the drill reads the same dataset the report's own queries resolve. editSchema was correctly added to the useCallback deps. A refusal is still caught by the existing catch: no drawer, no bare retry. I checked the dev's premise against service-analytics/src/analytics-service.ts on main. drillDims filters out type: 'date' (:3360), and drillRanges comes only from granularity or window dims. So a report grouped by a date dimension with no granularity does reach this branch, and keeping it (not deleting it) is the right arm of the card's item 3. useMetadataClient returns the real MetadataClient, so the option reaches the transport.
  • Nothing app-shell or console publishes changes shape. @object-ui/app-shell is private: true. It has no export change, only internal behaviour. @object-ui/console is public (publishConfig.access: public). It ships the prebuilt SPA that bundles app-shell, so its users see a behaviour patch and no API change. @object-ui/core is only imported (servedPackageId was already exported, and app-shell already depends on core). @object-ui/plugin-charts changes a test file only. Its files is dist plus docs, so nothing published moves (ObjectChart.tsx is not edited).
  • Item 2 pin (ObjectChart.optionColors.test.tsx:460-496). Right. A 409 whose body also carries a definition naming task is the case that tells the status guard apart: without the guard the probe would read meta/object/task. The dev's ablation B1 reds only this row, which matches the card's ask.
  • Item 1 dropped. Right. There is no .changeset/32077-* on origin/main, and the card itself says to drop the item if a release cut between. No pending changeset is edited.

② Semver level

  • The changeset .changeset/32760-report-drill-caller-package.md names @object-ui/data-objectstack, @object-ui/app-shell (private, versioned under privatePackages.version: true) and @object-ui/console, all at patch. Every package whose shipped output moves is named: data-objectstack dist, and console via its bundled app-shell. plugin-charts is correctly left out because only a test changed. All four are in the root fixed group, so the release bump is shared anyway.
  • patch is correct under AGENTS.md: a non-protocol widening ships patch, and Metadata-protocol: none holds because no authorable key, value, type or stored shape changes. check-changeset-no-major was exit 0 per the dev's gate record.
  • The declaration line in the changeset, in the PR body and in the amended claim 6880606745 reads Clause-②: yes (widening) in all three places, and it matches the diff: one optional member is added and nothing is narrowed. The original claim's no was amended before the edit.
  • Changeset sentences checked against the diff and the server:
    • "omitted, every read is sent exactly as before": true (if (options.callerPackage)).
    • "sends no drill metadata for a type: 'date' dimension with no dateGranularity": true (analytics-service.ts:3360, plus the drillRanges conditions).
    • "A report authored in the environment reads the name bare": true (servedPackageId returns undefined for no _packageId, sys_metadata or __runtime__).
    • "A refusal opens no drill and is not retried": true (one get, caught).
    • The client paragraph (own item, else the one holder among the declared dependencies plus sys, else 409; distinct from packageId; dataset only; refused beside packageId): true against meta-item-read-gate.ts:2388-2406 and :2614-2633.

③ Boundary flags

  • open_questions: empty. Nothing to answer.
  • Deviations:
    • (a) No labels on pr_create. Accepted, because a changeset is owed and present.
    • (b) The file surface and Clause-② differ from the original claim. Answered: amendment 6880606745 covers both, and the diff stays inside the amended surface: plugin-charts test, ReportView plus its test, metadata-client plus its test, and the root changeset.
    • (c) Local suites were narrowed to the touched packages. Accepted on the condition that CI's sharded Test UI answers the rest, which it has not yet done (see gates below).
  • Out-of-scope finding (not filed, no carrier). Escalated to the seat: file a finding follow-up card in domain:ui. On the ReportView fallback, a type: 'date' dimension with no granularity filters its field by equality with the displayed group value, and the fallback ignores the object the server now sends. Both behaviours predate this PR, and this PR only changes which dataset definition the fallback reads, so this does not block. A filed card is the carrier the brief requires.
  • Premise check: the claim says item 3 is "old-server-only or not". The dev measured it and the PR body records the measurement. I confirmed it on main above.
  • Gates on c72c8a04, read from the head's check-runs at review time:
    • Completed success: Check Changeset (run 43621856744), Governed Surface Queue Guard, PR-body guards, Check PR Size, filter, Test Core, Dogfood Regression Gate, Build UI Deps, Plan Test UI shards, Live E2E UI, Type Check · source gates, Auto Label.
    • Still running, and not counted as green: Test UI 1-16/16, Type Check UI, Build & E2E UI, Lint UI, Type Check · workspace / consumer gates / debt ledger, every Lint · job (PM dispatch-gates, docs & code guards, ESLint, scoped slot lookup & corpus, CI release & engine gates, scoped tooling self-tests, scoped query-options erasure, repo & tooling gates), and a second Check Changeset (run 43622068083).
    • Skipped by path filter or opt-in: the rest.
    • No check-run has failed. This verdict is on the contract. Landing still waits for every running gate to finish green.

Findings:

  • nit, ui/packages/app-shell/src/views/ReportView.tsx:136. The inline comment still reads "Fallback (older server with no drill metadata)". This contradicts the rewritten header comment at :105-109, which says the branch is not only an older server's. Reword it to "no objectFilter arrived".
  • should-fix (seat follow-up, not this PR), ReportView.tsx:157-171. The equality filter on a no-granularity date dimension, and the fallback ignoring the answer's object, should be carried on a filed finding card (see ③).

Implemented-by: claude/project-thread-yut48b
Reviewed-by: session_01FEkQ5nWoa1Ze1QzjRTSYXD

VERDICT: PASS

@objectstack-fleet objectstack-fleet Bot removed the needs:contract-review Marker only — PR awaits its at-tier Contract review PASS; no check reads it, the record decides label Nov 14, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

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

席位核对

Verdict: ACCEPT · head c72c8a04 · 2026-11-14T17:56Z

  1. Shape: draft → main, Fixes #32760; 6 files, +350/−5; root changeset patches @object-ui/data-objectstack, @object-ui/app-shell, @object-ui/console; no file outside ui/packages/{app-shell,data-objectstack,plugin-charts}/src/ and the changeset.
  2. Premise, item by item against the order:
    • Item 1 (stale 32077-* changeset line): dropped, as the order allowed: .changeset/32077-* is gone on origin/main (18.4.0 cut).
    • Item 2: ObjectChart.optionColors.test.tsx pins the colour probe's non-2xx guard with a refused envelope that names the object (ablation red in the report).
    • Item 3: the fallback branch is KEPT, measured live: the current server sends no drill metadata for a type: 'date' dimension with no dateGranularity, so the branch is not dormant. It now sends callerPackage = servedPackageId(editSchema || reportData), omitted when the report has no package; MetadataGetOptions.callerPackage → ?callerPackage=.
    • Changeset sentences read against the diff: each holds.
  3. Contract record: PASS, comment 6881609696, on this head c72c8a04 (Clause-② yes (widening), declaration face, TIER_DEFAULT).
  4. Gates on head c72c8a04: all 66 check runs success or skipped (Lint & Repo Gates, TypeScript Type Check, Type Check UI, Lint UI, Test UI 16/16 shards + Test UI, Build & E2E UI, Live E2E UI, Check Changeset, Governed Surface Queue Guard, PR-body guards). check-governed-merges.mjs --pr 33366: NOT governed, 355 lines ≤ 3000.
  5. Accepted deviations:
    • The comment at ReportView.tsx:136 still reads "Fallback (older server with no drill metadata)"; the block comment above it (L105–113) now states the true reach. It is a comment nit and does not hold the landing.
    • The contract review observed that the fallback may build an equality filter on the undated date dimension. That is unmeasured inference with no observed wrong result, so it is not filed (filing gate: reach).
    • K = 25 first-parent commits since the PR base ⇒ base sync before landing; landing waits for the rerun green.
  6. Out of scope: none.
  7. Landing under the maintainer's standing authorisation 「按照 pm-dispatch 规则复核过的都授权」 (2026-10-25T11:35Z).

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

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

Regen-provenance: 6881609696 · c72c8a04ca5633a6c054ffd2701350d95ed7cd8f → 14f931ea730fd10d76e57541efac1513a1b9e849 · base sync only (merge of main at 6538ba48): no PR-side path moves between the two heads, and git diff 6538ba48 14f931ea is exactly the PR's 6 files, +350/−5.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

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

Landing · head 14f931ea (base sync of the ACCEPTed c72c8a04) · 2026-11-14T18:19Z

reading value
check runs on 14f931ea 58, all success or skipped
contract record PASS 6881609696 on c72c8a04, carried by the Regen-provenance: line above (merge of main only)

State: ready + auto-merge.

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review November 14, 2026 18:19
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Nov 14, 2026
@github-actions

Copy link
Copy Markdown
Contributor

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

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

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

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

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

    @objectstack/dogfood:test:  FAIL   isolated  test/object-unknown-datasource-refusal.dogfood.test.ts > dogfood: an object bound to a datasource that does not exist is refused at save (#26724) > control
      ↳ 失败原因: @objectstack/dogfood: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/object-unknown-datasource-refusal.dogfood.test.ts — 24h 窗口内只有本 PR 撞到过,暂不汇总(再有一个不同 PR 撞到就会自动开汇总 issue)。
  • ⚠️ 24h 评论账本没读完(超过 5 页仍未读到窗口尽头),所以上面的「不同 PR 数」是下界,不是全量。

历史信号:

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

分诊清单:

  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_01FEkQ5nWoa1Ze1QzjRTSYXD

Queue red triage · 2026-11-14T18:47Z · queue build 43626642771 failed Dogfood Regression Gate (1/3) on object-unknown-datasource-refusal.dogfood.test.ts › control with Test timed out in 5000ms, a timeout under load. This PR changes only the report drill read (app-shell, data-objectstack) and a chart test, and no server path. The main push run on e0ce1b52 (43627446452) passed Dogfood Regression Gate 1/3. Re-queued once.

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

Copy link
Copy Markdown
Contributor

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

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

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

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

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

    × exits 0 as a process, which is what CI reads 15183ms
    FAIL   unit  scripts/__tests__/check-hand-rolled-comment-mask.test.ts > this tree, today > exits 0 as a process, which is what CI reads
      ↳ 失败原因: Error: Test timed out in 15000ms.
    

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

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

历史信号:

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

分诊清单:

  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_01FEkQ5nWoa1Ze1QzjRTSYXD

Queue red triage 2 · 2026-11-14T19:54Z

Re-queued a second and last time. A third red goes to the server lane / coordinator, not back to the queue.

@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Nov 14, 2026
Merged via the queue into main with commit 9499dcc Nov 14, 2026
59 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/project-thread-yut48b branch November 14, 2026 21:10
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.

ui: follow-ups of the dataset caller arm (#32311) — stale 32077 BREAKING line, the colour-probe guard pin, ReportView drill bare read

1 participant