rcf-lite 0.20.0 → 0.22.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 +39 -0
- package/blueprints/application-account-settings/CHANGELOG.md +12 -0
- package/blueprints/application-account-settings/README.md +114 -0
- package/blueprints/application-account-settings/blueprint.json +234 -0
- package/blueprints/application-account-settings/contributions/adrs/adr-2601-application-account-settings-capability-vocabulary.json +20 -0
- package/blueprints/application-account-settings/contributions/adrs/adr-2602-application-account-settings-security-surface-shape.json +20 -0
- package/blueprints/application-account-settings/contributions/adrs/adr-2603-application-account-settings-theme-persistence.json +20 -0
- package/blueprints/application-account-settings/contributions/adrs/adr-2604-application-account-settings-reauth-window.json +20 -0
- package/blueprints/application-account-settings/contributions/requirements/application-account-settings-req-001.json +18 -0
- package/blueprints/application-account-settings/contributions/requirements/application-account-settings-req-002.json +18 -0
- package/blueprints/application-account-settings/contributions/requirements/application-account-settings-req-003.json +18 -0
- package/blueprints/application-account-settings/contributions/requirements/application-account-settings-req-004.json +18 -0
- package/blueprints/application-account-settings/contributions/requirements/application-account-settings-req-005.json +18 -0
- package/blueprints/application-account-settings/contributions/requirements/application-account-settings-req-006.json +18 -0
- package/blueprints/application-account-settings/contributions/tacs/tac-2601-application-account-settings-shell.json +41 -0
- package/blueprints/application-account-settings/contributions/tacs/tac-2602-application-account-settings-capability-discovery.json +28 -0
- package/blueprints/application-account-settings/contributions/tacs/tac-2603-application-account-settings-hosted-ui-bridge.json +35 -0
- package/blueprints/application-account-settings/contributions/tacs/tac-2604-application-account-settings-session-store.json +40 -0
- package/blueprints/application-account-settings/contributions/user-stories/application-account-settings-us-25101.json +34 -0
- package/blueprints/application-account-settings/contributions/user-stories/application-account-settings-us-25102.json +27 -0
- package/blueprints/application-account-settings/contributions/user-stories/application-account-settings-us-25103.json +27 -0
- package/blueprints/application-account-settings/contributions/user-stories/application-account-settings-us-25104.json +27 -0
- package/blueprints/application-account-settings/contributions/user-stories/application-account-settings-us-25105.json +33 -0
- package/blueprints/application-account-settings/contributions/user-stories/application-account-settings-us-25106.json +27 -0
- package/blueprints/application-account-settings/contributions/user-stories/application-account-settings-us-25107.json +27 -0
- package/blueprints/application-account-settings/contributions/user-stories/application-account-settings-us-25108.json +27 -0
- package/blueprints/application-account-settings/contributions/user-stories/application-account-settings-us-25109.json +33 -0
- package/blueprints/application-account-settings/contributions/user-stories/application-account-settings-us-25110.json +27 -0
- package/blueprints/application-account-settings/docs/topics.md +48 -0
- package/blueprints/application-account-settings/guide/application-account-settings.md +30 -0
- package/blueprints/application-account-settings/probe-packs/application-account-settings.pack.mjs +246 -0
- package/blueprints/application-admin-console/CHANGELOG.md +11 -0
- package/blueprints/application-admin-console/README.md +98 -0
- package/blueprints/application-admin-console/blueprint.json +226 -0
- package/blueprints/application-admin-console/contributions/adrs/adr-2201-application-admin-console-capability-vocabulary.json +25 -0
- package/blueprints/application-admin-console/contributions/adrs/adr-2202-application-admin-console-baseline-roles.json +25 -0
- package/blueprints/application-admin-console/contributions/adrs/adr-2203-application-admin-console-invite-transport.json +20 -0
- package/blueprints/application-admin-console/contributions/adrs/adr-2204-application-admin-console-audit-retention.json +20 -0
- package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-001.json +18 -0
- package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-002.json +18 -0
- package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-003.json +18 -0
- package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-004.json +18 -0
- package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-005.json +18 -0
- package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-006.json +18 -0
- package/blueprints/application-admin-console/contributions/tacs/tac-2201-application-admin-console-shell.json +40 -0
- package/blueprints/application-admin-console/contributions/tacs/tac-2202-application-admin-console-capability-discovery.json +44 -0
- package/blueprints/application-admin-console/contributions/tacs/tac-2203-application-admin-console-permission-matrix.json +34 -0
- package/blueprints/application-admin-console/contributions/tacs/tac-2204-application-admin-console-audit-view.json +40 -0
- package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21101.json +34 -0
- package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21102.json +34 -0
- package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21103.json +34 -0
- package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21104.json +28 -0
- package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21105.json +34 -0
- package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21106.json +27 -0
- package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21107.json +27 -0
- package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21108.json +27 -0
- package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21109.json +33 -0
- package/blueprints/application-admin-console/docs/topics.md +42 -0
- package/blueprints/application-admin-console/guide/application-admin-console.md +29 -0
- package/blueprints/application-admin-console/probe-packs/application-admin-console.pack.mjs +182 -0
- package/blueprints/application-api-rest/docs/topics.md +13 -1
- package/blueprints/application-charts/CHANGELOG.md +12 -0
- package/blueprints/application-charts/README.md +73 -0
- package/blueprints/application-charts/blueprint.json +26 -0
- package/blueprints/application-charts/contributions/adrs/adr-1901-application-charts-engine-choice.json +25 -0
- package/blueprints/application-charts/contributions/adrs/adr-1902-application-charts-accessible-palette.json +25 -0
- package/blueprints/application-charts/contributions/adrs/adr-1903-application-charts-motion.json +25 -0
- package/blueprints/application-charts/contributions/requirements/application-charts-req-001.json +15 -0
- package/blueprints/application-charts/contributions/requirements/application-charts-req-002.json +15 -0
- package/blueprints/application-charts/contributions/requirements/application-charts-req-003.json +15 -0
- package/blueprints/application-charts/contributions/requirements/application-charts-req-004.json +15 -0
- package/blueprints/application-charts/contributions/tacs/tac-1901-application-charts-render-shell.json +42 -0
- package/blueprints/application-charts/contributions/tacs/tac-1902-application-charts-keyboard-traversal.json +40 -0
- package/blueprints/application-charts/contributions/user-stories/application-charts-us-18101.json +35 -0
- package/blueprints/application-charts/contributions/user-stories/application-charts-us-18102.json +35 -0
- package/blueprints/application-charts/contributions/user-stories/application-charts-us-18103.json +35 -0
- package/blueprints/application-charts/contributions/user-stories/application-charts-us-18104.json +35 -0
- package/blueprints/application-charts/contributions/user-stories/application-charts-us-18105.json +35 -0
- package/blueprints/application-charts/contributions/user-stories/application-charts-us-18106.json +35 -0
- package/blueprints/application-charts/docs/topics.md +44 -0
- package/blueprints/application-charts/guide/application-charts.md +44 -0
- package/blueprints/application-charts/probe-packs/application-charts.pack.mjs +191 -0
- package/blueprints/application-dashboard/CHANGELOG.md +10 -0
- package/blueprints/application-dashboard/README.md +102 -0
- package/blueprints/application-dashboard/assets/guidance/dashboard-design.md +124 -0
- package/blueprints/application-dashboard/blueprint.json +29 -0
- package/blueprints/application-dashboard/contributions/adrs/adr-2001-application-dashboard-primary-kpi-enum.json +25 -0
- package/blueprints/application-dashboard/contributions/adrs/adr-2002-application-dashboard-timeframe-presets.json +25 -0
- package/blueprints/application-dashboard/contributions/adrs/adr-2003-application-dashboard-export-formats.json +25 -0
- package/blueprints/application-dashboard/contributions/requirements/application-dashboard-req-001.json +15 -0
- package/blueprints/application-dashboard/contributions/requirements/application-dashboard-req-002.json +15 -0
- package/blueprints/application-dashboard/contributions/requirements/application-dashboard-req-003.json +15 -0
- package/blueprints/application-dashboard/contributions/requirements/application-dashboard-req-004.json +15 -0
- package/blueprints/application-dashboard/contributions/requirements/application-dashboard-req-005.json +15 -0
- package/blueprints/application-dashboard/contributions/tacs/tac-2001-application-dashboard-tile-grid.json +47 -0
- package/blueprints/application-dashboard/contributions/tacs/tac-2002-application-dashboard-filter-chrome.json +41 -0
- package/blueprints/application-dashboard/contributions/tacs/tac-2003-application-dashboard-export-handle.json +35 -0
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19101.json +35 -0
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19102.json +35 -0
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19103.json +35 -0
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19104.json +35 -0
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19105.json +35 -0
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19106.json +35 -0
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19107.json +35 -0
- package/blueprints/application-dashboard/docs/topics.md +50 -0
- package/blueprints/application-dashboard/guide/application-dashboard.md +48 -0
- package/blueprints/application-dashboard/probe-packs/application-dashboard.pack.mjs +231 -0
- package/blueprints/application-datatable/CHANGELOG.md +8 -0
- package/blueprints/application-datatable/README.md +43 -0
- package/blueprints/application-datatable/blueprint.json +33 -0
- package/blueprints/application-datatable/contributions/adrs/adr-1801-application-datatable-pattern-choice.json +25 -0
- package/blueprints/application-datatable/contributions/adrs/adr-1802-application-datatable-url-state.json +20 -0
- package/blueprints/application-datatable/contributions/adrs/adr-1803-application-datatable-page-size.json +20 -0
- package/blueprints/application-datatable/contributions/adrs/adr-1804-application-datatable-selection-persistence.json +20 -0
- package/blueprints/application-datatable/contributions/requirements/application-datatable-req-001.json +15 -0
- package/blueprints/application-datatable/contributions/requirements/application-datatable-req-002.json +15 -0
- package/blueprints/application-datatable/contributions/requirements/application-datatable-req-003.json +15 -0
- package/blueprints/application-datatable/contributions/requirements/application-datatable-req-004.json +15 -0
- package/blueprints/application-datatable/contributions/requirements/application-datatable-req-005.json +15 -0
- package/blueprints/application-datatable/contributions/requirements/application-datatable-req-006.json +15 -0
- package/blueprints/application-datatable/contributions/tacs/tac-1801-application-datatable-shell.json +50 -0
- package/blueprints/application-datatable/contributions/tacs/tac-1802-application-datatable-query-adapter.json +39 -0
- package/blueprints/application-datatable/contributions/tacs/tac-1803-application-datatable-selection-model.json +28 -0
- package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17101.json +44 -0
- package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17102.json +44 -0
- package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17103.json +44 -0
- package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17104.json +44 -0
- package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17105.json +44 -0
- package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17106.json +44 -0
- package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17107.json +44 -0
- package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17108.json +44 -0
- package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17109.json +44 -0
- package/blueprints/application-datatable/docs/topics.md +42 -0
- package/blueprints/application-datatable/guide/application-datatable.md +38 -0
- package/blueprints/application-datatable/probe-packs/application-datatable.pack.mjs +240 -0
- package/blueprints/application-empty-error-states/CHANGELOG.md +9 -0
- package/blueprints/application-empty-error-states/README.md +88 -0
- package/blueprints/application-empty-error-states/blueprint.json +119 -0
- package/blueprints/application-empty-error-states/contributions/adrs/adr-2301-application-empty-error-states-status-contract.json +25 -0
- package/blueprints/application-empty-error-states/contributions/adrs/adr-2302-application-empty-error-states-stack-trace-visibility.json +25 -0
- package/blueprints/application-empty-error-states/contributions/adrs/adr-2303-application-empty-error-states-offline-strategy.json +25 -0
- package/blueprints/application-empty-error-states/contributions/requirements/application-empty-error-states-req-001.json +18 -0
- package/blueprints/application-empty-error-states/contributions/requirements/application-empty-error-states-req-002.json +18 -0
- package/blueprints/application-empty-error-states/contributions/requirements/application-empty-error-states-req-003.json +18 -0
- package/blueprints/application-empty-error-states/contributions/requirements/application-empty-error-states-req-004.json +18 -0
- package/blueprints/application-empty-error-states/contributions/requirements/application-empty-error-states-req-005.json +18 -0
- package/blueprints/application-empty-error-states/contributions/tacs/tac-2301-application-empty-error-states-state-machine.json +46 -0
- package/blueprints/application-empty-error-states/contributions/tacs/tac-2302-application-empty-error-states-recovery-router.json +36 -0
- package/blueprints/application-empty-error-states/contributions/tacs/tac-2303-application-empty-error-states-offline-buffer.json +40 -0
- package/blueprints/application-empty-error-states/contributions/user-stories/application-empty-error-states-us-22101.json +29 -0
- package/blueprints/application-empty-error-states/contributions/user-stories/application-empty-error-states-us-22102.json +29 -0
- package/blueprints/application-empty-error-states/contributions/user-stories/application-empty-error-states-us-22103.json +29 -0
- package/blueprints/application-empty-error-states/contributions/user-stories/application-empty-error-states-us-22104.json +29 -0
- package/blueprints/application-empty-error-states/contributions/user-stories/application-empty-error-states-us-22105.json +29 -0
- package/blueprints/application-empty-error-states/contributions/user-stories/application-empty-error-states-us-22106.json +29 -0
- package/blueprints/application-empty-error-states/contributions/user-stories/application-empty-error-states-us-22107.json +29 -0
- package/blueprints/application-empty-error-states/contributions/user-stories/application-empty-error-states-us-22108.json +29 -0
- package/blueprints/application-empty-error-states/docs/topics.md +53 -0
- package/blueprints/application-empty-error-states/guide/application-empty-error-states.md +50 -0
- package/blueprints/application-empty-error-states/probe-packs/application-empty-error-states.pack.mjs +284 -0
- package/blueprints/application-error-handling/docs/topics.md +12 -0
- package/blueprints/application-file-upload/CHANGELOG.md +9 -0
- package/blueprints/application-file-upload/README.md +85 -0
- package/blueprints/application-file-upload/blueprint.json +114 -0
- package/blueprints/application-file-upload/contributions/adrs/adr-2401-application-file-upload-transport.json +25 -0
- package/blueprints/application-file-upload/contributions/adrs/adr-2402-application-file-upload-accepted-set.json +25 -0
- package/blueprints/application-file-upload/contributions/adrs/adr-2403-application-file-upload-virus-scan.json +25 -0
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-001.json +18 -0
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-002.json +18 -0
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-003.json +18 -0
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-004.json +18 -0
- package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-005.json +18 -0
- package/blueprints/application-file-upload/contributions/tacs/tac-2401-application-file-upload-input.json +46 -0
- package/blueprints/application-file-upload/contributions/tacs/tac-2402-application-file-upload-transport.json +47 -0
- package/blueprints/application-file-upload/contributions/tacs/tac-2403-application-file-upload-progress-announcer.json +46 -0
- package/blueprints/application-file-upload/contributions/user-stories/application-file-upload-us-23101.json +28 -0
- package/blueprints/application-file-upload/contributions/user-stories/application-file-upload-us-23102.json +28 -0
- package/blueprints/application-file-upload/contributions/user-stories/application-file-upload-us-23103.json +29 -0
- package/blueprints/application-file-upload/contributions/user-stories/application-file-upload-us-23104.json +28 -0
- package/blueprints/application-file-upload/contributions/user-stories/application-file-upload-us-23105.json +29 -0
- package/blueprints/application-file-upload/contributions/user-stories/application-file-upload-us-23106.json +28 -0
- package/blueprints/application-file-upload/contributions/user-stories/application-file-upload-us-23107.json +28 -0
- package/blueprints/application-file-upload/docs/topics.md +58 -0
- package/blueprints/application-file-upload/guide/application-file-upload.md +48 -0
- package/blueprints/application-file-upload/probe-packs/application-file-upload.pack.mjs +238 -0
- package/blueprints/application-forms-wizard/CHANGELOG.md +9 -0
- package/blueprints/application-forms-wizard/README.md +102 -0
- package/blueprints/application-forms-wizard/blueprint.json +120 -0
- package/blueprints/application-forms-wizard/contributions/adrs/adr-2501-application-forms-wizard-navigation.json +25 -0
- package/blueprints/application-forms-wizard/contributions/adrs/adr-2502-application-forms-wizard-save-and-return.json +25 -0
- package/blueprints/application-forms-wizard/contributions/adrs/adr-2503-application-forms-wizard-step-indicator.json +25 -0
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-001.json +18 -0
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-002.json +18 -0
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-003.json +18 -0
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-004.json +18 -0
- package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-005.json +18 -0
- package/blueprints/application-forms-wizard/contributions/tacs/tac-2501-application-forms-wizard-task-list.json +46 -0
- package/blueprints/application-forms-wizard/contributions/tacs/tac-2502-application-forms-wizard-error-summary.json +40 -0
- package/blueprints/application-forms-wizard/contributions/tacs/tac-2503-application-forms-wizard-draft-store.json +40 -0
- package/blueprints/application-forms-wizard/contributions/user-stories/application-forms-wizard-us-24101.json +28 -0
- package/blueprints/application-forms-wizard/contributions/user-stories/application-forms-wizard-us-24102.json +29 -0
- package/blueprints/application-forms-wizard/contributions/user-stories/application-forms-wizard-us-24103.json +28 -0
- package/blueprints/application-forms-wizard/contributions/user-stories/application-forms-wizard-us-24104.json +29 -0
- package/blueprints/application-forms-wizard/contributions/user-stories/application-forms-wizard-us-24105.json +28 -0
- package/blueprints/application-forms-wizard/contributions/user-stories/application-forms-wizard-us-24106.json +28 -0
- package/blueprints/application-forms-wizard/contributions/user-stories/application-forms-wizard-us-24107.json +28 -0
- package/blueprints/application-forms-wizard/contributions/user-stories/application-forms-wizard-us-24108.json +29 -0
- package/blueprints/application-forms-wizard/docs/topics.md +49 -0
- package/blueprints/application-forms-wizard/guide/application-forms-wizard.md +48 -0
- package/blueprints/application-forms-wizard/probe-packs/application-forms-wizard.pack.mjs +233 -0
- package/blueprints/application-notifications-in-app/CHANGELOG.md +9 -0
- package/blueprints/application-notifications-in-app/README.md +80 -0
- package/blueprints/application-notifications-in-app/blueprint.json +30 -0
- package/blueprints/application-notifications-in-app/contributions/adrs/adr-2101-application-notifications-in-app-live-region-role-mapping.json +25 -0
- package/blueprints/application-notifications-in-app/contributions/adrs/adr-2102-application-notifications-in-app-toast-timeout-floor.json +25 -0
- package/blueprints/application-notifications-in-app/contributions/adrs/adr-2103-application-notifications-in-app-retention-window.json +25 -0
- package/blueprints/application-notifications-in-app/contributions/requirements/application-notifications-in-app-req-001.json +15 -0
- package/blueprints/application-notifications-in-app/contributions/requirements/application-notifications-in-app-req-002.json +15 -0
- package/blueprints/application-notifications-in-app/contributions/requirements/application-notifications-in-app-req-003.json +15 -0
- package/blueprints/application-notifications-in-app/contributions/requirements/application-notifications-in-app-req-004.json +15 -0
- package/blueprints/application-notifications-in-app/contributions/requirements/application-notifications-in-app-req-005.json +15 -0
- package/blueprints/application-notifications-in-app/contributions/tacs/tac-2101-application-notifications-in-app-live-region.json +46 -0
- package/blueprints/application-notifications-in-app/contributions/tacs/tac-2102-application-notifications-in-app-centre.json +52 -0
- package/blueprints/application-notifications-in-app/contributions/tacs/tac-2103-application-notifications-in-app-preferences.json +40 -0
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20101.json +35 -0
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20102.json +35 -0
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20103.json +35 -0
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20104.json +35 -0
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20105.json +35 -0
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20106.json +26 -0
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20107.json +26 -0
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20108.json +26 -0
- package/blueprints/application-notifications-in-app/docs/topics.md +46 -0
- package/blueprints/application-notifications-in-app/guide/application-notifications-in-app.md +47 -0
- package/blueprints/application-notifications-in-app/probe-packs/application-notifications-in-app.pack.mjs +328 -0
- package/blueprints/application-onboarding-tour/CHANGELOG.md +12 -0
- package/blueprints/application-onboarding-tour/README.md +77 -0
- package/blueprints/application-onboarding-tour/blueprint.json +164 -0
- package/blueprints/application-onboarding-tour/contributions/adrs/adr-2701-application-onboarding-tour-dismissal-policy.json +20 -0
- package/blueprints/application-onboarding-tour/contributions/adrs/adr-2702-application-onboarding-tour-completion-store-shape.json +20 -0
- package/blueprints/application-onboarding-tour/contributions/adrs/adr-2703-application-onboarding-tour-checklist-anchor.json +20 -0
- package/blueprints/application-onboarding-tour/contributions/requirements/application-onboarding-tour-req-001.json +18 -0
- package/blueprints/application-onboarding-tour/contributions/requirements/application-onboarding-tour-req-002.json +18 -0
- package/blueprints/application-onboarding-tour/contributions/requirements/application-onboarding-tour-req-003.json +18 -0
- package/blueprints/application-onboarding-tour/contributions/requirements/application-onboarding-tour-req-004.json +18 -0
- package/blueprints/application-onboarding-tour/contributions/tacs/tac-2701-application-onboarding-tour-step-runner.json +41 -0
- package/blueprints/application-onboarding-tour/contributions/tacs/tac-2702-application-onboarding-tour-checklist-slot.json +35 -0
- package/blueprints/application-onboarding-tour/contributions/tacs/tac-2703-application-onboarding-tour-completion-store.json +34 -0
- package/blueprints/application-onboarding-tour/contributions/user-stories/application-onboarding-tour-us-26101.json +27 -0
- package/blueprints/application-onboarding-tour/contributions/user-stories/application-onboarding-tour-us-26102.json +27 -0
- package/blueprints/application-onboarding-tour/contributions/user-stories/application-onboarding-tour-us-26103.json +27 -0
- package/blueprints/application-onboarding-tour/contributions/user-stories/application-onboarding-tour-us-26104.json +27 -0
- package/blueprints/application-onboarding-tour/contributions/user-stories/application-onboarding-tour-us-26105.json +27 -0
- package/blueprints/application-onboarding-tour/contributions/user-stories/application-onboarding-tour-us-26106.json +27 -0
- package/blueprints/application-onboarding-tour/contributions/user-stories/application-onboarding-tour-us-26107.json +27 -0
- package/blueprints/application-onboarding-tour/docs/topics.md +48 -0
- package/blueprints/application-onboarding-tour/guide/application-onboarding-tour.md +59 -0
- package/blueprints/application-onboarding-tour/probe-packs/application-onboarding-tour.pack.mjs +231 -0
- package/blueprints/application-spa/docs/topics.md +13 -1
- package/blueprints/delivery-ci-workflows/docs/topics.md +13 -1
- package/blueprints/deploy-cloudflare-workers/docs/topics.md +13 -1
- package/blueprints/email-smtp-resend/docs/topics.md +13 -1
- package/blueprints/object-storage-s3/CHANGELOG.md +13 -0
- package/blueprints/object-storage-s3/README.md +108 -0
- package/blueprints/object-storage-s3/blueprint.json +72 -0
- package/blueprints/object-storage-s3/contributions/adrs/adr-2901-object-storage-s3-adapter.json +30 -0
- package/blueprints/object-storage-s3/contributions/adrs/adr-2902-object-storage-s3-presigned-ttl-floor.json +25 -0
- package/blueprints/object-storage-s3/contributions/adrs/adr-2903-object-storage-s3-multipart-threshold.json +25 -0
- package/blueprints/object-storage-s3/contributions/adrs/adr-2904-object-storage-s3-contract.json +25 -0
- package/blueprints/object-storage-s3/contributions/probes/event-secrecy.mjs +103 -0
- package/blueprints/object-storage-s3/contributions/probes/facade-round-trip.mjs +43 -0
- package/blueprints/object-storage-s3/contributions/probes/multipart-upload.mjs +84 -0
- package/blueprints/object-storage-s3/contributions/probes/presigned-url.mjs +101 -0
- package/blueprints/object-storage-s3/contributions/probes/probe-utils.mjs +85 -0
- package/blueprints/object-storage-s3/contributions/probes/put-get-round-trip.mjs +84 -0
- package/blueprints/object-storage-s3/contributions/probes/r2-real-account-smoke.mjs +64 -0
- package/blueprints/object-storage-s3/contributions/probes/run-event-secrecy.mjs +4 -0
- package/blueprints/object-storage-s3/contributions/probes/run-facade-round-trip.mjs +10 -0
- package/blueprints/object-storage-s3/contributions/probes/run-multipart-upload.mjs +4 -0
- package/blueprints/object-storage-s3/contributions/probes/run-presigned-url.mjs +4 -0
- package/blueprints/object-storage-s3/contributions/probes/run-put-get-round-trip.mjs +7 -0
- package/blueprints/object-storage-s3/contributions/probes/run-r2-real-account-smoke.mjs +4 -0
- package/blueprints/object-storage-s3/contributions/requirements/object-storage-s3-req-001.json +18 -0
- package/blueprints/object-storage-s3/contributions/requirements/object-storage-s3-req-002.json +18 -0
- package/blueprints/object-storage-s3/contributions/requirements/object-storage-s3-req-003.json +18 -0
- package/blueprints/object-storage-s3/contributions/requirements/object-storage-s3-req-004.json +18 -0
- package/blueprints/object-storage-s3/contributions/requirements/object-storage-s3-req-005.json +18 -0
- package/blueprints/object-storage-s3/contributions/requirements/object-storage-s3-req-006.json +18 -0
- package/blueprints/object-storage-s3/contributions/tacs/tac-2901-object-storage-s3-facade.json +57 -0
- package/blueprints/object-storage-s3/contributions/tacs/tac-2902-object-storage-s3-multipart-uploader.json +36 -0
- package/blueprints/object-storage-s3/contributions/tacs/tac-2903-object-storage-s3-event-sink.json +36 -0
- package/blueprints/object-storage-s3/contributions/user-stories/object-storage-s3-us-28101.json +34 -0
- package/blueprints/object-storage-s3/contributions/user-stories/object-storage-s3-us-28102.json +43 -0
- package/blueprints/object-storage-s3/contributions/user-stories/object-storage-s3-us-28103.json +25 -0
- package/blueprints/object-storage-s3/contributions/user-stories/object-storage-s3-us-28104.json +34 -0
- package/blueprints/object-storage-s3/contributions/user-stories/object-storage-s3-us-28105.json +25 -0
- package/blueprints/object-storage-s3/contributions/user-stories/object-storage-s3-us-28106.json +34 -0
- package/blueprints/object-storage-s3/contributions/user-stories/object-storage-s3-us-28107.json +34 -0
- package/blueprints/object-storage-s3/contributions/user-stories/object-storage-s3-us-28108.json +34 -0
- package/blueprints/object-storage-s3/docs/topics.md +62 -0
- package/blueprints/object-storage-s3/guide/object-storage-s3.md +207 -0
- package/blueprints/observability-essentials/docs/topics.md +13 -1
- package/blueprints/observability-logging/CHANGELOG.md +9 -0
- package/blueprints/observability-logging/README.md +4 -1
- package/blueprints/observability-logging/blueprint.json +114 -21
- package/blueprints/observability-logging/docs/topics.md +12 -0
- package/blueprints/observability-probe-endpoints/docs/topics.md +13 -1
- package/blueprints/persistence-data-d1/docs/topics.md +13 -1
- package/blueprints/persistence-data-postgres/CHANGELOG.md +12 -0
- package/blueprints/persistence-data-postgres/README.md +101 -0
- package/blueprints/persistence-data-postgres/blueprint.json +80 -0
- package/blueprints/persistence-data-postgres/contributions/adrs/adr-2801-persistence-data-postgres-driver.json +30 -0
- package/blueprints/persistence-data-postgres/contributions/adrs/adr-2802-persistence-data-postgres-migration-shape.json +25 -0
- package/blueprints/persistence-data-postgres/contributions/adrs/adr-2803-persistence-data-postgres-runner-mode.json +25 -0
- package/blueprints/persistence-data-postgres/contributions/adrs/adr-2804-persistence-data-postgres-recovery.json +25 -0
- package/blueprints/persistence-data-postgres/contributions/adrs/adr-2805-persistence-data-postgres-connection-pool-posture.json +25 -0
- package/blueprints/persistence-data-postgres/contributions/probes/facade-round-trip.mjs +56 -0
- package/blueprints/persistence-data-postgres/contributions/probes/migration-apply.mjs +75 -0
- package/blueprints/persistence-data-postgres/contributions/probes/pool-posture-smoke.mjs +56 -0
- package/blueprints/persistence-data-postgres/contributions/probes/prepared-statement-scan.mjs +186 -0
- package/blueprints/persistence-data-postgres/contributions/probes/probe-utils.mjs +76 -0
- package/blueprints/persistence-data-postgres/contributions/probes/recovery-restore-round-trip.mjs +173 -0
- package/blueprints/persistence-data-postgres/contributions/probes/run-facade-round-trip.mjs +10 -0
- package/blueprints/persistence-data-postgres/contributions/probes/run-migration-apply.mjs +10 -0
- package/blueprints/persistence-data-postgres/contributions/probes/run-pool-posture-smoke.mjs +9 -0
- package/blueprints/persistence-data-postgres/contributions/probes/run-prepared-statement-scan.mjs +10 -0
- package/blueprints/persistence-data-postgres/contributions/probes/run-recovery-restore-round-trip.mjs +9 -0
- package/blueprints/persistence-data-postgres/contributions/probes/run-transaction-atomicity.mjs +10 -0
- package/blueprints/persistence-data-postgres/contributions/probes/transaction-atomicity.mjs +79 -0
- package/blueprints/persistence-data-postgres/contributions/requirements/persistence-data-postgres-req-001.json +18 -0
- package/blueprints/persistence-data-postgres/contributions/requirements/persistence-data-postgres-req-002.json +18 -0
- package/blueprints/persistence-data-postgres/contributions/requirements/persistence-data-postgres-req-003.json +18 -0
- package/blueprints/persistence-data-postgres/contributions/requirements/persistence-data-postgres-req-004.json +18 -0
- package/blueprints/persistence-data-postgres/contributions/requirements/persistence-data-postgres-req-005.json +18 -0
- package/blueprints/persistence-data-postgres/contributions/requirements/persistence-data-postgres-req-006.json +18 -0
- package/blueprints/persistence-data-postgres/contributions/requirements/persistence-data-postgres-req-007.json +18 -0
- package/blueprints/persistence-data-postgres/contributions/tacs/tac-2801-persistence-data-postgres-facade.json +58 -0
- package/blueprints/persistence-data-postgres/contributions/tacs/tac-2802-persistence-data-postgres-migration-runner.json +40 -0
- package/blueprints/persistence-data-postgres/contributions/tacs/tac-2803-persistence-data-postgres-transaction-helper.json +35 -0
- package/blueprints/persistence-data-postgres/contributions/tacs/tac-2804-persistence-data-postgres-recovery-runner.json +40 -0
- package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27101.json +34 -0
- package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27102.json +25 -0
- package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27103.json +25 -0
- package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27104.json +25 -0
- package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27105.json +25 -0
- package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27106.json +25 -0
- package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27107.json +25 -0
- package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27108.json +25 -0
- package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27109.json +25 -0
- package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27110.json +25 -0
- package/blueprints/persistence-data-postgres/docs/topics.md +64 -0
- package/blueprints/persistence-data-postgres/guide/persistence-data-postgres.md +172 -0
- package/blueprints/persistence-data-sqlite/docs/topics.md +13 -1
- package/blueprints/security-auth-clerk/CHANGELOG.md +9 -0
- package/blueprints/security-auth-clerk/README.md +3 -0
- package/blueprints/security-auth-clerk/blueprint.json +147 -29
- package/blueprints/security-auth-clerk/docs/topics.md +13 -1
- package/blueprints/security-auth-keycloak/CHANGELOG.md +9 -0
- package/blueprints/security-auth-keycloak/README.md +3 -0
- package/blueprints/security-auth-keycloak/blueprint.json +182 -36
- package/blueprints/security-auth-keycloak/docs/topics.md +13 -1
- package/blueprints/security-auth-magic-link/CHANGELOG.md +9 -0
- package/blueprints/security-auth-magic-link/README.md +3 -0
- package/blueprints/security-auth-magic-link/blueprint.json +159 -32
- package/blueprints/security-auth-magic-link/docs/topics.md +13 -1
- package/blueprints/security-auth-oauth2/CHANGELOG.md +9 -0
- package/blueprints/security-auth-oauth2/README.md +3 -0
- package/blueprints/security-auth-oauth2/blueprint.json +158 -31
- package/blueprints/security-auth-oauth2/docs/topics.md +13 -1
- package/blueprints/security-secrets-management/CHANGELOG.md +11 -0
- package/blueprints/security-secrets-management/blueprint.json +2 -1
- package/blueprints/security-secrets-management/docs/topics.md +13 -1
- package/fixtures/canary-manifest.json +9 -9
- package/package.json +2 -2
- package/rcf/code-nodes/cn-106.json +13 -0
- package/rcf/code-nodes/cn-107.json +14 -0
- package/rcf/code-nodes/cn-108.json +13 -0
- package/rcf/code-nodes/cn-109.json +12 -0
- package/rcf/code-nodes/cn-110.json +12 -0
- package/rcf/code-nodes/cn-111.json +14 -0
- package/rcf/code-nodes/cn-112.json +14 -0
- package/rcf/code-nodes/cn-113.json +12 -0
- package/rcf/code-nodes/cn-114.json +13 -0
- package/rcf/code-nodes/cn-115.json +13 -0
- package/rcf/code-nodes/cn-116.json +12 -0
- package/rcf/code-nodes/cn-117.json +13 -0
- package/rcf/code-nodes/cn-118.json +13 -0
- package/rcf/code-nodes/cn-119.json +13 -0
- package/rcf/code-nodes/cn-120.json +13 -0
- package/rcf/code-nodes/cn-121.json +12 -0
- package/rcf/code-nodes/cn-122.json +12 -0
- package/rcf/code-nodes/cn-123.json +13 -0
- package/rcf/code-nodes/cn-124.json +13 -0
- package/rcf/code-nodes/cn-125.json +13 -0
- package/rcf/code-nodes/cn-126.json +13 -0
- package/rcf/code-nodes/cn-127.json +12 -0
- package/rcf/code-nodes/cn-128.json +14 -0
- package/rcf/code-nodes/cn-129.json +14 -0
- package/rcf/code-nodes/cn-130.json +14 -0
- package/rcf/code-nodes/cn-131.json +15 -0
- package/rcf/code-nodes/cn-132.json +12 -0
- package/rcf/code-nodes/cn-133.json +13 -0
- package/rcf/code-nodes/cn-134.json +13 -0
- package/rcf/code-nodes/cn-135.json +12 -0
- package/rcf/code-nodes/cn-136.json +13 -0
- package/rcf/code-nodes/cn-137.json +13 -0
- package/rcf/code-nodes/cn-138.json +12 -0
- package/rcf/code-nodes/cn-139.json +12 -0
- package/rcf/code-nodes/cn-140.json +13 -0
- package/rcf/code-nodes/cn-141.json +13 -0
- package/rcf/code-nodes/cn-142.json +12 -0
- package/rcf/code-nodes/cn-143.json +13 -0
- package/rcf/code-nodes/cn-144.json +13 -0
- package/rcf/code-nodes/cn-145.json +12 -0
- package/rcf/code-nodes/cn-146.json +12 -0
- package/rcf/code-nodes/cn-147.json +13 -0
- package/rcf/code-nodes/cn-148.json +13 -0
- package/rcf/code-nodes/cn-149.json +12 -0
- package/rcf/code-nodes/cn-150.json +13 -0
- package/rcf/code-nodes/cn-151.json +13 -0
- package/rcf/code-nodes/cn-152.json +12 -0
- package/rcf/code-nodes/cn-153.json +12 -0
- package/rcf/code-nodes/cn-154.json +13 -0
- package/rcf/code-nodes/cn-155.json +14 -0
- package/rcf/code-nodes/cn-156.json +13 -0
- package/rcf/code-nodes/cn-157.json +13 -0
- package/rcf/code-nodes/cn-158.json +12 -0
- package/rcf/code-nodes/cn-159.json +13 -0
- package/rcf/code-nodes/cn-160.json +12 -0
- package/rcf/code-nodes/cn-161.json +12 -0
- package/rcf/code-nodes/cn-162.json +13 -0
- package/rcf/code-nodes/cn-163.json +12 -0
- package/rcf/code-nodes/cn-164.json +13 -0
- package/rcf/code-nodes/cn-165.json +12 -0
- package/rcf/code-nodes/cn-166.json +12 -0
- package/rcf/code-nodes/cn-167.json +12 -0
- package/rcf/code-nodes/cn-168.json +12 -0
- package/rcf/code-nodes/cn-169.json +12 -0
- package/rcf/code-nodes/cn-170.json +12 -0
- package/rcf/code-nodes/cn-171.json +12 -0
- package/rcf/code-nodes/cn-172.json +12 -0
- package/rcf/code-nodes/cn-173.json +12 -0
- package/rcf/code-nodes/cn-174.json +12 -0
- package/rcf/code-nodes/cn-175.json +13 -0
- package/rcf/code-nodes/cn-176.json +12 -0
- package/rcf/code-nodes/cn-177.json +12 -0
- package/rcf/code-nodes/cn-178.json +12 -0
- package/rcf/code-nodes/cn-179.json +12 -0
- package/rcf/code-nodes/cn-180.json +13 -0
- package/rcf/code-nodes/cn-181.json +12 -0
- package/rcf/code-nodes/cn-182.json +13 -0
- package/rcf/code-nodes/cn-183.json +12 -0
- package/rcf/code-nodes/cn-184.json +13 -0
- package/rcf/code-nodes/cn-185.json +12 -0
- package/rcf/code-nodes/cn-186.json +12 -0
- package/rcf/code-nodes/cn-200.json +14 -0
- package/rcf/code-nodes/cn-201.json +13 -0
- package/rcf/code-nodes/cn-202.json +14 -0
- package/rcf/code-nodes/cn-203.json +14 -0
- package/rcf/code-nodes/cn-204.json +13 -0
- package/rcf/code-nodes/cn-205.json +14 -0
- package/rcf/fbs/fbs-036.json +22 -0
- package/rcf/fbs/fbs-037.json +19 -0
- package/rcf/fbs/fbs-038.json +19 -0
- package/rcf/fbs/fbs-039.json +21 -0
- package/rcf/fbs/fbs-040.json +20 -0
- package/rcf/fbs/fbs-041.json +13 -0
- package/rcf/fbs/fbs-042.json +13 -0
- package/rcf/fbs/fbs-043.json +23 -0
- package/rcf/fbs/fbs-044.json +23 -0
- package/rcf/fbs/fbs-045.json +23 -0
- package/rcf/fbs/fbs-046.json +24 -0
- package/rcf/fbs/fbs-047.json +24 -0
- package/rcf/fbs/fbs-060.json +22 -0
- package/rcf/fbs/fbs-061.json +20 -0
- package/rcf/requirements/req-017.json +18 -0
- package/rcf/requirements/req-018.json +18 -0
- package/rcf/requirements/req-019.json +38 -0
- package/rcf/requirements/req-020.json +13 -0
- package/rcf/requirements/req-021.json +13 -0
- package/rcf/requirements/req-022.json +13 -0
- package/rcf/requirements/req-023.json +14 -0
- package/rcf/requirements/req-024.json +69 -0
- package/rcf/requirements/req-025.json +59 -0
- package/rcf/requirements/req-026.json +154 -0
- package/rcf/requirements/req-027.json +33 -0
- package/rcf/requirements/req-028.json +13 -0
- package/rcf/requirements/req-040.json +13 -0
- package/rcf/requirements/req-041.json +125 -0
- package/rcf/test-suites/ts-046.json +78 -0
- package/rcf/test-suites/ts-047.json +54 -0
- package/rcf/test-suites/ts-048.json +54 -0
- package/rcf/test-suites/ts-049.json +70 -0
- package/rcf/test-suites/ts-050.json +69 -0
- package/rcf/test-suites/ts-051.json +22 -0
- package/rcf/test-suites/ts-052.json +20 -0
- package/rcf/test-suites/ts-053.json +70 -0
- package/rcf/test-suites/ts-054.json +70 -0
- package/rcf/test-suites/ts-055.json +77 -0
- package/rcf/test-suites/ts-056.json +78 -0
- package/rcf/test-suites/ts-057.json +78 -0
- package/rcf/test-suites/ts-070.json +62 -0
- package/rcf/test-suites/ts-071.json +62 -0
- package/rcf/user-stories/us-1701.json +56 -0
- package/rcf/user-stories/us-1801.json +40 -0
- package/rcf/user-stories/us-1901.json +40 -0
- package/rcf/user-stories/us-2001.json +50 -0
- package/rcf/user-stories/us-2101.json +45 -0
- package/rcf/user-stories/us-2201.json +60 -0
- package/rcf/user-stories/us-2301.json +51 -0
- package/rcf/user-stories/us-2401.json +62 -0
- package/rcf/user-stories/us-2501.json +58 -0
- package/rcf/user-stories/us-2601.json +51 -0
- package/rcf/user-stories/us-2701.json +55 -0
- package/rcf/user-stories/us-2801.json +55 -0
- package/rcf/user-stories/us-4001.json +69 -0
- package/rcf/user-stories/us-4101.json +69 -0
- package/releases/releases.yaml +21 -1
- package/src/blueprint/apply.js +107 -1
- package/src/blueprint/capabilities.js +357 -0
- package/src/blueprint/loader.js +247 -0
- package/src/browser-verify/boot.js +180 -0
- package/src/browser-verify/index.js +13 -0
- package/src/browser-verify/manifest-writer.js +31 -6
- package/src/browser-verify/pack-browser.js +294 -0
- package/src/browser-verify/pack-loader.js +176 -0
- package/src/browser-verify/pack-runner.js +193 -0
- package/src/browser-verify/pack-schema.js +155 -0
- package/src/browser-verify/runner.js +24 -1
- package/src/cli/blueprint.js +99 -0
- package/src/cli/browser-verify.js +147 -7
- package/src/core/errors/index.js +7 -0
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
// Boot fallback for probe packs (visual-round-spec-2026-09-04 §3.5).
|
|
2
|
+
//
|
|
3
|
+
// The normal path is a dev server already running at `runtimeUrl`. When
|
|
4
|
+
// a pack declares `boot: { bootCommand, waitForUrl, waitForSelector }`
|
|
5
|
+
// AND the runtime is not answering, this module spawns `bootCommand`
|
|
6
|
+
// from the project root, waits (bounded) for `waitForUrl` then
|
|
7
|
+
// `waitForSelector`, hands the running server off to the pack pass,
|
|
8
|
+
// and stops the process it started when the pass completes.
|
|
9
|
+
//
|
|
10
|
+
// Never used as a per-blueprint harness: this only fires when the URL
|
|
11
|
+
// is genuinely unreachable, per Baz's ruling that the running dev
|
|
12
|
+
// server is the normal case (2026-09-04).
|
|
13
|
+
|
|
14
|
+
import { spawn } from 'node:child_process';
|
|
15
|
+
import { setTimeout as sleep } from 'node:timers/promises';
|
|
16
|
+
|
|
17
|
+
export const DEFAULT_URL_TIMEOUT_MS = 60000;
|
|
18
|
+
export const DEFAULT_SELECTOR_TIMEOUT_MS = 10000;
|
|
19
|
+
export const DEFAULT_REACHABLE_PROBE_TIMEOUT_MS = 3000;
|
|
20
|
+
const POLL_INTERVAL_MS = 500;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @param {string} url
|
|
24
|
+
* @param {(url: string, init?: object) => Promise<any>} fetchFn
|
|
25
|
+
* @param {number} timeoutMs
|
|
26
|
+
* @returns {Promise<boolean>}
|
|
27
|
+
*/
|
|
28
|
+
export async function isReachable(url, fetchFn, timeoutMs = DEFAULT_REACHABLE_PROBE_TIMEOUT_MS) {
|
|
29
|
+
if (typeof url !== 'string' || url.length === 0) return false;
|
|
30
|
+
const controller = new AbortController();
|
|
31
|
+
const t = setTimeout(() => controller.abort(), timeoutMs);
|
|
32
|
+
try {
|
|
33
|
+
const res = await fetchFn(url, { signal: controller.signal });
|
|
34
|
+
if (!res) return false;
|
|
35
|
+
// Any HTTP response counts as "server up"; even a 404 tells us a
|
|
36
|
+
// process is listening. Only a network failure means unreachable.
|
|
37
|
+
return typeof res.status === 'number' && res.status > 0;
|
|
38
|
+
} catch {
|
|
39
|
+
return false;
|
|
40
|
+
} finally {
|
|
41
|
+
clearTimeout(t);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Choose the first boot config across loaded packs (any is fine; the
|
|
47
|
+
* spec pins one boot per pack pass because runtimeUrl is single).
|
|
48
|
+
*
|
|
49
|
+
* @param {Array<import('./pack-loader.js').LoadedPack>} packs
|
|
50
|
+
* @returns {object|null}
|
|
51
|
+
*/
|
|
52
|
+
export function pickBootFromPacks(packs) {
|
|
53
|
+
if (!Array.isArray(packs)) return null;
|
|
54
|
+
for (const pack of packs) {
|
|
55
|
+
if (pack?.boot && typeof pack.boot === 'object') return pack.boot;
|
|
56
|
+
}
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* If the runtime does not answer AND `boot` is declared, bring it up.
|
|
62
|
+
*
|
|
63
|
+
* @param {object} args
|
|
64
|
+
* @param {object|null} args.boot
|
|
65
|
+
* @param {string} args.runtimeUrl
|
|
66
|
+
* @param {string} args.projectRoot
|
|
67
|
+
* @param {(url: string, init?: object) => Promise<any>} args.fetch
|
|
68
|
+
* @param {object|null} [args.browser] probe-pack browser (for waitForSelector via snapshot)
|
|
69
|
+
* @param {(line: string) => void} [args.logger]
|
|
70
|
+
* @param {() => number} [args.now] injectable clock (unit tests)
|
|
71
|
+
* @param {{ urlMs?: number, selectorMs?: number, reachableProbeMs?: number }} [args.timeouts]
|
|
72
|
+
* @param {(command: string, opts: object) => import('node:child_process').ChildProcess} [args.spawnFn] injectable spawner (unit tests)
|
|
73
|
+
* @returns {Promise<{ started: boolean, source: 'already-up'|'no-boot'|'no-boot-command'|'boot-command'|'no-runtime-url', stop: () => Promise<void>, notes: string[] }>}
|
|
74
|
+
*/
|
|
75
|
+
export async function bootIfNeeded({
|
|
76
|
+
boot,
|
|
77
|
+
runtimeUrl,
|
|
78
|
+
projectRoot,
|
|
79
|
+
fetch: fetchFn,
|
|
80
|
+
browser = null,
|
|
81
|
+
logger = () => {},
|
|
82
|
+
now = () => Date.now(),
|
|
83
|
+
timeouts = {},
|
|
84
|
+
spawnFn = spawn,
|
|
85
|
+
}) {
|
|
86
|
+
const notes = [];
|
|
87
|
+
const urlTimeout = timeouts.urlMs ?? DEFAULT_URL_TIMEOUT_MS;
|
|
88
|
+
const selectorTimeout = timeouts.selectorMs ?? DEFAULT_SELECTOR_TIMEOUT_MS;
|
|
89
|
+
const reachableTimeout = timeouts.reachableProbeMs ?? DEFAULT_REACHABLE_PROBE_TIMEOUT_MS;
|
|
90
|
+
|
|
91
|
+
if (!boot || typeof boot !== 'object') {
|
|
92
|
+
return { started: false, source: 'no-boot', stop: async () => {}, notes };
|
|
93
|
+
}
|
|
94
|
+
const probeUrl = typeof boot.waitForUrl === 'string' && boot.waitForUrl.length > 0
|
|
95
|
+
? boot.waitForUrl
|
|
96
|
+
: runtimeUrl;
|
|
97
|
+
if (typeof probeUrl !== 'string' || probeUrl.length === 0) {
|
|
98
|
+
return { started: false, source: 'no-runtime-url', stop: async () => {}, notes };
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (await isReachable(probeUrl, fetchFn, reachableTimeout)) {
|
|
102
|
+
notes.push(`runtime ${probeUrl} already reachable; boot skipped`);
|
|
103
|
+
return { started: false, source: 'already-up', stop: async () => {}, notes };
|
|
104
|
+
}
|
|
105
|
+
if (typeof boot.bootCommand !== 'string' || boot.bootCommand.length === 0) {
|
|
106
|
+
notes.push(`runtime ${probeUrl} unreachable but pack declares no bootCommand`);
|
|
107
|
+
return { started: false, source: 'no-boot-command', stop: async () => {}, notes };
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
logger(`[boot] runtime ${probeUrl} unreachable; spawning: ${boot.bootCommand}`);
|
|
111
|
+
const [cmd, ...args] = boot.bootCommand.split(/\s+/).filter(Boolean);
|
|
112
|
+
const child = spawnFn(cmd, args, {
|
|
113
|
+
cwd: projectRoot,
|
|
114
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
115
|
+
env: { ...process.env },
|
|
116
|
+
detached: false,
|
|
117
|
+
});
|
|
118
|
+
child.stdout?.on('data', (b) => logger(`[boot:stdout] ${b.toString('utf8').trimEnd()}`));
|
|
119
|
+
child.stderr?.on('data', (b) => logger(`[boot:stderr] ${b.toString('utf8').trimEnd()}`));
|
|
120
|
+
|
|
121
|
+
const start = now();
|
|
122
|
+
let up = false;
|
|
123
|
+
while (now() - start < urlTimeout) {
|
|
124
|
+
if (await isReachable(probeUrl, fetchFn, reachableTimeout)) { up = true; break; }
|
|
125
|
+
await sleep(POLL_INTERVAL_MS);
|
|
126
|
+
}
|
|
127
|
+
if (!up) {
|
|
128
|
+
await stopChild(child);
|
|
129
|
+
throw new Error(`boot: waitForUrl ${probeUrl} did not respond within ${urlTimeout}ms (bootCommand: ${boot.bootCommand})`);
|
|
130
|
+
}
|
|
131
|
+
notes.push(`bootCommand up at ${probeUrl} after ${now() - start}ms`);
|
|
132
|
+
|
|
133
|
+
if (typeof boot.waitForSelector === 'string' && boot.waitForSelector.length > 0 && browser) {
|
|
134
|
+
try {
|
|
135
|
+
await browser.goto(probeUrl);
|
|
136
|
+
const s0 = now();
|
|
137
|
+
let selectorSeen = false;
|
|
138
|
+
while (now() - s0 < selectorTimeout) {
|
|
139
|
+
const snap = await browser.snapshot();
|
|
140
|
+
if (matchesSnapshot(snap, boot.waitForSelector)) { selectorSeen = true; break; }
|
|
141
|
+
await sleep(POLL_INTERVAL_MS);
|
|
142
|
+
}
|
|
143
|
+
if (!selectorSeen) notes.push(`waitForSelector '${boot.waitForSelector}' not observed within ${selectorTimeout}ms; proceeding anyway`);
|
|
144
|
+
else notes.push(`waitForSelector '${boot.waitForSelector}' observed`);
|
|
145
|
+
} catch (err) {
|
|
146
|
+
notes.push(`waitForSelector probe failed: ${err.message}`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return {
|
|
151
|
+
started: true,
|
|
152
|
+
source: 'boot-command',
|
|
153
|
+
stop: async () => { await stopChild(child); },
|
|
154
|
+
notes,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
async function stopChild(child) {
|
|
159
|
+
try { child.kill('SIGTERM'); } catch { /* fine */ }
|
|
160
|
+
await new Promise((resolve) => {
|
|
161
|
+
if (typeof child.exitCode === 'number' && child.exitCode !== null) return resolve();
|
|
162
|
+
const timer = setTimeout(() => { try { child.kill('SIGKILL'); } catch { /* fine */ } resolve(); }, 3000);
|
|
163
|
+
child.once?.('exit', () => { clearTimeout(timer); resolve(); });
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Best-effort match of a "selector-shaped" hint against a snapshot text.
|
|
169
|
+
* We accept: raw substring, an aria role hint (e.g. `role="grid"` -> "grid"),
|
|
170
|
+
* or a text-content hint. Exposed for unit tests.
|
|
171
|
+
*/
|
|
172
|
+
export function matchesSnapshot(snapshot, selectorOrRef) {
|
|
173
|
+
if (typeof snapshot !== 'string' || typeof selectorOrRef !== 'string') return false;
|
|
174
|
+
if (snapshot.includes(selectorOrRef)) return true;
|
|
175
|
+
const roleMatch = selectorOrRef.match(/\[role\s*=\s*['"]?([\w-]+)['"]?\]/);
|
|
176
|
+
if (roleMatch && snapshot.includes(roleMatch[1])) return true;
|
|
177
|
+
const bracketed = selectorOrRef.replace(/[[\]"'=*]/g, ' ').trim();
|
|
178
|
+
if (bracketed && snapshot.includes(bracketed)) return true;
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
@@ -27,3 +27,16 @@ export {
|
|
|
27
27
|
runAgentScreenshotCritique,
|
|
28
28
|
stubBrowserDriver,
|
|
29
29
|
} from './runner.js';
|
|
30
|
+
|
|
31
|
+
export { validatePackModule, PACK_SCHEMA_INTERNALS } from './pack-schema.js';
|
|
32
|
+
export { loadProbePacks, readContributedAcIds } from './pack-loader.js';
|
|
33
|
+
export { runProbePacksForFbs } from './pack-runner.js';
|
|
34
|
+
export { createPackBrowser, parseEvaluateResult } from './pack-browser.js';
|
|
35
|
+
export {
|
|
36
|
+
bootIfNeeded,
|
|
37
|
+
isReachable,
|
|
38
|
+
matchesSnapshot,
|
|
39
|
+
pickBootFromPacks,
|
|
40
|
+
DEFAULT_URL_TIMEOUT_MS,
|
|
41
|
+
DEFAULT_SELECTOR_TIMEOUT_MS,
|
|
42
|
+
} from './boot.js';
|
|
@@ -27,25 +27,49 @@ export function nextBrowserVerificationId(manifest, fbsId) {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
|
-
* Aggregate the record verdict per spec §8.5
|
|
31
|
-
*
|
|
32
|
-
*
|
|
30
|
+
* Aggregate the record verdict per spec §8.5, extended for the visual
|
|
31
|
+
* round T-0 probe-pack pass (visual-round-spec-2026-09-04 §3.4):
|
|
32
|
+
* block if any invariant severity=block verdict=fail, OR any auth smoke fail,
|
|
33
|
+
* OR any pack check / pre-check severity=block verdict=fail;
|
|
34
|
+
* warn if any invariant severity=warn verdict=fail (and no block),
|
|
35
|
+
* OR any pack check / pre-check severity=warn verdict=fail (and no block);
|
|
33
36
|
* pass otherwise.
|
|
34
37
|
*
|
|
38
|
+
* `probePacks` is optional so pre-T-0 callers keep the old signature.
|
|
39
|
+
*
|
|
35
40
|
* @param {Array<{ invariant: string, verdict: 'pass'|'warn'|'fail', severity: 'block'|'warn'|'advisory' }>} invariantChecks
|
|
36
41
|
* @param {Array<{ verdict: 'pass'|'warn'|'fail' }>} authSmokeChecks
|
|
42
|
+
* @param {Array<{ applicable?: boolean, checks?: Array<{ verdict: 'pass'|'warn'|'fail'|'skipped', severity?: 'block'|'warn'|'advisory' }>, preChecks?: Array<{ verdict: 'pass'|'warn'|'fail'|'skipped', severity?: 'block'|'warn'|'advisory' }> }>} [probePacks]
|
|
37
43
|
* @returns {'pass'|'warn'|'block'}
|
|
38
44
|
*/
|
|
39
|
-
export function aggregateVerdict(invariantChecks, authSmokeChecks) {
|
|
45
|
+
export function aggregateVerdict(invariantChecks, authSmokeChecks, probePacks) {
|
|
40
46
|
for (const check of invariantChecks) {
|
|
41
47
|
if (check.severity === 'block' && check.verdict === 'fail') return 'block';
|
|
42
48
|
}
|
|
43
49
|
for (const check of authSmokeChecks ?? []) {
|
|
44
50
|
if (check.verdict === 'fail') return 'block';
|
|
45
51
|
}
|
|
52
|
+
for (const pack of probePacks ?? []) {
|
|
53
|
+
if (pack?.applicable === false) continue;
|
|
54
|
+
for (const c of pack?.checks ?? []) {
|
|
55
|
+
if (c?.severity === 'block' && c?.verdict === 'fail') return 'block';
|
|
56
|
+
}
|
|
57
|
+
for (const c of pack?.preChecks ?? []) {
|
|
58
|
+
if (c?.severity === 'block' && c?.verdict === 'fail') return 'block';
|
|
59
|
+
}
|
|
60
|
+
}
|
|
46
61
|
for (const check of invariantChecks) {
|
|
47
62
|
if (check.severity === 'warn' && (check.verdict === 'fail' || check.verdict === 'warn')) return 'warn';
|
|
48
63
|
}
|
|
64
|
+
for (const pack of probePacks ?? []) {
|
|
65
|
+
if (pack?.applicable === false) continue;
|
|
66
|
+
for (const c of pack?.checks ?? []) {
|
|
67
|
+
if (c?.severity === 'warn' && c?.verdict === 'fail') return 'warn';
|
|
68
|
+
}
|
|
69
|
+
for (const c of pack?.preChecks ?? []) {
|
|
70
|
+
if (c?.severity === 'warn' && c?.verdict === 'fail') return 'warn';
|
|
71
|
+
}
|
|
72
|
+
}
|
|
49
73
|
return 'pass';
|
|
50
74
|
}
|
|
51
75
|
|
|
@@ -67,10 +91,10 @@ export function aggregateVerdict(invariantChecks, authSmokeChecks) {
|
|
|
67
91
|
*/
|
|
68
92
|
export function composeBrowserVerificationRecord({
|
|
69
93
|
manifest, fbsId, mode, runtimeProfile, runtimeUrl, routesChecked,
|
|
70
|
-
invariantChecks, authSmokeChecks = [], notes, now = new Date(),
|
|
94
|
+
invariantChecks, authSmokeChecks = [], probePacks = [], notes, now = new Date(),
|
|
71
95
|
}) {
|
|
72
96
|
const id = nextBrowserVerificationId(manifest, fbsId);
|
|
73
|
-
const verdict = aggregateVerdict(invariantChecks, authSmokeChecks);
|
|
97
|
+
const verdict = aggregateVerdict(invariantChecks, authSmokeChecks, probePacks);
|
|
74
98
|
const record = {
|
|
75
99
|
id,
|
|
76
100
|
fbsId,
|
|
@@ -83,6 +107,7 @@ export function composeBrowserVerificationRecord({
|
|
|
83
107
|
verdict,
|
|
84
108
|
};
|
|
85
109
|
if (authSmokeChecks && authSmokeChecks.length > 0) record.authSmokeChecks = authSmokeChecks;
|
|
110
|
+
if (Array.isArray(probePacks) && probePacks.length > 0) record.probePacks = probePacks;
|
|
86
111
|
if (typeof notes === 'string' && notes.length > 0) record.notes = notes;
|
|
87
112
|
return record;
|
|
88
113
|
}
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
// packBrowser: a real headless browser exposed to blueprint-shipped
|
|
2
|
+
// probe packs (visual-round-spec-2026-09-04 §3.3). The browser is
|
|
3
|
+
// provisioned through the pinned Playwright MCP server as a JSON-RPC
|
|
4
|
+
// 2.0 stdio client, with an optional cheaper route via a `playwright`
|
|
5
|
+
// installation already resolved from the consuming project's own
|
|
6
|
+
// node_modules. Both routes expose the same small stable API:
|
|
7
|
+
//
|
|
8
|
+
// goto(url) navigate to a URL
|
|
9
|
+
// snapshot() accessibility-tree text (searchable)
|
|
10
|
+
// evaluate(fn, arg?) run JS in page context; returns parsed value
|
|
11
|
+
// click(selectorOrRef, hint) click an element by CSS selector or a11y ref
|
|
12
|
+
// type(selectorOrRef, text) type into an editable element
|
|
13
|
+
// press(key) press a keyboard key
|
|
14
|
+
// resize(width, height) set viewport dimensions (breakpoint reflow probes)
|
|
15
|
+
// screenshot(filename?) capture a PNG; returns descriptor / path
|
|
16
|
+
// close() close the page + terminate the browser process
|
|
17
|
+
//
|
|
18
|
+
// Zero new npm dependencies: MCP over stdio uses only Node built-ins;
|
|
19
|
+
// the cheap route uses `playwright` peer dep if the project already
|
|
20
|
+
// installed it. No LLM call anywhere.
|
|
21
|
+
|
|
22
|
+
import { spawn } from 'node:child_process';
|
|
23
|
+
import { createRequire } from 'node:module';
|
|
24
|
+
import { pathToFileURL } from 'node:url';
|
|
25
|
+
import { resolve as resolvePath } from 'node:path';
|
|
26
|
+
|
|
27
|
+
import { PLAYWRIGHT_MCP_VERSION } from '../verify/engine/launcher.js';
|
|
28
|
+
|
|
29
|
+
const DEFAULT_TOOL_TIMEOUT_MS = 30000;
|
|
30
|
+
const INIT_TIMEOUT_MS = 45000;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Compose a packBrowser for use by probe packs.
|
|
34
|
+
*
|
|
35
|
+
* @param {object} [options]
|
|
36
|
+
* @param {string} [options.projectRoot] consuming project root; used to try the cheap route
|
|
37
|
+
* @param {string} [options.playwrightMcpVersion] pinned MCP semver (defaults to PLAYWRIGHT_MCP_VERSION)
|
|
38
|
+
* @param {'auto'|'mcp'|'project'} [options.route] force a route (default 'auto')
|
|
39
|
+
* @param {(line: string) => void} [options.logger]
|
|
40
|
+
* @param {NodeJS.ProcessEnv} [options.env]
|
|
41
|
+
* @param {number} [options.timeoutMs] per-RPC timeout
|
|
42
|
+
* @returns {Promise<object>} the packBrowser handle
|
|
43
|
+
*/
|
|
44
|
+
export async function createPackBrowser(options = {}) {
|
|
45
|
+
const {
|
|
46
|
+
projectRoot,
|
|
47
|
+
playwrightMcpVersion = PLAYWRIGHT_MCP_VERSION,
|
|
48
|
+
route = 'auto',
|
|
49
|
+
logger = () => {},
|
|
50
|
+
env = process.env,
|
|
51
|
+
timeoutMs = DEFAULT_TOOL_TIMEOUT_MS,
|
|
52
|
+
} = options;
|
|
53
|
+
|
|
54
|
+
if (route === 'project' || (route === 'auto' && projectRoot && await tryResolveProjectPlaywright(projectRoot))) {
|
|
55
|
+
const handle = await createProjectPlaywrightHandle({ projectRoot, logger });
|
|
56
|
+
if (handle) return handle;
|
|
57
|
+
if (route === 'project') throw new Error(`packBrowser: project route requested but 'playwright' is not installed under ${projectRoot}`);
|
|
58
|
+
}
|
|
59
|
+
return createMcpPackBrowser({ playwrightMcpVersion, logger, env, timeoutMs });
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async function tryResolveProjectPlaywright(projectRoot) {
|
|
63
|
+
try {
|
|
64
|
+
const req = createRequire(resolvePath(projectRoot, 'package.json'));
|
|
65
|
+
req.resolve('playwright');
|
|
66
|
+
return true;
|
|
67
|
+
} catch {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async function createProjectPlaywrightHandle({ projectRoot, logger }) {
|
|
73
|
+
try {
|
|
74
|
+
const req = createRequire(resolvePath(projectRoot, 'package.json'));
|
|
75
|
+
const playwrightPath = req.resolve('playwright');
|
|
76
|
+
const mod = await import(pathToFileURL(playwrightPath).href);
|
|
77
|
+
const chromium = mod?.chromium ?? mod?.default?.chromium;
|
|
78
|
+
if (!chromium) return null;
|
|
79
|
+
const browser = await chromium.launch({ headless: true });
|
|
80
|
+
const context = await browser.newContext();
|
|
81
|
+
const page = await context.newPage();
|
|
82
|
+
return Object.freeze({
|
|
83
|
+
provisioning: { via: 'project-playwright', playwrightPath },
|
|
84
|
+
async goto(url) { await page.goto(url, { waitUntil: 'load' }); },
|
|
85
|
+
async snapshot() {
|
|
86
|
+
const tree = await page.accessibility.snapshot({ interestingOnly: false });
|
|
87
|
+
return renderA11yTree(tree);
|
|
88
|
+
},
|
|
89
|
+
async evaluate(fn, arg) {
|
|
90
|
+
if (typeof fn === 'function') return page.evaluate(fn, arg);
|
|
91
|
+
return page.evaluate(String(fn));
|
|
92
|
+
},
|
|
93
|
+
async click(selector) { await page.click(selector); },
|
|
94
|
+
async type(selector, text) { await page.fill(selector, text); },
|
|
95
|
+
async press(key) { await page.keyboard.press(key); },
|
|
96
|
+
async resize(width, height) {
|
|
97
|
+
const w = normaliseDim(width, 'width');
|
|
98
|
+
const h = normaliseDim(height, 'height');
|
|
99
|
+
await page.setViewportSize({ width: w, height: h });
|
|
100
|
+
},
|
|
101
|
+
async screenshot(filename) {
|
|
102
|
+
const target = filename ? { path: filename } : undefined;
|
|
103
|
+
const buf = await page.screenshot(target);
|
|
104
|
+
return filename ?? `data:image/png;base64,${buf.toString('base64')}`;
|
|
105
|
+
},
|
|
106
|
+
async close() {
|
|
107
|
+
logger('[pack-browser] closing project-playwright browser');
|
|
108
|
+
try { await page.close(); } catch { /* fine */ }
|
|
109
|
+
try { await context.close(); } catch { /* fine */ }
|
|
110
|
+
try { await browser.close(); } catch { /* fine */ }
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
} catch (err) {
|
|
114
|
+
logger(`[pack-browser] project-playwright route failed: ${err.message}`);
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function renderA11yTree(node, depth = 0) {
|
|
120
|
+
if (!node) return '';
|
|
121
|
+
const pad = ' '.repeat(depth);
|
|
122
|
+
const parts = [];
|
|
123
|
+
parts.push(`${pad}${node.role ?? '?'} ${node.name ? JSON.stringify(node.name) : ''}`.trimEnd());
|
|
124
|
+
for (const child of node.children ?? []) parts.push(renderA11yTree(child, depth + 1));
|
|
125
|
+
return parts.join('\n');
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async function createMcpPackBrowser({ playwrightMcpVersion, logger, env, timeoutMs }) {
|
|
129
|
+
const child = spawn('npx', ['-y', `@playwright/mcp@${playwrightMcpVersion}`, '--headless', '--isolated'], {
|
|
130
|
+
env: { ...env },
|
|
131
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
/** @type {Map<number, { resolve: (v: any) => void, reject: (e: Error) => void, timer: NodeJS.Timeout|null }>} */
|
|
135
|
+
const pending = new Map();
|
|
136
|
+
let nextId = 1;
|
|
137
|
+
let buffer = '';
|
|
138
|
+
let exited = false;
|
|
139
|
+
|
|
140
|
+
child.stdout.on('data', (chunk) => {
|
|
141
|
+
buffer += chunk.toString('utf8');
|
|
142
|
+
for (;;) {
|
|
143
|
+
const nl = buffer.indexOf('\n');
|
|
144
|
+
if (nl === -1) break;
|
|
145
|
+
const line = buffer.slice(0, nl).trim();
|
|
146
|
+
buffer = buffer.slice(nl + 1);
|
|
147
|
+
if (!line) continue;
|
|
148
|
+
let msg;
|
|
149
|
+
try { msg = JSON.parse(line); } catch { continue; }
|
|
150
|
+
if (msg.id != null && pending.has(msg.id)) {
|
|
151
|
+
const p = pending.get(msg.id);
|
|
152
|
+
pending.delete(msg.id);
|
|
153
|
+
if (p.timer) clearTimeout(p.timer);
|
|
154
|
+
if (msg.error) p.reject(new Error(msg.error.message ?? `MCP error ${JSON.stringify(msg.error)}`));
|
|
155
|
+
else p.resolve(msg.result);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
child.stderr.on('data', (chunk) => logger(`[playwright-mcp] ${chunk.toString('utf8').trimEnd()}`));
|
|
160
|
+
child.on('exit', (code) => {
|
|
161
|
+
exited = true;
|
|
162
|
+
for (const [, p] of pending) {
|
|
163
|
+
if (p.timer) clearTimeout(p.timer);
|
|
164
|
+
p.reject(new Error(`Playwright MCP exited (code=${code})`));
|
|
165
|
+
}
|
|
166
|
+
pending.clear();
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
function rpc(method, params, { timeout = timeoutMs } = {}) {
|
|
170
|
+
if (exited) return Promise.reject(new Error('Playwright MCP process already exited'));
|
|
171
|
+
const id = nextId++;
|
|
172
|
+
return new Promise((resolve, reject) => {
|
|
173
|
+
const timer = setTimeout(() => {
|
|
174
|
+
if (pending.has(id)) {
|
|
175
|
+
pending.delete(id);
|
|
176
|
+
reject(new Error(`MCP method ${method} timed out after ${timeout}ms`));
|
|
177
|
+
}
|
|
178
|
+
}, timeout);
|
|
179
|
+
pending.set(id, { resolve, reject, timer });
|
|
180
|
+
child.stdin.write(`${JSON.stringify({ jsonrpc: '2.0', id, method, params })}\n`);
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
async function tool(name, args) {
|
|
185
|
+
const result = await rpc('tools/call', { name, arguments: args ?? {} });
|
|
186
|
+
if (result?.isError) {
|
|
187
|
+
const text = textOf(result);
|
|
188
|
+
throw new Error(`Playwright MCP ${name} failed: ${text || JSON.stringify(result)}`);
|
|
189
|
+
}
|
|
190
|
+
return result;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
await rpc('initialize', {
|
|
194
|
+
protocolVersion: '2024-11-05',
|
|
195
|
+
capabilities: {},
|
|
196
|
+
clientInfo: { name: 'rcf-lite-pack-browser', version: '0.0.0' },
|
|
197
|
+
}, { timeout: INIT_TIMEOUT_MS });
|
|
198
|
+
// Best-effort initialized notification (some servers ignore, that is fine).
|
|
199
|
+
try {
|
|
200
|
+
child.stdin.write(`${JSON.stringify({ jsonrpc: '2.0', method: 'notifications/initialized' })}\n`);
|
|
201
|
+
} catch { /* fine */ }
|
|
202
|
+
|
|
203
|
+
return Object.freeze({
|
|
204
|
+
provisioning: { via: 'playwright-mcp', version: playwrightMcpVersion },
|
|
205
|
+
async goto(url) {
|
|
206
|
+
await tool('browser_navigate', { url });
|
|
207
|
+
},
|
|
208
|
+
async snapshot() {
|
|
209
|
+
return textOf(await tool('browser_snapshot', {}));
|
|
210
|
+
},
|
|
211
|
+
async evaluate(fn, arg) {
|
|
212
|
+
const src = composeEvaluateSource(fn, arg);
|
|
213
|
+
const text = textOf(await tool('browser_evaluate', { function: src }));
|
|
214
|
+
return parseEvaluateResult(text);
|
|
215
|
+
},
|
|
216
|
+
async click(selector, hint) {
|
|
217
|
+
await tool('browser_click', { target: selector, element: hint ?? selector });
|
|
218
|
+
},
|
|
219
|
+
async type(selector, text, hint) {
|
|
220
|
+
await tool('browser_type', { target: selector, text, element: hint ?? selector });
|
|
221
|
+
},
|
|
222
|
+
async press(key) {
|
|
223
|
+
await tool('browser_press_key', { key });
|
|
224
|
+
},
|
|
225
|
+
async resize(width, height) {
|
|
226
|
+
const w = normaliseDim(width, 'width');
|
|
227
|
+
const h = normaliseDim(height, 'height');
|
|
228
|
+
await tool('browser_resize', { width: w, height: h });
|
|
229
|
+
},
|
|
230
|
+
async screenshot(filename) {
|
|
231
|
+
const args = filename ? { filename } : {};
|
|
232
|
+
return textOf(await tool('browser_take_screenshot', args));
|
|
233
|
+
},
|
|
234
|
+
async close() {
|
|
235
|
+
logger('[pack-browser] closing playwright-mcp browser');
|
|
236
|
+
try { await tool('browser_close', {}); } catch { /* fine */ }
|
|
237
|
+
try { child.stdin.end(); } catch { /* fine */ }
|
|
238
|
+
await new Promise((resolve) => {
|
|
239
|
+
if (exited) return resolve();
|
|
240
|
+
const timer = setTimeout(() => { try { child.kill('SIGKILL'); } catch { /* fine */ } resolve(); }, 5000);
|
|
241
|
+
child.once('exit', () => { clearTimeout(timer); resolve(); });
|
|
242
|
+
});
|
|
243
|
+
},
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Coerce a viewport dimension argument to a positive integer.
|
|
249
|
+
* Exposed for unit tests through resize() call sites.
|
|
250
|
+
*/
|
|
251
|
+
function normaliseDim(value, label) {
|
|
252
|
+
const n = Number(value);
|
|
253
|
+
if (!Number.isFinite(n) || n <= 0) {
|
|
254
|
+
throw new Error(`packBrowser.resize: ${label} must be a positive number (got ${JSON.stringify(value)})`);
|
|
255
|
+
}
|
|
256
|
+
return Math.round(n);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
function textOf(result) {
|
|
260
|
+
const parts = Array.isArray(result?.content) ? result.content : [];
|
|
261
|
+
return parts.map((c) => (c?.type === 'text' ? (c.text ?? '') : '')).join('\n');
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function composeEvaluateSource(fn, arg) {
|
|
265
|
+
if (typeof fn !== 'function') return String(fn);
|
|
266
|
+
if (arg === undefined) return fn.toString();
|
|
267
|
+
return `() => (${fn.toString()})(${JSON.stringify(arg)})`;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* The MCP browser_evaluate response is a human-readable text block, usually of
|
|
272
|
+
* the shape "- Ran Playwright code:\n... - Result: <json-ish>". Parse the trailing
|
|
273
|
+
* value out of it and JSON-parse when possible. Exported for unit tests.
|
|
274
|
+
*/
|
|
275
|
+
export function parseEvaluateResult(text) {
|
|
276
|
+
if (typeof text !== 'string') return text;
|
|
277
|
+
// MCP 0.0.80+ returns "### Result\n<value>\n### Ran Playwright code\n```js..."
|
|
278
|
+
const headed = text.match(/###\s*Result\s*\n([\s\S]*?)(?=\n###\s|\n?$)/);
|
|
279
|
+
if (headed) {
|
|
280
|
+
const inner = headed[1].trim().replace(/^```(?:json)?\s*/i, '').replace(/```\s*$/i, '').trim();
|
|
281
|
+
try { return JSON.parse(inner); } catch { return inner; }
|
|
282
|
+
}
|
|
283
|
+
// Older MCP shape: "Result: <value>" trailing block.
|
|
284
|
+
const marker = text.lastIndexOf('Result:');
|
|
285
|
+
const tail = marker >= 0 ? text.slice(marker + 'Result:'.length).trim() : text.trim();
|
|
286
|
+
const stripped = tail.replace(/^```(?:json)?\s*/i, '').replace(/```\s*$/i, '').trim();
|
|
287
|
+
try { return JSON.parse(stripped); } catch { return stripped; }
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Internals exposed to unit tests. Not part of the public seam a
|
|
292
|
+
* probe pack sees; do not import from a pack.
|
|
293
|
+
*/
|
|
294
|
+
export const PACK_BROWSER_INTERNALS = Object.freeze({ normaliseDim });
|