rcf-lite 0.29.0 → 0.31.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 (775) hide show
  1. package/CHANGELOG.md +133 -0
  2. package/blueprints/application-account-settings/contributions/requirements/application-account-settings-req-001.json +1 -1
  3. package/blueprints/application-account-settings/contributions/requirements/application-account-settings-req-002.json +1 -1
  4. package/blueprints/application-account-settings/contributions/requirements/application-account-settings-req-003.json +1 -1
  5. package/blueprints/application-account-settings/contributions/requirements/application-account-settings-req-004.json +1 -1
  6. package/blueprints/application-account-settings/contributions/requirements/application-account-settings-req-005.json +1 -1
  7. package/blueprints/application-account-settings/contributions/requirements/application-account-settings-req-006.json +1 -1
  8. package/blueprints/application-account-settings/contributions/requirements/application-account-settings-req-007.json +1 -1
  9. package/blueprints/application-account-settings/contributions/requirements/application-account-settings-req-009.json +1 -1
  10. package/blueprints/application-account-settings/contributions/tacs/tac-2601-application-account-settings-shell.json +4 -4
  11. package/blueprints/application-account-settings/contributions/tacs/tac-2602-application-account-settings-capability-discovery.json +2 -2
  12. package/blueprints/application-account-settings/contributions/tacs/tac-2603-application-account-settings-hosted-ui-bridge.json +2 -2
  13. package/blueprints/application-account-settings/contributions/tacs/tac-2604-application-account-settings-session-store.json +7 -7
  14. package/blueprints/application-account-settings/contributions/user-stories/application-account-settings-us-25105.json +3 -15
  15. package/blueprints/application-account-settings/contributions/user-stories/application-account-settings-us-25106.json +2 -10
  16. package/blueprints/application-account-settings/contributions/user-stories/application-account-settings-us-25111.json +3 -6
  17. package/blueprints/application-account-settings/contributions/user-stories/application-account-settings-us-25112.json +4 -4
  18. package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-001.json +1 -1
  19. package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-002.json +1 -1
  20. package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-003.json +1 -1
  21. package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-004.json +1 -1
  22. package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-005.json +1 -1
  23. package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-006.json +1 -1
  24. package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-007.json +1 -1
  25. package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-008.json +1 -1
  26. package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-009.json +1 -1
  27. package/blueprints/application-admin-console/contributions/requirements/application-admin-console-req-014.json +1 -1
  28. package/blueprints/application-admin-console/contributions/tacs/tac-2201-application-admin-console-shell.json +4 -4
  29. package/blueprints/application-admin-console/contributions/tacs/tac-2202-application-admin-console-capability-discovery.json +7 -7
  30. package/blueprints/application-admin-console/contributions/tacs/tac-2203-application-admin-console-permission-matrix.json +2 -2
  31. package/blueprints/application-admin-console/contributions/tacs/tac-2204-application-admin-console-audit-view.json +2 -2
  32. package/blueprints/application-admin-console/contributions/tacs/tac-2214-application-admin-console-access-gated-signin-surface.json +3 -2
  33. package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21107.json +2 -2
  34. package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21111.json +3 -11
  35. package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21112.json +4 -4
  36. package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21815.json +2 -2
  37. package/blueprints/application-admin-console/contributions/user-stories/application-admin-console-us-21816.json +2 -2
  38. package/blueprints/application-api-rest/contributions/requirements/application-api-rest-req-001.json +1 -1
  39. package/blueprints/application-api-rest/contributions/requirements/application-api-rest-req-002.json +1 -2
  40. package/blueprints/application-api-rest/contributions/requirements/application-api-rest-req-004.json +1 -1
  41. package/blueprints/application-api-rest/contributions/requirements/application-api-rest-req-008.json +1 -1
  42. package/blueprints/application-api-rest/contributions/requirements/application-api-rest-req-016.json +1 -1
  43. package/blueprints/application-api-rest/contributions/tacs/tac-301-application-api-rest-request-pipeline.json +4 -4
  44. package/blueprints/application-api-rest/contributions/tacs/tac-302-application-api-rest-auth-middleware.json +4 -4
  45. package/blueprints/application-api-rest/contributions/tacs/tac-303-application-api-rest-contract-surface.json +4 -4
  46. package/blueprints/application-api-rest/contributions/tacs/tac-304-application-api-rest-resource-layer.json +4 -4
  47. package/blueprints/application-api-rest/contributions/tacs/tac-305-application-api-rest-observability.json +4 -4
  48. package/blueprints/application-api-rest/contributions/tacs/tac-306-application-api-rest-operability.json +4 -4
  49. package/blueprints/application-api-rest/contributions/user-stories/application-api-rest-us-2102.json +1 -1
  50. package/blueprints/application-api-rest/contributions/user-stories/application-api-rest-us-2103.json +1 -1
  51. package/blueprints/application-api-rest/contributions/user-stories/application-api-rest-us-2104.json +4 -4
  52. package/blueprints/application-api-rest/contributions/user-stories/application-api-rest-us-2105.json +2 -2
  53. package/blueprints/application-api-rest/contributions/user-stories/application-api-rest-us-2108.json +1 -1
  54. package/blueprints/application-api-rest/contributions/user-stories/application-api-rest-us-2110.json +1 -1
  55. package/blueprints/application-api-rest/contributions/user-stories/application-api-rest-us-2111.json +1 -1
  56. package/blueprints/application-api-rest/contributions/user-stories/application-api-rest-us-2118.json +1 -1
  57. package/blueprints/application-api-rest/contributions/user-stories/application-api-rest-us-2119.json +2 -2
  58. package/blueprints/application-charts/contributions/tacs/tac-1901-application-charts-render-shell.json +4 -4
  59. package/blueprints/application-charts/contributions/tacs/tac-1902-application-charts-keyboard-traversal.json +4 -4
  60. package/blueprints/application-charts/contributions/user-stories/application-charts-us-18105.json +1 -1
  61. package/blueprints/application-dashboard/contributions/tacs/tac-2001-application-dashboard-tile-grid.json +4 -4
  62. package/blueprints/application-dashboard/contributions/tacs/tac-2002-application-dashboard-filter-chrome.json +4 -4
  63. package/blueprints/application-dashboard/contributions/tacs/tac-2003-application-dashboard-export-handle.json +2 -2
  64. package/blueprints/application-dashboard/contributions/user-stories/application-dashboard-us-19106.json +1 -1
  65. package/blueprints/application-datatable/contributions/tacs/tac-1801-application-datatable-shell.json +4 -4
  66. package/blueprints/application-datatable/contributions/tacs/tac-1802-application-datatable-query-adapter.json +4 -4
  67. package/blueprints/application-datatable/contributions/tacs/tac-1803-application-datatable-selection-model.json +2 -2
  68. package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17101.json +1 -1
  69. package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17102.json +1 -1
  70. package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17103.json +1 -1
  71. package/blueprints/application-datatable/contributions/user-stories/application-datatable-us-17105.json +1 -1
  72. package/blueprints/application-empty-error-states/contributions/requirements/application-empty-error-states-req-001.json +1 -1
  73. package/blueprints/application-empty-error-states/contributions/requirements/application-empty-error-states-req-002.json +1 -1
  74. package/blueprints/application-empty-error-states/contributions/requirements/application-empty-error-states-req-003.json +1 -1
  75. package/blueprints/application-empty-error-states/contributions/requirements/application-empty-error-states-req-004.json +1 -1
  76. package/blueprints/application-empty-error-states/contributions/requirements/application-empty-error-states-req-005.json +2 -2
  77. package/blueprints/application-empty-error-states/contributions/requirements/application-empty-error-states-req-006.json +1 -1
  78. package/blueprints/application-empty-error-states/contributions/requirements/application-empty-error-states-req-007.json +2 -2
  79. package/blueprints/application-empty-error-states/contributions/tacs/tac-2301-application-empty-error-states-state-machine.json +5 -5
  80. package/blueprints/application-empty-error-states/contributions/tacs/tac-2302-application-empty-error-states-recovery-router.json +2 -2
  81. package/blueprints/application-empty-error-states/contributions/tacs/tac-2303-application-empty-error-states-offline-buffer.json +5 -5
  82. package/blueprints/application-error-handling/contributions/tacs/tac-1701-application-error-handling-boundary.json +6 -6
  83. package/blueprints/application-error-handling/contributions/tacs/tac-1702-application-error-handling-record-factory.json +4 -4
  84. package/blueprints/application-error-handling/contributions/user-stories/application-error-handling-us-16101.json +1 -1
  85. package/blueprints/application-error-handling/contributions/user-stories/application-error-handling-us-16107.json +4 -4
  86. package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-001.json +1 -1
  87. package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-002.json +1 -1
  88. package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-003.json +1 -1
  89. package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-004.json +1 -1
  90. package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-005.json +1 -1
  91. package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-006.json +2 -2
  92. package/blueprints/application-file-upload/contributions/requirements/application-file-upload-req-007.json +2 -2
  93. package/blueprints/application-file-upload/contributions/tacs/tac-2401-application-file-upload-input.json +7 -7
  94. package/blueprints/application-file-upload/contributions/tacs/tac-2402-application-file-upload-transport.json +8 -8
  95. package/blueprints/application-file-upload/contributions/tacs/tac-2403-application-file-upload-progress-announcer.json +11 -11
  96. package/blueprints/application-file-upload/contributions/user-stories/application-file-upload-us-23102.json +1 -1
  97. package/blueprints/application-file-upload/contributions/user-stories/application-file-upload-us-23105.json +1 -1
  98. package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-001.json +1 -1
  99. package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-002.json +1 -1
  100. package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-003.json +1 -1
  101. package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-004.json +1 -1
  102. package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-005.json +1 -1
  103. package/blueprints/application-forms-wizard/contributions/requirements/application-forms-wizard-req-006.json +2 -2
  104. package/blueprints/application-forms-wizard/contributions/tacs/tac-2501-application-forms-wizard-task-list.json +7 -7
  105. package/blueprints/application-forms-wizard/contributions/tacs/tac-2502-application-forms-wizard-error-summary.json +4 -4
  106. package/blueprints/application-forms-wizard/contributions/tacs/tac-2503-application-forms-wizard-draft-store.json +4 -4
  107. package/blueprints/application-forms-wizard/contributions/user-stories/application-forms-wizard-us-24101.json +1 -1
  108. package/blueprints/application-notifications-in-app/contributions/requirements/application-notifications-in-app-req-001.json +1 -1
  109. package/blueprints/application-notifications-in-app/contributions/requirements/application-notifications-in-app-req-002.json +1 -1
  110. package/blueprints/application-notifications-in-app/contributions/requirements/application-notifications-in-app-req-003.json +1 -1
  111. package/blueprints/application-notifications-in-app/contributions/requirements/application-notifications-in-app-req-004.json +1 -1
  112. package/blueprints/application-notifications-in-app/contributions/requirements/application-notifications-in-app-req-005.json +2 -2
  113. package/blueprints/application-notifications-in-app/contributions/requirements/application-notifications-in-app-req-006.json +2 -2
  114. package/blueprints/application-notifications-in-app/contributions/tacs/tac-2101-application-notifications-in-app-live-region.json +6 -6
  115. package/blueprints/application-notifications-in-app/contributions/tacs/tac-2102-application-notifications-in-app-centre.json +9 -9
  116. package/blueprints/application-notifications-in-app/contributions/tacs/tac-2103-application-notifications-in-app-preferences.json +4 -4
  117. package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20101.json +1 -1
  118. package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20102.json +1 -1
  119. package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20103.json +2 -2
  120. package/blueprints/application-notifications-in-app/contributions/user-stories/application-notifications-in-app-us-20105.json +4 -4
  121. package/blueprints/application-onboarding-tour/contributions/requirements/application-onboarding-tour-req-001.json +1 -1
  122. package/blueprints/application-onboarding-tour/contributions/requirements/application-onboarding-tour-req-002.json +1 -1
  123. package/blueprints/application-onboarding-tour/contributions/requirements/application-onboarding-tour-req-003.json +1 -1
  124. package/blueprints/application-onboarding-tour/contributions/requirements/application-onboarding-tour-req-004.json +1 -1
  125. package/blueprints/application-onboarding-tour/contributions/requirements/application-onboarding-tour-req-005.json +1 -1
  126. package/blueprints/application-onboarding-tour/contributions/requirements/application-onboarding-tour-req-006.json +1 -1
  127. package/blueprints/application-onboarding-tour/contributions/tacs/tac-2701-application-onboarding-tour-step-runner.json +4 -4
  128. package/blueprints/application-onboarding-tour/contributions/tacs/tac-2702-application-onboarding-tour-checklist-slot.json +2 -2
  129. package/blueprints/application-onboarding-tour/contributions/tacs/tac-2703-application-onboarding-tour-completion-store.json +2 -2
  130. package/blueprints/application-onboarding-tour/contributions/user-stories/application-onboarding-tour-us-26108.json +2 -2
  131. package/blueprints/application-spa/contributions/requirements/application-spa-req-004.json +1 -2
  132. package/blueprints/application-spa/contributions/requirements/application-spa-req-007.json +1 -1
  133. package/blueprints/application-spa/contributions/requirements/application-spa-req-014.json +1 -1
  134. package/blueprints/application-spa/contributions/requirements/application-spa-req-015.json +1 -1
  135. package/blueprints/application-spa/contributions/requirements/application-spa-req-017.json +1 -1
  136. package/blueprints/application-spa/contributions/requirements/application-spa-req-018.json +1 -1
  137. package/blueprints/application-spa/contributions/tacs/tac-201-application-spa-app-shell.json +4 -4
  138. package/blueprints/application-spa/contributions/tacs/tac-202-application-spa-theme-system.json +4 -4
  139. package/blueprints/application-spa/contributions/tacs/tac-207-application-spa-token-adherence-probe.json +6 -6
  140. package/blueprints/application-spa/contributions/tacs/tac-208-application-spa-icon-adherence-probe.json +6 -6
  141. package/blueprints/application-spa/contributions/tacs/tac-209-application-spa-csp-styled-adherence-probe.json +6 -6
  142. package/blueprints/application-spa/contributions/tacs/tac-210-application-spa-external-dependency-provisioning-probe.json +8 -8
  143. package/blueprints/application-spa/contributions/tacs/tac-211-application-spa-core-flow-e2e-probe.json +8 -8
  144. package/blueprints/application-spa/contributions/user-stories/application-spa-us-1101.json +2 -2
  145. package/blueprints/application-spa/contributions/user-stories/application-spa-us-1102.json +1 -1
  146. package/blueprints/application-spa/contributions/user-stories/application-spa-us-1107.json +1 -1
  147. package/blueprints/application-spa/contributions/user-stories/application-spa-us-1117.json +1 -1
  148. package/blueprints/application-spa/contributions/user-stories/application-spa-us-1129.json +4 -4
  149. package/blueprints/application-spa/contributions/user-stories/application-spa-us-1130.json +4 -4
  150. package/blueprints/application-spa/contributions/user-stories/application-spa-us-1131.json +1 -1
  151. package/blueprints/application-spa/contributions/user-stories/application-spa-us-1132.json +6 -6
  152. package/blueprints/application-spa/contributions/user-stories/application-spa-us-1133.json +5 -5
  153. package/blueprints/application-spa/contributions/user-stories/application-spa-us-1134.json +2 -2
  154. package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-001.json +1 -1
  155. package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-002.json +1 -1
  156. package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-003.json +1 -1
  157. package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-004.json +1 -1
  158. package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-005.json +1 -1
  159. package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-006.json +1 -1
  160. package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-007.json +1 -1
  161. package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-008.json +1 -1
  162. package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-009.json +1 -1
  163. package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-010.json +1 -1
  164. package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-011.json +1 -1
  165. package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-012.json +1 -1
  166. package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-013.json +1 -1
  167. package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-014.json +1 -1
  168. package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-015.json +1 -1
  169. package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-016.json +1 -1
  170. package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-017.json +1 -1
  171. package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-018.json +1 -1
  172. package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-019.json +1 -1
  173. package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-020.json +1 -1
  174. package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-021.json +1 -1
  175. package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-022.json +1 -1
  176. package/blueprints/delivery-ci-workflows/contributions/requirements/delivery-ci-workflows-req-023.json +1 -1
  177. package/blueprints/delivery-ci-workflows/contributions/tacs/tac-701-delivery-ci-workflows-gate-runner.json +6 -6
  178. package/blueprints/delivery-ci-workflows/contributions/tacs/tac-702-delivery-ci-workflows-gate-report.json +4 -4
  179. package/blueprints/delivery-ci-workflows/contributions/tacs/tac-703-delivery-ci-workflows-aggregate-report.json +4 -4
  180. package/blueprints/delivery-ci-workflows/contributions/tacs/tac-704-delivery-ci-workflows-workflow-materialiser.json +6 -6
  181. package/blueprints/delivery-ci-workflows/contributions/tacs/tac-705-delivery-ci-workflows-release-workflow.json +6 -6
  182. package/blueprints/delivery-ci-workflows/contributions/tacs/tac-706-delivery-ci-workflows-scheduled-audit.json +4 -4
  183. package/blueprints/delivery-ci-workflows/contributions/user-stories/delivery-ci-workflows-us-6101.json +1 -1
  184. package/blueprints/delivery-ci-workflows/contributions/user-stories/delivery-ci-workflows-us-6102.json +1 -1
  185. package/blueprints/delivery-ci-workflows/contributions/user-stories/delivery-ci-workflows-us-6103.json +1 -1
  186. package/blueprints/delivery-ci-workflows/contributions/user-stories/delivery-ci-workflows-us-6104.json +1 -1
  187. package/blueprints/delivery-ci-workflows/contributions/user-stories/delivery-ci-workflows-us-6106.json +1 -1
  188. package/blueprints/delivery-ci-workflows/contributions/user-stories/delivery-ci-workflows-us-6107.json +1 -1
  189. package/blueprints/delivery-ci-workflows/contributions/user-stories/delivery-ci-workflows-us-6109.json +1 -1
  190. package/blueprints/delivery-ci-workflows/contributions/user-stories/delivery-ci-workflows-us-6110.json +1 -1
  191. package/blueprints/delivery-ci-workflows/contributions/user-stories/delivery-ci-workflows-us-6111.json +1 -1
  192. package/blueprints/delivery-ci-workflows/contributions/user-stories/delivery-ci-workflows-us-6113.json +1 -1
  193. package/blueprints/delivery-ci-workflows/contributions/user-stories/delivery-ci-workflows-us-6115.json +1 -1
  194. package/blueprints/delivery-ci-workflows/contributions/user-stories/delivery-ci-workflows-us-6116.json +1 -1
  195. package/blueprints/delivery-ci-workflows/contributions/user-stories/delivery-ci-workflows-us-6117.json +1 -1
  196. package/blueprints/delivery-ci-workflows/contributions/user-stories/delivery-ci-workflows-us-6118.json +1 -1
  197. package/blueprints/delivery-ci-workflows/contributions/user-stories/delivery-ci-workflows-us-6119.json +1 -1
  198. package/blueprints/delivery-ci-workflows/contributions/user-stories/delivery-ci-workflows-us-6120.json +1 -1
  199. package/blueprints/delivery-ci-workflows/contributions/user-stories/delivery-ci-workflows-us-6122.json +1 -1
  200. package/blueprints/delivery-ci-workflows/contributions/user-stories/delivery-ci-workflows-us-6123.json +1 -1
  201. package/blueprints/delivery-ci-workflows/contributions/user-stories/delivery-ci-workflows-us-6124.json +1 -1
  202. package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-001.json +1 -1
  203. package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-002.json +1 -1
  204. package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-003.json +1 -1
  205. package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-004.json +1 -1
  206. package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-005.json +1 -1
  207. package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-006.json +1 -1
  208. package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-007.json +1 -1
  209. package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-008.json +1 -1
  210. package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-009.json +1 -1
  211. package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-010.json +1 -1
  212. package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-011.json +1 -1
  213. package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-012.json +1 -1
  214. package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-013.json +1 -1
  215. package/blueprints/deploy-cloudflare-workers/contributions/requirements/deploy-cloudflare-workers-req-014.json +1 -1
  216. package/blueprints/deploy-cloudflare-workers/contributions/tacs/tac-1301-deploy-cloudflare-workers-deploy-adapter.json +6 -6
  217. package/blueprints/deploy-cloudflare-workers/contributions/tacs/tac-1302-deploy-cloudflare-workers-wrangler-manifest.json +8 -8
  218. package/blueprints/deploy-cloudflare-workers/contributions/tacs/tac-1303-deploy-cloudflare-workers-preview-url-resolver.json +6 -6
  219. package/blueprints/deploy-cloudflare-workers/contributions/tacs/tac-1304-deploy-cloudflare-workers-promote-gate.json +8 -8
  220. package/blueprints/deploy-cloudflare-workers/contributions/tacs/tac-1305-deploy-cloudflare-workers-served-surface-verifier.json +8 -8
  221. package/blueprints/deploy-cloudflare-workers/contributions/tacs/tac-1306-deploy-cloudflare-workers-deploy-ci-workflows.json +8 -8
  222. package/blueprints/deploy-cloudflare-workers/contributions/user-stories/deploy-cloudflare-workers-us-12101.json +1 -1
  223. package/blueprints/deploy-cloudflare-workers/contributions/user-stories/deploy-cloudflare-workers-us-12102.json +2 -2
  224. package/blueprints/deploy-cloudflare-workers/contributions/user-stories/deploy-cloudflare-workers-us-12105.json +1 -1
  225. package/blueprints/deploy-cloudflare-workers/contributions/user-stories/deploy-cloudflare-workers-us-12109.json +1 -1
  226. package/blueprints/deploy-cloudflare-workers/contributions/user-stories/deploy-cloudflare-workers-us-12113.json +2 -2
  227. package/blueprints/deploy-cloudflare-workers/contributions/user-stories/deploy-cloudflare-workers-us-12114.json +1 -1
  228. package/blueprints/deploy-cloudflare-workers/contributions/user-stories/deploy-cloudflare-workers-us-12115.json +1 -1
  229. package/blueprints/deploy-hetzner-server/contributions/requirements/deploy-hetzner-server-req-001.json +1 -1
  230. package/blueprints/deploy-hetzner-server/contributions/requirements/deploy-hetzner-server-req-002.json +1 -1
  231. package/blueprints/deploy-hetzner-server/contributions/requirements/deploy-hetzner-server-req-003.json +1 -1
  232. package/blueprints/deploy-hetzner-server/contributions/requirements/deploy-hetzner-server-req-004.json +1 -1
  233. package/blueprints/deploy-hetzner-server/contributions/requirements/deploy-hetzner-server-req-005.json +1 -1
  234. package/blueprints/deploy-hetzner-server/contributions/requirements/deploy-hetzner-server-req-006.json +1 -1
  235. package/blueprints/deploy-hetzner-server/contributions/tacs/tac-3801-deploy-hetzner-server-provisioner.json +3 -2
  236. package/blueprints/deploy-hetzner-server/contributions/tacs/tac-3802-deploy-hetzner-server-manifest-schema.json +3 -2
  237. package/blueprints/deploy-hetzner-server/contributions/tacs/tac-3803-deploy-hetzner-server-cloud-init-template.json +3 -2
  238. package/blueprints/deploy-hetzner-server/contributions/tacs/tac-3804-deploy-hetzner-server-firewall-shape.json +3 -2
  239. package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37101.json +4 -4
  240. package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37102.json +3 -3
  241. package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37103.json +4 -4
  242. package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37104.json +2 -2
  243. package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37105.json +2 -2
  244. package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37106.json +3 -3
  245. package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37107.json +2 -2
  246. package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37108.json +2 -2
  247. package/blueprints/deploy-hetzner-server/contributions/user-stories/deploy-hetzner-server-us-37109.json +2 -2
  248. package/blueprints/edge-cloudflare-access/contributions/requirements/edge-cloudflare-access-req-001.json +1 -1
  249. package/blueprints/edge-cloudflare-access/contributions/requirements/edge-cloudflare-access-req-002.json +1 -1
  250. package/blueprints/edge-cloudflare-access/contributions/requirements/edge-cloudflare-access-req-003.json +1 -1
  251. package/blueprints/edge-cloudflare-access/contributions/requirements/edge-cloudflare-access-req-004.json +1 -1
  252. package/blueprints/edge-cloudflare-access/contributions/requirements/edge-cloudflare-access-req-005.json +1 -1
  253. package/blueprints/edge-cloudflare-access/contributions/requirements/edge-cloudflare-access-req-006.json +1 -1
  254. package/blueprints/edge-cloudflare-access/contributions/requirements/edge-cloudflare-access-req-007.json +1 -1
  255. package/blueprints/edge-cloudflare-access/contributions/tacs/tac-3501-edge-cloudflare-access-jwt-validator.json +6 -4
  256. package/blueprints/edge-cloudflare-access/contributions/tacs/tac-3502-edge-cloudflare-access-application-declaration.json +3 -2
  257. package/blueprints/edge-cloudflare-access/contributions/tacs/tac-3503-edge-cloudflare-access-policy-shape.json +3 -2
  258. package/blueprints/edge-cloudflare-access/contributions/tacs/tac-3504-edge-cloudflare-access-audit-sink.json +3 -2
  259. package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34101.json +1 -1
  260. package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34102.json +5 -5
  261. package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34103.json +1 -1
  262. package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34104.json +3 -3
  263. package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34105.json +1 -1
  264. package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34106.json +1 -1
  265. package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34107.json +5 -5
  266. package/blueprints/edge-cloudflare-access/contributions/user-stories/edge-cloudflare-access-us-34110.json +1 -1
  267. package/blueprints/edge-cloudflare-rate-limiting/contributions/requirements/edge-cloudflare-rate-limiting-req-001.json +1 -1
  268. package/blueprints/edge-cloudflare-rate-limiting/contributions/requirements/edge-cloudflare-rate-limiting-req-002.json +1 -1
  269. package/blueprints/edge-cloudflare-rate-limiting/contributions/requirements/edge-cloudflare-rate-limiting-req-003.json +1 -1
  270. package/blueprints/edge-cloudflare-rate-limiting/contributions/requirements/edge-cloudflare-rate-limiting-req-004.json +1 -1
  271. package/blueprints/edge-cloudflare-rate-limiting/contributions/requirements/edge-cloudflare-rate-limiting-req-005.json +1 -1
  272. package/blueprints/edge-cloudflare-rate-limiting/contributions/tacs/tac-3701-edge-cloudflare-rate-limiting-manifest-schema.json +6 -4
  273. package/blueprints/edge-cloudflare-rate-limiting/contributions/tacs/tac-3702-edge-cloudflare-rate-limiting-management-surface-doc.json +3 -2
  274. package/blueprints/edge-cloudflare-rate-limiting/contributions/tacs/tac-3703-edge-cloudflare-rate-limiting-drift-audit-runner.json +3 -2
  275. package/blueprints/edge-cloudflare-rate-limiting/contributions/user-stories/edge-cloudflare-rate-limiting-us-36101.json +2 -2
  276. package/blueprints/edge-cloudflare-rate-limiting/contributions/user-stories/edge-cloudflare-rate-limiting-us-36103.json +1 -1
  277. package/blueprints/edge-cloudflare-rate-limiting/contributions/user-stories/edge-cloudflare-rate-limiting-us-36104.json +6 -6
  278. package/blueprints/edge-cloudflare-rate-limiting/contributions/user-stories/edge-cloudflare-rate-limiting-us-36106.json +2 -2
  279. package/blueprints/edge-cloudflare-tunnel/contributions/requirements/edge-cloudflare-tunnel-req-001.json +1 -1
  280. package/blueprints/edge-cloudflare-tunnel/contributions/requirements/edge-cloudflare-tunnel-req-002.json +1 -1
  281. package/blueprints/edge-cloudflare-tunnel/contributions/requirements/edge-cloudflare-tunnel-req-003.json +1 -1
  282. package/blueprints/edge-cloudflare-tunnel/contributions/requirements/edge-cloudflare-tunnel-req-004.json +1 -1
  283. package/blueprints/edge-cloudflare-tunnel/contributions/requirements/edge-cloudflare-tunnel-req-005.json +1 -1
  284. package/blueprints/edge-cloudflare-tunnel/contributions/requirements/edge-cloudflare-tunnel-req-006.json +1 -1
  285. package/blueprints/edge-cloudflare-tunnel/contributions/requirements/edge-cloudflare-tunnel-req-007.json +1 -1
  286. package/blueprints/edge-cloudflare-tunnel/contributions/tacs/tac-4001-edge-cloudflare-tunnel-connector-shape.json +3 -2
  287. package/blueprints/edge-cloudflare-tunnel/contributions/tacs/tac-4002-edge-cloudflare-tunnel-manifest-schema.json +3 -2
  288. package/blueprints/edge-cloudflare-tunnel/contributions/tacs/tac-4003-edge-cloudflare-tunnel-access-binding.json +3 -2
  289. package/blueprints/edge-cloudflare-tunnel/contributions/tacs/tac-4004-edge-cloudflare-tunnel-zone-and-hostname-apply.json +3 -2
  290. package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39101.json +3 -3
  291. package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39102.json +2 -2
  292. package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39103.json +4 -4
  293. package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39104.json +2 -2
  294. package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39105.json +2 -2
  295. package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39106.json +5 -5
  296. package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39107.json +2 -2
  297. package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39108.json +3 -3
  298. package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39109.json +4 -4
  299. package/blueprints/edge-cloudflare-tunnel/contributions/user-stories/edge-cloudflare-tunnel-us-39110.json +3 -3
  300. package/blueprints/edge-cloudflare-turnstile/contributions/requirements/edge-cloudflare-turnstile-req-001.json +1 -1
  301. package/blueprints/edge-cloudflare-turnstile/contributions/requirements/edge-cloudflare-turnstile-req-002.json +1 -1
  302. package/blueprints/edge-cloudflare-turnstile/contributions/requirements/edge-cloudflare-turnstile-req-003.json +1 -1
  303. package/blueprints/edge-cloudflare-turnstile/contributions/requirements/edge-cloudflare-turnstile-req-004.json +1 -1
  304. package/blueprints/edge-cloudflare-turnstile/contributions/requirements/edge-cloudflare-turnstile-req-005.json +1 -1
  305. package/blueprints/edge-cloudflare-turnstile/contributions/tacs/tac-3601-edge-cloudflare-turnstile-widget-mount.json +3 -2
  306. package/blueprints/edge-cloudflare-turnstile/contributions/tacs/tac-3602-edge-cloudflare-turnstile-server-verifier.json +9 -6
  307. package/blueprints/edge-cloudflare-turnstile/contributions/tacs/tac-3603-edge-cloudflare-turnstile-magic-link-hook.json +3 -2
  308. package/blueprints/edge-cloudflare-turnstile/contributions/user-stories/edge-cloudflare-turnstile-us-35101.json +3 -3
  309. package/blueprints/edge-cloudflare-turnstile/contributions/user-stories/edge-cloudflare-turnstile-us-35102.json +4 -4
  310. package/blueprints/edge-cloudflare-turnstile/contributions/user-stories/edge-cloudflare-turnstile-us-35103.json +6 -6
  311. package/blueprints/edge-cloudflare-turnstile/contributions/user-stories/edge-cloudflare-turnstile-us-35104.json +2 -2
  312. package/blueprints/edge-cloudflare-turnstile/contributions/user-stories/edge-cloudflare-turnstile-us-35105.json +1 -1
  313. package/blueprints/email-smtp-resend/contributions/requirements/email-smtp-resend-req-001.json +1 -1
  314. package/blueprints/email-smtp-resend/contributions/requirements/email-smtp-resend-req-002.json +1 -1
  315. package/blueprints/email-smtp-resend/contributions/requirements/email-smtp-resend-req-003.json +1 -1
  316. package/blueprints/email-smtp-resend/contributions/requirements/email-smtp-resend-req-004.json +1 -1
  317. package/blueprints/email-smtp-resend/contributions/requirements/email-smtp-resend-req-005.json +1 -1
  318. package/blueprints/email-smtp-resend/contributions/requirements/email-smtp-resend-req-006.json +1 -1
  319. package/blueprints/email-smtp-resend/contributions/tacs/tac-401-email-smtp-resend-send-adapter.json +8 -8
  320. package/blueprints/email-smtp-resend/contributions/tacs/tac-402-email-smtp-resend-webhook-verifier.json +10 -10
  321. package/blueprints/email-smtp-resend/contributions/user-stories/email-smtp-resend-us-4101.json +1 -1
  322. package/blueprints/email-smtp-resend/contributions/user-stories/email-smtp-resend-us-4102.json +1 -1
  323. package/blueprints/email-smtp-resend/contributions/user-stories/email-smtp-resend-us-4103.json +1 -1
  324. package/blueprints/email-smtp-resend/contributions/user-stories/email-smtp-resend-us-4105.json +1 -1
  325. package/blueprints/email-smtp-resend/contributions/user-stories/email-smtp-resend-us-4106.json +2 -2
  326. package/blueprints/jobs-background/contributions/requirements/jobs-background-req-001.json +1 -1
  327. package/blueprints/jobs-background/contributions/requirements/jobs-background-req-002.json +1 -1
  328. package/blueprints/jobs-background/contributions/requirements/jobs-background-req-003.json +1 -1
  329. package/blueprints/jobs-background/contributions/requirements/jobs-background-req-004.json +1 -1
  330. package/blueprints/jobs-background/contributions/requirements/jobs-background-req-005.json +1 -1
  331. package/blueprints/jobs-background/contributions/requirements/jobs-background-req-006.json +1 -1
  332. package/blueprints/jobs-background/contributions/tacs/tac-3101-jobs-background-job-definition.json +4 -4
  333. package/blueprints/jobs-background/contributions/tacs/tac-3102-jobs-background-scheduler.json +6 -6
  334. package/blueprints/jobs-background/contributions/tacs/tac-3103-jobs-background-run-log.json +6 -6
  335. package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30101.json +1 -1
  336. package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30102.json +3 -3
  337. package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30103.json +1 -1
  338. package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30104.json +4 -4
  339. package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30105.json +1 -1
  340. package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30106.json +1 -1
  341. package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30107.json +1 -1
  342. package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30108.json +1 -1
  343. package/blueprints/jobs-background/contributions/user-stories/jobs-background-us-30109.json +1 -1
  344. package/blueprints/messaging-queue-cloudflare/contributions/requirements/messaging-queue-cloudflare-req-001.json +1 -1
  345. package/blueprints/messaging-queue-cloudflare/contributions/requirements/messaging-queue-cloudflare-req-002.json +1 -1
  346. package/blueprints/messaging-queue-cloudflare/contributions/requirements/messaging-queue-cloudflare-req-003.json +1 -1
  347. package/blueprints/messaging-queue-cloudflare/contributions/requirements/messaging-queue-cloudflare-req-004.json +1 -1
  348. package/blueprints/messaging-queue-cloudflare/contributions/requirements/messaging-queue-cloudflare-req-005.json +1 -1
  349. package/blueprints/messaging-queue-cloudflare/contributions/requirements/messaging-queue-cloudflare-req-006.json +1 -1
  350. package/blueprints/messaging-queue-cloudflare/contributions/tacs/tac-3001-messaging-queue-cloudflare-producer-facade.json +6 -6
  351. package/blueprints/messaging-queue-cloudflare/contributions/tacs/tac-3002-messaging-queue-cloudflare-consumer-registration.json +2 -2
  352. package/blueprints/messaging-queue-cloudflare/contributions/tacs/tac-3003-messaging-queue-cloudflare-event-sink.json +2 -2
  353. package/blueprints/messaging-queue-cloudflare/contributions/user-stories/messaging-queue-cloudflare-us-29101.json +1 -1
  354. package/blueprints/messaging-queue-cloudflare/contributions/user-stories/messaging-queue-cloudflare-us-29102.json +1 -1
  355. package/blueprints/messaging-queue-cloudflare/contributions/user-stories/messaging-queue-cloudflare-us-29103.json +1 -1
  356. package/blueprints/messaging-queue-cloudflare/contributions/user-stories/messaging-queue-cloudflare-us-29104.json +2 -2
  357. package/blueprints/messaging-queue-cloudflare/contributions/user-stories/messaging-queue-cloudflare-us-29105.json +1 -1
  358. package/blueprints/messaging-queue-cloudflare/contributions/user-stories/messaging-queue-cloudflare-us-29106.json +2 -2
  359. package/blueprints/messaging-queue-cloudflare/contributions/user-stories/messaging-queue-cloudflare-us-29107.json +1 -1
  360. package/blueprints/messaging-queue-cloudflare/contributions/user-stories/messaging-queue-cloudflare-us-29108.json +1 -1
  361. package/blueprints/object-storage-s3/contributions/requirements/object-storage-s3-req-001.json +1 -1
  362. package/blueprints/object-storage-s3/contributions/requirements/object-storage-s3-req-002.json +1 -1
  363. package/blueprints/object-storage-s3/contributions/requirements/object-storage-s3-req-003.json +1 -1
  364. package/blueprints/object-storage-s3/contributions/requirements/object-storage-s3-req-004.json +1 -1
  365. package/blueprints/object-storage-s3/contributions/requirements/object-storage-s3-req-005.json +1 -1
  366. package/blueprints/object-storage-s3/contributions/requirements/object-storage-s3-req-006.json +1 -1
  367. package/blueprints/object-storage-s3/contributions/requirements/object-storage-s3-req-101.json +1 -1
  368. package/blueprints/object-storage-s3/contributions/tacs/tac-2901-object-storage-s3-facade.json +6 -6
  369. package/blueprints/object-storage-s3/contributions/tacs/tac-2902-object-storage-s3-multipart-uploader.json +2 -2
  370. package/blueprints/object-storage-s3/contributions/tacs/tac-2903-object-storage-s3-event-sink.json +2 -2
  371. package/blueprints/object-storage-s3/contributions/tacs/tac-2904-object-storage-s3-hetzner-endpoint-helper.json +2 -2
  372. package/blueprints/object-storage-s3/contributions/user-stories/object-storage-s3-us-28101.json +1 -1
  373. package/blueprints/object-storage-s3/contributions/user-stories/object-storage-s3-us-28102.json +1 -1
  374. package/blueprints/object-storage-s3/contributions/user-stories/object-storage-s3-us-28103.json +2 -2
  375. package/blueprints/object-storage-s3/contributions/user-stories/object-storage-s3-us-28104.json +1 -1
  376. package/blueprints/object-storage-s3/contributions/user-stories/object-storage-s3-us-28105.json +2 -2
  377. package/blueprints/object-storage-s3/contributions/user-stories/object-storage-s3-us-28106.json +1 -1
  378. package/blueprints/object-storage-s3/contributions/user-stories/object-storage-s3-us-28110.json +1 -1
  379. package/blueprints/observability-essentials/contributions/requirements/observability-essentials-req-001.json +1 -1
  380. package/blueprints/observability-essentials/contributions/requirements/observability-essentials-req-002.json +1 -1
  381. package/blueprints/observability-essentials/contributions/requirements/observability-essentials-req-003.json +1 -1
  382. package/blueprints/observability-essentials/contributions/requirements/observability-essentials-req-004.json +1 -1
  383. package/blueprints/observability-essentials/contributions/requirements/observability-essentials-req-005.json +1 -1
  384. package/blueprints/observability-essentials/contributions/requirements/observability-essentials-req-006.json +1 -1
  385. package/blueprints/observability-essentials/contributions/requirements/observability-essentials-req-007.json +1 -1
  386. package/blueprints/observability-essentials/contributions/requirements/observability-essentials-req-008.json +1 -1
  387. package/blueprints/observability-essentials/contributions/requirements/observability-essentials-req-009.json +1 -1
  388. package/blueprints/observability-essentials/contributions/requirements/observability-essentials-req-010.json +1 -1
  389. package/blueprints/observability-essentials/contributions/tacs/tac-801-observability-essentials-liveness-probe.json +4 -4
  390. package/blueprints/observability-essentials/contributions/tacs/tac-802-observability-essentials-readiness-probe.json +12 -12
  391. package/blueprints/observability-essentials/contributions/tacs/tac-803-observability-essentials-status-page.json +6 -6
  392. package/blueprints/observability-essentials/contributions/tacs/tac-804-observability-essentials-notification-outcome.json +8 -8
  393. package/blueprints/observability-essentials/contributions/user-stories/observability-essentials-us-7101.json +1 -1
  394. package/blueprints/observability-essentials/contributions/user-stories/observability-essentials-us-7103.json +3 -3
  395. package/blueprints/observability-essentials/contributions/user-stories/observability-essentials-us-7106.json +2 -2
  396. package/blueprints/observability-essentials/contributions/user-stories/observability-essentials-us-7107.json +1 -1
  397. package/blueprints/observability-logging/contributions/requirements/observability-logging-req-001.json +1 -1
  398. package/blueprints/observability-logging/contributions/requirements/observability-logging-req-002.json +1 -1
  399. package/blueprints/observability-logging/contributions/requirements/observability-logging-req-003.json +1 -1
  400. package/blueprints/observability-logging/contributions/requirements/observability-logging-req-004.json +1 -1
  401. package/blueprints/observability-logging/contributions/requirements/observability-logging-req-005.json +1 -1
  402. package/blueprints/observability-logging/contributions/requirements/observability-logging-req-006.json +8 -2
  403. package/blueprints/observability-logging/contributions/tacs/tac-1601-observability-logging-logger-factory.json +6 -6
  404. package/blueprints/observability-logging/contributions/tacs/tac-1602-observability-logging-redaction-boundary.json +2 -2
  405. package/blueprints/observability-logging/contributions/user-stories/observability-logging-us-15101.json +4 -4
  406. package/blueprints/observability-logging/contributions/user-stories/observability-logging-us-15103.json +2 -2
  407. package/blueprints/observability-logging/contributions/user-stories/observability-logging-us-15104.json +2 -2
  408. package/blueprints/observability-logging/contributions/user-stories/observability-logging-us-15105.json +1 -1
  409. package/blueprints/observability-logging/contributions/user-stories/observability-logging-us-15106.json +1 -1
  410. package/blueprints/observability-logging/contributions/user-stories/observability-logging-us-15107.json +2 -2
  411. package/blueprints/observability-logging/contributions/user-stories/observability-logging-us-15108.json +1 -1
  412. package/blueprints/observability-logging/contributions/user-stories/observability-logging-us-15109.json +3 -3
  413. package/blueprints/observability-probe-endpoints/contributions/requirements/observability-probe-endpoints-req-001.json +1 -1
  414. package/blueprints/observability-probe-endpoints/contributions/requirements/observability-probe-endpoints-req-002.json +1 -1
  415. package/blueprints/observability-probe-endpoints/contributions/requirements/observability-probe-endpoints-req-003.json +1 -1
  416. package/blueprints/observability-probe-endpoints/contributions/requirements/observability-probe-endpoints-req-004.json +1 -1
  417. package/blueprints/observability-probe-endpoints/contributions/requirements/observability-probe-endpoints-req-005.json +1 -1
  418. package/blueprints/observability-probe-endpoints/contributions/requirements/observability-probe-endpoints-req-006.json +1 -1
  419. package/blueprints/observability-probe-endpoints/contributions/requirements/observability-probe-endpoints-req-007.json +1 -1
  420. package/blueprints/observability-probe-endpoints/contributions/requirements/observability-probe-endpoints-req-008.json +1 -1
  421. package/blueprints/observability-probe-endpoints/contributions/tacs/tac-1501-observability-probe-endpoints-profile-resolver.json +6 -6
  422. package/blueprints/observability-probe-endpoints/contributions/tacs/tac-1502-observability-probe-endpoints-handler-set.json +4 -4
  423. package/blueprints/observability-probe-endpoints/contributions/tacs/tac-1503-observability-probe-endpoints-listener-topology.json +6 -6
  424. package/blueprints/observability-probe-endpoints/contributions/tacs/tac-1504-observability-probe-endpoints-non-http-adapters.json +4 -4
  425. package/blueprints/observability-probe-endpoints/contributions/user-stories/observability-probe-endpoints-us-14101.json +2 -2
  426. package/blueprints/observability-probe-endpoints/contributions/user-stories/observability-probe-endpoints-us-14102.json +1 -1
  427. package/blueprints/observability-probe-endpoints/contributions/user-stories/observability-probe-endpoints-us-14105.json +3 -3
  428. package/blueprints/persistence-data-d1/contributions/requirements/persistence-data-d1-req-001.json +1 -1
  429. package/blueprints/persistence-data-d1/contributions/requirements/persistence-data-d1-req-002.json +1 -1
  430. package/blueprints/persistence-data-d1/contributions/requirements/persistence-data-d1-req-003.json +1 -1
  431. package/blueprints/persistence-data-d1/contributions/requirements/persistence-data-d1-req-004.json +1 -1
  432. package/blueprints/persistence-data-d1/contributions/requirements/persistence-data-d1-req-005.json +1 -1
  433. package/blueprints/persistence-data-d1/contributions/requirements/persistence-data-d1-req-006.json +1 -1
  434. package/blueprints/persistence-data-d1/contributions/requirements/persistence-data-d1-req-007.json +1 -1
  435. package/blueprints/persistence-data-d1/contributions/tacs/tac-1401-persistence-data-d1-facade.json +6 -6
  436. package/blueprints/persistence-data-d1/contributions/tacs/tac-1402-persistence-data-d1-migration-catalog.json +4 -4
  437. package/blueprints/persistence-data-d1/contributions/tacs/tac-1403-persistence-data-d1-deploy-gate.json +4 -4
  438. package/blueprints/persistence-data-d1/contributions/tacs/tac-1404-persistence-data-d1-recovery-runner.json +4 -4
  439. package/blueprints/persistence-data-d1/contributions/user-stories/persistence-data-d1-us-13101.json +2 -2
  440. package/blueprints/persistence-data-d1/contributions/user-stories/persistence-data-d1-us-13102.json +1 -1
  441. package/blueprints/persistence-data-d1/contributions/user-stories/persistence-data-d1-us-13107.json +2 -2
  442. package/blueprints/persistence-data-postgres/contributions/requirements/persistence-data-postgres-req-001.json +1 -1
  443. package/blueprints/persistence-data-postgres/contributions/requirements/persistence-data-postgres-req-002.json +1 -1
  444. package/blueprints/persistence-data-postgres/contributions/requirements/persistence-data-postgres-req-003.json +1 -1
  445. package/blueprints/persistence-data-postgres/contributions/requirements/persistence-data-postgres-req-004.json +1 -1
  446. package/blueprints/persistence-data-postgres/contributions/requirements/persistence-data-postgres-req-005.json +1 -1
  447. package/blueprints/persistence-data-postgres/contributions/requirements/persistence-data-postgres-req-006.json +1 -1
  448. package/blueprints/persistence-data-postgres/contributions/requirements/persistence-data-postgres-req-007.json +1 -1
  449. package/blueprints/persistence-data-postgres/contributions/tacs/tac-2801-persistence-data-postgres-facade.json +6 -6
  450. package/blueprints/persistence-data-postgres/contributions/tacs/tac-2802-persistence-data-postgres-migration-runner.json +4 -4
  451. package/blueprints/persistence-data-postgres/contributions/tacs/tac-2803-persistence-data-postgres-transaction-helper.json +2 -2
  452. package/blueprints/persistence-data-postgres/contributions/tacs/tac-2804-persistence-data-postgres-recovery-runner.json +4 -4
  453. package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27101.json +1 -1
  454. package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27102.json +4 -4
  455. package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27103.json +1 -1
  456. package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27104.json +2 -2
  457. package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27105.json +1 -1
  458. package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27106.json +1 -1
  459. package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27107.json +1 -1
  460. package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27108.json +1 -1
  461. package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27109.json +1 -1
  462. package/blueprints/persistence-data-postgres/contributions/user-stories/persistence-data-postgres-us-27110.json +1 -1
  463. package/blueprints/persistence-data-sqlite/contributions/requirements/persistence-data-sqlite-req-001.json +1 -1
  464. package/blueprints/persistence-data-sqlite/contributions/requirements/persistence-data-sqlite-req-002.json +1 -1
  465. package/blueprints/persistence-data-sqlite/contributions/requirements/persistence-data-sqlite-req-003.json +1 -1
  466. package/blueprints/persistence-data-sqlite/contributions/requirements/persistence-data-sqlite-req-004.json +1 -1
  467. package/blueprints/persistence-data-sqlite/contributions/requirements/persistence-data-sqlite-req-005.json +1 -1
  468. package/blueprints/persistence-data-sqlite/contributions/requirements/persistence-data-sqlite-req-006.json +1 -1
  469. package/blueprints/persistence-data-sqlite/contributions/requirements/persistence-data-sqlite-req-007.json +1 -1
  470. package/blueprints/persistence-data-sqlite/contributions/requirements/persistence-data-sqlite-req-008.json +1 -1
  471. package/blueprints/persistence-data-sqlite/contributions/requirements/persistence-data-sqlite-req-009.json +1 -1
  472. package/blueprints/persistence-data-sqlite/contributions/requirements/persistence-data-sqlite-req-010.json +1 -1
  473. package/blueprints/persistence-data-sqlite/contributions/requirements/persistence-data-sqlite-req-011.json +1 -1
  474. package/blueprints/persistence-data-sqlite/contributions/tacs/tac-601-persistence-data-sqlite-store.json +6 -6
  475. package/blueprints/persistence-data-sqlite/contributions/tacs/tac-602-persistence-data-sqlite-migration-runner.json +2 -2
  476. package/blueprints/persistence-data-sqlite/contributions/tacs/tac-603-persistence-data-sqlite-migration-catalog.json +4 -4
  477. package/blueprints/persistence-data-sqlite/contributions/tacs/tac-604-persistence-data-sqlite-backup-runner.json +2 -2
  478. package/blueprints/persistence-data-sqlite/contributions/user-stories/persistence-data-sqlite-us-5101.json +2 -2
  479. package/blueprints/persistence-data-sqlite/contributions/user-stories/persistence-data-sqlite-us-5103.json +1 -1
  480. package/blueprints/persistence-data-sqlite/contributions/user-stories/persistence-data-sqlite-us-5104.json +1 -1
  481. package/blueprints/persistence-data-sqlite/contributions/user-stories/persistence-data-sqlite-us-5106.json +1 -1
  482. package/blueprints/persistence-data-sqlite/contributions/user-stories/persistence-data-sqlite-us-5110.json +2 -2
  483. package/blueprints/persistence-data-sqlite/contributions/user-stories/persistence-data-sqlite-us-5111.json +1 -1
  484. package/blueprints/platform-cloudflare-cron-triggers/contributions/requirements/platform-cloudflare-cron-triggers-req-001.json +1 -1
  485. package/blueprints/platform-cloudflare-cron-triggers/contributions/requirements/platform-cloudflare-cron-triggers-req-002.json +1 -1
  486. package/blueprints/platform-cloudflare-cron-triggers/contributions/requirements/platform-cloudflare-cron-triggers-req-003.json +1 -1
  487. package/blueprints/platform-cloudflare-cron-triggers/contributions/requirements/platform-cloudflare-cron-triggers-req-004.json +1 -1
  488. package/blueprints/platform-cloudflare-cron-triggers/contributions/tacs/tac-3301-platform-cloudflare-cron-triggers-scheduled-handler.json +6 -1
  489. package/blueprints/platform-cloudflare-cron-triggers/contributions/tacs/tac-3302-platform-cloudflare-cron-triggers-expression-router.json +9 -2
  490. package/blueprints/platform-cloudflare-cron-triggers/contributions/tacs/tac-3303-platform-cloudflare-cron-triggers-event-sink.json +6 -1
  491. package/blueprints/platform-cloudflare-cron-triggers/contributions/user-stories/platform-cloudflare-cron-triggers-us-32101.json +6 -6
  492. package/blueprints/platform-cloudflare-cron-triggers/contributions/user-stories/platform-cloudflare-cron-triggers-us-32102.json +5 -5
  493. package/blueprints/platform-cloudflare-cron-triggers/contributions/user-stories/platform-cloudflare-cron-triggers-us-32103.json +3 -3
  494. package/blueprints/platform-cloudflare-cron-triggers/contributions/user-stories/platform-cloudflare-cron-triggers-us-32104.json +4 -4
  495. package/blueprints/platform-cloudflare-cron-triggers/contributions/user-stories/platform-cloudflare-cron-triggers-us-32105.json +4 -4
  496. package/blueprints/platform-cloudflare-cron-triggers/contributions/user-stories/platform-cloudflare-cron-triggers-us-32106.json +4 -4
  497. package/blueprints/platform-cloudflare-cron-triggers/contributions/user-stories/platform-cloudflare-cron-triggers-us-32107.json +3 -3
  498. package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-001.json +1 -1
  499. package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-002.json +1 -1
  500. package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-003.json +1 -1
  501. package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-004.json +1 -1
  502. package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-005.json +1 -1
  503. package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-006.json +1 -1
  504. package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-007.json +1 -1
  505. package/blueprints/platform-cloudflare-durable-objects/contributions/requirements/platform-cloudflare-durable-objects-req-008.json +1 -1
  506. package/blueprints/platform-cloudflare-durable-objects/contributions/tacs/tac-3401-platform-cloudflare-durable-objects-namespace-facade.json +6 -4
  507. package/blueprints/platform-cloudflare-durable-objects/contributions/tacs/tac-3402-platform-cloudflare-durable-objects-single-cell-shape.json +6 -4
  508. package/blueprints/platform-cloudflare-durable-objects/contributions/tacs/tac-3403-platform-cloudflare-durable-objects-alarm-handler.json +6 -4
  509. package/blueprints/platform-cloudflare-durable-objects/contributions/tacs/tac-3404-platform-cloudflare-durable-objects-websocket-hub.json +6 -4
  510. package/blueprints/platform-cloudflare-durable-objects/contributions/tacs/tac-3405-platform-cloudflare-durable-objects-event-sink.json +3 -2
  511. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33101.json +5 -5
  512. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33102.json +4 -4
  513. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33103.json +5 -5
  514. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33104.json +5 -5
  515. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33105.json +5 -5
  516. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33106.json +4 -4
  517. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33107.json +3 -3
  518. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33108.json +5 -5
  519. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33109.json +3 -3
  520. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33110.json +4 -4
  521. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33111.json +3 -3
  522. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33112.json +3 -3
  523. package/blueprints/platform-cloudflare-durable-objects/contributions/user-stories/platform-cloudflare-durable-objects-us-33113.json +5 -5
  524. package/blueprints/platform-cloudflare-kv/contributions/requirements/platform-cloudflare-kv-req-001.json +1 -1
  525. package/blueprints/platform-cloudflare-kv/contributions/requirements/platform-cloudflare-kv-req-002.json +1 -1
  526. package/blueprints/platform-cloudflare-kv/contributions/requirements/platform-cloudflare-kv-req-003.json +1 -1
  527. package/blueprints/platform-cloudflare-kv/contributions/requirements/platform-cloudflare-kv-req-004.json +1 -1
  528. package/blueprints/platform-cloudflare-kv/contributions/requirements/platform-cloudflare-kv-req-005.json +1 -1
  529. package/blueprints/platform-cloudflare-kv/contributions/requirements/platform-cloudflare-kv-req-006.json +1 -1
  530. package/blueprints/platform-cloudflare-kv/contributions/requirements/platform-cloudflare-kv-req-007.json +1 -1
  531. package/blueprints/platform-cloudflare-kv/contributions/tacs/tac-3201-platform-cloudflare-kv-facade.json +3 -2
  532. package/blueprints/platform-cloudflare-kv/contributions/tacs/tac-3202-platform-cloudflare-kv-cache-aside.json +3 -2
  533. package/blueprints/platform-cloudflare-kv/contributions/tacs/tac-3203-platform-cloudflare-kv-event-sink.json +3 -2
  534. package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31101.json +4 -4
  535. package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31102.json +3 -3
  536. package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31103.json +4 -4
  537. package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31104.json +4 -4
  538. package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31105.json +4 -4
  539. package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31106.json +3 -3
  540. package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31107.json +3 -3
  541. package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31108.json +3 -3
  542. package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31109.json +4 -4
  543. package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31110.json +5 -5
  544. package/blueprints/platform-cloudflare-kv/contributions/user-stories/platform-cloudflare-kv-us-31111.json +5 -5
  545. package/blueprints/platform-docker-compose-host/contributions/requirements/platform-docker-compose-host-req-001.json +1 -1
  546. package/blueprints/platform-docker-compose-host/contributions/requirements/platform-docker-compose-host-req-002.json +1 -1
  547. package/blueprints/platform-docker-compose-host/contributions/requirements/platform-docker-compose-host-req-003.json +1 -1
  548. package/blueprints/platform-docker-compose-host/contributions/requirements/platform-docker-compose-host-req-004.json +1 -1
  549. package/blueprints/platform-docker-compose-host/contributions/requirements/platform-docker-compose-host-req-005.json +1 -1
  550. package/blueprints/platform-docker-compose-host/contributions/requirements/platform-docker-compose-host-req-006.json +1 -1
  551. package/blueprints/platform-docker-compose-host/contributions/requirements/platform-docker-compose-host-req-007.json +1 -1
  552. package/blueprints/platform-docker-compose-host/contributions/tacs/tac-3901-platform-docker-compose-host-compose-layout.json +3 -2
  553. package/blueprints/platform-docker-compose-host/contributions/tacs/tac-3902-platform-docker-compose-host-secrets-mount.json +3 -2
  554. package/blueprints/platform-docker-compose-host/contributions/tacs/tac-3903-platform-docker-compose-host-healthcheck-lint.json +3 -2
  555. package/blueprints/platform-docker-compose-host/contributions/tacs/tac-3904-platform-docker-compose-host-reverse-proxy-artefact.json +3 -2
  556. package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38101.json +5 -5
  557. package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38102.json +4 -4
  558. package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38103.json +4 -4
  559. package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38104.json +4 -4
  560. package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38105.json +3 -3
  561. package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38106.json +3 -3
  562. package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38107.json +3 -3
  563. package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38108.json +3 -3
  564. package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38109.json +3 -3
  565. package/blueprints/platform-docker-compose-host/contributions/user-stories/platform-docker-compose-host-us-38110.json +3 -3
  566. package/blueprints/security-auth-clerk/contributions/requirements/security-auth-clerk-req-001.json +1 -1
  567. package/blueprints/security-auth-clerk/contributions/requirements/security-auth-clerk-req-002.json +1 -1
  568. package/blueprints/security-auth-clerk/contributions/requirements/security-auth-clerk-req-003.json +1 -1
  569. package/blueprints/security-auth-clerk/contributions/requirements/security-auth-clerk-req-004.json +1 -1
  570. package/blueprints/security-auth-clerk/contributions/requirements/security-auth-clerk-req-006.json +1 -1
  571. package/blueprints/security-auth-clerk/contributions/requirements/security-auth-clerk-req-010.json +1 -1
  572. package/blueprints/security-auth-clerk/contributions/requirements/security-auth-clerk-req-011.json +1 -1
  573. package/blueprints/security-auth-clerk/contributions/tacs/tac-1001-security-auth-clerk-middleware.json +6 -6
  574. package/blueprints/security-auth-clerk/contributions/tacs/tac-1002-security-auth-clerk-authorisation-adapter.json +8 -3
  575. package/blueprints/security-auth-clerk/contributions/tacs/tac-1003-security-auth-clerk-session-verifier.json +8 -8
  576. package/blueprints/security-auth-clerk/contributions/user-stories/security-auth-clerk-us-9102.json +1 -1
  577. package/blueprints/security-auth-clerk/contributions/user-stories/security-auth-clerk-us-9108.json +1 -1
  578. package/blueprints/security-auth-clerk/contributions/user-stories/security-auth-clerk-us-9112.json +6 -6
  579. package/blueprints/security-auth-clerk/contributions/user-stories/security-auth-clerk-us-9113.json +6 -6
  580. package/blueprints/security-auth-keycloak/contributions/requirements/security-auth-keycloak-req-002.json +1 -1
  581. package/blueprints/security-auth-keycloak/contributions/requirements/security-auth-keycloak-req-003.json +1 -1
  582. package/blueprints/security-auth-keycloak/contributions/requirements/security-auth-keycloak-req-004.json +1 -1
  583. package/blueprints/security-auth-keycloak/contributions/requirements/security-auth-keycloak-req-005.json +1 -1
  584. package/blueprints/security-auth-keycloak/contributions/requirements/security-auth-keycloak-req-006.json +1 -1
  585. package/blueprints/security-auth-keycloak/contributions/requirements/security-auth-keycloak-req-011.json +1 -1
  586. package/blueprints/security-auth-keycloak/contributions/requirements/security-auth-keycloak-req-013.json +1 -1
  587. package/blueprints/security-auth-keycloak/contributions/requirements/security-auth-keycloak-req-014.json +1 -1
  588. package/blueprints/security-auth-keycloak/contributions/requirements/security-auth-keycloak-req-015.json +1 -1
  589. package/blueprints/security-auth-keycloak/contributions/requirements/security-auth-keycloak-req-016.json +1 -1
  590. package/blueprints/security-auth-keycloak/contributions/requirements/security-auth-keycloak-req-017.json +1 -1
  591. package/blueprints/security-auth-keycloak/contributions/requirements/security-auth-keycloak-req-018.json +1 -1
  592. package/blueprints/security-auth-keycloak/contributions/requirements/security-auth-keycloak-req-019.json +1 -1
  593. package/blueprints/security-auth-keycloak/contributions/tacs/tac-1201-security-auth-keycloak-discovery-client.json +10 -10
  594. package/blueprints/security-auth-keycloak/contributions/tacs/tac-1202-security-auth-keycloak-jwt-verifier.json +8 -8
  595. package/blueprints/security-auth-keycloak/contributions/tacs/tac-1203-security-auth-keycloak-introspection-client.json +8 -8
  596. package/blueprints/security-auth-keycloak/contributions/tacs/tac-1204-security-auth-keycloak-provider-router.json +6 -6
  597. package/blueprints/security-auth-keycloak/contributions/tacs/tac-1205-security-auth-keycloak-role-adapter.json +4 -4
  598. package/blueprints/security-auth-keycloak/contributions/user-stories/security-auth-keycloak-us-11102.json +1 -1
  599. package/blueprints/security-auth-keycloak/contributions/user-stories/security-auth-keycloak-us-11103.json +2 -2
  600. package/blueprints/security-auth-keycloak/contributions/user-stories/security-auth-keycloak-us-11104.json +1 -1
  601. package/blueprints/security-auth-keycloak/contributions/user-stories/security-auth-keycloak-us-11106.json +3 -3
  602. package/blueprints/security-auth-keycloak/contributions/user-stories/security-auth-keycloak-us-11111.json +2 -2
  603. package/blueprints/security-auth-keycloak/contributions/user-stories/security-auth-keycloak-us-11114.json +1 -1
  604. package/blueprints/security-auth-keycloak/contributions/user-stories/security-auth-keycloak-us-11115.json +5 -5
  605. package/blueprints/security-auth-keycloak/contributions/user-stories/security-auth-keycloak-us-11116.json +7 -7
  606. package/blueprints/security-auth-keycloak/contributions/user-stories/security-auth-keycloak-us-11117.json +7 -7
  607. package/blueprints/security-auth-keycloak/contributions/user-stories/security-auth-keycloak-us-11118.json +7 -7
  608. package/blueprints/security-auth-keycloak/contributions/user-stories/security-auth-keycloak-us-11119.json +7 -7
  609. package/blueprints/security-auth-keycloak/contributions/user-stories/security-auth-keycloak-us-11120.json +6 -6
  610. package/blueprints/security-auth-magic-link/contributions/requirements/security-auth-magic-link-req-002.json +1 -1
  611. package/blueprints/security-auth-magic-link/contributions/requirements/security-auth-magic-link-req-003.json +1 -1
  612. package/blueprints/security-auth-magic-link/contributions/requirements/security-auth-magic-link-req-004.json +1 -1
  613. package/blueprints/security-auth-magic-link/contributions/requirements/security-auth-magic-link-req-005.json +1 -1
  614. package/blueprints/security-auth-magic-link/contributions/requirements/security-auth-magic-link-req-008.json +1 -1
  615. package/blueprints/security-auth-magic-link/contributions/requirements/security-auth-magic-link-req-009.json +1 -1
  616. package/blueprints/security-auth-magic-link/contributions/requirements/security-auth-magic-link-req-010.json +1 -1
  617. package/blueprints/security-auth-magic-link/contributions/requirements/security-auth-magic-link-req-011.json +1 -1
  618. package/blueprints/security-auth-magic-link/contributions/tacs/tac-501-security-auth-magic-link-manager.json +6 -6
  619. package/blueprints/security-auth-magic-link/contributions/tacs/tac-502-security-auth-magic-link-session-manager.json +6 -6
  620. package/blueprints/security-auth-magic-link/contributions/tacs/tac-503-security-auth-magic-link-login-routes.json +10 -10
  621. package/blueprints/security-auth-magic-link/contributions/tacs/tac-504-security-auth-magic-link-email-delivery-adapter.json +2 -2
  622. package/blueprints/security-auth-magic-link/contributions/tacs/tac-505-security-auth-magic-link-principal-registry.json +2 -2
  623. package/blueprints/security-auth-magic-link/contributions/user-stories/security-auth-magic-link-us-3111.json +2 -2
  624. package/blueprints/security-auth-oauth2/contributions/requirements/security-auth-oauth2-req-002.json +1 -1
  625. package/blueprints/security-auth-oauth2/contributions/requirements/security-auth-oauth2-req-003.json +1 -1
  626. package/blueprints/security-auth-oauth2/contributions/requirements/security-auth-oauth2-req-005.json +1 -1
  627. package/blueprints/security-auth-oauth2/contributions/requirements/security-auth-oauth2-req-006.json +1 -1
  628. package/blueprints/security-auth-oauth2/contributions/requirements/security-auth-oauth2-req-008.json +1 -1
  629. package/blueprints/security-auth-oauth2/contributions/requirements/security-auth-oauth2-req-009.json +1 -1
  630. package/blueprints/security-auth-oauth2/contributions/requirements/security-auth-oauth2-req-011.json +1 -1
  631. package/blueprints/security-auth-oauth2/contributions/requirements/security-auth-oauth2-req-012.json +1 -1
  632. package/blueprints/security-auth-oauth2/contributions/requirements/security-auth-oauth2-req-013.json +1 -1
  633. package/blueprints/security-auth-oauth2/contributions/tacs/tac-1101-security-auth-oauth2-flow-controller.json +24 -14
  634. package/blueprints/security-auth-oauth2/contributions/tacs/tac-1102-security-auth-oauth2-provider-adapter.json +4 -4
  635. package/blueprints/security-auth-oauth2/contributions/tacs/tac-1103-security-auth-oauth2-session-bridge.json +10 -10
  636. package/blueprints/security-auth-oauth2/contributions/tacs/tac-1104-security-auth-oauth2-provider-selector.json +8 -3
  637. package/blueprints/security-auth-oauth2/contributions/user-stories/security-auth-oauth2-us-10111.json +1 -1
  638. package/blueprints/security-auth-oauth2/contributions/user-stories/security-auth-oauth2-us-10112.json +1 -1
  639. package/blueprints/security-auth-oauth2/contributions/user-stories/security-auth-oauth2-us-10114.json +5 -5
  640. package/blueprints/security-secrets-management/contributions/requirements/security-secrets-management-req-001.json +1 -1
  641. package/blueprints/security-secrets-management/contributions/requirements/security-secrets-management-req-002.json +1 -1
  642. package/blueprints/security-secrets-management/contributions/requirements/security-secrets-management-req-003.json +1 -1
  643. package/blueprints/security-secrets-management/contributions/requirements/security-secrets-management-req-004.json +1 -1
  644. package/blueprints/security-secrets-management/contributions/requirements/security-secrets-management-req-005.json +1 -1
  645. package/blueprints/security-secrets-management/contributions/requirements/security-secrets-management-req-006.json +1 -1
  646. package/blueprints/security-secrets-management/contributions/requirements/security-secrets-management-req-007.json +1 -1
  647. package/blueprints/security-secrets-management/contributions/requirements/security-secrets-management-req-008.json +1 -1
  648. package/blueprints/security-secrets-management/contributions/requirements/security-secrets-management-req-009.json +1 -1
  649. package/blueprints/security-secrets-management/contributions/tacs/tac-901-security-secrets-management-manager-client.json +8 -8
  650. package/blueprints/security-secrets-management/contributions/tacs/tac-902-security-secrets-management-manifest.json +4 -4
  651. package/blueprints/security-secrets-management/contributions/tacs/tac-903-security-secrets-management-env-reflector.json +4 -4
  652. package/blueprints/security-secrets-management/contributions/tacs/tac-904-security-secrets-management-rotation-gate.json +8 -8
  653. package/blueprints/security-secrets-management/contributions/tacs/tac-905-security-secrets-management-agent-cli.json +4 -4
  654. package/fixtures/canary-manifest.json +9 -9
  655. package/guidance/define-draft-shapes.md +15 -10
  656. package/guidance/define-litmus.md +102 -0
  657. package/guidance/manifest.json +2 -1
  658. package/package.json +1 -1
  659. package/rcf/adrs/adr-4131-gates-bite-ack-recorded-override.json +30 -0
  660. package/rcf/adrs/adr-4137-standalone-theme-persistence.json +30 -0
  661. package/rcf/adrs/adr-4138-tree-wide-checks-before-scope-shortcircuit.json +35 -0
  662. package/rcf/code-nodes/cn-753.json +19 -0
  663. package/rcf/code-nodes/cn-754.json +17 -0
  664. package/rcf/code-nodes/cn-755.json +14 -0
  665. package/rcf/code-nodes/cn-756.json +15 -0
  666. package/rcf/code-nodes/cn-757.json +21 -0
  667. package/rcf/code-nodes/cn-758.json +16 -0
  668. package/rcf/code-nodes/cn-759.json +21 -0
  669. package/rcf/code-nodes/cn-760.json +19 -0
  670. package/rcf/code-nodes/cn-761.json +16 -0
  671. package/rcf/code-nodes/cn-762.json +18 -0
  672. package/rcf/code-nodes/cn-763.json +18 -0
  673. package/rcf/code-nodes/cn-764.json +15 -0
  674. package/rcf/code-nodes/cn-765.json +23 -0
  675. package/rcf/code-nodes/cn-766.json +17 -0
  676. package/rcf/code-nodes/cn-767.json +17 -0
  677. package/rcf/code-nodes/cn-768.json +19 -0
  678. package/rcf/code-nodes/cn-769.json +17 -0
  679. package/rcf/code-nodes/cn-770.json +18 -0
  680. package/rcf/code-nodes/cn-771.json +14 -0
  681. package/rcf/code-nodes/cn-772.json +14 -0
  682. package/rcf/code-nodes/cn-773.json +16 -0
  683. package/rcf/code-nodes/cn-774.json +20 -0
  684. package/rcf/code-nodes/cn-775.json +15 -0
  685. package/rcf/code-nodes/cn-776.json +17 -0
  686. package/rcf/code-nodes/cn-777.json +21 -0
  687. package/rcf/fbs/fbs-202.json +85 -9
  688. package/rcf/fbs/fbs-203.json +12 -4
  689. package/rcf/requirements/req-002.json +2 -2
  690. package/rcf/requirements/req-173.json +2 -2
  691. package/rcf/requirements/req-174.json +2 -2
  692. package/rcf/requirements/req-175.json +2 -2
  693. package/rcf/requirements/req-177.json +31 -0
  694. package/rcf/requirements/req-178.json +31 -0
  695. package/rcf/requirements/req-179.json +31 -0
  696. package/rcf/tacs/tac-001.json +7 -7
  697. package/rcf/tacs/tac-002.json +23 -23
  698. package/rcf/tacs/tac-003.json +5 -5
  699. package/rcf/tacs/tac-004.json +9 -9
  700. package/rcf/tacs/tac-005.json +7 -7
  701. package/rcf/tacs/tac-006.json +21 -21
  702. package/rcf/tacs/tac-007.json +7 -7
  703. package/rcf/tacs/tac-008.json +7 -7
  704. package/rcf/tacs/tac-4101-feedback-cli.json +5 -5
  705. package/rcf/tacs/tac-4102-feedback-store.json +9 -9
  706. package/rcf/tacs/tac-4103-feedback-redact.json +5 -5
  707. package/rcf/tacs/tac-4104-feedback-fingerprint.json +3 -3
  708. package/rcf/tacs/tac-4105-feedback-render.json +7 -7
  709. package/rcf/tacs/tac-4106-feedback-destination.json +5 -5
  710. package/rcf/tacs/tac-4107-feedback-gh.json +7 -7
  711. package/rcf/tacs/tac-4108-feedback-hook.json +7 -7
  712. package/rcf/tacs/tac-4121-define-ledgers.json +3 -2
  713. package/rcf/tacs/tac-4122-define-gates.json +36 -3
  714. package/rcf/tacs/tac-4123-define-readiness.json +29 -3
  715. package/rcf/tacs/tac-4125-build-bundle-refuse-override-skip.json +43 -0
  716. package/rcf/tacs/tac-4126-define-validate-findings.json +32 -0
  717. package/rcf/tacs/tac-4128-define-guidance.json +8 -2
  718. package/rcf/tacs/tac-4129-define-questions.json +3 -3
  719. package/rcf/tacs/tac-4134-wespa-host-fixture.json +9 -9
  720. package/rcf/test-suites/ts-007.json +1 -1
  721. package/rcf/test-suites/ts-215.json +64 -1
  722. package/rcf/test-suites/ts-216.json +18 -2
  723. package/rcf/test-suites/ts-219.json +10 -2
  724. package/rcf/test-suites/ts-220.json +18 -2
  725. package/rcf/test-suites/ts-222.json +4 -4
  726. package/rcf/test-suites/ts-225.json +10 -2
  727. package/rcf/test-suites/ts-228.json +4 -4
  728. package/rcf/test-suites/ts-229.json +49 -3
  729. package/rcf/test-suites/ts-230.json +100 -0
  730. package/rcf/test-suites/ts-231.json +119 -0
  731. package/rcf/test-suites/ts-232.json +109 -0
  732. package/rcf/test-suites/ts-233.json +61 -0
  733. package/rcf/test-suites/ts-234.json +53 -0
  734. package/rcf/test-suites/ts-235.json +53 -0
  735. package/rcf/test-suites/ts-236.json +44 -0
  736. package/rcf/user-stories/us-17302.json +36 -1
  737. package/rcf/user-stories/us-17401.json +11 -1
  738. package/rcf/user-stories/us-17402.json +6 -1
  739. package/rcf/user-stories/us-17403.json +11 -1
  740. package/rcf/user-stories/us-17404.json +66 -0
  741. package/rcf/user-stories/us-17405.json +66 -0
  742. package/rcf/user-stories/us-17406.json +51 -0
  743. package/rcf/user-stories/us-17503.json +2 -2
  744. package/rcf/user-stories/us-17504.json +46 -0
  745. package/rcf/user-stories/us-17702.json +51 -0
  746. package/rcf/user-stories/us-17802.json +40 -0
  747. package/rcf/user-stories/us-17902.json +46 -0
  748. package/rcf/user-stories/us-205.json +6 -1
  749. package/rcf/user-stories/us-206.json +25 -4
  750. package/rcf/user-stories/us-207.json +36 -0
  751. package/releases/releases.yaml +21 -1
  752. package/src/blueprint/consistency-lint.js +72 -3
  753. package/src/cli/build.js +206 -3
  754. package/src/cli/create.js +22 -2
  755. package/src/cli/freeze.js +68 -18
  756. package/src/cli/ledger.js +96 -4
  757. package/src/cli/readiness.js +151 -36
  758. package/src/cli/validate.js +8 -0
  759. package/src/core/errors/index.js +7 -1
  760. package/src/core/store/writer.js +181 -13
  761. package/src/define/concern-catalogue.js +130 -0
  762. package/src/define/freeze-record.js +74 -0
  763. package/src/define/ledgers.js +86 -7
  764. package/src/define/probe-runner.js +55 -0
  765. package/src/define/validate-findings.js +256 -0
  766. package/src/mcp/tools.js +1 -1
  767. package/src/query/gates.js +1235 -67
  768. package/src/query/index.js +6 -1
  769. package/src/query/readiness.js +179 -2
  770. package/src/query/refuse-on-admissibility.js +137 -4
  771. package/src/ruleset/ruleset.json +35 -0
  772. package/src/view/html-page.js +14 -2
  773. package/src/view/page-init.js +149 -8
  774. package/src/view/style.css +97 -18
  775. package/src/view/view-index.js +22 -0
@@ -46,6 +46,7 @@
46
46
  import { computeQueue } from '../build/queue.js';
47
47
  import { isOptedOut } from '../req-baseline/opt-out.js';
48
48
  import { BRIEF_KINDS, parseResolvedBy } from '../define/ledgers.js';
49
+ import { applicableConcernsForShapes } from '../define/concern-catalogue.js';
49
50
 
50
51
  /** Canonical stage order (proposal §3.2). */
51
52
  export const STAGE_ORDER = /** @type {const} */ (['D1', 'D2', 'D3', 'D4', 'D5', 'D6', 'D7', 'D8']);
@@ -113,26 +114,37 @@ export const CHECK_PERSONA = /** @type {const} */ ({
113
114
  'brief:kinds': 'productOwner',
114
115
  'brief:openQuestions': 'productOwner',
115
116
  'brief:profile': 'productOwner',
116
- // D2 Skeleton: resolvedBy + reqIntent are PO; reqShape, tadPersistence, deployAdr are engineer.
117
+ // D2 Skeleton: resolvedBy + reqIntent are PO; reqShape, tadPersistence, deployAdr, standardsCited are engineer.
117
118
  'skeleton:resolvedBy': 'productOwner',
118
119
  'skeleton:reqIntent': 'productOwner',
119
120
  'skeleton:reqShape': 'engineer',
120
121
  'skeleton:tadPersistence': 'engineer',
121
122
  'skeleton:deployAdr': 'engineer',
123
+ 'skeleton:standardsCited': 'engineer',
122
124
  // D3 Shapes: every check is engineer (shapes are the engineer's first act after hand-over).
123
125
  'shapes:tacHasInterface': 'engineer',
124
126
  'shapes:kindVocabulary': 'engineer',
125
127
  'shapes:draftSettled': 'engineer',
126
- // D4 Stories: reqHasUs is PO ("what does someone do with this?"); the floors are engineer.
128
+ 'shapes:templateMarkers': 'engineer',
129
+ 'shapes:entityJoin': 'engineer',
130
+ 'shapes:pathsResolve': 'engineer',
131
+ // D4 Stories: reqHasUs is PO ("what does someone do with this?"); the floors, closed sets and ownerRef resolution are engineer.
127
132
  'stories:reqHasUs': 'productOwner',
128
133
  'stories:usFloors': 'engineer',
129
- // D5 Crosscut: TAD + concern-ledger content is engineering.
134
+ 'stories:closedSets': 'engineer',
135
+ 'stories:ownerRefResolves': 'engineer',
136
+ // D5 Crosscut: TAD + concern-ledger content and the catalogue walk are engineering.
130
137
  'crosscut:securityArchitecture': 'engineer',
131
138
  'crosscut:operationalConcerns': 'engineer',
132
139
  'crosscut:concernsResolved': 'engineer',
133
- // D6 Consistency: schema validity and probes are engineer.
140
+ 'crosscut:catalogue': 'engineer',
141
+ // D6 Consistency: schema validity, probes and the four scans are engineer.
134
142
  'consistency:validateClean': 'engineer',
135
143
  'consistency:probeCount': 'engineer',
144
+ 'consistency:contradictions': 'engineer',
145
+ 'consistency:unsatisfiable': 'engineer',
146
+ 'consistency:duplicates': 'engineer',
147
+ 'consistency:orphanInterfaces': 'engineer',
136
148
  // D7 Decisions: enumeration is PO (the PO answers or lets the default stand);
137
149
  // zero-open is the engineer's hand-over condition.
138
150
  'decisions:wellFormed': 'productOwner',
@@ -161,16 +173,27 @@ export const CHECK_QUESTION = /** @type {const} */ ({
161
173
  'skeleton:reqShape': 'Every requirement in scope carries a shape classification.',
162
174
  'skeleton:tadPersistence': 'TAD data architecture lists dataStores and coreEntities for persistence REQs.',
163
175
  'skeleton:deployAdr': 'Exactly one Deploy target or Deploy deferral ADR exists.',
176
+ 'skeleton:standardsCited': 'Every registered standards pack is cited, applied or waived.',
164
177
  'shapes:tacHasInterface': 'Every TAC in scope has at least one interface.',
165
178
  'shapes:kindVocabulary': 'Every interface kind is in the closed vocabulary.',
166
179
  'shapes:draftSettled': 'Every draft interface has been settled (the [draft] marker is removed).',
180
+ 'shapes:templateMarkers': 'Every interface description carries the per-kind markers (recordShape fields:, httpRoute method/path/request/response/errors, and so on).',
181
+ 'shapes:entityJoin': 'Every core entity is named by exactly one recordShape.',
182
+ 'shapes:pathsResolve': 'Every path: token in an interface description resolves on disk or the description is authoredAt D3.',
167
183
  'stories:reqHasUs': 'What does someone do with this requirement?',
168
184
  'stories:usFloors': 'Every story in scope meets the class, tacIds and testability floors.',
185
+ 'stories:closedSets': 'Every acceptance criterion that invites a set of values names the set or points to an owner.',
186
+ 'stories:ownerRefResolves': 'Every ownerRef on an acceptance criterion resolves to an interface on the owning TAC.',
169
187
  'crosscut:securityArchitecture': 'TAD.securityArchitecture is present when an auth or httpApi REQ exists.',
170
188
  'crosscut:operationalConcerns': 'TAD.operationalConcerns is present when a deployed-scope AC exists.',
171
189
  'crosscut:concernsResolved': 'Every concern-ledger entry on a REQ in scope is applied or waived.',
190
+ 'crosscut:catalogue': 'Every applicable crosscut concern for a REQ in scope has a concern-ledger entry applied or waived.',
172
191
  'consistency:validateClean': 'Validate is clean tree-wide.',
173
192
  'consistency:probeCount': 'Zero open probe-ledger entries.',
193
+ 'consistency:contradictions': 'No two acceptance criteria on one story share a when clause with a negated then.',
194
+ 'consistency:unsatisfiable': 'Every then names a field some recordShape defines.',
195
+ 'consistency:duplicates': 'No two acceptance criteria across stories share an identical description.',
196
+ 'consistency:orphanInterfaces': 'Every interface is reached by an AC ownerRef or a REQ deliveredBy.',
174
197
  'decisions:wellFormed': 'Every decision is enumerated (question, two or more options, a default).',
175
198
  'decisions:allAnswered': 'Zero decisions are open.',
176
199
  'freeze:priorGates': 'Every prior stage passed or is acknowledged at the current hash.',
@@ -280,6 +303,146 @@ export function parseCoreEntityDraft(entity) {
280
303
  return hasDraftMarker(/** @type {any} */ (entity).description);
281
304
  }
282
305
 
306
+ /**
307
+ * Per-kind required marker tokens on `interfaces[].description` for
308
+ * the `shapes:templateMarkers` D3 bite check (ADR-4131, spec section 4
309
+ * row "D3 template parser"). A marker is "present" when a line of the
310
+ * description matches the marker's own regex: a `<name>:` prefix for
311
+ * `fields:`, `instances:`, `payload:`, `usage:` and `format:`; a
312
+ * `method`, `path`, `request`, `response`, `errors` or `protocol`
313
+ * token on an httpRoute, uiRoute or port (word-bounded, case-sensitive,
314
+ * tolerating a trailing colon or whitespace); `other` requires a
315
+ * non-empty description after the optional `[draft]` prefix (its
316
+ * "note"). The regexes are deliberately permissive so a plain
317
+ * `method: POST` and a bullet list `- method: POST` both qualify, and
318
+ * so a `[draft]` prefix never masks the marker scan.
319
+ */
320
+ const INTERFACE_TEMPLATE_MARKERS = /** @type {const} */ ({
321
+ recordShape: [{ name: 'fields', re: /(^|\n)\s*(?:[-*]\s*)?fields\s*:/ }],
322
+ httpRoute: [
323
+ { name: 'method', re: /(^|\n|\s)method\s*[:=]/ },
324
+ { name: 'path', re: /(^|\n|\s)path\s*[:=]/ },
325
+ { name: 'request', re: /(^|\n|\s)request\s*[:=]/ },
326
+ { name: 'response', re: /(^|\n|\s)response\s*[:=]/ },
327
+ { name: 'errors', re: /(^|\n|\s)errors\s*[:=]/ },
328
+ ],
329
+ fixture: [{ name: 'instances', re: /(^|\n)\s*(?:[-*]\s*)?instances\s*:/ }],
330
+ event: [{ name: 'payload', re: /(^|\n)\s*(?:[-*]\s*)?payload\s*:/ }],
331
+ cliCommand: [{ name: 'usage', re: /(^|\n)\s*(?:[-*]\s*)?usage\s*:/ }],
332
+ uiRoute: [{ name: 'path', re: /(^|\n|\s)path\s*[:=]/ }],
333
+ port: [{ name: 'protocol', re: /(^|\n|\s)protocol\s*[:=]/ }],
334
+ fileFormat: [{ name: 'format', re: /(^|\n)\s*(?:[-*]\s*)?format\s*:/ }],
335
+ other: [],
336
+ });
337
+
338
+ /**
339
+ * Strip a leading `[draft]` marker from a description so the marker
340
+ * scan sees the real text underneath. Pure.
341
+ *
342
+ * @param {string} desc
343
+ * @returns {string}
344
+ */
345
+ function stripDraftPrefix(desc) {
346
+ return desc.replace(/^\s*\[draft\]\s*/, '');
347
+ }
348
+
349
+ /**
350
+ * ADR-4131 (0.30.0 PR 5): per-kind marker presence on an interface.
351
+ * Returns `{ kind, missing: string[] }` naming the markers that are
352
+ * absent from `iface.description`. For `other` the "note" is any
353
+ * non-empty description after the optional `[draft]` prefix. For an
354
+ * interface whose kind is outside INTERFACE_KINDS the function returns
355
+ * `{ kind, missing: [] }` so the caller can treat vocabulary errors
356
+ * through `shapes:kindVocabulary` alone.
357
+ *
358
+ * @param {unknown} iface
359
+ * @returns {{ kind: string|null, missing: string[] }}
360
+ */
361
+ export function parseInterfaceTemplate(iface) {
362
+ if (!iface || typeof iface !== 'object') return { kind: null, missing: [] };
363
+ const kind = typeof (/** @type {any} */ (iface).kind) === 'string' ? /** @type {any} */ (iface).kind : null;
364
+ const descRaw = typeof (/** @type {any} */ (iface).description) === 'string'
365
+ ? /** @type {any} */ (iface).description
366
+ : '';
367
+ const desc = stripDraftPrefix(descRaw);
368
+ if (kind === 'other') {
369
+ const note = desc.trim();
370
+ return { kind, missing: note.length === 0 ? ['note'] : [] };
371
+ }
372
+ const markers = /** @type {any} */ (INTERFACE_TEMPLATE_MARKERS)[kind];
373
+ if (!Array.isArray(markers)) return { kind, missing: [] };
374
+ const missing = [];
375
+ for (const marker of markers) {
376
+ if (!marker.re.test(desc)) missing.push(marker.name);
377
+ }
378
+ return { kind, missing };
379
+ }
380
+
381
+ /**
382
+ * Known bare repo filenames the slash-or-extension rule would otherwise
383
+ * silently skip (ruling R6 2026-10-05). A `path: Dockerfile` on an
384
+ * interface description names a real file at the repo root, so the
385
+ * `shapes:pathsResolve` check should see it. Exported so the tests can
386
+ * assert the list verbatim; a bare word outside this set still fails
387
+ * the slash-or-extension rule as before.
388
+ */
389
+ export const BARE_PATH_WHITELIST = /** @type {const} */ ([
390
+ 'Dockerfile',
391
+ 'Containerfile',
392
+ 'Makefile',
393
+ 'LICENSE',
394
+ 'Procfile',
395
+ 'Justfile',
396
+ 'Rakefile',
397
+ 'Gemfile',
398
+ 'CODEOWNERS',
399
+ ]);
400
+ const BARE_PATH_WHITELIST_SET = new Set(BARE_PATH_WHITELIST);
401
+
402
+ /**
403
+ * Rough `path:` token scanner for an interface description. Returns
404
+ * every candidate path token the description names so the CLI can
405
+ * resolve them on disk and the gate can decide `shapes:pathsResolve`
406
+ * against the resolved map (ADR-4131). A candidate is any text that
407
+ * follows a `path:` or `path =` marker and looks like a repo-relative
408
+ * path (contains a `/` or ends with a file extension, or is one of the
409
+ * known bare repo names in BARE_PATH_WHITELIST per ruling R6
410
+ * 2026-10-05, no scheme). The scanner is deliberately conservative: an
411
+ * http URL, a bare word outside the whitelist, a glob or a template
412
+ * placeholder is not a candidate. Exported for the CLI's resolve-on-disk
413
+ * pass.
414
+ *
415
+ * @param {string} description
416
+ * @returns {string[]}
417
+ */
418
+ export function extractInterfacePathTokens(description) {
419
+ if (typeof description !== 'string' || description.length === 0) return [];
420
+ const text = stripDraftPrefix(description);
421
+ const out = [];
422
+ const re = /\bpath\s*[:=]\s*["'`]?([^\s"'`,;)\]]+)/g;
423
+ let m;
424
+ while ((m = re.exec(text)) !== null) {
425
+ const token = m[1];
426
+ if (!token) continue;
427
+ if (/^[a-z]+:\/\//i.test(token)) continue;
428
+ if (token.startsWith('{') || token.startsWith('<') || token.includes('*')) continue;
429
+ // Skip HTTP / UI route-ish tokens: a leading slash with no file
430
+ // extension is a route path (an httpRoute or uiRoute's `path:`
431
+ // marker), not a repo path. A legitimate file path lands as
432
+ // `src/x.js` or `packages/rcf-lite/CHANGELOG.md`; those don't
433
+ // start with `/`.
434
+ if (token.startsWith('/') && !/\.[a-zA-Z0-9]+$/.test(token)) continue;
435
+ // Ruling R6 2026-10-05: whitelist the usual bare repo names.
436
+ if (BARE_PATH_WHITELIST_SET.has(token)) {
437
+ out.push(token);
438
+ continue;
439
+ }
440
+ if (!/\//.test(token) && !/\.[a-zA-Z0-9]+$/.test(token)) continue;
441
+ out.push(token);
442
+ }
443
+ return out;
444
+ }
445
+
283
446
  /** Warn-with-ack stages in 0.29.0 (ADR-4122). */
284
447
  const WARN_WITH_ACK = new Set(['D3', 'D5', 'D6']);
285
448
 
@@ -297,6 +460,23 @@ export function stagePolicy(stage) {
297
460
  return WARN_WITH_ACK.has(stage) ? 'warnWithAck' : 'blocking';
298
461
  }
299
462
 
463
+ /**
464
+ * ADR-4131 (0.30.0 PR 5): the three gates that accept a recorded
465
+ * `--ack` override. `stagePolicy(stage)` returns `warnWithAck` for
466
+ * D3/D5/D6 and `blocking` for everything else (ruling R4 2026-10-05
467
+ * retired the pre-R4 wording that said `stagePolicy` kept returning
468
+ * `blocking` for every stage); `ackable(stage)` is the companion
469
+ * signal the readiness and freeze CLIs read to decide whether a
470
+ * failing stage honours an acknowledgement at the current hash. True
471
+ * for D3, D5 and D6; false for everything else.
472
+ *
473
+ * @param {string} stage
474
+ * @returns {boolean}
475
+ */
476
+ export function ackable(stage) {
477
+ return WARN_WITH_ACK.has(stage);
478
+ }
479
+
300
480
  /**
301
481
  * Scaffold TODO placeholder marker: uppercase "TODO" followed by a
302
482
  * colon, matching every scaffold string `rcf init` and `rcf define
@@ -313,6 +493,192 @@ const TODO_RE = /\bTODO:/;
313
493
  /** Bracketed AC-class prefix (Baz decision 6, proposal §3.2 D4). */
314
494
  const AC_CLASS_RE = /^\[(happy|edge|failure|must-not|non-functional)\]/;
315
495
 
496
+ /**
497
+ * Enumeration cues for `stories:closedSets` (spec section 4 row 'D4
498
+ * closed-set and ownerRef as findings', 0.30.0 PR 6). An AC description
499
+ * that contains any of these cues outside a quoted string, with no
500
+ * inline bracketed list or ownerRef, invites an unlisted value and
501
+ * fails the check. The cues are matched case-insensitively against the
502
+ * raw description (minus any leading [class] marker and any
503
+ * double-quoted substrings).
504
+ */
505
+ const CLOSED_SET_CUES = Object.freeze([
506
+ 'one of',
507
+ 'any of',
508
+ 'the following',
509
+ 'types of',
510
+ 'status is',
511
+ ]);
512
+ // Word-boundary matchers for each cue so a longer word that happens
513
+ // to contain the cue as a substring (e.g. "status issue" containing
514
+ // "status is") does not trip the gate.
515
+ const CLOSED_SET_CUE_RES = Object.freeze(
516
+ CLOSED_SET_CUES.map((cue) => new RegExp(`\\b${cue.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}\\b`, 'i')),
517
+ );
518
+
519
+ /**
520
+ * Inline bracketed list regex for the closed-sets check: a square-
521
+ * bracketed group whose contents look like a list of two or more
522
+ * tokens separated by commas, slashes or pipes. A bare `[happy]`
523
+ * class marker is NOT a list (one token, no separator); `[a, b]`,
524
+ * `[a | b | c]` and `[a/b]` are.
525
+ */
526
+ const INLINE_LIST_RE = /\[[^\]\n]*[,|\/][^\]\n]*\]/;
527
+
528
+ /**
529
+ * ownerRef marker: a cheap presence check for the structured
530
+ * `{ tacId, field: "interfaces[<name>]" }` pointer. True when the AC
531
+ * carries an ownerRef object (consistency-lint and PR 6 both read the
532
+ * same field).
533
+ *
534
+ * @param {unknown} ac
535
+ * @returns {boolean}
536
+ */
537
+ function acHasOwnerRef(ac) {
538
+ const ref = ac && typeof ac === 'object' ? /** @type {any} */ (ac).ownerRef : null;
539
+ if (!ref || typeof ref !== 'object') return false;
540
+ // R11 (spec section 17, 2026-10-03): an ownerRef may name a TAC
541
+ // (via tacId) OR an ADR (via adrId). Pre-R11 code only recognised
542
+ // tacId; the ADR branch was dropped silently.
543
+ return typeof ref.tacId === 'string' || typeof ref.adrId === 'string';
544
+ }
545
+
546
+ /**
547
+ * Strip double-quoted substrings so a quoted cue inside the AC text
548
+ * does not fire the closed-sets check (shared with D6's negation guard
549
+ * convention). Matches `"..."` with no embedded unescaped double
550
+ * quote; the regex is deliberately permissive. The strip is only for
551
+ * the cue scan; the inline-list scan reads the full description.
552
+ *
553
+ * @param {string} desc
554
+ * @returns {string}
555
+ */
556
+ function stripQuotedSubstrings(desc) {
557
+ return desc.replace(/"[^"\n]*"/g, '');
558
+ }
559
+
560
+ /**
561
+ * True when the AC description carries an enumeration cue outside a
562
+ * quoted substring, with no inline bracketed list and no ownerRef
563
+ * pointer. Pure.
564
+ *
565
+ * @param {unknown} ac
566
+ * @returns {boolean}
567
+ */
568
+ function failsClosedSets(ac) {
569
+ const descRaw = ac && typeof ac === 'object' ? /** @type {any} */ (ac).description : null;
570
+ if (typeof descRaw !== 'string' || descRaw.length === 0) return false;
571
+ if (acHasOwnerRef(ac)) return false;
572
+ const descNoClass = descRaw.replace(AC_CLASS_RE, '').trim();
573
+ if (INLINE_LIST_RE.test(descNoClass)) return false;
574
+ const descForCues = stripQuotedSubstrings(descNoClass);
575
+ for (const re of CLOSED_SET_CUE_RES) {
576
+ if (re.test(descForCues)) return true;
577
+ }
578
+ return false;
579
+ }
580
+
581
+ /**
582
+ * Parse an `interfaces[<name>]` field pointer into its interface
583
+ * name. Accepts any non-empty name between the brackets (interface
584
+ * names routinely carry dots, slashes and spaces); returns null for
585
+ * an unparseable pointer.
586
+ *
587
+ * @param {unknown} field
588
+ * @returns {string | null}
589
+ */
590
+ function parseOwnerRefInterfaceField(field) {
591
+ if (typeof field !== 'string') return null;
592
+ const m = field.match(/^interfaces\[([^\]\n]+)\]$/);
593
+ return m ? m[1] : null;
594
+ }
595
+
596
+ /**
597
+ * R11 field grammar (spec section 17, 2026-10-03). An `ownerRef` or
598
+ * object-form `deliveredBy` `{ tacId | adrId, field }` resolves when
599
+ * `field` names an existing field path on the owning document in
600
+ * bracket grammar:
601
+ *
602
+ * - `interfaces[<name>]` resolves when `doc.interfaces[].name` matches.
603
+ * - `responsibilities[<n>]` resolves when `doc.responsibilities[n]`
604
+ * exists (non-negative integer index, zero-based).
605
+ * - `dependencies[<name>]` resolves when `doc.dependencies[].name` matches.
606
+ * - `alternativesConsidered[<n>]` resolves when the ADR has an
607
+ * alternative at that index.
608
+ * - A bare schema field name (`purpose`, `internalStructure`,
609
+ * `decision`, `name`, `context`, `consequences`, `tradeoffs`,
610
+ * `notes`, `description`, `responsibilities`, `dependencies`,
611
+ * `interfaces`, `alternativesConsidered`) resolves when the
612
+ * document carries a non-empty value under that key.
613
+ *
614
+ * Dotted grammar (`interfaces.name`, `responsibilities.foo`) is NOT
615
+ * accepted: callers of the R11 widening MUST rewrite to bracket
616
+ * grammar first. A path that does not match any arm returns false.
617
+ *
618
+ * `AC-17405-2` is unchanged in effect: `interfaces[loan]` on a TAC
619
+ * carrying an interface named `loan` resolves; `interfaces[missing]`
620
+ * fails.
621
+ *
622
+ * @param {unknown} doc - the owning TAC or ADR document.
623
+ * @param {unknown} field - the ownerRef/deliveredBy field string.
624
+ * @returns {boolean}
625
+ */
626
+ export function resolveOwnerRefField(doc, field) {
627
+ if (!doc || typeof doc !== 'object') return false;
628
+ if (typeof field !== 'string' || field.length === 0) return false;
629
+ const d = /** @type {any} */ (doc);
630
+ // interfaces[<name>] -- preserved from the 0.29.0 helper.
631
+ const ifaceMatch = field.match(/^interfaces\[([^\]\n]+)\]$/);
632
+ if (ifaceMatch) {
633
+ const name = ifaceMatch[1];
634
+ return Array.isArray(d.interfaces)
635
+ && d.interfaces.some((iface) => iface && typeof iface === 'object' && iface.name === name);
636
+ }
637
+ // dependencies[<name>] (TAC.dependencies[].name).
638
+ const depMatch = field.match(/^dependencies\[([^\]\n]+)\]$/);
639
+ if (depMatch) {
640
+ const name = depMatch[1];
641
+ return Array.isArray(d.dependencies)
642
+ && d.dependencies.some((dep) => dep && typeof dep === 'object' && dep.name === name);
643
+ }
644
+ // responsibilities[<n>] (zero-based integer index on the strings array).
645
+ const respMatch = field.match(/^responsibilities\[(\d+)\]$/);
646
+ if (respMatch) {
647
+ const idx = Number(respMatch[1]);
648
+ return Array.isArray(d.responsibilities) && idx < d.responsibilities.length
649
+ && typeof d.responsibilities[idx] === 'string'
650
+ && d.responsibilities[idx].length > 0;
651
+ }
652
+ // alternativesConsidered[<n>] (ADR).
653
+ const altMatch = field.match(/^alternativesConsidered\[(\d+)\]$/);
654
+ if (altMatch) {
655
+ const idx = Number(altMatch[1]);
656
+ return Array.isArray(d.alternativesConsidered) && idx < d.alternativesConsidered.length
657
+ && d.alternativesConsidered[idx] && typeof d.alternativesConsidered[idx] === 'object';
658
+ }
659
+ // Bare schema field name. Must be in the TAC/ADR schema and present
660
+ // and non-empty on the document. The accepted set covers the schema
661
+ // fields the spec names and the extras TAC/ADR carry; a field name
662
+ // outside the set returns false.
663
+ const BARE_FIELDS = new Set([
664
+ // TAC fields.
665
+ 'purpose', 'internalStructure', 'tradeoffs', 'notes', 'name',
666
+ 'responsibilities', 'interfaces', 'dependencies',
667
+ // ADR fields.
668
+ 'decision', 'context', 'consequences', 'title',
669
+ 'alternativesConsidered',
670
+ // Common.
671
+ 'description',
672
+ ]);
673
+ if (!BARE_FIELDS.has(field)) return false;
674
+ const v = d[field];
675
+ if (v == null) return false;
676
+ if (typeof v === 'string') return v.length > 0;
677
+ if (Array.isArray(v)) return v.length > 0;
678
+ if (typeof v === 'object') return Object.keys(v).length > 0;
679
+ return true;
680
+ }
681
+
316
682
  /**
317
683
  * Parse the leading bracketed class marker on `ac.description`.
318
684
  * Returns the class token, or null when no marker is present.
@@ -417,6 +783,43 @@ function asSet(scope) {
417
783
  return scope instanceof Set ? scope : new Set(scope ?? []);
418
784
  }
419
785
 
786
+ /**
787
+ * ADR-4138 (DEFINE step 3 rulings R2, R5, R7 2026-10-05 and ruling R13
788
+ * 2026-10-05 PR 292 follow-up): run every tree-wide check for a stage
789
+ * and either return a stage envelope carrying only the tree-wide
790
+ * findings (plus the scope placeholder) folded through `foldState`, or
791
+ * null when every tree-wide check passed, letting the stage proceed to
792
+ * its own scope early-return or full checks list.
793
+ *
794
+ * The helper governs every tree-wide check: `shapes:draftSettled`
795
+ * (R2), `shapes:entityJoin` (R5), `skeleton:standardsCited` (R7),
796
+ * `skeleton:deployAdr` (R13), `crosscut:securityArchitecture` (R13)
797
+ * and `crosscut:operationalConcerns` (R13). Delta-only checks
798
+ * (templateMarkers, pathsResolve, closedSets, ownerRefResolves) are
799
+ * untouched: they stay on the stage's own full-checks path. The
800
+ * ack-at-current-hash fold is delegated to `foldState` so one
801
+ * implementation owns the acknowledgement rule and the failing
802
+ * envelope carries no stale `notApplicable` reason text (the pre-R13
803
+ * copy of the stage's notApplicable message misled the readiness CLI
804
+ * print line, which reads `stage.reason` on every state).
805
+ *
806
+ * @param {string} stage
807
+ * @param {string} gate
808
+ * @param {Array<{name: string, check: object}>} treeWideChecks
809
+ * @param {object} freezeCtx
810
+ * @returns {{ stage: string, gate: string, state: 'failing' | 'acknowledged', checks: object[] } | null}
811
+ */
812
+ function treeWideFailureEnvelope(stage, gate, treeWideChecks, freezeCtx) {
813
+ const anyFailing = treeWideChecks.some(({ check }) => !check.ok);
814
+ if (!anyFailing) return null;
815
+ const checks = [makeCheck(`stage:${stage}:scope`, 'delta', 0, [])];
816
+ for (const { check } of treeWideChecks) checks.push(check);
817
+ // Delegate to foldState: it owns the warn-with-ack fold rule
818
+ // (ADR-4122). The returned envelope carries { state: 'failing' } or
819
+ // { state: 'acknowledged' } and no reason field.
820
+ return foldState(stage, gate, checks, freezeCtx);
821
+ }
822
+
420
823
  // ---------------------------------------------------------------------------
421
824
  // D1 -- Brief intake and ledger (blocking in 0.29.0).
422
825
  // ---------------------------------------------------------------------------
@@ -435,6 +838,11 @@ function asSet(scope) {
435
838
  * @property {{ skipReviewFor?: string } | undefined} profile parsed profile switches (light shape)
436
839
  * @property {string | null | undefined} currentTreeHash for warn-with-ack acknowledgement match
437
840
  * @property {Array<{ state: string }> | undefined} priorStages D8 reads earlier stage states from this
841
+ * @property {Set<string> | undefined} resolvedPaths ADR-4131 (0.30.0 PR 5): set of repo-relative paths the CLI
842
+ * already resolved on disk; `shapes:pathsResolve` reads this to decide
843
+ * whether a `path:` token on an interface description resolves. Empty or
844
+ * undefined means no path is known-resolved, so every candidate token
845
+ * fails unless the interface description carries `authoredAt: D3`.
438
846
  */
439
847
 
440
848
  /**
@@ -521,6 +929,81 @@ export function checkD1Brief(ctx) {
521
929
  /** Kinds whose resolution D2 checks: capability / constraint / entity / actor / externalSystem / surface. */
522
930
  const D2_RESOLVING_KINDS = new Set(['capability', 'constraint', 'entity', 'actor', 'externalSystem', 'surface']);
523
931
 
932
+ /**
933
+ * Compute the `skeleton:deployAdr` check (engineer, tree-wide). Pure.
934
+ * Ruling R13 2026-10-05 (ADR-4138 extended, PR 292 follow-up): exactly
935
+ * one Deploy target or Deploy deferral ADR exists tree-wide (detected
936
+ * by title prefix per proposal section 11). The check runs ahead of
937
+ * the D2 scope early-return so a narrowed scope that excludes every
938
+ * REQ / PRD / TAD / brief statement still reports a missing (or
939
+ * doubled) Deploy ADR.
940
+ *
941
+ * @param {StageContext} ctx
942
+ * @returns {ReturnType<typeof makeCheck>}
943
+ */
944
+ function computeDeployAdrCheck(ctx) {
945
+ const tree = ctx.tree;
946
+ const deployAdrs = (tree.adrs ?? []).filter((a) => {
947
+ const t = typeof a?.title === 'string' ? a.title : '';
948
+ return t.startsWith('Deploy target:') || t.startsWith('Deploy deferral:');
949
+ });
950
+ const deployFail = [];
951
+ if (deployAdrs.length === 0) deployFail.push({ id: 'ADR:deploy', why: 'no Deploy target or Deploy deferral ADR found (title-prefix scan)' });
952
+ else if (deployAdrs.length > 1) deployFail.push({ id: 'ADR:deploy', why: `${deployAdrs.length} Deploy ADRs found; expected exactly one` });
953
+ return makeCheck('skeleton:deployAdr', 'tree', 1, deployFail);
954
+ }
955
+
956
+ /**
957
+ * Compute the `skeleton:standardsCited` check (engineer, tree-wide).
958
+ * Pure. Every standards pack registered through `rcf define standards`
959
+ * (manifest.standards[].slug) is cited in a REQ `rationale` or an ADR,
960
+ * or satisfied by a concern-ledger entry keyed `standards:<pack>` whose
961
+ * disposition is `applied` or `waived`. Ruling R8 2026-10-05: both
962
+ * `applied` and `waived` satisfy the check (an `applied` entry means the
963
+ * pack was adopted, which is at least as strong as a citation). Ruling
964
+ * R7 2026-10-05: the check runs tree-wide regardless of the D2 scope
965
+ * early-return, through the shared ADR-4138 helper.
966
+ *
967
+ * @param {StageContext} ctx
968
+ * @returns {ReturnType<typeof makeCheck>}
969
+ */
970
+ function computeStandardsCitedCheck(ctx) {
971
+ const tree = ctx.tree;
972
+ const standardsList = Array.isArray(tree.manifest?.standards)
973
+ ? /** @type {any[]} */ (tree.manifest.standards)
974
+ : [];
975
+ /** @type {Array<{ id: string, why: string }>} */
976
+ const standardsFail = [];
977
+ if (standardsList.length > 0) {
978
+ const reqRationales = (tree.requirements ?? [])
979
+ .map((r) => (typeof r?.rationale === 'string' ? r.rationale : ''))
980
+ .join('\n');
981
+ const adrDocs = (tree.adrs ?? []).map((a) => {
982
+ try { return JSON.stringify(a); } catch { return ''; }
983
+ }).join('\n');
984
+ const concernsBody = /** @type {any} */ (ctx.ledgers?.concerns);
985
+ const concernList = Array.isArray(concernsBody?.concerns) ? concernsBody.concerns : [];
986
+ const satisfierSlugs = new Set();
987
+ for (const entry of concernList) {
988
+ if (!entry || typeof entry.concern !== 'string') continue;
989
+ const disposition = typeof entry.disposition === 'string' ? entry.disposition : null;
990
+ // Ruling R8 2026-10-05: both applied and waived satisfy standardsCited.
991
+ if (disposition !== 'applied' && disposition !== 'waived') continue;
992
+ const m = entry.concern.match(/^standards:(.+)$/);
993
+ if (m) satisfierSlugs.add(m[1]);
994
+ }
995
+ for (const pack of standardsList) {
996
+ const slug = typeof pack?.slug === 'string' ? pack.slug : null;
997
+ if (!slug) continue;
998
+ if (satisfierSlugs.has(slug)) continue;
999
+ if (reqRationales.includes(slug)) continue;
1000
+ if (adrDocs.includes(slug)) continue;
1001
+ standardsFail.push({ id: `standards:${slug}`, why: 'uncited, unapplied and unwaived' });
1002
+ }
1003
+ }
1004
+ return makeCheck('skeleton:standardsCited', 'tree', Math.max(standardsList.length, 1), standardsFail);
1005
+ }
1006
+
524
1007
  /**
525
1008
  * D2 -- Requirements and architecture skeleton.
526
1009
  *
@@ -539,7 +1022,25 @@ export function checkD2Skeleton(ctx) {
539
1022
  const prdInScope = tree.prd && scope.has(tree.prd.prdId ?? '');
540
1023
  const tadInScope = tree.tad && scope.has(tree.tad.tadId ?? '');
541
1024
 
1025
+ // Ruling R7 2026-10-05 (ADR-4138) and R13 2026-10-05 (ADR-4138
1026
+ // extended, PR 292 follow-up): skeleton:standardsCited and
1027
+ // skeleton:deployAdr are tree-wide checks; evaluate them before any
1028
+ // scope early-return so a narrowed D2 scope that excludes every
1029
+ // REQ/PRD/TAD/brief statement still reports an uncited pack or a
1030
+ // missing Deploy ADR.
1031
+ const standardsCheck = computeStandardsCitedCheck(ctx);
1032
+ const deployAdrCheck = computeDeployAdrCheck(ctx);
1033
+
542
1034
  if (resolvingStmts.length === 0 && reqInScope.length === 0 && !prdInScope && !tadInScope) {
1035
+ const treeWideFailure = treeWideFailureEnvelope(
1036
+ 'D2', gate,
1037
+ [
1038
+ { name: 'skeleton:standardsCited', check: standardsCheck },
1039
+ { name: 'skeleton:deployAdr', check: deployAdrCheck },
1040
+ ],
1041
+ { currentTreeHash: ctx.currentTreeHash ?? null, freezeGates: /** @type {any} */ (ctx.freeze?.gates) },
1042
+ );
1043
+ if (treeWideFailure) return treeWideFailure;
543
1044
  return notApplicable('D2', gate, 'no resolving brief statements and no REQ / PRD / TAD in scope');
544
1045
  }
545
1046
 
@@ -611,15 +1112,17 @@ export function checkD2Skeleton(ctx) {
611
1112
  checks.push(makeCheck('skeleton:tadPersistence', 'tree', persistenceReq ? 2 : 0, tadFail));
612
1113
 
613
1114
  // Check 4: exactly one deploy or deferral ADR tree-wide. Cheap
614
- // detection by title prefix (proposal §11 assumption).
615
- const deployAdrs = (tree.adrs ?? []).filter((a) => {
616
- const t = typeof a?.title === 'string' ? a.title : '';
617
- return t.startsWith('Deploy target:') || t.startsWith('Deploy deferral:');
618
- });
619
- const deployFail = [];
620
- if (deployAdrs.length === 0) deployFail.push({ id: 'ADR:deploy', why: 'no Deploy target or Deploy deferral ADR found (title-prefix scan)' });
621
- else if (deployAdrs.length > 1) deployFail.push({ id: 'ADR:deploy', why: `${deployAdrs.length} Deploy ADRs found; expected exactly one` });
622
- checks.push(makeCheck('skeleton:deployAdr', 'tree', 1, deployFail));
1115
+ // detection by title prefix (proposal §11 assumption). Ruling R13
1116
+ // 2026-10-05: tree-wide by definition; computed by
1117
+ // computeDeployAdrCheck so the same check is reused ahead of the
1118
+ // scope early-return (ADR-4138 extended).
1119
+ checks.push(deployAdrCheck);
1120
+
1121
+ // Check 5 (0.30.0 PR 6, ruling R7+R8 2026-10-05): skeleton:standardsCited
1122
+ // (engineer, over tree). Computed by `computeStandardsCitedCheck` so the
1123
+ // same check runs ahead of the scope early-return (R7) and so the R8
1124
+ // behaviour (applied | waived | cited all satisfy) lives in one place.
1125
+ checks.push(standardsCheck);
623
1126
 
624
1127
  return foldState('D2', gate, checks, {
625
1128
  currentTreeHash: ctx.currentTreeHash ?? null,
@@ -634,6 +1137,98 @@ export function checkD2Skeleton(ctx) {
634
1137
  /** Set form of INTERFACE_KINDS for O(1) checks. */
635
1138
  const INTERFACE_KINDS_SET = new Set(INTERFACE_KINDS);
636
1139
 
1140
+ /**
1141
+ * Compute the `shapes:draftSettled` check (engineer, tree-wide). Pure.
1142
+ * Ruling R2 2026-10-05 (ADR-4138): a `[draft]` marker on any TAC
1143
+ * purpose, any interface description or any coreEntities[].description
1144
+ * fails the check regardless of the D3 scope's own early-return. The
1145
+ * three id forms are `<tacId>`, `<tacId>:<name>` and `TAD.entity:<name>`.
1146
+ *
1147
+ * @param {StageContext} ctx
1148
+ * @returns {ReturnType<typeof makeCheck>}
1149
+ */
1150
+ function computeDraftSettledCheck(ctx) {
1151
+ const tree = ctx.tree;
1152
+ const tacs = tree.tacs ?? [];
1153
+ const coreEntities = Array.isArray(tree.tad?.dataArchitecture?.coreEntities)
1154
+ ? /** @type {any[]} */ (tree.tad.dataArchitecture.coreEntities)
1155
+ : [];
1156
+ /** @type {Array<{ id: string, why: string }>} */
1157
+ const draftFindings = [];
1158
+ let totalInterfaces = 0;
1159
+ for (const tac of tacs) {
1160
+ if (parseTacPurposeDraft(tac)) {
1161
+ draftFindings.push({ id: tac.tacId, why: 'draft TAC purpose pre-populated at L1, not yet settled' });
1162
+ }
1163
+ for (const iface of tac.interfaces ?? []) {
1164
+ totalInterfaces += 1;
1165
+ if (parseInterfaceDraft(iface)) {
1166
+ draftFindings.push({ id: `${tac.tacId}:${iface?.name ?? '(unnamed)'}`, why: 'draft interface pre-populated at L1, not yet settled' });
1167
+ }
1168
+ }
1169
+ }
1170
+ for (const entity of coreEntities) {
1171
+ if (parseCoreEntityDraft(entity)) {
1172
+ draftFindings.push({ id: `TAD.entity:${entity?.name ?? '(unnamed)'}`, why: 'draft core entity pre-populated at L1, not yet settled' });
1173
+ }
1174
+ }
1175
+ const totalDraftHomes = tacs.length + totalInterfaces + coreEntities.length;
1176
+ return makeCheck('shapes:draftSettled', 'tree', Math.max(totalDraftHomes, 1), draftFindings);
1177
+ }
1178
+
1179
+ /**
1180
+ * Compute the `shapes:entityJoin` check (engineer, tree-wide). Pure.
1181
+ * Ruling R5 2026-10-05 (ADR-4138): every entry in
1182
+ * `TAD.dataArchitecture.coreEntities` must be named by exactly one
1183
+ * `recordShape` across the whole tree (matching on the recordShape's
1184
+ * `name` field or an `entity:` line in its description, with a
1185
+ * `[draft]` prefix stripped before the scan). The check runs ahead of
1186
+ * the D3 scope early-return so a narrowed scope that excludes every
1187
+ * recordShape still reports an unjoined entity.
1188
+ *
1189
+ * @param {StageContext} ctx
1190
+ * @returns {ReturnType<typeof makeCheck>}
1191
+ */
1192
+ function computeEntityJoinCheck(ctx) {
1193
+ const tree = ctx.tree;
1194
+ const coreEntities = Array.isArray(tree.tad?.dataArchitecture?.coreEntities)
1195
+ ? /** @type {any[]} */ (tree.tad.dataArchitecture.coreEntities)
1196
+ : [];
1197
+ /** @type {Array<{ id: string, why: string }>} */
1198
+ const joinFindings = [];
1199
+ const recordShapesByEntity = new Map();
1200
+ for (const tac of tree.tacs ?? []) {
1201
+ for (const iface of tac.interfaces ?? []) {
1202
+ if (iface?.kind !== 'recordShape') continue;
1203
+ const ownerLabel = `${tac.tacId}:${iface?.name ?? '(unnamed)'}`;
1204
+ const names = new Set();
1205
+ if (typeof iface?.name === 'string') names.add(iface.name);
1206
+ const desc = typeof iface?.description === 'string' ? stripDraftPrefix(iface.description) : '';
1207
+ const entityRe = /(^|\n)\s*(?:[-*]\s*)?entity\s*[:=]\s*["'`]?([A-Za-z_][A-Za-z0-9_]*)/g;
1208
+ let em;
1209
+ while ((em = entityRe.exec(desc)) !== null) {
1210
+ if (em[2]) names.add(em[2]);
1211
+ }
1212
+ for (const name of names) {
1213
+ const owners = recordShapesByEntity.get(name) ?? [];
1214
+ owners.push(ownerLabel);
1215
+ recordShapesByEntity.set(name, owners);
1216
+ }
1217
+ }
1218
+ }
1219
+ for (const entity of coreEntities) {
1220
+ const name = typeof entity?.name === 'string' ? entity.name : null;
1221
+ if (!name) continue;
1222
+ const owners = recordShapesByEntity.get(name) ?? [];
1223
+ if (owners.length === 0) {
1224
+ joinFindings.push({ id: `TAD.entity:${name}`, why: 'no record shape' });
1225
+ } else if (owners.length > 1) {
1226
+ joinFindings.push({ id: `TAD.entity:${name}`, why: `${owners.length} record shapes` });
1227
+ }
1228
+ }
1229
+ return makeCheck('shapes:entityJoin', 'tree', coreEntities.length, joinFindings);
1230
+ }
1231
+
637
1232
  /**
638
1233
  * D3 -- Interface contracts and shapes. 0.29.0 runs the cheap
639
1234
  * presence, closed-vocabulary and draft-marker checks
@@ -670,10 +1265,30 @@ export function checkD3Shapes(ctx) {
670
1265
  const coreEntities = Array.isArray(tree.tad?.dataArchitecture?.coreEntities)
671
1266
  ? /** @type {any[]} */ (tree.tad.dataArchitecture.coreEntities)
672
1267
  : [];
673
- const draftEntities = coreEntities.filter(parseCoreEntityDraft);
674
1268
 
675
- if (tacsInScope.length === 0 && shapedReqInScope.length === 0 && draftEntities.length === 0) {
676
- return notApplicable('D3', gate, 'no TAC, no shaped REQ (httpApi/persistence/auth) and no [draft] core entity in scope');
1269
+ // Ruling R2+R5 2026-10-05 (ADR-4138): shapes:draftSettled and
1270
+ // shapes:entityJoin are tree-wide checks; evaluate them before any
1271
+ // scope early-return so a narrowed D3 scope that excludes every TAC
1272
+ // and shaped REQ still reports a [draft] anywhere in the tree and an
1273
+ // unjoined core entity.
1274
+ const draftCheck = computeDraftSettledCheck(ctx);
1275
+ const entityJoinCheck = computeEntityJoinCheck(ctx);
1276
+
1277
+ if (tacsInScope.length === 0 && shapedReqInScope.length === 0) {
1278
+ const treeWideFailure = treeWideFailureEnvelope(
1279
+ 'D3', gate,
1280
+ [
1281
+ { name: 'shapes:draftSettled', check: draftCheck },
1282
+ { name: 'shapes:entityJoin', check: entityJoinCheck },
1283
+ ],
1284
+ { currentTreeHash: ctx.currentTreeHash ?? null, freezeGates: /** @type {any} */ (ctx.freeze?.gates) },
1285
+ );
1286
+ if (treeWideFailure) return treeWideFailure;
1287
+ // Ruling R2 2026-10-05: `[draft]` is tree-wide (not a D3 scope
1288
+ // input), so the pre-R2 reason trailer "and no [draft] core entity
1289
+ // in scope" was stale -- the applicability condition is just the
1290
+ // two local-scope sets.
1291
+ return notApplicable('D3', gate, 'no TAC and no shaped REQ (httpApi/persistence/auth) in scope');
677
1292
  }
678
1293
 
679
1294
  const checks = [];
@@ -687,40 +1302,90 @@ export function checkD3Shapes(ctx) {
687
1302
  noIfaceTacs.map((t) => ({ id: t.tacId, why: 'no interfaces authored' })),
688
1303
  ));
689
1304
 
690
- // Check 2: every interface kind is in the closed vocabulary.
691
- // Check 3: no description across the three draft homes still
692
- // carries the `[draft]` marker. A draft shape is entry material
693
- // the agent pre-populates after L1; the engineer removes the
694
- // marker when the shape is settled. `tacHasInterface` and
695
- // `kindVocabulary` apply equally to drafts.
1305
+ // Check 2: every interface kind is in the closed vocabulary (over
1306
+ // delta; drafts included).
696
1307
  let totalInterfaces = 0;
697
1308
  const badKinds = [];
698
- const draftFindings = [];
699
1309
  for (const tac of tacsInScope) {
700
- if (parseTacPurposeDraft(tac)) {
701
- draftFindings.push({ id: tac.tacId, why: 'draft TAC purpose pre-populated at L1, not yet settled' });
702
- }
703
1310
  for (const iface of tac.interfaces ?? []) {
704
1311
  totalInterfaces += 1;
705
1312
  const kind = iface?.kind;
706
1313
  if (typeof kind !== 'string' || !INTERFACE_KINDS_SET.has(kind)) {
707
1314
  badKinds.push({ id: `${tac.tacId}:${iface?.name ?? '(unnamed)'}`, why: `unknown interface kind ${JSON.stringify(kind)}` });
708
1315
  }
709
- if (parseInterfaceDraft(iface)) {
710
- draftFindings.push({ id: `${tac.tacId}:${iface?.name ?? '(unnamed)'}`, why: 'draft interface pre-populated at L1, not yet settled' });
1316
+ }
1317
+ }
1318
+ checks.push(makeCheck('shapes:kindVocabulary', 'delta', totalInterfaces, badKinds));
1319
+
1320
+ // Check 3: shapes:draftSettled. Ruling R2 2026-10-05: tree-wide (a
1321
+ // [draft] anywhere is unfinished work). Computed by
1322
+ // computeDraftSettledCheck so the same check is reused ahead of the
1323
+ // scope early-return.
1324
+ checks.push(draftCheck);
1325
+
1326
+ // ADR-4131 (0.30.0 PR 5): three D3 bite checks follow.
1327
+ // Check 4: shapes:templateMarkers (engineer, over delta). For every
1328
+ // interface on an in-scope TAC, parseInterfaceTemplate reports which
1329
+ // per-kind markers are missing from the description; a draft marker
1330
+ // is stripped before the scan so a [draft] recordShape without
1331
+ // `fields:` fails exactly as a settled one. An interface whose kind
1332
+ // is outside INTERFACE_KINDS is left to shapes:kindVocabulary (the
1333
+ // marker map returns `{missing: []}` for an unknown kind so this
1334
+ // check does not double-report the vocabulary miss).
1335
+ /** @type {Array<{ id: string, why: string }>} */
1336
+ const templateFindings = [];
1337
+ for (const tac of tacsInScope) {
1338
+ for (const iface of tac.interfaces ?? []) {
1339
+ const result = parseInterfaceTemplate(iface);
1340
+ if (!result.kind) continue;
1341
+ for (const marker of result.missing) {
1342
+ templateFindings.push({
1343
+ id: `${tac.tacId}:${iface?.name ?? '(unnamed)'}`,
1344
+ why: `missing marker ${marker}`,
1345
+ });
711
1346
  }
712
1347
  }
713
1348
  }
714
- for (const entity of draftEntities) {
715
- draftFindings.push({ id: `TAD.entity:${entity?.name ?? '(unnamed)'}`, why: 'draft core entity pre-populated at L1, not yet settled' });
1349
+ checks.push(makeCheck('shapes:templateMarkers', 'delta', totalInterfaces, templateFindings));
1350
+
1351
+ // Check 5: shapes:entityJoin. Ruling R5 2026-10-05: tree-wide by
1352
+ // definition. Computed by computeEntityJoinCheck so the same check
1353
+ // is reused ahead of the scope early-return (ADR-4138).
1354
+ checks.push(entityJoinCheck);
1355
+
1356
+ // Check 6: shapes:pathsResolve (engineer, over delta). Any path:
1357
+ // token on an in-scope interface description must either resolve
1358
+ // against `resolvedPaths` (the CLI's on-disk pass) or the
1359
+ // description must carry an `authoredAt: D3` marker (the engineer
1360
+ // owns the path even when the file is yet to land). The marker is
1361
+ // a token in the description text (`authoredAt: D3` or
1362
+ // `authoredAt = D3`), not a separate schema field; the TAC schema
1363
+ // keeps interfaces to { name, kind, description }. Over delta,
1364
+ // one failing entry per unresolved (tacId:name, path) pair.
1365
+ const resolvedPaths = ctx.resolvedPaths instanceof Set ? ctx.resolvedPaths : new Set();
1366
+ /** @type {Array<{ id: string, why: string }>} */
1367
+ const pathFindings = [];
1368
+ let totalPathChecks = 0;
1369
+ for (const tac of tacsInScope) {
1370
+ for (const iface of tac.interfaces ?? []) {
1371
+ const desc = typeof iface?.description === 'string' ? iface.description : '';
1372
+ const tokens = extractInterfacePathTokens(desc);
1373
+ if (tokens.length === 0) continue;
1374
+ const authoredAtD3 = /\bauthoredAt\s*[:=]\s*["'`]?D3\b/.test(stripDraftPrefix(desc));
1375
+ for (const token of tokens) {
1376
+ totalPathChecks += 1;
1377
+ if (authoredAtD3) continue;
1378
+ if (resolvedPaths.has(token)) continue;
1379
+ pathFindings.push({
1380
+ id: `${tac.tacId}:${iface?.name ?? '(unnamed)'}`,
1381
+ why: `path does not resolve: ${token}`,
1382
+ });
1383
+ }
1384
+ }
716
1385
  }
717
- // Total for the draft check is every draft home that could carry
718
- // the marker on an in-scope TAC plus every core entity (tree-wide):
719
- // the TAC itself (its purpose) + every interface on it, plus the
720
- // coreEntities list.
721
- const totalDraftHomes = tacsInScope.length + totalInterfaces + coreEntities.length;
722
- checks.push(makeCheck('shapes:kindVocabulary', 'delta', totalInterfaces, badKinds));
723
- checks.push(makeCheck('shapes:draftSettled', 'delta', totalDraftHomes, draftFindings));
1386
+ // Keep total >= 1 so the chip prints a sensible ratio when no
1387
+ // interface in scope names a path.
1388
+ checks.push(makeCheck('shapes:pathsResolve', 'delta', Math.max(totalPathChecks, 1), pathFindings));
724
1389
 
725
1390
  return foldState('D3', gate, checks, {
726
1391
  currentTreeHash: ctx.currentTreeHash ?? null,
@@ -801,6 +1466,72 @@ export function checkD4Stories(ctx) {
801
1466
  }
802
1467
  checks.push(makeCheck('stories:usFloors', 'delta', usInScope.length, usFail));
803
1468
 
1469
+ // Check 3 (0.30.0 PR 6): stories:closedSets (engineer, over delta).
1470
+ // Every AC on a US in scope whose description contains an enumeration
1471
+ // cue (one of | any of | the following | types of | status is)
1472
+ // without an inline bracketed list of two or more tokens AND without
1473
+ // an ownerRef fails. The quoted-cue guard strips `"..."` substrings
1474
+ // before the cue scan so prose that quotes a cue does not fire the
1475
+ // check.
1476
+ /** @type {Array<{ id: string, why: string }>} */
1477
+ const closedSetFindings = [];
1478
+ let totalClosedSetAcs = 0;
1479
+ for (const us of usInScope) {
1480
+ const acs = Array.isArray(us.acceptanceCriteria) ? us.acceptanceCriteria : [];
1481
+ for (const ac of acs) {
1482
+ if (typeof ac?.description !== 'string' || ac.description.length === 0) continue;
1483
+ totalClosedSetAcs += 1;
1484
+ if (failsClosedSets(ac)) {
1485
+ closedSetFindings.push({
1486
+ id: ac.id ?? us.usId,
1487
+ why: 'enumeration cue without a closed set',
1488
+ });
1489
+ }
1490
+ }
1491
+ }
1492
+ checks.push(makeCheck('stories:closedSets', 'delta', totalClosedSetAcs, closedSetFindings));
1493
+
1494
+ // Check 4 (0.30.0 PR 6): stories:ownerRefResolves (engineer, over
1495
+ // delta plus tree for ownerRef targets). Every AC on a US in scope
1496
+ // whose ownerRef is set must point to an interface by name on the
1497
+ // named TAC. Ids `<acId>:<field>`; why 'ownerRef does not resolve'.
1498
+ /** @type {Array<{ id: string, why: string }>} */
1499
+ const ownerRefFindings = [];
1500
+ let totalOwnerRefAcs = 0;
1501
+ // R11 (spec section 17, 2026-10-03): the ownerRef field grammar
1502
+ // widens beyond `interfaces[<name>]` to every bracket-grammar path
1503
+ // that names an existing field on the owning TAC or ADR. The owner
1504
+ // may now be a TAC (via tacId) or an ADR (via adrId); the resolver
1505
+ // handles the bracket forms (`interfaces[<name>]`,
1506
+ // `responsibilities[<n>]`, `dependencies[<name>]`,
1507
+ // `alternativesConsidered[<n>]`) and bare schema fields (`purpose`,
1508
+ // `internalStructure`, `decision`, etc.). A path that does not
1509
+ // match any arm still fails. AC-17405-2 is unchanged in effect.
1510
+ for (const us of usInScope) {
1511
+ const acs = Array.isArray(us.acceptanceCriteria) ? us.acceptanceCriteria : [];
1512
+ for (const ac of acs) {
1513
+ if (!acHasOwnerRef(ac)) continue;
1514
+ totalOwnerRefAcs += 1;
1515
+ const ref = /** @type {any} */ (ac).ownerRef;
1516
+ let owner = null;
1517
+ if (typeof ref.tacId === 'string') {
1518
+ owner = (tree.tacs ?? []).find((t) => t?.tacId === ref.tacId) ?? null;
1519
+ } else if (typeof ref.adrId === 'string') {
1520
+ owner = (tree.adrs ?? []).find((a) => a?.adrId === ref.adrId) ?? null;
1521
+ }
1522
+ const resolves = !!(owner && resolveOwnerRefField(owner, ref.field));
1523
+ if (!resolves) {
1524
+ ownerRefFindings.push({
1525
+ id: `${ac.id ?? us.usId}:${ref.field ?? '(no field)'}`,
1526
+ why: 'ownerRef does not resolve',
1527
+ });
1528
+ }
1529
+ }
1530
+ }
1531
+ // Keep total >= 1 so the chip prints a sensible ratio when no AC in
1532
+ // scope carries an ownerRef.
1533
+ checks.push(makeCheck('stories:ownerRefResolves', 'delta', Math.max(totalOwnerRefAcs, 1), ownerRefFindings));
1534
+
804
1535
  return foldState('D4', gate, checks, {
805
1536
  currentTreeHash: ctx.currentTreeHash ?? null,
806
1537
  freezeGates: /** @type {any} */ (ctx.freeze?.gates),
@@ -812,27 +1543,17 @@ export function checkD4Stories(ctx) {
812
1543
  // ---------------------------------------------------------------------------
813
1544
 
814
1545
  /**
815
- * D5 -- Cross-cutting weave. 0.29.0 runs cheap presence checks.
816
- *
817
- * SEAM 0.30: full concern catalogue with per-shape applicability;
818
- * per-(concern, REQ) pair enumeration; TAD securityArchitecture and
819
- * operationalConcerns structure checks beyond presence.
1546
+ * Compute the `crosscut:securityArchitecture` check (engineer,
1547
+ * tree-wide). Pure. Ruling R13 2026-10-05 (ADR-4138 extended): if the
1548
+ * tree carries any REQ with shape `auth` or `httpApi`, TAD.securityArchitecture
1549
+ * must be non-empty. Runs ahead of the D5 scope early-return so a
1550
+ * narrowed scope that excludes the auth REQ still reports the finding.
820
1551
  *
821
1552
  * @param {StageContext} ctx
1553
+ * @returns {ReturnType<typeof makeCheck>}
822
1554
  */
823
- export function checkD5Crosscut(ctx) {
824
- const gate = STAGE_GATES.D5;
825
- const scope = asSet(ctx.scope);
1555
+ function computeSecurityArchitectureCheck(ctx) {
826
1556
  const tree = ctx.tree;
827
- const reqInScope = (tree.requirements ?? []).filter((r) => scope.has(r.reqId));
828
-
829
- if (reqInScope.length === 0) {
830
- return notApplicable('D5', gate, 'no REQ in scope');
831
- }
832
-
833
- const checks = [];
834
-
835
- // Check 1: TAD.securityArchitecture non-empty when any REQ carries shape 'auth' or 'httpApi'.
836
1557
  const authApi = (tree.requirements ?? []).some((r) => {
837
1558
  const s = r.shapeClassification?.shapes ?? [];
838
1559
  return s.includes('auth') || s.includes('httpApi');
@@ -845,11 +1566,22 @@ export function checkD5Crosscut(ctx) {
845
1566
  secFail.push({ id: 'TAD.securityArchitecture', why: 'empty while auth or httpApi REQ exists' });
846
1567
  }
847
1568
  }
848
- checks.push(makeCheck('crosscut:securityArchitecture', 'tree', authApi ? 1 : 0, secFail));
1569
+ return makeCheck('crosscut:securityArchitecture', 'tree', authApi ? 1 : 0, secFail);
1570
+ }
849
1571
 
850
- // Check 2: TAD.operationalConcerns non-empty when any AC description
851
- // carries the '[deployed]' marker (a cheap presence signal that
852
- // proposal §3.2 D5 lists as 'deployed-scope AC').
1572
+ /**
1573
+ * Compute the `crosscut:operationalConcerns` check (engineer,
1574
+ * tree-wide). Pure. Ruling R13 2026-10-05 (ADR-4138 extended): if any
1575
+ * AC description tree-wide carries the `[deployed]` marker, then
1576
+ * TAD.operationalConcerns must be non-empty. Runs ahead of the D5
1577
+ * scope early-return.
1578
+ *
1579
+ * @param {StageContext} ctx
1580
+ * @returns {ReturnType<typeof makeCheck>}
1581
+ */
1582
+ function computeOperationalConcernsCheck(ctx) {
1583
+ const tree = ctx.tree;
1584
+ const tad = /** @type {any} */ (tree.tad ?? {});
853
1585
  const hasDeployedAc = (tree.userStories ?? []).some((us) => (us.acceptanceCriteria ?? []).some((ac) => typeof ac?.description === 'string' && ac.description.includes('[deployed]')));
854
1586
  const opFail = [];
855
1587
  if (hasDeployedAc) {
@@ -858,7 +1590,59 @@ export function checkD5Crosscut(ctx) {
858
1590
  opFail.push({ id: 'TAD.operationalConcerns', why: 'empty while deployed-scope AC exists' });
859
1591
  }
860
1592
  }
861
- checks.push(makeCheck('crosscut:operationalConcerns', 'tree', hasDeployedAc ? 1 : 0, opFail));
1593
+ return makeCheck('crosscut:operationalConcerns', 'tree', hasDeployedAc ? 1 : 0, opFail);
1594
+ }
1595
+
1596
+ /**
1597
+ * D5 -- Cross-cutting weave. 0.29.0 runs cheap presence checks.
1598
+ *
1599
+ * SEAM 0.30: full concern catalogue with per-shape applicability;
1600
+ * per-(concern, REQ) pair enumeration; TAD securityArchitecture and
1601
+ * operationalConcerns structure checks beyond presence.
1602
+ *
1603
+ * @param {StageContext} ctx
1604
+ */
1605
+ export function checkD5Crosscut(ctx) {
1606
+ const gate = STAGE_GATES.D5;
1607
+ const scope = asSet(ctx.scope);
1608
+ const tree = ctx.tree;
1609
+ const reqInScope = (tree.requirements ?? []).filter((r) => scope.has(r.reqId));
1610
+
1611
+ // Ruling R13 2026-10-05 (ADR-4138 extended, PR 292 follow-up):
1612
+ // crosscut:securityArchitecture and crosscut:operationalConcerns are
1613
+ // tree-wide checks; evaluate them before any scope early-return so a
1614
+ // narrowed D5 scope that excludes the triggering REQ or AC still
1615
+ // reports an empty TAD.securityArchitecture / TAD.operationalConcerns.
1616
+ const securityCheck = computeSecurityArchitectureCheck(ctx);
1617
+ const operationalCheck = computeOperationalConcernsCheck(ctx);
1618
+
1619
+ if (reqInScope.length === 0) {
1620
+ const treeWideFailure = treeWideFailureEnvelope(
1621
+ 'D5', gate,
1622
+ [
1623
+ { name: 'crosscut:securityArchitecture', check: securityCheck },
1624
+ { name: 'crosscut:operationalConcerns', check: operationalCheck },
1625
+ ],
1626
+ { currentTreeHash: ctx.currentTreeHash ?? null, freezeGates: /** @type {any} */ (ctx.freeze?.gates) },
1627
+ );
1628
+ if (treeWideFailure) return treeWideFailure;
1629
+ return notApplicable('D5', gate, 'no REQ in scope');
1630
+ }
1631
+
1632
+ const checks = [];
1633
+
1634
+ // Check 1: TAD.securityArchitecture non-empty when any REQ carries
1635
+ // shape 'auth' or 'httpApi'. Ruling R13 2026-10-05: tree-wide;
1636
+ // computed by computeSecurityArchitectureCheck so the same check is
1637
+ // reused ahead of the scope early-return (ADR-4138 extended).
1638
+ checks.push(securityCheck);
1639
+
1640
+ // Check 2: TAD.operationalConcerns non-empty when any AC description
1641
+ // carries the '[deployed]' marker (a cheap presence signal that
1642
+ // proposal §3.2 D5 lists as 'deployed-scope AC'). Ruling R13
1643
+ // 2026-10-05: tree-wide; computed by computeOperationalConcernsCheck
1644
+ // so the same check is reused ahead of the scope early-return.
1645
+ checks.push(operationalCheck);
862
1646
 
863
1647
  // Check 3: no open concern-ledger entry on a REQ in scope.
864
1648
  const concerns = /** @type {any} */ (ctx.ledgers?.concerns);
@@ -871,6 +1655,52 @@ export function checkD5Crosscut(ctx) {
871
1655
  openInScope.map((c) => ({ id: `concern:${c.id}`, why: `open concern on ${c.reqId}: ${c.concern}` })),
872
1656
  ));
873
1657
 
1658
+ // Check 4 (0.30.0 PR 6): crosscut:catalogue (engineer, over tree).
1659
+ // For every REQ in scope, enumerate applicable (reqShape, concern)
1660
+ // pairs via src/define/concern-catalogue.js; each pair needs a
1661
+ // concern-ledger entry keyed <REQ>:<concern> with disposition
1662
+ // applied or waived (a waived entry carries a reason). Fail ids are
1663
+ // `<REQ>:<concern>`; the why names the missing concern. A waived
1664
+ // entry without a reason also fails. Keys shared with the baseline
1665
+ // catalogue where names coincide (today only `auth`).
1666
+ const entriesByKey = new Map();
1667
+ for (const entry of concernEntries) {
1668
+ if (!entry || typeof entry.reqId !== 'string' || typeof entry.concern !== 'string') continue;
1669
+ entriesByKey.set(`${entry.reqId}:${entry.concern}`, entry);
1670
+ }
1671
+ /** @type {Array<{ id: string, why: string }>} */
1672
+ const catalogueFindings = [];
1673
+ let totalCataloguePairs = 0;
1674
+ for (const req of reqInScope) {
1675
+ const shapes = Array.isArray(req?.shapeClassification?.shapes)
1676
+ ? req.shapeClassification.shapes.filter((s) => typeof s === 'string')
1677
+ : [];
1678
+ const applicable = applicableConcernsForShapes(shapes);
1679
+ for (const concern of applicable) {
1680
+ totalCataloguePairs += 1;
1681
+ const key = `${req.reqId}:${concern}`;
1682
+ const entry = entriesByKey.get(key);
1683
+ if (!entry) {
1684
+ catalogueFindings.push({ id: key, why: `missing concern-ledger entry for ${concern}` });
1685
+ continue;
1686
+ }
1687
+ const disposition = typeof entry.disposition === 'string' ? entry.disposition : null;
1688
+ if (disposition !== 'applied' && disposition !== 'waived') {
1689
+ catalogueFindings.push({ id: key, why: `concern-ledger entry disposition is ${disposition ?? '(unset)'}` });
1690
+ continue;
1691
+ }
1692
+ if (disposition === 'waived') {
1693
+ const reason = typeof entry.reason === 'string' ? entry.reason.trim() : '';
1694
+ if (reason.length === 0) {
1695
+ catalogueFindings.push({ id: key, why: 'waived without a reason' });
1696
+ }
1697
+ }
1698
+ }
1699
+ }
1700
+ // Keep total >= 1 so the chip prints a sensible ratio when no REQ in
1701
+ // scope has applicable concerns (every REQ carries shape 'other').
1702
+ checks.push(makeCheck('crosscut:catalogue', 'tree', Math.max(totalCataloguePairs, 1), catalogueFindings));
1703
+
874
1704
  return foldState('D5', gate, checks, {
875
1705
  currentTreeHash: ctx.currentTreeHash ?? null,
876
1706
  freezeGates: /** @type {any} */ (ctx.freeze?.gates),
@@ -882,14 +1712,14 @@ export function checkD5Crosscut(ctx) {
882
1712
  // ---------------------------------------------------------------------------
883
1713
 
884
1714
  /**
885
- * D6 -- Consistency and satisfiability probe. 0.29.0 runs only the
886
- * validate-clean tree-wide check and the probe-ledger open count.
887
- *
888
- * SEAM 0.30: contradiction-lite across criteria on one story and
889
- * across their TACs' ADRs; unsatisfiable-lite (a `then` naming
890
- * undefined state); duplicate scan; orphan-interface scan;
891
- * regeneration probe runner injectable like `mutationRunner` in
892
- * src/review/index.js.
1715
+ * D6 -- Consistency and satisfiability probe. 0.29.0 ran the
1716
+ * validate-clean tree-wide check and the probe-ledger open count;
1717
+ * 0.30.0 PR 7 (ADR-4131 extended, spec section 4 row 'D6 scans and the
1718
+ * injectable probe runner') adds the four mechanical scans
1719
+ * consistency:contradictions, consistency:unsatisfiable,
1720
+ * consistency:duplicates and consistency:orphanInterfaces. The probe
1721
+ * runner lives on the readiness compute (TAC-4123); the gate reads the
1722
+ * merged probes.probes[] it ends up with.
893
1723
  *
894
1724
  * @param {StageContext} ctx
895
1725
  */
@@ -933,12 +1763,350 @@ export function checkD6Consistency(ctx) {
933
1763
  // uses a single representative entry regardless.
934
1764
  checks.push(makeCheck('consistency:probeCount', 'tree', Math.max(effectiveOpen, 1), failing, effectiveOpen));
935
1765
 
1766
+ // ADR-4131 extended (0.30.0 PR 7): the four D6 scans.
1767
+ const scope = asSet(ctx.scope);
1768
+ const tree = ctx.tree;
1769
+ const usInScope = (tree.userStories ?? []).filter((us) => scope.has(us.usId));
1770
+
1771
+ // Scan 1: consistency:contradictions (engineer, over delta). Two ACs
1772
+ // on one story share a `when` clause and one of their `then` clauses
1773
+ // is a negation of the other. The quoted-cue guard strips
1774
+ // double-quoted substrings before the negation scan so prose that
1775
+ // quotes a negation inside a `then` does not fire the check.
1776
+ /** @type {Array<{ id: string, why: string }>} */
1777
+ const contradictionFindings = [];
1778
+ let totalStoriesScanned = 0;
1779
+ for (const us of usInScope) {
1780
+ const acs = Array.isArray(us.acceptanceCriteria) ? us.acceptanceCriteria : [];
1781
+ if (acs.length < 2) continue;
1782
+ totalStoriesScanned += 1;
1783
+ const parsed = acs
1784
+ .map((ac) => ({ ac, parts: parseWhenThen(ac?.description) }))
1785
+ .filter((p) => p.parts !== null);
1786
+ const reported = new Set();
1787
+ for (let i = 0; i < parsed.length; i += 1) {
1788
+ for (let j = i + 1; j < parsed.length; j += 1) {
1789
+ const a = parsed[i];
1790
+ const b = parsed[j];
1791
+ if (normaliseClause(a.parts.when) !== normaliseClause(b.parts.when)) continue;
1792
+ if (!thensNegateEachOther(a.parts.then, b.parts.then)) continue;
1793
+ const pairKey = `${us.usId}:${a.ac.id ?? '?'}:${b.ac.id ?? '?'}`;
1794
+ if (reported.has(pairKey)) continue;
1795
+ reported.add(pairKey);
1796
+ const idA = a.ac.id ?? us.usId;
1797
+ const idB = b.ac.id ?? us.usId;
1798
+ contradictionFindings.push({
1799
+ id: us.usId,
1800
+ why: `ACs ${idA} and ${idB} share a when clause with a negated then`,
1801
+ });
1802
+ }
1803
+ }
1804
+ }
1805
+ checks.push(makeCheck(
1806
+ 'consistency:contradictions',
1807
+ 'delta',
1808
+ Math.max(totalStoriesScanned, 1),
1809
+ contradictionFindings,
1810
+ ));
1811
+
1812
+ // Scan 2: consistency:unsatisfiable (engineer, over delta). A `then`
1813
+ // naming a field that no recordShape anywhere in the tree defines
1814
+ // fails the AC with id `<acId>:<field>`. A field defined in a
1815
+ // `[draft]` recordShape counts as defined (the engineer owns the
1816
+ // draft; its `fields:` list is honest about what the then may name).
1817
+ const definedFields = collectRecordShapeFields(tree);
1818
+ /** @type {Array<{ id: string, why: string }>} */
1819
+ const unsatisfiableFindings = [];
1820
+ let totalThenFieldChecks = 0;
1821
+ for (const us of usInScope) {
1822
+ const acs = Array.isArray(us.acceptanceCriteria) ? us.acceptanceCriteria : [];
1823
+ for (const ac of acs) {
1824
+ const parts = parseWhenThen(ac?.description);
1825
+ if (!parts) continue;
1826
+ const fields = extractThenFieldTokens(parts.then);
1827
+ for (const field of fields) {
1828
+ totalThenFieldChecks += 1;
1829
+ if (definedFields.has(field)) continue;
1830
+ unsatisfiableFindings.push({
1831
+ id: `${ac.id ?? us.usId}:${field}`,
1832
+ why: `then names field ${field} that no recordShape defines`,
1833
+ });
1834
+ }
1835
+ }
1836
+ }
1837
+ checks.push(makeCheck(
1838
+ 'consistency:unsatisfiable',
1839
+ 'delta',
1840
+ Math.max(totalThenFieldChecks, 1),
1841
+ unsatisfiableFindings,
1842
+ ));
1843
+
1844
+ // Scan 3: consistency:duplicates (engineer, over tree). Identical AC
1845
+ // descriptions across stories fail both ACs. The comparison trims
1846
+ // leading whitespace and the leading `[class]` marker.
1847
+ /** @type {Map<string, Array<{ usId: string, acId: string }>>} */
1848
+ const descBuckets = new Map();
1849
+ const allUs = tree.userStories ?? [];
1850
+ let totalDupAcs = 0;
1851
+ for (const us of allUs) {
1852
+ const acs = Array.isArray(us.acceptanceCriteria) ? us.acceptanceCriteria : [];
1853
+ for (const ac of acs) {
1854
+ const desc = typeof ac?.description === 'string' ? ac.description.trim() : '';
1855
+ if (desc.length === 0) continue;
1856
+ totalDupAcs += 1;
1857
+ const normalised = desc.replace(AC_CLASS_RE, '').trim().toLowerCase();
1858
+ if (normalised.length === 0) continue;
1859
+ const bucket = descBuckets.get(normalised) ?? [];
1860
+ bucket.push({ usId: us.usId, acId: ac.id ?? us.usId });
1861
+ descBuckets.set(normalised, bucket);
1862
+ }
1863
+ }
1864
+ /** @type {Array<{ id: string, why: string }>} */
1865
+ const duplicateFindings = [];
1866
+ for (const bucket of descBuckets.values()) {
1867
+ if (bucket.length < 2) continue;
1868
+ const stories = [...new Set(bucket.map((b) => b.usId))];
1869
+ if (stories.length < 2) continue;
1870
+ for (const entry of bucket) {
1871
+ duplicateFindings.push({
1872
+ id: entry.acId,
1873
+ why: `duplicate description (also on ${bucket.filter((b) => b.acId !== entry.acId).map((b) => b.acId).join(', ')})`,
1874
+ });
1875
+ }
1876
+ }
1877
+ checks.push(makeCheck(
1878
+ 'consistency:duplicates',
1879
+ 'tree',
1880
+ Math.max(totalDupAcs, 1),
1881
+ duplicateFindings,
1882
+ ));
1883
+
1884
+ // Scan 4: consistency:orphanInterfaces (engineer, over tree). An
1885
+ // interface on any TAC that no AC `ownerRef` points at AND that no
1886
+ // REQ `deliveredBy` reaches fails. Shares the `interfaces[<name>]`
1887
+ // pointer grammar with D4 `stories:ownerRefResolves`. A REQ's
1888
+ // `deliveredBy` reaches an interface when it names the owning TAC id
1889
+ // (either as a `tacId` string or as a `TAC-nnnn:<name>` pointer).
1890
+ const reachedInterfaces = collectReachedInterfaces(tree);
1891
+ /** @type {Array<{ id: string, why: string }>} */
1892
+ const orphanFindings = [];
1893
+ let totalInterfacesScanned = 0;
1894
+ for (const tac of tree.tacs ?? []) {
1895
+ const list = Array.isArray(tac?.interfaces) ? tac.interfaces : [];
1896
+ for (const iface of list) {
1897
+ const name = typeof iface?.name === 'string' ? iface.name : null;
1898
+ if (!name) continue;
1899
+ totalInterfacesScanned += 1;
1900
+ const key = `${tac.tacId}:${name}`;
1901
+ if (reachedInterfaces.has(key)) continue;
1902
+ orphanFindings.push({
1903
+ id: key,
1904
+ why: 'no AC ownerRef and no REQ deliveredBy reaches it',
1905
+ });
1906
+ }
1907
+ }
1908
+ checks.push(makeCheck(
1909
+ 'consistency:orphanInterfaces',
1910
+ 'tree',
1911
+ Math.max(totalInterfacesScanned, 1),
1912
+ orphanFindings,
1913
+ ));
1914
+
936
1915
  return foldState('D6', gate, checks, {
937
1916
  currentTreeHash: ctx.currentTreeHash ?? null,
938
1917
  freezeGates: /** @type {any} */ (ctx.freeze?.gates),
939
1918
  });
940
1919
  }
941
1920
 
1921
+ /**
1922
+ * Parse an AC description into { when, then } clause strings. Accepts
1923
+ * the common "given ... when ... then ..." shape used across the ACs
1924
+ * of this codebase; returns null when the description does not carry
1925
+ * both a `when` and a `then` segment. The leading `[class]` marker is
1926
+ * stripped before the scan. The match is case-insensitive on the
1927
+ * keywords only; the clause bodies keep their original casing.
1928
+ *
1929
+ * @param {unknown} desc
1930
+ * @returns {{ when: string, then: string } | null}
1931
+ */
1932
+ function parseWhenThen(desc) {
1933
+ if (typeof desc !== 'string' || desc.length === 0) return null;
1934
+ const stripped = desc.replace(AC_CLASS_RE, '').trim();
1935
+ const re = /\bwhen\b([\s\S]*?)\bthen\b([\s\S]*)$/i;
1936
+ const m = stripped.match(re);
1937
+ if (!m) return null;
1938
+ const when = m[1].trim();
1939
+ const then = m[2].trim();
1940
+ if (when.length === 0 || then.length === 0) return null;
1941
+ return { when, then };
1942
+ }
1943
+
1944
+ /**
1945
+ * Normalise a clause for the contradictions scan: lower-case, trim,
1946
+ * collapse whitespace. A clause is "the same" between two ACs when
1947
+ * their normalised forms match.
1948
+ *
1949
+ * @param {string} clause
1950
+ * @returns {string}
1951
+ */
1952
+ function normaliseClause(clause) {
1953
+ return clause.toLowerCase().replace(/\s+/g, ' ').trim();
1954
+ }
1955
+
1956
+ /**
1957
+ * Strip double-quoted substrings and then test whether one `then`
1958
+ * clause is the negation of the other. "Negation" is a cheap test: one
1959
+ * clause begins (or carries, after a verb) a `not`, `no`, `does not`,
1960
+ * `is not`, `never`, `must not` token where the other clause does not;
1961
+ * or the two clauses are the same body with one carrying such a token.
1962
+ * The quoted-substring strip is the shared guard with D4.
1963
+ *
1964
+ * @param {string} a
1965
+ * @param {string} b
1966
+ * @returns {boolean}
1967
+ */
1968
+ function thensNegateEachOther(a, b) {
1969
+ const aPlain = normaliseClause(stripQuotedSubstrings(a));
1970
+ const bPlain = normaliseClause(stripQuotedSubstrings(b));
1971
+ if (aPlain === bPlain) return false;
1972
+ const NEG_RE = /\b(?:not|no|never|does not|is not|must not|cannot|won't|will not)\b/;
1973
+ const aNeg = NEG_RE.test(aPlain);
1974
+ const bNeg = NEG_RE.test(bPlain);
1975
+ if (aNeg === bNeg) return false;
1976
+ // One side negates; test the negated body against the positive one.
1977
+ const positive = aNeg ? bPlain : aPlain;
1978
+ const negative = aNeg ? aPlain : bPlain;
1979
+ const negativeStripped = negative.replace(NEG_RE, '').replace(/\s+/g, ' ').trim();
1980
+ // A sufficiently similar body is "the same claim with a negation".
1981
+ // We treat the shorter being a prefix / suffix / substring of the
1982
+ // longer, or sharing 80% of its tokens, as "same body".
1983
+ if (negativeStripped.length === 0) return false;
1984
+ if (positive.includes(negativeStripped) || negativeStripped.includes(positive)) return true;
1985
+ const posTokens = new Set(positive.split(/\s+/).filter((t) => t.length > 2));
1986
+ const negTokens = negativeStripped.split(/\s+/).filter((t) => t.length > 2);
1987
+ if (negTokens.length === 0) return false;
1988
+ const shared = negTokens.filter((t) => posTokens.has(t)).length;
1989
+ return shared / negTokens.length >= 0.6;
1990
+ }
1991
+
1992
+ /**
1993
+ * Collect every field name defined by any `recordShape` interface in
1994
+ * the tree. A `fields:` marker in the interface description introduces
1995
+ * a list of field names; each name is a token on a bullet, a line, or
1996
+ * a comma-separated list. Draft recordShapes are included (the
1997
+ * engineer owns the draft and its fields: list is honest).
1998
+ *
1999
+ * @param {import('#core/store/walker.js').TreeModel} tree
2000
+ * @returns {Set<string>}
2001
+ */
2002
+ function collectRecordShapeFields(tree) {
2003
+ const out = new Set();
2004
+ for (const tac of tree.tacs ?? []) {
2005
+ for (const iface of tac.interfaces ?? []) {
2006
+ if (iface?.kind !== 'recordShape') continue;
2007
+ const desc = typeof iface?.description === 'string' ? iface.description : '';
2008
+ const stripped = stripDraftPrefix(desc);
2009
+ // Find the `fields:` segment and read until the next `:` or end.
2010
+ const match = stripped.match(/(^|\n)\s*(?:[-*]\s*)?fields\s*:\s*([\s\S]*?)(?=(?:\n\s*(?:[-*]\s*)?[a-zA-Z][a-zA-Z0-9_]*\s*:)|$)/);
2011
+ if (!match) continue;
2012
+ const body = match[2];
2013
+ for (const token of body.split(/[\s,]+/)) {
2014
+ const name = token.replace(/^[-*]/, '').replace(/[:(){}\[\]]/g, '').trim();
2015
+ if (!name) continue;
2016
+ if (/^[A-Za-z_][A-Za-z0-9_]*$/.test(name)) out.add(name);
2017
+ }
2018
+ }
2019
+ }
2020
+ return out;
2021
+ }
2022
+
2023
+ /**
2024
+ * Pull field tokens out of a `then` clause. A field token is a word
2025
+ * that follows a verb like `set`, `write`, `include`, `return`,
2026
+ * `contain`, `name` or appears as the direct object of a `then`'s
2027
+ * verb phrase; a cheap approximation uses `then <subject> <verb>
2028
+ * <field>` plus `field <name>`, `<name> field` and `field: <name>`
2029
+ * patterns. The scan is deliberately conservative so a plain English
2030
+ * sentence yields a small set.
2031
+ *
2032
+ * @param {string} thenClause
2033
+ * @returns {string[]}
2034
+ */
2035
+ function extractThenFieldTokens(thenClause) {
2036
+ if (typeof thenClause !== 'string' || thenClause.length === 0) return [];
2037
+ const text = stripQuotedSubstrings(thenClause);
2038
+ /** @type {Set<string>} */
2039
+ const tokens = new Set();
2040
+ // Pattern 1: backticked identifier (`then `balance` is set`). The
2041
+ // primary signal; prose that quotes a field name under backticks is
2042
+ // the convention this check expects.
2043
+ for (const m of text.matchAll(/`([A-Za-z_][A-Za-z0-9_]*)`/g)) {
2044
+ if (m[1]) tokens.add(m[1]);
2045
+ }
2046
+ // Pattern 2: `<name> field` (adjective-form naming). An English
2047
+ // "stop word" skip keeps "the field", "a field" and "its field" from
2048
+ // tripping the check.
2049
+ const STOP = new Set(['the', 'a', 'an', 'this', 'that', 'its', 'our', 'their', 'any', 'no', 'some', 'each', 'every', 'another']);
2050
+ for (const m of text.matchAll(/\b([A-Za-z_][A-Za-z0-9_]*)\s+field\b/g)) {
2051
+ const token = m[1];
2052
+ if (!token) continue;
2053
+ if (STOP.has(token.toLowerCase())) continue;
2054
+ tokens.add(token);
2055
+ }
2056
+ // Pattern 3: `field: <name>` or `field = <name>` (schema-like
2057
+ // notation inside a then clause).
2058
+ for (const m of text.matchAll(/\bfield\s*[:=]\s*([A-Za-z_][A-Za-z0-9_]*)/g)) {
2059
+ if (m[1]) tokens.add(m[1]);
2060
+ }
2061
+ return [...tokens];
2062
+ }
2063
+
2064
+ /**
2065
+ * Collect every interface the tree "reaches" from an AC `ownerRef` or
2066
+ * a REQ `deliveredBy` (REQ-174 companion field). The result is a Set
2067
+ * of `<tacId>:<name>` keys. A `deliveredBy` on a REQ can take two
2068
+ * shapes: an array of `TAC-nnnn:<name>` pointer strings, or an array
2069
+ * of plain TAC ids ("delivered by this TAC"); the second shape reaches
2070
+ * every interface on the named TAC.
2071
+ *
2072
+ * @param {import('#core/store/walker.js').TreeModel} tree
2073
+ * @returns {Set<string>}
2074
+ */
2075
+ function collectReachedInterfaces(tree) {
2076
+ const out = new Set();
2077
+ // AC ownerRefs.
2078
+ for (const us of tree.userStories ?? []) {
2079
+ const acs = Array.isArray(us.acceptanceCriteria) ? us.acceptanceCriteria : [];
2080
+ for (const ac of acs) {
2081
+ if (!acHasOwnerRef(ac)) continue;
2082
+ const ref = /** @type {any} */ (ac).ownerRef;
2083
+ const name = parseOwnerRefInterfaceField(ref?.field);
2084
+ if (!name || typeof ref?.tacId !== 'string') continue;
2085
+ out.add(`${ref.tacId}:${name}`);
2086
+ }
2087
+ }
2088
+ // REQ deliveredBy (optional field; shapes above).
2089
+ for (const req of tree.requirements ?? []) {
2090
+ const deliveredBy = /** @type {any} */ (req)?.deliveredBy;
2091
+ if (!Array.isArray(deliveredBy)) continue;
2092
+ for (const entry of deliveredBy) {
2093
+ if (typeof entry !== 'string' || entry.length === 0) continue;
2094
+ const m = entry.match(/^(TAC-[A-Za-z0-9-]+):(.+)$/);
2095
+ if (m) {
2096
+ out.add(`${m[1]}:${m[2]}`);
2097
+ continue;
2098
+ }
2099
+ // Plain TAC id: every interface on that TAC is reached.
2100
+ const tac = (tree.tacs ?? []).find((t) => t?.tacId === entry);
2101
+ if (!tac) continue;
2102
+ for (const iface of tac.interfaces ?? []) {
2103
+ if (typeof iface?.name === 'string') out.add(`${tac.tacId}:${iface.name}`);
2104
+ }
2105
+ }
2106
+ }
2107
+ return out;
2108
+ }
2109
+
942
2110
  // ---------------------------------------------------------------------------
943
2111
  // D7 -- Decisions and review (blocking in 0.29.0).
944
2112
  // ---------------------------------------------------------------------------