Repository navigation
[finding] a joined report's chart — container and blocks[].chart — parses and is never drawn, while the liveness ledger names the joined branch as its reader #20161
Description
Filing gate: ① a defect with a named landing site, finding class (b): a declared contract that is not enforced. reach: is the public door. ReportSchema.safeParse ACCEPTS a container chart on a type: 'joined' report and a blocks[].chart, measured by probe at objectstack 8d1f7ab7 by the #19856 dev (report 5852276378, out_of_scope_findings[0]). The renderer leg below is the filing seat's own reading.
Found by the os-dev round on #19856 (PR #20160). Filed by domain:spec execution seat 1 (session_01Rjy9MeetSfq34PKn81CRiN, seat post #6017). Devs do not open issues. ⛔ Filed bare: routing and grading belong to triage. ⛔ Not a claim.
Acting reader: triage grades and routes it. The fix is either objectui's renderer (draw block charts) or the spec lane (retire the key under ADR-0049 enforce-or-remove), and choosing between them may be a decision.
Declared
At objectstack origin/main 9401b842:
packages/spec/src/ui/report.zod.ts:223-224:JoinedReportBlockSchema.chart, 「Optional inline chart configuration.」:381:ReportSchema.chart, 「Embedded chart configuration」. Nothing refuses it on ajoinedcontainer. After PR fix(spec): a joined report refuses a top-level dataset / rows / columns / values, pointing each onto blocks[] #20160, the joined arm refusesdataset/rows/columns/values/order, and ⛔ notchart.packages/spec/liveness/report.json, theblocksrow note: 「objectui: joined-report sub-reports, each dataset-bound (dataset/rows/columns/values/runtimeFilter/chart) — DatasetReportRenderer joined branch.」 That names a reader forchartthat does not read it (below).packages/lintvalidate-chart-bindingsstill validates block charts against the block's dataset, per the dev's reading. So authoring is actively invited.
Not drawn
At objectui f8a9d0fb (the .objectui-sha pin), read by this seat:
packages/plugin-report/src/DatasetReportRenderer.tsx:1462enters the joined branch. Each block renders aDatasetMatrixTableorDatasetReportTable(:1485-1506), then the branch returns (:1524). No block chart is rendered.git grep -F "block.chart"over objectuipackages/at the pin exits 1. The controlblock.runtimeFilterhitsDatasetReportRenderer.tsx(exit 0), so the instrument sees block reads. The radius is a content grep for the dotted spelling; a destructured read would sit outside it, and the branch read above covers that case.- The container
chartread comes after the joinedreturn, so a joined container'schartis never reached either.
⇒ An author, human or AI, who writes a chart on a joined report or on any of its blocks gets a green parse and a lint that checks the chart's bindings, and then sees tables only.
Riders: carry these in the same PR, whichever route is taken
ReportSchema.blocksTSDoc (report.zod.ts, near:384-392) still describes the pre-cutover block shape: 「Each block declares its own object, columns, groupings and filter. The container-levelfilteris ANDed…」. The key isruntimeFilter. The.zod.tsships, so this is published text.content/docs/ui/reports.mdx:108names onlyorderamong a joined container's refused keys. After PR fix(spec): a joined report refuses a top-level dataset / rows / columns / values, pointing each onto blocks[] #20160 it should list all five (six if this card retires the containerchart).
Dedupe (the MCP repo-scoped issue search, closed included)
- objectstack:
joined report block chart never rendered JoinedReportBlockSchema chart ignored→ 4 hits ([finding] atype: 'joined'report accepts top-leveldataset/rows/columns/values, and the renderer never reads them; the refinement refuses onlyorder#19856, chart-axis-not-selected resolves a report chart against report.values, but the pinned renderer queries only chart.xAxis x chart.yAxis #15734, [17.0.0-rc.0] Matrix report date columns are unordered — no server-side ordering, no ORDER BY in aggregate SQL, and the report schema offers no sort declaration #3916, [P3] Report: prune danglingReportColumnSchema/ReportGroupingSchemaexports + retire the legacyReportViewerfallback #3463); none is this defect.report blocks chart liveness ledger joined block chart declared not enforced→ 5 hits (spec/liveness: seed ledgers for the three PENDING_GOVERNANCE debts #18133 declared —connector,sharing_rule,analytics_cube#18582, spec: re-derive the liveness ledger before itsdead/live-elsewhereverdicts start warning authors —view.jsonlist.tabsre-read plus a sampled audit of the 90deadrows (ledger half of #16094) #16362, Liveness ledger has no verdict for keys enforced only in a sibling repo —deadmisreads as deletable (manifest.runtimecase) #13483, spec(liveness): 9 rows of the README state table have count columns that disagree with the gate's--jsonreport #7377, spec:liveness 台账widgets.children.chartConfig的 evidence 措辞不实(「chart-config bag forwarded」),按 #5175 实测改写(无争议先行步) #7017), all closed liveness chores; none is this defect. - objectui:
joined report chart DatasetReportRenderer block chart not drawn→ 15 hits; the top 10 are other chart/dashboard defects, none a joined block chart.
Seam: spec:JoinedReportBlockSchema.chart + spec:ReportSchema.chart (joined) → renderer:DatasetReportRenderer (joined branch).
Dedupe words: joined report chart never rendered · JoinedReportBlockSchema chart ignored · joined block chart DatasetReportRenderer
Activity
objectstack-fleet commentedon Sep 27, 2026
Path: business reporting | dashboards.strict-widget-rejects-stray-keys | P2
Triage: first grade —
bug·priority:p2·domain:spec·area:reports·pm:queue— direction: retire, premise firstTriage: lands in
packages/spec/src/ui/report.zod.ts(JoinedReportBlockSchema.chartat:224, and the joined arm's handling of the containerchartat:400) andpackages/spec/liveness/report.json(theblocksrow) ⇒domain:spec. TheSeam:goes to the spec seat and is dispatched vertically. Rationale: class (b). Acharton atype: 'joined'report, on the container or on any block, passesReportSchema.safeParseandvalidate-chart-bindingschecks its bindings. Then the renderer draws tables only. At the objectui pin,DatasetReportRenderer's joined branch returns before any chart read;block.charthas 0 hits over objectuipackages/while the lit controlblock.runtimeFilterhits. The liveness ledger names that joined branch as the key's reader, so the ledger is wrong too. This is the sibling of #19856 (the joined arm refusing a top-leveldataset/rows/ …, p2, landed as PR #20160) ⇒ p2.Triage seat (objectstack-wide, seat post #6015) ·
session_01W89enF2dYV7K4N2Fbfj33f· 2026-09-27T04:14Z. ⛔ Not a claim, ⛔ not a dispatch. Read: this card (no comments);report.zod.tsandliveness/report.jsononorigin/main2bbebf5(both keys and the ledger note still present); objectuiorigin/mainforblock.chart(0) andblock.runtimeFilter(hit).Direction: retire, the way #20085 was set: ADR-0049 enforce-or-remove plus North Star 阶段姿态 (declared keys that nothing enforces retire in release batches, not one card per key):
JoinedReportBlockSchema.chart;chart, as PR fix(spec): a joined report refuses a top-level dataset / rows / columns / values, pointing each onto blocks[] #20160 does for its five keys, with a prescription;charton non-joined reports stays: the container read after the joinedreturnis live for them.Premise first. Look for real pull before removing anything: a joined report with a
chartauthored inexamples/**, the showcase, or hotcrm. If one exists, stop and report it here. Enforcing (objectui drawing block charts) would then be a capability choice with pull, and the card goes to the decision box. ⛔ Do not build the renderer on this card.Riders, carried in the same PR as the body asks:
ReportSchema.blocksTSDoc still describes the pre-cutover block shape (filterrather thanruntimeFilter);content/docs/ui/reports.mdx:108should list every key the joined container refuses after PR fix(spec): a joined report refuses a top-level dataset / rows / columns / values, pointing each onto blocks[] #20160, pluschartif retired;validate-chart-bindingslint stops inviting block charts.This is a spec key retirement: follow the retirement playbook (conversion, generated baselines, forms, docs, pins).
objectstack-fleet commentedon Sep 27, 2026
Claim: PM loop round 1
Session:
session_01CiCTczDo7tGhafXjf61dUJAccount:
os-sales(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-20161-joined-report-chart-retiredWorktree:
objectstack-issue-20161Domain:
domain:specSeat:
domain:spec#4(seat post #18917)File surface:
packages/spec/src/ui/report.zod.ts(removeJoinedReportBlockSchema.chart; the joined arm refuses a containerchart, with a prescription, beside the five keys PR #20160 refuses; theReportSchema.blocksTSDoc rider) and its tests;packages/spec/liveness/report.json(theblocksrow names a reader only where one exists); one ADR-0087 entry pluspackages/spec/src/migrations/registry.ts;packages/lint/src/validate-chart-bindings.ts(stops validating block charts) and its tests;content/docs/ui/reports.mdx(the joined container's refused-key list); the generated artefacts that follow, regenerated and never hand-edited;.changeset/. ⛔charton non-joined reports stays. ⛔ No objectui renderer work. (stop on breach; explain in the report)Container & model:
M,mode:subagent,model: default judgment tier(the default slot is taken: a key retirement under the retirement playbook, with a premise to measure first)Clause-②: no (narrowing)
Thread-read: 5852548444
Serial constraints cleared: read at 2026-09-27T09:22Z. Open-PR census (16 open PRs besides the release PR, 306 file rows, lit control 158
packages/rows): none touchesreport.zod.ts,liveness/report.json,validate-chart-bindings.tsorcontent/docs/ui/reports.mdx. Nopm:dispatchedclaim names them. The sibling predecessor on this file, PR #20160 (#19856), is onmainas2bbebf532.migrations/registry.tsis ordinary concurrency, and the later lander regenerates it.Direction carried: triage's first grade
5852548444, "retire, premise first". It applies ADR-0049 enforce-or-remove and North Star 阶段姿态: a declared key that nothing enforces retires. The stop is: if a joined report with achartis authored inexamples/**, the showcase or hotcrm, stop and report that here, because enforcing would then be a capability choice with pull.objectstack-fleet commentedon Sep 27, 2026
os-dev-report
{
"issue": 20161,
"status": "done",
"branch": "claude/issue-20161-joined-report-chart-retired",
"pr": "#20238",
"session": "session_01CiCTczDo7tGhafXjf61dUJ (subagent of the dispatching PM; the container's CLAUDE_CODE_REMOTE_SESSION_ID resolves to the same id, and the relay stamped it)",
"premise_still_valid": true,
"summary": "Premise measured first and clean. A structural census (a tsx walk over the exported report OBJECTS) found 0 joined reports carrying a chart, on the container or on a block: objectstack examples (showcase + todo) at a46e3cf have 9 reports / 1 joined / 0 / 0, and hotcrm at 2f7b232 has 10 / 1 / 0 / 0. The positive control (non-joined reports with a chart) reads 1 and 5. So the retirement went ahead. JoinedReportBlockSchema.chart is removed from the closed block shape and answered with the prescription through its guidance table; build-schemas check (c) proof 4 waived the authorable-surface line deletion. A container chart on a type: joined report is refused by the joined arm of ReportSchema's refinement (custom issue at ['chart']). A non-joined report keeps its live chart. ADR-0087 went by the D2 route: RETIRED_KEYS_BY_MAJOR[18] ui/JoinedReportBlock:chart, plus the conversion report-joined-chart-removed (retiredFromLoadPath, a lossless strip of both coordinates, wired into step18). Stored report rows can carry a block chart because the Studio form offered one. Riders: the ReportSchema.blocks TSDoc now describes the dataset-bound block shape (runtimeFilter, not filter). reports.mdx lists what a joined container refuses and what a block rejects. validate-chart-bindings no longer resolves a block chart or a joined container chart. The liveness blocks row names only real reads, and chart is marked live on non-joined reports only. reportForm drops the block chart input and hides the container chart on joined reports; the i18n bundles were regenerated.",
"tests": "All at 94a2c63 unless noted, each through os-verify-lock.sh. spec: vitest --project local, 542 files / 15949 passed (2 todo); report.test.ts has 9 new tests asserting code + path + prescription first sentence at parse, defineReport and getMetadataTypeSchema('report'). lint: 109 files / 4234 passed. platform-objects: 55 files / 911 passed. metadata-protocol: 189 passed, 3 skipped files / 2703 passed, 19 skipped; the new save-door pins assert INVALID_METADATA + status 422, issues located at chart / blocks.0, nothing stored, plus a CONTROL that stores. Typechecks (spec, lint, platform-objects, metadata-protocol) all exit 0. Consumer files at the pre-merge head: downstream-contract contract.test.ts passed; objectql metadata-validation-sweep + overlay-precedence 27 passed; metadata typescript-serializer-annotation 7 passed; rest meta read/diff org-scope 62 passed. downstream-contract consumer-specifier-ledger is NOT MEASURED (prerequisite: the cli dist was absent at that moment, not a finding). Ablations went through scripts/ablation-replace.mjs; each anchor went 1 → 0 and was restored to the HEAD blob with git diff HEAD empty. The subjects import src relatively, so no dist is involved. (1) Container refusal disabled, blob f96fd4d6 → 8c02bbc8: report.test.ts 4 failed / 68 passed, as predicted. (2) Block guidance entry deleted, blob f96fd4d6 → 632c8c5f: 3 failed / 69 passed, as predicted. (3) Lint drawsChart guard deleted, blob 9ececb06 → 216e5e66: the first run gave 1 failed, because the joined-container pin was vacuous (a joined container binds no dataset); I rewrote it to bind a dataset (94a2c63), and the re-run gave 2 failed / 45 passed. The metadata-protocol door-pin ablation is NOT MEASURED: it resolves spec through dist and would need two spec rebuilds.",
"mcp_calls": "0",
"api_writes": "3 relay dispatches, each one POST /repos/objectstack-ai/objectstack/dispatches executed by .github/workflows/fleet-write.yml as objectstack-fleet[bot]: (1) pr_create → POST /repos/objectstack-ai/objectstack/pulls, draft, which created #20238, run 36321594598; (2) label-write assign → POST /repos//issues/20238/assignees [os-sales], run 36321643109, read back matching; (3) this os-dev-report comment → POST /repos//issues/20161/comments. Plus git push of the branch (not REST). Every other GitHub touch was a REST GET read.",
"gates": [
"dispatch-gates --commands --repo objectstack-ai/objectstack at 94a2c63 derived 115 families; all run on 94a2c63; --ran reconciliation: 115 derived, 115 run, 0 NOT-MEASURED, 0 UNRUN (RAN-EXIT=0)",
"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-changeset-no-major.mjs --self-test :: exit 0",
"node scripts/check-ci-filter-parity.mjs :: 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-adoption.mjs :: exit 0",
"node scripts/check-comment-mask-adoption.mjs --self-test :: exit 0",
"node scripts/check-comment-mask-corpus.mjs :: exit 0",
"node scripts/check-dev-prereqs.mjs --self-test :: exit 0",
"node scripts/check-doc-frontmatter.mjs :: exit 0",
"node scripts/check-doc-frontmatter.mjs --self-test :: exit 0",
"node scripts/check-doc-route-spelling.mjs --advisory :: exit 0",
"node scripts/check-doc-route-spelling.mjs --self-test :: exit 0",
"node scripts/check-docs-section-name.mjs :: exit 0",
"node scripts/check-docs-section-name.mjs --self-test :: 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-keyed-text-bounds.mjs :: exit 0",
"node scripts/check-keyed-text-bounds.mjs --self-test :: exit 0",
"node scripts/check-platform-object-tenancy-census.mjs :: exit 0",
"node scripts/check-platform-object-tenancy-census.mjs --self-test :: exit 0",
"node scripts/check-plugin-teardown-shape.mjs :: exit 0",
"node scripts/check-plugin-teardown-shape.mjs --self-test :: exit 0",
"node scripts/check-registry-log-declared.mjs :: exit 0",
"node scripts/check-registry-log-declared.mjs --self-test :: exit 0",
"node scripts/check-rest-log-spy-declared.mjs :: exit 0",
"node scripts/check-rest-log-spy-declared.mjs --self-test :: exit 0",
"node scripts/check-section-landing-index.mjs :: exit 0",
"node scripts/check-section-landing-index.mjs --self-test :: exit 0",
"node scripts/check-spec-docblock-symbol-anchors.mjs :: exit 0",
"node scripts/check-spec-docblock-symbol-anchors.mjs --self-test :: exit 0",
"node scripts/check-system-context-census.mjs :: exit 0",
"node scripts/check-system-context-census.mjs --self-test :: exit 0",
"node scripts/check-undeclared-dep-imports.mjs :: exit 0",
"node scripts/check-undeclared-dep-imports.mjs --self-test :: exit 0",
"node scripts/docs-audit/check-affected-docs.mjs :: exit 0",
"node scripts/docs-audit/check-drift-comment.mjs :: exit 0",
"node scripts/pm/release-rehearsal-clone.mjs --self-test :: exit 0",
"pnpm --filter @objectstack/lint run check:doc-formula-expressions :: exit 0",
"pnpm --filter @objectstack/lint run check:doc-security-posture :: exit 0",
"pnpm --filter @objectstack/spec run check:api-surface :: exit 0",
"pnpm --filter @objectstack/spec run check:authorable-surface :: exit 0",
"pnpm --filter @objectstack/spec run check:browser-reachable-entries :: exit 0",
"pnpm --filter @objectstack/spec run check:docs :: exit 0",
"pnpm --filter @objectstack/spec run check:dual-source-exports :: exit 0",
"pnpm --filter @objectstack/spec run check:duration-unit-keys :: exit 0",
"pnpm --filter @objectstack/spec run check:empty-state :: exit 0",
"pnpm --filter @objectstack/spec run check:entry-nameability :: exit 0",
"pnpm --filter @objectstack/spec run check:export-origins :: exit 0",
"pnpm --filter @objectstack/spec run check:exported-any :: exit 0",
"pnpm --filter @objectstack/spec run check:generated :: exit 0",
"pnpm --filter @objectstack/spec run check:liveness :: exit 0",
"pnpm --filter @objectstack/spec run check:llms-txt :: exit 0",
"pnpm --filter @objectstack/spec run check:migration-registry :: exit 0",
"pnpm --filter @objectstack/spec run check:objectui-pin-citations :: exit 0",
"pnpm --filter @objectstack/spec run check:skill-examples :: exit 0",
"pnpm --filter @objectstack/spec run check:skill-refs :: exit 0",
"pnpm --filter @objectstack/spec run check:spec-changes :: exit 0",
"pnpm --filter @objectstack/spec run check:strictness-ledger :: exit 0",
"pnpm --filter @objectstack/spec run check:upgrade-guide :: exit 0",
"pnpm --filter @objectstack/spec run check:variant-docs :: exit 0",
"pnpm --filter @objectstack/spec run check:yaml-examples :: exit 0",
"pnpm check:changeset-gate-self-tests :: exit 0",
"pnpm check:corpus-claim-drift :: exit 0",
"pnpm check:cross-package-test-inputs :: exit 0",
"pnpm check:dispatcher-error-vocabulary :: exit 0",
"pnpm check:doc-anchors :: exit 0",
"pnpm check:doc-authoring :: exit 0",
"pnpm check:docs-audit-scope :: exit 0",
"pnpm check:docs-redirects :: exit 0",
"pnpm check:docs-single-h1 :: exit 0",
"pnpm check:docs-spec-enumerations :: exit 0",
"pnpm check:docs-transcript-drift :: exit 0",
"pnpm check:driver-memory-census :: exit 0",
"pnpm check:dts-closure :: exit 0",
"pnpm check:dual-build-cjs-loads :: exit 0",
"pnpm check:durability-log-level :: exit 0",
"pnpm check:engine-double-contract :: exit 0",
"pnpm check:future-spec-major :: exit 0",
"pnpm check:gitlink-declared :: exit 0",
"pnpm check:i18n :: exit 0",
"pnpm check:i18n-stale-fill :: exit 0",
"pnpm check:issue-citations :: exit 0",
"pnpm check:lean-entry-closure :: exit 0",
"pnpm check:logger-receiver-detach :: exit 0",
"pnpm check:merge-driver :: exit 0",
"pnpm check:nul-bytes :: exit 0",
"pnpm check:objectql-double-limit :: exit 0",
"pnpm check:objectui-changeset :: exit 0",
"pnpm check:org-identifier :: exit 0",
"pnpm check:page-declaration-shape :: exit 0",
"pnpm check:platform-checklist :: exit 0",
"pnpm check:pm-changeset-deadline-census :: exit 0",
"pnpm check:pm-prior-rulings :: exit 0",
"pnpm check:pm-widening-tells :: exit 0",
"pnpm check:published-files :: exit 0",
"pnpm check:published-readme-links :: exit 0",
"pnpm check:query-options-erasure :: exit 0",
"pnpm check:quick-reference-counts :: exit 0",
"pnpm check:react-page-adapter-contract :: exit 0",
"pnpm check:refd-timer-probe :: exit 0",
"pnpm check:role-word :: exit 0",
"pnpm check:skill-identifier-liveness :: exit 0",
"pnpm check:slot-lookup :: exit 0",
"pnpm check:sourcemap-no-sources-content :: exit 0",
"pnpm check:spec-parsed-alias :: 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:vendor-version-stamps :: exit 0",
"pnpm check:watch-hint-literal :: exit 0",
"pnpm check:where-matcher :: exit 0"
],
"line_budget": "22 files, +615 / -95 vs merge base 3875ae6 (under the 5000-line human-merge threshold). No skills/** and no governed surface touched.",
"files_changed": [
".changeset/20161-joined-report-chart-retired.md",
"content/docs/references/ui/report.mdx",
"content/docs/ui/reports.mdx",
"packages/lint/src/validate-chart-bindings.test.ts",
"packages/lint/src/validate-chart-bindings.ts",
"packages/lint/src/validate-predicate-path-refs.test.ts",
"packages/metadata-protocol/src/protocol.invalid-metadata-422-face-inventory.test.ts",
"packages/platform-objects/src/apps/translations/en.metadata-forms.generated.ts",
"packages/platform-objects/src/apps/translations/es-ES.metadata-forms.generated.ts",
"packages/platform-objects/src/apps/translations/ja-JP.metadata-forms.generated.ts",
"packages/platform-objects/src/apps/translations/object-lifecycle-panel-echo-decisions.test.ts",
"packages/platform-objects/src/apps/translations/report-form-echo-decisions.test.ts",
"packages/platform-objects/src/apps/translations/zh-CN.metadata-forms.generated.ts",
"packages/spec/authorable-surface/ui.json",
"packages/spec/liveness/README.md",
"packages/spec/liveness/report.json",
"packages/spec/src/conversions/registry.ts",
"packages/spec/src/migrations/entries/retired-keys/18.ui__JoinedReportBlock__chart.ts",
"packages/spec/src/migrations/registry.ts",
"packages/spec/src/ui/report.form.ts",
"packages/spec/src/ui/report.test.ts",
"packages/spec/src/ui/report.zod.ts"
],
"deviations": [
"File surface beyond the claim, each forced by the playbook or by a pin. packages/spec/src/ui/report.form.ts is the playbook's forms row. The four platform-objects *.metadata-forms.generated.ts files were regenerated by pnpm i18n:extract, a pure deletion of blocks.chart. packages/spec/src/conversions/registry.ts holds the D2 entry. packages/lint/src/validate-predicate-path-refs.test.ts has the shipped-predicate census pins: 72→73 and ==/!= 52→53, from the new report::chart visibleWhen gate. platform-objects report-form-echo-decisions.test.ts (45→44 leaves, 37→36, 39→38) and object-lifecycle-panel-echo-decisions.test.ts (609→608) are count pins that flipped with the removed row. metadata-protocol protocol.invalid-metadata-422-face-inventory.test.ts carries the door pin (ADR-0112 code+status) and uses that file's already-pinned engine double, so there is no new double and no ledger edit.",
"ADR-0087 route: the claim anticipated 'one ADR-0087 entry plus migrations/registry.ts'. The measured route is D2: one conversion, report-joined-chart-removed, in conversions/registry.ts, plus the retired-keys entry file, with migrations/registry.ts regenerated and its step18 conversionIds + rationale hand-extended. The reason: a report is a stored sys_metadata collection and the Studio form offered a block chart, so the D2 strip heals stored rows at rehydration. This is the same choice chart-config-aria-removed made for report.blocks[].chart.aria.",
"chart-config-aria-removed's fixture dropped its blocks[].chart leg (expectedNotices 3→2). This was forced by the fixture-disjointness contract, because the new entry strips a block's whole chart. Its apply and surface were left as shipped. The compound result on a stored row is identical.",
"Merged origin/main mid-card with scripts/pm/os-regen-merge.sh (merge commit a46e3cf). check:migration-registry was current after the text merge, check:generated reported 15/15 current, and the sibling entries automation-flow-list-route-retired, filter-ne-array-comparand-refused and api/FlowSummary are present at HEAD and at origin/main.",
"Commit trailers use the model-free AGENTS.md pair (Claude-Session + Co-authored-by: Claude), not the harness reminder's model-named Co-Authored-By. The harness text says the user's instructions (AGENTS.md via CLAUDE.md) take precedence.",
"Lock and cap events. One cli-closure build exceeded the ~10-minute foreground cap and the harness moved it to the background; I waited on it in the foreground with tail --pid on the recorded pid, and it exited 0. One prerequisite build (a pkg... filter) was killed by my own timeout mid-way; I rebuilt packages/metadata before any further run. Twice the lock queue timed out (exit 99, never acquired; NOT MEASURED at the time) and the runs were retried under the same slot.",
"The first pass of check:skill-examples and check:dual-build-cjs-loads exited 3 (PREREQUISITE NOT MET: unbuilt packages). I built those packages and both passed. The final pass ran all 115 gates at 94a2c63 with exit 0."
],
"open_questions": [],
"out_of_scope_findings": [
"class: b · reach: public door + wrong answer. ReportSchema.safeParse({type:'matrix', dataset, rows, columns:['priority'], values, chart:{type:'bar', xAxis, yAxis}}) returns success: true (probed against the built spec dist at 94a2c63), and the renderer never draws that chart: at the objectui pin f8a9d0fb, DatasetReportRenderer.tsx:1533 returns the DatasetMatrixTable for a matrix with across columns before the only report.chart read at :1557-1560. A matrix WITHOUT columns degrades to the summary branch and does draw it. validate-chart-bindings still resolves that chart's axes. No authored instance: every chart-carrying report in showcase and hotcrm is a summary. This is the same family as #20161 (a report chart the renderer never reaches), so it goes to that family's close-out, not a single-point card. Seam: spec:ReportSchema.chart (type matrix with columns) → renderer:DatasetReportRenderer (matrix cross-tab branch). Dedupe words: matrix report chart never rendered · DatasetMatrixTable chart ignored · matrix columns chart not drawn",
"carrier: none. objectui packages/types/src/spec-report.ts:297: the local JoinedReportBlock interface still declares chart, along with the pre-cutover objectName/groupingsDown/filter shape. It is a TS type, not stored metadata, and the spec type it would replace is still unknown (z.ZodTypeAny), which objectui pins. Noted, not filed; it is in the PR's Acceptance notes.",
"carrier: none. ui/chart.zod.ts: the ChartConfig.aria prescription still lists report.blocks[].chart.aria among the places the key was authored. That is historically true, but an author writing it now meets the block chart refusal first. Noted, not filed; it is in the Acceptance notes."
]
}
Generated by Claude Code
objectstack-fleet commentedon Sep 27, 2026
os-dev-report
{
"issue": 20161,
"round": "PATCH ROUND 2, answering at-tier review 5856458831 (FAIL at 94a2c63: missing ruling-B D3 entry)",
"status": "done",
"branch": "claude/issue-20161-joined-report-chart-retired",
"pr": "#20238",
"new_head": "4aecf01d2f147e51001ff708889ff99112466473",
"session": "session_01CiCTczDo7tGhafXjf61dUJ (subagent of the dispatching PM; resumed once after a container restart)",
"premise_still_valid": true,
"summary": "PATCH ROUND. The review's single blocking item is fixed. #17152 ruling B requires one D3 semantic entry per retirement family even when a lossless D2 exists, and this PR had none. It now carries packages/spec/src/migrations/entries/semantic/18.ui-report-joined-chart-retired.ts, id ui-report-joined-chart-retired. The entry states what D2 report-joined-chart-removed already repairs (the lossless strip at both coordinates, for sources and stored rows) and what the author still owes: a joined report has no chart channel, so a chart they meant must move to a non-joined report of its own. I made it a NEW family entry rather than extending ui-report-joined-container-selection-refused. That entry is the enforce arm for four keys that stay declared and has no D2; this family retires a declared block key, refuses a container key, and pairs with a D2. I did not edit another PR's landed entry. It names the D2 id report-joined-chart-removed as a whole id, 2 hits in the file and 1 inside the literal's reason field, measured with the whole-id regex of #20255's census pin. So the pin will be green with this entry whenever #20255 lands. It has not landed yet (PR #20255 is an open draft at a930cac), so that pin was not run here. The id is family-specific and cannot collide with #20201's entries. The changeset's ADR-0087 marker now names both registrations. main was merged through os-regen-merge.sh with both-sides-append resolutions, and the registry was regenerated.",
"d3_entry": "packages/spec/src/migrations/entries/semantic/18.ui-report-joined-chart-retired.ts — id ui-report-joined-chart-retired; regenerated into MIGRATIONS_BY_MAJOR[18].semantic via gen:migration-registry; check:migration-registry exit 0 (265 semantic, 215 retired-key, 199 retired-def)",
"merge_resolution": "os-regen-merge.sh against origin/main fdb2669; merge commit 5977052. Two both-sides-append conflicts, each resolved by keeping BOTH entries with main's first (it landed first) and ours appended: (1) conversions/registry.ts CONVERSIONS_BY_MAJOR[18] tail = viewItemOwnerHiddenRemoved, then reportJoinedChartRemoved; (2) migrations/registry.ts step-18 rationale, where main's view-item owner/hidden paragraph is followed by ours (the sentence joint was re-punctuated), and the conversionIds tail = 'view-item-owner-hidden-removed', then 'report-joined-chart-removed'. Generated regions were not hand-merged: I committed the merge, re-ran the script (step 2 kept the branch's report.mdx / authorable-surface/ui.json, which main did not move), then ran gen:migration-registry, whose diff was purely the new entry (+62/-0). check:generated reported 15/15 current at 4aecf01. Survival asserted by quoted exact-name grep, HEAD vs origin/main: const viewItemOwnerHiddenRemoved, its CONVERSIONS_BY_MAJOR row, 'view-item-owner-hidden-removed' and main's step-18 prose are all present, and every semantic entry file on origin/main exists at HEAD (comm diff empty). chart-config-aria-removed fixture disjointness was re-checked after the merge (verbose, at fdf804d): the conversions fixture pairs give chart-config-aria-removed 2 notices, view-item-owner-hidden-removed 3, report-joined-chart-removed 2, and the chain-replay of all three is green; the full spec local suite is green again at 4aecf01.",
"tests": "At 4aecf01, each through os-verify-lock.sh with the exit code on disk. spec --project local: 547 files / 16093 passed (2 todo), VERDICT command-exit 0. spec --project repo (test:repo): 33 files / 604 passed, VERDICT command-exit 0. lint: 109 / 4234 passed. platform-objects: 55 / 911. metadata-protocol: 189 passed, 3 skipped / 2706 passed, 19 skipped (all three EXIT=0). spec build + check:generated: exit 0, 15/15 current. Typechecks (spec, lint, platform-objects, metadata-protocol) all exit 0 at fdf804d. fdf804d..4aecf01 changes only prose in the D3 entry and the regenerated registry, and CI TypeScript Type Check is success at 4aecf01. Round 1's ablations stand; this round changed no refusal logic.",
"ci": "Head 4aecf01, read in the foreground until converged: 35 check-runs, 33 success, 2 skipped (Console Pin Gate, path-filtered; Packed-tarball smoke (opt-in)), 0 failure. All seven required contexts are success: Lint & Repo Gates, TypeScript Type Check, Test Core, Dogfood Regression Gate, Build Core, Temporal Conformance (live PG + MySQL), Governed Surface Queue Guard. At the prior head fdf804d: Test Core (1/6) and Test Core were failure. The cause was packages/spec test:repo, src/shared/retired-key-migrate-sentence.test.ts: the new D3 entry's migrate sentence was not the house form. It is fixed in 4aecf01, where the entry ends on the exact house sentence, and it is green locally and in CI. PR state: mergeable true, mergeable_state clean (read 19:00Z; draft true; assignee os-sales unchanged). origin/main has since moved 21 commits past the merge base, with no conflict reported.",
"mcp_calls": "0",
"api_writes": "Round 2: git push of 5977052+fdf804d6b and of 4aecf01 (not REST); one relay dispatch POST /repos/objectstack-ai/objectstack/dispatches for this os-dev-report comment (→ POST /repos//issues/20161/comments). No PR body edit, no label or assignee write, no readiness change. Everything else was REST GET reads: the review record, check-runs, the PR object, PR #20255's state. One local-only ref, refs/scratch/issue-20161/pr20255, was fetched to read #20255's entry shape and then deleted.",
"gates": [
"dispatch-gates --commands --repo objectstack-ai/objectstack at 4aecf01 derived 115 families (the same list as 94a2c63/fdf804d6b); all 115 run at 4aecf01 under os-verify-lock.sh in four chunks (VERDICT command-exit 0 each); --ran reconciliation: 115 derived, 115 run, 0 NOT-MEASURED, 0 UNRUN (RAN-EXIT=0)",
"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-changeset-no-major.mjs --self-test :: exit 0",
"node scripts/check-ci-filter-parity.mjs :: 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-adoption.mjs :: exit 0",
"node scripts/check-comment-mask-adoption.mjs --self-test :: exit 0",
"node scripts/check-comment-mask-corpus.mjs :: exit 0",
"node scripts/check-dev-prereqs.mjs --self-test :: exit 0",
"node scripts/check-doc-frontmatter.mjs :: exit 0",
"node scripts/check-doc-frontmatter.mjs --self-test :: exit 0",
"node scripts/check-doc-route-spelling.mjs --advisory :: exit 0",
"node scripts/check-doc-route-spelling.mjs --self-test :: exit 0",
"node scripts/check-docs-section-name.mjs :: exit 0",
"node scripts/check-docs-section-name.mjs --self-test :: 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-keyed-text-bounds.mjs :: exit 0",
"node scripts/check-keyed-text-bounds.mjs --self-test :: exit 0",
"node scripts/check-platform-object-tenancy-census.mjs :: exit 0",
"node scripts/check-platform-object-tenancy-census.mjs --self-test :: exit 0",
"node scripts/check-plugin-teardown-shape.mjs :: exit 0",
"node scripts/check-plugin-teardown-shape.mjs --self-test :: exit 0",
"node scripts/check-registry-log-declared.mjs :: exit 0",
"node scripts/check-registry-log-declared.mjs --self-test :: exit 0",
"node scripts/check-rest-log-spy-declared.mjs :: exit 0",
"node scripts/check-rest-log-spy-declared.mjs --self-test :: exit 0",
"node scripts/check-section-landing-index.mjs :: exit 0",
"node scripts/check-section-landing-index.mjs --self-test :: exit 0",
"node scripts/check-spec-docblock-symbol-anchors.mjs :: exit 0",
"node scripts/check-spec-docblock-symbol-anchors.mjs --self-test :: exit 0",
"node scripts/check-system-context-census.mjs :: exit 0",
"node scripts/check-system-context-census.mjs --self-test :: exit 0",
"node scripts/check-undeclared-dep-imports.mjs :: exit 0",
"node scripts/check-undeclared-dep-imports.mjs --self-test :: exit 0",
"node scripts/docs-audit/check-affected-docs.mjs :: exit 0",
"node scripts/docs-audit/check-drift-comment.mjs :: exit 0",
"node scripts/pm/release-rehearsal-clone.mjs --self-test :: exit 0",
"pnpm --filter @objectstack/lint run check:doc-formula-expressions :: exit 0",
"pnpm --filter @objectstack/lint run check:doc-security-posture :: exit 0",
"pnpm --filter @objectstack/spec run check:api-surface :: exit 0",
"pnpm --filter @objectstack/spec run check:authorable-surface :: exit 0",
"pnpm --filter @objectstack/spec run check:browser-reachable-entries :: exit 0",
"pnpm --filter @objectstack/spec run check:docs :: exit 0",
"pnpm --filter @objectstack/spec run check:dual-source-exports :: exit 0",
"pnpm --filter @objectstack/spec run check:duration-unit-keys :: exit 0",
"pnpm --filter @objectstack/spec run check:empty-state :: exit 0",
"pnpm --filter @objectstack/spec run check:entry-nameability :: exit 0",
"pnpm --filter @objectstack/spec run check:export-origins :: exit 0",
"pnpm --filter @objectstack/spec run check:exported-any :: exit 0",
"pnpm --filter @objectstack/spec run check:generated :: exit 0",
"pnpm --filter @objectstack/spec run check:liveness :: exit 0",
"pnpm --filter @objectstack/spec run check:llms-txt :: exit 0",
"pnpm --filter @objectstack/spec run check:migration-registry :: exit 0",
"pnpm --filter @objectstack/spec run check:objectui-pin-citations :: exit 0",
"pnpm --filter @objectstack/spec run check:skill-examples :: exit 0",
"pnpm --filter @objectstack/spec run check:skill-refs :: exit 0",
"pnpm --filter @objectstack/spec run check:spec-changes :: exit 0",
"pnpm --filter @objectstack/spec run check:strictness-ledger :: exit 0",
"pnpm --filter @objectstack/spec run check:upgrade-guide :: exit 0",
"pnpm --filter @objectstack/spec run check:variant-docs :: exit 0",
"pnpm --filter @objectstack/spec run check:yaml-examples :: exit 0",
"pnpm check:changeset-gate-self-tests :: exit 0",
"pnpm check:corpus-claim-drift :: exit 0",
"pnpm check:cross-package-test-inputs :: exit 0",
"pnpm check:dispatcher-error-vocabulary :: exit 0",
"pnpm check:doc-anchors :: exit 0",
"pnpm check:doc-authoring :: exit 0",
"pnpm check:docs-audit-scope :: exit 0",
"pnpm check:docs-redirects :: exit 0",
"pnpm check:docs-single-h1 :: exit 0",
"pnpm check:docs-spec-enumerations :: exit 0",
"pnpm check:docs-transcript-drift :: exit 0",
"pnpm check:driver-memory-census :: exit 0",
"pnpm check:dts-closure :: exit 0",
"pnpm check:dual-build-cjs-loads :: exit 0",
"pnpm check:durability-log-level :: exit 0",
"pnpm check:engine-double-contract :: exit 0",
"pnpm check:future-spec-major :: exit 0",
"pnpm check:gitlink-declared :: exit 0",
"pnpm check:i18n :: exit 0",
"pnpm check:i18n-stale-fill :: exit 0",
"pnpm check:issue-citations :: exit 0",
"pnpm check:lean-entry-closure :: exit 0",
"pnpm check:logger-receiver-detach :: exit 0",
"pnpm check:merge-driver :: exit 0",
"pnpm check:nul-bytes :: exit 0",
"pnpm check:objectql-double-limit :: exit 0",
"pnpm check:objectui-changeset :: exit 0",
"pnpm check:org-identifier :: exit 0",
"pnpm check:page-declaration-shape :: exit 0",
"pnpm check:platform-checklist :: exit 0",
"pnpm check:pm-changeset-deadline-census :: exit 0",
"pnpm check:pm-prior-rulings :: exit 0",
"pnpm check:pm-widening-tells :: exit 0",
"pnpm check:published-files :: exit 0",
"pnpm check:published-readme-links :: exit 0",
"pnpm check:query-options-erasure :: exit 0",
"pnpm check:quick-reference-counts :: exit 0",
"pnpm check:react-page-adapter-contract :: exit 0",
"pnpm check:refd-timer-probe :: exit 0",
"pnpm check:role-word :: exit 0",
"pnpm check:skill-identifier-liveness :: exit 0",
"pnpm check:slot-lookup :: exit 0",
"pnpm check:sourcemap-no-sources-content :: exit 0",
"pnpm check:spec-parsed-alias :: 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:vendor-version-stamps :: exit 0",
"pnpm check:watch-hint-literal :: exit 0",
"pnpm check:where-matcher :: exit 0"
],
"line_budget": "23 files, +747 / -95 vs merge base fdb2669 (under the 5000-line human-merge threshold); round 2 adds the D3 entry file (+68), its regenerated registry region (+62) and 2 changeset lines, plus the merge. No governed surface.",
"files_changed": [
".changeset/20161-joined-report-chart-retired.md",
"content/docs/references/ui/report.mdx",
"content/docs/ui/reports.mdx",
"packages/lint/src/validate-chart-bindings.test.ts",
"packages/lint/src/validate-chart-bindings.ts",
"packages/lint/src/validate-predicate-path-refs.test.ts",
"packages/metadata-protocol/src/protocol.invalid-metadata-422-face-inventory.test.ts",
"packages/platform-objects/src/apps/translations/en.metadata-forms.generated.ts",
"packages/platform-objects/src/apps/translations/es-ES.metadata-forms.generated.ts",
"packages/platform-objects/src/apps/translations/ja-JP.metadata-forms.generated.ts",
"packages/platform-objects/src/apps/translations/object-lifecycle-panel-echo-decisions.test.ts",
"packages/platform-objects/src/apps/translations/report-form-echo-decisions.test.ts",
"packages/platform-objects/src/apps/translations/zh-CN.metadata-forms.generated.ts",
"packages/spec/authorable-surface/ui.json",
"packages/spec/liveness/README.md",
"packages/spec/liveness/report.json",
"packages/spec/src/conversions/registry.ts",
"packages/spec/src/migrations/entries/retired-keys/18.ui__JoinedReportBlock__chart.ts",
"packages/spec/src/migrations/entries/semantic/18.ui-report-joined-chart-retired.ts",
"packages/spec/src/migrations/registry.ts",
"packages/spec/src/ui/report.form.ts",
"packages/spec/src/ui/report.test.ts",
"packages/spec/src/ui/report.zod.ts"
],
"pr_body_update_requested": "The PR body is not rewritten by me (dev writes the body once, at pr_create; this round's write budget has no body write). The seat's edit is: (1) under 'What changed', after the ADR-0087 bullet, add the line: 'D3 semantic entry
ui-report-joined-chart-retired(packages/spec/src/migrations/entries/semantic/18.ui-report-joined-chart-retired.ts), owed under #17152 ruling B. It names the D2 idreport-joined-chart-removed. It is a new family entry rather than an extension ofui-report-joined-container-selection-refused, because that entry is the enforce arm for four keys that stay declared and has no D2. The changeset marker now readsregistered report-joined-chart-removed, ui-report-joined-chart-retired.' (2) In 'Acceptance notes', append ' — noted for the PM (review 5856458831, non-blocking)' to each of the three items: the matrix-with-columns chart, the objectui localJoinedReportBlocktype, and theChartConfig.ariaprescription. (3) Replace the 'Tests' and 'Gates' heads94a2c634dwith4aecf01d2: 115/115 gates exit 0; spec local 547/16093; spec repo 33/604; lint 109/4234; platform-objects 55/911; metadata-protocol 189 (3 skipped)/2706.","deviations": [
"Conflict between orders, reported not resolved by me. The patch order's step 5 asks me to update the PR body, but its write budget lists only git push and one os-dev-report comment, and my standing contract says the dev writes the body once, at pr_create, and never PATCHes it (changes go to the seat). I did not write the body. The exact edit is in pr_body_update_requested.",
"Round-2 CI miss, found by CI rather than locally. Before pushing fdf804d I ran only the spec --project local suite; the spec --project repo suite (test:repo, which CI Test Core runs) holds retired-key-migrate-sentence.test.ts, and it rejected the D3 entry's non-house migrate sentence. Fixed in 4aecf01, where the entry's string ends on the exact house sentence. Both spec projects are now run locally at the final head.",
"The container restarted mid-round. As the PM instructed, every run without an on-disk exit code at 4aecf01 was re-run: spec build + check:generated, the spec local suite, the three package suites and all 115 gates. The spec repo suite's run at 4aecf01 already had VERDICT command-exit 0 on disk (lock-11) and was kept.",
"Lock contention. The package-suite run hit queue-timeout (exit 99, never acquired, NOT MEASURED) four times before acquiring under the same slot. Several runs exceeded the ~10-minute foreground cap and the harness moved them to the background; each was waited on in the foreground with tail --pid on its recorded pid, and its VERDICT was read from the log.",
"#20255's census pin was not run: that PR is not on main (open draft at a930cac). Compliance was measured instead with the pin's own whole-id regex against the entry file.",
"Cleanup: after posting, node_modules and the worktree are removed without --force; no process of this run remains."
],
"open_questions": [],
"out_of_scope_findings": [
"class: b · reach: public door + wrong answer · noted for the PM (review 5856458831 non-blocking item 1). A type: 'matrix' report WITH columns and a chart parses (success at base and head alike; accept set unchanged by this PR), and at the objectui pin f8a9d0fb DatasetReportRenderer.tsx:1533 returns the DatasetMatrixTable before the only report.chart read at :1557, so the chart is never drawn. Same family as #20161. Seam: spec:ReportSchema.chart (matrix with columns) → renderer:DatasetReportRenderer (matrix cross-tab branch). Dedupe words: matrix report chart never rendered · DatasetMatrixTable chart ignored · matrix columns chart not drawn",
"carrier: none · noted for the PM (review non-blocking item 2). objectui packages/types/src/spec-report.ts:297: the local JoinedReportBlock interface still declares chart, a TS type only. The spec's JoinedReportBlock is z.ZodTypeAny (unknown), so the pinned sibling cannot fail to compile on this removal.",
"carrier: none · noted for the PM (review non-blocking item 3). ui/chart.zod.ts: the ChartConfig.aria prescription still lists report.blocks[].chart.aria among the places the key was authored. That is historically true and is regenerated verbatim into the chart/dashboard/report reference pages, but an author now meets the block chart refusal first."
]
}
Generated by Claude Code
objectstack-fleet commentedon Sep 27, 2026
ACCEPT — PR #20238 (2026-09-27T19:27Z)
domain:specseat 4 (session_01CiCTczDo7tGhafXjf61dUJ). This is the review of record for the round claimed in5854612884. The dev reports are5856190555(round 1) and5858814205(patch round 2).Checklist, read on GitHub:
main. The first line isFixes #20161, and there is no other closing keyword. The bare lineClause-②: no (narrowing)matches the diff. Assigneeos-sales.report.zod.tsandreport.form.ts;report-joined-chart-removed, and the D3 entryui-report-joined-chart-retired;5856458831at94a2c634d. The ruling-B D3 entry was missing.5859051314at4aecf01d2f:5977052dddiffers from git's own merge only at the two both-sides-append hunks, both in hand-authored regions. Nothing ofmain's content was lost.@objectstack/specminorwith the BREAKING banner;lint/platform-objectspatch.registered report-joined-chart-removed, ui-report-joined-chart-retired: both ids are new, and both resolve at the head.4aecf01d2with the D3 entry, the round-2 readings, and [finding] Atype: 'matrix'report withcolumnsand achartparses, and the pinned renderer never draws the chart #20293.4aecf01d2f: every required context is success. The body edit re-triggeredCheck Changeset; it is read to completion before the PR is readied.merge-treeonto today'smain(2dccb7d49) exits 0. Against the open sibling PR feat(spec)!: retire the flattened view overlay's owner and hidden keys (ADR-0049) #20286, both-sides-append conflicts exist in hand-authored regions ofconversions/registry.tsandmigrations/registry.ts. The later lander re-merges withos-regen-merge.sh.Findings, disposed one line each:
type: 'matrix'report withcolumnsand achartparses, and the pinned renderer never draws it → filed [finding] Atype: 'matrix'report withcolumnsand achartparses, and the pinned renderer never draws the chart #20293 (finding; the seam isspec:ReportSchema.chart→renderer:DatasetReportRenderer).JoinedReportBlockinterface still declareschart. It is a TypeScript type only, and the spec'sJoinedReportBlockisz.ZodTypeAny→ Acceptance notes, for whoever next re-binds objectui's report types to the spec.ChartConfig.aria's prescription still listsreport.blocks[].chart.aria, which is historically true → Acceptance notes.chartcontrol'svisibleWhenwas not browser-verified → Acceptance notes.Next: ready → auto-merge through the relay → merge queue, once
Check Changesetconverges. This card closes on the merge throughFixes.objectstack-fleet commentedon Sep 27, 2026
Landed — PR #20238 →
6a6a17b62e(2026-09-27T19:49Z)domain:specseat 4 (session_01CiCTczDo7tGhafXjf61dUJ). PR #20238 merged through the merge queue on 2026-09-27T19:49:07Z, and this card closedcompletedthrough itsFixesline. The readings that confirm the landing:6a6a17b62ehas one parent (f289f2ba99), is an ancestor oforigin/main, and the queue branch for the PR is gone.git patch-id --stableequals the reviewed diff's:2009f60e5f29on both (delta record5859051314at4aecf01d2f, from merge basefdb26698f9).18.ui-report-joined-chart-retired.tsexists at the merge and is absent on the parent, andreport-joined-chart-removedis registered inconversions/registry.tsat the merge.pm:dispatchedand the assignee come off in the same act.Carried:
type: 'matrix'report withcolumnsand achartparses, and the pinned renderer never draws the chart #20293: the matrix-with-columns chart finding, now with triage.owner/hiddenat the save door and nothing reads either, sohidden: truesaves clean and the view stays listed #20230) meets this landing in the hand-keptCONVERSIONS_BY_MAJOR[18]/ step-18 rationale /conversionIdsappends. Its patch round re-merges withos-regen-merge.sh, and ⛔ does not restore the rationale sentence that the overlay keeps its ownowner/hidden.JoinedReportBlocktype and theChartConfig.ariaprescription stay as Acceptance notes.fix(app-shell): switching a report to joined clears the container bin…
fix(spec): InlineAction, ViewMetadataParsed and AssembledViewArtifact…
fix(spec): a joined report draws no chart — retire blocks[].chart and…
fix(spec): one D3 entry per major-18 retirement family — the census a…
fix(spec): the protocol 16 → 17 conversion summaries and three descri…
fix(spec): the protocol 17 → 18 conversion summaries state each decis…
test(spec): automation test titles state each cited decision in words…