rcf-lite 0.28.4 → 0.30.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 +194 -1
- package/bin/rcf.js +4 -0
- package/blueprints/application-account-settings/contributions/requirements/application-account-settings-req-001.json +1 -1
- package/blueprints/application-account-settings/contributions/requirements/application-account-settings-req-002.json +1 -1
- package/blueprints/application-account-settings/contributions/requirements/application-account-settings-req-003.json +1 -1
- package/blueprints/application-account-settings/contributions/requirements/application-account-settings-req-004.json +1 -1
- package/blueprints/application-account-settings/contributions/requirements/application-account-settings-req-005.json +1 -1
- package/blueprints/application-account-settings/contributions/requirements/application-account-settings-req-006.json +1 -1
- package/blueprints/application-account-settings/contributions/requirements/application-account-settings-req-007.json +1 -1
- package/blueprints/application-account-settings/contributions/requirements/application-account-settings-req-009.json +1 -1
- package/blueprints/application-account-settings/contributions/tacs/tac-2601-application-account-settings-shell.json +4 -4
- package/blueprints/application-account-settings/contributions/tacs/tac-2602-application-account-settings-capability-discovery.json +2 -2
- package/blueprints/application-account-settings/contributions/tacs/tac-2603-application-account-settings-hosted-ui-bridge.json +2 -2
- package/blueprints/application-account-settings/contributions/tacs/tac-2604-application-account-settings-session-store.json +7 -7
- package/blueprints/application-account-settings/contributions/user-stories/application-account-settings-us-25105.json +3 -15
- package/blueprints/application-account-settings/contributions/user-stories/application-account-settings-us-25106.json +2 -10
- package/blueprints/application-account-settings/contributions/user-stories/application-account-settings-us-25111.json +3 -6
- package/blueprints/application-account-settings/contributions/user-stories/application-account-settings-us-25112.json +4 -4
- package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-001.json +1 -1
- package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-002.json +1 -1
- package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-003.json +1 -1
- package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-004.json +1 -1
- package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-005.json +1 -1
- package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-006.json +1 -1
- package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-007.json +1 -1
- package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-008.json +1 -1
- package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-009.json +1 -1
- package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-014.json +1 -1
- package/blueprints/application-admin-console/contributions/tacs/tac-2201-application-admin-console-shell.json +4 -4
- package/blueprints/application-admin-console/contributions/tacs/tac-2202-application-admin-console-capability-discovery.json +7 -7
- package/blueprints/application-admin-console/contributions/tacs/tac-2203-application-admin-console-permission-matrix.json +2 -2
- package/blueprints/application-admin-console/contributions/tacs/tac-2204-application-admin-console-audit-view.json +2 -2
- package/blueprints/application-admin-console/contributions/tacs/tac-2214-application-admin-console-access-gated-signin-surface.json +3 -2
- package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21107.json +2 -2
- package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21111.json +3 -11
- package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21112.json +4 -4
- package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21815.json +2 -2
- package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21816.json +2 -2
- package/blueprints/application-api-rest/contributions/requirements/application-api-rest-req-001.json +1 -1
- package/blueprints/application-api-rest/contributions/requirements/application-api-rest-req-002.json +1 -2
- package/blueprints/application-api-rest/contributions/requirements/application-api-rest-req-004.json +1 -1
- package/blueprints/application-api-rest/contributions/requirements/application-api-rest-req-008.json +1 -1
- package/blueprints/application-api-rest/contributions/requirements/application-api-rest-req-016.json +1 -1
- package/blueprints/application-api-rest/contributions/tacs/tac-301-application-api-rest-request-pipeline.json +4 -4
- package/blueprints/application-api-rest/contributions/tacs/tac-302-application-api-rest-auth-middleware.json +4 -4
- package/blueprints/application-api-rest/contributions/tacs/tac-303-application-api-rest-contract-surface.json +4 -4
- package/blueprints/application-api-rest/contributions/tacs/tac-304-application-api-rest-resource-layer.json +4 -4
- package/blueprints/application-api-rest/contributions/tacs/tac-305-application-api-rest-observability.json +4 -4
- package/blueprints/application-api-rest/contributions/tacs/tac-306-application-api-rest-operability.json +4 -4
- package/blueprints/application-api-rest/contributions/user-stories/application-api-rest-us-2102.json +1 -1
- package/blueprints/application-api-rest/contributions/user-stories/application-api-rest-us-2103.json +1 -1
- package/blueprints/application-api-rest/contributions/user-stories/application-api-rest-us-2104.json +4 -4
- package/blueprints/application-api-rest/contributions/user-stories/application-api-rest-us-2105.json +2 -2
- package/blueprints/application-api-rest/contributions/user-stories/application-api-rest-us-2108.json +1 -1
- package/blueprints/application-api-rest/contributions/user-stories/application-api-rest-us-2110.json +1 -1
- package/blueprints/application-api-rest/contributions/user-stories/application-api-rest-us-2111.json +1 -1
- package/blueprints/application-api-rest/contributions/user-stories/application-api-rest-us-2118.json +1 -1
- package/blueprints/application-api-rest/contributions/user-stories/application-api-rest-us-2119.json +2 -2
- package/blueprints/application-charts/contributions/tacs/tac-1901-application-charts-render-shell.json +4 -4
- package/blueprints/application-charts/contributions/tacs/tac-1902-application-charts-keyboard-traversal.json +4 -4
- package/blueprints/application-charts/contributions/user-stories/application-charts-us-18105.json +1 -1
- package/blueprints/application-dashboard/contributions/tacs/tac-2001-application-dashboard-tile-grid.json +4 -4
- package/blueprints/application-dashboard/contributions/tacs/tac-2002-application-dashboard-filter-chrome.json +4 -4
- package/blueprints/application-dashboard/contributions/tacs/tac-2003-application-dashboard-export-handle.json +2 -2
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19106.json +1 -1
- package/blueprints/application-datatable/contributions/tacs/tac-1801-application-datatable-shell.json +4 -4
- package/blueprints/application-datatable/contributions/tacs/tac-1802-application-datatable-query-adapter.json +4 -4
- package/blueprints/application-datatable/contributions/tacs/tac-1803-application-datatable-selection-model.json +2 -2
- package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17101.json +1 -1
- package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17102.json +1 -1
- package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17103.json +1 -1
- package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17105.json +1 -1
- package/blueprints/application-empty-error-states/contributions/requirements/application-empty-error-states-req-001.json +1 -1
- package/blueprints/application-empty-error-states/contributions/requirements/application-empty-error-states-req-002.json +1 -1
- package/blueprints/application-empty-error-states/contributions/requirements/application-empty-error-states-req-003.json +1 -1
- package/blueprints/application-empty-error-states/contributions/requirements/application-empty-error-states-req-004.json +1 -1
- package/blueprints/application-empty-error-states/contributions/requirements/application-empty-error-states-req-005.json +2 -2
- package/blueprints/application-empty-error-states/contributions/requirements/application-empty-error-states-req-006.json +1 -1
- package/blueprints/application-empty-error-states/contributions/requirements/application-empty-error-states-req-007.json +2 -2
- package/blueprints/application-empty-error-states/contributions/tacs/tac-2301-application-empty-error-states-state-machine.json +5 -5
- package/blueprints/application-empty-error-states/contributions/tacs/tac-2302-application-empty-error-states-recovery-router.json +2 -2
- package/blueprints/application-empty-error-states/contributions/tacs/tac-2303-application-empty-error-states-offline-buffer.json +5 -5
- package/blueprints/application-error-handling/contributions/tacs/tac-1701-application-error-handling-boundary.json +6 -6
- package/blueprints/application-error-handling/contributions/tacs/tac-1702-application-error-handling-record-factory.json +4 -4
- package/blueprints/application-error-handling/contributions/user-stories/application-error-handling-us-16101.json +1 -1
- package/blueprints/application-error-handling/contributions/user-stories/application-error-handling-us-16107.json +4 -4
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-001.json +1 -1
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-002.json +1 -1
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-003.json +1 -1
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-004.json +1 -1
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-005.json +1 -1
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-006.json +2 -2
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-007.json +2 -2
- package/blueprints/application-file-upload/contributions/tacs/tac-2401-application-file-upload-input.json +7 -7
- package/blueprints/application-file-upload/contributions/tacs/tac-2402-application-file-upload-transport.json +8 -8
- package/blueprints/application-file-upload/contributions/tacs/tac-2403-application-file-upload-progress-announcer.json +11 -11
- package/blueprints/application-file-upload/contributions/user-stories/application-file-upload-us-23102.json +1 -1
- package/blueprints/application-file-upload/contributions/user-stories/application-file-upload-us-23105.json +1 -1
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-001.json +1 -1
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-002.json +1 -1
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-003.json +1 -1
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-004.json +1 -1
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-005.json +1 -1
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-006.json +2 -2
- package/blueprints/application-forms-wizard/contributions/tacs/tac-2501-application-forms-wizard-task-list.json +7 -7
- package/blueprints/application-forms-wizard/contributions/tacs/tac-2502-application-forms-wizard-error-summary.json +4 -4
- package/blueprints/application-forms-wizard/contributions/tacs/tac-2503-application-forms-wizard-draft-store.json +4 -4
- package/blueprints/application-forms-wizard/contributions/user-stories/application-forms-wizard-us-24101.json +1 -1
- package/blueprints/application-notifications-in-app/contributions/requirements/application-notifications-in-app-req-001.json +1 -1
- package/blueprints/application-notifications-in-app/contributions/requirements/application-notifications-in-app-req-002.json +1 -1
- package/blueprints/application-notifications-in-app/contributions/requirements/application-notifications-in-app-req-003.json +1 -1
- package/blueprints/application-notifications-in-app/contributions/requirements/application-notifications-in-app-req-004.json +1 -1
- package/blueprints/application-notifications-in-app/contributions/requirements/application-notifications-in-app-req-005.json +2 -2
- package/blueprints/application-notifications-in-app/contributions/requirements/application-notifications-in-app-req-006.json +2 -2
- package/blueprints/application-notifications-in-app/contributions/tacs/tac-2101-application-notifications-in-app-live-region.json +6 -6
- package/blueprints/application-notifications-in-app/contributions/tacs/tac-2102-application-notifications-in-app-centre.json +9 -9
- package/blueprints/application-notifications-in-app/contributions/tacs/tac-2103-application-notifications-in-app-preferences.json +4 -4
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20101.json +1 -1
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20102.json +1 -1
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20103.json +2 -2
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20105.json +4 -4
- package/blueprints/application-onboarding-tour/contributions/requirements/application-onboarding-tour-req-001.json +1 -1
- package/blueprints/application-onboarding-tour/contributions/requirements/application-onboarding-tour-req-002.json +1 -1
- package/blueprints/application-onboarding-tour/contributions/requirements/application-onboarding-tour-req-003.json +1 -1
- package/blueprints/application-onboarding-tour/contributions/requirements/application-onboarding-tour-req-004.json +1 -1
- package/blueprints/application-onboarding-tour/contributions/requirements/application-onboarding-tour-req-005.json +1 -1
- package/blueprints/application-onboarding-tour/contributions/requirements/application-onboarding-tour-req-006.json +1 -1
- package/blueprints/application-onboarding-tour/contributions/tacs/tac-2701-application-onboarding-tour-step-runner.json +4 -4
- package/blueprints/application-onboarding-tour/contributions/tacs/tac-2702-application-onboarding-tour-checklist-slot.json +2 -2
- package/blueprints/application-onboarding-tour/contributions/tacs/tac-2703-application-onboarding-tour-completion-store.json +2 -2
- package/blueprints/application-onboarding-tour/contributions/user-stories/application-onboarding-tour-us-26108.json +2 -2
- package/blueprints/application-spa/contributions/requirements/application-spa-req-004.json +1 -2
- package/blueprints/application-spa/contributions/requirements/application-spa-req-007.json +1 -1
- package/blueprints/application-spa/contributions/requirements/application-spa-req-014.json +1 -1
- package/blueprints/application-spa/contributions/requirements/application-spa-req-015.json +1 -1
- package/blueprints/application-spa/contributions/requirements/application-spa-req-017.json +1 -1
- package/blueprints/application-spa/contributions/requirements/application-spa-req-018.json +1 -1
- package/blueprints/application-spa/contributions/tacs/tac-201-application-spa-app-shell.json +4 -4
- package/blueprints/application-spa/contributions/tacs/tac-202-application-spa-theme-system.json +4 -4
- package/blueprints/application-spa/contributions/tacs/tac-207-application-spa-token-adherence-probe.json +6 -6
- package/blueprints/application-spa/contributions/tacs/tac-208-application-spa-icon-adherence-probe.json +6 -6
- package/blueprints/application-spa/contributions/tacs/tac-209-application-spa-csp-styled-adherence-probe.json +6 -6
- package/blueprints/application-spa/contributions/tacs/tac-210-application-spa-external-dependency-provisioning-probe.json +8 -8
- package/blueprints/application-spa/contributions/tacs/tac-211-application-spa-core-flow-e2e-probe.json +8 -8
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1101.json +2 -2
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1102.json +1 -1
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1107.json +1 -1
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1117.json +1 -1
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1129.json +4 -4
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1130.json +4 -4
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1131.json +1 -1
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1132.json +6 -6
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1133.json +5 -5
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1134.json +2 -2
- package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-001.json +1 -1
- package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-002.json +1 -1
- package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-003.json +1 -1
- package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-004.json +1 -1
- package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-005.json +1 -1
- package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-006.json +1 -1
- package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-007.json +1 -1
- package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-008.json +1 -1
- package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-009.json +1 -1
- package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-010.json +1 -1
- package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-011.json +1 -1
- package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-012.json +1 -1
- package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-013.json +1 -1
- package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-014.json +1 -1
- package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-015.json +1 -1
- package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-016.json +1 -1
- package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-017.json +1 -1
- package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-018.json +1 -1
- package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-019.json +1 -1
- package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-020.json +1 -1
- package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-021.json +1 -1
- package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-022.json +1 -1
- package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-023.json +1 -1
- package/blueprints/delivery-ci-workflows/contributions/tacs/tac-701-delivery-ci-workflows-gate-runner.json +6 -6
- package/blueprints/delivery-ci-workflows/contributions/tacs/tac-702-delivery-ci-workflows-gate-report.json +4 -4
- package/blueprints/delivery-ci-workflows/contributions/tacs/tac-703-delivery-ci-workflows-aggregate-report.json +4 -4
- package/blueprints/delivery-ci-workflows/contributions/tacs/tac-704-delivery-ci-workflows-workflow-materialiser.json +6 -6
- package/blueprints/delivery-ci-workflows/contributions/tacs/tac-705-delivery-ci-workflows-release-workflow.json +6 -6
- package/blueprints/delivery-ci-workflows/contributions/tacs/tac-706-delivery-ci-workflows-scheduled-audit.json +4 -4
- package/blueprints/delivery-ci-workflows/contributions/user-stories/delivery-ci-workflows-us-6101.json +1 -1
- package/blueprints/delivery-ci-workflows/contributions/user-stories/delivery-ci-workflows-us-6102.json +1 -1
- package/blueprints/delivery-ci-workflows/contributions/user-stories/delivery-ci-workflows-us-6103.json +1 -1
- package/blueprints/delivery-ci-workflows/contributions/user-stories/delivery-ci-workflows-us-6104.json +1 -1
- package/blueprints/delivery-ci-workflows/contributions/user-stories/delivery-ci-workflows-us-6106.json +1 -1
- package/blueprints/delivery-ci-workflows/contributions/user-stories/delivery-ci-workflows-us-6107.json +1 -1
- package/blueprints/delivery-ci-workflows/contributions/user-stories/delivery-ci-workflows-us-6109.json +1 -1
- package/blueprints/delivery-ci-workflows/contributions/user-stories/delivery-ci-workflows-us-6110.json +1 -1
- package/blueprints/delivery-ci-workflows/contributions/user-stories/delivery-ci-workflows-us-6111.json +1 -1
- package/blueprints/delivery-ci-workflows/contributions/user-stories/delivery-ci-workflows-us-6113.json +1 -1
- package/blueprints/delivery-ci-workflows/contributions/user-stories/delivery-ci-workflows-us-6115.json +1 -1
- package/blueprints/delivery-ci-workflows/contributions/user-stories/delivery-ci-workflows-us-6116.json +1 -1
- package/blueprints/delivery-ci-workflows/contributions/user-stories/delivery-ci-workflows-us-6117.json +1 -1
- package/blueprints/delivery-ci-workflows/contributions/user-stories/delivery-ci-workflows-us-6118.json +1 -1
- package/blueprints/delivery-ci-workflows/contributions/user-stories/delivery-ci-workflows-us-6119.json +1 -1
- package/blueprints/delivery-ci-workflows/contributions/user-stories/delivery-ci-workflows-us-6120.json +1 -1
- package/blueprints/delivery-ci-workflows/contributions/user-stories/delivery-ci-workflows-us-6122.json +1 -1
- package/blueprints/delivery-ci-workflows/contributions/user-stories/delivery-ci-workflows-us-6123.json +1 -1
- package/blueprints/delivery-ci-workflows/contributions/user-stories/delivery-ci-workflows-us-6124.json +1 -1
- package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-001.json +1 -1
- package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-002.json +1 -1
- package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-003.json +1 -1
- package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-004.json +1 -1
- package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-005.json +1 -1
- package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-006.json +1 -1
- package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-007.json +1 -1
- package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-008.json +1 -1
- package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-009.json +1 -1
- package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-010.json +1 -1
- package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-011.json +1 -1
- package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-012.json +1 -1
- package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-013.json +1 -1
- package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-014.json +1 -1
- package/blueprints/deploy-cloudflare-workers/contributions/tacs/tac-1301-deploy-cloudflare-workers-deploy-adapter.json +6 -6
- package/blueprints/deploy-cloudflare-workers/contributions/tacs/tac-1302-deploy-cloudflare-workers-wrangler-manifest.json +8 -8
- package/blueprints/deploy-cloudflare-workers/contributions/tacs/tac-1303-deploy-cloudflare-workers-preview-url-resolver.json +6 -6
- package/blueprints/deploy-cloudflare-workers/contributions/tacs/tac-1304-deploy-cloudflare-workers-promote-gate.json +8 -8
- package/blueprints/deploy-cloudflare-workers/contributions/tacs/tac-1305-deploy-cloudflare-workers-served-surface-verifier.json +8 -8
- package/blueprints/deploy-cloudflare-workers/contributions/tacs/tac-1306-deploy-cloudflare-workers-deploy-ci-workflows.json +8 -8
- package/blueprints/deploy-cloudflare-workers/contributions/user-stories/deploy-cloudflare-workers-us-12101.json +1 -1
- package/blueprints/deploy-cloudflare-workers/contributions/user-stories/deploy-cloudflare-workers-us-12102.json +2 -2
- package/blueprints/deploy-cloudflare-workers/contributions/user-stories/deploy-cloudflare-workers-us-12105.json +1 -1
- package/blueprints/deploy-cloudflare-workers/contributions/user-stories/deploy-cloudflare-workers-us-12109.json +1 -1
- package/blueprints/deploy-cloudflare-workers/contributions/user-stories/deploy-cloudflare-workers-us-12113.json +2 -2
- package/blueprints/deploy-cloudflare-workers/contributions/user-stories/deploy-cloudflare-workers-us-12114.json +1 -1
- package/blueprints/deploy-cloudflare-workers/contributions/user-stories/deploy-cloudflare-workers-us-12115.json +1 -1
- package/blueprints/deploy-hetzner-server/contributions/requirements/deploy-hetzner-server-req-001.json +1 -1
- package/blueprints/deploy-hetzner-server/contributions/requirements/deploy-hetzner-server-req-002.json +1 -1
- package/blueprints/deploy-hetzner-server/contributions/requirements/deploy-hetzner-server-req-003.json +1 -1
- package/blueprints/deploy-hetzner-server/contributions/requirements/deploy-hetzner-server-req-004.json +1 -1
- package/blueprints/deploy-hetzner-server/contributions/requirements/deploy-hetzner-server-req-005.json +1 -1
- package/blueprints/deploy-hetzner-server/contributions/requirements/deploy-hetzner-server-req-006.json +1 -1
- package/blueprints/deploy-hetzner-server/contributions/tacs/tac-3801-deploy-hetzner-server-provisioner.json +3 -2
- package/blueprints/deploy-hetzner-server/contributions/tacs/tac-3802-deploy-hetzner-server-manifest-schema.json +3 -2
- package/blueprints/deploy-hetzner-server/contributions/tacs/tac-3803-deploy-hetzner-server-cloud-init-template.json +3 -2
- package/blueprints/deploy-hetzner-server/contributions/tacs/tac-3804-deploy-hetzner-server-firewall-shape.json +3 -2
- package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37101.json +4 -4
- package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37102.json +3 -3
- package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37103.json +4 -4
- package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37104.json +2 -2
- package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37105.json +2 -2
- package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37106.json +3 -3
- package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37107.json +2 -2
- package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37108.json +2 -2
- package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37109.json +2 -2
- package/blueprints/edge-cloudflare-access/contributions/requirements/edge-cloudflare-access-req-001.json +1 -1
- package/blueprints/edge-cloudflare-access/contributions/requirements/edge-cloudflare-access-req-002.json +1 -1
- package/blueprints/edge-cloudflare-access/contributions/requirements/edge-cloudflare-access-req-003.json +1 -1
- package/blueprints/edge-cloudflare-access/contributions/requirements/edge-cloudflare-access-req-004.json +1 -1
- package/blueprints/edge-cloudflare-access/contributions/requirements/edge-cloudflare-access-req-005.json +1 -1
- package/blueprints/edge-cloudflare-access/contributions/requirements/edge-cloudflare-access-req-006.json +1 -1
- package/blueprints/edge-cloudflare-access/contributions/requirements/edge-cloudflare-access-req-007.json +1 -1
- package/blueprints/edge-cloudflare-access/contributions/tacs/tac-3501-edge-cloudflare-access-jwt-validator.json +6 -4
- package/blueprints/edge-cloudflare-access/contributions/tacs/tac-3502-edge-cloudflare-access-application-declaration.json +3 -2
- package/blueprints/edge-cloudflare-access/contributions/tacs/tac-3503-edge-cloudflare-access-policy-shape.json +3 -2
- package/blueprints/edge-cloudflare-access/contributions/tacs/tac-3504-edge-cloudflare-access-audit-sink.json +3 -2
- package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34101.json +1 -1
- package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34102.json +5 -5
- package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34103.json +1 -1
- package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34104.json +3 -3
- package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34105.json +1 -1
- package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34106.json +1 -1
- package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34107.json +5 -5
- package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34110.json +1 -1
- package/blueprints/edge-cloudflare-rate-limiting/contributions/requirements/edge-cloudflare-rate-limiting-req-001.json +1 -1
- package/blueprints/edge-cloudflare-rate-limiting/contributions/requirements/edge-cloudflare-rate-limiting-req-002.json +1 -1
- package/blueprints/edge-cloudflare-rate-limiting/contributions/requirements/edge-cloudflare-rate-limiting-req-003.json +1 -1
- package/blueprints/edge-cloudflare-rate-limiting/contributions/requirements/edge-cloudflare-rate-limiting-req-004.json +1 -1
- package/blueprints/edge-cloudflare-rate-limiting/contributions/requirements/edge-cloudflare-rate-limiting-req-005.json +1 -1
- package/blueprints/edge-cloudflare-rate-limiting/contributions/tacs/tac-3701-edge-cloudflare-rate-limiting-manifest-schema.json +6 -4
- package/blueprints/edge-cloudflare-rate-limiting/contributions/tacs/tac-3702-edge-cloudflare-rate-limiting-management-surface-doc.json +3 -2
- package/blueprints/edge-cloudflare-rate-limiting/contributions/tacs/tac-3703-edge-cloudflare-rate-limiting-drift-audit-runner.json +3 -2
- package/blueprints/edge-cloudflare-rate-limiting/contributions/user-stories/edge-cloudflare-rate-limiting-us-36101.json +2 -2
- package/blueprints/edge-cloudflare-rate-limiting/contributions/user-stories/edge-cloudflare-rate-limiting-us-36103.json +1 -1
- package/blueprints/edge-cloudflare-rate-limiting/contributions/user-stories/edge-cloudflare-rate-limiting-us-36104.json +6 -6
- package/blueprints/edge-cloudflare-rate-limiting/contributions/user-stories/edge-cloudflare-rate-limiting-us-36106.json +2 -2
- package/blueprints/edge-cloudflare-tunnel/contributions/requirements/edge-cloudflare-tunnel-req-001.json +1 -1
- package/blueprints/edge-cloudflare-tunnel/contributions/requirements/edge-cloudflare-tunnel-req-002.json +1 -1
- package/blueprints/edge-cloudflare-tunnel/contributions/requirements/edge-cloudflare-tunnel-req-003.json +1 -1
- package/blueprints/edge-cloudflare-tunnel/contributions/requirements/edge-cloudflare-tunnel-req-004.json +1 -1
- package/blueprints/edge-cloudflare-tunnel/contributions/requirements/edge-cloudflare-tunnel-req-005.json +1 -1
- package/blueprints/edge-cloudflare-tunnel/contributions/requirements/edge-cloudflare-tunnel-req-006.json +1 -1
- package/blueprints/edge-cloudflare-tunnel/contributions/requirements/edge-cloudflare-tunnel-req-007.json +1 -1
- package/blueprints/edge-cloudflare-tunnel/contributions/tacs/tac-4001-edge-cloudflare-tunnel-connector-shape.json +3 -2
- package/blueprints/edge-cloudflare-tunnel/contributions/tacs/tac-4002-edge-cloudflare-tunnel-manifest-schema.json +3 -2
- package/blueprints/edge-cloudflare-tunnel/contributions/tacs/tac-4003-edge-cloudflare-tunnel-access-binding.json +3 -2
- package/blueprints/edge-cloudflare-tunnel/contributions/tacs/tac-4004-edge-cloudflare-tunnel-zone-and-hostname-apply.json +3 -2
- package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39101.json +3 -3
- package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39102.json +2 -2
- package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39103.json +4 -4
- package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39104.json +2 -2
- package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39105.json +2 -2
- package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39106.json +5 -5
- package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39107.json +2 -2
- package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39108.json +3 -3
- package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39109.json +4 -4
- package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39110.json +3 -3
- package/blueprints/edge-cloudflare-turnstile/contributions/requirements/edge-cloudflare-turnstile-req-001.json +1 -1
- package/blueprints/edge-cloudflare-turnstile/contributions/requirements/edge-cloudflare-turnstile-req-002.json +1 -1
- package/blueprints/edge-cloudflare-turnstile/contributions/requirements/edge-cloudflare-turnstile-req-003.json +1 -1
- package/blueprints/edge-cloudflare-turnstile/contributions/requirements/edge-cloudflare-turnstile-req-004.json +1 -1
- package/blueprints/edge-cloudflare-turnstile/contributions/requirements/edge-cloudflare-turnstile-req-005.json +1 -1
- package/blueprints/edge-cloudflare-turnstile/contributions/tacs/tac-3601-edge-cloudflare-turnstile-widget-mount.json +3 -2
- package/blueprints/edge-cloudflare-turnstile/contributions/tacs/tac-3602-edge-cloudflare-turnstile-server-verifier.json +9 -6
- package/blueprints/edge-cloudflare-turnstile/contributions/tacs/tac-3603-edge-cloudflare-turnstile-magic-link-hook.json +3 -2
- package/blueprints/edge-cloudflare-turnstile/contributions/user-stories/edge-cloudflare-turnstile-us-35101.json +3 -3
- package/blueprints/edge-cloudflare-turnstile/contributions/user-stories/edge-cloudflare-turnstile-us-35102.json +4 -4
- package/blueprints/edge-cloudflare-turnstile/contributions/user-stories/edge-cloudflare-turnstile-us-35103.json +6 -6
- package/blueprints/edge-cloudflare-turnstile/contributions/user-stories/edge-cloudflare-turnstile-us-35104.json +2 -2
- package/blueprints/edge-cloudflare-turnstile/contributions/user-stories/edge-cloudflare-turnstile-us-35105.json +1 -1
- package/blueprints/email-smtp-resend/contributions/requirements/email-smtp-resend-req-001.json +1 -1
- package/blueprints/email-smtp-resend/contributions/requirements/email-smtp-resend-req-002.json +1 -1
- package/blueprints/email-smtp-resend/contributions/requirements/email-smtp-resend-req-003.json +1 -1
- package/blueprints/email-smtp-resend/contributions/requirements/email-smtp-resend-req-004.json +1 -1
- package/blueprints/email-smtp-resend/contributions/requirements/email-smtp-resend-req-005.json +1 -1
- package/blueprints/email-smtp-resend/contributions/requirements/email-smtp-resend-req-006.json +1 -1
- package/blueprints/email-smtp-resend/contributions/tacs/tac-401-email-smtp-resend-send-adapter.json +8 -8
- package/blueprints/email-smtp-resend/contributions/tacs/tac-402-email-smtp-resend-webhook-verifier.json +10 -10
- package/blueprints/email-smtp-resend/contributions/user-stories/email-smtp-resend-us-4101.json +1 -1
- package/blueprints/email-smtp-resend/contributions/user-stories/email-smtp-resend-us-4102.json +1 -1
- package/blueprints/email-smtp-resend/contributions/user-stories/email-smtp-resend-us-4103.json +1 -1
- package/blueprints/email-smtp-resend/contributions/user-stories/email-smtp-resend-us-4105.json +1 -1
- package/blueprints/email-smtp-resend/contributions/user-stories/email-smtp-resend-us-4106.json +2 -2
- package/blueprints/jobs-background/contributions/requirements/jobs-background-req-001.json +1 -1
- package/blueprints/jobs-background/contributions/requirements/jobs-background-req-002.json +1 -1
- package/blueprints/jobs-background/contributions/requirements/jobs-background-req-003.json +1 -1
- package/blueprints/jobs-background/contributions/requirements/jobs-background-req-004.json +1 -1
- package/blueprints/jobs-background/contributions/requirements/jobs-background-req-005.json +1 -1
- package/blueprints/jobs-background/contributions/requirements/jobs-background-req-006.json +1 -1
- package/blueprints/jobs-background/contributions/tacs/tac-3101-jobs-background-job-definition.json +4 -4
- package/blueprints/jobs-background/contributions/tacs/tac-3102-jobs-background-scheduler.json +6 -6
- package/blueprints/jobs-background/contributions/tacs/tac-3103-jobs-background-run-log.json +6 -6
- package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30101.json +1 -1
- package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30102.json +3 -3
- package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30103.json +1 -1
- package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30104.json +4 -4
- package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30105.json +1 -1
- package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30106.json +1 -1
- package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30107.json +1 -1
- package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30108.json +1 -1
- package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30109.json +1 -1
- package/blueprints/messaging-queue-cloudflare/contributions/requirements/messaging-queue-cloudflare-req-001.json +1 -1
- package/blueprints/messaging-queue-cloudflare/contributions/requirements/messaging-queue-cloudflare-req-002.json +1 -1
- package/blueprints/messaging-queue-cloudflare/contributions/requirements/messaging-queue-cloudflare-req-003.json +1 -1
- package/blueprints/messaging-queue-cloudflare/contributions/requirements/messaging-queue-cloudflare-req-004.json +1 -1
- package/blueprints/messaging-queue-cloudflare/contributions/requirements/messaging-queue-cloudflare-req-005.json +1 -1
- package/blueprints/messaging-queue-cloudflare/contributions/requirements/messaging-queue-cloudflare-req-006.json +1 -1
- package/blueprints/messaging-queue-cloudflare/contributions/tacs/tac-3001-messaging-queue-cloudflare-producer-facade.json +6 -6
- package/blueprints/messaging-queue-cloudflare/contributions/tacs/tac-3002-messaging-queue-cloudflare-consumer-registration.json +2 -2
- package/blueprints/messaging-queue-cloudflare/contributions/tacs/tac-3003-messaging-queue-cloudflare-event-sink.json +2 -2
- package/blueprints/messaging-queue-cloudflare/contributions/user-stories/messaging-queue-cloudflare-us-29101.json +1 -1
- package/blueprints/messaging-queue-cloudflare/contributions/user-stories/messaging-queue-cloudflare-us-29102.json +1 -1
- package/blueprints/messaging-queue-cloudflare/contributions/user-stories/messaging-queue-cloudflare-us-29103.json +1 -1
- package/blueprints/messaging-queue-cloudflare/contributions/user-stories/messaging-queue-cloudflare-us-29104.json +2 -2
- package/blueprints/messaging-queue-cloudflare/contributions/user-stories/messaging-queue-cloudflare-us-29105.json +1 -1
- package/blueprints/messaging-queue-cloudflare/contributions/user-stories/messaging-queue-cloudflare-us-29106.json +2 -2
- package/blueprints/messaging-queue-cloudflare/contributions/user-stories/messaging-queue-cloudflare-us-29107.json +1 -1
- package/blueprints/messaging-queue-cloudflare/contributions/user-stories/messaging-queue-cloudflare-us-29108.json +1 -1
- package/blueprints/object-storage-s3/contributions/requirements/object-storage-s3-req-001.json +1 -1
- package/blueprints/object-storage-s3/contributions/requirements/object-storage-s3-req-002.json +1 -1
- package/blueprints/object-storage-s3/contributions/requirements/object-storage-s3-req-003.json +1 -1
- package/blueprints/object-storage-s3/contributions/requirements/object-storage-s3-req-004.json +1 -1
- package/blueprints/object-storage-s3/contributions/requirements/object-storage-s3-req-005.json +1 -1
- package/blueprints/object-storage-s3/contributions/requirements/object-storage-s3-req-006.json +1 -1
- package/blueprints/object-storage-s3/contributions/requirements/object-storage-s3-req-101.json +1 -1
- package/blueprints/object-storage-s3/contributions/tacs/tac-2901-object-storage-s3-facade.json +6 -6
- package/blueprints/object-storage-s3/contributions/tacs/tac-2902-object-storage-s3-multipart-uploader.json +2 -2
- package/blueprints/object-storage-s3/contributions/tacs/tac-2903-object-storage-s3-event-sink.json +2 -2
- package/blueprints/object-storage-s3/contributions/tacs/tac-2904-object-storage-s3-hetzner-endpoint-helper.json +2 -2
- package/blueprints/object-storage-s3/contributions/user-stories/object-storage-s3-us-28101.json +1 -1
- package/blueprints/object-storage-s3/contributions/user-stories/object-storage-s3-us-28102.json +1 -1
- package/blueprints/object-storage-s3/contributions/user-stories/object-storage-s3-us-28103.json +2 -2
- package/blueprints/object-storage-s3/contributions/user-stories/object-storage-s3-us-28104.json +1 -1
- package/blueprints/object-storage-s3/contributions/user-stories/object-storage-s3-us-28105.json +2 -2
- package/blueprints/object-storage-s3/contributions/user-stories/object-storage-s3-us-28106.json +1 -1
- package/blueprints/object-storage-s3/contributions/user-stories/object-storage-s3-us-28110.json +1 -1
- package/blueprints/observability-essentials/contributions/requirements/observability-essentials-req-001.json +1 -1
- package/blueprints/observability-essentials/contributions/requirements/observability-essentials-req-002.json +1 -1
- package/blueprints/observability-essentials/contributions/requirements/observability-essentials-req-003.json +1 -1
- package/blueprints/observability-essentials/contributions/requirements/observability-essentials-req-004.json +1 -1
- package/blueprints/observability-essentials/contributions/requirements/observability-essentials-req-005.json +1 -1
- package/blueprints/observability-essentials/contributions/requirements/observability-essentials-req-006.json +1 -1
- package/blueprints/observability-essentials/contributions/requirements/observability-essentials-req-007.json +1 -1
- package/blueprints/observability-essentials/contributions/requirements/observability-essentials-req-008.json +1 -1
- package/blueprints/observability-essentials/contributions/requirements/observability-essentials-req-009.json +1 -1
- package/blueprints/observability-essentials/contributions/requirements/observability-essentials-req-010.json +1 -1
- package/blueprints/observability-essentials/contributions/tacs/tac-801-observability-essentials-liveness-probe.json +4 -4
- package/blueprints/observability-essentials/contributions/tacs/tac-802-observability-essentials-readiness-probe.json +12 -12
- package/blueprints/observability-essentials/contributions/tacs/tac-803-observability-essentials-status-page.json +6 -6
- package/blueprints/observability-essentials/contributions/tacs/tac-804-observability-essentials-notification-outcome.json +8 -8
- package/blueprints/observability-essentials/contributions/user-stories/observability-essentials-us-7101.json +1 -1
- package/blueprints/observability-essentials/contributions/user-stories/observability-essentials-us-7103.json +3 -3
- package/blueprints/observability-essentials/contributions/user-stories/observability-essentials-us-7106.json +2 -2
- package/blueprints/observability-essentials/contributions/user-stories/observability-essentials-us-7107.json +1 -1
- package/blueprints/observability-logging/contributions/requirements/observability-logging-req-001.json +1 -1
- package/blueprints/observability-logging/contributions/requirements/observability-logging-req-002.json +1 -1
- package/blueprints/observability-logging/contributions/requirements/observability-logging-req-003.json +1 -1
- package/blueprints/observability-logging/contributions/requirements/observability-logging-req-004.json +1 -1
- package/blueprints/observability-logging/contributions/requirements/observability-logging-req-005.json +1 -1
- package/blueprints/observability-logging/contributions/requirements/observability-logging-req-006.json +8 -2
- package/blueprints/observability-logging/contributions/tacs/tac-1601-observability-logging-logger-factory.json +6 -6
- package/blueprints/observability-logging/contributions/tacs/tac-1602-observability-logging-redaction-boundary.json +2 -2
- package/blueprints/observability-logging/contributions/user-stories/observability-logging-us-15101.json +4 -4
- package/blueprints/observability-logging/contributions/user-stories/observability-logging-us-15103.json +2 -2
- package/blueprints/observability-logging/contributions/user-stories/observability-logging-us-15104.json +2 -2
- package/blueprints/observability-logging/contributions/user-stories/observability-logging-us-15105.json +1 -1
- package/blueprints/observability-logging/contributions/user-stories/observability-logging-us-15106.json +1 -1
- package/blueprints/observability-logging/contributions/user-stories/observability-logging-us-15107.json +2 -2
- package/blueprints/observability-logging/contributions/user-stories/observability-logging-us-15108.json +1 -1
- package/blueprints/observability-logging/contributions/user-stories/observability-logging-us-15109.json +3 -3
- package/blueprints/observability-probe-endpoints/contributions/requirements/observability-probe-endpoints-req-001.json +1 -1
- package/blueprints/observability-probe-endpoints/contributions/requirements/observability-probe-endpoints-req-002.json +1 -1
- package/blueprints/observability-probe-endpoints/contributions/requirements/observability-probe-endpoints-req-003.json +1 -1
- package/blueprints/observability-probe-endpoints/contributions/requirements/observability-probe-endpoints-req-004.json +1 -1
- package/blueprints/observability-probe-endpoints/contributions/requirements/observability-probe-endpoints-req-005.json +1 -1
- package/blueprints/observability-probe-endpoints/contributions/requirements/observability-probe-endpoints-req-006.json +1 -1
- package/blueprints/observability-probe-endpoints/contributions/requirements/observability-probe-endpoints-req-007.json +1 -1
- package/blueprints/observability-probe-endpoints/contributions/requirements/observability-probe-endpoints-req-008.json +1 -1
- package/blueprints/observability-probe-endpoints/contributions/tacs/tac-1501-observability-probe-endpoints-profile-resolver.json +6 -6
- package/blueprints/observability-probe-endpoints/contributions/tacs/tac-1502-observability-probe-endpoints-handler-set.json +4 -4
- package/blueprints/observability-probe-endpoints/contributions/tacs/tac-1503-observability-probe-endpoints-listener-topology.json +6 -6
- package/blueprints/observability-probe-endpoints/contributions/tacs/tac-1504-observability-probe-endpoints-non-http-adapters.json +4 -4
- package/blueprints/observability-probe-endpoints/contributions/user-stories/observability-probe-endpoints-us-14101.json +2 -2
- package/blueprints/observability-probe-endpoints/contributions/user-stories/observability-probe-endpoints-us-14102.json +1 -1
- package/blueprints/observability-probe-endpoints/contributions/user-stories/observability-probe-endpoints-us-14105.json +3 -3
- package/blueprints/persistence-data-d1/contributions/requirements/persistence-data-d1-req-001.json +1 -1
- package/blueprints/persistence-data-d1/contributions/requirements/persistence-data-d1-req-002.json +1 -1
- package/blueprints/persistence-data-d1/contributions/requirements/persistence-data-d1-req-003.json +1 -1
- package/blueprints/persistence-data-d1/contributions/requirements/persistence-data-d1-req-004.json +1 -1
- package/blueprints/persistence-data-d1/contributions/requirements/persistence-data-d1-req-005.json +1 -1
- package/blueprints/persistence-data-d1/contributions/requirements/persistence-data-d1-req-006.json +1 -1
- package/blueprints/persistence-data-d1/contributions/requirements/persistence-data-d1-req-007.json +1 -1
- package/blueprints/persistence-data-d1/contributions/tacs/tac-1401-persistence-data-d1-facade.json +6 -6
- package/blueprints/persistence-data-d1/contributions/tacs/tac-1402-persistence-data-d1-migration-catalog.json +4 -4
- package/blueprints/persistence-data-d1/contributions/tacs/tac-1403-persistence-data-d1-deploy-gate.json +4 -4
- package/blueprints/persistence-data-d1/contributions/tacs/tac-1404-persistence-data-d1-recovery-runner.json +4 -4
- package/blueprints/persistence-data-d1/contributions/user-stories/persistence-data-d1-us-13101.json +2 -2
- package/blueprints/persistence-data-d1/contributions/user-stories/persistence-data-d1-us-13102.json +1 -1
- package/blueprints/persistence-data-d1/contributions/user-stories/persistence-data-d1-us-13107.json +2 -2
- package/blueprints/persistence-data-postgres/contributions/requirements/persistence-data-postgres-req-001.json +1 -1
- package/blueprints/persistence-data-postgres/contributions/requirements/persistence-data-postgres-req-002.json +1 -1
- package/blueprints/persistence-data-postgres/contributions/requirements/persistence-data-postgres-req-003.json +1 -1
- package/blueprints/persistence-data-postgres/contributions/requirements/persistence-data-postgres-req-004.json +1 -1
- package/blueprints/persistence-data-postgres/contributions/requirements/persistence-data-postgres-req-005.json +1 -1
- package/blueprints/persistence-data-postgres/contributions/requirements/persistence-data-postgres-req-006.json +1 -1
- package/blueprints/persistence-data-postgres/contributions/requirements/persistence-data-postgres-req-007.json +1 -1
- package/blueprints/persistence-data-postgres/contributions/tacs/tac-2801-persistence-data-postgres-facade.json +6 -6
- package/blueprints/persistence-data-postgres/contributions/tacs/tac-2802-persistence-data-postgres-migration-runner.json +4 -4
- package/blueprints/persistence-data-postgres/contributions/tacs/tac-2803-persistence-data-postgres-transaction-helper.json +2 -2
- package/blueprints/persistence-data-postgres/contributions/tacs/tac-2804-persistence-data-postgres-recovery-runner.json +4 -4
- package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27101.json +1 -1
- package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27102.json +4 -4
- package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27103.json +1 -1
- package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27104.json +2 -2
- package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27105.json +1 -1
- package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27106.json +1 -1
- package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27107.json +1 -1
- package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27108.json +1 -1
- package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27109.json +1 -1
- package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27110.json +1 -1
- package/blueprints/persistence-data-sqlite/contributions/requirements/persistence-data-sqlite-req-001.json +1 -1
- package/blueprints/persistence-data-sqlite/contributions/requirements/persistence-data-sqlite-req-002.json +1 -1
- package/blueprints/persistence-data-sqlite/contributions/requirements/persistence-data-sqlite-req-003.json +1 -1
- package/blueprints/persistence-data-sqlite/contributions/requirements/persistence-data-sqlite-req-004.json +1 -1
- package/blueprints/persistence-data-sqlite/contributions/requirements/persistence-data-sqlite-req-005.json +1 -1
- package/blueprints/persistence-data-sqlite/contributions/requirements/persistence-data-sqlite-req-006.json +1 -1
- package/blueprints/persistence-data-sqlite/contributions/requirements/persistence-data-sqlite-req-007.json +1 -1
- package/blueprints/persistence-data-sqlite/contributions/requirements/persistence-data-sqlite-req-008.json +1 -1
- package/blueprints/persistence-data-sqlite/contributions/requirements/persistence-data-sqlite-req-009.json +1 -1
- package/blueprints/persistence-data-sqlite/contributions/requirements/persistence-data-sqlite-req-010.json +1 -1
- package/blueprints/persistence-data-sqlite/contributions/requirements/persistence-data-sqlite-req-011.json +1 -1
- package/blueprints/persistence-data-sqlite/contributions/tacs/tac-601-persistence-data-sqlite-store.json +6 -6
- package/blueprints/persistence-data-sqlite/contributions/tacs/tac-602-persistence-data-sqlite-migration-runner.json +2 -2
- package/blueprints/persistence-data-sqlite/contributions/tacs/tac-603-persistence-data-sqlite-migration-catalog.json +4 -4
- package/blueprints/persistence-data-sqlite/contributions/tacs/tac-604-persistence-data-sqlite-backup-runner.json +2 -2
- package/blueprints/persistence-data-sqlite/contributions/user-stories/persistence-data-sqlite-us-5101.json +2 -2
- package/blueprints/persistence-data-sqlite/contributions/user-stories/persistence-data-sqlite-us-5103.json +1 -1
- package/blueprints/persistence-data-sqlite/contributions/user-stories/persistence-data-sqlite-us-5104.json +1 -1
- package/blueprints/persistence-data-sqlite/contributions/user-stories/persistence-data-sqlite-us-5106.json +1 -1
- package/blueprints/persistence-data-sqlite/contributions/user-stories/persistence-data-sqlite-us-5110.json +2 -2
- package/blueprints/persistence-data-sqlite/contributions/user-stories/persistence-data-sqlite-us-5111.json +1 -1
- package/blueprints/platform-cloudflare-cron-triggers/contributions/requirements/platform-cloudflare-cron-triggers-req-001.json +1 -1
- package/blueprints/platform-cloudflare-cron-triggers/contributions/requirements/platform-cloudflare-cron-triggers-req-002.json +1 -1
- package/blueprints/platform-cloudflare-cron-triggers/contributions/requirements/platform-cloudflare-cron-triggers-req-003.json +1 -1
- package/blueprints/platform-cloudflare-cron-triggers/contributions/requirements/platform-cloudflare-cron-triggers-req-004.json +1 -1
- package/blueprints/platform-cloudflare-cron-triggers/contributions/tacs/tac-3301-platform-cloudflare-cron-triggers-scheduled-handler.json +6 -1
- package/blueprints/platform-cloudflare-cron-triggers/contributions/tacs/tac-3302-platform-cloudflare-cron-triggers-expression-router.json +9 -2
- package/blueprints/platform-cloudflare-cron-triggers/contributions/tacs/tac-3303-platform-cloudflare-cron-triggers-event-sink.json +6 -1
- package/blueprints/platform-cloudflare-cron-triggers/contributions/user-stories/platform-cloudflare-cron-triggers-us-32101.json +6 -6
- package/blueprints/platform-cloudflare-cron-triggers/contributions/user-stories/platform-cloudflare-cron-triggers-us-32102.json +5 -5
- package/blueprints/platform-cloudflare-cron-triggers/contributions/user-stories/platform-cloudflare-cron-triggers-us-32103.json +3 -3
- package/blueprints/platform-cloudflare-cron-triggers/contributions/user-stories/platform-cloudflare-cron-triggers-us-32104.json +4 -4
- package/blueprints/platform-cloudflare-cron-triggers/contributions/user-stories/platform-cloudflare-cron-triggers-us-32105.json +4 -4
- package/blueprints/platform-cloudflare-cron-triggers/contributions/user-stories/platform-cloudflare-cron-triggers-us-32106.json +4 -4
- package/blueprints/platform-cloudflare-cron-triggers/contributions/user-stories/platform-cloudflare-cron-triggers-us-32107.json +3 -3
- package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-001.json +1 -1
- package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-002.json +1 -1
- package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-003.json +1 -1
- package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-004.json +1 -1
- package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-005.json +1 -1
- package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-006.json +1 -1
- package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-007.json +1 -1
- package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-008.json +1 -1
- package/blueprints/platform-cloudflare-durable-objects/contributions/tacs/tac-3401-platform-cloudflare-durable-objects-namespace-facade.json +6 -4
- package/blueprints/platform-cloudflare-durable-objects/contributions/tacs/tac-3402-platform-cloudflare-durable-objects-single-cell-shape.json +6 -4
- package/blueprints/platform-cloudflare-durable-objects/contributions/tacs/tac-3403-platform-cloudflare-durable-objects-alarm-handler.json +6 -4
- package/blueprints/platform-cloudflare-durable-objects/contributions/tacs/tac-3404-platform-cloudflare-durable-objects-websocket-hub.json +6 -4
- package/blueprints/platform-cloudflare-durable-objects/contributions/tacs/tac-3405-platform-cloudflare-durable-objects-event-sink.json +3 -2
- package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33101.json +5 -5
- package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33102.json +4 -4
- package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33103.json +5 -5
- package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33104.json +5 -5
- package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33105.json +5 -5
- package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33106.json +4 -4
- package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33107.json +3 -3
- package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33108.json +5 -5
- package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33109.json +3 -3
- package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33110.json +4 -4
- package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33111.json +3 -3
- package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33112.json +3 -3
- package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33113.json +5 -5
- package/blueprints/platform-cloudflare-kv/contributions/requirements/platform-cloudflare-kv-req-001.json +1 -1
- package/blueprints/platform-cloudflare-kv/contributions/requirements/platform-cloudflare-kv-req-002.json +1 -1
- package/blueprints/platform-cloudflare-kv/contributions/requirements/platform-cloudflare-kv-req-003.json +1 -1
- package/blueprints/platform-cloudflare-kv/contributions/requirements/platform-cloudflare-kv-req-004.json +1 -1
- package/blueprints/platform-cloudflare-kv/contributions/requirements/platform-cloudflare-kv-req-005.json +1 -1
- package/blueprints/platform-cloudflare-kv/contributions/requirements/platform-cloudflare-kv-req-006.json +1 -1
- package/blueprints/platform-cloudflare-kv/contributions/requirements/platform-cloudflare-kv-req-007.json +1 -1
- package/blueprints/platform-cloudflare-kv/contributions/tacs/tac-3201-platform-cloudflare-kv-facade.json +3 -2
- package/blueprints/platform-cloudflare-kv/contributions/tacs/tac-3202-platform-cloudflare-kv-cache-aside.json +3 -2
- package/blueprints/platform-cloudflare-kv/contributions/tacs/tac-3203-platform-cloudflare-kv-event-sink.json +3 -2
- package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31101.json +4 -4
- package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31102.json +3 -3
- package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31103.json +4 -4
- package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31104.json +4 -4
- package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31105.json +4 -4
- package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31106.json +3 -3
- package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31107.json +3 -3
- package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31108.json +3 -3
- package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31109.json +4 -4
- package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31110.json +5 -5
- package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31111.json +5 -5
- package/blueprints/platform-docker-compose-host/contributions/requirements/platform-docker-compose-host-req-001.json +1 -1
- package/blueprints/platform-docker-compose-host/contributions/requirements/platform-docker-compose-host-req-002.json +1 -1
- package/blueprints/platform-docker-compose-host/contributions/requirements/platform-docker-compose-host-req-003.json +1 -1
- package/blueprints/platform-docker-compose-host/contributions/requirements/platform-docker-compose-host-req-004.json +1 -1
- package/blueprints/platform-docker-compose-host/contributions/requirements/platform-docker-compose-host-req-005.json +1 -1
- package/blueprints/platform-docker-compose-host/contributions/requirements/platform-docker-compose-host-req-006.json +1 -1
- package/blueprints/platform-docker-compose-host/contributions/requirements/platform-docker-compose-host-req-007.json +1 -1
- package/blueprints/platform-docker-compose-host/contributions/tacs/tac-3901-platform-docker-compose-host-compose-layout.json +3 -2
- package/blueprints/platform-docker-compose-host/contributions/tacs/tac-3902-platform-docker-compose-host-secrets-mount.json +3 -2
- package/blueprints/platform-docker-compose-host/contributions/tacs/tac-3903-platform-docker-compose-host-healthcheck-lint.json +3 -2
- package/blueprints/platform-docker-compose-host/contributions/tacs/tac-3904-platform-docker-compose-host-reverse-proxy-artefact.json +3 -2
- package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38101.json +5 -5
- package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38102.json +4 -4
- package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38103.json +4 -4
- package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38104.json +4 -4
- package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38105.json +3 -3
- package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38106.json +3 -3
- package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38107.json +3 -3
- package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38108.json +3 -3
- package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38109.json +3 -3
- package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38110.json +3 -3
- package/blueprints/security-auth-clerk/contributions/requirements/security-auth-clerk-req-001.json +1 -1
- package/blueprints/security-auth-clerk/contributions/requirements/security-auth-clerk-req-002.json +1 -1
- package/blueprints/security-auth-clerk/contributions/requirements/security-auth-clerk-req-003.json +1 -1
- package/blueprints/security-auth-clerk/contributions/requirements/security-auth-clerk-req-004.json +1 -1
- package/blueprints/security-auth-clerk/contributions/requirements/security-auth-clerk-req-006.json +1 -1
- package/blueprints/security-auth-clerk/contributions/requirements/security-auth-clerk-req-010.json +1 -1
- package/blueprints/security-auth-clerk/contributions/requirements/security-auth-clerk-req-011.json +1 -1
- package/blueprints/security-auth-clerk/contributions/tacs/tac-1001-security-auth-clerk-middleware.json +6 -6
- package/blueprints/security-auth-clerk/contributions/tacs/tac-1002-security-auth-clerk-authorisation-adapter.json +8 -3
- package/blueprints/security-auth-clerk/contributions/tacs/tac-1003-security-auth-clerk-session-verifier.json +8 -8
- package/blueprints/security-auth-clerk/contributions/user-stories/security-auth-clerk-us-9102.json +1 -1
- package/blueprints/security-auth-clerk/contributions/user-stories/security-auth-clerk-us-9108.json +1 -1
- package/blueprints/security-auth-clerk/contributions/user-stories/security-auth-clerk-us-9112.json +6 -6
- package/blueprints/security-auth-clerk/contributions/user-stories/security-auth-clerk-us-9113.json +6 -6
- package/blueprints/security-auth-keycloak/contributions/requirements/security-auth-keycloak-req-002.json +1 -1
- package/blueprints/security-auth-keycloak/contributions/requirements/security-auth-keycloak-req-003.json +1 -1
- package/blueprints/security-auth-keycloak/contributions/requirements/security-auth-keycloak-req-004.json +1 -1
- package/blueprints/security-auth-keycloak/contributions/requirements/security-auth-keycloak-req-005.json +1 -1
- package/blueprints/security-auth-keycloak/contributions/requirements/security-auth-keycloak-req-006.json +1 -1
- package/blueprints/security-auth-keycloak/contributions/requirements/security-auth-keycloak-req-011.json +1 -1
- package/blueprints/security-auth-keycloak/contributions/requirements/security-auth-keycloak-req-013.json +1 -1
- package/blueprints/security-auth-keycloak/contributions/requirements/security-auth-keycloak-req-014.json +1 -1
- package/blueprints/security-auth-keycloak/contributions/requirements/security-auth-keycloak-req-015.json +1 -1
- package/blueprints/security-auth-keycloak/contributions/requirements/security-auth-keycloak-req-016.json +1 -1
- package/blueprints/security-auth-keycloak/contributions/requirements/security-auth-keycloak-req-017.json +1 -1
- package/blueprints/security-auth-keycloak/contributions/requirements/security-auth-keycloak-req-018.json +1 -1
- package/blueprints/security-auth-keycloak/contributions/requirements/security-auth-keycloak-req-019.json +1 -1
- package/blueprints/security-auth-keycloak/contributions/tacs/tac-1201-security-auth-keycloak-discovery-client.json +10 -10
- package/blueprints/security-auth-keycloak/contributions/tacs/tac-1202-security-auth-keycloak-jwt-verifier.json +8 -8
- package/blueprints/security-auth-keycloak/contributions/tacs/tac-1203-security-auth-keycloak-introspection-client.json +8 -8
- package/blueprints/security-auth-keycloak/contributions/tacs/tac-1204-security-auth-keycloak-provider-router.json +6 -6
- package/blueprints/security-auth-keycloak/contributions/tacs/tac-1205-security-auth-keycloak-role-adapter.json +4 -4
- package/blueprints/security-auth-keycloak/contributions/user-stories/security-auth-keycloak-us-11102.json +1 -1
- package/blueprints/security-auth-keycloak/contributions/user-stories/security-auth-keycloak-us-11103.json +2 -2
- package/blueprints/security-auth-keycloak/contributions/user-stories/security-auth-keycloak-us-11104.json +1 -1
- package/blueprints/security-auth-keycloak/contributions/user-stories/security-auth-keycloak-us-11106.json +3 -3
- package/blueprints/security-auth-keycloak/contributions/user-stories/security-auth-keycloak-us-11111.json +2 -2
- package/blueprints/security-auth-keycloak/contributions/user-stories/security-auth-keycloak-us-11114.json +1 -1
- package/blueprints/security-auth-keycloak/contributions/user-stories/security-auth-keycloak-us-11115.json +5 -5
- package/blueprints/security-auth-keycloak/contributions/user-stories/security-auth-keycloak-us-11116.json +7 -7
- package/blueprints/security-auth-keycloak/contributions/user-stories/security-auth-keycloak-us-11117.json +7 -7
- package/blueprints/security-auth-keycloak/contributions/user-stories/security-auth-keycloak-us-11118.json +7 -7
- package/blueprints/security-auth-keycloak/contributions/user-stories/security-auth-keycloak-us-11119.json +7 -7
- package/blueprints/security-auth-keycloak/contributions/user-stories/security-auth-keycloak-us-11120.json +6 -6
- package/blueprints/security-auth-magic-link/contributions/requirements/security-auth-magic-link-req-002.json +1 -1
- package/blueprints/security-auth-magic-link/contributions/requirements/security-auth-magic-link-req-003.json +1 -1
- package/blueprints/security-auth-magic-link/contributions/requirements/security-auth-magic-link-req-004.json +1 -1
- package/blueprints/security-auth-magic-link/contributions/requirements/security-auth-magic-link-req-005.json +1 -1
- package/blueprints/security-auth-magic-link/contributions/requirements/security-auth-magic-link-req-008.json +1 -1
- package/blueprints/security-auth-magic-link/contributions/requirements/security-auth-magic-link-req-009.json +1 -1
- package/blueprints/security-auth-magic-link/contributions/requirements/security-auth-magic-link-req-010.json +1 -1
- package/blueprints/security-auth-magic-link/contributions/requirements/security-auth-magic-link-req-011.json +1 -1
- package/blueprints/security-auth-magic-link/contributions/tacs/tac-501-security-auth-magic-link-manager.json +6 -6
- package/blueprints/security-auth-magic-link/contributions/tacs/tac-502-security-auth-magic-link-session-manager.json +6 -6
- package/blueprints/security-auth-magic-link/contributions/tacs/tac-503-security-auth-magic-link-login-routes.json +10 -10
- package/blueprints/security-auth-magic-link/contributions/tacs/tac-504-security-auth-magic-link-email-delivery-adapter.json +2 -2
- package/blueprints/security-auth-magic-link/contributions/tacs/tac-505-security-auth-magic-link-principal-registry.json +2 -2
- package/blueprints/security-auth-magic-link/contributions/user-stories/security-auth-magic-link-us-3111.json +2 -2
- package/blueprints/security-auth-oauth2/contributions/requirements/security-auth-oauth2-req-002.json +1 -1
- package/blueprints/security-auth-oauth2/contributions/requirements/security-auth-oauth2-req-003.json +1 -1
- package/blueprints/security-auth-oauth2/contributions/requirements/security-auth-oauth2-req-005.json +1 -1
- package/blueprints/security-auth-oauth2/contributions/requirements/security-auth-oauth2-req-006.json +1 -1
- package/blueprints/security-auth-oauth2/contributions/requirements/security-auth-oauth2-req-008.json +1 -1
- package/blueprints/security-auth-oauth2/contributions/requirements/security-auth-oauth2-req-009.json +1 -1
- package/blueprints/security-auth-oauth2/contributions/requirements/security-auth-oauth2-req-011.json +1 -1
- package/blueprints/security-auth-oauth2/contributions/requirements/security-auth-oauth2-req-012.json +1 -1
- package/blueprints/security-auth-oauth2/contributions/requirements/security-auth-oauth2-req-013.json +1 -1
- package/blueprints/security-auth-oauth2/contributions/tacs/tac-1101-security-auth-oauth2-flow-controller.json +24 -14
- package/blueprints/security-auth-oauth2/contributions/tacs/tac-1102-security-auth-oauth2-provider-adapter.json +4 -4
- package/blueprints/security-auth-oauth2/contributions/tacs/tac-1103-security-auth-oauth2-session-bridge.json +10 -10
- package/blueprints/security-auth-oauth2/contributions/tacs/tac-1104-security-auth-oauth2-provider-selector.json +8 -3
- package/blueprints/security-auth-oauth2/contributions/user-stories/security-auth-oauth2-us-10111.json +1 -1
- package/blueprints/security-auth-oauth2/contributions/user-stories/security-auth-oauth2-us-10112.json +1 -1
- package/blueprints/security-auth-oauth2/contributions/user-stories/security-auth-oauth2-us-10114.json +5 -5
- package/blueprints/security-secrets-management/contributions/requirements/security-secrets-management-req-001.json +1 -1
- package/blueprints/security-secrets-management/contributions/requirements/security-secrets-management-req-002.json +1 -1
- package/blueprints/security-secrets-management/contributions/requirements/security-secrets-management-req-003.json +1 -1
- package/blueprints/security-secrets-management/contributions/requirements/security-secrets-management-req-004.json +1 -1
- package/blueprints/security-secrets-management/contributions/requirements/security-secrets-management-req-005.json +1 -1
- package/blueprints/security-secrets-management/contributions/requirements/security-secrets-management-req-006.json +1 -1
- package/blueprints/security-secrets-management/contributions/requirements/security-secrets-management-req-007.json +1 -1
- package/blueprints/security-secrets-management/contributions/requirements/security-secrets-management-req-008.json +1 -1
- package/blueprints/security-secrets-management/contributions/requirements/security-secrets-management-req-009.json +1 -1
- package/blueprints/security-secrets-management/contributions/tacs/tac-901-security-secrets-management-manager-client.json +8 -8
- package/blueprints/security-secrets-management/contributions/tacs/tac-902-security-secrets-management-manifest.json +4 -4
- package/blueprints/security-secrets-management/contributions/tacs/tac-903-security-secrets-management-env-reflector.json +4 -4
- package/blueprints/security-secrets-management/contributions/tacs/tac-904-security-secrets-management-rotation-gate.json +8 -8
- package/blueprints/security-secrets-management/contributions/tacs/tac-905-security-secrets-management-agent-cli.json +4 -4
- package/fixtures/canary-manifest.json +9 -9
- package/guidance/define-draft-shapes.md +89 -0
- package/guidance/define-intake.md +97 -0
- package/guidance/define-intent.md +107 -0
- package/guidance/define-litmus.md +102 -0
- package/guidance/discover-prototype.md +67 -0
- package/guidance/discovery-prototypes.md +69 -0
- package/guidance/harness-template.md +34 -0
- package/guidance/managed/agent-instructions-block.hash +1 -1
- package/guidance/managed/agent-instructions-block.md +34 -0
- package/guidance/manifest.json +10 -2
- package/package.json +1 -1
- package/rcf/adrs/adr-4124-define-freeze-verb.json +30 -0
- package/rcf/adrs/adr-4126-persona-tagged-blockers-two-levels.json +40 -0
- package/rcf/adrs/adr-4127-readiness-tab-order-and-register.json +40 -0
- package/rcf/adrs/adr-4129-questions-harness-driven-loop.json +25 -0
- package/rcf/adrs/adr-4130-intake-harness-split-tool-scanned.json +20 -0
- package/rcf/adrs/adr-4131-gates-bite-ack-recorded-override.json +30 -0
- package/rcf/adrs/adr-4132-prototypes-in-discovery-as-evidence.json +20 -0
- package/rcf/adrs/adr-4133-dag-dependency-depth-layout.json +40 -0
- package/rcf/adrs/adr-4134-index-json-route.json +35 -0
- package/rcf/adrs/adr-4135-readiness-po-register-and-adapter.json +35 -0
- package/rcf/adrs/adr-4136-embedding-host-fixture.json +35 -0
- package/rcf/code-nodes/cn-725.json +18 -2
- package/rcf/code-nodes/cn-726.json +10 -2
- package/rcf/code-nodes/cn-727.json +13 -4
- package/rcf/code-nodes/cn-728.json +18 -2
- package/rcf/code-nodes/cn-729.json +10 -2
- package/rcf/code-nodes/cn-730.json +13 -3
- package/rcf/code-nodes/cn-731.json +20 -0
- package/rcf/code-nodes/cn-732.json +14 -0
- package/rcf/code-nodes/cn-733.json +14 -0
- package/rcf/code-nodes/cn-734.json +14 -0
- package/rcf/code-nodes/cn-735.json +20 -0
- package/rcf/code-nodes/cn-736.json +14 -0
- package/rcf/code-nodes/cn-737.json +14 -0
- package/rcf/code-nodes/cn-738.json +14 -0
- package/rcf/code-nodes/cn-739.json +18 -0
- package/rcf/code-nodes/cn-740.json +19 -0
- package/rcf/code-nodes/cn-741.json +16 -0
- package/rcf/code-nodes/cn-742.json +16 -0
- package/rcf/code-nodes/cn-743.json +15 -0
- package/rcf/code-nodes/cn-744.json +22 -0
- package/rcf/code-nodes/cn-745.json +16 -0
- package/rcf/code-nodes/cn-746.json +14 -0
- package/rcf/code-nodes/cn-747.json +18 -0
- package/rcf/code-nodes/cn-748.json +16 -0
- package/rcf/code-nodes/cn-749.json +16 -0
- package/rcf/code-nodes/cn-750.json +15 -0
- package/rcf/code-nodes/cn-751.json +18 -0
- package/rcf/code-nodes/cn-752.json +14 -0
- package/rcf/code-nodes/cn-753.json +19 -0
- package/rcf/code-nodes/cn-754.json +17 -0
- package/rcf/code-nodes/cn-755.json +14 -0
- package/rcf/code-nodes/cn-756.json +15 -0
- package/rcf/code-nodes/cn-757.json +21 -0
- package/rcf/code-nodes/cn-758.json +16 -0
- package/rcf/code-nodes/cn-759.json +21 -0
- package/rcf/code-nodes/cn-760.json +19 -0
- package/rcf/code-nodes/cn-761.json +16 -0
- package/rcf/code-nodes/cn-762.json +18 -0
- package/rcf/code-nodes/cn-763.json +18 -0
- package/rcf/code-nodes/cn-764.json +15 -0
- package/rcf/code-nodes/cn-765.json +23 -0
- package/rcf/code-nodes/cn-766.json +17 -0
- package/rcf/code-nodes/cn-767.json +17 -0
- package/rcf/code-nodes/cn-768.json +19 -0
- package/rcf/code-nodes/cn-769.json +17 -0
- package/rcf/code-nodes/cn-770.json +18 -0
- package/rcf/fbs/fbs-196.json +13 -5
- package/rcf/fbs/fbs-198.json +42 -0
- package/rcf/fbs/fbs-199.json +59 -0
- package/rcf/fbs/fbs-200.json +46 -0
- package/rcf/fbs/fbs-201.json +49 -0
- package/rcf/fbs/fbs-202.json +170 -0
- package/rcf/fbs/fbs-203.json +100 -0
- package/rcf/requirements/req-002.json +2 -2
- package/rcf/requirements/req-173.json +2 -2
- package/rcf/requirements/req-174.json +10 -4
- package/rcf/requirements/req-175.json +10 -4
- package/rcf/requirements/req-176.json +25 -0
- package/rcf/requirements/req-177.json +31 -0
- package/rcf/requirements/req-178.json +31 -0
- package/rcf/requirements/req-179.json +31 -0
- package/rcf/requirements/req-180.json +31 -0
- package/rcf/requirements/req-181.json +31 -0
- package/rcf/requirements/req-182.json +25 -0
- package/rcf/requirements/req-186.json +25 -0
- package/rcf/requirements/req-187.json +31 -0
- package/rcf/requirements/req-188.json +25 -0
- package/rcf/tacs/tac-001.json +7 -7
- package/rcf/tacs/tac-002.json +23 -23
- package/rcf/tacs/tac-003.json +5 -5
- package/rcf/tacs/tac-004.json +9 -9
- package/rcf/tacs/tac-005.json +7 -7
- package/rcf/tacs/tac-006.json +21 -21
- package/rcf/tacs/tac-007.json +7 -7
- package/rcf/tacs/tac-008.json +7 -7
- package/rcf/tacs/tac-4101-feedback-cli.json +5 -5
- package/rcf/tacs/tac-4102-feedback-store.json +9 -9
- package/rcf/tacs/tac-4103-feedback-redact.json +5 -5
- package/rcf/tacs/tac-4104-feedback-fingerprint.json +3 -3
- package/rcf/tacs/tac-4105-feedback-render.json +7 -7
- package/rcf/tacs/tac-4106-feedback-destination.json +5 -5
- package/rcf/tacs/tac-4107-feedback-gh.json +7 -7
- package/rcf/tacs/tac-4108-feedback-hook.json +7 -7
- package/rcf/tacs/tac-4121-define-ledgers.json +16 -3
- package/rcf/tacs/tac-4122-define-gates.json +69 -5
- package/rcf/tacs/tac-4123-define-readiness.json +66 -4
- package/rcf/tacs/tac-4124-define-freeze.json +28 -0
- package/rcf/tacs/tac-4125-build-bundle-refuse-override-skip.json +43 -0
- package/rcf/tacs/tac-4126-define-validate-findings.json +32 -0
- package/rcf/tacs/tac-4127-readiness-view.json +49 -0
- package/rcf/tacs/tac-4128-define-guidance.json +59 -0
- package/rcf/tacs/tac-4129-define-questions.json +45 -0
- package/rcf/tacs/tac-4130-define-intake-brief.json +35 -0
- package/rcf/tacs/tac-4131-build-dag-view.json +39 -0
- package/rcf/tacs/tac-4132-id-lookup.json +42 -0
- package/rcf/tacs/tac-4133-readiness-po-layer.json +37 -0
- package/rcf/tacs/tac-4134-wespa-host-fixture.json +54 -0
- package/rcf/test-suites/ts-016.json +3 -3
- package/rcf/test-suites/ts-215.json +148 -4
- package/rcf/test-suites/ts-216.json +19 -3
- package/rcf/test-suites/ts-218.json +78 -0
- package/rcf/test-suites/ts-219.json +70 -0
- package/rcf/test-suites/ts-220.json +78 -0
- package/rcf/test-suites/ts-221.json +78 -0
- package/rcf/test-suites/ts-222.json +100 -0
- package/rcf/test-suites/ts-223.json +94 -0
- package/rcf/test-suites/ts-224.json +70 -0
- package/rcf/test-suites/ts-225.json +78 -0
- package/rcf/test-suites/ts-226.json +158 -0
- package/rcf/test-suites/ts-227.json +38 -0
- package/rcf/test-suites/ts-228.json +86 -0
- package/rcf/test-suites/ts-229.json +83 -0
- package/rcf/test-suites/ts-230.json +76 -0
- package/rcf/test-suites/ts-231.json +104 -0
- package/rcf/test-suites/ts-232.json +109 -0
- package/rcf/test-suites/ts-233.json +61 -0
- package/rcf/test-suites/ts-234.json +53 -0
- package/rcf/test-suites/ts-235.json +53 -0
- package/rcf/user-stories/us-17302.json +50 -0
- package/rcf/user-stories/us-17401.json +14 -2
- package/rcf/user-stories/us-17402.json +55 -0
- package/rcf/user-stories/us-17403.json +60 -0
- package/rcf/user-stories/us-17404.json +51 -0
- package/rcf/user-stories/us-17405.json +61 -0
- package/rcf/user-stories/us-17406.json +51 -0
- package/rcf/user-stories/us-17502.json +60 -0
- package/rcf/user-stories/us-17503.json +65 -0
- package/rcf/user-stories/us-17504.json +46 -0
- package/rcf/user-stories/us-17601.json +58 -0
- package/rcf/user-stories/us-17702.json +51 -0
- package/rcf/user-stories/us-17802.json +40 -0
- package/rcf/user-stories/us-17902.json +46 -0
- package/rcf/user-stories/us-18001.json +55 -0
- package/rcf/user-stories/us-18002.json +35 -0
- package/rcf/user-stories/us-18101.json +35 -0
- package/rcf/user-stories/us-18202.json +40 -0
- package/rcf/user-stories/us-18601.json +55 -0
- package/rcf/user-stories/us-18602.json +50 -0
- package/rcf/user-stories/us-18603.json +45 -0
- package/rcf/user-stories/us-18701.json +50 -0
- package/rcf/user-stories/us-18702.json +50 -0
- package/rcf/user-stories/us-18801.json +45 -0
- package/rcf/user-stories/us-204.json +59 -0
- package/rcf/user-stories/us-205.json +64 -0
- package/rcf/user-stories/us-206.json +54 -0
- package/releases/releases.yaml +21 -1
- package/src/blueprint/consistency-lint.js +72 -3
- package/src/cli/build.js +206 -3
- package/src/cli/freeze.js +780 -0
- package/src/cli/help.js +12 -0
- package/src/cli/ledger.js +228 -12
- package/src/cli/questions.js +288 -0
- package/src/cli/readiness.js +393 -74
- package/src/cli/validate.js +8 -0
- package/src/cli/view.js +29 -0
- package/src/define/concern-catalogue.js +130 -0
- package/src/define/freeze-record.js +104 -15
- package/src/define/ledgers.js +210 -11
- package/src/define/probe-runner.js +55 -0
- package/src/define/validate-findings.js +256 -0
- package/src/intake/index.js +1 -1
- package/src/intake/orchestrator.js +117 -0
- package/src/mcp/tools.js +354 -0
- package/src/query/delta.js +6 -0
- package/src/query/gates.js +1258 -48
- package/src/query/index.js +22 -3
- package/src/query/questions.js +438 -0
- package/src/query/readiness.js +427 -9
- package/src/query/refuse-on-admissibility.js +137 -4
- package/src/ruleset/ruleset.json +35 -0
- package/src/server/index.js +24 -2
- package/src/server/routes.js +68 -1
- package/src/setup/identity-seed.js +17 -0
- package/src/view/build-dag.js +563 -0
- package/src/view/components/badge.js +41 -0
- package/src/view/components/diff.js +72 -0
- package/src/view/components/doc-row.js +62 -0
- package/src/view/components/empty-state.js +35 -0
- package/src/view/components/entity-selector.js +137 -0
- package/src/view/components/filter-bar.js +97 -0
- package/src/view/components/findings-list.js +49 -0
- package/src/view/components/index.js +12 -0
- package/src/view/components/pill.js +46 -0
- package/src/view/components/sub-tab-strip.js +43 -0
- package/src/view/components/toast.js +25 -0
- package/src/view/components-fixture.js +265 -0
- package/src/view/doc-renderers/architecture.js +304 -0
- package/src/view/doc-renderers/build.js +160 -0
- package/src/view/doc-renderers/index.js +2 -0
- package/src/view/doc-renderers/prd.js +35 -6
- package/src/view/html-page.js +700 -602
- package/src/view/index.js +96 -3
- package/src/view/live-client.js +39 -6
- package/src/view/needs-work.js +79 -0
- package/src/view/page-init.js +2193 -0
- package/src/view/readiness/phrasebook.js +115 -0
- package/src/view/readiness/po-layer.js +288 -0
- package/src/view/readiness/question-adapter.js +329 -0
- package/src/view/readiness/stage-legend.js +71 -0
- package/src/view/readiness.js +505 -0
- package/src/view/style.css +2017 -382
- package/src/view/test-host/embed-client.js +121 -0
- package/src/view/test-host/fixture.js +183 -0
- package/src/view/test-host/lints.js +220 -0
- package/src/view/view-index.js +323 -0
|
@@ -0,0 +1,2193 @@
|
|
|
1
|
+
// Page init script. Classic (non-module) browser script extracted from
|
|
2
|
+
// the former inline <script> block in html-page.js: wespa (Dex,
|
|
3
|
+
// 2026-10-02) pins inline scripts by CSP hash, so the viewer now
|
|
4
|
+
// serves this logic as a cacheable asset at ./page-init.js and the
|
|
5
|
+
// shell page carries no inline script at all. PR 1 (viewer UI
|
|
6
|
+
// refresh) also folds in the shell contract:
|
|
7
|
+
// - Theme boot: read ?theme=light|dark|auto, stamp data-theme on
|
|
8
|
+
// <html>. Live changes arrive via postMessage from the embedding
|
|
9
|
+
// host as { type: "rcf-view-theme", theme: "light"|"dark" }; we
|
|
10
|
+
// check event.origin against our own and ignore anything else.
|
|
11
|
+
// The viewport media query handles theme=auto natively; explicit
|
|
12
|
+
// light/dark wins over the media query.
|
|
13
|
+
// - Embed boot: ?embed=1 stamps data-embed on <html>; the stylesheet
|
|
14
|
+
// hides the brand block and footer in that state and keeps the
|
|
15
|
+
// tab nav sticky.
|
|
16
|
+
// - Router: hash scheme #tab=&sub=&entity=&... with bare #REQ-002
|
|
17
|
+
// still working; every hash write preserves the host query string
|
|
18
|
+
// (?embed=1, ?theme=..., ?blueprint=..., ?ticket=...) so embed and
|
|
19
|
+
// theme survive every in-viewer navigation.
|
|
20
|
+
//
|
|
21
|
+
// Idempotent: live-client re-invokes rcfPage.init() after every SSE
|
|
22
|
+
// innerHTML swap of #rcf-live-content. All wiring guards with
|
|
23
|
+
// __rcfTabWired-style sentinels.
|
|
24
|
+
|
|
25
|
+
(function () {
|
|
26
|
+
var TABS = ['readiness', 'overview', 'requirements', 'architecture', 'build', 'product-map'];
|
|
27
|
+
var PM_GROUPS = ['shape', 'component', 'trace', 'capability', 'blueprint'];
|
|
28
|
+
var PM_STATUSES = ['all', 'draft', 'review', 'needsRevision', 'approved', 'superseded'];
|
|
29
|
+
// Partial-render cache: grouping -> HTML string. First fetch fills it,
|
|
30
|
+
// subsequent switches use the cache.
|
|
31
|
+
var pmPartialCache = {};
|
|
32
|
+
function pmCacheKey(group) { return group; }
|
|
33
|
+
|
|
34
|
+
// ---- shell: theme + embed ---------------------------------------------
|
|
35
|
+
|
|
36
|
+
function parseQuery(search) {
|
|
37
|
+
var out = {};
|
|
38
|
+
if (typeof search !== 'string' || search.length === 0) return out;
|
|
39
|
+
var raw = search.charAt(0) === '?' ? search.slice(1) : search;
|
|
40
|
+
if (raw.length === 0) return out;
|
|
41
|
+
var pairs = raw.split('&');
|
|
42
|
+
for (var i = 0; i < pairs.length; i += 1) {
|
|
43
|
+
var eq = pairs[i].indexOf('=');
|
|
44
|
+
var k = eq === -1 ? pairs[i] : pairs[i].slice(0, eq);
|
|
45
|
+
var v = eq === -1 ? '' : pairs[i].slice(eq + 1);
|
|
46
|
+
if (!k) continue;
|
|
47
|
+
try { out[decodeURIComponent(k)] = decodeURIComponent(v.replace(/\+/g, ' ')); }
|
|
48
|
+
catch (e) { out[k] = v; }
|
|
49
|
+
}
|
|
50
|
+
return out;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function applyTheme(t) {
|
|
54
|
+
var root = document.documentElement;
|
|
55
|
+
if (t === 'light' || t === 'dark') root.setAttribute('data-theme', t);
|
|
56
|
+
else root.removeAttribute('data-theme');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function applyEmbed(flag) {
|
|
60
|
+
var root = document.documentElement;
|
|
61
|
+
if (flag) root.setAttribute('data-embed', '1');
|
|
62
|
+
else root.removeAttribute('data-embed');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function initShellFromQuery() {
|
|
66
|
+
var q = parseQuery(window.location.search);
|
|
67
|
+
// theme: explicit light|dark wins, auto falls through to the
|
|
68
|
+
// :root:not([data-theme]) + @media prefers-color-scheme block in
|
|
69
|
+
// style.css. Absent stays light (the base :root tokens).
|
|
70
|
+
var theme = q.theme;
|
|
71
|
+
if (theme === 'light' || theme === 'dark' || theme === 'auto') applyTheme(theme === 'auto' ? null : theme);
|
|
72
|
+
// embed: any value other than exactly "1" is ignored.
|
|
73
|
+
applyEmbed(q.embed === '1');
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
var messageListenerWired = false;
|
|
77
|
+
function wireThemeMessages() {
|
|
78
|
+
if (messageListenerWired) return;
|
|
79
|
+
messageListenerWired = true;
|
|
80
|
+
window.addEventListener('message', function (ev) {
|
|
81
|
+
// Same-origin only: wespa reverse-proxies the viewer under its
|
|
82
|
+
// own origin, so a legitimate theme ping comes from the viewer's
|
|
83
|
+
// own origin. Anything else is a cross-origin posting we ignore.
|
|
84
|
+
if (!ev || ev.origin !== window.location.origin) return;
|
|
85
|
+
var data = ev.data || {};
|
|
86
|
+
if (data.type !== 'rcf-view-theme') return;
|
|
87
|
+
if (data.theme === 'light' || data.theme === 'dark') applyTheme(data.theme);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// ---- hash parsing + preservation --------------------------------------
|
|
92
|
+
|
|
93
|
+
function flashLookupTarget(el) {
|
|
94
|
+
if (!el || !el.classList) return;
|
|
95
|
+
try {
|
|
96
|
+
el.classList.remove('is-rcf-lookup-flash');
|
|
97
|
+
// Force reflow so the animation restarts on repeat picks.
|
|
98
|
+
void el.offsetWidth;
|
|
99
|
+
el.classList.add('is-rcf-lookup-flash');
|
|
100
|
+
setTimeout(function () { try { el.classList.remove('is-rcf-lookup-flash'); } catch (e) {} }, 1400);
|
|
101
|
+
} catch (e) {}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function parseHashParams(raw) {
|
|
105
|
+
var out = {};
|
|
106
|
+
if (!raw) return out;
|
|
107
|
+
var parts = raw.split('&');
|
|
108
|
+
for (var i = 0; i < parts.length; i += 1) {
|
|
109
|
+
var eq = parts[i].indexOf('=');
|
|
110
|
+
if (eq === -1) continue;
|
|
111
|
+
var k = parts[i].slice(0, eq);
|
|
112
|
+
var v = parts[i].slice(eq + 1);
|
|
113
|
+
if (k) out[k] = v;
|
|
114
|
+
}
|
|
115
|
+
return out;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Build a URL that keeps the host query untouched (?embed=, ?theme=,
|
|
119
|
+
// ?blueprint=, ?ticket=, ...) and only swaps the hash. Required by
|
|
120
|
+
// Dex's embed contract: embed/theme survive every in-viewer navigation.
|
|
121
|
+
function urlWithHash(hash) {
|
|
122
|
+
var base = window.location.pathname + window.location.search;
|
|
123
|
+
if (!hash) return base;
|
|
124
|
+
return base + (hash.charAt(0) === '#' ? hash : '#' + hash);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function writeHash(hash, replace) {
|
|
128
|
+
if (!window.history) return;
|
|
129
|
+
var fn = replace === false ? 'pushState' : 'replaceState';
|
|
130
|
+
if (typeof window.history[fn] !== 'function') return;
|
|
131
|
+
var next = urlWithHash(hash);
|
|
132
|
+
if (next === window.location.pathname + window.location.search + window.location.hash) return;
|
|
133
|
+
window.history[fn](null, '', next);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// ---- mermaid lifecycle ------------------------------------------------
|
|
137
|
+
|
|
138
|
+
function initMermaid() {
|
|
139
|
+
if (typeof window.mermaid !== 'undefined') {
|
|
140
|
+
window.mermaid.initialize({ startOnLoad: false, securityLevel: 'loose' });
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function runMermaidIn(container) {
|
|
145
|
+
if (!container || typeof window.mermaid === 'undefined') return;
|
|
146
|
+
var pending = container.querySelectorAll('.mermaid:not([data-processed="true"])');
|
|
147
|
+
if (pending.length === 0) return;
|
|
148
|
+
try {
|
|
149
|
+
window.mermaid.run({ nodes: Array.prototype.slice.call(pending) });
|
|
150
|
+
} catch (e) { /* swallow */ }
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// ---- tabs -------------------------------------------------------------
|
|
154
|
+
|
|
155
|
+
function tabButtons() {
|
|
156
|
+
return Array.prototype.slice.call(document.querySelectorAll('nav.tabs [role="tab"]'));
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function panelFor(name) {
|
|
160
|
+
return document.getElementById('tab-' + name);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function activateTab(name) {
|
|
164
|
+
if (TABS.indexOf(name) === -1) return false;
|
|
165
|
+
tabButtons().forEach(function (btn) {
|
|
166
|
+
var isTarget = btn.getAttribute('data-tab') === name;
|
|
167
|
+
btn.setAttribute('aria-selected', isTarget ? 'true' : 'false');
|
|
168
|
+
});
|
|
169
|
+
TABS.forEach(function (t) {
|
|
170
|
+
var p = panelFor(t);
|
|
171
|
+
if (!p) return;
|
|
172
|
+
if (t === name) {
|
|
173
|
+
p.removeAttribute('hidden');
|
|
174
|
+
runMermaidIn(p);
|
|
175
|
+
} else {
|
|
176
|
+
p.setAttribute('hidden', '');
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
return true;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function tabForNode(node) {
|
|
183
|
+
var cur = node;
|
|
184
|
+
while (cur && cur !== document.body) {
|
|
185
|
+
if (cur.getAttribute && cur.getAttribute('role') === 'tabpanel') {
|
|
186
|
+
var id = cur.id || '';
|
|
187
|
+
if (id.indexOf('tab-') === 0) return id.slice(4);
|
|
188
|
+
}
|
|
189
|
+
cur = cur.parentNode;
|
|
190
|
+
}
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function openAncestorDetails(node) {
|
|
195
|
+
var cur = node.parentNode;
|
|
196
|
+
while (cur && cur !== document.body) {
|
|
197
|
+
if (cur.tagName && cur.tagName.toLowerCase() === 'details') {
|
|
198
|
+
cur.open = true;
|
|
199
|
+
}
|
|
200
|
+
cur = cur.parentNode;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function findByDocId(id) {
|
|
205
|
+
if (!id) return null;
|
|
206
|
+
var byId = document.getElementById(id);
|
|
207
|
+
if (byId) return byId;
|
|
208
|
+
return document.querySelector('[data-doc-id="' + id.replace(/"/g, '\\\\"') + '"]');
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// ---- product map ------------------------------------------------------
|
|
212
|
+
|
|
213
|
+
function pmGroupPanel(name) {
|
|
214
|
+
return document.getElementById('pm-group-' + name);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function hydrateLazyGroup(name, cb) {
|
|
218
|
+
var panel = pmGroupPanel(name);
|
|
219
|
+
if (!panel) { if (cb) cb(false); return; }
|
|
220
|
+
if (panel.getAttribute('data-pm-lazy') !== 'true' && !pmPartialCache[pmCacheKey(name)]) {
|
|
221
|
+
if (cb) cb(true);
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
if (window.__rcfPmDirty) {
|
|
225
|
+
pmPartialCache = {};
|
|
226
|
+
window.__rcfPmDirty = false;
|
|
227
|
+
}
|
|
228
|
+
var cached = pmPartialCache[pmCacheKey(name)];
|
|
229
|
+
var heading = panel.querySelector('.pm-group-heading');
|
|
230
|
+
var headingHtml = heading ? heading.outerHTML : '';
|
|
231
|
+
if (cached) {
|
|
232
|
+
panel.innerHTML = headingHtml + cached;
|
|
233
|
+
panel.removeAttribute('data-pm-lazy');
|
|
234
|
+
wireProductMapWithin(panel);
|
|
235
|
+
if (cb) cb(true);
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
panel.setAttribute('data-pm-loading', 'true');
|
|
239
|
+
var xhr = new XMLHttpRequest();
|
|
240
|
+
// Dex / wespa 2026-10-02: asset references are relative so the
|
|
241
|
+
// reverse-proxy mount point can live anywhere under its origin.
|
|
242
|
+
xhr.open('GET', './product-map/' + name, true);
|
|
243
|
+
xhr.onreadystatechange = function () {
|
|
244
|
+
if (xhr.readyState !== 4) return;
|
|
245
|
+
panel.removeAttribute('data-pm-loading');
|
|
246
|
+
if (xhr.status >= 200 && xhr.status < 300) {
|
|
247
|
+
pmPartialCache[pmCacheKey(name)] = xhr.responseText;
|
|
248
|
+
panel.innerHTML = headingHtml + xhr.responseText;
|
|
249
|
+
panel.removeAttribute('data-pm-lazy');
|
|
250
|
+
wireProductMapWithin(panel);
|
|
251
|
+
if (cb) cb(true);
|
|
252
|
+
} else {
|
|
253
|
+
panel.setAttribute('data-pm-lazy', 'true');
|
|
254
|
+
if (cb) cb(false);
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
xhr.send();
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function activatePmGroup(name, opts) {
|
|
261
|
+
if (PM_GROUPS.indexOf(name) === -1) return false;
|
|
262
|
+
var buttons = document.querySelectorAll('.pm-group-btn');
|
|
263
|
+
for (var i = 0; i < buttons.length; i += 1) {
|
|
264
|
+
var btn = buttons[i];
|
|
265
|
+
var isTarget = btn.getAttribute('data-pm-group') === name;
|
|
266
|
+
btn.setAttribute('aria-selected', isTarget ? 'true' : 'false');
|
|
267
|
+
}
|
|
268
|
+
var panels = document.querySelectorAll('.pm-group');
|
|
269
|
+
for (var j = 0; j < panels.length; j += 1) {
|
|
270
|
+
var p = panels[j];
|
|
271
|
+
if (p.getAttribute('data-pm-group') === name) {
|
|
272
|
+
p.removeAttribute('hidden');
|
|
273
|
+
} else {
|
|
274
|
+
p.setAttribute('hidden', '');
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
var target = pmGroupPanel(name);
|
|
278
|
+
if (target && target.getAttribute('data-pm-lazy') === 'true') {
|
|
279
|
+
hydrateLazyGroup(name, function () {
|
|
280
|
+
if (opts && opts.after) opts.after();
|
|
281
|
+
applyPmStatusFilter(currentStatus());
|
|
282
|
+
});
|
|
283
|
+
} else {
|
|
284
|
+
if (opts && opts.after) opts.after();
|
|
285
|
+
applyPmStatusFilter(currentStatus());
|
|
286
|
+
}
|
|
287
|
+
return true;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
function currentGroup() {
|
|
291
|
+
var sel = document.querySelector('.pm-group-btn[aria-selected="true"]');
|
|
292
|
+
return sel ? sel.getAttribute('data-pm-group') : 'shape';
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
function currentStatus() {
|
|
296
|
+
var s = document.querySelector('.pm-status-select');
|
|
297
|
+
return s ? s.value : 'all';
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function currentOpenBuckets() {
|
|
301
|
+
var group = currentGroup();
|
|
302
|
+
var panel = pmGroupPanel(group);
|
|
303
|
+
if (!panel) return [];
|
|
304
|
+
var nodes = panel.querySelectorAll('details.pm-bucket[open]');
|
|
305
|
+
var out = [];
|
|
306
|
+
for (var i = 0; i < nodes.length; i += 1) {
|
|
307
|
+
var id = nodes[i].getAttribute('data-pm-bucket-id');
|
|
308
|
+
if (id) out.push(id);
|
|
309
|
+
}
|
|
310
|
+
return out;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
function applyPmStatusFilter(status) {
|
|
314
|
+
if (PM_STATUSES.indexOf(status) === -1) return false;
|
|
315
|
+
var select = document.querySelector('.pm-status-select');
|
|
316
|
+
if (select) select.value = status;
|
|
317
|
+
var reqCards = document.querySelectorAll('#tab-product-map [data-req-status]');
|
|
318
|
+
for (var i = 0; i < reqCards.length; i += 1) {
|
|
319
|
+
var card = reqCards[i];
|
|
320
|
+
var s = card.getAttribute('data-req-status') || '';
|
|
321
|
+
if (status === 'all' || s === status) {
|
|
322
|
+
card.removeAttribute('hidden');
|
|
323
|
+
} else {
|
|
324
|
+
card.setAttribute('hidden', '');
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
var buckets = document.querySelectorAll('#tab-product-map .pm-group:not([hidden]) details.pm-bucket');
|
|
328
|
+
var emptyCount = 0;
|
|
329
|
+
for (var k = 0; k < buckets.length; k += 1) {
|
|
330
|
+
var bk = buckets[k];
|
|
331
|
+
var visible = bk.querySelectorAll('[data-req-status]:not([hidden])');
|
|
332
|
+
var bodyEmpty = bk.querySelector('.pm-bucket-body') && bk.querySelector('.pm-bucket-body').children.length === 0;
|
|
333
|
+
var isEmpty = visible.length === 0 && !bodyEmpty;
|
|
334
|
+
var body = bk.querySelector('.pm-bucket-body');
|
|
335
|
+
var emptyNote = body ? body.querySelector('.pm-bucket-empty-filter') : null;
|
|
336
|
+
if (isEmpty && status !== 'all') {
|
|
337
|
+
if (body && !emptyNote) {
|
|
338
|
+
emptyNote = document.createElement('p');
|
|
339
|
+
emptyNote.className = 'pm-bucket-empty pm-bucket-empty-filter';
|
|
340
|
+
emptyNote.innerHTML = '<em>0 requirements match this filter.</em>';
|
|
341
|
+
body.appendChild(emptyNote);
|
|
342
|
+
}
|
|
343
|
+
bk.setAttribute('data-pm-empty-under-filter', 'true');
|
|
344
|
+
emptyCount += 1;
|
|
345
|
+
} else {
|
|
346
|
+
if (emptyNote) emptyNote.parentNode.removeChild(emptyNote);
|
|
347
|
+
bk.removeAttribute('data-pm-empty-under-filter');
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
var activePanel = document.querySelector('#tab-product-map .pm-group:not([hidden])');
|
|
351
|
+
if (activePanel) {
|
|
352
|
+
var roll = activePanel.querySelector('.pm-empty-roll');
|
|
353
|
+
if (roll) {
|
|
354
|
+
var showBtn = roll.querySelector('.pm-empty-count');
|
|
355
|
+
if (emptyCount > 0 && status !== 'all') {
|
|
356
|
+
if (showBtn) showBtn.textContent = String(emptyCount);
|
|
357
|
+
roll.removeAttribute('hidden');
|
|
358
|
+
activePanel.classList.add('pm-hide-empty');
|
|
359
|
+
} else {
|
|
360
|
+
roll.setAttribute('hidden', '');
|
|
361
|
+
activePanel.classList.remove('pm-hide-empty');
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
return true;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
function updatePmHash() {
|
|
369
|
+
if (!window.history || typeof window.history.pushState !== 'function') return;
|
|
370
|
+
var group = currentGroup();
|
|
371
|
+
var status = currentStatus();
|
|
372
|
+
var open = currentOpenBuckets();
|
|
373
|
+
var next = '#tab=product-map&group=' + group + '&status=' + status;
|
|
374
|
+
if (open.length > 0) next += '&open=' + encodeURIComponent(open.join(','));
|
|
375
|
+
if (window.location.hash === next && window.location.search === window.location.search) return;
|
|
376
|
+
// Preserve host query (?embed=, ?theme=, ?blueprint=, ?ticket=).
|
|
377
|
+
window.history.pushState(null, '', urlWithHash(next));
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
function openPmBuckets(ids) {
|
|
381
|
+
if (!ids || ids.length === 0) return;
|
|
382
|
+
var group = currentGroup();
|
|
383
|
+
var panel = pmGroupPanel(group);
|
|
384
|
+
if (!panel) return;
|
|
385
|
+
for (var i = 0; i < ids.length; i += 1) {
|
|
386
|
+
var raw = ids[i];
|
|
387
|
+
if (!raw) continue;
|
|
388
|
+
var node = panel.querySelector('details.pm-bucket[data-pm-bucket-id="' + raw.replace(/"/g, '\\"') + '"]');
|
|
389
|
+
if (node) node.open = true;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
function wireProductMapWithin(root) {
|
|
394
|
+
root = root || document;
|
|
395
|
+
var buckets = root.querySelectorAll('details.pm-bucket');
|
|
396
|
+
for (var i = 0; i < buckets.length; i += 1) {
|
|
397
|
+
var bk = buckets[i];
|
|
398
|
+
if (bk.__rcfPmBucketWired) continue;
|
|
399
|
+
bk.__rcfPmBucketWired = true;
|
|
400
|
+
bk.addEventListener('toggle', function () {
|
|
401
|
+
if (window.__rcfPmSuppress) return;
|
|
402
|
+
updatePmHash();
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
var chips = root.querySelectorAll('.pm-jump-chip');
|
|
406
|
+
for (var j = 0; j < chips.length; j += 1) {
|
|
407
|
+
var chip = chips[j];
|
|
408
|
+
if (chip.__rcfPmChipWired) continue;
|
|
409
|
+
chip.__rcfPmChipWired = true;
|
|
410
|
+
chip.addEventListener('click', function (ev) {
|
|
411
|
+
var target = ev.currentTarget.getAttribute('data-pm-jump');
|
|
412
|
+
var groupAttr = ev.currentTarget.closest('.pm-jump-nav').getAttribute('data-pm-jump-group');
|
|
413
|
+
var panel = pmGroupPanel(groupAttr);
|
|
414
|
+
if (!panel) return;
|
|
415
|
+
var node = panel.querySelector('details.pm-bucket[data-pm-bucket-id="' + target.replace(/"/g, '\\"') + '"]');
|
|
416
|
+
if (!node) return;
|
|
417
|
+
node.open = true;
|
|
418
|
+
try { node.scrollIntoView({ block: 'start' }); } catch (e) { node.scrollIntoView(); }
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
var bulk = root.querySelectorAll('.pm-bulk-btn');
|
|
422
|
+
for (var b = 0; b < bulk.length; b += 1) {
|
|
423
|
+
var btn = bulk[b];
|
|
424
|
+
if (btn.__rcfPmBulkWired) continue;
|
|
425
|
+
btn.__rcfPmBulkWired = true;
|
|
426
|
+
btn.addEventListener('click', function (ev) {
|
|
427
|
+
var action = ev.currentTarget.getAttribute('data-pm-bulk');
|
|
428
|
+
var panel = document.querySelector('#tab-product-map .pm-group:not([hidden])');
|
|
429
|
+
if (!panel) return;
|
|
430
|
+
var all = panel.querySelectorAll('details.pm-bucket');
|
|
431
|
+
window.__rcfPmSuppress = true;
|
|
432
|
+
for (var i = 0; i < all.length; i += 1) all[i].open = (action === 'expand');
|
|
433
|
+
window.__rcfPmSuppress = false;
|
|
434
|
+
updatePmHash();
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
var rolls = root.querySelectorAll('.pm-empty-toggle');
|
|
438
|
+
for (var r = 0; r < rolls.length; r += 1) {
|
|
439
|
+
var rt = rolls[r];
|
|
440
|
+
if (rt.__rcfPmEmptyWired) continue;
|
|
441
|
+
rt.__rcfPmEmptyWired = true;
|
|
442
|
+
rt.addEventListener('click', function (ev) {
|
|
443
|
+
var panel = ev.currentTarget.closest('.pm-group');
|
|
444
|
+
if (!panel) return;
|
|
445
|
+
if (panel.classList.contains('pm-hide-empty')) {
|
|
446
|
+
panel.classList.remove('pm-hide-empty');
|
|
447
|
+
ev.currentTarget.textContent = 'Hide empty buckets';
|
|
448
|
+
} else {
|
|
449
|
+
panel.classList.add('pm-hide-empty');
|
|
450
|
+
var span = document.createElement('span');
|
|
451
|
+
span.className = 'pm-empty-count';
|
|
452
|
+
span.textContent = String(panel.querySelectorAll('details.pm-bucket[data-pm-empty-under-filter="true"]').length);
|
|
453
|
+
ev.currentTarget.textContent = '';
|
|
454
|
+
ev.currentTarget.appendChild(document.createTextNode('Show '));
|
|
455
|
+
ev.currentTarget.appendChild(span);
|
|
456
|
+
ev.currentTarget.appendChild(document.createTextNode(' empty buckets'));
|
|
457
|
+
}
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
function wireProductMap() {
|
|
463
|
+
var buttons = document.querySelectorAll('.pm-group-btn');
|
|
464
|
+
for (var i = 0; i < buttons.length; i += 1) {
|
|
465
|
+
if (buttons[i].__rcfPmWired) continue;
|
|
466
|
+
buttons[i].__rcfPmWired = true;
|
|
467
|
+
buttons[i].addEventListener('click', function (ev) {
|
|
468
|
+
var name = ev.currentTarget.getAttribute('data-pm-group');
|
|
469
|
+
if (activatePmGroup(name)) updatePmHash();
|
|
470
|
+
});
|
|
471
|
+
}
|
|
472
|
+
var select = document.querySelector('.pm-status-select');
|
|
473
|
+
if (select && !select.__rcfPmWired) {
|
|
474
|
+
select.__rcfPmWired = true;
|
|
475
|
+
select.addEventListener('change', function () {
|
|
476
|
+
applyPmStatusFilter(select.value);
|
|
477
|
+
updatePmHash();
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
wireProductMapWithin(document);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
// ---- hash router ------------------------------------------------------
|
|
484
|
+
//
|
|
485
|
+
// PR 1 contract: #tab=<name>&sub=<name>&entity=<id>&... with bare
|
|
486
|
+
// #REQ-002 still resolving. Unknown params survive. Writes go through
|
|
487
|
+
// urlWithHash so the ?embed=/?theme= query is preserved. 'sub=' is
|
|
488
|
+
// owned by the active tab (Build tab in PR 5 for specs|dag); for PR 1
|
|
489
|
+
// we only read the value and leave acting on it to a later tab-side
|
|
490
|
+
// handler.
|
|
491
|
+
|
|
492
|
+
function resolveHash(hash) {
|
|
493
|
+
if (!hash) { activateTab('readiness'); return; }
|
|
494
|
+
var raw = hash.charAt(0) === '#' ? hash.slice(1) : hash;
|
|
495
|
+
// Decision 11 (PR 3): `#entity=<id>` without a tab key still
|
|
496
|
+
// resolves - we find the target, activate its tab and open ancestors.
|
|
497
|
+
if (raw.indexOf('=') !== -1 && raw.indexOf('tab=') === -1) {
|
|
498
|
+
var kv = parseHashParams(raw);
|
|
499
|
+
if (kv.entity) {
|
|
500
|
+
var entTarget = findByDocId(kv.entity);
|
|
501
|
+
if (entTarget) {
|
|
502
|
+
var entTab = tabForNode(entTarget);
|
|
503
|
+
if (entTab) activateTab(entTab);
|
|
504
|
+
openAncestorDetails(entTarget);
|
|
505
|
+
if (entTarget.tagName && entTarget.tagName.toLowerCase() === 'details') entTarget.open = true;
|
|
506
|
+
try { entTarget.scrollIntoView({ block: 'start' }); } catch (e) { entTarget.scrollIntoView(); }
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
if (raw.indexOf('tab=') === 0 || raw.indexOf('tab=') > 0) {
|
|
512
|
+
// Fast path: tab is the first key.
|
|
513
|
+
var params = parseHashParams(raw);
|
|
514
|
+
var tab = params.tab;
|
|
515
|
+
if (tab && TABS.indexOf(tab) !== -1) {
|
|
516
|
+
activateTab(tab);
|
|
517
|
+
if (tab === 'product-map') {
|
|
518
|
+
var openIds = params.open ? decodeURIComponent(params.open).split(',').filter(Boolean) : [];
|
|
519
|
+
activatePmGroup(params.group || 'shape', {
|
|
520
|
+
after: function () {
|
|
521
|
+
if (params.status) applyPmStatusFilter(params.status);
|
|
522
|
+
openPmBuckets(openIds);
|
|
523
|
+
},
|
|
524
|
+
});
|
|
525
|
+
}
|
|
526
|
+
// Requirements tab: push the hash filter slots into the
|
|
527
|
+
// FilterBar inputs and re-run the row filter so the first paint
|
|
528
|
+
// reflects the URL exactly. #entity=... below opens the entity.
|
|
529
|
+
if (tab === 'requirements' && requirementsFilterBar()) {
|
|
530
|
+
applyRequirementsHash(params);
|
|
531
|
+
}
|
|
532
|
+
// Architecture tab: push the two FilterBar states + any
|
|
533
|
+
// `open=<tad-section>,<tad-section>...` deep-link so the first
|
|
534
|
+
// paint reflects the URL (PR 4, decisions 3 and 5).
|
|
535
|
+
if (tab === 'architecture' && (archBar('architecture-components') || archBar('architecture-decisions'))) {
|
|
536
|
+
applyArchitectureHash(params);
|
|
537
|
+
}
|
|
538
|
+
// Build tab (PR 5): activate the right sub-tab and push the
|
|
539
|
+
// Specs FilterBar state so the first paint reflects the URL.
|
|
540
|
+
if (tab === 'build') {
|
|
541
|
+
applyBuildHash(params);
|
|
542
|
+
}
|
|
543
|
+
// #tab=requirements&entity=REQ-002 opens the entity in place.
|
|
544
|
+
if (params.entity) {
|
|
545
|
+
var ent = findByDocId(params.entity);
|
|
546
|
+
if (ent) {
|
|
547
|
+
openAncestorDetails(ent);
|
|
548
|
+
if (ent.tagName && ent.tagName.toLowerCase() === 'details') ent.open = true;
|
|
549
|
+
try { ent.scrollIntoView({ block: 'start' }); } catch (e) { ent.scrollIntoView(); }
|
|
550
|
+
flashLookupTarget(ent);
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
// Bare hash (#REQ-002 etc) stays supported.
|
|
557
|
+
var target = findByDocId(raw);
|
|
558
|
+
if (!target) { activateTab('readiness'); return; }
|
|
559
|
+
var tabName = tabForNode(target);
|
|
560
|
+
if (tabName) activateTab(tabName);
|
|
561
|
+
openAncestorDetails(target);
|
|
562
|
+
if (target.tagName && target.tagName.toLowerCase() === 'details') target.open = true;
|
|
563
|
+
try { target.scrollIntoView({ block: 'start' }); } catch (e) { target.scrollIntoView(); }
|
|
564
|
+
flashLookupTarget(target);
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
function onTabClick(ev) {
|
|
568
|
+
var btn = ev.currentTarget;
|
|
569
|
+
var name = btn.getAttribute('data-tab');
|
|
570
|
+
if (!name) return;
|
|
571
|
+
ev.preventDefault && ev.preventDefault();
|
|
572
|
+
activateTab(name);
|
|
573
|
+
if (name === 'product-map') {
|
|
574
|
+
activatePmGroup(currentGroup());
|
|
575
|
+
}
|
|
576
|
+
// The Build tab carries a SubTabStrip + FilterBar state the URL
|
|
577
|
+
// mirrors; re-emit the current fragment so #tab=build / UI stay in
|
|
578
|
+
// step (fixes the DAG-sticky case: previously `#tab=build` was
|
|
579
|
+
// written while DAG remained visible).
|
|
580
|
+
if (name === 'build' && buildSubTabStrip()) {
|
|
581
|
+
writeHash(buildHashFragment(), true);
|
|
582
|
+
return;
|
|
583
|
+
}
|
|
584
|
+
// Hash write preserves ?embed=/?theme=/... (Dex contract, PR 1).
|
|
585
|
+
writeHash('#tab=' + name, true);
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
function wireTabs() {
|
|
589
|
+
tabButtons().forEach(function (btn) {
|
|
590
|
+
if (btn.__rcfTabWired) return;
|
|
591
|
+
btn.__rcfTabWired = true;
|
|
592
|
+
btn.addEventListener('click', onTabClick);
|
|
593
|
+
});
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
// ---- shared toast helper (viewer UI refresh PR 2) --------------------
|
|
597
|
+
//
|
|
598
|
+
// The shell renders exactly one <div class="rcf-toast" data-toast> and
|
|
599
|
+
// keeps it outside #rcf-live-content so the SSE innerHTML swap does
|
|
600
|
+
// not blow it away. showToast() is idempotent across repeat calls:
|
|
601
|
+
// the latest message replaces whatever is showing, the fade-out
|
|
602
|
+
// timer resets, and the element clears when the fade completes.
|
|
603
|
+
var toastHideTimer = null;
|
|
604
|
+
function showToast(message, opts) {
|
|
605
|
+
var el = document.querySelector('[data-toast]');
|
|
606
|
+
if (!el) return;
|
|
607
|
+
var text = message == null ? '' : String(message);
|
|
608
|
+
el.textContent = text;
|
|
609
|
+
el.classList.add('show');
|
|
610
|
+
if (toastHideTimer) { clearTimeout(toastHideTimer); toastHideTimer = null; }
|
|
611
|
+
var durationMs = opts && typeof opts.durationMs === 'number' ? opts.durationMs : 2200;
|
|
612
|
+
toastHideTimer = setTimeout(function () {
|
|
613
|
+
el.classList.remove('show');
|
|
614
|
+
// Clear the text one fade-out later so a reader does not re-announce it.
|
|
615
|
+
toastHideTimer = setTimeout(function () {
|
|
616
|
+
if (!el.classList.contains('show')) el.textContent = '';
|
|
617
|
+
}, 200);
|
|
618
|
+
}, durationMs);
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
// ---- component fixture page wiring (viewer UI refresh PR 2) ----------
|
|
622
|
+
//
|
|
623
|
+
// The /_fixtures/components page carries a theme toggle and a demo
|
|
624
|
+
// button that fires showToast() so a reviewer can confirm the Toast
|
|
625
|
+
// round-trips end-to-end. Both guards against null elements so the
|
|
626
|
+
// helpers no-op on every other page.
|
|
627
|
+
function wireFixturePage() {
|
|
628
|
+
var themeBtns = document.querySelectorAll('[data-rcf-fixture-theme]');
|
|
629
|
+
for (var i = 0; i < themeBtns.length; i += 1) {
|
|
630
|
+
var btn = themeBtns[i];
|
|
631
|
+
if (btn.__rcfFixtureThemeWired) continue;
|
|
632
|
+
btn.__rcfFixtureThemeWired = true;
|
|
633
|
+
btn.addEventListener('click', function (ev) {
|
|
634
|
+
var mode = ev.currentTarget.getAttribute('data-rcf-fixture-theme');
|
|
635
|
+
applyTheme(mode === 'auto' ? null : mode);
|
|
636
|
+
var buttons = document.querySelectorAll('[data-rcf-fixture-theme]');
|
|
637
|
+
for (var j = 0; j < buttons.length; j += 1) {
|
|
638
|
+
var b = buttons[j];
|
|
639
|
+
var isTarget = b.getAttribute('data-rcf-fixture-theme') === mode;
|
|
640
|
+
b.setAttribute('aria-pressed', isTarget ? 'true' : 'false');
|
|
641
|
+
}
|
|
642
|
+
});
|
|
643
|
+
}
|
|
644
|
+
var toastBtns = document.querySelectorAll('[data-rcf-fixture-toast]');
|
|
645
|
+
for (var k = 0; k < toastBtns.length; k += 1) {
|
|
646
|
+
var tb = toastBtns[k];
|
|
647
|
+
if (tb.__rcfFixtureToastWired) continue;
|
|
648
|
+
tb.__rcfFixtureToastWired = true;
|
|
649
|
+
tb.addEventListener('click', function () {
|
|
650
|
+
showToast('Saved. (demo of the shared Toast helper)');
|
|
651
|
+
});
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
// ---- Requirements FilterBar + EntitySelector (viewer UI refresh PR 3) --
|
|
656
|
+
//
|
|
657
|
+
// The Requirements tab mounts a FilterBar (text, area, priority, status,
|
|
658
|
+
// Needs-work) and the PRD tab mounts an EntitySelector (type-ahead jump
|
|
659
|
+
// + area chips). Filter state lives in the hash so a filtered view is a
|
|
660
|
+
// link (decision 3). The hash slots this reads/writes:
|
|
661
|
+
// #tab=requirements[&q=...][&domain=...][&priority=...][&status=...][&needswork=1]
|
|
662
|
+
// Area chips in the PRD selector write #tab=requirements&domain=...;
|
|
663
|
+
// the type-ahead jump writes #tab=requirements&entity=<id>.
|
|
664
|
+
|
|
665
|
+
function requirementsListNode() {
|
|
666
|
+
return document.querySelector('[data-rcf-list="requirements"]');
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
function requirementsFilterBar() {
|
|
670
|
+
return document.querySelector('[data-rcf-filterbar="requirements"]');
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
function readRequirementsFilterState() {
|
|
674
|
+
var bar = requirementsFilterBar();
|
|
675
|
+
if (!bar) return null;
|
|
676
|
+
var text = bar.querySelector('.rcf-filter-text');
|
|
677
|
+
var state = { q: text ? text.value.trim() : '', needswork: false };
|
|
678
|
+
var selects = bar.querySelectorAll('.rcf-filter-select');
|
|
679
|
+
for (var i = 0; i < selects.length; i += 1) {
|
|
680
|
+
state[selects[i].getAttribute('data-filter-key') || 'select'] = selects[i].value;
|
|
681
|
+
}
|
|
682
|
+
var toggles = bar.querySelectorAll('.rcf-filter-toggle input[type="checkbox"]');
|
|
683
|
+
for (var j = 0; j < toggles.length; j += 1) {
|
|
684
|
+
state[toggles[j].getAttribute('data-filter-key') || 'toggle'] = toggles[j].checked;
|
|
685
|
+
}
|
|
686
|
+
return state;
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
function writeRequirementsFilterState(state) {
|
|
690
|
+
var bar = requirementsFilterBar();
|
|
691
|
+
if (!bar) return;
|
|
692
|
+
var text = bar.querySelector('.rcf-filter-text');
|
|
693
|
+
if (text) text.value = state.q || '';
|
|
694
|
+
var selects = bar.querySelectorAll('.rcf-filter-select');
|
|
695
|
+
for (var i = 0; i < selects.length; i += 1) {
|
|
696
|
+
var key = selects[i].getAttribute('data-filter-key') || '';
|
|
697
|
+
selects[i].value = state[key] != null ? String(state[key]) : '';
|
|
698
|
+
}
|
|
699
|
+
var toggles = bar.querySelectorAll('.rcf-filter-toggle input[type="checkbox"]');
|
|
700
|
+
for (var j = 0; j < toggles.length; j += 1) {
|
|
701
|
+
var tkey = toggles[j].getAttribute('data-filter-key') || '';
|
|
702
|
+
toggles[j].checked = state[tkey] === true || state[tkey] === 'true' || state[tkey] === '1';
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
function applyRequirementsFilter() {
|
|
707
|
+
var list = requirementsListNode();
|
|
708
|
+
if (!list) return;
|
|
709
|
+
var state = readRequirementsFilterState() || { q: '', domain: '', priority: '', status: '', needswork: false };
|
|
710
|
+
var qLower = (state.q || '').toLowerCase();
|
|
711
|
+
var rows = list.querySelectorAll(':scope > details.rcf-row[data-doc-id^="REQ-"]');
|
|
712
|
+
var visible = 0;
|
|
713
|
+
for (var i = 0; i < rows.length; i += 1) {
|
|
714
|
+
var row = rows[i];
|
|
715
|
+
var hide = false;
|
|
716
|
+
if (state.domain && row.getAttribute('data-domain') !== state.domain) hide = true;
|
|
717
|
+
if (!hide && state.priority && row.getAttribute('data-priority') !== state.priority) hide = true;
|
|
718
|
+
if (!hide && state.status && row.getAttribute('data-status') !== state.status) hide = true;
|
|
719
|
+
if (!hide && state.needswork && row.getAttribute('data-needswork') !== '1') hide = true;
|
|
720
|
+
if (!hide && qLower) {
|
|
721
|
+
var hay = row.getAttribute('data-text') || '';
|
|
722
|
+
if (hay.indexOf(qLower) === -1) hide = true;
|
|
723
|
+
}
|
|
724
|
+
if (hide) row.setAttribute('hidden', '');
|
|
725
|
+
else { row.removeAttribute('hidden'); visible += 1; }
|
|
726
|
+
}
|
|
727
|
+
var countEl = document.querySelector('[data-rcf-filterbar="requirements"] .rcf-filter-count');
|
|
728
|
+
if (countEl) countEl.textContent = String(visible) + ' of ' + String(rows.length) + ' visible';
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
function requirementsHashFragment(state) {
|
|
732
|
+
var parts = ['tab=requirements'];
|
|
733
|
+
if (state.q) parts.push('q=' + encodeURIComponent(state.q));
|
|
734
|
+
if (state.domain) parts.push('domain=' + encodeURIComponent(state.domain));
|
|
735
|
+
if (state.priority) parts.push('priority=' + encodeURIComponent(state.priority));
|
|
736
|
+
if (state.status) parts.push('status=' + encodeURIComponent(state.status));
|
|
737
|
+
if (state.needswork) parts.push('needswork=1');
|
|
738
|
+
if (state.entity) parts.push('entity=' + encodeURIComponent(state.entity));
|
|
739
|
+
// Decision 11: preserve unknown hash params through filter writes.
|
|
740
|
+
if (state.extraParts) parts = parts.concat(state.extraParts);
|
|
741
|
+
return '#' + parts.join('&');
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
function currentRequirementsHashExtras() {
|
|
745
|
+
// Read the live hash, keep every param not owned by the Requirements
|
|
746
|
+
// FilterBar so filter writes preserve the selected entity and any
|
|
747
|
+
// other extension (decision 11 preservation contract).
|
|
748
|
+
var raw = window.location.hash || '';
|
|
749
|
+
if (raw[0] === '#') raw = raw.slice(1);
|
|
750
|
+
if (!raw) return { entity: '', extraParts: [] };
|
|
751
|
+
var pairs = raw.split('&');
|
|
752
|
+
var entity = '';
|
|
753
|
+
var extras = [];
|
|
754
|
+
var owned = { tab: true, q: true, domain: true, priority: true, status: true, needswork: true, entity: true };
|
|
755
|
+
for (var i = 0; i < pairs.length; i += 1) {
|
|
756
|
+
var p = pairs[i];
|
|
757
|
+
if (!p) continue;
|
|
758
|
+
var eq = p.indexOf('=');
|
|
759
|
+
var k = eq === -1 ? p : p.slice(0, eq);
|
|
760
|
+
if (k === 'entity' && eq !== -1) { entity = decodeURIComponent(p.slice(eq + 1)); continue; }
|
|
761
|
+
if (owned[k]) continue;
|
|
762
|
+
extras.push(p);
|
|
763
|
+
}
|
|
764
|
+
return { entity: entity, extraParts: extras };
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
function writeRequirementsHash() {
|
|
768
|
+
var state = readRequirementsFilterState();
|
|
769
|
+
if (!state) return;
|
|
770
|
+
var extras = currentRequirementsHashExtras();
|
|
771
|
+
state.entity = extras.entity;
|
|
772
|
+
state.extraParts = extras.extraParts;
|
|
773
|
+
writeHash(requirementsHashFragment(state), true);
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
function applyRequirementsHash(params) {
|
|
777
|
+
var state = {
|
|
778
|
+
q: params.q ? decodeURIComponent(params.q) : '',
|
|
779
|
+
domain: params.domain ? decodeURIComponent(params.domain) : '',
|
|
780
|
+
priority: params.priority ? decodeURIComponent(params.priority) : '',
|
|
781
|
+
status: params.status ? decodeURIComponent(params.status) : '',
|
|
782
|
+
needswork: params.needswork === '1' || params.needswork === 'true',
|
|
783
|
+
};
|
|
784
|
+
writeRequirementsFilterState(state);
|
|
785
|
+
applyRequirementsFilter();
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
function expandAllRequirements(open) {
|
|
789
|
+
var list = requirementsListNode();
|
|
790
|
+
if (!list) return;
|
|
791
|
+
var rows = list.querySelectorAll(':scope > details.rcf-row');
|
|
792
|
+
for (var i = 0; i < rows.length; i += 1) {
|
|
793
|
+
if (rows[i].hasAttribute('hidden')) continue;
|
|
794
|
+
rows[i].open = !!open;
|
|
795
|
+
}
|
|
796
|
+
var btn = document.querySelector('[data-rcf-filterbar="requirements"] .rcf-filter-expand');
|
|
797
|
+
if (btn) {
|
|
798
|
+
btn.textContent = open ? 'Collapse all' : 'Expand all';
|
|
799
|
+
btn.setAttribute('data-expand-state', open ? 'expanded' : 'collapsed');
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
function wireRequirementsFilterBar() {
|
|
804
|
+
var bar = requirementsFilterBar();
|
|
805
|
+
if (!bar || bar.__rcfReqFilterWired) return;
|
|
806
|
+
bar.__rcfReqFilterWired = true;
|
|
807
|
+
var text = bar.querySelector('.rcf-filter-text');
|
|
808
|
+
if (text) {
|
|
809
|
+
var debounceTimer = null;
|
|
810
|
+
text.addEventListener('input', function () {
|
|
811
|
+
if (debounceTimer) clearTimeout(debounceTimer);
|
|
812
|
+
debounceTimer = setTimeout(function () {
|
|
813
|
+
applyRequirementsFilter();
|
|
814
|
+
writeRequirementsHash();
|
|
815
|
+
}, 150);
|
|
816
|
+
});
|
|
817
|
+
}
|
|
818
|
+
var selects = bar.querySelectorAll('.rcf-filter-select');
|
|
819
|
+
for (var i = 0; i < selects.length; i += 1) {
|
|
820
|
+
selects[i].addEventListener('change', function () {
|
|
821
|
+
applyRequirementsFilter();
|
|
822
|
+
writeRequirementsHash();
|
|
823
|
+
});
|
|
824
|
+
}
|
|
825
|
+
var toggles = bar.querySelectorAll('.rcf-filter-toggle input[type="checkbox"]');
|
|
826
|
+
for (var j = 0; j < toggles.length; j += 1) {
|
|
827
|
+
toggles[j].addEventListener('change', function () {
|
|
828
|
+
applyRequirementsFilter();
|
|
829
|
+
writeRequirementsHash();
|
|
830
|
+
});
|
|
831
|
+
}
|
|
832
|
+
var expandBtn = bar.querySelector('.rcf-filter-expand');
|
|
833
|
+
if (expandBtn) {
|
|
834
|
+
expandBtn.addEventListener('click', function (ev) {
|
|
835
|
+
ev.preventDefault && ev.preventDefault();
|
|
836
|
+
var isCollapsed = expandBtn.getAttribute('data-expand-state') !== 'expanded';
|
|
837
|
+
expandAllRequirements(isCollapsed);
|
|
838
|
+
});
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
// ---- Architecture FilterBars (viewer UI refresh PR 4) ----------------
|
|
843
|
+
//
|
|
844
|
+
// The Architecture tab mounts two FilterBars: Components
|
|
845
|
+
// (architecture-components) and Decisions (architecture-decisions).
|
|
846
|
+
// Each is text + Status facet; state lives in the hash under the
|
|
847
|
+
// owning tab so the view is a link. Hash slots this reads/writes:
|
|
848
|
+
// #tab=architecture[&cq=...][&cstatus=...][&dq=...][&dstatus=...]
|
|
849
|
+
// [&open=components|decisions|<tad-section-key>]
|
|
850
|
+
// The `open=` key is a comma-separated set so a review link can
|
|
851
|
+
// deep-open one TAD section (e.g. open=integrationArchitecture).
|
|
852
|
+
|
|
853
|
+
var ARCH_HASH_KEYS = {
|
|
854
|
+
'architecture-components': { q: 'cq', status: 'cstatus' },
|
|
855
|
+
'architecture-decisions': { q: 'dq', status: 'dstatus' },
|
|
856
|
+
};
|
|
857
|
+
|
|
858
|
+
function archBar(hashKey) {
|
|
859
|
+
return document.querySelector('[data-rcf-filterbar="' + hashKey + '"]');
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
function archList(hashKey) {
|
|
863
|
+
return document.querySelector('[data-rcf-list="' + hashKey + '"]');
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
function readArchitectureFilterState(hashKey) {
|
|
867
|
+
var bar = archBar(hashKey);
|
|
868
|
+
if (!bar) return null;
|
|
869
|
+
var text = bar.querySelector('.rcf-filter-text');
|
|
870
|
+
var state = { q: text ? text.value.trim() : '' };
|
|
871
|
+
var selects = bar.querySelectorAll('.rcf-filter-select');
|
|
872
|
+
for (var i = 0; i < selects.length; i += 1) {
|
|
873
|
+
state[selects[i].getAttribute('data-filter-key') || 'select'] = selects[i].value;
|
|
874
|
+
}
|
|
875
|
+
return state;
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
function writeArchitectureFilterState(hashKey, state) {
|
|
879
|
+
var bar = archBar(hashKey);
|
|
880
|
+
if (!bar) return;
|
|
881
|
+
var text = bar.querySelector('.rcf-filter-text');
|
|
882
|
+
if (text) text.value = state.q || '';
|
|
883
|
+
var selects = bar.querySelectorAll('.rcf-filter-select');
|
|
884
|
+
for (var i = 0; i < selects.length; i += 1) {
|
|
885
|
+
var key = selects[i].getAttribute('data-filter-key') || '';
|
|
886
|
+
selects[i].value = state[key] != null ? String(state[key]) : '';
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
function applyArchitectureFilter(hashKey) {
|
|
891
|
+
var list = archList(hashKey);
|
|
892
|
+
if (!list) return;
|
|
893
|
+
var state = readArchitectureFilterState(hashKey) || { q: '', status: '' };
|
|
894
|
+
var qLower = (state.q || '').toLowerCase();
|
|
895
|
+
var rows = list.querySelectorAll(':scope > details.rcf-row');
|
|
896
|
+
var visible = 0;
|
|
897
|
+
for (var i = 0; i < rows.length; i += 1) {
|
|
898
|
+
var row = rows[i];
|
|
899
|
+
var hide = false;
|
|
900
|
+
if (state.status && row.getAttribute('data-status') !== state.status) hide = true;
|
|
901
|
+
if (!hide && qLower) {
|
|
902
|
+
var hay = row.getAttribute('data-text') || '';
|
|
903
|
+
if (hay.indexOf(qLower) === -1) hide = true;
|
|
904
|
+
}
|
|
905
|
+
if (hide) row.setAttribute('hidden', '');
|
|
906
|
+
else { row.removeAttribute('hidden'); visible += 1; }
|
|
907
|
+
}
|
|
908
|
+
var countEl = document.querySelector('[data-rcf-filterbar="' + hashKey + '"] .rcf-filter-count');
|
|
909
|
+
if (countEl) countEl.textContent = String(visible) + ' of ' + String(rows.length) + ' visible';
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
function architectureHashFragment() {
|
|
913
|
+
var parts = ['tab=architecture'];
|
|
914
|
+
for (var hk in ARCH_HASH_KEYS) {
|
|
915
|
+
if (!Object.prototype.hasOwnProperty.call(ARCH_HASH_KEYS, hk)) continue;
|
|
916
|
+
var state = readArchitectureFilterState(hk);
|
|
917
|
+
var map = ARCH_HASH_KEYS[hk];
|
|
918
|
+
if (!state) continue;
|
|
919
|
+
if (state.q) parts.push(map.q + '=' + encodeURIComponent(state.q));
|
|
920
|
+
if (state.status) parts.push(map.status + '=' + encodeURIComponent(state.status));
|
|
921
|
+
}
|
|
922
|
+
return '#' + parts.join('&');
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
function writeArchitectureHash() {
|
|
926
|
+
writeHash(architectureHashFragment(), true);
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
function applyArchitectureHash(params) {
|
|
930
|
+
var statesByBar = {
|
|
931
|
+
'architecture-components': {
|
|
932
|
+
q: params.cq ? decodeURIComponent(params.cq) : '',
|
|
933
|
+
status: params.cstatus ? decodeURIComponent(params.cstatus) : '',
|
|
934
|
+
},
|
|
935
|
+
'architecture-decisions': {
|
|
936
|
+
q: params.dq ? decodeURIComponent(params.dq) : '',
|
|
937
|
+
status: params.dstatus ? decodeURIComponent(params.dstatus) : '',
|
|
938
|
+
},
|
|
939
|
+
};
|
|
940
|
+
for (var hk in statesByBar) {
|
|
941
|
+
if (!Object.prototype.hasOwnProperty.call(statesByBar, hk)) continue;
|
|
942
|
+
writeArchitectureFilterState(hk, statesByBar[hk]);
|
|
943
|
+
applyArchitectureFilter(hk);
|
|
944
|
+
}
|
|
945
|
+
if (params.open) {
|
|
946
|
+
var openSet = decodeURIComponent(params.open).split(',').filter(Boolean);
|
|
947
|
+
openArchitectureSections(openSet);
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
|
|
951
|
+
function openArchitectureSections(keys) {
|
|
952
|
+
for (var i = 0; i < keys.length; i += 1) {
|
|
953
|
+
var el = document.querySelector('[data-rcf-tad-section="' + keys[i] + '"]');
|
|
954
|
+
if (el && el.tagName && el.tagName.toLowerCase() === 'details') el.open = true;
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
function expandAllArchitecture(hashKey, open) {
|
|
959
|
+
var list = archList(hashKey);
|
|
960
|
+
if (!list) return;
|
|
961
|
+
var rows = list.querySelectorAll(':scope > details.rcf-row');
|
|
962
|
+
for (var i = 0; i < rows.length; i += 1) {
|
|
963
|
+
if (rows[i].hasAttribute('hidden')) continue;
|
|
964
|
+
rows[i].open = !!open;
|
|
965
|
+
}
|
|
966
|
+
var btn = document.querySelector('[data-rcf-filterbar="' + hashKey + '"] .rcf-filter-expand');
|
|
967
|
+
if (btn) {
|
|
968
|
+
btn.textContent = open ? 'Collapse all' : 'Expand all';
|
|
969
|
+
btn.setAttribute('data-expand-state', open ? 'expanded' : 'collapsed');
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
function wireArchitectureFilterBar(hashKey) {
|
|
974
|
+
var bar = archBar(hashKey);
|
|
975
|
+
if (!bar || bar.__rcfArchFilterWired) return;
|
|
976
|
+
bar.__rcfArchFilterWired = true;
|
|
977
|
+
var text = bar.querySelector('.rcf-filter-text');
|
|
978
|
+
if (text) {
|
|
979
|
+
var debounceTimer = null;
|
|
980
|
+
text.addEventListener('input', function () {
|
|
981
|
+
if (debounceTimer) clearTimeout(debounceTimer);
|
|
982
|
+
debounceTimer = setTimeout(function () {
|
|
983
|
+
applyArchitectureFilter(hashKey);
|
|
984
|
+
writeArchitectureHash();
|
|
985
|
+
}, 150);
|
|
986
|
+
});
|
|
987
|
+
}
|
|
988
|
+
var selects = bar.querySelectorAll('.rcf-filter-select');
|
|
989
|
+
for (var i = 0; i < selects.length; i += 1) {
|
|
990
|
+
selects[i].addEventListener('change', function () {
|
|
991
|
+
applyArchitectureFilter(hashKey);
|
|
992
|
+
writeArchitectureHash();
|
|
993
|
+
});
|
|
994
|
+
}
|
|
995
|
+
var expandBtn = bar.querySelector('.rcf-filter-expand');
|
|
996
|
+
if (expandBtn) {
|
|
997
|
+
expandBtn.addEventListener('click', function (ev) {
|
|
998
|
+
ev.preventDefault && ev.preventDefault();
|
|
999
|
+
var isCollapsed = expandBtn.getAttribute('data-expand-state') !== 'expanded';
|
|
1000
|
+
expandAllArchitecture(hashKey, isCollapsed);
|
|
1001
|
+
});
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
function wireArchitectureFilterBars() {
|
|
1006
|
+
wireArchitectureFilterBar('architecture-components');
|
|
1007
|
+
wireArchitectureFilterBar('architecture-decisions');
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
// ---- Build tab (viewer UI refresh PR 5) ------------------------------
|
|
1011
|
+
//
|
|
1012
|
+
// The Build tab carries a SubTabStrip (Specs | DAG; DAG is a PR 6
|
|
1013
|
+
// placeholder) and the Specs sub-tab mounts a FilterBar
|
|
1014
|
+
// (text, status, area, size, Buildable-now). Filter + sub-tab state
|
|
1015
|
+
// live in the hash so a filtered view is a link. Hash slots read /
|
|
1016
|
+
// written here:
|
|
1017
|
+
// #tab=build[&sub=specs|dag][&q=...][&status=...][&domain=...][&size=...][&buildable=1]
|
|
1018
|
+
|
|
1019
|
+
var BUILD_SUB = ['specs', 'dag'];
|
|
1020
|
+
|
|
1021
|
+
function buildBar() {
|
|
1022
|
+
return document.querySelector('[data-rcf-filterbar="build-specs"]');
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
function buildListNode() {
|
|
1026
|
+
return document.querySelector('[data-rcf-list="build-specs"]');
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
function buildSubTabStrip() {
|
|
1030
|
+
return document.querySelector('[data-rcf-subtabstrip="build"]');
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
function buildSubPanel(sub) {
|
|
1034
|
+
return document.querySelector('[data-rcf-subpanel="' + sub + '"]');
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
function activateBuildSub(sub) {
|
|
1038
|
+
if (BUILD_SUB.indexOf(sub) === -1) sub = 'specs';
|
|
1039
|
+
var strip = buildSubTabStrip();
|
|
1040
|
+
if (strip) {
|
|
1041
|
+
var btns = strip.querySelectorAll('[role="tab"]');
|
|
1042
|
+
for (var i = 0; i < btns.length; i += 1) {
|
|
1043
|
+
var isTarget = btns[i].getAttribute('data-sub') === sub;
|
|
1044
|
+
btns[i].setAttribute('aria-selected', isTarget ? 'true' : 'false');
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
1047
|
+
for (var j = 0; j < BUILD_SUB.length; j += 1) {
|
|
1048
|
+
var p = buildSubPanel(BUILD_SUB[j]);
|
|
1049
|
+
if (!p) continue;
|
|
1050
|
+
if (BUILD_SUB[j] === sub) p.removeAttribute('hidden');
|
|
1051
|
+
else p.setAttribute('hidden', '');
|
|
1052
|
+
}
|
|
1053
|
+
return sub;
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
function currentBuildSub() {
|
|
1057
|
+
var strip = buildSubTabStrip();
|
|
1058
|
+
if (!strip) return 'specs';
|
|
1059
|
+
var active = strip.querySelector('[role="tab"][aria-selected="true"]');
|
|
1060
|
+
return (active && active.getAttribute('data-sub')) || 'specs';
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
function readBuildFilterState() {
|
|
1064
|
+
var bar = buildBar();
|
|
1065
|
+
if (!bar) return null;
|
|
1066
|
+
var text = bar.querySelector('.rcf-filter-text');
|
|
1067
|
+
var state = { q: text ? text.value.trim() : '', buildable: false };
|
|
1068
|
+
var selects = bar.querySelectorAll('.rcf-filter-select');
|
|
1069
|
+
for (var i = 0; i < selects.length; i += 1) {
|
|
1070
|
+
state[selects[i].getAttribute('data-filter-key') || 'select'] = selects[i].value;
|
|
1071
|
+
}
|
|
1072
|
+
var toggles = bar.querySelectorAll('.rcf-filter-toggle input[type="checkbox"]');
|
|
1073
|
+
for (var j = 0; j < toggles.length; j += 1) {
|
|
1074
|
+
state[toggles[j].getAttribute('data-filter-key') || 'toggle'] = toggles[j].checked;
|
|
1075
|
+
}
|
|
1076
|
+
return state;
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
function writeBuildFilterState(state) {
|
|
1080
|
+
var bar = buildBar();
|
|
1081
|
+
if (!bar) return;
|
|
1082
|
+
var text = bar.querySelector('.rcf-filter-text');
|
|
1083
|
+
if (text) text.value = state.q || '';
|
|
1084
|
+
var selects = bar.querySelectorAll('.rcf-filter-select');
|
|
1085
|
+
for (var i = 0; i < selects.length; i += 1) {
|
|
1086
|
+
var key = selects[i].getAttribute('data-filter-key') || '';
|
|
1087
|
+
selects[i].value = state[key] != null ? String(state[key]) : '';
|
|
1088
|
+
}
|
|
1089
|
+
var toggles = bar.querySelectorAll('.rcf-filter-toggle input[type="checkbox"]');
|
|
1090
|
+
for (var j = 0; j < toggles.length; j += 1) {
|
|
1091
|
+
var tkey = toggles[j].getAttribute('data-filter-key') || '';
|
|
1092
|
+
toggles[j].checked = state[tkey] === true || state[tkey] === 'true' || state[tkey] === '1';
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
function applyBuildFilter() {
|
|
1097
|
+
var list = buildListNode();
|
|
1098
|
+
if (!list) return;
|
|
1099
|
+
var state = readBuildFilterState() || { q: '', status: '', domain: '', size: '', buildable: false };
|
|
1100
|
+
var qLower = (state.q || '').toLowerCase();
|
|
1101
|
+
var rows = list.querySelectorAll(':scope > details.rcf-row');
|
|
1102
|
+
var visible = 0;
|
|
1103
|
+
for (var i = 0; i < rows.length; i += 1) {
|
|
1104
|
+
var row = rows[i];
|
|
1105
|
+
var hide = false;
|
|
1106
|
+
if (state.status && row.getAttribute('data-status') !== state.status) hide = true;
|
|
1107
|
+
if (!hide && state.domain && row.getAttribute('data-domain') !== state.domain) hide = true;
|
|
1108
|
+
if (!hide && state.size && row.getAttribute('data-size') !== state.size) hide = true;
|
|
1109
|
+
if (!hide && state.buildable && row.getAttribute('data-buildable') !== '1') hide = true;
|
|
1110
|
+
if (!hide && qLower) {
|
|
1111
|
+
var hay = row.getAttribute('data-text') || '';
|
|
1112
|
+
if (hay.indexOf(qLower) === -1) hide = true;
|
|
1113
|
+
}
|
|
1114
|
+
if (hide) row.setAttribute('hidden', '');
|
|
1115
|
+
else { row.removeAttribute('hidden'); visible += 1; }
|
|
1116
|
+
}
|
|
1117
|
+
var countEl = document.querySelector('[data-rcf-filterbar="build-specs"] .rcf-filter-count');
|
|
1118
|
+
if (countEl) countEl.textContent = String(visible) + ' of ' + String(rows.length) + ' visible';
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
function currentBuildHashExtras() {
|
|
1122
|
+
// Read the live hash, keep every param not owned by the Build
|
|
1123
|
+
// FilterBar + SubTabStrip so sub-tab / filter writes preserve the
|
|
1124
|
+
// selected entity and any other extension (decision 11 preservation
|
|
1125
|
+
// contract; same shape as currentRequirementsHashExtras).
|
|
1126
|
+
var raw = window.location.hash || '';
|
|
1127
|
+
if (raw[0] === '#') raw = raw.slice(1);
|
|
1128
|
+
if (!raw) return { entity: '', extraParts: [] };
|
|
1129
|
+
var pairs = raw.split('&');
|
|
1130
|
+
var entity = '';
|
|
1131
|
+
var extras = [];
|
|
1132
|
+
var owned = { tab: true, sub: true, q: true, status: true, domain: true, size: true, buildable: true, entity: true };
|
|
1133
|
+
for (var i = 0; i < pairs.length; i += 1) {
|
|
1134
|
+
var p = pairs[i];
|
|
1135
|
+
if (!p) continue;
|
|
1136
|
+
var eq = p.indexOf('=');
|
|
1137
|
+
var k = eq === -1 ? p : p.slice(0, eq);
|
|
1138
|
+
if (k === 'entity' && eq !== -1) { entity = decodeURIComponent(p.slice(eq + 1)); continue; }
|
|
1139
|
+
if (owned[k]) continue;
|
|
1140
|
+
extras.push(p);
|
|
1141
|
+
}
|
|
1142
|
+
return { entity: entity, extraParts: extras };
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
function currentDagHashExtras() {
|
|
1146
|
+
// On the DAG sub-tab, the Specs filter params (q/status/domain/size/
|
|
1147
|
+
// buildable) are UNKNOWN - the DAG does not own them. Preserve them
|
|
1148
|
+
// through DAG writes per the decision 11 preservation contract so
|
|
1149
|
+
// deep links like `#tab=build&sub=dag&entity=FBS-012&status=notStarted`
|
|
1150
|
+
// survive filter and selection changes.
|
|
1151
|
+
var raw = window.location.hash || '';
|
|
1152
|
+
if (raw[0] === '#') raw = raw.slice(1);
|
|
1153
|
+
if (!raw) return [];
|
|
1154
|
+
var pairs = raw.split('&');
|
|
1155
|
+
var extras = [];
|
|
1156
|
+
var owned = { tab: true, sub: true, entity: true };
|
|
1157
|
+
for (var i = 0; i < pairs.length; i += 1) {
|
|
1158
|
+
var p = pairs[i];
|
|
1159
|
+
if (!p) continue;
|
|
1160
|
+
var eq = p.indexOf('=');
|
|
1161
|
+
var k = eq === -1 ? p : p.slice(0, eq);
|
|
1162
|
+
if (owned[k]) continue;
|
|
1163
|
+
extras.push(p);
|
|
1164
|
+
}
|
|
1165
|
+
return extras;
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
function buildHashFragment() {
|
|
1169
|
+
var parts = ['tab=build'];
|
|
1170
|
+
var sub = currentBuildSub();
|
|
1171
|
+
if (sub && sub !== 'specs') parts.push('sub=' + encodeURIComponent(sub));
|
|
1172
|
+
if (sub === 'dag') {
|
|
1173
|
+
var canvas = dagCanvas();
|
|
1174
|
+
var sel = canvas && canvas.getAttribute('data-rcf-dag-sel');
|
|
1175
|
+
if (sel) parts.push('entity=' + encodeURIComponent(sel));
|
|
1176
|
+
// Preserve any non-DAG-owned params (Specs filter keys etc.)
|
|
1177
|
+
// through DAG writes. Entity is already written above from the
|
|
1178
|
+
// live selection; do NOT re-append extras.entity.
|
|
1179
|
+
var dagExtras = currentDagHashExtras();
|
|
1180
|
+
if (dagExtras.length > 0) parts = parts.concat(dagExtras);
|
|
1181
|
+
return '#' + parts.join('&');
|
|
1182
|
+
}
|
|
1183
|
+
var state = readBuildFilterState();
|
|
1184
|
+
if (state) {
|
|
1185
|
+
if (state.q) parts.push('q=' + encodeURIComponent(state.q));
|
|
1186
|
+
if (state.status) parts.push('status=' + encodeURIComponent(state.status));
|
|
1187
|
+
if (state.domain) parts.push('domain=' + encodeURIComponent(state.domain));
|
|
1188
|
+
if (state.size) parts.push('size=' + encodeURIComponent(state.size));
|
|
1189
|
+
if (state.buildable) parts.push('buildable=1');
|
|
1190
|
+
}
|
|
1191
|
+
var extras = currentBuildHashExtras();
|
|
1192
|
+
if (extras.entity) parts.push('entity=' + encodeURIComponent(extras.entity));
|
|
1193
|
+
// Decision 11: preserve unknown hash params through filter writes.
|
|
1194
|
+
if (extras.extraParts && extras.extraParts.length > 0) parts = parts.concat(extras.extraParts);
|
|
1195
|
+
return '#' + parts.join('&');
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
function writeBuildHash() {
|
|
1199
|
+
writeHash(buildHashFragment(), true);
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
function applyBuildHash(params) {
|
|
1203
|
+
var sub = params.sub ? decodeURIComponent(params.sub) : 'specs';
|
|
1204
|
+
activateBuildSub(sub);
|
|
1205
|
+
if (sub === 'dag') {
|
|
1206
|
+
var canvas = dagCanvas();
|
|
1207
|
+
var entity = params.entity ? decodeURIComponent(params.entity) : '';
|
|
1208
|
+
if (canvas) {
|
|
1209
|
+
if (entity) {
|
|
1210
|
+
canvas.setAttribute('data-rcf-dag-sel', entity);
|
|
1211
|
+
// AC-204-4: a deep link to an unconnected FBS must land visibly.
|
|
1212
|
+
// Auto-press Show-unconnected so the lane renders and the node
|
|
1213
|
+
// is not display:none when applyDagFilters runs below.
|
|
1214
|
+
var payload = parseDagInspectorPayload();
|
|
1215
|
+
if (payload[entity] && payload[entity].unconnected) {
|
|
1216
|
+
var tunc = document.querySelector('[data-rcf-dag-toggle="unconnected"]');
|
|
1217
|
+
if (tunc && tunc.getAttribute('aria-pressed') !== 'true') tunc.setAttribute('aria-pressed', 'true');
|
|
1218
|
+
}
|
|
1219
|
+
} else {
|
|
1220
|
+
canvas.removeAttribute('data-rcf-dag-sel');
|
|
1221
|
+
}
|
|
1222
|
+
applyDagFilters();
|
|
1223
|
+
renderDagInspector();
|
|
1224
|
+
if (entity) {
|
|
1225
|
+
var el = canvas.querySelector('.rcf-dag-node[data-fbs-id="' + entity + '"]');
|
|
1226
|
+
if (el) { try { el.scrollIntoView({ block: 'center', inline: 'center' }); } catch (e) { el.scrollIntoView(); } }
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
return;
|
|
1230
|
+
}
|
|
1231
|
+
var state = {
|
|
1232
|
+
q: params.q ? decodeURIComponent(params.q) : '',
|
|
1233
|
+
status: params.status ? decodeURIComponent(params.status) : '',
|
|
1234
|
+
domain: params.domain ? decodeURIComponent(params.domain) : '',
|
|
1235
|
+
size: params.size ? decodeURIComponent(params.size) : '',
|
|
1236
|
+
buildable: params.buildable === '1' || params.buildable === 'true',
|
|
1237
|
+
};
|
|
1238
|
+
if (buildBar()) {
|
|
1239
|
+
writeBuildFilterState(state);
|
|
1240
|
+
applyBuildFilter();
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1243
|
+
|
|
1244
|
+
function expandAllBuildSpecs(open) {
|
|
1245
|
+
var list = buildListNode();
|
|
1246
|
+
if (!list) return;
|
|
1247
|
+
var rows = list.querySelectorAll(':scope > details.rcf-row');
|
|
1248
|
+
for (var i = 0; i < rows.length; i += 1) {
|
|
1249
|
+
if (rows[i].hasAttribute('hidden')) continue;
|
|
1250
|
+
rows[i].open = !!open;
|
|
1251
|
+
}
|
|
1252
|
+
var btn = document.querySelector('[data-rcf-filterbar="build-specs"] .rcf-filter-expand');
|
|
1253
|
+
if (btn) {
|
|
1254
|
+
btn.textContent = open ? 'Collapse all' : 'Expand all';
|
|
1255
|
+
btn.setAttribute('data-expand-state', open ? 'expanded' : 'collapsed');
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
|
|
1259
|
+
function wireBuildFilterBar() {
|
|
1260
|
+
var bar = buildBar();
|
|
1261
|
+
if (!bar || bar.__rcfBuildFilterWired) return;
|
|
1262
|
+
bar.__rcfBuildFilterWired = true;
|
|
1263
|
+
var text = bar.querySelector('.rcf-filter-text');
|
|
1264
|
+
if (text) {
|
|
1265
|
+
var debounceTimer = null;
|
|
1266
|
+
text.addEventListener('input', function () {
|
|
1267
|
+
if (debounceTimer) clearTimeout(debounceTimer);
|
|
1268
|
+
debounceTimer = setTimeout(function () {
|
|
1269
|
+
applyBuildFilter();
|
|
1270
|
+
writeBuildHash();
|
|
1271
|
+
}, 150);
|
|
1272
|
+
});
|
|
1273
|
+
}
|
|
1274
|
+
var selects = bar.querySelectorAll('.rcf-filter-select');
|
|
1275
|
+
for (var i = 0; i < selects.length; i += 1) {
|
|
1276
|
+
selects[i].addEventListener('change', function () {
|
|
1277
|
+
applyBuildFilter();
|
|
1278
|
+
writeBuildHash();
|
|
1279
|
+
});
|
|
1280
|
+
}
|
|
1281
|
+
var toggles = bar.querySelectorAll('.rcf-filter-toggle input[type="checkbox"]');
|
|
1282
|
+
for (var j = 0; j < toggles.length; j += 1) {
|
|
1283
|
+
toggles[j].addEventListener('change', function () {
|
|
1284
|
+
applyBuildFilter();
|
|
1285
|
+
writeBuildHash();
|
|
1286
|
+
});
|
|
1287
|
+
}
|
|
1288
|
+
var expandBtn = bar.querySelector('.rcf-filter-expand');
|
|
1289
|
+
if (expandBtn) {
|
|
1290
|
+
expandBtn.addEventListener('click', function (ev) {
|
|
1291
|
+
ev.preventDefault && ev.preventDefault();
|
|
1292
|
+
var isCollapsed = expandBtn.getAttribute('data-expand-state') !== 'expanded';
|
|
1293
|
+
expandAllBuildSpecs(isCollapsed);
|
|
1294
|
+
});
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
|
|
1298
|
+
function wireBuildSubTabStrip() {
|
|
1299
|
+
var strip = buildSubTabStrip();
|
|
1300
|
+
if (!strip || strip.__rcfBuildSubWired) return;
|
|
1301
|
+
strip.__rcfBuildSubWired = true;
|
|
1302
|
+
var btns = strip.querySelectorAll('[role="tab"]');
|
|
1303
|
+
for (var i = 0; i < btns.length; i += 1) {
|
|
1304
|
+
btns[i].addEventListener('click', function (ev) {
|
|
1305
|
+
ev.preventDefault && ev.preventDefault();
|
|
1306
|
+
var sub = ev.currentTarget.getAttribute('data-sub');
|
|
1307
|
+
if (!sub) return;
|
|
1308
|
+
activateBuildSub(sub);
|
|
1309
|
+
if (sub === 'dag' && dagCanvas()) {
|
|
1310
|
+
applyDagFilters();
|
|
1311
|
+
renderDagInspector();
|
|
1312
|
+
}
|
|
1313
|
+
writeBuildHash();
|
|
1314
|
+
});
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
|
|
1318
|
+
function wireBuildTab() {
|
|
1319
|
+
wireBuildSubTabStrip();
|
|
1320
|
+
wireBuildFilterBar();
|
|
1321
|
+
wireBuildDag();
|
|
1322
|
+
}
|
|
1323
|
+
|
|
1324
|
+
// ---- Build / DAG (viewer UI refresh PR 6, TAC-4131, ADR-4133) --------
|
|
1325
|
+
//
|
|
1326
|
+
// Client-side wiring for the Build/DAG sub-tab. The server emits the
|
|
1327
|
+
// layout (toolbar, canvas with HTML nodes + SVG edges, inspector shell,
|
|
1328
|
+
// unconnected lane) plus an inline <script type="application/json"
|
|
1329
|
+
// data-rcf-dag-inspector-data> payload keyed by fbsId. The client:
|
|
1330
|
+
// - toggles filters (status chips, area, Buildable-now, Critical-path,
|
|
1331
|
+
// Show-unconnected) by setting data attributes on nodes and edges;
|
|
1332
|
+
// - handles click-to-highlight: selects a node, writes
|
|
1333
|
+
// `#tab=build&sub=dag&entity=<id>` through writeHash, outlines its
|
|
1334
|
+
// upstream closure in link colour and downstream in warning;
|
|
1335
|
+
// - fills the inspector from the inline payload (no outbound fetch,
|
|
1336
|
+
// no postMessage), with Open-in-Specs linking to
|
|
1337
|
+
// `#tab=build&sub=specs&entity=<id>` (REQ-002 / US-204 AC-204-7).
|
|
1338
|
+
|
|
1339
|
+
function dagRoot() { return document.querySelector('[data-rcf-dag="build"]'); }
|
|
1340
|
+
function dagCanvas() { return document.querySelector('[data-rcf-dag-canvas]'); }
|
|
1341
|
+
function dagToolbar() { return document.querySelector('[data-rcf-dag-toolbar]'); }
|
|
1342
|
+
function dagInspectorBody() { return document.querySelector('[data-rcf-dag-inspector-body]'); }
|
|
1343
|
+
|
|
1344
|
+
function parseDagInspectorPayload() {
|
|
1345
|
+
// PR 1 contract (standing criterion): payload rides on the inspector
|
|
1346
|
+
// shell as a `data-rcf-dag-inspector-data` attribute, not an inline
|
|
1347
|
+
// `<script>` body.
|
|
1348
|
+
var shell = document.querySelector('[data-rcf-dag-inspector-body]');
|
|
1349
|
+
if (!shell) return {};
|
|
1350
|
+
var raw = shell.getAttribute('data-rcf-dag-inspector-data');
|
|
1351
|
+
if (!raw) return {};
|
|
1352
|
+
try { return JSON.parse(raw); }
|
|
1353
|
+
catch (e) { return {}; }
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
function dagEscape(s) {
|
|
1357
|
+
return String(s == null ? '' : s)
|
|
1358
|
+
.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
|
|
1359
|
+
.replace(/"/g, '"').replace(/'/g, ''');
|
|
1360
|
+
}
|
|
1361
|
+
|
|
1362
|
+
function readDagState() {
|
|
1363
|
+
var state = {
|
|
1364
|
+
statuses: { notStarted: true, inProgress: true, complete: true, verified: true },
|
|
1365
|
+
domain: '',
|
|
1366
|
+
buildable: false,
|
|
1367
|
+
critical: false,
|
|
1368
|
+
unconnected: false,
|
|
1369
|
+
sel: null,
|
|
1370
|
+
};
|
|
1371
|
+
var bar = dagToolbar();
|
|
1372
|
+
if (bar) {
|
|
1373
|
+
var statusChips = bar.querySelectorAll('[data-rcf-dag-status]');
|
|
1374
|
+
for (var i = 0; i < statusChips.length; i += 1) {
|
|
1375
|
+
var k = statusChips[i].getAttribute('data-rcf-dag-status');
|
|
1376
|
+
state.statuses[k] = statusChips[i].getAttribute('aria-pressed') === 'true';
|
|
1377
|
+
}
|
|
1378
|
+
var dom = bar.querySelector('[data-rcf-dag-domain]');
|
|
1379
|
+
if (dom) state.domain = dom.value || '';
|
|
1380
|
+
var tbuild = bar.querySelector('[data-rcf-dag-toggle="buildable"]');
|
|
1381
|
+
if (tbuild) state.buildable = tbuild.getAttribute('aria-pressed') === 'true';
|
|
1382
|
+
var tcrit = bar.querySelector('[data-rcf-dag-toggle="critical"]');
|
|
1383
|
+
if (tcrit) state.critical = tcrit.getAttribute('aria-pressed') === 'true';
|
|
1384
|
+
var tunc = bar.querySelector('[data-rcf-dag-toggle="unconnected"]');
|
|
1385
|
+
if (tunc) state.unconnected = tunc.getAttribute('aria-pressed') === 'true';
|
|
1386
|
+
}
|
|
1387
|
+
var canvas = dagCanvas();
|
|
1388
|
+
if (canvas) state.sel = canvas.getAttribute('data-rcf-dag-sel') || null;
|
|
1389
|
+
return state;
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1392
|
+
function dagClosure(payload, startId, dir) {
|
|
1393
|
+
var out = {};
|
|
1394
|
+
if (!payload[startId]) return out;
|
|
1395
|
+
var stack = (dir === 'up' ? payload[startId].needs : payload[startId].waits).slice();
|
|
1396
|
+
while (stack.length > 0) {
|
|
1397
|
+
var cur = stack.pop();
|
|
1398
|
+
if (out[cur]) continue;
|
|
1399
|
+
out[cur] = true;
|
|
1400
|
+
var p = payload[cur];
|
|
1401
|
+
if (!p) continue;
|
|
1402
|
+
var next = dir === 'up' ? p.needs : p.waits;
|
|
1403
|
+
for (var i = 0; i < next.length; i += 1) stack.push(next[i]);
|
|
1404
|
+
}
|
|
1405
|
+
return out;
|
|
1406
|
+
}
|
|
1407
|
+
|
|
1408
|
+
function applyDagFilters() {
|
|
1409
|
+
var canvas = dagCanvas();
|
|
1410
|
+
if (!canvas) return;
|
|
1411
|
+
var payload = parseDagInspectorPayload();
|
|
1412
|
+
var state = readDagState();
|
|
1413
|
+
if (state.unconnected) canvas.removeAttribute('data-rcf-dag-unconnected-hidden');
|
|
1414
|
+
else canvas.setAttribute('data-rcf-dag-unconnected-hidden', '1');
|
|
1415
|
+
|
|
1416
|
+
var ups = {};
|
|
1417
|
+
var downs = {};
|
|
1418
|
+
if (state.sel && payload[state.sel]) {
|
|
1419
|
+
ups = dagClosure(payload, state.sel, 'up');
|
|
1420
|
+
downs = dagClosure(payload, state.sel, 'down');
|
|
1421
|
+
}
|
|
1422
|
+
if (state.sel) canvas.setAttribute('data-rcf-dag-sel', state.sel);
|
|
1423
|
+
else canvas.removeAttribute('data-rcf-dag-sel');
|
|
1424
|
+
|
|
1425
|
+
var nodes = canvas.querySelectorAll('.rcf-dag-node');
|
|
1426
|
+
for (var i = 0; i < nodes.length; i += 1) {
|
|
1427
|
+
var el = nodes[i];
|
|
1428
|
+
var id = el.getAttribute('data-fbs-id');
|
|
1429
|
+
var status = el.getAttribute('data-status') || '';
|
|
1430
|
+
var domain = el.getAttribute('data-domain') || '';
|
|
1431
|
+
var buildable = el.getAttribute('data-buildable') === '1';
|
|
1432
|
+
var critical = el.getAttribute('data-critical') === '1';
|
|
1433
|
+
var unconnected = el.getAttribute('data-unconnected') === '1';
|
|
1434
|
+
var hide = false;
|
|
1435
|
+
if (state.statuses[status] === false) hide = true;
|
|
1436
|
+
if (!hide && state.domain && domain !== state.domain) hide = true;
|
|
1437
|
+
if (!hide && state.buildable && !buildable) hide = true;
|
|
1438
|
+
if (!hide && state.critical && !critical) hide = true;
|
|
1439
|
+
if (unconnected && !state.unconnected) hide = true;
|
|
1440
|
+
if (hide) el.setAttribute('data-rcf-dag-hidden', '1');
|
|
1441
|
+
else el.removeAttribute('data-rcf-dag-hidden');
|
|
1442
|
+
var role = '';
|
|
1443
|
+
if (state.sel) {
|
|
1444
|
+
if (id === state.sel) role = 'sel';
|
|
1445
|
+
else if (ups[id]) role = 'up';
|
|
1446
|
+
else if (downs[id]) role = 'down';
|
|
1447
|
+
}
|
|
1448
|
+
if (role) el.setAttribute('data-rcf-dag-role', role);
|
|
1449
|
+
else el.removeAttribute('data-rcf-dag-role');
|
|
1450
|
+
if (state.critical && critical) el.setAttribute('data-rcf-dag-critical', 'on');
|
|
1451
|
+
else el.removeAttribute('data-rcf-dag-critical');
|
|
1452
|
+
}
|
|
1453
|
+
|
|
1454
|
+
var edges = canvas.querySelectorAll('[data-rcf-dag-edge]');
|
|
1455
|
+
for (var j = 0; j < edges.length; j += 1) {
|
|
1456
|
+
var ed = edges[j];
|
|
1457
|
+
var from = ed.getAttribute('data-from');
|
|
1458
|
+
var to = ed.getAttribute('data-to');
|
|
1459
|
+
var fromNode = canvas.querySelector('.rcf-dag-node[data-fbs-id="' + from + '"]');
|
|
1460
|
+
var toNode = canvas.querySelector('.rcf-dag-node[data-fbs-id="' + to + '"]');
|
|
1461
|
+
var filtered = (fromNode && fromNode.getAttribute('data-rcf-dag-hidden') === '1')
|
|
1462
|
+
|| (toNode && toNode.getAttribute('data-rcf-dag-hidden') === '1');
|
|
1463
|
+
if (filtered) ed.setAttribute('data-rcf-dag-hidden', '1');
|
|
1464
|
+
else ed.removeAttribute('data-rcf-dag-hidden');
|
|
1465
|
+
var erole = '';
|
|
1466
|
+
if (state.sel) {
|
|
1467
|
+
var fromUp = from === state.sel || ups[from];
|
|
1468
|
+
var toUp = to === state.sel || ups[to];
|
|
1469
|
+
var fromDown = from === state.sel || downs[from];
|
|
1470
|
+
var toDown = to === state.sel || downs[to];
|
|
1471
|
+
if (fromUp && toUp) erole = 'up';
|
|
1472
|
+
else if (fromDown && toDown) erole = 'down';
|
|
1473
|
+
}
|
|
1474
|
+
if (erole) ed.setAttribute('data-rcf-dag-edge-role', erole);
|
|
1475
|
+
else ed.removeAttribute('data-rcf-dag-edge-role');
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1479
|
+
function renderDagInspector() {
|
|
1480
|
+
var body = dagInspectorBody();
|
|
1481
|
+
if (!body) return;
|
|
1482
|
+
var payload = parseDagInspectorPayload();
|
|
1483
|
+
var state = readDagState();
|
|
1484
|
+
if (!state.sel || !payload[state.sel]) {
|
|
1485
|
+
body.innerHTML = '<div class="muted small">Select a build spec to see what it needs and what waits on it.</div>';
|
|
1486
|
+
return;
|
|
1487
|
+
}
|
|
1488
|
+
var f = payload[state.sel];
|
|
1489
|
+
var meta = '<div class="rcf-dag-inspector-meta">'
|
|
1490
|
+
+ '<span class="rcf-pill rcf-pill--doc-status rcf-pill--' + dagEscape((f.status || '').toLowerCase()) + '">' + dagEscape(f.status || 'unknown') + '</span>'
|
|
1491
|
+
+ (f.domain ? '<span class="rcf-badge rcf-badge--facet">' + dagEscape(f.domain) + '</span>' : '')
|
|
1492
|
+
+ '<span class="rcf-badge rcf-badge--count">AC ' + (f.acCount || 0) + '</span>'
|
|
1493
|
+
+ (f.size ? '<span class="rcf-badge rcf-badge--facet">' + dagEscape(f.size) + '</span>' : '')
|
|
1494
|
+
+ '<span class="rcf-badge rcf-badge--count">order ' + (f.buildOrder != null ? f.buildOrder : '') + '</span>'
|
|
1495
|
+
+ (f.buildable ? '<span class="rcf-pill rcf-pill--build-queue">buildable now</span>' : '')
|
|
1496
|
+
+ (f.critical ? '<span class="rcf-pill rcf-pill--doc-status">critical path</span>' : '')
|
|
1497
|
+
+ '</div>';
|
|
1498
|
+
var needsItems = (f.needsMeta || []).map(function (m) {
|
|
1499
|
+
return '<li><a class="mono" href="#" data-rcf-dag-go="' + dagEscape(m.id) + '">' + dagEscape(m.id) + '</a> <span>' + dagEscape(m.title) + '</span> <span class="rcf-pill rcf-pill--doc-status rcf-pill--' + dagEscape((m.status || '').toLowerCase()) + '">' + dagEscape(m.status || '?') + '</span></li>';
|
|
1500
|
+
}).join('');
|
|
1501
|
+
var needsBlock = '<h4>Needs first (' + (f.needs ? f.needs.length : 0) + ' direct, ' + (f.needsTotal || 0) + ' in total)</h4>'
|
|
1502
|
+
+ (needsItems ? '<ul class="rcf-dag-inspector-list">' + needsItems + '</ul>' : '<div class="muted small">Nothing.</div>');
|
|
1503
|
+
var waitsItems = (f.waitsMeta || []).map(function (m) {
|
|
1504
|
+
return '<li><a class="mono" href="#" data-rcf-dag-go="' + dagEscape(m.id) + '">' + dagEscape(m.id) + '</a> <span>' + dagEscape(m.title) + '</span></li>';
|
|
1505
|
+
}).join('');
|
|
1506
|
+
var waitsBlock = '<h4>Waits on this (' + (f.waits ? f.waits.length : 0) + ' direct, ' + (f.waitsTotal || 0) + ' in total)</h4>'
|
|
1507
|
+
+ (waitsItems ? '<ul class="rcf-dag-inspector-list">' + waitsItems + '</ul>' : '<div class="muted small">Nothing.</div>');
|
|
1508
|
+
var footer = '<p class="small" style="margin-top:0.8rem"><a href="#tab=build&sub=specs&entity=' + dagEscape(f.id) + '" data-rcf-dag-open-specs>Open in Specs</a> · <a href="#" data-rcf-dag-go="" class="muted">Clear selection</a></p>';
|
|
1509
|
+
body.innerHTML = '<div class="mono small" style="color:var(--sv-link)">' + dagEscape(f.id) + '</div>'
|
|
1510
|
+
+ '<h3>' + dagEscape(f.title) + '</h3>'
|
|
1511
|
+
+ meta
|
|
1512
|
+
+ needsBlock
|
|
1513
|
+
+ waitsBlock
|
|
1514
|
+
+ footer;
|
|
1515
|
+
|
|
1516
|
+
var goLinks = body.querySelectorAll('[data-rcf-dag-go]');
|
|
1517
|
+
for (var i = 0; i < goLinks.length; i += 1) {
|
|
1518
|
+
goLinks[i].addEventListener('click', function (ev) {
|
|
1519
|
+
ev.preventDefault && ev.preventDefault();
|
|
1520
|
+
var next = ev.currentTarget.getAttribute('data-rcf-dag-go');
|
|
1521
|
+
if (!next) selectDagNode(null);
|
|
1522
|
+
else selectDagNode(next);
|
|
1523
|
+
});
|
|
1524
|
+
}
|
|
1525
|
+
var specsLink = body.querySelector('[data-rcf-dag-open-specs]');
|
|
1526
|
+
if (specsLink) {
|
|
1527
|
+
specsLink.addEventListener('click', function (ev) {
|
|
1528
|
+
ev.preventDefault && ev.preventDefault();
|
|
1529
|
+
var href = ev.currentTarget.getAttribute('href') || '';
|
|
1530
|
+
writeHash(href, false);
|
|
1531
|
+
resolveHash(window.location.hash);
|
|
1532
|
+
});
|
|
1533
|
+
}
|
|
1534
|
+
}
|
|
1535
|
+
|
|
1536
|
+
function selectDagNode(id) {
|
|
1537
|
+
var canvas = dagCanvas();
|
|
1538
|
+
if (!canvas) return;
|
|
1539
|
+
var cur = canvas.getAttribute('data-rcf-dag-sel') || null;
|
|
1540
|
+
var payload = parseDagInspectorPayload();
|
|
1541
|
+
var next = id === cur ? null : id;
|
|
1542
|
+
if (next && !payload[next]) next = null;
|
|
1543
|
+
if (next) canvas.setAttribute('data-rcf-dag-sel', next);
|
|
1544
|
+
else canvas.removeAttribute('data-rcf-dag-sel');
|
|
1545
|
+
if (next && payload[next] && payload[next].unconnected) {
|
|
1546
|
+
var tunc = document.querySelector('[data-rcf-dag-toggle="unconnected"]');
|
|
1547
|
+
if (tunc && tunc.getAttribute('aria-pressed') !== 'true') tunc.setAttribute('aria-pressed', 'true');
|
|
1548
|
+
}
|
|
1549
|
+
applyDagFilters();
|
|
1550
|
+
renderDagInspector();
|
|
1551
|
+
writeBuildHash();
|
|
1552
|
+
if (next) {
|
|
1553
|
+
var el = canvas.querySelector('.rcf-dag-node[data-fbs-id="' + next + '"]');
|
|
1554
|
+
if (el) { try { el.scrollIntoView({ block: 'center', inline: 'center' }); } catch (e) { el.scrollIntoView(); } }
|
|
1555
|
+
}
|
|
1556
|
+
}
|
|
1557
|
+
|
|
1558
|
+
function wireBuildDag() {
|
|
1559
|
+
var root = dagRoot();
|
|
1560
|
+
if (!root || root.__rcfBuildDagWired) return;
|
|
1561
|
+
root.__rcfBuildDagWired = true;
|
|
1562
|
+
var canvas = dagCanvas();
|
|
1563
|
+
if (canvas) {
|
|
1564
|
+
var nodes = canvas.querySelectorAll('.rcf-dag-node');
|
|
1565
|
+
for (var i = 0; i < nodes.length; i += 1) {
|
|
1566
|
+
nodes[i].addEventListener('click', function (ev) {
|
|
1567
|
+
ev.preventDefault && ev.preventDefault();
|
|
1568
|
+
var id = ev.currentTarget.getAttribute('data-fbs-id');
|
|
1569
|
+
if (id) selectDagNode(id);
|
|
1570
|
+
});
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
var bar = dagToolbar();
|
|
1574
|
+
if (bar) {
|
|
1575
|
+
var statusChips = bar.querySelectorAll('[data-rcf-dag-status]');
|
|
1576
|
+
for (var j = 0; j < statusChips.length; j += 1) {
|
|
1577
|
+
statusChips[j].addEventListener('click', function (ev) {
|
|
1578
|
+
var btn = ev.currentTarget;
|
|
1579
|
+
btn.setAttribute('aria-pressed', btn.getAttribute('aria-pressed') === 'true' ? 'false' : 'true');
|
|
1580
|
+
applyDagFilters();
|
|
1581
|
+
});
|
|
1582
|
+
}
|
|
1583
|
+
var dom = bar.querySelector('[data-rcf-dag-domain]');
|
|
1584
|
+
if (dom) dom.addEventListener('change', function () { applyDagFilters(); });
|
|
1585
|
+
var toggles = bar.querySelectorAll('[data-rcf-dag-toggle]');
|
|
1586
|
+
for (var k = 0; k < toggles.length; k += 1) {
|
|
1587
|
+
toggles[k].addEventListener('click', function (ev) {
|
|
1588
|
+
var btn = ev.currentTarget;
|
|
1589
|
+
btn.setAttribute('aria-pressed', btn.getAttribute('aria-pressed') === 'true' ? 'false' : 'true');
|
|
1590
|
+
applyDagFilters();
|
|
1591
|
+
});
|
|
1592
|
+
}
|
|
1593
|
+
}
|
|
1594
|
+
applyDagFilters();
|
|
1595
|
+
renderDagInspector();
|
|
1596
|
+
}
|
|
1597
|
+
|
|
1598
|
+
// ---- EntitySelector (viewer UI refresh PR 3, decision 4) -----
|
|
1599
|
+
|
|
1600
|
+
function parseEntitySelectorPayload(root) {
|
|
1601
|
+
// Payload rides on the container as a `data-items` attribute so
|
|
1602
|
+
// the shell carries no inline <script> body (PR 1 contract).
|
|
1603
|
+
var raw = root.getAttribute('data-items');
|
|
1604
|
+
if (!raw) return [];
|
|
1605
|
+
try { return JSON.parse(raw); }
|
|
1606
|
+
catch (e) { return []; }
|
|
1607
|
+
}
|
|
1608
|
+
|
|
1609
|
+
function wireEntitySelector(root) {
|
|
1610
|
+
if (!root || root.__rcfEntitySelectorWired) return;
|
|
1611
|
+
root.__rcfEntitySelectorWired = true;
|
|
1612
|
+
var input = root.querySelector('.rcf-entity-selector-input');
|
|
1613
|
+
var results = root.querySelector('.rcf-entity-selector-results');
|
|
1614
|
+
var targetTab = root.getAttribute('data-target-tab') || 'requirements';
|
|
1615
|
+
var items = parseEntitySelectorPayload(root);
|
|
1616
|
+
if (!input || !results || items.length === 0) return;
|
|
1617
|
+
|
|
1618
|
+
function escapeHtml(s) {
|
|
1619
|
+
return String(s == null ? '' : s)
|
|
1620
|
+
.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
|
|
1621
|
+
.replace(/"/g, '"').replace(/'/g, ''');
|
|
1622
|
+
}
|
|
1623
|
+
|
|
1624
|
+
function render(matches) {
|
|
1625
|
+
if (matches.length === 0) {
|
|
1626
|
+
results.innerHTML = '<div class="rcf-entity-selector-empty muted small">No match.</div>';
|
|
1627
|
+
results.removeAttribute('hidden');
|
|
1628
|
+
return;
|
|
1629
|
+
}
|
|
1630
|
+
var html = '';
|
|
1631
|
+
for (var i = 0; i < matches.length; i += 1) {
|
|
1632
|
+
var m = matches[i];
|
|
1633
|
+
var hash = '#tab=' + encodeURIComponent(targetTab) + '&entity=' + encodeURIComponent(m.id);
|
|
1634
|
+
html += '<a class="rcf-entity-selector-result" href="' + escapeHtml(hash) + '" role="option" data-entity-id="' + escapeHtml(m.id) + '">'
|
|
1635
|
+
+ '<span class="rcf-entity-selector-result-id">' + escapeHtml(m.id) + '</span>'
|
|
1636
|
+
+ '<span class="rcf-entity-selector-result-title">' + escapeHtml(m.title) + '</span>'
|
|
1637
|
+
+ (m.facet ? '<span class="rcf-entity-selector-result-facet">' + escapeHtml(m.facet) + '</span>' : '')
|
|
1638
|
+
+ '</a>';
|
|
1639
|
+
}
|
|
1640
|
+
results.innerHTML = html;
|
|
1641
|
+
results.removeAttribute('hidden');
|
|
1642
|
+
}
|
|
1643
|
+
|
|
1644
|
+
function run() {
|
|
1645
|
+
var q = (input.value || '').trim().toLowerCase();
|
|
1646
|
+
if (!q) { results.innerHTML = ''; results.setAttribute('hidden', ''); return; }
|
|
1647
|
+
var out = [];
|
|
1648
|
+
for (var i = 0; i < items.length && out.length < 12; i += 1) {
|
|
1649
|
+
var it = items[i];
|
|
1650
|
+
var idL = (it.id || '').toLowerCase();
|
|
1651
|
+
var tL = (it.title || '').toLowerCase();
|
|
1652
|
+
if (idL.indexOf(q) === 0 || tL.indexOf(q) !== -1) out.push(it);
|
|
1653
|
+
}
|
|
1654
|
+
render(out);
|
|
1655
|
+
}
|
|
1656
|
+
|
|
1657
|
+
input.addEventListener('input', run);
|
|
1658
|
+
input.addEventListener('focus', function () { if (input.value.trim()) run(); });
|
|
1659
|
+
input.addEventListener('blur', function () {
|
|
1660
|
+
setTimeout(function () { results.setAttribute('hidden', ''); }, 150);
|
|
1661
|
+
});
|
|
1662
|
+
input.addEventListener('keydown', function (ev) {
|
|
1663
|
+
if (ev.key !== 'Enter') return;
|
|
1664
|
+
var first = results.querySelector('.rcf-entity-selector-result');
|
|
1665
|
+
if (!first) return;
|
|
1666
|
+
ev.preventDefault && ev.preventDefault();
|
|
1667
|
+
// Navigate via the Router: writes to hash so #entity=... resolves.
|
|
1668
|
+
var href = first.getAttribute('href');
|
|
1669
|
+
if (href) {
|
|
1670
|
+
writeHash(href, false);
|
|
1671
|
+
resolveHash(window.location.hash);
|
|
1672
|
+
}
|
|
1673
|
+
});
|
|
1674
|
+
}
|
|
1675
|
+
|
|
1676
|
+
function wireEntitySelectors() {
|
|
1677
|
+
var selectors = document.querySelectorAll('[data-rcf-entity-selector]');
|
|
1678
|
+
for (var i = 0; i < selectors.length; i += 1) wireEntitySelector(selectors[i]);
|
|
1679
|
+
}
|
|
1680
|
+
|
|
1681
|
+
// ---- ID lookup (viewer UI refresh PR 7, TAC-4132) --------------------
|
|
1682
|
+
//
|
|
1683
|
+
// SearchButton + LookupModal + Cmd/Ctrl+F. The index at `./index.json`
|
|
1684
|
+
// is fetched lazily on first open; the SSE tree-update broadcast sets
|
|
1685
|
+
// __rcfLookupDirty so the next open refetches. Rank order (design
|
|
1686
|
+
// doc section 6): a single character searches ids only; otherwise ids
|
|
1687
|
+
// rank first (exact > prefix > contains), then every query word must
|
|
1688
|
+
// match title or snippet, title above snippet; 20 results; matches
|
|
1689
|
+
// marked. A pick writes `#tab=<tab>&entity=<id>` through writeHash so
|
|
1690
|
+
// `?embed=` and `?theme=` survive (Dex contract, PR 1).
|
|
1691
|
+
|
|
1692
|
+
var lookupRows = null;
|
|
1693
|
+
var lookupFetching = false;
|
|
1694
|
+
var lookupLastQuery = null;
|
|
1695
|
+
var lookupResults = [];
|
|
1696
|
+
var lookupActiveIdx = -1;
|
|
1697
|
+
var lookupPrevFocus = null;
|
|
1698
|
+
var lookupLoadError = false;
|
|
1699
|
+
var lookupKeybindWired = false;
|
|
1700
|
+
|
|
1701
|
+
function lookupModal() { return document.querySelector('[data-rcf-lookup]'); }
|
|
1702
|
+
function lookupInput() { return document.querySelector('[data-rcf-lookup-input]'); }
|
|
1703
|
+
function lookupResultsList() { return document.querySelector('[data-rcf-lookup-results]'); }
|
|
1704
|
+
function lookupEmpty() { return document.querySelector('[data-rcf-lookup-empty]'); }
|
|
1705
|
+
function lookupEmptyMsg() { return document.querySelector('[data-rcf-lookup-empty-msg]'); }
|
|
1706
|
+
function lookupReload() { return document.querySelector('[data-rcf-lookup-reload]'); }
|
|
1707
|
+
function lookupStatus() { return document.querySelector('[data-rcf-lookup-status]'); }
|
|
1708
|
+
|
|
1709
|
+
function lookupEscapeHtml(s) {
|
|
1710
|
+
if (typeof s !== 'string') return '';
|
|
1711
|
+
return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
|
1712
|
+
}
|
|
1713
|
+
|
|
1714
|
+
function lookupMarkMatches(text, needles) {
|
|
1715
|
+
if (!text) return '';
|
|
1716
|
+
var lower = text.toLowerCase();
|
|
1717
|
+
var marks = [];
|
|
1718
|
+
for (var i = 0; i < needles.length; i += 1) {
|
|
1719
|
+
var n = needles[i];
|
|
1720
|
+
if (!n) continue;
|
|
1721
|
+
var from = 0;
|
|
1722
|
+
while (from <= lower.length) {
|
|
1723
|
+
var at = lower.indexOf(n, from);
|
|
1724
|
+
if (at === -1) break;
|
|
1725
|
+
marks.push([at, at + n.length]);
|
|
1726
|
+
from = at + n.length;
|
|
1727
|
+
}
|
|
1728
|
+
}
|
|
1729
|
+
if (marks.length === 0) return lookupEscapeHtml(text);
|
|
1730
|
+
marks.sort(function (a, b) { return a[0] - b[0]; });
|
|
1731
|
+
var merged = [];
|
|
1732
|
+
for (var j = 0; j < marks.length; j += 1) {
|
|
1733
|
+
var last = merged[merged.length - 1];
|
|
1734
|
+
if (last && marks[j][0] <= last[1]) last[1] = Math.max(last[1], marks[j][1]);
|
|
1735
|
+
else merged.push(marks[j].slice());
|
|
1736
|
+
}
|
|
1737
|
+
var out = '';
|
|
1738
|
+
var cursor = 0;
|
|
1739
|
+
for (var k = 0; k < merged.length; k += 1) {
|
|
1740
|
+
var start = merged[k][0];
|
|
1741
|
+
var end = merged[k][1];
|
|
1742
|
+
if (cursor < start) out += lookupEscapeHtml(text.slice(cursor, start));
|
|
1743
|
+
out += '<mark>' + lookupEscapeHtml(text.slice(start, end)) + '</mark>';
|
|
1744
|
+
cursor = end;
|
|
1745
|
+
}
|
|
1746
|
+
if (cursor < text.length) out += lookupEscapeHtml(text.slice(cursor));
|
|
1747
|
+
return out;
|
|
1748
|
+
}
|
|
1749
|
+
|
|
1750
|
+
function lookupRank(query, rows) {
|
|
1751
|
+
if (!query || !rows) return [];
|
|
1752
|
+
var q = String(query).trim().toLowerCase();
|
|
1753
|
+
if (!q) return [];
|
|
1754
|
+
var scored = [];
|
|
1755
|
+
// Single-character query: id-only match (design doc section 6).
|
|
1756
|
+
if (q.length === 1) {
|
|
1757
|
+
for (var i = 0; i < rows.length; i += 1) {
|
|
1758
|
+
var r = rows[i];
|
|
1759
|
+
var idLow = (r.id || '').toLowerCase();
|
|
1760
|
+
if (idLow.indexOf(q) !== -1) {
|
|
1761
|
+
var score = 0;
|
|
1762
|
+
if (idLow === q) score = 1000;
|
|
1763
|
+
else if (idLow.indexOf(q) === 0) score = 500;
|
|
1764
|
+
else score = 100;
|
|
1765
|
+
scored.push({ row: r, score: score, needles: [q] });
|
|
1766
|
+
}
|
|
1767
|
+
}
|
|
1768
|
+
} else {
|
|
1769
|
+
var words = q.split(/\s+/).filter(Boolean);
|
|
1770
|
+
for (var i2 = 0; i2 < rows.length; i2 += 1) {
|
|
1771
|
+
var r2 = rows[i2];
|
|
1772
|
+
var idLow2 = (r2.id || '').toLowerCase();
|
|
1773
|
+
var titleLow = (r2.title || '').toLowerCase();
|
|
1774
|
+
var snipLow = (r2.snippet || '').toLowerCase();
|
|
1775
|
+
var score2 = 0;
|
|
1776
|
+
// Id first: exact / prefix / contains against the full query.
|
|
1777
|
+
if (idLow2 === q) score2 = 10000;
|
|
1778
|
+
else if (idLow2.indexOf(q) === 0) score2 = 5000;
|
|
1779
|
+
else if (idLow2.indexOf(q) !== -1) score2 = 2500;
|
|
1780
|
+
else {
|
|
1781
|
+
// Word-match pass: every word must hit title or snippet.
|
|
1782
|
+
var titleHits = 0;
|
|
1783
|
+
var snipHits = 0;
|
|
1784
|
+
var allHit = true;
|
|
1785
|
+
for (var w = 0; w < words.length; w += 1) {
|
|
1786
|
+
var word = words[w];
|
|
1787
|
+
var inTitle = titleLow.indexOf(word) !== -1;
|
|
1788
|
+
var inSnip = snipLow.indexOf(word) !== -1;
|
|
1789
|
+
if (inTitle) titleHits += 1;
|
|
1790
|
+
else if (inSnip) snipHits += 1;
|
|
1791
|
+
else { allHit = false; break; }
|
|
1792
|
+
}
|
|
1793
|
+
if (!allHit) continue;
|
|
1794
|
+
// Title above snippet: title hits weighted higher than snippet.
|
|
1795
|
+
score2 = 1000 + titleHits * 50 + snipHits * 10;
|
|
1796
|
+
}
|
|
1797
|
+
if (score2 > 0) scored.push({ row: r2, score: score2, needles: words });
|
|
1798
|
+
}
|
|
1799
|
+
}
|
|
1800
|
+
scored.sort(function (a, b) {
|
|
1801
|
+
if (b.score !== a.score) return b.score - a.score;
|
|
1802
|
+
return (a.row.id || '').localeCompare(b.row.id || '');
|
|
1803
|
+
});
|
|
1804
|
+
return scored.slice(0, 20);
|
|
1805
|
+
}
|
|
1806
|
+
|
|
1807
|
+
function lookupKindLabel(kind) {
|
|
1808
|
+
switch (kind) {
|
|
1809
|
+
case 'prd': return 'PRD';
|
|
1810
|
+
case 'req': return 'REQ';
|
|
1811
|
+
case 'us': return 'US';
|
|
1812
|
+
case 'ac': return 'AC';
|
|
1813
|
+
case 'tad': return 'TAD';
|
|
1814
|
+
case 'tac': return 'TAC';
|
|
1815
|
+
case 'adr': return 'ADR';
|
|
1816
|
+
case 'bs': return 'BS';
|
|
1817
|
+
case 'fbs': return 'FBS';
|
|
1818
|
+
case 'ts': return 'TS';
|
|
1819
|
+
default: return kind || '';
|
|
1820
|
+
}
|
|
1821
|
+
}
|
|
1822
|
+
|
|
1823
|
+
function lookupRenderResults(results) {
|
|
1824
|
+
var list = lookupResultsList();
|
|
1825
|
+
var empty = lookupEmpty();
|
|
1826
|
+
var emptyMsg = lookupEmptyMsg();
|
|
1827
|
+
var reload = lookupReload();
|
|
1828
|
+
var status = lookupStatus();
|
|
1829
|
+
if (!list) return;
|
|
1830
|
+
if (results.length === 0) {
|
|
1831
|
+
list.innerHTML = '';
|
|
1832
|
+
list.hidden = true;
|
|
1833
|
+
var hasQuery = (lookupLastQuery || '').trim().length > 0;
|
|
1834
|
+
if (empty) empty.hidden = !lookupLoadError && !hasQuery;
|
|
1835
|
+
if (emptyMsg) emptyMsg.textContent = lookupLoadError ? 'The index could not be loaded.' : 'No matches.';
|
|
1836
|
+
if (reload) reload.hidden = !lookupLoadError;
|
|
1837
|
+
if (status) {
|
|
1838
|
+
if (lookupLoadError) status.textContent = 'Index failed to load.';
|
|
1839
|
+
else if (hasQuery) status.textContent = 'No matches.';
|
|
1840
|
+
else status.textContent = (lookupRows ? 'Type an id or a few words.' : 'Loading index...');
|
|
1841
|
+
}
|
|
1842
|
+
return;
|
|
1843
|
+
}
|
|
1844
|
+
if (empty) empty.hidden = true;
|
|
1845
|
+
if (reload) reload.hidden = true;
|
|
1846
|
+
list.hidden = false;
|
|
1847
|
+
var html = '';
|
|
1848
|
+
for (var i = 0; i < results.length; i += 1) {
|
|
1849
|
+
var scored = results[i];
|
|
1850
|
+
var r = scored.row;
|
|
1851
|
+
var needles = scored.needles || [];
|
|
1852
|
+
var active = i === lookupActiveIdx ? ' is-active' : '';
|
|
1853
|
+
var markedId = lookupMarkMatches(r.id || '', needles);
|
|
1854
|
+
var markedTitle = lookupMarkMatches(r.title || '', needles);
|
|
1855
|
+
var markedSnip = lookupMarkMatches(r.snippet || '', needles);
|
|
1856
|
+
var parentHtml = r.parent ? ' <span class="rcf-lookup-parent">in ' + lookupEscapeHtml(r.parent) + '</span>' : '';
|
|
1857
|
+
html += '<li class="rcf-lookup-row' + active + '" role="option"'
|
|
1858
|
+
+ (i === lookupActiveIdx ? ' aria-selected="true"' : '')
|
|
1859
|
+
+ ' data-rcf-lookup-row data-rcf-lookup-id="' + lookupEscapeHtml(r.id || '')
|
|
1860
|
+
+ '" data-rcf-lookup-tab="' + lookupEscapeHtml(r.tab || '')
|
|
1861
|
+
+ '" data-rcf-lookup-kind="' + lookupEscapeHtml(r.kind || '')
|
|
1862
|
+
+ '" data-rcf-lookup-parent="' + lookupEscapeHtml(r.parent || '') + '" data-rcf-lookup-idx="' + i + '">'
|
|
1863
|
+
+ '<span class="rcf-lookup-kind rcf-lookup-kind-' + lookupEscapeHtml(r.kind || '') + '">' + lookupKindLabel(r.kind) + '</span>'
|
|
1864
|
+
+ '<span class="rcf-lookup-id">' + markedId + '</span>'
|
|
1865
|
+
+ (r.title ? '<span class="rcf-lookup-title">' + markedTitle + '</span>' : '')
|
|
1866
|
+
+ parentHtml
|
|
1867
|
+
+ (r.snippet ? '<p class="rcf-lookup-snippet">' + markedSnip + '</p>' : '')
|
|
1868
|
+
+ '</li>';
|
|
1869
|
+
}
|
|
1870
|
+
list.innerHTML = html;
|
|
1871
|
+
if (status) status.textContent = results.length + ' result' + (results.length === 1 ? '' : 's') + '.';
|
|
1872
|
+
}
|
|
1873
|
+
|
|
1874
|
+
function lookupRun() {
|
|
1875
|
+
var input = lookupInput();
|
|
1876
|
+
if (!input) return;
|
|
1877
|
+
var query = input.value || '';
|
|
1878
|
+
lookupLastQuery = query;
|
|
1879
|
+
if (!lookupRows) {
|
|
1880
|
+
lookupResults = [];
|
|
1881
|
+
lookupActiveIdx = -1;
|
|
1882
|
+
var list = lookupResultsList();
|
|
1883
|
+
if (list) { list.innerHTML = ''; list.hidden = true; }
|
|
1884
|
+
var empty = lookupEmpty();
|
|
1885
|
+
var emptyMsg = lookupEmptyMsg();
|
|
1886
|
+
var reload = lookupReload();
|
|
1887
|
+
if (empty) empty.hidden = false;
|
|
1888
|
+
if (emptyMsg) emptyMsg.textContent = lookupLoadError ? 'The index could not be loaded.' : (lookupFetching ? 'Loading index...' : 'Index not loaded.');
|
|
1889
|
+
if (reload) reload.hidden = !lookupLoadError;
|
|
1890
|
+
return;
|
|
1891
|
+
}
|
|
1892
|
+
lookupResults = lookupRank(query, lookupRows);
|
|
1893
|
+
lookupActiveIdx = lookupResults.length > 0 ? 0 : -1;
|
|
1894
|
+
lookupRenderResults(lookupResults);
|
|
1895
|
+
}
|
|
1896
|
+
|
|
1897
|
+
function lookupLoad(force) {
|
|
1898
|
+
if (lookupFetching) return;
|
|
1899
|
+
if (lookupRows && !force && !window.__rcfLookupDirty) { lookupRun(); return; }
|
|
1900
|
+
lookupFetching = true;
|
|
1901
|
+
lookupLoadError = false;
|
|
1902
|
+
var status = lookupStatus();
|
|
1903
|
+
if (status) status.textContent = 'Loading index...';
|
|
1904
|
+
var xhr = new XMLHttpRequest();
|
|
1905
|
+
xhr.open('GET', './index.json', true);
|
|
1906
|
+
xhr.onreadystatechange = function () {
|
|
1907
|
+
if (xhr.readyState !== 4) return;
|
|
1908
|
+
lookupFetching = false;
|
|
1909
|
+
var ok = xhr.status >= 200 && xhr.status < 300;
|
|
1910
|
+
var parsed = null;
|
|
1911
|
+
if (ok) {
|
|
1912
|
+
try { parsed = JSON.parse(xhr.responseText); } catch (e) { parsed = null; }
|
|
1913
|
+
}
|
|
1914
|
+
if (!ok || !parsed || !Array.isArray(parsed.rows)) {
|
|
1915
|
+
lookupLoadError = true;
|
|
1916
|
+
lookupRows = null;
|
|
1917
|
+
lookupRun();
|
|
1918
|
+
return;
|
|
1919
|
+
}
|
|
1920
|
+
lookupLoadError = false;
|
|
1921
|
+
lookupRows = parsed.rows;
|
|
1922
|
+
window.__rcfLookupDirty = false;
|
|
1923
|
+
lookupRun();
|
|
1924
|
+
};
|
|
1925
|
+
try { xhr.send(); } catch (e) { lookupFetching = false; lookupLoadError = true; lookupRun(); }
|
|
1926
|
+
}
|
|
1927
|
+
|
|
1928
|
+
function lookupOpen() {
|
|
1929
|
+
var modal = lookupModal();
|
|
1930
|
+
if (!modal) return;
|
|
1931
|
+
if (modal.hidden === false) return;
|
|
1932
|
+
lookupPrevFocus = document.activeElement;
|
|
1933
|
+
modal.hidden = false;
|
|
1934
|
+
document.documentElement.setAttribute('data-rcf-lookup-open', '1');
|
|
1935
|
+
var input = lookupInput();
|
|
1936
|
+
if (input) {
|
|
1937
|
+
input.value = '';
|
|
1938
|
+
try { input.focus(); } catch (e) { /* soft */ }
|
|
1939
|
+
}
|
|
1940
|
+
lookupLastQuery = '';
|
|
1941
|
+
lookupResults = [];
|
|
1942
|
+
lookupActiveIdx = -1;
|
|
1943
|
+
var list = lookupResultsList();
|
|
1944
|
+
if (list) { list.innerHTML = ''; list.hidden = true; }
|
|
1945
|
+
var empty = lookupEmpty();
|
|
1946
|
+
if (empty) empty.hidden = true;
|
|
1947
|
+
lookupLoad(false);
|
|
1948
|
+
}
|
|
1949
|
+
|
|
1950
|
+
function lookupClose() {
|
|
1951
|
+
var modal = lookupModal();
|
|
1952
|
+
if (!modal || modal.hidden) return;
|
|
1953
|
+
modal.hidden = true;
|
|
1954
|
+
document.documentElement.removeAttribute('data-rcf-lookup-open');
|
|
1955
|
+
if (lookupPrevFocus && typeof lookupPrevFocus.focus === 'function') {
|
|
1956
|
+
try { lookupPrevFocus.focus(); } catch (e) { /* soft */ }
|
|
1957
|
+
}
|
|
1958
|
+
lookupPrevFocus = null;
|
|
1959
|
+
}
|
|
1960
|
+
|
|
1961
|
+
function lookupMove(delta) {
|
|
1962
|
+
if (lookupResults.length === 0) return;
|
|
1963
|
+
var next = lookupActiveIdx + delta;
|
|
1964
|
+
if (next < 0) next = lookupResults.length - 1;
|
|
1965
|
+
else if (next >= lookupResults.length) next = 0;
|
|
1966
|
+
lookupActiveIdx = next;
|
|
1967
|
+
lookupRenderResults(lookupResults);
|
|
1968
|
+
var row = document.querySelector('[data-rcf-lookup-row][data-rcf-lookup-idx="' + next + '"]');
|
|
1969
|
+
if (row && typeof row.scrollIntoView === 'function') {
|
|
1970
|
+
try { row.scrollIntoView({ block: 'nearest' }); } catch (e) { /* soft */ }
|
|
1971
|
+
}
|
|
1972
|
+
}
|
|
1973
|
+
|
|
1974
|
+
function lookupPick(row) {
|
|
1975
|
+
if (!row) return;
|
|
1976
|
+
var id = row.getAttribute('data-rcf-lookup-id');
|
|
1977
|
+
var tab = row.getAttribute('data-rcf-lookup-tab');
|
|
1978
|
+
if (!id || !tab) return;
|
|
1979
|
+
// Design decision 6: test suites render inside their owning US (not
|
|
1980
|
+
// a Build sub-tab). A TS pick re-routes to the US id so the Router
|
|
1981
|
+
// opens the US and the TS card inside it (viewer stream carry).
|
|
1982
|
+
var kind = row.getAttribute('data-rcf-lookup-kind');
|
|
1983
|
+
var parentId = row.getAttribute('data-rcf-lookup-parent');
|
|
1984
|
+
if (kind === 'ts' && parentId) { id = parentId; tab = 'requirements'; }
|
|
1985
|
+
lookupClose();
|
|
1986
|
+
// writeHash preserves ?embed=/?theme=/... (Dex contract, PR 1); the
|
|
1987
|
+
// Router's hashchange listener then activates the tab and opens
|
|
1988
|
+
// every ancestor DocRow (resolveHash).
|
|
1989
|
+
writeHash('#tab=' + encodeURIComponent(tab) + '&entity=' + encodeURIComponent(id), false);
|
|
1990
|
+
// If the hash was already the same (user picked the current entity
|
|
1991
|
+
// again), writeHash is a no-op and no hashchange fires. Re-resolve
|
|
1992
|
+
// to re-flash the target in that case.
|
|
1993
|
+
resolveHash(window.location.hash);
|
|
1994
|
+
}
|
|
1995
|
+
|
|
1996
|
+
function lookupOnKeydown(ev) {
|
|
1997
|
+
if (ev.key === 'Escape') {
|
|
1998
|
+
ev.preventDefault && ev.preventDefault();
|
|
1999
|
+
lookupClose();
|
|
2000
|
+
return;
|
|
2001
|
+
}
|
|
2002
|
+
if (ev.key === 'ArrowDown') {
|
|
2003
|
+
ev.preventDefault && ev.preventDefault();
|
|
2004
|
+
lookupMove(1);
|
|
2005
|
+
return;
|
|
2006
|
+
}
|
|
2007
|
+
if (ev.key === 'ArrowUp') {
|
|
2008
|
+
ev.preventDefault && ev.preventDefault();
|
|
2009
|
+
lookupMove(-1);
|
|
2010
|
+
return;
|
|
2011
|
+
}
|
|
2012
|
+
if (ev.key === 'Enter') {
|
|
2013
|
+
ev.preventDefault && ev.preventDefault();
|
|
2014
|
+
if (lookupActiveIdx < 0 || lookupActiveIdx >= lookupResults.length) return;
|
|
2015
|
+
var row = document.querySelector('[data-rcf-lookup-row][data-rcf-lookup-idx="' + lookupActiveIdx + '"]');
|
|
2016
|
+
lookupPick(row);
|
|
2017
|
+
}
|
|
2018
|
+
}
|
|
2019
|
+
|
|
2020
|
+
function lookupOnInput() {
|
|
2021
|
+
lookupRun();
|
|
2022
|
+
}
|
|
2023
|
+
|
|
2024
|
+
// Readiness StageLegend (viewer UI refresh PR 8). Any element carrying
|
|
2025
|
+
// `data-rcf-stage-ref="Dn"` opens the stage legend dialog focused on
|
|
2026
|
+
// that row. The dialog is server-rendered (readiness/stage-legend.js);
|
|
2027
|
+
// this wiring is purely a click + <dialog>.showModal() delegation.
|
|
2028
|
+
var stageLegendWired = false;
|
|
2029
|
+
function wireStageLegend() {
|
|
2030
|
+
if (stageLegendWired) return;
|
|
2031
|
+
stageLegendWired = true;
|
|
2032
|
+
document.addEventListener('click', function (ev) {
|
|
2033
|
+
var el = ev.target;
|
|
2034
|
+
while (el && el !== document.body) {
|
|
2035
|
+
if (el.getAttribute && el.getAttribute('data-rcf-stage-ref') !== null) {
|
|
2036
|
+
var stage = el.getAttribute('data-rcf-stage-ref');
|
|
2037
|
+
var dialog = document.getElementById('rcf-stage-legend');
|
|
2038
|
+
if (!dialog) return;
|
|
2039
|
+
var rows = dialog.querySelectorAll('tr[data-stage]');
|
|
2040
|
+
for (var i = 0; i < rows.length; i += 1) {
|
|
2041
|
+
if (rows[i].getAttribute('data-stage') === stage) {
|
|
2042
|
+
rows[i].classList.add('rcf-stage-legend__highlighted');
|
|
2043
|
+
} else {
|
|
2044
|
+
rows[i].classList.remove('rcf-stage-legend__highlighted');
|
|
2045
|
+
}
|
|
2046
|
+
}
|
|
2047
|
+
if (typeof dialog.showModal === 'function' && !dialog.open) {
|
|
2048
|
+
ev.preventDefault && ev.preventDefault();
|
|
2049
|
+
dialog.showModal();
|
|
2050
|
+
} else if (!dialog.open) {
|
|
2051
|
+
ev.preventDefault && ev.preventDefault();
|
|
2052
|
+
dialog.setAttribute('open', '');
|
|
2053
|
+
}
|
|
2054
|
+
return;
|
|
2055
|
+
}
|
|
2056
|
+
el = el.parentNode;
|
|
2057
|
+
}
|
|
2058
|
+
});
|
|
2059
|
+
}
|
|
2060
|
+
|
|
2061
|
+
function wireLookup() {
|
|
2062
|
+
var modal = lookupModal();
|
|
2063
|
+
if (modal && !modal.__rcfLookupWired) {
|
|
2064
|
+
modal.__rcfLookupWired = true;
|
|
2065
|
+
var input = lookupInput();
|
|
2066
|
+
if (input) {
|
|
2067
|
+
input.addEventListener('input', lookupOnInput);
|
|
2068
|
+
input.addEventListener('keydown', lookupOnKeydown);
|
|
2069
|
+
}
|
|
2070
|
+
var closeBtn = document.querySelector('[data-rcf-lookup-close]');
|
|
2071
|
+
if (closeBtn) closeBtn.addEventListener('click', function (ev) { ev.preventDefault && ev.preventDefault(); lookupClose(); });
|
|
2072
|
+
var backdrop = document.querySelector('[data-rcf-lookup-backdrop]');
|
|
2073
|
+
if (backdrop) backdrop.addEventListener('click', function () { lookupClose(); });
|
|
2074
|
+
var reload = lookupReload();
|
|
2075
|
+
if (reload) reload.addEventListener('click', function (ev) { ev.preventDefault && ev.preventDefault(); lookupLoad(true); });
|
|
2076
|
+
var list = lookupResultsList();
|
|
2077
|
+
if (list) {
|
|
2078
|
+
list.addEventListener('click', function (ev) {
|
|
2079
|
+
var el = ev.target;
|
|
2080
|
+
while (el && el !== list) {
|
|
2081
|
+
if (el.getAttribute && el.getAttribute('data-rcf-lookup-row') !== null) {
|
|
2082
|
+
ev.preventDefault && ev.preventDefault();
|
|
2083
|
+
lookupPick(el);
|
|
2084
|
+
return;
|
|
2085
|
+
}
|
|
2086
|
+
el = el.parentNode;
|
|
2087
|
+
}
|
|
2088
|
+
});
|
|
2089
|
+
list.addEventListener('mousemove', function (ev) {
|
|
2090
|
+
var el = ev.target;
|
|
2091
|
+
while (el && el !== list) {
|
|
2092
|
+
if (el.getAttribute && el.getAttribute('data-rcf-lookup-idx') !== null) {
|
|
2093
|
+
var idx = Number(el.getAttribute('data-rcf-lookup-idx'));
|
|
2094
|
+
if (!Number.isNaN(idx) && idx !== lookupActiveIdx) {
|
|
2095
|
+
lookupActiveIdx = idx;
|
|
2096
|
+
lookupRenderResults(lookupResults);
|
|
2097
|
+
}
|
|
2098
|
+
return;
|
|
2099
|
+
}
|
|
2100
|
+
el = el.parentNode;
|
|
2101
|
+
}
|
|
2102
|
+
});
|
|
2103
|
+
}
|
|
2104
|
+
}
|
|
2105
|
+
var btn = document.querySelector('[data-rcf-search]');
|
|
2106
|
+
if (btn && !btn.__rcfLookupWired) {
|
|
2107
|
+
btn.__rcfLookupWired = true;
|
|
2108
|
+
btn.addEventListener('click', function (ev) { ev.preventDefault && ev.preventDefault(); lookupOpen(); });
|
|
2109
|
+
}
|
|
2110
|
+
if (!lookupKeybindWired) {
|
|
2111
|
+
lookupKeybindWired = true;
|
|
2112
|
+
// Cmd/Ctrl+F opens the modal; Cmd/Ctrl+Shift+F stays the browser's
|
|
2113
|
+
// in-page find (design doc section 11 recommendation 1).
|
|
2114
|
+
document.addEventListener('keydown', function (ev) {
|
|
2115
|
+
var mod = ev.ctrlKey || ev.metaKey;
|
|
2116
|
+
if (!mod) return;
|
|
2117
|
+
if (ev.shiftKey) return;
|
|
2118
|
+
if ((ev.key === 'f' || ev.key === 'F')) {
|
|
2119
|
+
ev.preventDefault && ev.preventDefault();
|
|
2120
|
+
var modalEl = lookupModal();
|
|
2121
|
+
if (modalEl && modalEl.hidden === false) {
|
|
2122
|
+
var inp = lookupInput();
|
|
2123
|
+
if (inp) try { inp.focus(); inp.select && inp.select(); } catch (e) { /* soft */ }
|
|
2124
|
+
} else {
|
|
2125
|
+
lookupOpen();
|
|
2126
|
+
}
|
|
2127
|
+
}
|
|
2128
|
+
});
|
|
2129
|
+
}
|
|
2130
|
+
}
|
|
2131
|
+
|
|
2132
|
+
var hashchangeWired = false;
|
|
2133
|
+
|
|
2134
|
+
// AC-205-5: a mount URL of `?tab=requirements&entity=US-304` lands on the
|
|
2135
|
+
// same position at first paint. The hash-router owns tab + entity, so we
|
|
2136
|
+
// promote the tab/sub/entity query params into the hash fragment at boot
|
|
2137
|
+
// when no explicit hash is already set. embed/theme stay in the query so
|
|
2138
|
+
// urlWithHash keeps the Dex contract.
|
|
2139
|
+
function bootHashFromQuery() {
|
|
2140
|
+
if (window.location.hash) return;
|
|
2141
|
+
var q = parseQuery(window.location.search);
|
|
2142
|
+
var parts = [];
|
|
2143
|
+
if (q.tab) parts.push('tab=' + encodeURIComponent(q.tab));
|
|
2144
|
+
if (q.sub) parts.push('sub=' + encodeURIComponent(q.sub));
|
|
2145
|
+
if (q.entity) parts.push('entity=' + encodeURIComponent(q.entity));
|
|
2146
|
+
if (parts.length === 0) return;
|
|
2147
|
+
try {
|
|
2148
|
+
if (window.history && typeof window.history.replaceState === 'function') {
|
|
2149
|
+
window.history.replaceState(null, '', window.location.pathname + window.location.search + '#' + parts.join('&'));
|
|
2150
|
+
} else {
|
|
2151
|
+
window.location.hash = parts.join('&');
|
|
2152
|
+
}
|
|
2153
|
+
} catch (err) { /* best effort; resolveHash will no-op on empty hash */ }
|
|
2154
|
+
}
|
|
2155
|
+
|
|
2156
|
+
function onReady() {
|
|
2157
|
+
initShellFromQuery();
|
|
2158
|
+
bootHashFromQuery();
|
|
2159
|
+
wireThemeMessages();
|
|
2160
|
+
initMermaid();
|
|
2161
|
+
wireTabs();
|
|
2162
|
+
wireProductMap();
|
|
2163
|
+
wireRequirementsFilterBar();
|
|
2164
|
+
wireArchitectureFilterBars();
|
|
2165
|
+
wireBuildTab();
|
|
2166
|
+
wireEntitySelectors();
|
|
2167
|
+
wireFixturePage();
|
|
2168
|
+
wireLookup();
|
|
2169
|
+
wireStageLegend();
|
|
2170
|
+
resolveHash(window.location.hash);
|
|
2171
|
+
if (!hashchangeWired) {
|
|
2172
|
+
hashchangeWired = true;
|
|
2173
|
+
window.addEventListener('hashchange', function () {
|
|
2174
|
+
resolveHash(window.location.hash);
|
|
2175
|
+
});
|
|
2176
|
+
}
|
|
2177
|
+
}
|
|
2178
|
+
|
|
2179
|
+
window.rcfPage = window.rcfPage || {};
|
|
2180
|
+
window.rcfPage.init = onReady;
|
|
2181
|
+
// Shared helpers available for later tabs to call. The toast helper
|
|
2182
|
+
// is the one the fixture page demos; later PRs reuse it for the
|
|
2183
|
+
// ID-lookup copy-id confirmation and the DAG inspector "linked"
|
|
2184
|
+
// acknowledgement.
|
|
2185
|
+
window.rcfView = window.rcfView || {};
|
|
2186
|
+
window.rcfView.showToast = showToast;
|
|
2187
|
+
|
|
2188
|
+
if (document.readyState === 'loading') {
|
|
2189
|
+
document.addEventListener('DOMContentLoaded', onReady);
|
|
2190
|
+
} else {
|
|
2191
|
+
onReady();
|
|
2192
|
+
}
|
|
2193
|
+
})();
|