rcf-lite 0.27.0 → 0.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/README.md +10 -0
- package/bin/rcf.js +2 -0
- package/blueprints/application-account-settings/CHANGELOG.md +35 -6
- package/blueprints/application-account-settings/README.md +1 -1
- package/blueprints/application-account-settings/blueprint.json +4 -2
- package/blueprints/application-account-settings/contributions/adrs/adr-2602-application-account-settings-security-surface-shape.json +1 -1
- package/blueprints/application-account-settings/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-account-settings/contributions/probes/profile-form-autocomplete.mjs +67 -0
- package/blueprints/application-account-settings/contributions/probes/run-profile-form-autocomplete.mjs +5 -0
- package/blueprints/application-account-settings/contributions/probes/run-sessions-adapter-uniform.mjs +5 -0
- package/blueprints/application-account-settings/contributions/probes/run-sessions-surface-shape.mjs +5 -0
- package/blueprints/application-account-settings/contributions/probes/run-shell-tablist-per-capability.mjs +5 -0
- package/blueprints/application-account-settings/contributions/probes/run-theme-radiogroup.mjs +5 -0
- package/blueprints/application-account-settings/contributions/probes/sessions-adapter-uniform.mjs +130 -0
- package/blueprints/application-account-settings/contributions/probes/sessions-surface-shape.mjs +70 -0
- package/blueprints/application-account-settings/contributions/probes/shell-tablist-per-capability.mjs +60 -0
- package/blueprints/application-account-settings/contributions/probes/theme-radiogroup.mjs +126 -0
- package/blueprints/application-admin-console/CHANGELOG.md +32 -6
- package/blueprints/application-admin-console/README.md +1 -1
- package/blueprints/application-admin-console/blueprint.json +4 -2
- package/blueprints/application-admin-console/contributions/adrs/adr-2201-application-admin-console-capability-vocabulary.json +1 -1
- package/blueprints/application-admin-console/contributions/probes/audit-log-surface.mjs +79 -0
- package/blueprints/application-admin-console/contributions/probes/org-switcher-surface.mjs +83 -0
- package/blueprints/application-admin-console/contributions/probes/permission-matrix-grid.mjs +67 -0
- package/blueprints/application-admin-console/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-admin-console/contributions/probes/run-audit-log-surface.mjs +5 -0
- package/blueprints/application-admin-console/contributions/probes/run-org-switcher-surface.mjs +5 -0
- package/blueprints/application-admin-console/contributions/probes/run-permission-matrix-grid.mjs +5 -0
- package/blueprints/application-admin-console/contributions/probes/run-sign-in-access-gated-surface.mjs +5 -0
- package/blueprints/application-admin-console/contributions/probes/run-users-directory-surface.mjs +5 -0
- package/blueprints/application-admin-console/contributions/probes/sign-in-access-gated-surface.mjs +117 -0
- package/blueprints/application-admin-console/contributions/probes/users-directory-surface.mjs +145 -0
- package/blueprints/application-api-rest/CHANGELOG.md +16 -8
- package/blueprints/application-api-rest/README.md +3 -3
- package/blueprints/application-api-rest/blueprint.json +3 -2
- package/blueprints/application-api-rest/contributions/adrs/adr-302-application-api-rest-auth-model.json +1 -1
- package/blueprints/application-api-rest/contributions/probes/cursor-pagination-round-trip.mjs +154 -0
- package/blueprints/application-api-rest/contributions/probes/health-probes-distinct.mjs +124 -0
- package/blueprints/application-api-rest/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-api-rest/contributions/probes/problem-details-on-error.mjs +77 -0
- package/blueprints/application-api-rest/contributions/probes/request-id-echoed.mjs +76 -0
- package/blueprints/application-api-rest/contributions/probes/run-cursor-pagination-round-trip.mjs +5 -0
- package/blueprints/application-api-rest/contributions/probes/run-health-probes-distinct.mjs +5 -0
- package/blueprints/application-api-rest/contributions/probes/run-problem-details-on-error.mjs +5 -0
- package/blueprints/application-api-rest/contributions/probes/run-request-id-echoed.mjs +5 -0
- package/blueprints/application-api-rest/docs/topics.md +1 -1
- package/blueprints/application-charts/CHANGELOG.md +35 -9
- package/blueprints/application-charts/README.md +6 -6
- package/blueprints/application-charts/blueprint.json +5 -3
- package/blueprints/application-charts/contributions/adrs/adr-1901-application-charts-engine-choice.json +1 -1
- package/blueprints/application-charts/contributions/probes/keyboard-traversal.mjs +151 -0
- package/blueprints/application-charts/contributions/probes/non-colour-distinction.mjs +67 -0
- package/blueprints/application-charts/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-charts/contributions/probes/run-keyboard-traversal.mjs +5 -0
- package/blueprints/application-charts/contributions/probes/run-non-colour-distinction.mjs +5 -0
- package/blueprints/application-charts/contributions/probes/run-text-alternative-table.mjs +5 -0
- package/blueprints/application-charts/contributions/probes/text-alternative-table.mjs +139 -0
- package/blueprints/application-charts/contributions/requirements/application-charts-req-001.json +1 -1
- package/blueprints/application-charts/contributions/requirements/application-charts-req-002.json +1 -1
- package/blueprints/application-charts/contributions/user-stories/application-charts-us-18101.json +5 -5
- package/blueprints/application-charts/contributions/user-stories/application-charts-us-18106.json +1 -1
- package/blueprints/application-charts/guide/application-charts.md +1 -1
- package/blueprints/application-dashboard/CHANGELOG.md +20 -10
- package/blueprints/application-dashboard/README.md +6 -6
- package/blueprints/application-dashboard/assets/guidance/dashboard-design.md +2 -2
- package/blueprints/application-dashboard/blueprint.json +3 -2
- package/blueprints/application-dashboard/contributions/adrs/adr-2001-application-dashboard-primary-kpi-enum.json +1 -1
- package/blueprints/application-dashboard/contributions/adrs/adr-2002-application-dashboard-timeframe-presets.json +1 -1
- package/blueprints/application-dashboard/contributions/probes/export-handle-formats.mjs +75 -0
- package/blueprints/application-dashboard/contributions/probes/four-tile-states.mjs +75 -0
- package/blueprints/application-dashboard/contributions/probes/primary-kpi-top-left.mjs +58 -0
- package/blueprints/application-dashboard/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-dashboard/contributions/probes/run-export-handle-formats.mjs +4 -0
- package/blueprints/application-dashboard/contributions/probes/run-four-tile-states.mjs +4 -0
- package/blueprints/application-dashboard/contributions/probes/run-primary-kpi-top-left.mjs +4 -0
- package/blueprints/application-dashboard/contributions/probes/run-shell-five-regions.mjs +4 -0
- package/blueprints/application-dashboard/contributions/probes/shell-five-regions.mjs +93 -0
- package/blueprints/application-dashboard/contributions/requirements/application-dashboard-req-002.json +1 -1
- package/blueprints/application-dashboard/contributions/requirements/application-dashboard-req-003.json +1 -1
- package/blueprints/application-dashboard/contributions/tacs/tac-2002-application-dashboard-filter-chrome.json +1 -1
- 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-19101.json +2 -2
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19102.json +2 -2
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19103.json +1 -1
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19104.json +1 -1
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19105.json +1 -1
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19106.json +2 -2
- package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19107.json +5 -5
- package/blueprints/application-dashboard/docs/topics.md +2 -2
- package/blueprints/application-dashboard/guide/application-dashboard.md +2 -2
- package/blueprints/application-datatable/CHANGELOG.md +19 -9
- package/blueprints/application-datatable/README.md +2 -2
- package/blueprints/application-datatable/blueprint.json +3 -2
- package/blueprints/application-datatable/contributions/probes/apg-table-shape.mjs +57 -0
- package/blueprints/application-datatable/contributions/probes/four-states-regions.mjs +80 -0
- package/blueprints/application-datatable/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-datatable/contributions/probes/run-apg-table-shape.mjs +4 -0
- package/blueprints/application-datatable/contributions/probes/run-four-states-regions.mjs +4 -0
- package/blueprints/application-datatable/contributions/probes/run-search-adapter-round-trip.mjs +4 -0
- package/blueprints/application-datatable/contributions/probes/run-sort-adapter-round-trip.mjs +4 -0
- package/blueprints/application-datatable/contributions/probes/search-adapter-round-trip.mjs +58 -0
- package/blueprints/application-datatable/contributions/probes/sort-adapter-round-trip.mjs +60 -0
- package/blueprints/application-datatable/contributions/requirements/application-datatable-req-006.json +1 -1
- package/blueprints/application-datatable/docs/topics.md +1 -1
- package/blueprints/application-empty-error-states/CHANGELOG.md +33 -3
- package/blueprints/application-empty-error-states/blueprint.json +4 -2
- package/blueprints/application-empty-error-states/contributions/probes/empty-list-and-no-search.mjs +66 -0
- package/blueprints/application-empty-error-states/contributions/probes/error-boundary-alert.mjs +65 -0
- package/blueprints/application-empty-error-states/contributions/probes/forbidden-and-server-error.mjs +167 -0
- package/blueprints/application-empty-error-states/contributions/probes/not-found-and-recovery.mjs +61 -0
- package/blueprints/application-empty-error-states/contributions/probes/permission-denied-and-offline.mjs +155 -0
- package/blueprints/application-empty-error-states/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-empty-error-states/contributions/probes/run-empty-list-and-no-search.mjs +5 -0
- package/blueprints/application-empty-error-states/contributions/probes/run-error-boundary-alert.mjs +5 -0
- package/blueprints/application-empty-error-states/contributions/probes/run-forbidden-and-server-error.mjs +5 -0
- package/blueprints/application-empty-error-states/contributions/probes/run-not-found-and-recovery.mjs +5 -0
- package/blueprints/application-empty-error-states/contributions/probes/run-permission-denied-and-offline.mjs +5 -0
- package/blueprints/application-error-handling/CHANGELOG.md +45 -6
- package/blueprints/application-error-handling/blueprint.json +3 -2
- package/blueprints/application-error-handling/contributions/probes/category-vocabulary.mjs +90 -0
- package/blueprints/application-error-handling/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-error-handling/contributions/probes/record-shape-adr-1701.mjs +78 -0
- package/blueprints/application-error-handling/contributions/probes/run-category-vocabulary.mjs +5 -0
- package/blueprints/application-error-handling/contributions/probes/run-record-shape-adr-1701.mjs +5 -0
- package/blueprints/application-error-handling/contributions/probes/run-two-boundaries-registered.mjs +5 -0
- package/blueprints/application-error-handling/contributions/probes/two-boundaries-registered.mjs +343 -0
- package/blueprints/application-file-upload/CHANGELOG.md +28 -6
- package/blueprints/application-file-upload/README.md +1 -1
- package/blueprints/application-file-upload/blueprint.json +3 -2
- package/blueprints/application-file-upload/contributions/probes/assertive-completion-slot.mjs +78 -0
- package/blueprints/application-file-upload/contributions/probes/chunked-transport-endpoints.mjs +173 -0
- package/blueprints/application-file-upload/contributions/probes/per-file-progressbar.mjs +124 -0
- package/blueprints/application-file-upload/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-file-upload/contributions/probes/run-assertive-completion-slot.mjs +4 -0
- package/blueprints/application-file-upload/contributions/probes/run-chunked-transport-endpoints.mjs +4 -0
- package/blueprints/application-file-upload/contributions/probes/run-per-file-progressbar.mjs +4 -0
- package/blueprints/application-file-upload/contributions/probes/run-upload-surface-shape.mjs +4 -0
- package/blueprints/application-file-upload/contributions/probes/upload-surface-shape.mjs +55 -0
- 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/probe-packs/application-file-upload.pack.mjs +1 -1
- package/blueprints/application-forms-wizard/CHANGELOG.md +20 -6
- package/blueprints/application-forms-wizard/README.md +2 -2
- package/blueprints/application-forms-wizard/blueprint.json +3 -2
- package/blueprints/application-forms-wizard/contributions/probes/draft-persistence-round-trip.mjs +110 -0
- package/blueprints/application-forms-wizard/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-forms-wizard/contributions/probes/run-draft-persistence-round-trip.mjs +4 -0
- package/blueprints/application-forms-wizard/contributions/probes/run-step-page-shape.mjs +4 -0
- package/blueprints/application-forms-wizard/contributions/probes/run-task-list-surface.mjs +4 -0
- package/blueprints/application-forms-wizard/contributions/probes/step-page-shape.mjs +61 -0
- package/blueprints/application-forms-wizard/contributions/probes/task-list-surface.mjs +109 -0
- 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/probe-packs/application-forms-wizard.pack.mjs +1 -1
- package/blueprints/application-notifications-in-app/CHANGELOG.md +38 -5
- package/blueprints/application-notifications-in-app/README.md +4 -4
- package/blueprints/application-notifications-in-app/blueprint.json +4 -2
- package/blueprints/application-notifications-in-app/contributions/adrs/adr-2101-application-notifications-in-app-live-region-role-mapping.json +1 -1
- package/blueprints/application-notifications-in-app/contributions/probes/centre-acknowledge-round-trip.mjs +210 -0
- package/blueprints/application-notifications-in-app/contributions/probes/live-region-preseeding.mjs +93 -0
- package/blueprints/application-notifications-in-app/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-notifications-in-app/contributions/probes/run-centre-acknowledge-round-trip.mjs +5 -0
- package/blueprints/application-notifications-in-app/contributions/probes/run-live-region-preseeding.mjs +5 -0
- package/blueprints/application-notifications-in-app/contributions/probes/run-toast-contract.mjs +5 -0
- package/blueprints/application-notifications-in-app/contributions/probes/toast-contract.mjs +92 -0
- package/blueprints/application-notifications-in-app/contributions/tacs/tac-2101-application-notifications-in-app-live-region.json +3 -3
- package/blueprints/application-notifications-in-app/contributions/tacs/tac-2102-application-notifications-in-app-centre.json +1 -1
- 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 +1 -1
- package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20105.json +1 -1
- package/blueprints/application-notifications-in-app/guide/application-notifications-in-app.md +3 -3
- package/blueprints/application-onboarding-tour/CHANGELOG.md +31 -5
- package/blueprints/application-onboarding-tour/README.md +1 -1
- package/blueprints/application-onboarding-tour/blueprint.json +5 -3
- package/blueprints/application-onboarding-tour/contributions/probes/checklist-anchor-open.mjs +81 -0
- package/blueprints/application-onboarding-tour/contributions/probes/completion-persistence.mjs +159 -0
- package/blueprints/application-onboarding-tour/contributions/probes/first-run-detection.mjs +67 -0
- package/blueprints/application-onboarding-tour/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-onboarding-tour/contributions/probes/run-checklist-anchor-open.mjs +5 -0
- package/blueprints/application-onboarding-tour/contributions/probes/run-completion-persistence.mjs +5 -0
- package/blueprints/application-onboarding-tour/contributions/probes/run-first-run-detection.mjs +5 -0
- package/blueprints/application-onboarding-tour/contributions/probes/run-stepper-role-dialog.mjs +5 -0
- package/blueprints/application-onboarding-tour/contributions/probes/stepper-role-dialog.mjs +45 -0
- package/blueprints/application-spa/CHANGELOG.md +20 -11
- package/blueprints/application-spa/README.md +9 -10
- package/blueprints/application-spa/blueprint.json +3 -2
- package/blueprints/application-spa/contributions/adrs/adr-202-application-spa-theming.json +1 -1
- package/blueprints/application-spa/contributions/adrs/adr-206-application-spa-iconography.json +1 -1
- package/blueprints/application-spa/contributions/probes/designed-empty-state.mjs +72 -0
- package/blueprints/application-spa/contributions/probes/probe-utils.mjs +177 -0
- package/blueprints/application-spa/contributions/probes/route-inventory-published.mjs +185 -0
- package/blueprints/application-spa/contributions/probes/run-designed-empty-state.mjs +5 -0
- package/blueprints/application-spa/contributions/probes/run-route-inventory-published.mjs +5 -0
- package/blueprints/application-spa/contributions/probes/run-shell-nav-present.mjs +5 -0
- package/blueprints/application-spa/contributions/probes/shell-nav-present.mjs +69 -0
- package/blueprints/application-spa/contributions/tacs/tac-207-application-spa-token-adherence-probe.json +1 -1
- package/blueprints/application-spa/contributions/tacs/tac-208-application-spa-icon-adherence-probe.json +2 -2
- package/blueprints/application-spa/contributions/tacs/tac-209-application-spa-csp-styled-adherence-probe.json +3 -3
- package/blueprints/application-spa/contributions/tacs/tac-210-application-spa-external-dependency-provisioning-probe.json +2 -2
- package/blueprints/application-spa/contributions/tacs/tac-211-application-spa-core-flow-e2e-probe.json +2 -2
- package/blueprints/application-spa/contributions/user-stories/application-spa-us-1131.json +1 -1
- package/blueprints/application-spa/docs/topics.md +1 -1
- package/blueprints/delivery-ci-workflows/CHANGELOG.md +31 -11
- package/blueprints/delivery-ci-workflows/README.md +3 -3
- package/blueprints/delivery-ci-workflows/blueprint.json +3 -2
- package/blueprints/delivery-ci-workflows/contributions/adrs/adr-702-delivery-ci-workflows-strict-coverage-gate.json +2 -2
- package/blueprints/delivery-ci-workflows/contributions/probes/node-gate-entrypoint.mjs +76 -0
- package/blueprints/delivery-ci-workflows/contributions/probes/probe-utils.mjs +56 -0
- package/blueprints/delivery-ci-workflows/contributions/probes/real-account-github-actions-run-record.mjs +139 -0
- package/blueprints/delivery-ci-workflows/contributions/probes/run-node-gate-entrypoint.mjs +3 -0
- package/blueprints/delivery-ci-workflows/contributions/probes/run-real-account-github-actions-run-record.mjs +3 -0
- package/blueprints/delivery-ci-workflows/contributions/probes/run-workflow-template-shape.mjs +3 -0
- package/blueprints/delivery-ci-workflows/contributions/probes/workflow-template-shape.mjs +94 -0
- package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-004.json +1 -1
- package/blueprints/delivery-ci-workflows/docs/topics.md +2 -3
- package/blueprints/deploy-cloudflare-workers/CHANGELOG.md +4 -4
- package/blueprints/deploy-cloudflare-workers/README.md +3 -3
- package/blueprints/deploy-cloudflare-workers/contributions/adrs/adr-1306-deploy-cloudflare-workers-spa-shape.json +2 -2
- package/blueprints/deploy-cloudflare-workers/docs/topics.md +2 -2
- package/blueprints/deploy-hetzner-server/CHANGELOG.md +98 -7
- package/blueprints/deploy-hetzner-server/blueprint.json +7 -6
- package/blueprints/deploy-hetzner-server/contributions/probes/cloud-init-render-lint.mjs +46 -21
- package/blueprints/deploy-hetzner-server/contributions/probes/hcloud-dry-run-mock.mjs +344 -83
- package/blueprints/deploy-hetzner-server/contributions/probes/manifest-schema-validate.mjs +211 -42
- package/blueprints/deploy-hetzner-server/contributions/probes/probe-utils.mjs +140 -22
- package/blueprints/deploy-hetzner-server/contributions/probes/real-account-cloud-init-hardened.mjs +111 -30
- package/blueprints/deploy-hetzner-server/contributions/probes/real-account-snapshot-on-demand.mjs +158 -30
- package/blueprints/deploy-hetzner-server/contributions/probes/real-account-throwaway-server-provision.mjs +154 -32
- package/blueprints/edge-cloudflare-access/CHANGELOG.md +6 -5
- package/blueprints/edge-cloudflare-access/blueprint.json +1 -1
- package/blueprints/edge-cloudflare-access/contributions/probes/admin-console-gate-surface.mjs +9 -1
- package/blueprints/edge-cloudflare-access/docs/topics.md +1 -1
- package/blueprints/edge-cloudflare-rate-limiting/CHANGELOG.md +4 -7
- package/blueprints/edge-cloudflare-rate-limiting/docs/topics.md +1 -1
- package/blueprints/edge-cloudflare-tunnel/CHANGELOG.md +4 -6
- package/blueprints/edge-cloudflare-tunnel/README.md +1 -2
- package/blueprints/edge-cloudflare-tunnel/docs/topics.md +1 -1
- package/blueprints/edge-cloudflare-turnstile/CHANGELOG.md +2 -3
- package/blueprints/edge-cloudflare-turnstile/docs/topics.md +1 -1
- package/blueprints/email-smtp-resend/CHANGELOG.md +24 -8
- package/blueprints/email-smtp-resend/README.md +2 -2
- package/blueprints/email-smtp-resend/blueprint.json +3 -2
- package/blueprints/email-smtp-resend/contributions/probes/probe-utils.mjs +50 -0
- package/blueprints/email-smtp-resend/contributions/probes/real-account-resend-send.mjs +50 -0
- package/blueprints/email-smtp-resend/contributions/probes/run-real-account-resend-send.mjs +3 -0
- package/blueprints/email-smtp-resend/contributions/probes/run-smtp-round-trip.mjs +3 -0
- package/blueprints/email-smtp-resend/contributions/probes/run-unverified-sender-refusal.mjs +3 -0
- package/blueprints/email-smtp-resend/contributions/probes/smtp-round-trip.mjs +43 -0
- package/blueprints/email-smtp-resend/contributions/probes/unverified-sender-refusal.mjs +99 -0
- package/blueprints/email-smtp-resend/docs/topics.md +2 -3
- package/blueprints/jobs-background/CHANGELOG.md +66 -5
- package/blueprints/jobs-background/README.md +2 -2
- package/blueprints/jobs-background/blueprint.json +3 -2
- package/blueprints/jobs-background/contributions/probes/apply-time-override.mjs +38 -10
- package/blueprints/jobs-background/contributions/probes/apply-time-refusal.mjs +28 -6
- package/blueprints/jobs-background/contributions/probes/event-secrecy.mjs +16 -2
- package/blueprints/jobs-background/contributions/probes/fake-clock-cron.mjs +102 -21
- package/blueprints/jobs-background/contributions/probes/probe-utils.mjs +10 -2
- package/blueprints/jobs-background/contributions/probes/retry-and-fail-real-account.mjs +355 -0
- package/blueprints/jobs-background/contributions/probes/retry-and-fail.mjs +33 -2
- package/blueprints/jobs-background/contributions/probes/run-retry-and-fail-real-account.mjs +12 -0
- package/blueprints/jobs-background/docs/topics.md +1 -1
- package/blueprints/jobs-background/guide/jobs-background.md +1 -1
- package/blueprints/messaging-queue-cloudflare/CHANGELOG.md +25 -19
- package/blueprints/messaging-queue-cloudflare/README.md +12 -12
- package/blueprints/messaging-queue-cloudflare/blueprint.json +1 -1
- package/blueprints/messaging-queue-cloudflare/contributions/adrs/adr-3001-messaging-queue-cloudflare-adapter.json +2 -2
- package/blueprints/messaging-queue-cloudflare/contributions/adrs/adr-3002-messaging-queue-cloudflare-delivery-semantics.json +1 -1
- package/blueprints/messaging-queue-cloudflare/contributions/probes/real-account-concurrency-smoke.mjs +180 -12
- package/blueprints/messaging-queue-cloudflare/contributions/requirements/messaging-queue-cloudflare-req-006.json +1 -1
- package/blueprints/messaging-queue-cloudflare/docs/topics.md +2 -2
- package/blueprints/messaging-queue-cloudflare/guide/messaging-queue-cloudflare.md +2 -2
- package/blueprints/object-storage-s3/CHANGELOG.md +75 -4
- package/blueprints/object-storage-s3/blueprint.json +3 -2
- package/blueprints/object-storage-s3/contributions/probes/event-secrecy.mjs +73 -12
- package/blueprints/object-storage-s3/contributions/probes/facade-round-trip.mjs +55 -7
- package/blueprints/object-storage-s3/contributions/probes/hetzner-object-storage-round-trip.mjs +102 -18
- package/blueprints/object-storage-s3/contributions/probes/multipart-upload.mjs +105 -36
- package/blueprints/object-storage-s3/contributions/probes/presigned-url.mjs +104 -55
- package/blueprints/object-storage-s3/contributions/probes/probe-utils.mjs +129 -7
- package/blueprints/object-storage-s3/contributions/probes/put-get-round-trip.mjs +80 -18
- package/blueprints/object-storage-s3/contributions/probes/r2-real-account-smoke.mjs +291 -37
- package/blueprints/object-storage-s3/contributions/probes/run-event-secrecy.mjs +8 -2
- package/blueprints/object-storage-s3/contributions/probes/run-facade-round-trip.mjs +5 -5
- package/blueprints/object-storage-s3/contributions/probes/run-hetzner-object-storage-round-trip.mjs +8 -5
- package/blueprints/object-storage-s3/contributions/probes/run-multipart-upload.mjs +8 -2
- package/blueprints/object-storage-s3/contributions/probes/run-presigned-url.mjs +8 -2
- package/blueprints/object-storage-s3/contributions/probes/run-put-get-round-trip.mjs +6 -3
- package/blueprints/object-storage-s3/contributions/probes/run-r2-real-account-smoke.mjs +10 -2
- package/blueprints/object-storage-s3/contributions/requirements/object-storage-s3-req-006.json +1 -1
- package/blueprints/object-storage-s3/docs/topics.md +1 -1
- package/blueprints/object-storage-s3/guide/object-storage-s3.md +1 -1
- package/blueprints/observability-essentials/CHANGELOG.md +23 -7
- package/blueprints/observability-essentials/README.md +2 -2
- package/blueprints/observability-essentials/assets/probe-samples/probe-response-baseline.v2.json +1 -1
- package/blueprints/observability-essentials/blueprint.json +3 -2
- package/blueprints/observability-essentials/contributions/probes/liveness-probe.mjs +84 -0
- package/blueprints/observability-essentials/contributions/probes/metrics-endpoint.mjs +96 -0
- package/blueprints/observability-essentials/contributions/probes/probe-utils.mjs +52 -0
- package/blueprints/observability-essentials/contributions/probes/readiness-probe.mjs +171 -0
- package/blueprints/observability-essentials/contributions/probes/run-liveness-probe.mjs +3 -0
- package/blueprints/observability-essentials/contributions/probes/run-metrics-endpoint.mjs +3 -0
- package/blueprints/observability-essentials/contributions/probes/run-readiness-probe.mjs +3 -0
- package/blueprints/observability-essentials/docs/topics.md +2 -3
- package/blueprints/observability-logging/CHANGELOG.md +29 -4
- package/blueprints/observability-logging/README.md +2 -2
- package/blueprints/observability-logging/blueprint.json +3 -2
- package/blueprints/observability-logging/contributions/probes/correlation-id-flow.mjs +173 -0
- package/blueprints/observability-logging/contributions/probes/line-shape-and-fields.mjs +82 -0
- package/blueprints/observability-logging/contributions/probes/probe-utils.mjs +47 -0
- package/blueprints/observability-logging/contributions/probes/redaction-boundary.mjs +130 -0
- package/blueprints/observability-logging/contributions/probes/run-correlation-id-flow.mjs +3 -0
- package/blueprints/observability-logging/contributions/probes/run-line-shape-and-fields.mjs +3 -0
- package/blueprints/observability-logging/contributions/probes/run-redaction-boundary.mjs +3 -0
- package/blueprints/observability-probe-endpoints/CHANGELOG.md +23 -8
- package/blueprints/observability-probe-endpoints/README.md +3 -3
- package/blueprints/observability-probe-endpoints/blueprint.json +3 -2
- package/blueprints/observability-probe-endpoints/contributions/probes/kubernetes-startup-enabled.mjs +80 -0
- package/blueprints/observability-probe-endpoints/contributions/probes/partial-profile-refusal.mjs +101 -0
- package/blueprints/observability-probe-endpoints/contributions/probes/probe-utils.mjs +49 -0
- package/blueprints/observability-probe-endpoints/contributions/probes/profile-boot-materialisation.mjs +69 -0
- package/blueprints/observability-probe-endpoints/contributions/probes/run-kubernetes-startup-enabled.mjs +3 -0
- package/blueprints/observability-probe-endpoints/contributions/probes/run-partial-profile-refusal.mjs +3 -0
- package/blueprints/observability-probe-endpoints/contributions/probes/run-profile-boot-materialisation.mjs +3 -0
- package/blueprints/observability-probe-endpoints/docs/topics.md +2 -2
- package/blueprints/persistence-data-d1/CHANGELOG.md +16 -3
- package/blueprints/persistence-data-d1/README.md +2 -2
- package/blueprints/persistence-data-d1/blueprint.json +3 -2
- package/blueprints/persistence-data-d1/contributions/adrs/adr-1404-persistence-data-d1-store-boundary.json +1 -1
- package/blueprints/persistence-data-d1/contributions/probes/facade-round-trip.mjs +140 -0
- package/blueprints/persistence-data-d1/contributions/probes/migrations-forward-only.mjs +66 -0
- package/blueprints/persistence-data-d1/contributions/probes/probe-utils.mjs +51 -0
- package/blueprints/persistence-data-d1/contributions/probes/real-account-d1-round-trip.mjs +133 -0
- package/blueprints/persistence-data-d1/contributions/probes/run-facade-round-trip.mjs +3 -0
- package/blueprints/persistence-data-d1/contributions/probes/run-migrations-forward-only.mjs +3 -0
- package/blueprints/persistence-data-d1/contributions/probes/run-real-account-d1-round-trip.mjs +3 -0
- package/blueprints/persistence-data-d1/docs/topics.md +2 -3
- package/blueprints/persistence-data-postgres/CHANGELOG.md +84 -4
- package/blueprints/persistence-data-postgres/README.md +2 -2
- package/blueprints/persistence-data-postgres/blueprint.json +3 -2
- package/blueprints/persistence-data-postgres/contributions/adrs/adr-2801-persistence-data-postgres-driver.json +1 -1
- package/blueprints/persistence-data-postgres/contributions/probes/facade-round-trip.mjs +87 -12
- package/blueprints/persistence-data-postgres/contributions/probes/migration-apply.mjs +245 -19
- package/blueprints/persistence-data-postgres/contributions/probes/pool-posture-smoke.mjs +109 -26
- package/blueprints/persistence-data-postgres/contributions/probes/prepared-statement-scan.mjs +151 -38
- package/blueprints/persistence-data-postgres/contributions/probes/probe-utils.mjs +24 -6
- package/blueprints/persistence-data-postgres/contributions/probes/recovery-restore-round-trip.mjs +261 -48
- package/blueprints/persistence-data-postgres/contributions/probes/transaction-atomicity.mjs +76 -20
- package/blueprints/persistence-data-postgres/contributions/requirements/persistence-data-postgres-req-003.json +1 -1
- package/blueprints/persistence-data-postgres/docs/topics.md +1 -1
- package/blueprints/persistence-data-sqlite/CHANGELOG.md +16 -2
- package/blueprints/persistence-data-sqlite/README.md +2 -2
- package/blueprints/persistence-data-sqlite/blueprint.json +3 -2
- package/blueprints/persistence-data-sqlite/contributions/probes/boot-open-migrate.mjs +90 -0
- package/blueprints/persistence-data-sqlite/contributions/probes/facade-round-trip.mjs +82 -0
- package/blueprints/persistence-data-sqlite/contributions/probes/probe-utils.mjs +83 -0
- package/blueprints/persistence-data-sqlite/contributions/probes/run-boot-open-migrate.mjs +5 -0
- package/blueprints/persistence-data-sqlite/contributions/probes/run-facade-round-trip.mjs +5 -0
- package/blueprints/persistence-data-sqlite/contributions/probes/run-wal-checkpoint.mjs +5 -0
- package/blueprints/persistence-data-sqlite/contributions/probes/wal-checkpoint.mjs +137 -0
- package/blueprints/persistence-data-sqlite/docs/topics.md +2 -3
- package/blueprints/platform-cloudflare-cron-triggers/CHANGELOG.md +5 -5
- package/blueprints/platform-cloudflare-cron-triggers/README.md +2 -3
- package/blueprints/platform-cloudflare-cron-triggers/docs/topics.md +1 -1
- package/blueprints/platform-cloudflare-durable-objects/CHANGELOG.md +6 -10
- package/blueprints/platform-cloudflare-durable-objects/docs/topics.md +1 -1
- package/blueprints/platform-cloudflare-kv/CHANGELOG.md +16 -12
- package/blueprints/platform-cloudflare-kv/README.md +2 -4
- package/blueprints/platform-cloudflare-kv/blueprint.json +2 -2
- package/blueprints/platform-cloudflare-kv/docs/topics.md +1 -1
- package/blueprints/platform-docker-compose-host/CHANGELOG.md +92 -5
- package/blueprints/platform-docker-compose-host/blueprint.json +2 -2
- package/blueprints/platform-docker-compose-host/contributions/probes/caddyfile-validate.mjs +116 -29
- package/blueprints/platform-docker-compose-host/contributions/probes/compose-config-lint.mjs +181 -109
- package/blueprints/platform-docker-compose-host/contributions/probes/probe-utils.mjs +146 -26
- package/blueprints/platform-docker-compose-host/contributions/probes/real-account-minimal-stack-up.mjs +238 -24
- package/blueprints/platform-docker-compose-host/contributions/probes/real-account-reload-burst.mjs +207 -21
- package/blueprints/platform-docker-compose-host/contributions/probes/secrets-as-files-scan.mjs +246 -42
- package/blueprints/platform-docker-compose-host/docs/topics.md +1 -1
- package/blueprints/security-auth-clerk/CHANGELOG.md +18 -6
- package/blueprints/security-auth-clerk/README.md +3 -3
- package/blueprints/security-auth-clerk/assets/wiring/workers-wrangler-toml-shape.md +1 -1
- package/blueprints/security-auth-clerk/blueprint.json +3 -2
- package/blueprints/security-auth-clerk/contributions/probes/hosted-identity-ui-config.mjs +61 -0
- package/blueprints/security-auth-clerk/contributions/probes/probe-utils.mjs +188 -0
- package/blueprints/security-auth-clerk/contributions/probes/real-account-principal-directory-round-trip.mjs +216 -0
- package/blueprints/security-auth-clerk/contributions/probes/real-account-session-inventory.mjs +260 -0
- package/blueprints/security-auth-clerk/contributions/probes/role-model-adapter.mjs +53 -0
- package/blueprints/security-auth-clerk/contributions/probes/run-hosted-identity-ui-config.mjs +4 -0
- package/blueprints/security-auth-clerk/contributions/probes/run-real-account-principal-directory-round-trip.mjs +4 -0
- package/blueprints/security-auth-clerk/contributions/probes/run-real-account-session-inventory.mjs +4 -0
- package/blueprints/security-auth-clerk/contributions/probes/run-role-model-adapter.mjs +4 -0
- package/blueprints/security-auth-clerk/docs/topics.md +2 -3
- package/blueprints/security-auth-keycloak/CHANGELOG.md +18 -7
- package/blueprints/security-auth-keycloak/README.md +2 -2
- package/blueprints/security-auth-keycloak/blueprint.json +3 -2
- package/blueprints/security-auth-keycloak/contributions/probes/discovery-shape.mjs +68 -0
- package/blueprints/security-auth-keycloak/contributions/probes/introspection-shape.mjs +88 -0
- package/blueprints/security-auth-keycloak/contributions/probes/jwt-verifier-shape.mjs +86 -0
- package/blueprints/security-auth-keycloak/contributions/probes/probe-utils.mjs +180 -0
- package/blueprints/security-auth-keycloak/contributions/probes/real-account-realm-round-trip.mjs +91 -0
- package/blueprints/security-auth-keycloak/contributions/probes/role-adapter-shape.mjs +69 -0
- package/blueprints/security-auth-keycloak/contributions/probes/run-discovery-shape.mjs +4 -0
- package/blueprints/security-auth-keycloak/contributions/probes/run-introspection-shape.mjs +4 -0
- package/blueprints/security-auth-keycloak/contributions/probes/run-jwt-verifier-shape.mjs +4 -0
- package/blueprints/security-auth-keycloak/contributions/probes/run-real-account-realm-round-trip.mjs +4 -0
- package/blueprints/security-auth-keycloak/contributions/probes/run-role-adapter-shape.mjs +4 -0
- package/blueprints/security-auth-keycloak/docs/topics.md +1 -2
- package/blueprints/security-auth-magic-link/CHANGELOG.md +15 -4
- package/blueprints/security-auth-magic-link/README.md +2 -2
- package/blueprints/security-auth-magic-link/assets/principal-registry-samples/single-address.md +1 -1
- package/blueprints/security-auth-magic-link/blueprint.json +3 -2
- package/blueprints/security-auth-magic-link/contributions/probes/probe-utils.mjs +174 -0
- package/blueprints/security-auth-magic-link/contributions/probes/real-account-magic-link-send.mjs +139 -0
- package/blueprints/security-auth-magic-link/contributions/probes/run-real-account-magic-link-send.mjs +4 -0
- package/blueprints/security-auth-magic-link/contributions/probes/run-token-entropy-shape.mjs +4 -0
- package/blueprints/security-auth-magic-link/contributions/probes/run-token-issue-verify.mjs +4 -0
- package/blueprints/security-auth-magic-link/contributions/probes/token-entropy-shape.mjs +60 -0
- package/blueprints/security-auth-magic-link/contributions/probes/token-issue-verify.mjs +90 -0
- package/blueprints/security-auth-magic-link/docs/topics.md +1 -1
- package/blueprints/security-auth-oauth2/CHANGELOG.md +16 -5
- package/blueprints/security-auth-oauth2/README.md +2 -2
- package/blueprints/security-auth-oauth2/blueprint.json +3 -2
- package/blueprints/security-auth-oauth2/contributions/probes/authorisation-code-flow-shape.mjs +259 -0
- package/blueprints/security-auth-oauth2/contributions/probes/pkce-challenge-shape.mjs +58 -0
- package/blueprints/security-auth-oauth2/contributions/probes/probe-utils.mjs +190 -0
- package/blueprints/security-auth-oauth2/contributions/probes/provider-adapter-shape.mjs +64 -0
- package/blueprints/security-auth-oauth2/contributions/probes/real-account-authorisation-code-flow.mjs +93 -0
- package/blueprints/security-auth-oauth2/contributions/probes/run-authorisation-code-flow-shape.mjs +4 -0
- package/blueprints/security-auth-oauth2/contributions/probes/run-pkce-challenge-shape.mjs +4 -0
- package/blueprints/security-auth-oauth2/contributions/probes/run-provider-adapter-shape.mjs +4 -0
- package/blueprints/security-auth-oauth2/contributions/probes/run-real-account-authorisation-code-flow.mjs +4 -0
- package/blueprints/security-auth-oauth2/contributions/probes/run-session-bridge-shape.mjs +4 -0
- package/blueprints/security-auth-oauth2/contributions/probes/session-bridge-shape.mjs +78 -0
- package/blueprints/security-auth-oauth2/docs/topics.md +1 -2
- package/blueprints/security-secrets-management/CHANGELOG.md +15 -4
- package/blueprints/security-secrets-management/README.md +2 -2
- package/blueprints/security-secrets-management/blueprint.json +3 -2
- package/blueprints/security-secrets-management/contributions/probes/add-recipient-rotation.mjs +107 -0
- package/blueprints/security-secrets-management/contributions/probes/encrypt-decrypt-round-trip.mjs +122 -0
- package/blueprints/security-secrets-management/contributions/probes/key-rotation.mjs +93 -0
- package/blueprints/security-secrets-management/contributions/probes/mismatched-key-refusal.mjs +74 -0
- package/blueprints/security-secrets-management/contributions/probes/probe-utils.mjs +214 -0
- package/blueprints/security-secrets-management/contributions/probes/run-add-recipient-rotation.mjs +4 -0
- package/blueprints/security-secrets-management/contributions/probes/run-encrypt-decrypt-round-trip.mjs +4 -0
- package/blueprints/security-secrets-management/contributions/probes/run-key-rotation.mjs +4 -0
- package/blueprints/security-secrets-management/contributions/probes/run-mismatched-key-refusal.mjs +4 -0
- package/blueprints/security-secrets-management/docs/topics.md +2 -3
- package/fixtures/canary-manifest.json +9 -9
- package/guidance/harness-template.md +25 -0
- package/guidance/managed/agent-instructions-block.hash +1 -1
- package/guidance/managed/agent-instructions-block.md +25 -0
- package/package.json +2 -2
- package/rcf/adrs/adr-4101-feedback-store-gitignored.json +20 -0
- package/rcf/adrs/adr-4102-fingerprint-and-labels.json +25 -0
- package/rcf/adrs/adr-4103-redaction-rule-based.json +20 -0
- package/rcf/adrs/adr-4104-destination-on-library.json +25 -0
- package/rcf/adrs/adr-4105-gh-ambient-auth.json +20 -0
- package/rcf/adrs/adr-4106-bundled-entries-terminal.json +20 -0
- package/rcf/adrs/adr-4107-stop-is-ask-event.json +30 -0
- package/rcf/adrs/adr-4108-hooks-in-committed-config.json +25 -0
- package/rcf/adrs/adr-4109-referee-validate-adr-crosslinks.json +25 -0
- package/rcf/adrs/adr-4110-referee-coverage-strict-by-default.json +25 -0
- package/rcf/adrs/adr-4111-referee-finalise-refusals.json +20 -0
- package/rcf/adrs/adr-4112-referee-finalise-verified-invariant.json +30 -0
- package/rcf/code-nodes/cn-600.json +45 -0
- package/rcf/code-nodes/cn-601.json +18 -0
- package/rcf/code-nodes/cn-602.json +15 -0
- package/rcf/code-nodes/cn-603.json +12 -0
- package/rcf/code-nodes/cn-604.json +14 -0
- package/rcf/code-nodes/cn-605.json +17 -0
- package/rcf/code-nodes/cn-606.json +12 -0
- package/rcf/code-nodes/cn-607.json +12 -0
- package/rcf/code-nodes/cn-608.json +14 -0
- package/rcf/code-nodes/cn-609.json +17 -0
- package/rcf/code-nodes/cn-620.json +18 -0
- package/rcf/code-nodes/cn-621.json +14 -0
- package/rcf/code-nodes/cn-622.json +15 -0
- package/rcf/code-nodes/cn-623.json +16 -0
- package/rcf/code-nodes/cn-624.json +14 -0
- package/rcf/code-nodes/cn-625.json +15 -0
- package/rcf/code-nodes/cn-626.json +13 -0
- package/rcf/code-nodes/cn-627.json +13 -0
- package/rcf/code-nodes/cn-628.json +14 -0
- package/rcf/code-nodes/cn-629.json +12 -0
- package/rcf/code-nodes/cn-630.json +12 -0
- package/rcf/code-nodes/cn-631.json +13 -0
- package/rcf/code-nodes/cn-632.json +13 -0
- package/rcf/fbs/fbs-180.json +45 -0
- package/rcf/fbs/fbs-181.json +45 -0
- package/rcf/fbs/fbs-182.json +42 -0
- package/rcf/fbs/fbs-183.json +50 -0
- package/rcf/fbs/fbs-184.json +49 -0
- package/rcf/fbs/fbs-185.json +34 -0
- package/rcf/fbs/fbs-186.json +16 -0
- package/rcf/fbs/fbs-187.json +17 -0
- package/rcf/fbs/fbs-188.json +17 -0
- package/rcf/fbs/fbs-189.json +17 -0
- package/rcf/requirements/req-155.json +13 -0
- package/rcf/requirements/req-156.json +13 -0
- package/rcf/requirements/req-157.json +13 -0
- package/rcf/requirements/req-158.json +13 -0
- package/rcf/requirements/req-159.json +13 -0
- package/rcf/requirements/req-160.json +13 -0
- package/rcf/requirements/req-161.json +13 -0
- package/rcf/requirements/req-162.json +13 -0
- package/rcf/requirements/req-163.json +13 -0
- package/rcf/requirements/req-164.json +13 -0
- package/rcf/requirements/req-165.json +13 -0
- package/rcf/tacs/tac-4101-feedback-cli.json +77 -0
- package/rcf/tacs/tac-4102-feedback-store.json +50 -0
- package/rcf/tacs/tac-4103-feedback-redact.json +39 -0
- package/rcf/tacs/tac-4104-feedback-fingerprint.json +33 -0
- package/rcf/tacs/tac-4105-feedback-render.json +45 -0
- package/rcf/tacs/tac-4106-feedback-destination.json +39 -0
- package/rcf/tacs/tac-4107-feedback-gh.json +43 -0
- package/rcf/tacs/tac-4108-feedback-hook.json +46 -0
- package/rcf/tacs/tac-4109-referee-validate-adr-crosslinks.json +20 -0
- package/rcf/tacs/tac-4110-referee-coverage-mode-selector.json +21 -0
- package/rcf/tacs/tac-4111-referee-finalise-per-ac-refusals.json +21 -0
- package/rcf/tacs/tac-4112-referee-finalise-verified-invariant.json +22 -0
- package/rcf/test-suites/ts-140.json +9 -9
- package/rcf/test-suites/ts-150.json +9 -9
- package/rcf/test-suites/ts-185.json +54 -0
- package/rcf/test-suites/ts-186.json +58 -0
- package/rcf/test-suites/ts-187.json +44 -0
- package/rcf/test-suites/ts-188.json +166 -0
- package/rcf/test-suites/ts-189.json +38 -0
- package/rcf/test-suites/ts-190.json +30 -0
- package/rcf/test-suites/ts-191.json +51 -0
- package/rcf/test-suites/ts-192.json +37 -0
- package/rcf/test-suites/ts-193.json +60 -0
- package/rcf/test-suites/ts-194.json +67 -0
- package/rcf/test-suites/ts-195.json +52 -0
- package/rcf/test-suites/ts-196.json +58 -0
- package/rcf/test-suites/ts-197.json +66 -0
- package/rcf/test-suites/ts-198.json +87 -0
- package/rcf/test-suites/ts-199.json +51 -0
- package/rcf/test-suites/ts-200.json +30 -0
- package/rcf/test-suites/ts-201.json +38 -0
- package/rcf/test-suites/ts-202.json +38 -0
- package/rcf/test-suites/ts-203.json +38 -0
- package/rcf/user-stories/us-15501.json +60 -0
- package/rcf/user-stories/us-15502.json +33 -0
- package/rcf/user-stories/us-15503.json +33 -0
- package/rcf/user-stories/us-15601.json +51 -0
- package/rcf/user-stories/us-15701.json +42 -0
- package/rcf/user-stories/us-15801.json +42 -0
- package/rcf/user-stories/us-15802.json +33 -0
- package/rcf/user-stories/us-15901.json +33 -0
- package/rcf/user-stories/us-15902.json +51 -0
- package/rcf/user-stories/us-16001.json +51 -0
- package/rcf/user-stories/us-16101.json +42 -0
- package/rcf/user-stories/us-16102.json +33 -0
- package/rcf/user-stories/us-16103.json +42 -0
- package/rcf/user-stories/us-16104.json +42 -0
- package/rcf/user-stories/us-16201.json +33 -0
- package/rcf/user-stories/us-16301.json +36 -0
- package/rcf/user-stories/us-16401.json +45 -0
- package/rcf/user-stories/us-16501.json +45 -0
- package/rcf/user-stories/us-16502.json +45 -0
- package/releases/releases.yaml +11 -1
- package/src/blueprint/library-loader.js +48 -0
- package/src/blueprint/library-registry.js +13 -0
- package/src/browser-verify/pack-runner.js +7 -12
- package/src/build/mark.js +1 -1
- package/src/cli/blueprint-library.js +149 -0
- package/src/cli/coverage.js +49 -24
- package/src/cli/doctor.js +195 -7
- package/src/cli/feedback.js +2204 -0
- package/src/cli/finalise.js +158 -1
- package/src/cli/help.js +6 -0
- package/src/cli/init.js +63 -0
- package/src/cli/update.js +21 -1
- package/src/core/store/walker.js +33 -0
- package/src/core/store/writer.js +23 -0
- package/src/feedback/destination.js +361 -0
- package/src/feedback/fingerprint.js +132 -0
- package/src/feedback/gh.js +376 -0
- package/src/feedback/hook.js +183 -0
- package/src/feedback/labels.js +87 -0
- package/src/feedback/redact-allowlist.json +14 -0
- package/src/feedback/redact.js +1108 -0
- package/src/feedback/render.js +267 -0
- package/src/feedback/store.js +604 -0
- package/src/finalise/index.js +4 -0
- package/src/finalise/ingest.js +61 -0
- package/src/finalise/ship-without-eval.js +19 -7
- package/src/mcp/tools.js +8 -2
- package/src/setup/feedback-hooks.js +397 -0
- package/src/setup/managed-gitignore.js +3 -0
- package/src/view/html-page.js +5 -5
- package/src/view/style.css +2 -2
|
@@ -266,6 +266,12 @@ async function handleAdd({ args, parsed, projectRoot, now, stdout, stderr, stdin
|
|
|
266
266
|
reviewedBy: 'operator',
|
|
267
267
|
provenance,
|
|
268
268
|
cachePath: sourceKind === 'local' ? libraryRoot : cachePathRel,
|
|
269
|
+
// Feedback destination snapshot (design 3.3, AC-15801-1). Snapshotted
|
|
270
|
+
// so the resolver never re-reads the library's own library.json on
|
|
271
|
+
// every preview / submit; `library refresh` re-snapshots when the
|
|
272
|
+
// library owner changes the field.
|
|
273
|
+
...(library.issues?.repo ? { issuesRepo: library.issues.repo } : {}),
|
|
274
|
+
...(library.issues?.visibility ? { issuesVisibility: library.issues.visibility } : {}),
|
|
269
275
|
};
|
|
270
276
|
|
|
271
277
|
const nextRegistry = {
|
|
@@ -565,6 +571,11 @@ async function handleRefresh({ args, parsed, projectRoot, stdout, stderr }) {
|
|
|
565
571
|
return 2;
|
|
566
572
|
}
|
|
567
573
|
const libraryPrefix = args[0];
|
|
574
|
+
// F-slice-3-02 regression fix: honour --dry-run on refresh. The
|
|
575
|
+
// re-snapshot writes below (local / git / tarball) previously ran
|
|
576
|
+
// unconditionally, so a dry-run mutated the registry even though
|
|
577
|
+
// the flag is documented as "print intended writes without executing".
|
|
578
|
+
const dryRun = parsed.values['dry-run'] === true;
|
|
568
579
|
const registry = await readLibraryRegistry(projectRoot);
|
|
569
580
|
if (isRcfError(registry)) {
|
|
570
581
|
stderr.write(`[error] blueprint library refresh: ${registry.message}\n`);
|
|
@@ -588,8 +599,22 @@ async function handleRefresh({ args, parsed, projectRoot, stdout, stderr }) {
|
|
|
588
599
|
stderr.write("re-run 'rcf define blueprint library add <ref>' to pick up the newer library (spec §10.1: freshness is advisory, adoption is an operator act).\n");
|
|
589
600
|
return 3;
|
|
590
601
|
}
|
|
602
|
+
// F-slice-3-02: re-snapshot the issues field so a library owner's
|
|
603
|
+
// later change to issues.repo / issues.visibility reaches
|
|
604
|
+
// consumers on refresh, without a re-add.
|
|
605
|
+
const snap = refreshRegistryIssues(registry, libraryPrefix, library);
|
|
606
|
+
if (snap.changed && !dryRun) {
|
|
607
|
+
const write = await writeLibraryRegistry(projectRoot, snap.registry, {});
|
|
608
|
+
if (isRcfError(write)) {
|
|
609
|
+
stderr.write(`[error] blueprint library refresh: ${write.message}\n`);
|
|
610
|
+
return 2;
|
|
611
|
+
}
|
|
612
|
+
}
|
|
591
613
|
if (!parsed.values.quiet) {
|
|
592
614
|
stdout.write(`[blueprint library] '${libraryPrefix}' refresh clean: on-disk library matches the registry snapshot.\n`);
|
|
615
|
+
if (snap.changed) {
|
|
616
|
+
stdout.write(`[blueprint library] '${libraryPrefix}' feedback destination ${dryRun ? 'would be re-snapshotted (dry-run)' : 're-snapshotted'}: ${describeIssuesTransition(snap.from, snap.to)}.\n`);
|
|
617
|
+
}
|
|
593
618
|
}
|
|
594
619
|
return 0;
|
|
595
620
|
}
|
|
@@ -643,8 +668,26 @@ async function handleRefresh({ args, parsed, projectRoot, stdout, stderr }) {
|
|
|
643
668
|
const finalAbs = resolveCachePath(projectRoot, entry.cachePath);
|
|
644
669
|
const settleErr = await settleFinal(scratchAbs, finalAbs);
|
|
645
670
|
if (settleErr) { stderr.write(`[error] blueprint library refresh: ${settleErr.message}\n`); return 2; }
|
|
671
|
+
// F-slice-3-02: re-snapshot the issues field on the registered
|
|
672
|
+
// entry now that the on-disk library has landed.
|
|
673
|
+
const registryReload = await readLibraryRegistry(projectRoot);
|
|
674
|
+
if (isRcfError(registryReload)) {
|
|
675
|
+
stderr.write(`[error] blueprint library refresh: ${registryReload.message}\n`);
|
|
676
|
+
return 2;
|
|
677
|
+
}
|
|
678
|
+
const snap = refreshRegistryIssues(registryReload, libraryPrefix, library);
|
|
679
|
+
if (snap.changed && !dryRun) {
|
|
680
|
+
const write = await writeLibraryRegistry(projectRoot, snap.registry, {});
|
|
681
|
+
if (isRcfError(write)) {
|
|
682
|
+
stderr.write(`[error] blueprint library refresh: ${write.message}\n`);
|
|
683
|
+
return 2;
|
|
684
|
+
}
|
|
685
|
+
}
|
|
646
686
|
if (!parsed.values.quiet) {
|
|
647
687
|
stdout.write(`[blueprint library] '${libraryPrefix}' refresh clean: git ref '${parsedGit.ref}' still resolves to ${upstream.resolvedSha.slice(0, 12)}.\n`);
|
|
688
|
+
if (snap.changed) {
|
|
689
|
+
stdout.write(`[blueprint library] '${libraryPrefix}' feedback destination ${dryRun ? 'would be re-snapshotted (dry-run)' : 're-snapshotted'}: ${describeIssuesTransition(snap.from, snap.to)}.\n`);
|
|
690
|
+
}
|
|
648
691
|
}
|
|
649
692
|
return 0;
|
|
650
693
|
}
|
|
@@ -681,8 +724,26 @@ async function handleRefresh({ args, parsed, projectRoot, stdout, stderr }) {
|
|
|
681
724
|
const finalAbs = resolveCachePath(projectRoot, entry.cachePath);
|
|
682
725
|
const settleErr = await settleFinal(scratchAbs, finalAbs);
|
|
683
726
|
if (settleErr) { stderr.write(`[error] blueprint library refresh: ${settleErr.message}\n`); return 2; }
|
|
727
|
+
// F-slice-3-02: re-snapshot the issues field on the registered
|
|
728
|
+
// entry now that the on-disk library has landed.
|
|
729
|
+
const registryReload = await readLibraryRegistry(projectRoot);
|
|
730
|
+
if (isRcfError(registryReload)) {
|
|
731
|
+
stderr.write(`[error] blueprint library refresh: ${registryReload.message}\n`);
|
|
732
|
+
return 2;
|
|
733
|
+
}
|
|
734
|
+
const snap = refreshRegistryIssues(registryReload, libraryPrefix, library);
|
|
735
|
+
if (snap.changed && !dryRun) {
|
|
736
|
+
const write = await writeLibraryRegistry(projectRoot, snap.registry, {});
|
|
737
|
+
if (isRcfError(write)) {
|
|
738
|
+
stderr.write(`[error] blueprint library refresh: ${write.message}\n`);
|
|
739
|
+
return 2;
|
|
740
|
+
}
|
|
741
|
+
}
|
|
684
742
|
if (!parsed.values.quiet) {
|
|
685
743
|
stdout.write(`[blueprint library] '${libraryPrefix}' refresh clean: tarball SHA-256 still matches ${expected.slice(0, 12)}.\n`);
|
|
744
|
+
if (snap.changed) {
|
|
745
|
+
stdout.write(`[blueprint library] '${libraryPrefix}' feedback destination ${dryRun ? 'would be re-snapshotted (dry-run)' : 're-snapshotted'}: ${describeIssuesTransition(snap.from, snap.to)}.\n`);
|
|
746
|
+
}
|
|
686
747
|
}
|
|
687
748
|
return 0;
|
|
688
749
|
}
|
|
@@ -698,6 +759,86 @@ function compareLibrarySnapshot(entry, library) {
|
|
|
698
759
|
return drifted;
|
|
699
760
|
}
|
|
700
761
|
|
|
762
|
+
/**
|
|
763
|
+
* F-slice-3-02: re-snapshot the library's `issues` field onto the
|
|
764
|
+
* registry entry. Design 3.3 says `library refresh` re-snapshots the
|
|
765
|
+
* feedback destination so a library owner's later change to
|
|
766
|
+
* `issues.repo` or `issues.visibility` reaches consumers without a
|
|
767
|
+
* re-add. Returns `{ changed, next, from, to }` where `next` is the
|
|
768
|
+
* merged entry to write; `changed` is true when the on-disk library
|
|
769
|
+
* carries a different repo or visibility from the registered snapshot
|
|
770
|
+
* (including the case where the entry never had the fields).
|
|
771
|
+
*
|
|
772
|
+
* @param {object} entry
|
|
773
|
+
* @param {object} library
|
|
774
|
+
* @returns {{ changed: boolean, next: object, from: object, to: object }}
|
|
775
|
+
*/
|
|
776
|
+
export function reSnapshotIssues(entry, library) {
|
|
777
|
+
const nextRepo = typeof library?.issues?.repo === 'string' && library.issues.repo.length > 0
|
|
778
|
+
? library.issues.repo
|
|
779
|
+
: undefined;
|
|
780
|
+
const nextVisibility = library?.issues?.visibility === 'private' ? 'private'
|
|
781
|
+
: library?.issues?.visibility === 'public' ? 'public'
|
|
782
|
+
: undefined;
|
|
783
|
+
const from = {
|
|
784
|
+
issuesRepo: entry.issuesRepo,
|
|
785
|
+
issuesVisibility: entry.issuesVisibility,
|
|
786
|
+
};
|
|
787
|
+
const to = { issuesRepo: nextRepo, issuesVisibility: nextVisibility };
|
|
788
|
+
const changed = from.issuesRepo !== to.issuesRepo || from.issuesVisibility !== to.issuesVisibility;
|
|
789
|
+
const next = { ...entry };
|
|
790
|
+
if (nextRepo === undefined) delete next.issuesRepo;
|
|
791
|
+
else next.issuesRepo = nextRepo;
|
|
792
|
+
if (nextVisibility === undefined) delete next.issuesVisibility;
|
|
793
|
+
else next.issuesVisibility = nextVisibility;
|
|
794
|
+
return { changed, next, from, to };
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
/**
|
|
798
|
+
* Apply reSnapshotIssues across a registry: given the current registry
|
|
799
|
+
* and the freshly-loaded library, return the registry object with the
|
|
800
|
+
* matched entry replaced by the re-snapshotted one. Callers write the
|
|
801
|
+
* returned registry back through `writeLibraryRegistry`.
|
|
802
|
+
*
|
|
803
|
+
* @param {object} registry
|
|
804
|
+
* @param {string} libraryPrefix
|
|
805
|
+
* @param {object} library
|
|
806
|
+
* @returns {{ registry: object, changed: boolean, from: object, to: object }}
|
|
807
|
+
*/
|
|
808
|
+
function describeIssuesTransition(from, to) {
|
|
809
|
+
const fromRepo = from.issuesRepo ?? '(none)';
|
|
810
|
+
const toRepo = to.issuesRepo ?? '(none)';
|
|
811
|
+
const fromVis = from.issuesVisibility ?? '-';
|
|
812
|
+
const toVis = to.issuesVisibility ?? '-';
|
|
813
|
+
return `${fromRepo} (${fromVis}) -> ${toRepo} (${toVis})`;
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
function refreshRegistryIssues(registry, libraryPrefix, library) {
|
|
817
|
+
const nextLibs = [];
|
|
818
|
+
let changed = false;
|
|
819
|
+
let from = { issuesRepo: undefined, issuesVisibility: undefined };
|
|
820
|
+
let to = from;
|
|
821
|
+
for (const l of registry.libraries) {
|
|
822
|
+
if (l.libraryPrefix !== libraryPrefix) {
|
|
823
|
+
nextLibs.push(l);
|
|
824
|
+
continue;
|
|
825
|
+
}
|
|
826
|
+
const snap = reSnapshotIssues(l, library);
|
|
827
|
+
if (snap.changed) {
|
|
828
|
+
changed = true;
|
|
829
|
+
from = snap.from;
|
|
830
|
+
to = snap.to;
|
|
831
|
+
}
|
|
832
|
+
nextLibs.push(snap.next);
|
|
833
|
+
}
|
|
834
|
+
return {
|
|
835
|
+
registry: { ...registry, libraries: nextLibs },
|
|
836
|
+
changed,
|
|
837
|
+
from,
|
|
838
|
+
to,
|
|
839
|
+
};
|
|
840
|
+
}
|
|
841
|
+
|
|
701
842
|
function classifySourceRef(ref) {
|
|
702
843
|
// Tarball extension wins over the transport check because `https://.../foo.tar.gz`
|
|
703
844
|
// is a valid tarball ref and would otherwise be misclassified as git.
|
|
@@ -750,6 +891,14 @@ function printReview({ stdout, ref, library, libraryPrefix, coreReservations, so
|
|
|
750
891
|
stdout.write(`\n Provenance : ${sourceKind}${sourceKind === 'local' ? ' (dev use)' : ''}\n`);
|
|
751
892
|
stdout.write(` Band check : cross-checked ${coreReservations.ac.length} core AC row(s), ${coreReservations.suffixBlocks.length} core suffix block(s); no overlap.\n`);
|
|
752
893
|
stdout.write(` Prefix check : '${libraryPrefix}' does not collide with any core slug.\n`);
|
|
894
|
+
// Feedback destination line (design 3.3, AC-15801-1). Prints only
|
|
895
|
+
// when the library declares an `issues` field; a library without one
|
|
896
|
+
// is surfaced by `rcf doctor feedback-destinations` on the consuming
|
|
897
|
+
// project rather than by a review-card warning here.
|
|
898
|
+
if (library.issues?.repo) {
|
|
899
|
+
const vis = library.issues.visibility === 'private' ? 'private' : 'public';
|
|
900
|
+
stdout.write(` Feedback destination: ${library.issues.repo} (${vis})\n`);
|
|
901
|
+
}
|
|
753
902
|
stdout.write(`\n`);
|
|
754
903
|
}
|
|
755
904
|
|
package/src/cli/coverage.js
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
// `rcf coverage` subcommand handler. Reports structural coverage over
|
|
2
2
|
// the REQ chain (PRD -> REQ -> US -> AC -> TS -> TC). Phase 5 §D2 / §D10.
|
|
3
3
|
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
// the
|
|
4
|
+
// Referee-guarantees train (REQ-164 / US-16401, docs claims C-11 /
|
|
5
|
+
// C-14): strict-by-default. The default mode is per-AC-strict; a
|
|
6
|
+
// stub or stale pointer fails the gate exactly as a missing test does
|
|
7
|
+
// when the plain `rcf audit coverage` command is run. The explicit
|
|
8
|
+
// opt-out is `--mode shallow-any` (any AC covered by any resolving
|
|
9
|
+
// TC = REQ covered), which prints the gaps and exits 0 as before. The
|
|
10
|
+
// legacy `--strict` flag remains a no-op alias for the new default so
|
|
11
|
+
// existing CI invocations, blueprints and dogfood scripts stay green;
|
|
12
|
+
// `--mode shallow-any --strict` (or the inverse) is a usage refusal.
|
|
8
13
|
//
|
|
9
14
|
// Phase-boundary reminder (§D2, §1.4): this verb is a MECHANICAL /
|
|
10
15
|
// DETERMINISTIC structural check. It does NOT answer "does the AC
|
|
@@ -32,24 +37,29 @@ import {
|
|
|
32
37
|
|
|
33
38
|
const OPTION_SPEC = {
|
|
34
39
|
strict: { type: 'boolean' },
|
|
40
|
+
// Referee-guarantee train (REQ-164 / US-16401): explicit --mode
|
|
41
|
+
// selector. Values: strict | shallow-any. Default: strict.
|
|
42
|
+
mode: { type: 'string' },
|
|
35
43
|
format: { type: 'string' },
|
|
36
44
|
help: { type: 'boolean' },
|
|
37
45
|
// Phase 10 (X2 CodeNode bridge, D11): layer the code axis onto coverage.
|
|
38
46
|
'with-code': { type: 'boolean' },
|
|
39
|
-
// 0.7.0 verification-integrity: opt-in extra gate on
|
|
47
|
+
// 0.7.0 verification-integrity: opt-in extra gate on strict mode that
|
|
40
48
|
// refuses any TS still `draft` after Stage 4 (spec §7.2).
|
|
41
49
|
'require-approved': { type: 'boolean' },
|
|
42
50
|
};
|
|
43
51
|
|
|
52
|
+
const VALID_MODES = new Set(['strict', 'shallow-any']);
|
|
53
|
+
|
|
44
54
|
export const HELP = `Usage: rcf audit coverage [scope-id] [options]
|
|
45
55
|
|
|
46
56
|
Report structural coverage over the REQ chain (PRD -> REQ -> US -> AC
|
|
47
57
|
-> TS -> TC). A TC counts as covering its AC only when its testPointer
|
|
48
58
|
(filePath::testName) resolves to a real test in the working tree; a TC
|
|
49
59
|
whose pointer does not resolve is reported as covered-unresolved, never
|
|
50
|
-
counted as coverage.
|
|
51
|
-
|
|
52
|
-
|
|
60
|
+
counted as coverage. Strict-by-default (per-AC: every AC has resolving
|
|
61
|
+
TC coverage); --mode shallow-any is the explicit opt-out (any AC
|
|
62
|
+
covered by any resolving TC = REQ covered) and always exits 0.
|
|
53
63
|
|
|
54
64
|
This is a mechanical / deterministic structural check. It does NOT
|
|
55
65
|
answer 'does the AC set adequately capture the REQ's intent?' - that
|
|
@@ -63,14 +73,16 @@ Positional:
|
|
|
63
73
|
TAD) are refused with exit 2.
|
|
64
74
|
|
|
65
75
|
Options:
|
|
66
|
-
--
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
76
|
+
--mode <mode> strict (default) | shallow-any. Strict is
|
|
77
|
+
per-AC and exits 4 on any gap; shallow-any
|
|
78
|
+
prints gaps and exits 0.
|
|
79
|
+
--strict Legacy alias for --mode strict; kept for
|
|
80
|
+
backward compatibility with existing CI,
|
|
81
|
+
blueprints and dogfood invocations. A no-op
|
|
82
|
+
under the new default; conflict with an
|
|
83
|
+
explicit --mode shallow-any exits 2.
|
|
84
|
+
--require-approved Extra strict-mode gate: refuse any TS still
|
|
85
|
+
at authoringStatus 'draft' after Stage 4
|
|
74
86
|
(verification-integrity 0.7.0 §7.2). Off
|
|
75
87
|
by default; opt-in via CI.
|
|
76
88
|
--with-code Layer the code axis onto every AC: one of
|
|
@@ -117,6 +129,19 @@ export async function main(argv, deps = {}) {
|
|
|
117
129
|
stderr.write('[error] usage coverage: multiple positional ids are not supported\n');
|
|
118
130
|
return 2;
|
|
119
131
|
}
|
|
132
|
+
// Referee-guarantee train (REQ-164): resolve strict-vs-shallow.
|
|
133
|
+
// Default is strict. --mode wins if set; --strict is a legacy alias
|
|
134
|
+
// for --mode strict; --mode shallow-any --strict is a usage refusal
|
|
135
|
+
// so a scripted invocation cannot silently disagree with itself.
|
|
136
|
+
if (flags.mode !== undefined && !VALID_MODES.has(flags.mode)) {
|
|
137
|
+
stderr.write(`[error] usage coverage: unknown --mode ${flags.mode} (expected strict | shallow-any)\n`);
|
|
138
|
+
return 2;
|
|
139
|
+
}
|
|
140
|
+
if (flags.mode === 'shallow-any' && flags.strict === true) {
|
|
141
|
+
stderr.write('[error] usage coverage: --mode shallow-any conflicts with --strict; pick one\n');
|
|
142
|
+
return 2;
|
|
143
|
+
}
|
|
144
|
+
const strict = flags.mode === 'shallow-any' ? false : true;
|
|
120
145
|
|
|
121
146
|
const projectRoot = await findProjectRoot(cwd);
|
|
122
147
|
if (!projectRoot) {
|
|
@@ -156,7 +181,7 @@ export async function main(argv, deps = {}) {
|
|
|
156
181
|
// and a TC that fails resolution surfaces as covered-unresolved.
|
|
157
182
|
const testPointers = await resolveTestPointers({ projectRoot, tree });
|
|
158
183
|
const result = computeCoverage(tree, {
|
|
159
|
-
strict
|
|
184
|
+
strict, scopeId, withCode: Boolean(flags['with-code']), testPointers,
|
|
160
185
|
});
|
|
161
186
|
|
|
162
187
|
let output;
|
|
@@ -165,16 +190,16 @@ export async function main(argv, deps = {}) {
|
|
|
165
190
|
else output = formatTable(result, 'coverage');
|
|
166
191
|
stdout.write(output);
|
|
167
192
|
|
|
168
|
-
//
|
|
169
|
-
if (
|
|
193
|
+
// Strict mode on any gap = exit 4 (CI-gate friendly). Otherwise 0.
|
|
194
|
+
if (strict && !result.ok) return 4;
|
|
170
195
|
|
|
171
|
-
// 0.7.0 verification-integrity extension:
|
|
196
|
+
// 0.7.0 verification-integrity extension: strict mode also runs the
|
|
172
197
|
// attestation × profile matrix (spec §5.2). Three refusal classes:
|
|
173
198
|
// (1) attestation missing, (2) provenance missing, (3) attestation
|
|
174
199
|
// drift. All are additive — they never turn a passing coverage into
|
|
175
200
|
// a passing --strict run; they only add exit-4 refusals on new
|
|
176
201
|
// failure modes that the matrix now polices.
|
|
177
|
-
if (
|
|
202
|
+
if (strict) {
|
|
178
203
|
// Review N-3 (non-blocking): surface preFlightConfig services with
|
|
179
204
|
// empty affectedFbsIds so the operator knows findAttestationMissing
|
|
180
205
|
// is skipping them on purpose (honest-but-invisible without this
|
|
@@ -182,7 +207,7 @@ export async function main(argv, deps = {}) {
|
|
|
182
207
|
// into a failing one.
|
|
183
208
|
const emptyAffected = findServicesWithEmptyAffectedFbsIds(tree);
|
|
184
209
|
for (const s of emptyAffected) {
|
|
185
|
-
stderr.write(`[warn] coverage
|
|
210
|
+
stderr.write(`[warn] coverage strict: preFlightConfig service '${s.serviceId}' (${s.preFlightConfigId}) has empty affectedFbsIds; the attestation-missing detector cannot cross-check it until the back-reference is populated.\n`);
|
|
186
211
|
}
|
|
187
212
|
|
|
188
213
|
const missing = findAttestationMissing(tree);
|
|
@@ -203,14 +228,14 @@ export async function main(argv, deps = {}) {
|
|
|
203
228
|
for (const d of drifts) refusals.push(` - ${d.tsId}/${d.tcId} on ${d.acId} (service ${d.serviceId}): ${d.reason}`);
|
|
204
229
|
}
|
|
205
230
|
if (refusals.length > 0) {
|
|
206
|
-
stderr.write(`[error] coverage
|
|
231
|
+
stderr.write(`[error] coverage strict: refused - the verification-integrity matrix caught the following:\n${refusals.join('\n')}\n`);
|
|
207
232
|
return 4;
|
|
208
233
|
}
|
|
209
234
|
|
|
210
235
|
if (flags['require-approved']) {
|
|
211
236
|
const draftTsIds = (tree.testSuites ?? []).filter((ts) => ts.status !== 'approved').map((ts) => ts.id);
|
|
212
237
|
if (draftTsIds.length > 0) {
|
|
213
|
-
stderr.write(`[error] coverage
|
|
238
|
+
stderr.write(`[error] coverage strict --require-approved: refused - ${draftTsIds.length} test suite(s) still not approved: ${draftTsIds.join(', ')}\n`);
|
|
214
239
|
return 4;
|
|
215
240
|
}
|
|
216
241
|
}
|
package/src/cli/doctor.js
CHANGED
|
@@ -47,6 +47,14 @@ import {
|
|
|
47
47
|
} from '../setup/managed-gitignore.js';
|
|
48
48
|
import { identityProfilePath } from '../setup/identity-seed.js';
|
|
49
49
|
import { knowledgePaths } from '../setup/knowledge-seed.js';
|
|
50
|
+
import { readLibraryRegistry } from '../blueprint/library-registry.js';
|
|
51
|
+
import { listUnresolvedLibraries } from '../feedback/destination.js';
|
|
52
|
+
import {
|
|
53
|
+
diagnoseClaudeFeedbackHooks,
|
|
54
|
+
diagnoseCodexFeedbackHooks,
|
|
55
|
+
writeClaudeFeedbackHooks,
|
|
56
|
+
writeCodexFeedbackHooks,
|
|
57
|
+
} from '../setup/feedback-hooks.js';
|
|
50
58
|
import {
|
|
51
59
|
checkBrowserPresent,
|
|
52
60
|
checkPlaywrightMcpReachable,
|
|
@@ -77,6 +85,8 @@ const KNOWN_CHECKS = /** @type {const} */ ([
|
|
|
77
85
|
'playwright-mcp-reachable',
|
|
78
86
|
'playwright-mcp-redundant',
|
|
79
87
|
'probe-path-owner',
|
|
88
|
+
'feedback-destinations',
|
|
89
|
+
'feedback-hooks',
|
|
80
90
|
]);
|
|
81
91
|
|
|
82
92
|
/** The four Playwright-related checks doctor runs conditionally for
|
|
@@ -103,7 +113,8 @@ Options:
|
|
|
103
113
|
Values: agent-instructions, gitignore,
|
|
104
114
|
knowledge, identity, playwright-present,
|
|
105
115
|
browser-present, playwright-mcp-reachable,
|
|
106
|
-
playwright-mcp-redundant, probe-path-owner
|
|
116
|
+
playwright-mcp-redundant, probe-path-owner,
|
|
117
|
+
feedback-destinations, feedback-hooks.
|
|
107
118
|
--json Emit machine-readable envelope: { ok, drift, writes, notices }.
|
|
108
119
|
--quiet Only summary line + first 3 drift items.
|
|
109
120
|
--force Accept a legacy-markers --fix on hand-edited
|
|
@@ -253,6 +264,21 @@ export async function main(argv, deps = {}) {
|
|
|
253
264
|
// Runs on every project (not gated on browser-facing). Spec:
|
|
254
265
|
// projects/rcf-lite-wsd/specs/rcf-lite-probe-path-alignment-spec-2026-09-04.md section 9.
|
|
255
266
|
result = await runProbePathOwnerCheck(ctx);
|
|
267
|
+
} else if (check === 'feedback-destinations') {
|
|
268
|
+
// Feedback destination coverage across the library registry
|
|
269
|
+
// (design 3.3, AC-15801-3). Warn-only: --fix does not touch
|
|
270
|
+
// destinations. The fix is for the library owner (add the
|
|
271
|
+
// `issues` field to library.json) or the consuming operator
|
|
272
|
+
// (contact the library owner).
|
|
273
|
+
result = await runFeedbackDestinationsCheck(ctx);
|
|
274
|
+
} else if (check === 'feedback-hooks') {
|
|
275
|
+
// Feedback hook install coverage across .claude/settings.json
|
|
276
|
+
// and .codex/hooks.json (ADR-4108, AC-16104-3). Missing
|
|
277
|
+
// entries are fixable; foreign entries (a rcf feedback hook
|
|
278
|
+
// command under our marker but with different flags) are
|
|
279
|
+
// refused and named in the drift row so the operator can
|
|
280
|
+
// repair by hand.
|
|
281
|
+
result = await runFeedbackHooksCheck(ctx);
|
|
256
282
|
} else continue;
|
|
257
283
|
for (const d of result.drift) drift.push({ check, ...d });
|
|
258
284
|
for (const w of result.writes) writes.push(w);
|
|
@@ -262,8 +288,12 @@ export async function main(argv, deps = {}) {
|
|
|
262
288
|
// fixable drift item exits 0 even though drift WAS reported at scan
|
|
263
289
|
// time. Exit 3 only when at least one drift item remains unrepaired
|
|
264
290
|
// (either --fix was not passed, or the item was refused by --fix).
|
|
265
|
-
|
|
266
|
-
|
|
291
|
+
// Rows flagged `warnOnly: true` are surfaced in output but never
|
|
292
|
+
// ratchet the exit code up (design 3.3 feedback-destinations); they
|
|
293
|
+
// still appear in --json for tooling.
|
|
294
|
+
const gatingDrift = drift.filter((d) => d.warnOnly !== true);
|
|
295
|
+
const refusedCount = gatingDrift.filter((d) => d.refusedByFix).length;
|
|
296
|
+
const unrepairedCount = ctx.fix ? refusedCount : gatingDrift.length;
|
|
267
297
|
const ok = unrepairedCount === 0;
|
|
268
298
|
const exitCode = ok ? 0 : 3;
|
|
269
299
|
|
|
@@ -284,10 +314,21 @@ export async function main(argv, deps = {}) {
|
|
|
284
314
|
/** Render a human-readable summary. */
|
|
285
315
|
function writeHumanSummary({ stdout, ok, drift, writes, fixed, quiet }) {
|
|
286
316
|
const repaired = writes.length;
|
|
287
|
-
|
|
317
|
+
const warnOnlyRows = drift.filter((d) => d.warnOnly === true);
|
|
318
|
+
const gatingRows = drift.filter((d) => d.warnOnly !== true);
|
|
319
|
+
if (ok && repaired === 0 && warnOnlyRows.length === 0) {
|
|
288
320
|
stdout.write('rcf doctor: clean.\n');
|
|
289
321
|
return;
|
|
290
322
|
}
|
|
323
|
+
if (ok && repaired === 0 && warnOnlyRows.length > 0) {
|
|
324
|
+
stdout.write(`rcf doctor: clean (${warnOnlyRows.length} warning${warnOnlyRows.length === 1 ? '' : 's'}).\n`);
|
|
325
|
+
const limit = quiet ? 3 : warnOnlyRows.length;
|
|
326
|
+
for (const d of warnOnlyRows.slice(0, limit)) {
|
|
327
|
+
stdout.write(` [${d.check}] ${d.item} ${d.file} [warn]\n`);
|
|
328
|
+
if (!quiet) stdout.write(` ${d.message}\n`);
|
|
329
|
+
}
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
291
332
|
if (ok && repaired > 0) {
|
|
292
333
|
// Every drift item was repaired successfully. Report the repair
|
|
293
334
|
// count so the operator sees what the run did.
|
|
@@ -295,13 +336,14 @@ function writeHumanSummary({ stdout, ok, drift, writes, fixed, quiet }) {
|
|
|
295
336
|
for (const w of writes) stdout.write(` fixed: ${w.file} (${w.action}).\n`);
|
|
296
337
|
return;
|
|
297
338
|
}
|
|
298
|
-
const refused =
|
|
299
|
-
stdout.write(`rcf doctor: ${
|
|
339
|
+
const refused = gatingRows.filter((d) => d.refusedByFix);
|
|
340
|
+
stdout.write(`rcf doctor: ${gatingRows.length} drift item${gatingRows.length === 1 ? '' : 's'}`);
|
|
341
|
+
if (warnOnlyRows.length > 0) stdout.write(`, ${warnOnlyRows.length} warning${warnOnlyRows.length === 1 ? '' : 's'}`);
|
|
300
342
|
if (fixed) stdout.write(` (${repaired} repaired, ${refused.length} refused)`);
|
|
301
343
|
stdout.write('.\n');
|
|
302
344
|
const limit = quiet ? 3 : drift.length;
|
|
303
345
|
for (const d of drift.slice(0, limit)) {
|
|
304
|
-
const tag = d.refusedByFix ? ' [refused]' : '';
|
|
346
|
+
const tag = d.warnOnly ? ' [warn]' : d.refusedByFix ? ' [refused]' : '';
|
|
305
347
|
stdout.write(` [${d.check}] ${d.item} ${d.file}${tag}\n`);
|
|
306
348
|
if (!quiet) stdout.write(` ${d.message}\n`);
|
|
307
349
|
}
|
|
@@ -780,6 +822,152 @@ async function runProbePathOwnerCheck(ctx) {
|
|
|
780
822
|
}
|
|
781
823
|
|
|
782
824
|
|
|
825
|
+
/* ------------------------------------------------------------------ */
|
|
826
|
+
/* Check: feedback-destinations */
|
|
827
|
+
/* ------------------------------------------------------------------ */
|
|
828
|
+
|
|
829
|
+
/**
|
|
830
|
+
* List every registered library whose feedback destination the resolver
|
|
831
|
+
* cannot produce (no `issues.repo` on the library manifest and no
|
|
832
|
+
* derivable github source on the registered `sourceRef`). Warn-only:
|
|
833
|
+
* --fix does not touch destinations; the fix is on the library owner
|
|
834
|
+
* to publish an updated library with `issues` or on the consuming
|
|
835
|
+
* operator to contact them.
|
|
836
|
+
*
|
|
837
|
+
* A project that has never added a library returns no drift (the empty
|
|
838
|
+
* registry is not itself a defect). An unparseable registry surfaces as
|
|
839
|
+
* one refused drift row so a broken projection is not silently ignored.
|
|
840
|
+
*
|
|
841
|
+
* @param {object} ctx
|
|
842
|
+
* @returns {Promise<{ drift: Array<{item: string, file: string, message: string, refusedByFix: boolean}>, writes: Array<{file: string, action: string}> }>}
|
|
843
|
+
*/
|
|
844
|
+
async function runFeedbackDestinationsCheck(ctx) {
|
|
845
|
+
const drift = [];
|
|
846
|
+
const registry = await readLibraryRegistry(ctx.projectRoot);
|
|
847
|
+
if (registry && typeof registry === 'object' && 'kind' in registry) {
|
|
848
|
+
// rcfError: the registry file is present but unparseable. Report
|
|
849
|
+
// as one refused row so doctor never claims clean on a broken file.
|
|
850
|
+
drift.push({
|
|
851
|
+
item: 'registry-unreadable',
|
|
852
|
+
file: 'rcf/blueprint-libraries.json',
|
|
853
|
+
message: `library registry could not be read: ${registry.message}. Repair the file by hand or re-run 'rcf define blueprint library add' to rebuild the entry.`,
|
|
854
|
+
refusedByFix: true,
|
|
855
|
+
});
|
|
856
|
+
return { drift, writes: [] };
|
|
857
|
+
}
|
|
858
|
+
const unresolved = listUnresolvedLibraries(registry);
|
|
859
|
+
for (const row of unresolved) {
|
|
860
|
+
const contactSuffix = row.publisherContact ? ` Contact: ${row.publisherContact}.` : '';
|
|
861
|
+
const reasonSummary = row.reason === 'no-issues-field'
|
|
862
|
+
? 'the library declares no issues field on library.json'
|
|
863
|
+
: 'the registered sourceRef is not a github.com URL the resolver can derive from';
|
|
864
|
+
drift.push({
|
|
865
|
+
item: 'unresolved-library',
|
|
866
|
+
file: 'rcf/blueprint-libraries.json',
|
|
867
|
+
message: `library '${row.libraryPrefix}' has no resolvable feedback destination: ${reasonSummary}. Feedback entries on its blueprints route to a bundle at .rcf/feedback/outbox/ instead of a github issue.${contactSuffix} Fix in the library's own library.json (add an issues object per design 3.3); doctor --fix cannot repair this.`,
|
|
868
|
+
refusedByFix: true,
|
|
869
|
+
warnOnly: true,
|
|
870
|
+
});
|
|
871
|
+
}
|
|
872
|
+
return { drift, writes: [] };
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
|
|
876
|
+
/* ------------------------------------------------------------------ */
|
|
877
|
+
/* Check: feedback-hooks */
|
|
878
|
+
/* ------------------------------------------------------------------ */
|
|
879
|
+
|
|
880
|
+
/**
|
|
881
|
+
* Diagnose both harness config files and report:
|
|
882
|
+
* - missing-hook (per event per file): fixable with --fix; the
|
|
883
|
+
* installer merges the entry in without touching neighbours;
|
|
884
|
+
* - foreign-hook (per file): an entry whose command names our
|
|
885
|
+
* marker but whose flags/timeout/matcher differ from the current
|
|
886
|
+
* install shape. Refused: the operator repairs by hand so a
|
|
887
|
+
* bespoke variant is not silently overwritten;
|
|
888
|
+
* - parse-error (per file): a settings file that exists but is not
|
|
889
|
+
* valid JSON. Refused; the operator repairs by hand.
|
|
890
|
+
*
|
|
891
|
+
* With --fix, only missing-hook rows are repaired; the writer never
|
|
892
|
+
* touches a file when the merge would produce a foreign row.
|
|
893
|
+
*
|
|
894
|
+
* @param {object} ctx
|
|
895
|
+
* @returns {Promise<{ drift: Array<{item: string, file: string, message: string, refusedByFix: boolean}>, writes: Array<{file: string, action: string}> }>}
|
|
896
|
+
*/
|
|
897
|
+
async function runFeedbackHooksCheck(ctx) {
|
|
898
|
+
const drift = [];
|
|
899
|
+
const writes = [];
|
|
900
|
+
|
|
901
|
+
const claudeDiag = await diagnoseClaudeFeedbackHooks({ projectRoot: ctx.projectRoot });
|
|
902
|
+
if (claudeDiag.parseError) {
|
|
903
|
+
drift.push({
|
|
904
|
+
item: 'parse-error',
|
|
905
|
+
file: '.claude/settings.json',
|
|
906
|
+
message: `.claude/settings.json is present but not valid JSON (${claudeDiag.parseError}). Repair by hand.`,
|
|
907
|
+
refusedByFix: true,
|
|
908
|
+
});
|
|
909
|
+
} else {
|
|
910
|
+
for (const event of claudeDiag.missing) {
|
|
911
|
+
drift.push({
|
|
912
|
+
item: 'missing-hook',
|
|
913
|
+
file: '.claude/settings.json',
|
|
914
|
+
message: `.claude/settings.json is missing the feedback ${event} hook; \`rcf doctor --fix\` merges it in.`,
|
|
915
|
+
refusedByFix: false,
|
|
916
|
+
});
|
|
917
|
+
}
|
|
918
|
+
for (const f of claudeDiag.foreign) {
|
|
919
|
+
drift.push({
|
|
920
|
+
item: 'foreign-hook',
|
|
921
|
+
file: '.claude/settings.json',
|
|
922
|
+
message: `.claude/settings.json ${f.event} hook has a foreign command shape (${f.command}); refused. Repair by hand or remove the entry and re-run \`rcf init\`.`,
|
|
923
|
+
refusedByFix: true,
|
|
924
|
+
});
|
|
925
|
+
}
|
|
926
|
+
if (ctx.fix && claudeDiag.missing.length > 0 && claudeDiag.foreign.length === 0) {
|
|
927
|
+
const w = await writeClaudeFeedbackHooks({ projectRoot: ctx.projectRoot });
|
|
928
|
+
if (!('kind' in w)) {
|
|
929
|
+
writes.push({ file: '.claude/settings.json', action: w.action });
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
const codexDiag = await diagnoseCodexFeedbackHooks({ projectRoot: ctx.projectRoot });
|
|
935
|
+
if (codexDiag.parseError) {
|
|
936
|
+
drift.push({
|
|
937
|
+
item: 'parse-error',
|
|
938
|
+
file: '.codex/hooks.json',
|
|
939
|
+
message: `.codex/hooks.json is present but not valid JSON (${codexDiag.parseError}). Repair by hand.`,
|
|
940
|
+
refusedByFix: true,
|
|
941
|
+
});
|
|
942
|
+
} else {
|
|
943
|
+
for (const event of codexDiag.missing) {
|
|
944
|
+
drift.push({
|
|
945
|
+
item: 'missing-hook',
|
|
946
|
+
file: '.codex/hooks.json',
|
|
947
|
+
message: `.codex/hooks.json is missing the feedback ${event} hook; \`rcf doctor --fix\` merges it in.`,
|
|
948
|
+
refusedByFix: false,
|
|
949
|
+
});
|
|
950
|
+
}
|
|
951
|
+
for (const f of codexDiag.foreign) {
|
|
952
|
+
drift.push({
|
|
953
|
+
item: 'foreign-hook',
|
|
954
|
+
file: '.codex/hooks.json',
|
|
955
|
+
message: `.codex/hooks.json ${f.event} hook has a foreign command shape (${f.command}); refused. Repair by hand or remove the entry and re-run \`rcf init\`.`,
|
|
956
|
+
refusedByFix: true,
|
|
957
|
+
});
|
|
958
|
+
}
|
|
959
|
+
if (ctx.fix && codexDiag.missing.length > 0 && codexDiag.foreign.length === 0) {
|
|
960
|
+
const w = await writeCodexFeedbackHooks({ projectRoot: ctx.projectRoot });
|
|
961
|
+
if (!('kind' in w)) {
|
|
962
|
+
writes.push({ file: '.codex/hooks.json', action: w.action });
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
return { drift, writes };
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
|
|
783
971
|
/**
|
|
784
972
|
* Default reader for the project-root .mcp.json body. Returns the parsed
|
|
785
973
|
* object, or null on missing / unparseable (doctor treats an unparseable
|