rcf-lite 0.20.0 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/blueprints/application-admin-console/CHANGELOG.md +11 -0
- package/blueprints/application-admin-console/README.md +98 -0
- package/blueprints/application-admin-console/blueprint.json +226 -0
- package/blueprints/application-admin-console/contributions/adrs/adr-2201-application-admin-console-capability-vocabulary.json +25 -0
- package/blueprints/application-admin-console/contributions/adrs/adr-2202-application-admin-console-baseline-roles.json +25 -0
- package/blueprints/application-admin-console/contributions/adrs/adr-2203-application-admin-console-invite-transport.json +20 -0
- package/blueprints/application-admin-console/contributions/adrs/adr-2204-application-admin-console-audit-retention.json +20 -0
- package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-001.json +18 -0
- package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-002.json +18 -0
- package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-003.json +18 -0
- package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-004.json +18 -0
- package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-005.json +18 -0
- package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-006.json +18 -0
- package/blueprints/application-admin-console/contributions/tacs/tac-2201-application-admin-console-shell.json +40 -0
- package/blueprints/application-admin-console/contributions/tacs/tac-2202-application-admin-console-capability-discovery.json +44 -0
- package/blueprints/application-admin-console/contributions/tacs/tac-2203-application-admin-console-permission-matrix.json +34 -0
- package/blueprints/application-admin-console/contributions/tacs/tac-2204-application-admin-console-audit-view.json +40 -0
- package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21101.json +34 -0
- package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21102.json +34 -0
- package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21103.json +34 -0
- package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21104.json +28 -0
- package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21105.json +34 -0
- package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21106.json +27 -0
- package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21107.json +27 -0
- package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21108.json +27 -0
- package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21109.json +33 -0
- package/blueprints/application-admin-console/docs/topics.md +35 -0
- package/blueprints/application-admin-console/guide/application-admin-console.md +29 -0
- package/blueprints/application-admin-console/probe-packs/application-admin-console.pack.mjs +182 -0
- package/blueprints/application-api-rest/docs/topics.md +5 -0
- package/blueprints/application-charts/CHANGELOG.md +12 -0
- package/blueprints/application-charts/README.md +73 -0
- package/blueprints/application-charts/blueprint.json +26 -0
- package/blueprints/application-charts/contributions/adrs/adr-1901-application-charts-engine-choice.json +25 -0
- package/blueprints/application-charts/contributions/adrs/adr-1902-application-charts-accessible-palette.json +25 -0
- package/blueprints/application-charts/contributions/adrs/adr-1903-application-charts-motion.json +25 -0
- package/blueprints/application-charts/contributions/requirements/application-charts-req-001.json +15 -0
- package/blueprints/application-charts/contributions/requirements/application-charts-req-002.json +15 -0
- package/blueprints/application-charts/contributions/requirements/application-charts-req-003.json +15 -0
- package/blueprints/application-charts/contributions/requirements/application-charts-req-004.json +15 -0
- package/blueprints/application-charts/contributions/tacs/tac-1901-application-charts-render-shell.json +42 -0
- package/blueprints/application-charts/contributions/tacs/tac-1902-application-charts-keyboard-traversal.json +40 -0
- package/blueprints/application-charts/contributions/user-stories/application-charts-us-18101.json +35 -0
- package/blueprints/application-charts/contributions/user-stories/application-charts-us-18102.json +35 -0
- package/blueprints/application-charts/contributions/user-stories/application-charts-us-18103.json +35 -0
- package/blueprints/application-charts/contributions/user-stories/application-charts-us-18104.json +35 -0
- package/blueprints/application-charts/contributions/user-stories/application-charts-us-18105.json +35 -0
- package/blueprints/application-charts/contributions/user-stories/application-charts-us-18106.json +35 -0
- package/blueprints/application-charts/docs/topics.md +37 -0
- package/blueprints/application-charts/guide/application-charts.md +44 -0
- package/blueprints/application-charts/probe-packs/application-charts.pack.mjs +191 -0
- package/blueprints/application-dashboard/CHANGELOG.md +10 -0
- package/blueprints/application-dashboard/README.md +102 -0
- package/blueprints/application-dashboard/assets/guidance/dashboard-design.md +124 -0
- package/blueprints/application-dashboard/blueprint.json +29 -0
- package/blueprints/application-dashboard/contributions/adrs/adr-2001-application-dashboard-primary-kpi-enum.json +25 -0
- package/blueprints/application-dashboard/contributions/adrs/adr-2002-application-dashboard-timeframe-presets.json +25 -0
- package/blueprints/application-dashboard/contributions/adrs/adr-2003-application-dashboard-export-formats.json +25 -0
- package/blueprints/application-dashboard/contributions/requirements/application-dashboard-req-001.json +15 -0
- package/blueprints/application-dashboard/contributions/requirements/application-dashboard-req-002.json +15 -0
- package/blueprints/application-dashboard/contributions/requirements/application-dashboard-req-003.json +15 -0
- package/blueprints/application-dashboard/contributions/requirements/application-dashboard-req-004.json +15 -0
- package/blueprints/application-dashboard/contributions/requirements/application-dashboard-req-005.json +15 -0
- package/blueprints/application-dashboard/contributions/tacs/tac-2001-application-dashboard-tile-grid.json +47 -0
- package/blueprints/application-dashboard/contributions/tacs/tac-2002-application-dashboard-filter-chrome.json +41 -0
- package/blueprints/application-dashboard/contributions/tacs/tac-2003-application-dashboard-export-handle.json +35 -0
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19101.json +35 -0
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19102.json +35 -0
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19103.json +35 -0
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19104.json +35 -0
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19105.json +35 -0
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19106.json +35 -0
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19107.json +35 -0
- package/blueprints/application-dashboard/docs/topics.md +43 -0
- package/blueprints/application-dashboard/guide/application-dashboard.md +48 -0
- package/blueprints/application-dashboard/probe-packs/application-dashboard.pack.mjs +231 -0
- package/blueprints/application-datatable/CHANGELOG.md +8 -0
- package/blueprints/application-datatable/README.md +43 -0
- package/blueprints/application-datatable/blueprint.json +33 -0
- package/blueprints/application-datatable/contributions/adrs/adr-1801-application-datatable-pattern-choice.json +25 -0
- package/blueprints/application-datatable/contributions/adrs/adr-1802-application-datatable-url-state.json +20 -0
- package/blueprints/application-datatable/contributions/adrs/adr-1803-application-datatable-page-size.json +20 -0
- package/blueprints/application-datatable/contributions/adrs/adr-1804-application-datatable-selection-persistence.json +20 -0
- package/blueprints/application-datatable/contributions/requirements/application-datatable-req-001.json +15 -0
- package/blueprints/application-datatable/contributions/requirements/application-datatable-req-002.json +15 -0
- package/blueprints/application-datatable/contributions/requirements/application-datatable-req-003.json +15 -0
- package/blueprints/application-datatable/contributions/requirements/application-datatable-req-004.json +15 -0
- package/blueprints/application-datatable/contributions/requirements/application-datatable-req-005.json +15 -0
- package/blueprints/application-datatable/contributions/requirements/application-datatable-req-006.json +15 -0
- package/blueprints/application-datatable/contributions/tacs/tac-1801-application-datatable-shell.json +50 -0
- package/blueprints/application-datatable/contributions/tacs/tac-1802-application-datatable-query-adapter.json +39 -0
- package/blueprints/application-datatable/contributions/tacs/tac-1803-application-datatable-selection-model.json +28 -0
- package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17101.json +44 -0
- package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17102.json +44 -0
- package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17103.json +44 -0
- package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17104.json +44 -0
- package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17105.json +44 -0
- package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17106.json +44 -0
- package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17107.json +44 -0
- package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17108.json +44 -0
- package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17109.json +44 -0
- package/blueprints/application-datatable/docs/topics.md +35 -0
- package/blueprints/application-datatable/guide/application-datatable.md +38 -0
- package/blueprints/application-datatable/probe-packs/application-datatable.pack.mjs +240 -0
- package/blueprints/application-error-handling/docs/topics.md +5 -0
- package/blueprints/application-notifications-in-app/CHANGELOG.md +9 -0
- package/blueprints/application-notifications-in-app/README.md +80 -0
- package/blueprints/application-notifications-in-app/blueprint.json +30 -0
- package/blueprints/application-notifications-in-app/contributions/adrs/adr-2101-application-notifications-in-app-live-region-role-mapping.json +25 -0
- package/blueprints/application-notifications-in-app/contributions/adrs/adr-2102-application-notifications-in-app-toast-timeout-floor.json +25 -0
- package/blueprints/application-notifications-in-app/contributions/adrs/adr-2103-application-notifications-in-app-retention-window.json +25 -0
- package/blueprints/application-notifications-in-app/contributions/requirements/application-notifications-in-app-req-001.json +15 -0
- package/blueprints/application-notifications-in-app/contributions/requirements/application-notifications-in-app-req-002.json +15 -0
- package/blueprints/application-notifications-in-app/contributions/requirements/application-notifications-in-app-req-003.json +15 -0
- package/blueprints/application-notifications-in-app/contributions/requirements/application-notifications-in-app-req-004.json +15 -0
- package/blueprints/application-notifications-in-app/contributions/requirements/application-notifications-in-app-req-005.json +15 -0
- package/blueprints/application-notifications-in-app/contributions/tacs/tac-2101-application-notifications-in-app-live-region.json +46 -0
- package/blueprints/application-notifications-in-app/contributions/tacs/tac-2102-application-notifications-in-app-centre.json +52 -0
- package/blueprints/application-notifications-in-app/contributions/tacs/tac-2103-application-notifications-in-app-preferences.json +40 -0
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20101.json +35 -0
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20102.json +35 -0
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20103.json +35 -0
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20104.json +35 -0
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20105.json +35 -0
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20106.json +26 -0
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20107.json +26 -0
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20108.json +26 -0
- package/blueprints/application-notifications-in-app/docs/topics.md +39 -0
- package/blueprints/application-notifications-in-app/guide/application-notifications-in-app.md +47 -0
- package/blueprints/application-notifications-in-app/probe-packs/application-notifications-in-app.pack.mjs +328 -0
- package/blueprints/application-spa/docs/topics.md +5 -0
- package/blueprints/delivery-ci-workflows/docs/topics.md +5 -0
- package/blueprints/deploy-cloudflare-workers/docs/topics.md +5 -0
- package/blueprints/email-smtp-resend/docs/topics.md +5 -0
- package/blueprints/observability-essentials/docs/topics.md +5 -0
- package/blueprints/observability-logging/CHANGELOG.md +5 -0
- package/blueprints/observability-logging/README.md +1 -1
- package/blueprints/observability-logging/blueprint.json +113 -21
- package/blueprints/observability-logging/docs/topics.md +5 -0
- package/blueprints/observability-probe-endpoints/docs/topics.md +5 -0
- package/blueprints/persistence-data-d1/docs/topics.md +5 -0
- package/blueprints/persistence-data-sqlite/docs/topics.md +5 -0
- package/blueprints/security-auth-clerk/CHANGELOG.md +5 -0
- package/blueprints/security-auth-clerk/blueprint.json +2 -1
- package/blueprints/security-auth-clerk/docs/topics.md +5 -0
- package/blueprints/security-auth-keycloak/CHANGELOG.md +5 -0
- package/blueprints/security-auth-keycloak/blueprint.json +2 -1
- package/blueprints/security-auth-keycloak/docs/topics.md +5 -0
- package/blueprints/security-auth-magic-link/CHANGELOG.md +5 -0
- package/blueprints/security-auth-magic-link/blueprint.json +2 -1
- package/blueprints/security-auth-magic-link/docs/topics.md +5 -0
- package/blueprints/security-auth-oauth2/CHANGELOG.md +5 -0
- package/blueprints/security-auth-oauth2/blueprint.json +2 -1
- package/blueprints/security-auth-oauth2/docs/topics.md +5 -0
- package/blueprints/security-secrets-management/docs/topics.md +5 -0
- package/fixtures/canary-manifest.json +9 -9
- package/package.json +2 -2
- package/rcf/code-nodes/cn-106.json +13 -0
- package/rcf/code-nodes/cn-107.json +14 -0
- package/rcf/code-nodes/cn-108.json +13 -0
- package/rcf/code-nodes/cn-109.json +12 -0
- package/rcf/code-nodes/cn-110.json +12 -0
- package/rcf/code-nodes/cn-111.json +14 -0
- package/rcf/code-nodes/cn-112.json +14 -0
- package/rcf/code-nodes/cn-113.json +12 -0
- package/rcf/code-nodes/cn-114.json +13 -0
- package/rcf/code-nodes/cn-115.json +13 -0
- package/rcf/code-nodes/cn-116.json +12 -0
- package/rcf/code-nodes/cn-117.json +13 -0
- package/rcf/code-nodes/cn-118.json +13 -0
- package/rcf/code-nodes/cn-119.json +13 -0
- package/rcf/code-nodes/cn-120.json +13 -0
- package/rcf/code-nodes/cn-121.json +12 -0
- package/rcf/code-nodes/cn-122.json +12 -0
- package/rcf/code-nodes/cn-123.json +13 -0
- package/rcf/code-nodes/cn-124.json +13 -0
- package/rcf/code-nodes/cn-125.json +13 -0
- package/rcf/code-nodes/cn-126.json +13 -0
- package/rcf/code-nodes/cn-127.json +12 -0
- package/rcf/code-nodes/cn-128.json +14 -0
- package/rcf/code-nodes/cn-129.json +14 -0
- package/rcf/code-nodes/cn-130.json +14 -0
- package/rcf/code-nodes/cn-131.json +15 -0
- package/rcf/code-nodes/cn-132.json +12 -0
- package/rcf/code-nodes/cn-133.json +13 -0
- package/rcf/fbs/fbs-036.json +22 -0
- package/rcf/fbs/fbs-037.json +19 -0
- package/rcf/fbs/fbs-038.json +19 -0
- package/rcf/fbs/fbs-039.json +21 -0
- package/rcf/fbs/fbs-040.json +20 -0
- package/rcf/fbs/fbs-041.json +13 -0
- package/rcf/fbs/fbs-042.json +13 -0
- package/rcf/requirements/req-017.json +18 -0
- package/rcf/requirements/req-018.json +18 -0
- package/rcf/requirements/req-019.json +38 -0
- package/rcf/requirements/req-020.json +13 -0
- package/rcf/requirements/req-021.json +13 -0
- package/rcf/requirements/req-022.json +13 -0
- package/rcf/requirements/req-023.json +14 -0
- package/rcf/test-suites/ts-046.json +78 -0
- package/rcf/test-suites/ts-047.json +54 -0
- package/rcf/test-suites/ts-048.json +54 -0
- package/rcf/test-suites/ts-049.json +70 -0
- package/rcf/test-suites/ts-050.json +69 -0
- package/rcf/test-suites/ts-051.json +22 -0
- package/rcf/test-suites/ts-052.json +20 -0
- package/rcf/user-stories/us-1701.json +56 -0
- package/rcf/user-stories/us-1801.json +40 -0
- package/rcf/user-stories/us-1901.json +40 -0
- package/rcf/user-stories/us-2001.json +50 -0
- package/rcf/user-stories/us-2101.json +45 -0
- package/rcf/user-stories/us-2201.json +60 -0
- package/rcf/user-stories/us-2301.json +51 -0
- package/releases/releases.yaml +11 -1
- package/src/blueprint/apply.js +98 -1
- package/src/blueprint/capabilities.js +318 -0
- package/src/blueprint/loader.js +247 -0
- package/src/browser-verify/boot.js +180 -0
- package/src/browser-verify/index.js +13 -0
- package/src/browser-verify/manifest-writer.js +31 -6
- package/src/browser-verify/pack-browser.js +294 -0
- package/src/browser-verify/pack-loader.js +176 -0
- package/src/browser-verify/pack-runner.js +193 -0
- package/src/browser-verify/pack-schema.js +155 -0
- package/src/browser-verify/runner.js +24 -1
- package/src/cli/blueprint.js +92 -0
- package/src/cli/browser-verify.js +147 -7
- package/src/core/errors/index.js +7 -0
package/blueprints/application-charts/contributions/user-stories/application-charts-us-18102.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"usId": "application-charts-US-18102",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"reqId": "application-charts-REQ-002",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "approved",
|
|
7
|
+
"title": "Series distinction combines colour, pattern and direct label so a colour-blind reader reads the same distinction",
|
|
8
|
+
"asA": "reader with a colour-vision deficiency using the shipped surface",
|
|
9
|
+
"iWant": "each series on a multi-series chart to carry colour, a distinguishing pattern and a direct label at the series",
|
|
10
|
+
"soThat": "the series distinction is legible without relying on colour perception alone (WCAG 1.4.1)",
|
|
11
|
+
"acceptanceCriteria": [
|
|
12
|
+
{
|
|
13
|
+
"id": "AC-18102-1",
|
|
14
|
+
"description": "Given a rendered chart with N series, the series distinction combines colour, pattern (dashed line, hatched fill or a marker shape) and a direct label at the series; every series in the DOM carries a data-pattern attribute or a stroke-dasharray or an SVG pattern fill reference and a labelled text node adjacent to the series. Probed by the application-charts pack check AC-18102-1 (Playwright drives the browser to the chart route, reads the accessibility tree and the DOM, and asserts every series carries at least one non-colour attribute plus a direct label). The runner has no vision-deficiency emulation seam today, so the check is proven at the DOM level (colour is only one of the three cues); the README names the vision-deficiency simulation gap under known mechanism-reach gaps.",
|
|
15
|
+
"given": "a rendered multi-series chart",
|
|
16
|
+
"when": "the DOM is inspected",
|
|
17
|
+
"then": "every series carries colour plus a non-colour pattern attribute plus a direct label",
|
|
18
|
+
"testable": true,
|
|
19
|
+
"scope": "runtime"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"id": "AC-18102-2",
|
|
23
|
+
"description": "Given a rendered single-series chart, the AC-18102-1 rule does not apply (single-series distinction is not a WCAG 1.4.1 concern); the pack records applicable false for the check on the surface and no browser assertion runs. The blueprint's README names the single-series exemption under known mechanism-reach gaps.",
|
|
24
|
+
"given": "a rendered single-series chart",
|
|
25
|
+
"when": "the pack runs",
|
|
26
|
+
"then": "the AC-18102-1 rule does not apply and the pack records applicable false",
|
|
27
|
+
"testable": true,
|
|
28
|
+
"scope": "runtime"
|
|
29
|
+
}
|
|
30
|
+
],
|
|
31
|
+
"tacIds": ["TAC-1901-application-charts-render-shell"],
|
|
32
|
+
"tags": ["blueprint:application-charts"],
|
|
33
|
+
"createdAt": "2026-09-04T21:00:00Z",
|
|
34
|
+
"updatedAt": "2026-09-04T21:00:00Z"
|
|
35
|
+
}
|
package/blueprints/application-charts/contributions/user-stories/application-charts-us-18103.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"usId": "application-charts-US-18103",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"reqId": "application-charts-REQ-003",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "approved",
|
|
7
|
+
"title": "Every chart ships a paired text-alternative table with the same data, focus-reachable in the same landmark",
|
|
8
|
+
"asA": "screen-reader user using the shipped surface",
|
|
9
|
+
"iWant": "every chart to ship a text-alternative table carrying the same data as the chart, in the same landmark, cell-per-value, focus-reachable",
|
|
10
|
+
"soThat": "the chart's information is available in a form assistive tech traverses cell-by-cell (WCAG 1.1.1 the shelf inherits through TAC-1901)",
|
|
11
|
+
"acceptanceCriteria": [
|
|
12
|
+
{
|
|
13
|
+
"id": "AC-18103-1",
|
|
14
|
+
"description": "Given a rendered chart, a `<table>` element carrying the same data lives in the same landmark (`role=\"region\"` wrapping both the chart and the table, or the same `<section>` element), with a row per x-axis value or category and a column per series (cell-per-value contract). The table is either visible under the chart or visually-hidden and focus-reachable through a labelled control the shell renders (a `<button>` or a skip link). Assistive tech traverses the table cell-by-cell and every cell text matches the corresponding chart value. Probed by the application-charts pack check AC-18103-1 (Playwright drives to the route, reads the accessibility tree, asserts the table is present in the chart's landmark and the cell texts match the chart's rendered values).",
|
|
15
|
+
"given": "a rendered chart",
|
|
16
|
+
"when": "the accessibility tree is read",
|
|
17
|
+
"then": "a `<table>` in the same landmark carries the same values cell-by-cell and is focus-reachable",
|
|
18
|
+
"testable": true,
|
|
19
|
+
"scope": "runtime"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"id": "AC-18103-2",
|
|
23
|
+
"description": "Given a rendered chart whose text-alternative table is visually-hidden, the shell renders a labelled control (a `<button>` or an anchor link) that moves focus to the table's first cell; the control's accessible name reads `Show data table` or an equivalent operator-configured label. The control is keyboard-reachable in reading order before the chart's own interactive controls.",
|
|
24
|
+
"given": "a rendered chart with a visually-hidden text-alternative table",
|
|
25
|
+
"when": "the operator tabs into the chart's landmark",
|
|
26
|
+
"then": "a labelled control appears before the chart's data-point controls and moves focus to the table on activation",
|
|
27
|
+
"testable": true,
|
|
28
|
+
"scope": "runtime"
|
|
29
|
+
}
|
|
30
|
+
],
|
|
31
|
+
"tacIds": ["TAC-1901-application-charts-render-shell"],
|
|
32
|
+
"tags": ["blueprint:application-charts"],
|
|
33
|
+
"createdAt": "2026-09-04T21:00:00Z",
|
|
34
|
+
"updatedAt": "2026-09-04T21:00:00Z"
|
|
35
|
+
}
|
package/blueprints/application-charts/contributions/user-stories/application-charts-us-18104.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"usId": "application-charts-US-18104",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"reqId": "application-charts-REQ-004",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "approved",
|
|
7
|
+
"title": "Interactive charts expose a keyboard traversal path with a stable announced-string contract",
|
|
8
|
+
"asA": "keyboard-only user reading an interactive chart",
|
|
9
|
+
"iWant": "each data point to be focus-reachable in reading order with a stable announced string carrying series name, x-value, y-value and unit",
|
|
10
|
+
"soThat": "the pointer-only granular data-point access is available to a keyboard user (WCAG 2.1.1)",
|
|
11
|
+
"acceptanceCriteria": [
|
|
12
|
+
{
|
|
13
|
+
"id": "AC-18104-1",
|
|
14
|
+
"description": "Given an interactive chart (data points are clickable or hoverable and trigger a callback), keyboard focus reaches each data point in reading order (left-to-right, top-to-bottom for single-series; series-by-series for multi-series), and the announced string on focus matches the format `<seriesName>, <xValue>, <yValue> <unit>` (comma-separated, unit is the operator-configured unit or `unitless`). A `prefers-reduced-motion: reduce` media query on the rendered surface suppresses chart entry and update transitions (`transition-duration: 0` or `animation-duration: 0` on the affected elements). Probed by the application-charts pack check AC-18104-1 (Playwright drives the browser, tabs through the chart, asserts every data point receives focus, the announced string matches the format, and the reduced-motion CSS rule applies).",
|
|
15
|
+
"given": "an interactive chart with reduced-motion respect",
|
|
16
|
+
"when": "the operator tabs through the chart with prefers-reduced-motion set",
|
|
17
|
+
"then": "each data point receives focus in reading order, the announced string matches the format, and transitions are suppressed",
|
|
18
|
+
"testable": true,
|
|
19
|
+
"scope": "runtime"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"id": "AC-18104-2",
|
|
23
|
+
"description": "Given a non-interactive chart (no data-point activation), the keyboard-traversal AC does not apply; the chart is still tab-reachable as one focusable landmark exposing an accessible name (the chart's title or aria-label). The pack records applicable false for AC-18104-1 on a non-interactive chart; the reduced-motion rule still applies and is a separate observation on the pack record when the surface exposes any transition.",
|
|
24
|
+
"given": "a non-interactive chart",
|
|
25
|
+
"when": "the pack runs",
|
|
26
|
+
"then": "the AC-18104-1 keyboard-traversal rule does not apply and the pack records applicable false",
|
|
27
|
+
"testable": true,
|
|
28
|
+
"scope": "runtime"
|
|
29
|
+
}
|
|
30
|
+
],
|
|
31
|
+
"tacIds": ["TAC-1901-application-charts-render-shell", "TAC-1902-application-charts-keyboard-traversal"],
|
|
32
|
+
"tags": ["blueprint:application-charts"],
|
|
33
|
+
"createdAt": "2026-09-04T21:00:00Z",
|
|
34
|
+
"updatedAt": "2026-09-04T21:00:00Z"
|
|
35
|
+
}
|
package/blueprints/application-charts/contributions/user-stories/application-charts-us-18105.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"usId": "application-charts-US-18105",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"reqId": "application-charts-REQ-002",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "approved",
|
|
7
|
+
"title": "The shell exposes the accessible-defaults palette hook (light and dark) and accepts elicited operator overrides",
|
|
8
|
+
"asA": "operator applying the blueprint",
|
|
9
|
+
"iWant": "the render shell to ship a light and dark categorical palette matched against WCAG contrast and to accept my brand tokens as overrides",
|
|
10
|
+
"soThat": "the ratified palette is the recommended default and brand overrides remain contrast-safe when I feed them in (ADR-1902)",
|
|
11
|
+
"acceptanceCriteria": [
|
|
12
|
+
{
|
|
13
|
+
"id": "AC-18105-1",
|
|
14
|
+
"description": "Given a rendered chart on a light background, every series colour and every axis text carries a contrast ratio of at least 4.5:1 against its background (WCAG 1.4.3 for text; the 3:1 non-text contrast under WCAG 1.4.11 for series marks). The shell ships light and dark palettes matched against these ratios; the shell's palette accessor returns the applied palette by name and version. This AC is a build-scan surface (palette values readable from the applied blueprint's palette module); the pack has no dedicated check for it and the README names the gap under known mechanism-reach gaps as a build-scan opportunity for a v1.1 minor bump.",
|
|
15
|
+
"given": "a rendered chart under either the light or dark palette",
|
|
16
|
+
"when": "the palette is inspected",
|
|
17
|
+
"then": "series colours meet WCAG 1.4.11 (3:1 non-text contrast) and axis text meets WCAG 1.4.3 (4.5:1) against the applied background",
|
|
18
|
+
"testable": true,
|
|
19
|
+
"scope": "library"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"id": "AC-18105-2",
|
|
23
|
+
"description": "Given the shell's palette API, an operator supplies brand tokens (a palette override object keyed by series index or role) and the shell renders the operator palette; when the operator palette misses a token the shell falls back to the accessible-defaults palette at the same index and records a warning on the render log. The API surface (`renderShell({ palette, chart })`) is a project-side contract; the fallback behaviour is exercised by the applying project's own tests, not this blueprint's pack.",
|
|
24
|
+
"given": "an operator palette with missing tokens",
|
|
25
|
+
"when": "the shell renders",
|
|
26
|
+
"then": "missing tokens fall back to the accessible-defaults palette and a warning is recorded",
|
|
27
|
+
"testable": true,
|
|
28
|
+
"scope": "library"
|
|
29
|
+
}
|
|
30
|
+
],
|
|
31
|
+
"tacIds": ["TAC-1901-application-charts-render-shell"],
|
|
32
|
+
"tags": ["blueprint:application-charts"],
|
|
33
|
+
"createdAt": "2026-09-04T21:00:00Z",
|
|
34
|
+
"updatedAt": "2026-09-04T21:00:00Z"
|
|
35
|
+
}
|
package/blueprints/application-charts/contributions/user-stories/application-charts-us-18106.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"usId": "application-charts-US-18106",
|
|
3
|
+
"prdId": "PRD-001",
|
|
4
|
+
"reqId": "application-charts-REQ-004",
|
|
5
|
+
"version": "1.0.0",
|
|
6
|
+
"status": "approved",
|
|
7
|
+
"title": "A chart engine that refuses text-alternative access is refused on the applying project",
|
|
8
|
+
"asA": "shelf reviewer gating an applying project's chart engine choice",
|
|
9
|
+
"iWant": "the blueprint to refuse a chart engine choice that renders canvas-only surfaces with no text-alternative path",
|
|
10
|
+
"soThat": "the text-alternative REQ-003 and the keyboard-traversal REQ-004 stay reachable through the render shell's contract regardless of the chosen engine (ADR-1901)",
|
|
11
|
+
"acceptanceCriteria": [
|
|
12
|
+
{
|
|
13
|
+
"id": "AC-18106-1",
|
|
14
|
+
"description": "Given ADR-1901's engine choice (Recharts, ECharts, Chart.js, D3 primitives or another operator-elicited engine), the applying project's manifest records the engine and the text-alternative reach: the engine's rendered chart is paired with a `<table>` element the pack asserts (AC-18103-1). An engine that renders exclusively to a `<canvas>` and does not offer a text-alternative surface is refused at project-side review; the refusal is documented in the blueprint's README under the engine-refusal rule.",
|
|
15
|
+
"given": "an ADR-1901 engine choice",
|
|
16
|
+
"when": "the applying project's chart mount is reviewed",
|
|
17
|
+
"then": "the engine is refused if it renders canvas-only surfaces with no text-alternative path",
|
|
18
|
+
"testable": true,
|
|
19
|
+
"scope": "library"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"id": "AC-18106-2",
|
|
23
|
+
"description": "Given a compliant engine choice, the applying project's rendered chart carries a `data-chart-engine` attribute or an equivalent DOM marker naming the engine (Recharts, ECharts, Chart.js, D3 or the elicited name). This is a project-side observation, not a pack check; the README names it under known mechanism-reach gaps as a documentation contract on the applying project.",
|
|
24
|
+
"given": "a compliant chart engine on the applying project",
|
|
25
|
+
"when": "the rendered chart is inspected",
|
|
26
|
+
"then": "the engine name is discoverable on the rendered DOM through a stable attribute",
|
|
27
|
+
"testable": true,
|
|
28
|
+
"scope": "library"
|
|
29
|
+
}
|
|
30
|
+
],
|
|
31
|
+
"tacIds": ["TAC-1901-application-charts-render-shell"],
|
|
32
|
+
"tags": ["blueprint:application-charts"],
|
|
33
|
+
"createdAt": "2026-09-04T21:00:00Z",
|
|
34
|
+
"updatedAt": "2026-09-04T21:00:00Z"
|
|
35
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# application-charts: coordination vocabulary
|
|
2
|
+
|
|
3
|
+
## Global topics
|
|
4
|
+
|
|
5
|
+
The blueprint claims no new global topics at v1.0.0. The chart-component contract is a general accessibility-first practice; every ADR (engine choice, accessible palette, reduced motion) is non-global. When a second chart-shaped blueprint composes on the shelf (a Sankey blueprint, a mapping blueprint), THAT blueprint may claim a `chartEngine` topic; today, the single consumer (application-dashboard T-3) reads the shell contract directly.
|
|
6
|
+
|
|
7
|
+
## Deliberately unclaimed topics
|
|
8
|
+
|
|
9
|
+
- `chartEngine` (the chosen chart engine). Reserved for the applying project as an elicited choice, not a global topic; a second chart-shaped blueprint that composes with a specific engine would either supersede this blueprint or share the shell TAC.
|
|
10
|
+
- `categoricalPalette` (the shipped light and dark accessible-defaults). Not a global topic; the palette accessor is exposed through the shell factory input, not through a topic lookup.
|
|
11
|
+
- `chartMotionTokens` (the motion baseline the shell honours). The application-spa blueprint owns the motion tokens (`motionBaseline` topic in application-spa's docs/topics.md); the charts blueprint's ADR-1903 references them and adds no topic of its own.
|
|
12
|
+
|
|
13
|
+
## Shelf id band and suffix block
|
|
14
|
+
|
|
15
|
+
| Blueprint | US band | ADR/TAC suffix block | Status | Global topics |
|
|
16
|
+
|---|---|---|---|---|
|
|
17
|
+
| application-datatable | 17101-17899 | 18xx | shipped v1.0.0 | none |
|
|
18
|
+
| application-charts | 18101-18899 | 19xx | shipped v1.0.0 | none |
|
|
19
|
+
| application-dashboard | 19101-19899 | 20xx | shipped v1.0.0 | none |
|
|
20
|
+
| application-notifications-in-app | 20101-20899 | 21xx | shipped v1.0.0 | none |
|
|
21
|
+
| application-admin-console | 21101-21899 | 22xx | shipped v1.0.0 | none |
|
|
22
|
+
|
|
23
|
+
The shelf-wide band registry lives in `packages/rcf-lite/docs/blueprint-authoring.md` section 5.
|
|
24
|
+
|
|
25
|
+
## Probe pack
|
|
26
|
+
|
|
27
|
+
`probe-packs/application-charts.pack.mjs` ships three checks anchored to blueprint AC ids:
|
|
28
|
+
|
|
29
|
+
- `AC-18102-1` non-colour distinction (colour plus pattern plus direct label)
|
|
30
|
+
- `AC-18103-1` text-alternative table in the same landmark, cell-per-value
|
|
31
|
+
- `AC-18104-1` keyboard traversal contract with reduced-motion suppression
|
|
32
|
+
|
|
33
|
+
Every check carries a `description` field per spec section 9. `appliesTo` binds `TAC-1901-application-charts-render-shell` OR any FBS route matching an operator-configured chart-route glob. See `probe-packs/application-charts.pack.mjs` for the source; see `packages/rcf-lite/test/fixtures/probe-pack-application-charts/README.md` for the sample-app fixture and the negative-run break switches.
|
|
34
|
+
|
|
35
|
+
## Consumers
|
|
36
|
+
|
|
37
|
+
- `application-dashboard` (visual round T-3): the leaf blueprint the dashboard shell consumes. The dashboard's chart region delegates chart rendering to this blueprint's render shell; the dashboard pack does not duplicate the chart-accessibility ACs, it references them.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Guide: application-charts (v1.0.0)
|
|
2
|
+
|
|
3
|
+
## What it is
|
|
4
|
+
|
|
5
|
+
A shipped, vendor-neutral chart-component contract for a rcf-lite application. One render shell (TAC-1901), one keyboard-traversal contract (TAC-1902), an accessible-defaults palette, and a shipped Playwright probe pack that gates ship on the three runtime-observable surfaces the shelf assures: series distinguish on colour plus pattern plus label, every chart pairs with a text-alternative table in the same landmark, and interactive charts expose a keyboard traversal path with reduced-motion suppression.
|
|
6
|
+
|
|
7
|
+
## What it deliberately is not
|
|
8
|
+
|
|
9
|
+
- Not a chart library. The shell is a contract; the applying project picks Recharts, ECharts, Chart.js, D3 primitives or a hand-authored SVG mount. The ACs are what ship must meet; the HOW is the project's decision.
|
|
10
|
+
- Not a data-source contract. The applying `application-api-rest` blueprint owns the wire endpoint; the render shell reads the data it is given.
|
|
11
|
+
- Not a dashboard layout. The applying `application-dashboard` blueprint owns tile placement, hierarchy and export handles; the charts blueprint owns the chart contract every tile carries.
|
|
12
|
+
|
|
13
|
+
## When to reach for it
|
|
14
|
+
|
|
15
|
+
- Any shipped surface that renders bar, line, area, pie, donut, single-value with sparkline, or heatmap charts. Analytics dashboards, admin overview surfaces, per-record trend views, monitoring UIs.
|
|
16
|
+
- Projects that want the ARIA-first, palette-safe, keyboard-reachable discipline enforced at ship without hand-authoring per chart.
|
|
17
|
+
- Any project where the T-3 application-dashboard is applied (charts is the leaf application-dashboard consumes).
|
|
18
|
+
|
|
19
|
+
## When it does not fit
|
|
20
|
+
|
|
21
|
+
- Print-only or export-only chart output where the runtime accessibility contract does not apply. A PDF report generation pipeline is a separate concern.
|
|
22
|
+
- Highly bespoke visualisations outside the six committed forms (a network graph, a Sankey, a candlestick). Those supersede the blueprint with a project-authored engine contract naming the residuals.
|
|
23
|
+
|
|
24
|
+
## What a good outcome looks like
|
|
25
|
+
|
|
26
|
+
Every rendered chart on the surface mounts through the render shell; every multi-series chart carries colour AND a non-colour pattern AND a direct label at the series; every chart ships a paired `<table>` in the same landmark, focus-reachable through a labelled control, cell-per-value; every interactive chart tabs through its data points in reading order and announces `<seriesName>, <xValue>, <yValue> <unit>` on focus; `prefers-reduced-motion: reduce` suppresses transitions on every chart on the surface. The shipped probe pack runs green on the delivery-ci-workflows gate.
|
|
27
|
+
|
|
28
|
+
## The operator decisions that remain open
|
|
29
|
+
|
|
30
|
+
- **Chart engine** (ADR-1901). Recharts, ECharts, Chart.js, D3 primitives, hand-authored SVG. Elicited at apply; canvas-only-no-text-alternative is refused.
|
|
31
|
+
- **Categorical palette** (ADR-1902). Light and dark accessible-defaults ship as the recommended default; operator brand tokens accepted with a fallback to the defaults on missing tokens.
|
|
32
|
+
- **Interactive traversal scope**. Every chart interactive, or only detail-view charts. The shell binds the keyboard traversal contract on the interactive charts.
|
|
33
|
+
- **Sparkline behaviour**. In-tile (mounted inside a stat tile via application-dashboard) or standalone (mounted on the shipped surface as one chart).
|
|
34
|
+
|
|
35
|
+
## Common gotchas
|
|
36
|
+
|
|
37
|
+
- Chart.js is canvas-based. The shell renders the text-alternative table for you; do not disable it because your engine has its own accessibility mode.
|
|
38
|
+
- Colour-only series distinction is the single most common defect on shipped charts. The blueprint's palette is safe, but the pattern and label cues are still required regardless of palette.
|
|
39
|
+
- `prefers-reduced-motion` is a real user preference. Do not gate it behind a feature flag or a build variable; the shell handles it via CSS media query on every chart on the surface.
|
|
40
|
+
- A blueprint pack fires on any FBS whose surface matches the `appliesTo` predicate. A page with no chart declares no chart route and the pack records `applicable: false`; no need to disable the pack.
|
|
41
|
+
|
|
42
|
+
## Ratified spec reference
|
|
43
|
+
|
|
44
|
+
`projects/blueprint-library/specs/visual-round-spec-2026-09-04.md` section 5.2 in the operator repo names the contract this blueprint realises. Every content decision in the shipped v1.0.0 comes from the spec verbatim; where the shell contract carries a documented deviation from the spec, the blueprint README names it under CALLS MADE.
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
// application-charts probe pack (v1.0.0).
|
|
2
|
+
//
|
|
3
|
+
// Three runtime-observable checks anchored to the blueprint's ACs:
|
|
4
|
+
// AC-18102-1 non-colour distinction (colour plus pattern plus direct label)
|
|
5
|
+
// AC-18103-1 text-alternative table in the same landmark, cell-per-value
|
|
6
|
+
// AC-18104-1 keyboard traversal contract with reduced-motion suppression
|
|
7
|
+
//
|
|
8
|
+
// Every check drives the real Playwright browser the T-0 runner
|
|
9
|
+
// injects (packages/rcf-lite/src/browser-verify/pack-browser.js) and
|
|
10
|
+
// asserts on the DOM the applying project renders under the render
|
|
11
|
+
// shell (TAC-1901) and the keyboard traversal contract (TAC-1902).
|
|
12
|
+
//
|
|
13
|
+
// The runner has no vision-deficiency emulation seam today, so
|
|
14
|
+
// AC-18102-1 is proven at the DOM level: every series carries a
|
|
15
|
+
// non-colour cue (a `data-pattern` attribute, an SVG `pattern` fill
|
|
16
|
+
// reference, a `stroke-dasharray`, or a marker shape) AND a direct
|
|
17
|
+
// label at the series. When `emulateVisionDeficiency` reaches the
|
|
18
|
+
// pack seam in a future runner minor, this pack will add a
|
|
19
|
+
// deuteranopia render pass and lift the DOM-level cue rule; see the
|
|
20
|
+
// README's known-mechanism-reach-gaps section.
|
|
21
|
+
|
|
22
|
+
export default {
|
|
23
|
+
packName: 'application-charts',
|
|
24
|
+
version: '1.0.0',
|
|
25
|
+
blueprintSlug: 'application-charts',
|
|
26
|
+
// Applies to any FBS that realises the chart render-shell TAC or
|
|
27
|
+
// whose navModel routes match an operator-configured chart-route
|
|
28
|
+
// glob. The source references BOTH `tacIds` and `route` so the
|
|
29
|
+
// T-0 loader's applicability source-scan sees the two legal seams.
|
|
30
|
+
appliesTo: ({ fbs }) => {
|
|
31
|
+
const routes = fbs?.designStage?.navModel?.routes ?? [];
|
|
32
|
+
const tacIds = fbs?.contextRequirements?.tacIds ?? [];
|
|
33
|
+
if (tacIds.includes('TAC-1901-application-charts-render-shell')) return true;
|
|
34
|
+
return routes.some((r) => typeof r?.path === 'string' && /chart|charts|dashboard/.test(r.path));
|
|
35
|
+
},
|
|
36
|
+
boot: { bootCommand: null, waitForUrl: null, waitForSelector: null },
|
|
37
|
+
checks: [
|
|
38
|
+
{
|
|
39
|
+
id: 'AC-18102-1',
|
|
40
|
+
severity: 'block',
|
|
41
|
+
description: 'Non-colour distinction: every series carries a non-colour cue (data-pattern, stroke-dasharray, hatched fill or marker) plus a direct label at the series',
|
|
42
|
+
run: async ({ browser, runtimeUrl }) => {
|
|
43
|
+
if (!browser) return { verdict: 'fail', detail: 'no packBrowser wired' };
|
|
44
|
+
await browser.goto(new URL('', runtimeUrl).toString());
|
|
45
|
+
const seriesShape = await browser.evaluate(() => {
|
|
46
|
+
const svgs = Array.from(document.querySelectorAll('svg.chartSvg'));
|
|
47
|
+
const seriesReports = [];
|
|
48
|
+
svgs.forEach((svg) => {
|
|
49
|
+
const chartForm = svg.getAttribute('data-chart-form');
|
|
50
|
+
const seriesGroups = Array.from(svg.querySelectorAll('[data-series]'));
|
|
51
|
+
const seenSeries = new Set();
|
|
52
|
+
seriesGroups.forEach((el) => {
|
|
53
|
+
const name = el.getAttribute('data-series');
|
|
54
|
+
if (seenSeries.has(name)) return;
|
|
55
|
+
seenSeries.add(name);
|
|
56
|
+
const hasDataPattern = el.hasAttribute('data-pattern');
|
|
57
|
+
const hasDash = el.hasAttribute('stroke-dasharray') || (el.querySelector && el.querySelector('polyline[stroke-dasharray]')) ? true : false;
|
|
58
|
+
const fillRef = (el.getAttribute('fill') || '').startsWith('url(');
|
|
59
|
+
const nonColourCue = hasDataPattern || hasDash || fillRef;
|
|
60
|
+
const labelEl = svg.querySelector('[data-series-label="' + name + '"]');
|
|
61
|
+
const hasDirectLabel = Boolean(labelEl && labelEl.textContent && labelEl.textContent.trim() === name);
|
|
62
|
+
seriesReports.push({ chartForm, name, hasDataPattern, hasDash, fillRef, nonColourCue, hasDirectLabel });
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
return seriesReports;
|
|
66
|
+
});
|
|
67
|
+
if (!Array.isArray(seriesShape) || seriesShape.length === 0) {
|
|
68
|
+
return { verdict: 'fail', detail: 'no chart series found on the surface' };
|
|
69
|
+
}
|
|
70
|
+
const failing = seriesShape.filter((s) => !(s.nonColourCue && s.hasDirectLabel));
|
|
71
|
+
if (failing.length > 0) {
|
|
72
|
+
return { verdict: 'fail', detail: 'series missing non-colour cue or direct label: ' + JSON.stringify(failing) };
|
|
73
|
+
}
|
|
74
|
+
return { verdict: 'pass', detail: 'series with non-colour cue and direct label: ' + JSON.stringify(seriesShape.map((s) => ({ form: s.chartForm, name: s.name }))) };
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
id: 'AC-18103-1',
|
|
79
|
+
severity: 'block',
|
|
80
|
+
description: 'Text-alternative table: every chart landmark contains a table carrying the same values cell-per-value, focus-reachable through a labelled control',
|
|
81
|
+
run: async ({ browser, runtimeUrl }) => {
|
|
82
|
+
if (!browser) return { verdict: 'fail', detail: 'no packBrowser wired' };
|
|
83
|
+
await browser.goto(new URL('', runtimeUrl).toString());
|
|
84
|
+
const report = await browser.evaluate(() => {
|
|
85
|
+
const regions = Array.from(document.querySelectorAll('section.chartRegion[role="region"]'));
|
|
86
|
+
return regions.map((region) => {
|
|
87
|
+
const svg = region.querySelector('svg.chartSvg');
|
|
88
|
+
const chartForm = svg ? svg.getAttribute('data-chart-form') : null;
|
|
89
|
+
const table = region.querySelector('table.chartAltTable');
|
|
90
|
+
const showBtn = region.querySelector('button.chartShowAltTable');
|
|
91
|
+
let cellCount = 0;
|
|
92
|
+
let seriesCount = 0;
|
|
93
|
+
let xCount = 0;
|
|
94
|
+
const cellValues = [];
|
|
95
|
+
if (table) {
|
|
96
|
+
const headerCells = Array.from(table.querySelectorAll('thead th'));
|
|
97
|
+
seriesCount = Math.max(0, headerCells.length - 1);
|
|
98
|
+
const bodyRows = Array.from(table.querySelectorAll('tbody tr'));
|
|
99
|
+
xCount = bodyRows.length;
|
|
100
|
+
cellCount = bodyRows.reduce((acc, tr) => acc + tr.querySelectorAll('td').length, 0);
|
|
101
|
+
bodyRows.forEach((tr) => {
|
|
102
|
+
Array.from(tr.querySelectorAll('td')).forEach((td) => cellValues.push(Number(td.textContent.trim())));
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
const svgValues = svg ? Array.from(svg.querySelectorAll('[data-y]')).map((el) => Number(el.getAttribute('data-y'))) : [];
|
|
106
|
+
const svgSeries = new Set();
|
|
107
|
+
if (svg) Array.from(svg.querySelectorAll('[data-series]')).forEach((el) => svgSeries.add(el.getAttribute('data-series')));
|
|
108
|
+
const valuesMatch = svgValues.length > 0 && svgValues.every((v) => cellValues.includes(v));
|
|
109
|
+
return {
|
|
110
|
+
chartForm,
|
|
111
|
+
hasTable: Boolean(table),
|
|
112
|
+
cellCount,
|
|
113
|
+
seriesCount,
|
|
114
|
+
xCount,
|
|
115
|
+
showButtonPresent: Boolean(showBtn),
|
|
116
|
+
valuesMatch,
|
|
117
|
+
seriesCountSvg: svgSeries.size,
|
|
118
|
+
};
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
if (!Array.isArray(report) || report.length === 0) {
|
|
122
|
+
return { verdict: 'fail', detail: 'no chart regions found on the surface' };
|
|
123
|
+
}
|
|
124
|
+
const missingTable = report.filter((r) => !r.hasTable);
|
|
125
|
+
if (missingTable.length > 0) {
|
|
126
|
+
return { verdict: 'fail', detail: 'chart regions missing paired table: ' + JSON.stringify(missingTable.map((r) => r.chartForm)) };
|
|
127
|
+
}
|
|
128
|
+
const missingButton = report.filter((r) => !r.showButtonPresent);
|
|
129
|
+
if (missingButton.length > 0) {
|
|
130
|
+
return { verdict: 'fail', detail: 'chart regions missing show-table control: ' + JSON.stringify(missingButton.map((r) => r.chartForm)) };
|
|
131
|
+
}
|
|
132
|
+
const mismatched = report.filter((r) => r.hasTable && r.cellCount !== r.seriesCount * r.xCount);
|
|
133
|
+
if (mismatched.length > 0) {
|
|
134
|
+
return { verdict: 'fail', detail: 'chart tables do not honour cell-per-value: ' + JSON.stringify(mismatched) };
|
|
135
|
+
}
|
|
136
|
+
const valueMisses = report.filter((r) => r.hasTable && !r.valuesMatch);
|
|
137
|
+
if (valueMisses.length > 0) {
|
|
138
|
+
return { verdict: 'fail', detail: 'chart tables carry values that do not match the SVG data-y attributes: ' + JSON.stringify(valueMisses) };
|
|
139
|
+
}
|
|
140
|
+
return { verdict: 'pass', detail: 'chart regions with paired tables: ' + JSON.stringify(report.map((r) => ({ form: r.chartForm, rows: r.xCount, cols: r.seriesCount }))) };
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
id: 'AC-18104-1',
|
|
145
|
+
severity: 'block',
|
|
146
|
+
description: 'Keyboard traversal: every data point is tab-focusable, the announced string matches "series, x, y unit", and prefers-reduced-motion suppresses transitions',
|
|
147
|
+
run: async ({ browser, runtimeUrl }) => {
|
|
148
|
+
if (!browser) return { verdict: 'fail', detail: 'no packBrowser wired' };
|
|
149
|
+
await browser.goto(new URL('', runtimeUrl).toString());
|
|
150
|
+
const report = await browser.evaluate(() => {
|
|
151
|
+
const dataPoints = Array.from(document.querySelectorAll('.chartDataPoint'));
|
|
152
|
+
const focusable = dataPoints.filter((el) => el.getAttribute('tabindex') === '0');
|
|
153
|
+
const labelled = focusable.filter((el) => {
|
|
154
|
+
const label = el.getAttribute('aria-label');
|
|
155
|
+
if (!label) return false;
|
|
156
|
+
return /^[^,]+, [^,]+, [^ ]+ [^ ]+$/.test(label);
|
|
157
|
+
});
|
|
158
|
+
const sample = focusable.slice(0, 3).map((el) => ({
|
|
159
|
+
series: el.getAttribute('data-series'),
|
|
160
|
+
x: el.getAttribute('data-x'),
|
|
161
|
+
y: el.getAttribute('data-y'),
|
|
162
|
+
ariaLabel: el.getAttribute('aria-label'),
|
|
163
|
+
}));
|
|
164
|
+
const styles = Array.from(document.querySelectorAll('style')).map((s) => s.textContent).join('\n');
|
|
165
|
+
const hasReducedMotionRule = /@media\s*\(\s*prefers-reduced-motion:\s*reduce\s*\)/.test(styles) &&
|
|
166
|
+
/(transition-duration:\s*0|transition:\s*none|animation-duration:\s*0|animation:\s*none)/i.test(styles);
|
|
167
|
+
return {
|
|
168
|
+
totalDataPoints: dataPoints.length,
|
|
169
|
+
focusableCount: focusable.length,
|
|
170
|
+
labelledCount: labelled.length,
|
|
171
|
+
sample,
|
|
172
|
+
hasReducedMotionRule,
|
|
173
|
+
};
|
|
174
|
+
});
|
|
175
|
+
if (!report || report.totalDataPoints === 0) {
|
|
176
|
+
return { verdict: 'fail', detail: 'no data points found on the surface' };
|
|
177
|
+
}
|
|
178
|
+
if (report.focusableCount !== report.totalDataPoints) {
|
|
179
|
+
return { verdict: 'fail', detail: 'not every data point is focusable: total=' + report.totalDataPoints + ' focusable=' + report.focusableCount };
|
|
180
|
+
}
|
|
181
|
+
if (report.labelledCount !== report.focusableCount) {
|
|
182
|
+
return { verdict: 'fail', detail: 'aria-label format does not match "series, x, y unit" on every focusable data point: sample=' + JSON.stringify(report.sample) };
|
|
183
|
+
}
|
|
184
|
+
if (!report.hasReducedMotionRule) {
|
|
185
|
+
return { verdict: 'fail', detail: 'no prefers-reduced-motion rule suppressing transitions found in the rendered CSS' };
|
|
186
|
+
}
|
|
187
|
+
return { verdict: 'pass', detail: 'focusable data points=' + report.focusableCount + ' sample=' + JSON.stringify(report.sample.slice(0, 1)) + ' reduced-motion rule present' };
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
],
|
|
191
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# application-dashboard CHANGELOG
|
|
2
|
+
|
|
3
|
+
## 1.0.0 (visual round T-3, spec 2026-09-04)
|
|
4
|
+
|
|
5
|
+
- First ratified version of the shelf's application-dashboard blueprint. Five REQs (shell composition; primary-KPI top-left visual hierarchy on the F-scan across 1440, 1024 and 360; per-tile four-state contract with role region, aria-live polite and non-colour distinction; timeframe and filter chrome refetch fan-out with matching as-of stamp; export handle with format delegation to charts), seven USs binding runtime-observable ACs plus one on packaged-guidance adherence, three TACs (tile grid with CSS Grid position semantics and breakpoint reflow; timeframe picker and filter chrome with the fan-out contract; export handle with delegation to the application-charts render shell), three ADRs (primary-KPI kinds enum with elicited overrides; timeframe presets with recommendedDefault and elicited overrides plus auto-refresh off by default; export formats with recommendedDefault and elicited overrides). No new global topics.
|
|
6
|
+
- Ships `assets/guidance/dashboard-design.md`: eight sections (primary KPI placement; tile density and count limits; timeframe and filter chrome; loading, empty and error states; colour and contrast; when a table beats a chart, delegating to application-datatable; refresh cadence and staleness; anti-patterns) with five https-cited sources (NN/g dashboard design, Few, Tufte, GOV.UK Design System patterns, WCAG 2.2 Understanding docs). Each section names whether the rule hardens into an AC on this blueprint or stays operator guidance. The applying agent reads this asset at apply and the gate reviewer references it at ship.
|
|
7
|
+
- Ships `probe-packs/application-dashboard.pack.mjs`: three browser-verify checks anchored to blueprint AC ids, every check carrying a description field per spec section 9. `AC-19102-1` primary-KPI position by DOM order and CSS Grid position at 1440, 1024 and 360 (drives the new pack-browser `resize(width, height)` seam to each width). `AC-19104-1` timeframe refetch fan-out with matching boundary and as-of stamp (reads the request log from `window.__dashboardFetches` and reconciles with the `GET /__requests` endpoint). `AC-19103-1` per-tile four-state contract with role region, aria-live polite and non-colour distinction (drives `?tile=primary&state=<state>` for each of the four states). Third blueprint on the shelf that ships a Playwright probe pack under the T-0 runner extension.
|
|
8
|
+
- Ships a sample-app fixture at `packages/rcf-lite/test/fixtures/probe-pack-application-dashboard/` (dependency-free Node HTTP server) so the pack can be probed at the shelf's own gate; the fixture is the golden the gate reviewer drives, with `?break=kpi-position`, `?break=fanout` and `?break=state-aria` query switches for the negative runs, `?tile=<id>&state=<state>` state pinning for the four-state check, and `?asof=<iso>` for a fixed shell as-of stamp.
|
|
9
|
+
- Suggests the `logging` and `errorHandling` companions with the ratified spec's reasons. `providesRoles` absent, leaf blueprint per the loader contract (an empty array is refused, an omitted field marks the blueprint as a leaf).
|
|
10
|
+
- Extends the pack-browser seam (`packages/rcf-lite/src/browser-verify/pack-browser.js`) with a `resize(width, height)` method: on the MCP route the method calls the pinned Playwright MCP's `browser_resize` tool; on the project route it calls `page.setViewportSize({ width, height })`. The next blueprints on the shelf that ship breakpoint-scoped visual ACs (T-4 notifications-in-app, T-5 admin-console) reuse the same seam.
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# Dashboard blueprint (v1.0.0)
|
|
2
|
+
|
|
3
|
+
Vendor-neutral analytics-dashboard contract for a rcf-lite application. Ships the shell composition, the primary-KPI visual hierarchy, the per-tile four-state contract, the timeframe and filter chrome refetch fan-out, and the export handle with format delegation to charts. Consumes the application-charts render shell (TAC-1901) for every rendered chart; references application-datatable in the packaged design guidance's "when a table beats a chart" section. Ships a packaged design-guidance asset under `assets/guidance/dashboard-design.md` and a Playwright probe pack under `probe-packs/application-dashboard.pack.mjs` whose three checks are the runtime gate the delivery-ci-workflows runner drives (visual round spec 2026-09-04, section 5.3). No new global topics; suggests the `logging` and `errorHandling` companions. Third blueprint on the shelf that ships a Playwright probe pack under the T-0 runner extension.
|
|
4
|
+
|
|
5
|
+
## Apply
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
rcf define blueprint add <path-to>/blueprints/application-dashboard
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Applies namespaced contributions into the project tree and records `manifest.blueprints[]`. Consumes the `logging` and `errorHandling` companions when they resolve to an applied provider or a registered library; falls back to the shelf providers otherwise.
|
|
12
|
+
|
|
13
|
+
## Anatomy
|
|
14
|
+
|
|
15
|
+
| Piece | Where | What |
|
|
16
|
+
|---|---|---|
|
|
17
|
+
| Metadata | `blueprint.json` | Slug, version 1.0.0, category `application`, `suggestedCompanions: [{ logging }, { errorHandling }]`, `providesRoles: []`, 18 contributions in the 19xxx US band and 20xx ADR/TAC block |
|
|
18
|
+
| Doc set | `contributions/` | 5 REQs, 7 USs, 3 TACs, 3 ADRs, schema-valid and namespaced |
|
|
19
|
+
| Design guidance | `assets/guidance/dashboard-design.md` | Operator-and-agent-readable design guidance (eight sections; five https citations; each section names whether it hardens into an AC or stays guidance) |
|
|
20
|
+
| Probe pack | `probe-packs/application-dashboard.pack.mjs` | Three browser-verify checks anchored to AC-19102-1 (primary-KPI position by DOM order and CSS Grid position at 1440, 1024 and 360), AC-19104-1 (timeframe refetch fan-out with matching boundary and as-of stamp), AC-19103-1 (per-tile four-state contract with role region, aria-live polite and non-colour distinction) |
|
|
21
|
+
| Guide | `guide/application-dashboard.md` | Operator-facing: when to reach, when not, mechanism-reach gaps |
|
|
22
|
+
| Coordination vocabulary | `docs/topics.md` | Shelf id band registry update; no new global topics claimed |
|
|
23
|
+
|
|
24
|
+
## What it contributes, and what it deliberately does not
|
|
25
|
+
|
|
26
|
+
Contributed: REQ, US (with inline ACs), TAC, ADR, plus one shipped probe pack and one packaged design-guidance asset. Adherence is expressed as ACs; the blueprint ships no dashboard-framework source and no test files (the probe pack drives the real browser against the applying project's own runtime).
|
|
27
|
+
|
|
28
|
+
Deliberately not contributed: a choice of chart engine (the charts blueprint's ADR-1901 owns that); a chart-form set (application-charts REQ-001 owns that); a data-source contract (the applying project sources dashboard data through the applied `application-api-rest` blueprint or an equivalent); the sortable / filterable / exportable table (the applying `application-datatable` blueprint owns that; the dashboard's guidance section 6 delegates to it).
|
|
29
|
+
|
|
30
|
+
## The packaged design guidance
|
|
31
|
+
|
|
32
|
+
`assets/guidance/dashboard-design.md` is a shipped asset the applying agent reads at apply and the gate reviewer references at ship. Eight sections cover the ratified surface rules:
|
|
33
|
+
|
|
34
|
+
1. Primary KPI placement (hardens into AC-19102-1)
|
|
35
|
+
2. Tile density and count limits (stays operator guidance)
|
|
36
|
+
3. Timeframe and filter chrome (hardens into AC-19105-1 and the fan-out rule under AC-19104-1)
|
|
37
|
+
4. Loading, empty and error states (hardens into AC-19103-1 and AC-19103-2)
|
|
38
|
+
5. Colour and contrast (stays operator guidance for the tile row; hardens through the charts blueprint on the chart region)
|
|
39
|
+
6. When a table beats a chart, delegating to application-datatable (stays operator guidance)
|
|
40
|
+
7. Refresh cadence and staleness (hardens into AC-19104-1 and AC-19104-2)
|
|
41
|
+
8. Anti-patterns (stays operator guidance)
|
|
42
|
+
|
|
43
|
+
Five https-cited sources anchor the guidance: NN/g dashboard design, Few (Information Dashboard Design), Tufte (The Visual Display of Quantitative Information), GOV.UK Design System patterns, and WCAG 2.2 Understanding docs.
|
|
44
|
+
|
|
45
|
+
## The one runtime gate
|
|
46
|
+
|
|
47
|
+
`probe-packs/application-dashboard.pack.mjs` ships three checks the `rcf verify browser` runner invokes on any FBS whose surface matches the pack's `appliesTo` predicate (an FBS binding `TAC-2001-application-dashboard-tile-grid` or whose nav model routes name a dashboard path). Each check drives the real Playwright browser the runner provisions (through the pinned Playwright MCP or the consuming project's own `playwright` installation), reads the accessibility tree and the DOM, and returns a verdict. A failing block-severity check refuses ship through the existing `browserVerification` aggregate verdict.
|
|
48
|
+
|
|
49
|
+
The three shipped checks:
|
|
50
|
+
|
|
51
|
+
- `AC-19102-1` primary-KPI position by DOM order and CSS Grid position at 1440, 1024 and 360. Drives the pack-browser's `resize(width, height)` seam (new in T-3) to each of the three widths, reads DOM order and computed `grid-column-start`/`grid-row-start` on the primary tile, and asserts the top-left placement holds at every width.
|
|
52
|
+
- `AC-19104-1` timeframe refetch fan-out with matching boundary and as-of stamp. Clicks a second preset control, waits for the batch, reads the request log from `window.__dashboardFetches` and reconciles with the `GET /__requests` endpoint on the sample app, and asserts every fetch in the new batch carries the same `from`/`to`/`preset` trio and every tile's `data-as-of` matches the shell root in ISO-8601 form.
|
|
53
|
+
- `AC-19103-1` per-tile four-state contract. Drives the sample app's state-pinning switches (`?tile=primary&state=<state>`) for each of the four states, reads the accessibility tree and the DOM, and asserts every state carries `role="region"`, `aria-live="polite"`, the `data-tile-state` attribute, and a distinct non-colour visual cue.
|
|
54
|
+
|
|
55
|
+
The pack fires ONLY when its `appliesTo` returns true; a project whose FBS does not bind the tile-grid TAC or a dashboard route sees the pack recorded as `applicable: false` and no browser check runs.
|
|
56
|
+
|
|
57
|
+
## The shelf pattern for tile-state pinning and fetch capture
|
|
58
|
+
|
|
59
|
+
Two things this pack needs that the T-0 runner seam does not offer directly: viewport resize (added in T-3 through the `resize(width, height)` seam extension) and per-tile state mocking with fetch capture. Rather than adding a network interception seam, this blueprint documents a shelf pattern the applying project realises on its own runtime:
|
|
60
|
+
|
|
61
|
+
- **State pinning through query switches**: the sample app accepts `?tile=<id>&state=<state>` on the dashboard route so the pack can drive each of the four states without a synthetic-event seam. An applying project realises the same pattern through its own dev-mode query handling.
|
|
62
|
+
- **Fetch capture through a request log**: the sample app appends every fetch to `window.__dashboardFetches` (client-side) and to a server-side log the pack reads at `GET /__requests`. An applying project realises the same pattern through a dev-mode telemetry hook.
|
|
63
|
+
|
|
64
|
+
The pack-browser seam extension in T-3 adds `resize(width, height)`; the two patterns above stay a shelf convention this README documents.
|
|
65
|
+
|
|
66
|
+
## Elicited parameters (ADR-2001, ADR-2002, ADR-2003 and REQ notes)
|
|
67
|
+
|
|
68
|
+
The applying project elicits these at apply; the declarative ADR shape (`elicited: true`) records the intent on the manifest. The runner has no apply-time elicitation phase today (tracked as w-2026-09-04-dave-022, built in T-5); accept the declarative shape and gather the operator's answers by hand during the apply pass.
|
|
69
|
+
|
|
70
|
+
- **Primary-KPI kind** (ADR-2001): one of `revenue`, `active-users`, `error-rate`, `throughput`, `custom`. A `custom` value carries a short operator name in `data-kpi-name`.
|
|
71
|
+
- **Tile inventory with slots** (REQ-002 and TAC-2001): the tile list (primary tile plus up to seven supporting tiles) and each tile's slot on the CSS Grid.
|
|
72
|
+
- **Timeframe presets** (ADR-2002): the operator's preset set. Ships three by recommendedDefault (`last-7-days`, `last-30-days`, `quarter-to-date`); operator elicits an override.
|
|
73
|
+
- **Auto-refresh interval** (ADR-2002): OFF by default; operator elicits an interval in seconds if the surface needs unattended refresh.
|
|
74
|
+
- **Export formats** (ADR-2003): the operator's format list. Ships three by recommendedDefault (`csv`, `pdf`, `png-chart`); operator elicits an override.
|
|
75
|
+
- **Per-organisation vs per-user vs global scope** (REQ-004 note): the boundary on which the fan-out runs. A per-user dashboard passes the user id on every fetch; a per-organisation dashboard passes the tenant id; a global dashboard passes neither. Elicited at apply; recorded on the manifest.
|
|
76
|
+
|
|
77
|
+
## Standards trace
|
|
78
|
+
|
|
79
|
+
NN/g F-scan on primary-KPI placement (ADR-2001, guidance section 1). NN/g dashboard design on refresh cadence (guidance section 7). GOV.UK Design System download patterns and WCAG 1.3.1 on the export handle (ADR-2003, guidance section 3). WCAG 2.2 (1.4.1, 1.4.3, 1.4.11, 2.1.1, 4.1.3) on the four-state contract, filter chrome and colour discipline. `standardsTraceClause` on each ADR carries the primary source.
|
|
80
|
+
|
|
81
|
+
## Quality bar
|
|
82
|
+
|
|
83
|
+
Every dashboard surface renders the five shell regions (tile row, chart region, filter chrome, timeframe picker, export handle) as labelled `role="region"` elements. The primary KPI tile is first in DOM order and top-left in CSS Grid at 1440, 1024 and 360. Every tile carries the four-state contract with role region, aria-live polite, a `data-tile-state` attribute and a non-colour visual cue distinct per state. A timeframe preset change fans out one refetch per tile with the same from/to/preset trio and one shared `as of <ISO-8601>` stamp. Auto-refresh is off unless the elicited interval is set. The export handle is a labelled `<button>` opening an accessible format list, and PNG-of-chart delegates to the application-charts render shell.
|
|
84
|
+
|
|
85
|
+
## Known mechanism-reach gaps
|
|
86
|
+
|
|
87
|
+
Every runtime-observable AC that is not bound to a pack check appears here individually per the T-1 gate discipline (`blueprint-authoring-checklist.md` section 6.g): categories are not enough. The pack has three checks; every other runtime-observable AC on this blueprint is a mechanism-reach gap named below.
|
|
88
|
+
|
|
89
|
+
- **AC-19101-1 five-region shell composition**. The pack drives the primary-KPI region (AC-19102-1) and the timeframe region (AC-19104-1), which implies the shell renders at least those two, but the pack does not enumerate all five regions and their labels. A v1.1 minor bump could add a region-enumeration pre-check that walks `[data-region]` on the shell root.
|
|
90
|
+
- **AC-19101-2 chart region mounts through the charts shell**. The application-charts pack fires on the dashboard's chart route through its own `appliesTo` predicate; the dashboard's pack does not itself assert the chart-shell contract on the region. Project-side review is the current mechanism.
|
|
91
|
+
- **AC-19102-2 no-primary-KPI supersession fallback**. The pack asserts the primary KPI exists (AC-19102-1); the documentation-and-review contract on a surface with no primary KPI is not observable at runtime.
|
|
92
|
+
- **AC-19103-2 state-transition announcement**. The pack does not simulate the transition today (the runner has no synthetic-event seam beyond click / type / press). A v1.2 runner minor with an event-emit seam would close the class.
|
|
93
|
+
- **AC-19104-2 auto-refresh default and elicited interval**. The pack asserts `data-auto-refresh="off"` on the shell root at initial render (implied by the fixture); a runtime observation of the elicited-interval refresh cadence is not exercised. Project-side review carries the residual.
|
|
94
|
+
- **AC-19105-1 filter chrome accessible controls**. The pack does not enumerate filter controls today. A v1.1 minor bump could add a filter-control enumeration check.
|
|
95
|
+
- **AC-19105-2 filter fan-out**. The pack asserts the timeframe fan-out (AC-19104-1); the filter-change fan-out is a mechanism-reach gap. A v1.1 minor bump could add a paired filter-change check driving the filter chip and reading the same request log.
|
|
96
|
+
- **AC-19106-1 export handle accessible format list**. The pack does not open the export list today. A v1.1 minor bump could add a check that activates the export button, reads the exposed listbox and asserts the format entries.
|
|
97
|
+
- **AC-19106-2 PNG-of-chart delegation**. The pack browser has no download-capture seam today, so the PNG delegation is proven at project-side review. A v1.2 runner minor with a download-capture seam would close the class.
|
|
98
|
+
- **AC-19107-2 dashboard shape reflects guidance rules**. The pack asserts the specific attributes the fixture emits (primary-KPI kind, as-of stamp, auto-refresh default); a general check that a shipped surface honours the guidance's hardened rules is project-side review.
|
|
99
|
+
|
|
100
|
+
## The pack-browser resize seam extension
|
|
101
|
+
|
|
102
|
+
This blueprint's train adds a small, honest extension to the T-0 pack-browser seam: `resize(width, height)`. On the MCP route the method calls the pinned Playwright MCP's `browser_resize` tool; on the project route it calls `page.setViewportSize({ width, height })`. The extension lets the primary-KPI position check (AC-19102-1) drive the three ratified breakpoints (1440, 1024, 360) through the same browser handle. The next blueprints on the shelf that carry breakpoint-scoped visual ACs (T-4 notifications-in-app, T-5 admin-console) reuse the same seam.
|