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.
Files changed (601) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +10 -0
  3. package/bin/rcf.js +2 -0
  4. package/blueprints/application-account-settings/CHANGELOG.md +35 -6
  5. package/blueprints/application-account-settings/README.md +1 -1
  6. package/blueprints/application-account-settings/blueprint.json +4 -2
  7. package/blueprints/application-account-settings/contributions/adrs/adr-2602-application-account-settings-security-surface-shape.json +1 -1
  8. package/blueprints/application-account-settings/contributions/probes/probe-utils.mjs +177 -0
  9. package/blueprints/application-account-settings/contributions/probes/profile-form-autocomplete.mjs +67 -0
  10. package/blueprints/application-account-settings/contributions/probes/run-profile-form-autocomplete.mjs +5 -0
  11. package/blueprints/application-account-settings/contributions/probes/run-sessions-adapter-uniform.mjs +5 -0
  12. package/blueprints/application-account-settings/contributions/probes/run-sessions-surface-shape.mjs +5 -0
  13. package/blueprints/application-account-settings/contributions/probes/run-shell-tablist-per-capability.mjs +5 -0
  14. package/blueprints/application-account-settings/contributions/probes/run-theme-radiogroup.mjs +5 -0
  15. package/blueprints/application-account-settings/contributions/probes/sessions-adapter-uniform.mjs +130 -0
  16. package/blueprints/application-account-settings/contributions/probes/sessions-surface-shape.mjs +70 -0
  17. package/blueprints/application-account-settings/contributions/probes/shell-tablist-per-capability.mjs +60 -0
  18. package/blueprints/application-account-settings/contributions/probes/theme-radiogroup.mjs +126 -0
  19. package/blueprints/application-admin-console/CHANGELOG.md +32 -6
  20. package/blueprints/application-admin-console/README.md +1 -1
  21. package/blueprints/application-admin-console/blueprint.json +4 -2
  22. package/blueprints/application-admin-console/contributions/adrs/adr-2201-application-admin-console-capability-vocabulary.json +1 -1
  23. package/blueprints/application-admin-console/contributions/probes/audit-log-surface.mjs +79 -0
  24. package/blueprints/application-admin-console/contributions/probes/org-switcher-surface.mjs +83 -0
  25. package/blueprints/application-admin-console/contributions/probes/permission-matrix-grid.mjs +67 -0
  26. package/blueprints/application-admin-console/contributions/probes/probe-utils.mjs +177 -0
  27. package/blueprints/application-admin-console/contributions/probes/run-audit-log-surface.mjs +5 -0
  28. package/blueprints/application-admin-console/contributions/probes/run-org-switcher-surface.mjs +5 -0
  29. package/blueprints/application-admin-console/contributions/probes/run-permission-matrix-grid.mjs +5 -0
  30. package/blueprints/application-admin-console/contributions/probes/run-sign-in-access-gated-surface.mjs +5 -0
  31. package/blueprints/application-admin-console/contributions/probes/run-users-directory-surface.mjs +5 -0
  32. package/blueprints/application-admin-console/contributions/probes/sign-in-access-gated-surface.mjs +117 -0
  33. package/blueprints/application-admin-console/contributions/probes/users-directory-surface.mjs +145 -0
  34. package/blueprints/application-api-rest/CHANGELOG.md +16 -8
  35. package/blueprints/application-api-rest/README.md +3 -3
  36. package/blueprints/application-api-rest/blueprint.json +3 -2
  37. package/blueprints/application-api-rest/contributions/adrs/adr-302-application-api-rest-auth-model.json +1 -1
  38. package/blueprints/application-api-rest/contributions/probes/cursor-pagination-round-trip.mjs +154 -0
  39. package/blueprints/application-api-rest/contributions/probes/health-probes-distinct.mjs +124 -0
  40. package/blueprints/application-api-rest/contributions/probes/probe-utils.mjs +177 -0
  41. package/blueprints/application-api-rest/contributions/probes/problem-details-on-error.mjs +77 -0
  42. package/blueprints/application-api-rest/contributions/probes/request-id-echoed.mjs +76 -0
  43. package/blueprints/application-api-rest/contributions/probes/run-cursor-pagination-round-trip.mjs +5 -0
  44. package/blueprints/application-api-rest/contributions/probes/run-health-probes-distinct.mjs +5 -0
  45. package/blueprints/application-api-rest/contributions/probes/run-problem-details-on-error.mjs +5 -0
  46. package/blueprints/application-api-rest/contributions/probes/run-request-id-echoed.mjs +5 -0
  47. package/blueprints/application-api-rest/docs/topics.md +1 -1
  48. package/blueprints/application-charts/CHANGELOG.md +35 -9
  49. package/blueprints/application-charts/README.md +6 -6
  50. package/blueprints/application-charts/blueprint.json +5 -3
  51. package/blueprints/application-charts/contributions/adrs/adr-1901-application-charts-engine-choice.json +1 -1
  52. package/blueprints/application-charts/contributions/probes/keyboard-traversal.mjs +151 -0
  53. package/blueprints/application-charts/contributions/probes/non-colour-distinction.mjs +67 -0
  54. package/blueprints/application-charts/contributions/probes/probe-utils.mjs +177 -0
  55. package/blueprints/application-charts/contributions/probes/run-keyboard-traversal.mjs +5 -0
  56. package/blueprints/application-charts/contributions/probes/run-non-colour-distinction.mjs +5 -0
  57. package/blueprints/application-charts/contributions/probes/run-text-alternative-table.mjs +5 -0
  58. package/blueprints/application-charts/contributions/probes/text-alternative-table.mjs +139 -0
  59. package/blueprints/application-charts/contributions/requirements/application-charts-req-001.json +1 -1
  60. package/blueprints/application-charts/contributions/requirements/application-charts-req-002.json +1 -1
  61. package/blueprints/application-charts/contributions/user-stories/application-charts-us-18101.json +5 -5
  62. package/blueprints/application-charts/contributions/user-stories/application-charts-us-18106.json +1 -1
  63. package/blueprints/application-charts/guide/application-charts.md +1 -1
  64. package/blueprints/application-dashboard/CHANGELOG.md +20 -10
  65. package/blueprints/application-dashboard/README.md +6 -6
  66. package/blueprints/application-dashboard/assets/guidance/dashboard-design.md +2 -2
  67. package/blueprints/application-dashboard/blueprint.json +3 -2
  68. package/blueprints/application-dashboard/contributions/adrs/adr-2001-application-dashboard-primary-kpi-enum.json +1 -1
  69. package/blueprints/application-dashboard/contributions/adrs/adr-2002-application-dashboard-timeframe-presets.json +1 -1
  70. package/blueprints/application-dashboard/contributions/probes/export-handle-formats.mjs +75 -0
  71. package/blueprints/application-dashboard/contributions/probes/four-tile-states.mjs +75 -0
  72. package/blueprints/application-dashboard/contributions/probes/primary-kpi-top-left.mjs +58 -0
  73. package/blueprints/application-dashboard/contributions/probes/probe-utils.mjs +177 -0
  74. package/blueprints/application-dashboard/contributions/probes/run-export-handle-formats.mjs +4 -0
  75. package/blueprints/application-dashboard/contributions/probes/run-four-tile-states.mjs +4 -0
  76. package/blueprints/application-dashboard/contributions/probes/run-primary-kpi-top-left.mjs +4 -0
  77. package/blueprints/application-dashboard/contributions/probes/run-shell-five-regions.mjs +4 -0
  78. package/blueprints/application-dashboard/contributions/probes/shell-five-regions.mjs +93 -0
  79. package/blueprints/application-dashboard/contributions/requirements/application-dashboard-req-002.json +1 -1
  80. package/blueprints/application-dashboard/contributions/requirements/application-dashboard-req-003.json +1 -1
  81. package/blueprints/application-dashboard/contributions/tacs/tac-2002-application-dashboard-filter-chrome.json +1 -1
  82. package/blueprints/application-dashboard/contributions/tacs/tac-2003-application-dashboard-export-handle.json +2 -2
  83. package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19101.json +2 -2
  84. package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19102.json +2 -2
  85. package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19103.json +1 -1
  86. package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19104.json +1 -1
  87. package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19105.json +1 -1
  88. package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19106.json +2 -2
  89. package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19107.json +5 -5
  90. package/blueprints/application-dashboard/docs/topics.md +2 -2
  91. package/blueprints/application-dashboard/guide/application-dashboard.md +2 -2
  92. package/blueprints/application-datatable/CHANGELOG.md +19 -9
  93. package/blueprints/application-datatable/README.md +2 -2
  94. package/blueprints/application-datatable/blueprint.json +3 -2
  95. package/blueprints/application-datatable/contributions/probes/apg-table-shape.mjs +57 -0
  96. package/blueprints/application-datatable/contributions/probes/four-states-regions.mjs +80 -0
  97. package/blueprints/application-datatable/contributions/probes/probe-utils.mjs +177 -0
  98. package/blueprints/application-datatable/contributions/probes/run-apg-table-shape.mjs +4 -0
  99. package/blueprints/application-datatable/contributions/probes/run-four-states-regions.mjs +4 -0
  100. package/blueprints/application-datatable/contributions/probes/run-search-adapter-round-trip.mjs +4 -0
  101. package/blueprints/application-datatable/contributions/probes/run-sort-adapter-round-trip.mjs +4 -0
  102. package/blueprints/application-datatable/contributions/probes/search-adapter-round-trip.mjs +58 -0
  103. package/blueprints/application-datatable/contributions/probes/sort-adapter-round-trip.mjs +60 -0
  104. package/blueprints/application-datatable/contributions/requirements/application-datatable-req-006.json +1 -1
  105. package/blueprints/application-datatable/docs/topics.md +1 -1
  106. package/blueprints/application-empty-error-states/CHANGELOG.md +33 -3
  107. package/blueprints/application-empty-error-states/blueprint.json +4 -2
  108. package/blueprints/application-empty-error-states/contributions/probes/empty-list-and-no-search.mjs +66 -0
  109. package/blueprints/application-empty-error-states/contributions/probes/error-boundary-alert.mjs +65 -0
  110. package/blueprints/application-empty-error-states/contributions/probes/forbidden-and-server-error.mjs +167 -0
  111. package/blueprints/application-empty-error-states/contributions/probes/not-found-and-recovery.mjs +61 -0
  112. package/blueprints/application-empty-error-states/contributions/probes/permission-denied-and-offline.mjs +155 -0
  113. package/blueprints/application-empty-error-states/contributions/probes/probe-utils.mjs +177 -0
  114. package/blueprints/application-empty-error-states/contributions/probes/run-empty-list-and-no-search.mjs +5 -0
  115. package/blueprints/application-empty-error-states/contributions/probes/run-error-boundary-alert.mjs +5 -0
  116. package/blueprints/application-empty-error-states/contributions/probes/run-forbidden-and-server-error.mjs +5 -0
  117. package/blueprints/application-empty-error-states/contributions/probes/run-not-found-and-recovery.mjs +5 -0
  118. package/blueprints/application-empty-error-states/contributions/probes/run-permission-denied-and-offline.mjs +5 -0
  119. package/blueprints/application-error-handling/CHANGELOG.md +45 -6
  120. package/blueprints/application-error-handling/blueprint.json +3 -2
  121. package/blueprints/application-error-handling/contributions/probes/category-vocabulary.mjs +90 -0
  122. package/blueprints/application-error-handling/contributions/probes/probe-utils.mjs +177 -0
  123. package/blueprints/application-error-handling/contributions/probes/record-shape-adr-1701.mjs +78 -0
  124. package/blueprints/application-error-handling/contributions/probes/run-category-vocabulary.mjs +5 -0
  125. package/blueprints/application-error-handling/contributions/probes/run-record-shape-adr-1701.mjs +5 -0
  126. package/blueprints/application-error-handling/contributions/probes/run-two-boundaries-registered.mjs +5 -0
  127. package/blueprints/application-error-handling/contributions/probes/two-boundaries-registered.mjs +343 -0
  128. package/blueprints/application-file-upload/CHANGELOG.md +28 -6
  129. package/blueprints/application-file-upload/README.md +1 -1
  130. package/blueprints/application-file-upload/blueprint.json +3 -2
  131. package/blueprints/application-file-upload/contributions/probes/assertive-completion-slot.mjs +78 -0
  132. package/blueprints/application-file-upload/contributions/probes/chunked-transport-endpoints.mjs +173 -0
  133. package/blueprints/application-file-upload/contributions/probes/per-file-progressbar.mjs +124 -0
  134. package/blueprints/application-file-upload/contributions/probes/probe-utils.mjs +177 -0
  135. package/blueprints/application-file-upload/contributions/probes/run-assertive-completion-slot.mjs +4 -0
  136. package/blueprints/application-file-upload/contributions/probes/run-chunked-transport-endpoints.mjs +4 -0
  137. package/blueprints/application-file-upload/contributions/probes/run-per-file-progressbar.mjs +4 -0
  138. package/blueprints/application-file-upload/contributions/probes/run-upload-surface-shape.mjs +4 -0
  139. package/blueprints/application-file-upload/contributions/probes/upload-surface-shape.mjs +55 -0
  140. package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-001.json +1 -1
  141. package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-002.json +1 -1
  142. package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-003.json +1 -1
  143. package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-004.json +1 -1
  144. package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-005.json +1 -1
  145. package/blueprints/application-file-upload/probe-packs/application-file-upload.pack.mjs +1 -1
  146. package/blueprints/application-forms-wizard/CHANGELOG.md +20 -6
  147. package/blueprints/application-forms-wizard/README.md +2 -2
  148. package/blueprints/application-forms-wizard/blueprint.json +3 -2
  149. package/blueprints/application-forms-wizard/contributions/probes/draft-persistence-round-trip.mjs +110 -0
  150. package/blueprints/application-forms-wizard/contributions/probes/probe-utils.mjs +177 -0
  151. package/blueprints/application-forms-wizard/contributions/probes/run-draft-persistence-round-trip.mjs +4 -0
  152. package/blueprints/application-forms-wizard/contributions/probes/run-step-page-shape.mjs +4 -0
  153. package/blueprints/application-forms-wizard/contributions/probes/run-task-list-surface.mjs +4 -0
  154. package/blueprints/application-forms-wizard/contributions/probes/step-page-shape.mjs +61 -0
  155. package/blueprints/application-forms-wizard/contributions/probes/task-list-surface.mjs +109 -0
  156. package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-001.json +1 -1
  157. package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-002.json +1 -1
  158. package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-003.json +1 -1
  159. package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-004.json +1 -1
  160. package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-005.json +1 -1
  161. package/blueprints/application-forms-wizard/probe-packs/application-forms-wizard.pack.mjs +1 -1
  162. package/blueprints/application-notifications-in-app/CHANGELOG.md +38 -5
  163. package/blueprints/application-notifications-in-app/README.md +4 -4
  164. package/blueprints/application-notifications-in-app/blueprint.json +4 -2
  165. package/blueprints/application-notifications-in-app/contributions/adrs/adr-2101-application-notifications-in-app-live-region-role-mapping.json +1 -1
  166. package/blueprints/application-notifications-in-app/contributions/probes/centre-acknowledge-round-trip.mjs +210 -0
  167. package/blueprints/application-notifications-in-app/contributions/probes/live-region-preseeding.mjs +93 -0
  168. package/blueprints/application-notifications-in-app/contributions/probes/probe-utils.mjs +177 -0
  169. package/blueprints/application-notifications-in-app/contributions/probes/run-centre-acknowledge-round-trip.mjs +5 -0
  170. package/blueprints/application-notifications-in-app/contributions/probes/run-live-region-preseeding.mjs +5 -0
  171. package/blueprints/application-notifications-in-app/contributions/probes/run-toast-contract.mjs +5 -0
  172. package/blueprints/application-notifications-in-app/contributions/probes/toast-contract.mjs +92 -0
  173. package/blueprints/application-notifications-in-app/contributions/tacs/tac-2101-application-notifications-in-app-live-region.json +3 -3
  174. package/blueprints/application-notifications-in-app/contributions/tacs/tac-2102-application-notifications-in-app-centre.json +1 -1
  175. package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20101.json +1 -1
  176. package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20102.json +1 -1
  177. package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20103.json +1 -1
  178. package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20105.json +1 -1
  179. package/blueprints/application-notifications-in-app/guide/application-notifications-in-app.md +3 -3
  180. package/blueprints/application-onboarding-tour/CHANGELOG.md +31 -5
  181. package/blueprints/application-onboarding-tour/README.md +1 -1
  182. package/blueprints/application-onboarding-tour/blueprint.json +5 -3
  183. package/blueprints/application-onboarding-tour/contributions/probes/checklist-anchor-open.mjs +81 -0
  184. package/blueprints/application-onboarding-tour/contributions/probes/completion-persistence.mjs +159 -0
  185. package/blueprints/application-onboarding-tour/contributions/probes/first-run-detection.mjs +67 -0
  186. package/blueprints/application-onboarding-tour/contributions/probes/probe-utils.mjs +177 -0
  187. package/blueprints/application-onboarding-tour/contributions/probes/run-checklist-anchor-open.mjs +5 -0
  188. package/blueprints/application-onboarding-tour/contributions/probes/run-completion-persistence.mjs +5 -0
  189. package/blueprints/application-onboarding-tour/contributions/probes/run-first-run-detection.mjs +5 -0
  190. package/blueprints/application-onboarding-tour/contributions/probes/run-stepper-role-dialog.mjs +5 -0
  191. package/blueprints/application-onboarding-tour/contributions/probes/stepper-role-dialog.mjs +45 -0
  192. package/blueprints/application-spa/CHANGELOG.md +20 -11
  193. package/blueprints/application-spa/README.md +9 -10
  194. package/blueprints/application-spa/blueprint.json +3 -2
  195. package/blueprints/application-spa/contributions/adrs/adr-202-application-spa-theming.json +1 -1
  196. package/blueprints/application-spa/contributions/adrs/adr-206-application-spa-iconography.json +1 -1
  197. package/blueprints/application-spa/contributions/probes/designed-empty-state.mjs +72 -0
  198. package/blueprints/application-spa/contributions/probes/probe-utils.mjs +177 -0
  199. package/blueprints/application-spa/contributions/probes/route-inventory-published.mjs +185 -0
  200. package/blueprints/application-spa/contributions/probes/run-designed-empty-state.mjs +5 -0
  201. package/blueprints/application-spa/contributions/probes/run-route-inventory-published.mjs +5 -0
  202. package/blueprints/application-spa/contributions/probes/run-shell-nav-present.mjs +5 -0
  203. package/blueprints/application-spa/contributions/probes/shell-nav-present.mjs +69 -0
  204. package/blueprints/application-spa/contributions/tacs/tac-207-application-spa-token-adherence-probe.json +1 -1
  205. package/blueprints/application-spa/contributions/tacs/tac-208-application-spa-icon-adherence-probe.json +2 -2
  206. package/blueprints/application-spa/contributions/tacs/tac-209-application-spa-csp-styled-adherence-probe.json +3 -3
  207. package/blueprints/application-spa/contributions/tacs/tac-210-application-spa-external-dependency-provisioning-probe.json +2 -2
  208. package/blueprints/application-spa/contributions/tacs/tac-211-application-spa-core-flow-e2e-probe.json +2 -2
  209. package/blueprints/application-spa/contributions/user-stories/application-spa-us-1131.json +1 -1
  210. package/blueprints/application-spa/docs/topics.md +1 -1
  211. package/blueprints/delivery-ci-workflows/CHANGELOG.md +31 -11
  212. package/blueprints/delivery-ci-workflows/README.md +3 -3
  213. package/blueprints/delivery-ci-workflows/blueprint.json +3 -2
  214. package/blueprints/delivery-ci-workflows/contributions/adrs/adr-702-delivery-ci-workflows-strict-coverage-gate.json +2 -2
  215. package/blueprints/delivery-ci-workflows/contributions/probes/node-gate-entrypoint.mjs +76 -0
  216. package/blueprints/delivery-ci-workflows/contributions/probes/probe-utils.mjs +56 -0
  217. package/blueprints/delivery-ci-workflows/contributions/probes/real-account-github-actions-run-record.mjs +139 -0
  218. package/blueprints/delivery-ci-workflows/contributions/probes/run-node-gate-entrypoint.mjs +3 -0
  219. package/blueprints/delivery-ci-workflows/contributions/probes/run-real-account-github-actions-run-record.mjs +3 -0
  220. package/blueprints/delivery-ci-workflows/contributions/probes/run-workflow-template-shape.mjs +3 -0
  221. package/blueprints/delivery-ci-workflows/contributions/probes/workflow-template-shape.mjs +94 -0
  222. package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-004.json +1 -1
  223. package/blueprints/delivery-ci-workflows/docs/topics.md +2 -3
  224. package/blueprints/deploy-cloudflare-workers/CHANGELOG.md +4 -4
  225. package/blueprints/deploy-cloudflare-workers/README.md +3 -3
  226. package/blueprints/deploy-cloudflare-workers/contributions/adrs/adr-1306-deploy-cloudflare-workers-spa-shape.json +2 -2
  227. package/blueprints/deploy-cloudflare-workers/docs/topics.md +2 -2
  228. package/blueprints/deploy-hetzner-server/CHANGELOG.md +98 -7
  229. package/blueprints/deploy-hetzner-server/blueprint.json +7 -6
  230. package/blueprints/deploy-hetzner-server/contributions/probes/cloud-init-render-lint.mjs +46 -21
  231. package/blueprints/deploy-hetzner-server/contributions/probes/hcloud-dry-run-mock.mjs +344 -83
  232. package/blueprints/deploy-hetzner-server/contributions/probes/manifest-schema-validate.mjs +211 -42
  233. package/blueprints/deploy-hetzner-server/contributions/probes/probe-utils.mjs +140 -22
  234. package/blueprints/deploy-hetzner-server/contributions/probes/real-account-cloud-init-hardened.mjs +111 -30
  235. package/blueprints/deploy-hetzner-server/contributions/probes/real-account-snapshot-on-demand.mjs +158 -30
  236. package/blueprints/deploy-hetzner-server/contributions/probes/real-account-throwaway-server-provision.mjs +154 -32
  237. package/blueprints/edge-cloudflare-access/CHANGELOG.md +6 -5
  238. package/blueprints/edge-cloudflare-access/blueprint.json +1 -1
  239. package/blueprints/edge-cloudflare-access/contributions/probes/admin-console-gate-surface.mjs +9 -1
  240. package/blueprints/edge-cloudflare-access/docs/topics.md +1 -1
  241. package/blueprints/edge-cloudflare-rate-limiting/CHANGELOG.md +4 -7
  242. package/blueprints/edge-cloudflare-rate-limiting/docs/topics.md +1 -1
  243. package/blueprints/edge-cloudflare-tunnel/CHANGELOG.md +4 -6
  244. package/blueprints/edge-cloudflare-tunnel/README.md +1 -2
  245. package/blueprints/edge-cloudflare-tunnel/docs/topics.md +1 -1
  246. package/blueprints/edge-cloudflare-turnstile/CHANGELOG.md +2 -3
  247. package/blueprints/edge-cloudflare-turnstile/docs/topics.md +1 -1
  248. package/blueprints/email-smtp-resend/CHANGELOG.md +24 -8
  249. package/blueprints/email-smtp-resend/README.md +2 -2
  250. package/blueprints/email-smtp-resend/blueprint.json +3 -2
  251. package/blueprints/email-smtp-resend/contributions/probes/probe-utils.mjs +50 -0
  252. package/blueprints/email-smtp-resend/contributions/probes/real-account-resend-send.mjs +50 -0
  253. package/blueprints/email-smtp-resend/contributions/probes/run-real-account-resend-send.mjs +3 -0
  254. package/blueprints/email-smtp-resend/contributions/probes/run-smtp-round-trip.mjs +3 -0
  255. package/blueprints/email-smtp-resend/contributions/probes/run-unverified-sender-refusal.mjs +3 -0
  256. package/blueprints/email-smtp-resend/contributions/probes/smtp-round-trip.mjs +43 -0
  257. package/blueprints/email-smtp-resend/contributions/probes/unverified-sender-refusal.mjs +99 -0
  258. package/blueprints/email-smtp-resend/docs/topics.md +2 -3
  259. package/blueprints/jobs-background/CHANGELOG.md +66 -5
  260. package/blueprints/jobs-background/README.md +2 -2
  261. package/blueprints/jobs-background/blueprint.json +3 -2
  262. package/blueprints/jobs-background/contributions/probes/apply-time-override.mjs +38 -10
  263. package/blueprints/jobs-background/contributions/probes/apply-time-refusal.mjs +28 -6
  264. package/blueprints/jobs-background/contributions/probes/event-secrecy.mjs +16 -2
  265. package/blueprints/jobs-background/contributions/probes/fake-clock-cron.mjs +102 -21
  266. package/blueprints/jobs-background/contributions/probes/probe-utils.mjs +10 -2
  267. package/blueprints/jobs-background/contributions/probes/retry-and-fail-real-account.mjs +355 -0
  268. package/blueprints/jobs-background/contributions/probes/retry-and-fail.mjs +33 -2
  269. package/blueprints/jobs-background/contributions/probes/run-retry-and-fail-real-account.mjs +12 -0
  270. package/blueprints/jobs-background/docs/topics.md +1 -1
  271. package/blueprints/jobs-background/guide/jobs-background.md +1 -1
  272. package/blueprints/messaging-queue-cloudflare/CHANGELOG.md +25 -19
  273. package/blueprints/messaging-queue-cloudflare/README.md +12 -12
  274. package/blueprints/messaging-queue-cloudflare/blueprint.json +1 -1
  275. package/blueprints/messaging-queue-cloudflare/contributions/adrs/adr-3001-messaging-queue-cloudflare-adapter.json +2 -2
  276. package/blueprints/messaging-queue-cloudflare/contributions/adrs/adr-3002-messaging-queue-cloudflare-delivery-semantics.json +1 -1
  277. package/blueprints/messaging-queue-cloudflare/contributions/probes/real-account-concurrency-smoke.mjs +180 -12
  278. package/blueprints/messaging-queue-cloudflare/contributions/requirements/messaging-queue-cloudflare-req-006.json +1 -1
  279. package/blueprints/messaging-queue-cloudflare/docs/topics.md +2 -2
  280. package/blueprints/messaging-queue-cloudflare/guide/messaging-queue-cloudflare.md +2 -2
  281. package/blueprints/object-storage-s3/CHANGELOG.md +75 -4
  282. package/blueprints/object-storage-s3/blueprint.json +3 -2
  283. package/blueprints/object-storage-s3/contributions/probes/event-secrecy.mjs +73 -12
  284. package/blueprints/object-storage-s3/contributions/probes/facade-round-trip.mjs +55 -7
  285. package/blueprints/object-storage-s3/contributions/probes/hetzner-object-storage-round-trip.mjs +102 -18
  286. package/blueprints/object-storage-s3/contributions/probes/multipart-upload.mjs +105 -36
  287. package/blueprints/object-storage-s3/contributions/probes/presigned-url.mjs +104 -55
  288. package/blueprints/object-storage-s3/contributions/probes/probe-utils.mjs +129 -7
  289. package/blueprints/object-storage-s3/contributions/probes/put-get-round-trip.mjs +80 -18
  290. package/blueprints/object-storage-s3/contributions/probes/r2-real-account-smoke.mjs +291 -37
  291. package/blueprints/object-storage-s3/contributions/probes/run-event-secrecy.mjs +8 -2
  292. package/blueprints/object-storage-s3/contributions/probes/run-facade-round-trip.mjs +5 -5
  293. package/blueprints/object-storage-s3/contributions/probes/run-hetzner-object-storage-round-trip.mjs +8 -5
  294. package/blueprints/object-storage-s3/contributions/probes/run-multipart-upload.mjs +8 -2
  295. package/blueprints/object-storage-s3/contributions/probes/run-presigned-url.mjs +8 -2
  296. package/blueprints/object-storage-s3/contributions/probes/run-put-get-round-trip.mjs +6 -3
  297. package/blueprints/object-storage-s3/contributions/probes/run-r2-real-account-smoke.mjs +10 -2
  298. package/blueprints/object-storage-s3/contributions/requirements/object-storage-s3-req-006.json +1 -1
  299. package/blueprints/object-storage-s3/docs/topics.md +1 -1
  300. package/blueprints/object-storage-s3/guide/object-storage-s3.md +1 -1
  301. package/blueprints/observability-essentials/CHANGELOG.md +23 -7
  302. package/blueprints/observability-essentials/README.md +2 -2
  303. package/blueprints/observability-essentials/assets/probe-samples/probe-response-baseline.v2.json +1 -1
  304. package/blueprints/observability-essentials/blueprint.json +3 -2
  305. package/blueprints/observability-essentials/contributions/probes/liveness-probe.mjs +84 -0
  306. package/blueprints/observability-essentials/contributions/probes/metrics-endpoint.mjs +96 -0
  307. package/blueprints/observability-essentials/contributions/probes/probe-utils.mjs +52 -0
  308. package/blueprints/observability-essentials/contributions/probes/readiness-probe.mjs +171 -0
  309. package/blueprints/observability-essentials/contributions/probes/run-liveness-probe.mjs +3 -0
  310. package/blueprints/observability-essentials/contributions/probes/run-metrics-endpoint.mjs +3 -0
  311. package/blueprints/observability-essentials/contributions/probes/run-readiness-probe.mjs +3 -0
  312. package/blueprints/observability-essentials/docs/topics.md +2 -3
  313. package/blueprints/observability-logging/CHANGELOG.md +29 -4
  314. package/blueprints/observability-logging/README.md +2 -2
  315. package/blueprints/observability-logging/blueprint.json +3 -2
  316. package/blueprints/observability-logging/contributions/probes/correlation-id-flow.mjs +173 -0
  317. package/blueprints/observability-logging/contributions/probes/line-shape-and-fields.mjs +82 -0
  318. package/blueprints/observability-logging/contributions/probes/probe-utils.mjs +47 -0
  319. package/blueprints/observability-logging/contributions/probes/redaction-boundary.mjs +130 -0
  320. package/blueprints/observability-logging/contributions/probes/run-correlation-id-flow.mjs +3 -0
  321. package/blueprints/observability-logging/contributions/probes/run-line-shape-and-fields.mjs +3 -0
  322. package/blueprints/observability-logging/contributions/probes/run-redaction-boundary.mjs +3 -0
  323. package/blueprints/observability-probe-endpoints/CHANGELOG.md +23 -8
  324. package/blueprints/observability-probe-endpoints/README.md +3 -3
  325. package/blueprints/observability-probe-endpoints/blueprint.json +3 -2
  326. package/blueprints/observability-probe-endpoints/contributions/probes/kubernetes-startup-enabled.mjs +80 -0
  327. package/blueprints/observability-probe-endpoints/contributions/probes/partial-profile-refusal.mjs +101 -0
  328. package/blueprints/observability-probe-endpoints/contributions/probes/probe-utils.mjs +49 -0
  329. package/blueprints/observability-probe-endpoints/contributions/probes/profile-boot-materialisation.mjs +69 -0
  330. package/blueprints/observability-probe-endpoints/contributions/probes/run-kubernetes-startup-enabled.mjs +3 -0
  331. package/blueprints/observability-probe-endpoints/contributions/probes/run-partial-profile-refusal.mjs +3 -0
  332. package/blueprints/observability-probe-endpoints/contributions/probes/run-profile-boot-materialisation.mjs +3 -0
  333. package/blueprints/observability-probe-endpoints/docs/topics.md +2 -2
  334. package/blueprints/persistence-data-d1/CHANGELOG.md +16 -3
  335. package/blueprints/persistence-data-d1/README.md +2 -2
  336. package/blueprints/persistence-data-d1/blueprint.json +3 -2
  337. package/blueprints/persistence-data-d1/contributions/adrs/adr-1404-persistence-data-d1-store-boundary.json +1 -1
  338. package/blueprints/persistence-data-d1/contributions/probes/facade-round-trip.mjs +140 -0
  339. package/blueprints/persistence-data-d1/contributions/probes/migrations-forward-only.mjs +66 -0
  340. package/blueprints/persistence-data-d1/contributions/probes/probe-utils.mjs +51 -0
  341. package/blueprints/persistence-data-d1/contributions/probes/real-account-d1-round-trip.mjs +133 -0
  342. package/blueprints/persistence-data-d1/contributions/probes/run-facade-round-trip.mjs +3 -0
  343. package/blueprints/persistence-data-d1/contributions/probes/run-migrations-forward-only.mjs +3 -0
  344. package/blueprints/persistence-data-d1/contributions/probes/run-real-account-d1-round-trip.mjs +3 -0
  345. package/blueprints/persistence-data-d1/docs/topics.md +2 -3
  346. package/blueprints/persistence-data-postgres/CHANGELOG.md +84 -4
  347. package/blueprints/persistence-data-postgres/README.md +2 -2
  348. package/blueprints/persistence-data-postgres/blueprint.json +3 -2
  349. package/blueprints/persistence-data-postgres/contributions/adrs/adr-2801-persistence-data-postgres-driver.json +1 -1
  350. package/blueprints/persistence-data-postgres/contributions/probes/facade-round-trip.mjs +87 -12
  351. package/blueprints/persistence-data-postgres/contributions/probes/migration-apply.mjs +245 -19
  352. package/blueprints/persistence-data-postgres/contributions/probes/pool-posture-smoke.mjs +109 -26
  353. package/blueprints/persistence-data-postgres/contributions/probes/prepared-statement-scan.mjs +151 -38
  354. package/blueprints/persistence-data-postgres/contributions/probes/probe-utils.mjs +24 -6
  355. package/blueprints/persistence-data-postgres/contributions/probes/recovery-restore-round-trip.mjs +261 -48
  356. package/blueprints/persistence-data-postgres/contributions/probes/transaction-atomicity.mjs +76 -20
  357. package/blueprints/persistence-data-postgres/contributions/requirements/persistence-data-postgres-req-003.json +1 -1
  358. package/blueprints/persistence-data-postgres/docs/topics.md +1 -1
  359. package/blueprints/persistence-data-sqlite/CHANGELOG.md +16 -2
  360. package/blueprints/persistence-data-sqlite/README.md +2 -2
  361. package/blueprints/persistence-data-sqlite/blueprint.json +3 -2
  362. package/blueprints/persistence-data-sqlite/contributions/probes/boot-open-migrate.mjs +90 -0
  363. package/blueprints/persistence-data-sqlite/contributions/probes/facade-round-trip.mjs +82 -0
  364. package/blueprints/persistence-data-sqlite/contributions/probes/probe-utils.mjs +83 -0
  365. package/blueprints/persistence-data-sqlite/contributions/probes/run-boot-open-migrate.mjs +5 -0
  366. package/blueprints/persistence-data-sqlite/contributions/probes/run-facade-round-trip.mjs +5 -0
  367. package/blueprints/persistence-data-sqlite/contributions/probes/run-wal-checkpoint.mjs +5 -0
  368. package/blueprints/persistence-data-sqlite/contributions/probes/wal-checkpoint.mjs +137 -0
  369. package/blueprints/persistence-data-sqlite/docs/topics.md +2 -3
  370. package/blueprints/platform-cloudflare-cron-triggers/CHANGELOG.md +5 -5
  371. package/blueprints/platform-cloudflare-cron-triggers/README.md +2 -3
  372. package/blueprints/platform-cloudflare-cron-triggers/docs/topics.md +1 -1
  373. package/blueprints/platform-cloudflare-durable-objects/CHANGELOG.md +6 -10
  374. package/blueprints/platform-cloudflare-durable-objects/docs/topics.md +1 -1
  375. package/blueprints/platform-cloudflare-kv/CHANGELOG.md +16 -12
  376. package/blueprints/platform-cloudflare-kv/README.md +2 -4
  377. package/blueprints/platform-cloudflare-kv/blueprint.json +2 -2
  378. package/blueprints/platform-cloudflare-kv/docs/topics.md +1 -1
  379. package/blueprints/platform-docker-compose-host/CHANGELOG.md +92 -5
  380. package/blueprints/platform-docker-compose-host/blueprint.json +2 -2
  381. package/blueprints/platform-docker-compose-host/contributions/probes/caddyfile-validate.mjs +116 -29
  382. package/blueprints/platform-docker-compose-host/contributions/probes/compose-config-lint.mjs +181 -109
  383. package/blueprints/platform-docker-compose-host/contributions/probes/probe-utils.mjs +146 -26
  384. package/blueprints/platform-docker-compose-host/contributions/probes/real-account-minimal-stack-up.mjs +238 -24
  385. package/blueprints/platform-docker-compose-host/contributions/probes/real-account-reload-burst.mjs +207 -21
  386. package/blueprints/platform-docker-compose-host/contributions/probes/secrets-as-files-scan.mjs +246 -42
  387. package/blueprints/platform-docker-compose-host/docs/topics.md +1 -1
  388. package/blueprints/security-auth-clerk/CHANGELOG.md +18 -6
  389. package/blueprints/security-auth-clerk/README.md +3 -3
  390. package/blueprints/security-auth-clerk/assets/wiring/workers-wrangler-toml-shape.md +1 -1
  391. package/blueprints/security-auth-clerk/blueprint.json +3 -2
  392. package/blueprints/security-auth-clerk/contributions/probes/hosted-identity-ui-config.mjs +61 -0
  393. package/blueprints/security-auth-clerk/contributions/probes/probe-utils.mjs +188 -0
  394. package/blueprints/security-auth-clerk/contributions/probes/real-account-principal-directory-round-trip.mjs +216 -0
  395. package/blueprints/security-auth-clerk/contributions/probes/real-account-session-inventory.mjs +260 -0
  396. package/blueprints/security-auth-clerk/contributions/probes/role-model-adapter.mjs +53 -0
  397. package/blueprints/security-auth-clerk/contributions/probes/run-hosted-identity-ui-config.mjs +4 -0
  398. package/blueprints/security-auth-clerk/contributions/probes/run-real-account-principal-directory-round-trip.mjs +4 -0
  399. package/blueprints/security-auth-clerk/contributions/probes/run-real-account-session-inventory.mjs +4 -0
  400. package/blueprints/security-auth-clerk/contributions/probes/run-role-model-adapter.mjs +4 -0
  401. package/blueprints/security-auth-clerk/docs/topics.md +2 -3
  402. package/blueprints/security-auth-keycloak/CHANGELOG.md +18 -7
  403. package/blueprints/security-auth-keycloak/README.md +2 -2
  404. package/blueprints/security-auth-keycloak/blueprint.json +3 -2
  405. package/blueprints/security-auth-keycloak/contributions/probes/discovery-shape.mjs +68 -0
  406. package/blueprints/security-auth-keycloak/contributions/probes/introspection-shape.mjs +88 -0
  407. package/blueprints/security-auth-keycloak/contributions/probes/jwt-verifier-shape.mjs +86 -0
  408. package/blueprints/security-auth-keycloak/contributions/probes/probe-utils.mjs +180 -0
  409. package/blueprints/security-auth-keycloak/contributions/probes/real-account-realm-round-trip.mjs +91 -0
  410. package/blueprints/security-auth-keycloak/contributions/probes/role-adapter-shape.mjs +69 -0
  411. package/blueprints/security-auth-keycloak/contributions/probes/run-discovery-shape.mjs +4 -0
  412. package/blueprints/security-auth-keycloak/contributions/probes/run-introspection-shape.mjs +4 -0
  413. package/blueprints/security-auth-keycloak/contributions/probes/run-jwt-verifier-shape.mjs +4 -0
  414. package/blueprints/security-auth-keycloak/contributions/probes/run-real-account-realm-round-trip.mjs +4 -0
  415. package/blueprints/security-auth-keycloak/contributions/probes/run-role-adapter-shape.mjs +4 -0
  416. package/blueprints/security-auth-keycloak/docs/topics.md +1 -2
  417. package/blueprints/security-auth-magic-link/CHANGELOG.md +15 -4
  418. package/blueprints/security-auth-magic-link/README.md +2 -2
  419. package/blueprints/security-auth-magic-link/assets/principal-registry-samples/single-address.md +1 -1
  420. package/blueprints/security-auth-magic-link/blueprint.json +3 -2
  421. package/blueprints/security-auth-magic-link/contributions/probes/probe-utils.mjs +174 -0
  422. package/blueprints/security-auth-magic-link/contributions/probes/real-account-magic-link-send.mjs +139 -0
  423. package/blueprints/security-auth-magic-link/contributions/probes/run-real-account-magic-link-send.mjs +4 -0
  424. package/blueprints/security-auth-magic-link/contributions/probes/run-token-entropy-shape.mjs +4 -0
  425. package/blueprints/security-auth-magic-link/contributions/probes/run-token-issue-verify.mjs +4 -0
  426. package/blueprints/security-auth-magic-link/contributions/probes/token-entropy-shape.mjs +60 -0
  427. package/blueprints/security-auth-magic-link/contributions/probes/token-issue-verify.mjs +90 -0
  428. package/blueprints/security-auth-magic-link/docs/topics.md +1 -1
  429. package/blueprints/security-auth-oauth2/CHANGELOG.md +16 -5
  430. package/blueprints/security-auth-oauth2/README.md +2 -2
  431. package/blueprints/security-auth-oauth2/blueprint.json +3 -2
  432. package/blueprints/security-auth-oauth2/contributions/probes/authorisation-code-flow-shape.mjs +259 -0
  433. package/blueprints/security-auth-oauth2/contributions/probes/pkce-challenge-shape.mjs +58 -0
  434. package/blueprints/security-auth-oauth2/contributions/probes/probe-utils.mjs +190 -0
  435. package/blueprints/security-auth-oauth2/contributions/probes/provider-adapter-shape.mjs +64 -0
  436. package/blueprints/security-auth-oauth2/contributions/probes/real-account-authorisation-code-flow.mjs +93 -0
  437. package/blueprints/security-auth-oauth2/contributions/probes/run-authorisation-code-flow-shape.mjs +4 -0
  438. package/blueprints/security-auth-oauth2/contributions/probes/run-pkce-challenge-shape.mjs +4 -0
  439. package/blueprints/security-auth-oauth2/contributions/probes/run-provider-adapter-shape.mjs +4 -0
  440. package/blueprints/security-auth-oauth2/contributions/probes/run-real-account-authorisation-code-flow.mjs +4 -0
  441. package/blueprints/security-auth-oauth2/contributions/probes/run-session-bridge-shape.mjs +4 -0
  442. package/blueprints/security-auth-oauth2/contributions/probes/session-bridge-shape.mjs +78 -0
  443. package/blueprints/security-auth-oauth2/docs/topics.md +1 -2
  444. package/blueprints/security-secrets-management/CHANGELOG.md +15 -4
  445. package/blueprints/security-secrets-management/README.md +2 -2
  446. package/blueprints/security-secrets-management/blueprint.json +3 -2
  447. package/blueprints/security-secrets-management/contributions/probes/add-recipient-rotation.mjs +107 -0
  448. package/blueprints/security-secrets-management/contributions/probes/encrypt-decrypt-round-trip.mjs +122 -0
  449. package/blueprints/security-secrets-management/contributions/probes/key-rotation.mjs +93 -0
  450. package/blueprints/security-secrets-management/contributions/probes/mismatched-key-refusal.mjs +74 -0
  451. package/blueprints/security-secrets-management/contributions/probes/probe-utils.mjs +214 -0
  452. package/blueprints/security-secrets-management/contributions/probes/run-add-recipient-rotation.mjs +4 -0
  453. package/blueprints/security-secrets-management/contributions/probes/run-encrypt-decrypt-round-trip.mjs +4 -0
  454. package/blueprints/security-secrets-management/contributions/probes/run-key-rotation.mjs +4 -0
  455. package/blueprints/security-secrets-management/contributions/probes/run-mismatched-key-refusal.mjs +4 -0
  456. package/blueprints/security-secrets-management/docs/topics.md +2 -3
  457. package/fixtures/canary-manifest.json +9 -9
  458. package/guidance/harness-template.md +25 -0
  459. package/guidance/managed/agent-instructions-block.hash +1 -1
  460. package/guidance/managed/agent-instructions-block.md +25 -0
  461. package/package.json +2 -2
  462. package/rcf/adrs/adr-4101-feedback-store-gitignored.json +20 -0
  463. package/rcf/adrs/adr-4102-fingerprint-and-labels.json +25 -0
  464. package/rcf/adrs/adr-4103-redaction-rule-based.json +20 -0
  465. package/rcf/adrs/adr-4104-destination-on-library.json +25 -0
  466. package/rcf/adrs/adr-4105-gh-ambient-auth.json +20 -0
  467. package/rcf/adrs/adr-4106-bundled-entries-terminal.json +20 -0
  468. package/rcf/adrs/adr-4107-stop-is-ask-event.json +30 -0
  469. package/rcf/adrs/adr-4108-hooks-in-committed-config.json +25 -0
  470. package/rcf/adrs/adr-4109-referee-validate-adr-crosslinks.json +25 -0
  471. package/rcf/adrs/adr-4110-referee-coverage-strict-by-default.json +25 -0
  472. package/rcf/adrs/adr-4111-referee-finalise-refusals.json +20 -0
  473. package/rcf/adrs/adr-4112-referee-finalise-verified-invariant.json +30 -0
  474. package/rcf/code-nodes/cn-600.json +45 -0
  475. package/rcf/code-nodes/cn-601.json +18 -0
  476. package/rcf/code-nodes/cn-602.json +15 -0
  477. package/rcf/code-nodes/cn-603.json +12 -0
  478. package/rcf/code-nodes/cn-604.json +14 -0
  479. package/rcf/code-nodes/cn-605.json +17 -0
  480. package/rcf/code-nodes/cn-606.json +12 -0
  481. package/rcf/code-nodes/cn-607.json +12 -0
  482. package/rcf/code-nodes/cn-608.json +14 -0
  483. package/rcf/code-nodes/cn-609.json +17 -0
  484. package/rcf/code-nodes/cn-620.json +18 -0
  485. package/rcf/code-nodes/cn-621.json +14 -0
  486. package/rcf/code-nodes/cn-622.json +15 -0
  487. package/rcf/code-nodes/cn-623.json +16 -0
  488. package/rcf/code-nodes/cn-624.json +14 -0
  489. package/rcf/code-nodes/cn-625.json +15 -0
  490. package/rcf/code-nodes/cn-626.json +13 -0
  491. package/rcf/code-nodes/cn-627.json +13 -0
  492. package/rcf/code-nodes/cn-628.json +14 -0
  493. package/rcf/code-nodes/cn-629.json +12 -0
  494. package/rcf/code-nodes/cn-630.json +12 -0
  495. package/rcf/code-nodes/cn-631.json +13 -0
  496. package/rcf/code-nodes/cn-632.json +13 -0
  497. package/rcf/fbs/fbs-180.json +45 -0
  498. package/rcf/fbs/fbs-181.json +45 -0
  499. package/rcf/fbs/fbs-182.json +42 -0
  500. package/rcf/fbs/fbs-183.json +50 -0
  501. package/rcf/fbs/fbs-184.json +49 -0
  502. package/rcf/fbs/fbs-185.json +34 -0
  503. package/rcf/fbs/fbs-186.json +16 -0
  504. package/rcf/fbs/fbs-187.json +17 -0
  505. package/rcf/fbs/fbs-188.json +17 -0
  506. package/rcf/fbs/fbs-189.json +17 -0
  507. package/rcf/requirements/req-155.json +13 -0
  508. package/rcf/requirements/req-156.json +13 -0
  509. package/rcf/requirements/req-157.json +13 -0
  510. package/rcf/requirements/req-158.json +13 -0
  511. package/rcf/requirements/req-159.json +13 -0
  512. package/rcf/requirements/req-160.json +13 -0
  513. package/rcf/requirements/req-161.json +13 -0
  514. package/rcf/requirements/req-162.json +13 -0
  515. package/rcf/requirements/req-163.json +13 -0
  516. package/rcf/requirements/req-164.json +13 -0
  517. package/rcf/requirements/req-165.json +13 -0
  518. package/rcf/tacs/tac-4101-feedback-cli.json +77 -0
  519. package/rcf/tacs/tac-4102-feedback-store.json +50 -0
  520. package/rcf/tacs/tac-4103-feedback-redact.json +39 -0
  521. package/rcf/tacs/tac-4104-feedback-fingerprint.json +33 -0
  522. package/rcf/tacs/tac-4105-feedback-render.json +45 -0
  523. package/rcf/tacs/tac-4106-feedback-destination.json +39 -0
  524. package/rcf/tacs/tac-4107-feedback-gh.json +43 -0
  525. package/rcf/tacs/tac-4108-feedback-hook.json +46 -0
  526. package/rcf/tacs/tac-4109-referee-validate-adr-crosslinks.json +20 -0
  527. package/rcf/tacs/tac-4110-referee-coverage-mode-selector.json +21 -0
  528. package/rcf/tacs/tac-4111-referee-finalise-per-ac-refusals.json +21 -0
  529. package/rcf/tacs/tac-4112-referee-finalise-verified-invariant.json +22 -0
  530. package/rcf/test-suites/ts-140.json +9 -9
  531. package/rcf/test-suites/ts-150.json +9 -9
  532. package/rcf/test-suites/ts-185.json +54 -0
  533. package/rcf/test-suites/ts-186.json +58 -0
  534. package/rcf/test-suites/ts-187.json +44 -0
  535. package/rcf/test-suites/ts-188.json +166 -0
  536. package/rcf/test-suites/ts-189.json +38 -0
  537. package/rcf/test-suites/ts-190.json +30 -0
  538. package/rcf/test-suites/ts-191.json +51 -0
  539. package/rcf/test-suites/ts-192.json +37 -0
  540. package/rcf/test-suites/ts-193.json +60 -0
  541. package/rcf/test-suites/ts-194.json +67 -0
  542. package/rcf/test-suites/ts-195.json +52 -0
  543. package/rcf/test-suites/ts-196.json +58 -0
  544. package/rcf/test-suites/ts-197.json +66 -0
  545. package/rcf/test-suites/ts-198.json +87 -0
  546. package/rcf/test-suites/ts-199.json +51 -0
  547. package/rcf/test-suites/ts-200.json +30 -0
  548. package/rcf/test-suites/ts-201.json +38 -0
  549. package/rcf/test-suites/ts-202.json +38 -0
  550. package/rcf/test-suites/ts-203.json +38 -0
  551. package/rcf/user-stories/us-15501.json +60 -0
  552. package/rcf/user-stories/us-15502.json +33 -0
  553. package/rcf/user-stories/us-15503.json +33 -0
  554. package/rcf/user-stories/us-15601.json +51 -0
  555. package/rcf/user-stories/us-15701.json +42 -0
  556. package/rcf/user-stories/us-15801.json +42 -0
  557. package/rcf/user-stories/us-15802.json +33 -0
  558. package/rcf/user-stories/us-15901.json +33 -0
  559. package/rcf/user-stories/us-15902.json +51 -0
  560. package/rcf/user-stories/us-16001.json +51 -0
  561. package/rcf/user-stories/us-16101.json +42 -0
  562. package/rcf/user-stories/us-16102.json +33 -0
  563. package/rcf/user-stories/us-16103.json +42 -0
  564. package/rcf/user-stories/us-16104.json +42 -0
  565. package/rcf/user-stories/us-16201.json +33 -0
  566. package/rcf/user-stories/us-16301.json +36 -0
  567. package/rcf/user-stories/us-16401.json +45 -0
  568. package/rcf/user-stories/us-16501.json +45 -0
  569. package/rcf/user-stories/us-16502.json +45 -0
  570. package/releases/releases.yaml +11 -1
  571. package/src/blueprint/library-loader.js +48 -0
  572. package/src/blueprint/library-registry.js +13 -0
  573. package/src/browser-verify/pack-runner.js +7 -12
  574. package/src/build/mark.js +1 -1
  575. package/src/cli/blueprint-library.js +149 -0
  576. package/src/cli/coverage.js +49 -24
  577. package/src/cli/doctor.js +195 -7
  578. package/src/cli/feedback.js +2204 -0
  579. package/src/cli/finalise.js +158 -1
  580. package/src/cli/help.js +6 -0
  581. package/src/cli/init.js +63 -0
  582. package/src/cli/update.js +21 -1
  583. package/src/core/store/walker.js +33 -0
  584. package/src/core/store/writer.js +23 -0
  585. package/src/feedback/destination.js +361 -0
  586. package/src/feedback/fingerprint.js +132 -0
  587. package/src/feedback/gh.js +376 -0
  588. package/src/feedback/hook.js +183 -0
  589. package/src/feedback/labels.js +87 -0
  590. package/src/feedback/redact-allowlist.json +14 -0
  591. package/src/feedback/redact.js +1108 -0
  592. package/src/feedback/render.js +267 -0
  593. package/src/feedback/store.js +604 -0
  594. package/src/finalise/index.js +4 -0
  595. package/src/finalise/ingest.js +61 -0
  596. package/src/finalise/ship-without-eval.js +19 -7
  597. package/src/mcp/tools.js +8 -2
  598. package/src/setup/feedback-hooks.js +397 -0
  599. package/src/setup/managed-gitignore.js +3 -0
  600. package/src/view/html-page.js +5 -5
  601. 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
 
@@ -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
- // Shallow-any default (any AC covered by any TC = REQ covered);
5
- // --strict opts into per-AC-strict. --strict on a tree with uncovered
6
- // ACs exits 4 (CI-gate friendly). Otherwise coverage always exits 0 -
7
- // the gap count is data, not a refusal.
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 --strict that
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. Default is shallow-any (any AC covered by any
51
- resolving TC = REQ covered); --strict flips to per-AC-strict (every AC
52
- has resolving TC coverage).
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
- --strict Per-AC-strict mode; exits 4 on any gap. Also
67
- runs the attestation × profile matrix over
68
- every AC that binds a dependsOnServices
69
- entry (verification-integrity 0.7.0 §5.2):
70
- attestation drift, missing provenance, and
71
- missing FBS-level attestation all exit 4.
72
- --require-approved Extra --strict gate: refuse any TS still at
73
- authoringStatus 'draft' after Stage 4
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: Boolean(flags.strict), scopeId, withCode: Boolean(flags['with-code']), testPointers,
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
- // --strict on any gap = exit 4 (CI-gate friendly). Otherwise 0.
169
- if (flags.strict && !result.ok) return 4;
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: --strict also runs the
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 (flags.strict) {
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 --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`);
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 --strict: refused - the verification-integrity matrix caught the following:\n${refusals.join('\n')}\n`);
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 --strict --require-approved: refused - ${draftTsIds.length} test suite(s) still not approved: ${draftTsIds.join(', ')}\n`);
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
- const refusedCount = drift.filter((d) => d.refusedByFix).length;
266
- const unrepairedCount = ctx.fix ? refusedCount : drift.length;
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
- if (ok && repaired === 0) {
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 = drift.filter((d) => d.refusedByFix);
299
- stdout.write(`rcf doctor: ${drift.length} drift item${drift.length === 1 ? '' : 's'}`);
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