Skip to content

Commit a41ba5c

Browse files
os-zhuangclaude
andauthored
chore(spec): enroll report and dashboard in the liveness GOVERNED set (#3462) (#3474)
Closes the systemic anti-drift gap for two authorable UI types (umbrella #1878). Both were registered but ungoverned, so their property liveness wasn't CI-checked. - Add liveness/report.json (20 live / 2 dead) and dashboard.json (18 live / 2 dead), each property classified with an objectui consumer. - Re-verification corrected stale 2026-06 audit findings: report `chart` is live (DatasetReportChart via useDatasetRows, #1890/#3441); dashboard globalFilters/dateRange live (#2501); title↔label fixed (objectui#2806); ADR-0021 widget migration shipped (#3251). Only aria/performance dead. - Add both to GOVERNED in check-liveness.mts; gate green; README table + rollout list updated. webhook (third type in #3462) deferred — not a registered metadata type; rides with the disconnect decision in #3461. No spec shape/behavior change (ledger + gate config only). Claude-Session: https://claude.ai/code/session_01CMaDBhnZEUu1fcw8Rvo6Yq Co-authored-by: Claude <noreply@anthropic.com>
1 parent 169b58a commit a41ba5c

5 files changed

Lines changed: 152 additions & 2 deletions

File tree

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
---
2+
"@objectstack/spec": patch
3+
---
4+
5+
chore(spec): enroll `report` and `dashboard` in the liveness GOVERNED set (#3462)
6+
7+
Closes the systemic anti-drift gap for two more authorable UI types (umbrella
8+
#1878). Both were registered/round-trippable but ungoverned, so their property
9+
liveness wasn't CI-checked — the reason drifts like dashboard `title``label`
10+
and stale report `chart` config survived until an audit caught them.
11+
12+
- Added `packages/spec/liveness/report.json` (20 live / 2 dead) and
13+
`dashboard.json` (18 live / 2 dead), each property classified with an
14+
objectui consumer reference.
15+
- Re-verification corrected several stale 2026-06 audit findings against current
16+
code: report `chart` is **live** (DatasetReportChart plots `chart.xAxis`/
17+
`yAxis` via `useDatasetRows`, #1890/#3441); dashboard `globalFilters`/
18+
`dateRange` are **live** (framework#2501); `title``label` fixed (objectui#2806);
19+
the ADR-0021 widget migration shipped (#3251). Only `aria`/`performance` remain
20+
dead on each (perf `authorWarn`'d).
21+
- Added both to `GOVERNED` in `check-liveness.mts`; the gate is green. Future
22+
drift on these types is now a CI failure, not an audit finding.
23+
24+
`webhook` (the third type in #3462) is deferred — it isn't a registered
25+
metadata type; its enrollment rides with the disconnect decision in #3461.
26+
27+
No spec shape/behavior change (ledger + gate config only).

packages/spec/liveness/README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,10 @@ EOF
203203
| page | 16 ||| 1 | fully live + one planned |
204204
| view | 70 | 0 | 5 || list/form drilled via `children` (#2998 Track B); dead = list.{responsive,performance} + form.{data,defaultSort,aria}, all but aria authorWarn'd; form.{buttons,defaults} now live — objectui ObjectForm folds them onto its flat props (framework#1894 / #2998); audit-era DEAD lines superseded by re-verification (submitBehavior, sharing.lockedBy, list ViewData providers, and the ADR-0021 chart shape — all live now); level-2 dead residue (userActions.buttons, addRecord.mode/formView, tabs[].order) noted on parents — one drill level only |
205205

206+
| report | 20 | 0 | 2 || dataset-bound (ADR-0021); dead = aria + performance (perf authorWarn'd); audit-era `chart` DEAD superseded — DatasetReportChart plots `chart.xAxis`/`yAxis` via useDatasetRows (framework#1890 / #3441), `groupBy` stays experimental (describe marker) |
207+
| dashboard | 18 | 0 | 2 || ADR-0021 dataset widgets (WidgetConfigPanel + DashboardRenderer migrated #3251; DashboardWidgetSchema `.strict()`); dead = aria + performance (perf authorWarn'd); audit-era `globalFilters`/`dateRange` DEAD superseded — LIVE via framework#2501; `title``label` fixed (objectui#2806) |
208+
206209
The `dead` set across types is the enforce-or-remove worklist (ADR-0049); every
207210
misleading entry carries `authorWarn` so authors hear about it at compile time.
208-
Not yet governed (rollout): dashboard, app, report, job, datasource,
211+
Not yet governed (rollout): app, job, datasource,
209212
translation, email_template, doc, book, validation, seed.
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
{
2+
"type": "dashboard",
3+
"_note": "DashboardSchema (UI, ADR-0021 dataset-bound). Live path: objectui DashboardView → DashboardRenderer → DatasetWidget. Seeded from docs/audits/2026-06-dashboardschema-property-liveness.md and re-verified against objectui HEAD — several audit-era findings are superseded: the ADR-0021 widget migration shipped (Studio WidgetConfigPanel + DashboardRenderer on dataset/dimensions/values, framework#3251; DashboardWidgetSchema is now `.strict()`); `globalFilters`/`dateRange` are LIVE (dashboard-level filters, framework#2501); the `title`↔`label` drift is fixed (renderer falls back to `label`, objectui#2806); the undeclared widget props were reconciled (#1894). objectui paths cited as prose in `note` (not `evidence`). Framework provenance/lock fields auto-classify live (ADR-0010). Widget-level props are classified in the DashboardWidgetSchema subtree, not drilled here.",
4+
"props": {
5+
"name": {
6+
"status": "live",
7+
"note": "dashboard identity — metadata key + objectui DashboardView/DashboardRenderer."
8+
},
9+
"label": {
10+
"status": "live",
11+
"note": "objectui: DashboardRenderer header title (falls back from the legacy `title`, objectui#2806) + spec-bridge dashboard.ts."
12+
},
13+
"description": {
14+
"status": "live",
15+
"note": "objectui: DashboardRenderer header (`:787`), gated by header.showDescription."
16+
},
17+
"header": {
18+
"status": "live",
19+
"note": "objectui: DashboardRenderer.tsx:778-796 — showTitle/showDescription gates + header.actions row."
20+
},
21+
"widgets": {
22+
"status": "live",
23+
"note": "objectui: the widget grid — DashboardRenderer maps each to DatasetWidget/metric/etc. Per-widget props live in the DashboardWidgetSchema subtree (strict, ADR-0021)."
24+
},
25+
"columns": {
26+
"status": "live",
27+
"note": "objectui: DashboardRenderer.tsx:250 — grid column count (inferred when unset)."
28+
},
29+
"gap": {
30+
"status": "live",
31+
"note": "objectui: DashboardRenderer.tsx:262 — grid gap."
32+
},
33+
"refreshInterval": {
34+
"status": "live",
35+
"note": "objectui: DashboardRenderer.tsx:385-386 — sets a setInterval(onRefresh) every N seconds. Caveat: only fires when the host passes an `onRefresh` handler; the renderer is the consumer."
36+
},
37+
"globalFilters": {
38+
"status": "live",
39+
"note": "objectui: DashboardRenderer.tsx:279,988 — dashboard-level filter values hosted and merged into every widget's query (framework#2501). Supersedes the 2026-06 audit's DEAD finding."
40+
},
41+
"dateRange": {
42+
"status": "live",
43+
"note": "objectui: DashboardRenderer.tsx:279,988 — dashboard-level date-range filter (framework#2501). Supersedes the 2026-06 audit's DEAD finding."
44+
},
45+
"aria": {
46+
"status": "dead",
47+
"note": "ARIA attributes — authorable (dashboard.form.ts) but no DashboardRenderer path applies them."
48+
},
49+
"performance": {
50+
"status": "dead",
51+
"authorWarn": true,
52+
"authorHint": "Dashboard performance tuning is not implemented — this config has no runtime consumer.",
53+
"note": "Perf-optimization config — authorable but no renderer/runtime reads it (audit; re-verified — no consumer in plugin-dashboard)."
54+
}
55+
}
56+
}

packages/spec/liveness/report.json

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
{
2+
"type": "report",
3+
"_note": "ReportSchema (analytics report, ADR-0021 single-form). Live path: objectui ReportRenderer → DatasetReportRenderer (dataset-bound). Seeded from docs/audits/2026-06-reportschema-property-liveness.md and re-verified against objectui HEAD — the audit's `chart` = DEAD finding is superseded: DatasetReportRenderer's DatasetReportChart now plots `chart.xAxis`/`yAxis` (dataset dimension/measure) via useDatasetRows (framework#1890/#3441), so `chart` is LIVE (only its `groupBy` sub-key stays experimental, per its own describe marker). objectui paths cited as prose in `note` (not `evidence`, which resolves framework file:line). Framework provenance/lock fields (protection/_lock*) auto-classify live (ADR-0010).",
4+
"props": {
5+
"name": {
6+
"status": "live",
7+
"note": "report identity — metadata key + objectui ReportRenderer."
8+
},
9+
"label": {
10+
"status": "live",
11+
"note": "objectui: DatasetReportRenderer header + Studio ReportDefaultInspector."
12+
},
13+
"description": {
14+
"status": "live",
15+
"note": "display subtitle — objectui report header."
16+
},
17+
"type": {
18+
"status": "live",
19+
"note": "objectui: DatasetReportRenderer routes tabular/summary/matrix (cross-tab + server totals) / joined."
20+
},
21+
"dataset": {
22+
"status": "live",
23+
"note": "objectui: DatasetReportRenderer binds the semantic-layer dataset (ADR-0021); superRefine requires dataset+values for non-joined reports."
24+
},
25+
"rows": {
26+
"status": "live",
27+
"note": "objectui: dataset dimension names grouped down — DatasetReportRenderer."
28+
},
29+
"columns": {
30+
"status": "live",
31+
"note": "objectui: matrix across-dimensions (rows × columns pivot) — DatasetReportRenderer."
32+
},
33+
"values": {
34+
"status": "live",
35+
"note": "objectui: dataset measure names — DatasetReportRenderer; required (superRefine)."
36+
},
37+
"runtimeFilter": {
38+
"status": "live",
39+
"note": "objectui: render-time scope filter ANDed at query time (`?? filter`, mergeFilters) — DatasetReportRenderer."
40+
},
41+
"drilldown": {
42+
"status": "live",
43+
"note": "objectui: DatasetReportRenderer.tsx:697 — click-through to underlying records (default on; set false to disable)."
44+
},
45+
"chart": {
46+
"status": "live",
47+
"note": "objectui: DatasetReportRenderer.tsx:776 + DatasetReportChart plots `chart.xAxis` (dataset dimension) × `chart.yAxis` (measure) via useDatasetRows, honoring `type`/`title` (framework#1890/#3441). Supersedes the 2026-06 audit's DEAD finding. Sub-key `groupBy` stays experimental (its own describe marker) — the dataset renderer plots a single series and never reads it."
48+
},
49+
"blocks": {
50+
"status": "live",
51+
"note": "objectui: joined-report sub-reports, each dataset-bound (dataset/rows/columns/values/runtimeFilter/chart) — DatasetReportRenderer joined branch."
52+
},
53+
"aria": {
54+
"status": "dead",
55+
"note": "ARIA attributes — authorable (report.form.ts) but no report renderer applies them; the dataset renderer ignores `report.aria`."
56+
},
57+
"performance": {
58+
"status": "dead",
59+
"authorWarn": true,
60+
"authorHint": "Report performance tuning is not implemented — this config has no runtime consumer.",
61+
"note": "Perf-optimization config — authorable but no renderer/runtime reads it (audit L; re-verified — no consumer in plugin-report)."
62+
}
63+
}
64+
}

packages/spec/scripts/liveness/check-liveness.mts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ const repoRoot = resolve(specRoot, '../..');
5353
const ledgerRoot = join(specRoot, 'liveness');
5454

5555
// Governed metadata types, rolled out highest-frequency / highest-risk first.
56-
const GOVERNED = ['object', 'field', 'flow', 'action', 'hook', 'permission', 'position', 'agent', 'tool', 'skill', 'dataset', 'page', 'view'];
56+
const GOVERNED = ['object', 'field', 'flow', 'action', 'hook', 'permission', 'position', 'agent', 'tool', 'skill', 'dataset', 'page', 'view', 'report', 'dashboard'];
5757

5858
// ADR-0010 provenance/lock overlay fields — system-stamped, on every type; auto-live.
5959
const FRAMEWORK_FIELDS = new Set([

0 commit comments

Comments
 (0)