@maycombhq/atticus 0.0.0-stage → 2.0.0-beta.2

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 (475) hide show
  1. package/LICENSE +177 -0
  2. package/README.md +17 -2
  3. package/THIRD-PARTY-LICENSES.txt +2607 -0
  4. package/dist/bin.js +47 -0
  5. package/dist/chunk-23W7VWKR.js +2609 -0
  6. package/dist/chunk-27NKUS3X.js +4330 -0
  7. package/dist/chunk-2ANOROX3.js +2522 -0
  8. package/dist/chunk-2BF2EYJV.js +174 -0
  9. package/dist/chunk-2BFCZ3RK.js +315 -0
  10. package/dist/chunk-2DIQQJCB.js +378 -0
  11. package/dist/chunk-2RMYG36Q.js +1227 -0
  12. package/dist/chunk-2VHF7OXM.js +55 -0
  13. package/dist/chunk-3ALD2W2A.js +95 -0
  14. package/dist/chunk-3C7EYRFZ.js +41 -0
  15. package/dist/chunk-3G4YI4ZU.js +16 -0
  16. package/dist/chunk-3HI6Z55Y.js +5949 -0
  17. package/dist/chunk-3USYZGRF.js +324 -0
  18. package/dist/chunk-42EVSKME.js +37 -0
  19. package/dist/chunk-4AK7IBVP.js +915 -0
  20. package/dist/chunk-4BKGMUIK.js +53 -0
  21. package/dist/chunk-4BN53TG3.js +343 -0
  22. package/dist/chunk-4NDAAFQT.js +103 -0
  23. package/dist/chunk-4Q3NN7VF.js +32 -0
  24. package/dist/chunk-4RS5KZQD.js +25 -0
  25. package/dist/chunk-4SKZDI62.js +22 -0
  26. package/dist/chunk-4WBVUHXN.js +69 -0
  27. package/dist/chunk-5GDRCDQB.js +32 -0
  28. package/dist/chunk-5GGOLAKC.js +856 -0
  29. package/dist/chunk-5KLGBXG5.js +48 -0
  30. package/dist/chunk-5WG5YP4T.js +34 -0
  31. package/dist/chunk-64EQYWCA.js +180 -0
  32. package/dist/chunk-652QWTLZ.js +242 -0
  33. package/dist/chunk-65NYPGRC.js +766 -0
  34. package/dist/chunk-66YVAGGM.js +46 -0
  35. package/dist/chunk-6BNC6EQ4.js +41 -0
  36. package/dist/chunk-6BVONWJ7.js +50 -0
  37. package/dist/chunk-6D2CQ5II.js +41 -0
  38. package/dist/chunk-6IU67AEK.js +325 -0
  39. package/dist/chunk-6J5OKA4Y.js +49 -0
  40. package/dist/chunk-6JCPI55B.js +92 -0
  41. package/dist/chunk-6JUBZBMW.js +56 -0
  42. package/dist/chunk-6M5NK3K3.js +415 -0
  43. package/dist/chunk-6QSERWXH.js +53 -0
  44. package/dist/chunk-6TACQN3N.js +41 -0
  45. package/dist/chunk-76WKMA4J.js +14 -0
  46. package/dist/chunk-7AVHLZGD.js +45 -0
  47. package/dist/chunk-7EFILTCI.js +67 -0
  48. package/dist/chunk-7EKXJZ2Y.js +2902 -0
  49. package/dist/chunk-7EOBHUMC.js +133 -0
  50. package/dist/chunk-7FBGJFEE.js +66 -0
  51. package/dist/chunk-7JUKDRSZ.js +1726 -0
  52. package/dist/chunk-7SW2QWLU.js +212 -0
  53. package/dist/chunk-7WD63HU2.js +143 -0
  54. package/dist/chunk-7ZUIMTOU.js +108 -0
  55. package/dist/chunk-A3GY6SOA.js +95 -0
  56. package/dist/chunk-A7UPUQFY.js +2356 -0
  57. package/dist/chunk-AA6YULYB.js +376 -0
  58. package/dist/chunk-ABWHYWNI.js +101 -0
  59. package/dist/chunk-AIOQPLA5.js +540 -0
  60. package/dist/chunk-AVJDSJ2F.js +18 -0
  61. package/dist/chunk-B2WLAWNJ.js +374 -0
  62. package/dist/chunk-BKVWTZ6A.js +211 -0
  63. package/dist/chunk-BOHJZTEQ.js +1991 -0
  64. package/dist/chunk-BWZ77RQT.js +25 -0
  65. package/dist/chunk-C6EKFH7J.js +169 -0
  66. package/dist/chunk-CAQZUNOH.js +1150 -0
  67. package/dist/chunk-CEXSU4S6.js +1217 -0
  68. package/dist/chunk-CKSITVS4.js +16101 -0
  69. package/dist/chunk-CNUKCS2T.js +2741 -0
  70. package/dist/chunk-CPA6HPVR.js +3206 -0
  71. package/dist/chunk-CR3MTH32.js +207 -0
  72. package/dist/chunk-CSZ4C5N6.js +307 -0
  73. package/dist/chunk-D3PO4DOZ.js +261 -0
  74. package/dist/chunk-D46WUV3T.js +33 -0
  75. package/dist/chunk-DE76JROX.js +80 -0
  76. package/dist/chunk-DFBCSHVT.js +69 -0
  77. package/dist/chunk-DHPACDG7.js +104 -0
  78. package/dist/chunk-DKJA76CJ.js +113 -0
  79. package/dist/chunk-DPUYDDQG.js +164 -0
  80. package/dist/chunk-DPZHZQKE.js +285 -0
  81. package/dist/chunk-E36QOJMD.js +47 -0
  82. package/dist/chunk-EADP3PEN.js +450 -0
  83. package/dist/chunk-EBEW3XXQ.js +166 -0
  84. package/dist/chunk-EDS2L2LD.js +106 -0
  85. package/dist/chunk-EFHQ3TWP.js +637 -0
  86. package/dist/chunk-EPTBZ3GP.js +101 -0
  87. package/dist/chunk-EYWIDJFU.js +130 -0
  88. package/dist/chunk-F7HYOUFF.js +287 -0
  89. package/dist/chunk-FHH4I4ZV.js +128 -0
  90. package/dist/chunk-FITWGOJ2.js +131 -0
  91. package/dist/chunk-FQXYPF7E.js +147 -0
  92. package/dist/chunk-G2B4ZQGH.js +240 -0
  93. package/dist/chunk-GBRFVT63.js +45 -0
  94. package/dist/chunk-GDLULHTC.js +2919 -0
  95. package/dist/chunk-GLUX4EEP.js +583 -0
  96. package/dist/chunk-GQ4N4WKF.js +1142 -0
  97. package/dist/chunk-GT4I4ZWM.js +38 -0
  98. package/dist/chunk-HFQCFSJR.js +60 -0
  99. package/dist/chunk-HITVBIJS.js +1247 -0
  100. package/dist/chunk-HLJAXMM4.js +233 -0
  101. package/dist/chunk-HVUPKCGJ.js +162 -0
  102. package/dist/chunk-I3E7CX4H.js +155 -0
  103. package/dist/chunk-I4JRCD6M.js +184 -0
  104. package/dist/chunk-ICY36XCH.js +34 -0
  105. package/dist/chunk-IHMLFRVV.js +228 -0
  106. package/dist/chunk-IPKHE5D6.js +1963 -0
  107. package/dist/chunk-J4K3KVLD.js +131 -0
  108. package/dist/chunk-JBTK5OP2.js +55 -0
  109. package/dist/chunk-JCZIKA4C.js +163 -0
  110. package/dist/chunk-JGZCG5VM.js +189 -0
  111. package/dist/chunk-JIITQXFB.js +4087 -0
  112. package/dist/chunk-JMSCMUCA.js +271 -0
  113. package/dist/chunk-JZU3H6UQ.js +54 -0
  114. package/dist/chunk-K65BJIMT.js +49 -0
  115. package/dist/chunk-KEM4SDDP.js +3898 -0
  116. package/dist/chunk-KQDZXGNR.js +14 -0
  117. package/dist/chunk-L24C55VN.js +7923 -0
  118. package/dist/chunk-L6SGQIR3.js +471 -0
  119. package/dist/chunk-LR3R6Z2A.js +400 -0
  120. package/dist/chunk-M766ZJ6W.js +119 -0
  121. package/dist/chunk-MC3H7736.js +19910 -0
  122. package/dist/chunk-MGYZM27B.js +205 -0
  123. package/dist/chunk-MMOSZPWJ.js +273 -0
  124. package/dist/chunk-MVZVGYXH.js +1611 -0
  125. package/dist/chunk-N7IXEHK3.js +549 -0
  126. package/dist/chunk-NE2W3OO7.js +230 -0
  127. package/dist/chunk-NN2ZQEB4.js +38 -0
  128. package/dist/chunk-NXFPS2LR.js +182 -0
  129. package/dist/chunk-O3WI5KWW.js +31 -0
  130. package/dist/chunk-OLQJTJJU.js +76 -0
  131. package/dist/chunk-ONLS5QA5.js +102 -0
  132. package/dist/chunk-OT2O76OS.js +1496 -0
  133. package/dist/chunk-PAMPPUR6.js +4500 -0
  134. package/dist/chunk-PCOCACY3.js +385 -0
  135. package/dist/chunk-PCVDV3UZ.js +430 -0
  136. package/dist/chunk-PRPPGYZG.js +104 -0
  137. package/dist/chunk-Q4D5X7QB.js +264 -0
  138. package/dist/chunk-Q5AMFEWD.js +119 -0
  139. package/dist/chunk-QRAOANID.js +214 -0
  140. package/dist/chunk-QSXK2RGH.js +688 -0
  141. package/dist/chunk-QZSX3F7C.js +389 -0
  142. package/dist/chunk-R6RY4Q5T.js +51 -0
  143. package/dist/chunk-R6XF6UR3.js +149 -0
  144. package/dist/chunk-R77KLRB3.js +166 -0
  145. package/dist/chunk-RRTKKSLQ.js +251 -0
  146. package/dist/chunk-RTEYOSJY.js +29 -0
  147. package/dist/chunk-RUVFXE2L.js +666 -0
  148. package/dist/chunk-RVH5SUW5.js +69 -0
  149. package/dist/chunk-RZPYKDWS.js +26 -0
  150. package/dist/chunk-S2A7YC3Q.js +41433 -0
  151. package/dist/chunk-S3QNRWYR.js +25 -0
  152. package/dist/chunk-SJRGMG6A.js +174 -0
  153. package/dist/chunk-SP2I63OO.js +252 -0
  154. package/dist/chunk-T2UYZSCQ.js +545 -0
  155. package/dist/chunk-T6AIP7H5.js +3851 -0
  156. package/dist/chunk-T6XQL73F.js +94 -0
  157. package/dist/chunk-TANFV3MZ.js +531 -0
  158. package/dist/chunk-TDD55CJH.js +119 -0
  159. package/dist/chunk-TV45EUGM.js +51 -0
  160. package/dist/chunk-TXLH6WHQ.js +2078 -0
  161. package/dist/chunk-TYAID7B7.js +408 -0
  162. package/dist/chunk-UBBC2XSG.js +873 -0
  163. package/dist/chunk-UGLN7QHV.js +27 -0
  164. package/dist/chunk-UNM6ZOKP.js +878 -0
  165. package/dist/chunk-V2YTAIQO.js +1075 -0
  166. package/dist/chunk-VN3DP4LQ.js +43 -0
  167. package/dist/chunk-VOGCSYOI.js +16 -0
  168. package/dist/chunk-VYDBJ73M.js +32 -0
  169. package/dist/chunk-W3BQAZ3Q.js +34 -0
  170. package/dist/chunk-W5BVQF44.js +36 -0
  171. package/dist/chunk-WVPJSRRJ.js +52 -0
  172. package/dist/chunk-WY6PP6AA.js +53 -0
  173. package/dist/chunk-XAKWMCXI.js +285 -0
  174. package/dist/chunk-XPCM366L.js +70 -0
  175. package/dist/chunk-XPTOBS2D.js +48 -0
  176. package/dist/chunk-XY3P7JW7.js +3479 -0
  177. package/dist/chunk-XZRON6IV.js +131 -0
  178. package/dist/chunk-YEDDOYSC.js +27809 -0
  179. package/dist/chunk-YISXLPHN.js +496 -0
  180. package/dist/chunk-YMZ3TNYB.js +18 -0
  181. package/dist/chunk-YY6ZQQBP.js +203 -0
  182. package/dist/chunk-YYQN46FY.js +334 -0
  183. package/dist/chunk-Z6LF7HQN.js +22 -0
  184. package/dist/chunk-ZCJDOK2S.js +116 -0
  185. package/dist/chunk-ZDPAS56H.js +76 -0
  186. package/dist/chunk-ZMAINWBW.js +18 -0
  187. package/dist/chunk-ZMFPW66A.js +22 -0
  188. package/dist/chunk-ZNCEKR4J.js +296 -0
  189. package/dist/chunk-ZVM6AKKM.js +47 -0
  190. package/dist/files.json +1888 -0
  191. package/dist/fixtures/forge/README.md +19 -0
  192. package/dist/fixtures/forge/expected/discrepancies.yaml +54 -0
  193. package/dist/fixtures/forge/expected/inputs.yaml +38 -0
  194. package/dist/fixtures/forge/expected/scan.yaml +342 -0
  195. package/dist/fixtures/forge/inputs/diagrams/forge-context.drawio +23 -0
  196. package/dist/fixtures/forge/inputs/partner-specs/northwind-pay-openapi.yaml +11 -0
  197. package/dist/fixtures/forge/inputs/tickets/ado-stories.json +4 -0
  198. package/dist/fixtures/forge/inputs/tickets/closed-service-requests.json +5 -0
  199. package/dist/fixtures/forge/inputs/wiki/integration-patterns.md +11 -0
  200. package/dist/fixtures/forge/inputs/wiki/ledger-solution-spec.md +9 -0
  201. package/dist/fixtures/forge/inputs/wiki/snow-firewall-request.md +4 -0
  202. package/dist/fixtures/forge/metarepo/judgments/reaches/84af5b6af24f7ca8c23013f3.yaml +17 -0
  203. package/dist/fixtures/forge/metarepo/judgments/reaches/c3917555edebddce8cecb647.yaml +17 -0
  204. package/dist/fixtures/forge/metarepo/judgments/reaches/c5fafd6601f8ca9e34e0bbd0.yaml +17 -0
  205. package/dist/fixtures/forge/metarepo/org-pack/agents/architecture-critic.yaml +9 -0
  206. package/dist/fixtures/forge/metarepo/org-pack/agents/story-writer.yaml +10 -0
  207. package/dist/fixtures/forge/metarepo/org-pack/checklists/architecture.yaml +115 -0
  208. package/dist/fixtures/forge/metarepo/org-pack/dialects/forge.yaml +111 -0
  209. package/dist/fixtures/forge/metarepo/org-pack/gates.yaml +22 -0
  210. package/dist/fixtures/forge/metarepo/org-pack/pack.yaml +11 -0
  211. package/dist/fixtures/forge/metarepo/org-pack/patterns/A.EB.PUB.yaml +12 -0
  212. package/dist/fixtures/forge/metarepo/org-pack/patterns/D.JDBC.yaml +12 -0
  213. package/dist/fixtures/forge/metarepo/org-pack/patterns/S.DIR.BFF.yaml +12 -0
  214. package/dist/fixtures/forge/metarepo/org-pack/patterns/S.GW.SOR.yaml +13 -0
  215. package/dist/fixtures/forge/metarepo/org-pack/patterns/S.GW.VND.yaml +14 -0
  216. package/dist/fixtures/forge/metarepo/org-pack/process/change-templates/feature.md +37 -0
  217. package/dist/fixtures/forge/metarepo/org-pack/process/skills/add-forge-endpoint/SKILL.md +17 -0
  218. package/dist/fixtures/forge/metarepo/org-pack/process/snow/firewall-rule.yaml +14 -0
  219. package/dist/fixtures/forge/metarepo/org-pack/process/snow/gateway-route.yaml +13 -0
  220. package/dist/fixtures/forge/metarepo/org-pack/profiles/forge/profile.yaml +12 -0
  221. package/dist/fixtures/forge/metarepo/org-pack/profiles/forge/repos.manifest.yaml +44 -0
  222. package/dist/fixtures/forge/metarepo/org-pack/roles.yaml +14 -0
  223. package/dist/fixtures/forge/metarepo/org-pack/runtime.yaml +14 -0
  224. package/dist/fixtures/forge/metarepo/org-pack/sources.yaml +3 -0
  225. package/dist/fixtures/forge/repos/forge-events/topics/payments.initiated.yaml +4 -0
  226. package/dist/fixtures/forge/repos/forge-events/topics/transfers.completed.yaml +4 -0
  227. package/dist/fixtures/forge/repos/forge-gateway/proxies/ledger-v1/apiproxy/ledger-v1.xml +3 -0
  228. package/dist/fixtures/forge/repos/forge-gateway/proxies/ledger-v1/apiproxy/policies/SpikeArrest.xml +3 -0
  229. package/dist/fixtures/forge/repos/forge-gateway/proxies/ledger-v1/apiproxy/policies/VerifyOAuth.xml +4 -0
  230. package/dist/fixtures/forge/repos/forge-gateway/proxies/ledger-v1/apiproxy/proxies/default.xml +14 -0
  231. package/dist/fixtures/forge/repos/forge-gateway/proxies/ledger-v1/apiproxy/targets/ledger.xml +5 -0
  232. package/dist/fixtures/forge/repos/forge-infra/alerts/ledger-api.yaml +5 -0
  233. package/dist/fixtures/forge/repos/forge-infra/k8s/ledger-api.yaml +15 -0
  234. package/dist/fixtures/forge/repos/forge-infra/k8s/portal-bff.yaml +7 -0
  235. package/dist/fixtures/forge/repos/forge-infra/terraform/ledger-db.tf +9 -0
  236. package/dist/fixtures/forge/repos/forge-ledger/api/ledger-openapi.yaml +31 -0
  237. package/dist/fixtures/forge/repos/forge-ledger/forge.yaml +4 -0
  238. package/dist/fixtures/forge/repos/forge-ledger/src/main/java/forge/ledger/LedgerEndpoints.java +13 -0
  239. package/dist/fixtures/forge/repos/forge-ledger/src/main/java/forge/ledger/LedgerEvents.java +11 -0
  240. package/dist/fixtures/forge/repos/forge-ledger/src/main/java/forge/ledger/NorthwindClient.java +10 -0
  241. package/dist/fixtures/forge/repos/forge-ledger/src/main/resources/application.yml +3 -0
  242. package/dist/fixtures/forge/repos/forge-ledger/src/main/resources/db/migration/V1__create_account.sql +5 -0
  243. package/dist/fixtures/forge/repos/forge-ledger/src/main/resources/db/migration/V2__create_entry.sql +7 -0
  244. package/dist/fixtures/forge/repos/forge-portal-bff/pom.xml +1 -0
  245. package/dist/fixtures/forge/repos/forge-portal-bff/src/main/java/forge/portal/AuditPublisher.java +12 -0
  246. package/dist/fixtures/forge/repos/forge-portal-bff/src/main/java/forge/portal/BalanceController.java +16 -0
  247. package/dist/fixtures/forge/repos/forge-portal-bff/src/main/java/forge/portal/LedgerClient.java +13 -0
  248. package/dist/fixtures/forge/repos/forge-portal-bff/src/main/java/forge/portal/PaymentEvents.java +13 -0
  249. package/dist/fixtures/forge/repos/forge-portal-bff/src/main/resources/application.yml +8 -0
  250. package/dist/fixtures/forge/repos/forge-portal-ui/package.json +1 -0
  251. package/dist/fixtures/forge/repos/forge-portal-ui/src/api/balance.ts +5 -0
  252. package/dist/fixtures/forge/repos/forge-reports-job/src/main/java/forge/reports/DailyEntriesJob.java +19 -0
  253. package/dist/fixtures/forge/repos/forge-reports-job/src/main/resources/application.yml +3 -0
  254. package/dist/fixtures/forge-change/README.md +41 -0
  255. package/dist/fixtures/forge-change/expected/findings.yaml +301 -0
  256. package/dist/fixtures/forge-change/expected/stories.yaml +101 -0
  257. package/dist/fixtures/forge-change/judgments/personal-data/0b5f3dbf5257a22275d8c74b.yaml +18 -0
  258. package/dist/fixtures/forge-change/judgments/personal-data/2759a66770134c417440bf2d.yaml +18 -0
  259. package/dist/fixtures/forge-change/judgments/personal-data/31b1ea2f14d0737f1aca79fd.yaml +18 -0
  260. package/dist/fixtures/forge-change/judgments/personal-data/49afd70c08228e65ad6ca1ed.yaml +18 -0
  261. package/dist/fixtures/forge-change/judgments/personal-data/761cabcb8a39f5e5866d2dd6.yaml +18 -0
  262. package/dist/fixtures/forge-change/judgments/personal-data/adae902b90cc8ffa0c765145.yaml +18 -0
  263. package/dist/fixtures/forge-change/judgments/personal-data/ba11bb933105ec9493e065dd.yaml +18 -0
  264. package/dist/fixtures/forge-change/judgments/personal-data/bdbcd1cdac3021c68063c3e7.yaml +18 -0
  265. package/dist/fixtures/forge-change/openspec/changes/add-transfer-limit/brief.md +35 -0
  266. package/dist/fixtures/forge-change/openspec/changes/add-transfer-limit/change.yaml +120 -0
  267. package/dist/fixtures/forge-change/openspec/changes/add-transfer-limit/data.md +18 -0
  268. package/dist/fixtures/forge-change/openspec/changes/add-transfer-limit/design.md +29 -0
  269. package/dist/fixtures/forge-change/openspec/changes/add-transfer-limit/interfaces.md +17 -0
  270. package/dist/fixtures/forge-change/openspec/changes/add-transfer-limit/mappings.md +26 -0
  271. package/dist/fixtures/forge-change/openspec/changes/add-transfer-limit/proposal.md +35 -0
  272. package/dist/fixtures/forge-change/openspec/changes/add-transfer-limit/snow.md +12 -0
  273. package/dist/fixtures/forge-change/openspec/changes/add-transfer-limit/specs/transfer-limits/spec.md +19 -0
  274. package/dist/fixtures/forge-change/openspec/changes/add-transfer-limit/stories/s1-refuse-over-limit.md +17 -0
  275. package/dist/fixtures/forge-change/openspec/changes/add-transfer-limit/stories/s2-show-remaining.md +16 -0
  276. package/dist/fixtures/forge-change/openspec/changes/add-transfer-limit/stories/s3-audit-refusals.md +18 -0
  277. package/dist/fixtures/forge-change/openspec/changes/add-transfer-limit/stories/s4-velocity-check.md +16 -0
  278. package/dist/fixtures/forge-change/openspec/changes/add-transfer-limit/stories.md +8 -0
  279. package/dist/fixtures/forge-change/openspec/changes/add-transfer-limit/tasks.md +12 -0
  280. package/dist/fixtures/forge-change/openspec/changes/add-transfer-limit/ux.md +7 -0
  281. package/dist/fixtures/forge-change/org-pack/agents/code-and-test-critic.yaml +13 -0
  282. package/dist/fixtures/forge-change/org-pack/agents/complete-critic.yaml +12 -0
  283. package/dist/fixtures/forge-change/org-pack/agents/safe-critic.yaml +12 -0
  284. package/dist/fixtures/forge-change/org-pack/agents/ship-critic.yaml +11 -0
  285. package/dist/fixtures/forge-change/org-pack/agents/true-critic.yaml +11 -0
  286. package/dist/fixtures/forge-change/org-pack/checklists/review.yaml +54 -0
  287. package/dist/fixtures/forge-change/org-pack/gates.yaml +25 -0
  288. package/dist/fixtures/forge-change/org-pack/teams/team-ledger/checklists/ledger-team.yaml +227 -0
  289. package/dist/fixtures/forge-change/recordings/complete-critic/2ad84f84bf39c1d5412697e69fe23034d6983ec45a00314bf0975e627589a3c5.json +12 -0
  290. package/dist/fixtures/forge-change/recordings/complete-critic/417c98d8e54a4387d0fd93441c49f44c2868958739070d855c1dce0c41e24db3.json +12 -0
  291. package/dist/fixtures/forge-change/recordings/complete-critic/50203ee22e9cb3ef047295edb6538fe7d5695e1e4b139f3c929013dc6ce47021.json +12 -0
  292. package/dist/fixtures/forge-change/recordings/complete-critic/89f18d67f5d9c325bf35e2a9e020f9ddb6ee13b8523315037f0905cc57c040b1.json +12 -0
  293. package/dist/fixtures/forge-change/recordings/complete-critic/b4097867d26ae8eadc8b9efa8cdd86897013358035f0b40086c299a59c4ba121.json +12 -0
  294. package/dist/fixtures/forge-change/recordings/safe-critic/302d06f49664dd67ad2e21ab9cf74c1b0f7d3f750709c6ed8eff2b70983274e2.json +12 -0
  295. package/dist/fixtures/forge-change/recordings/safe-critic/32f1049c9a5ab4a759543290db4644ec6e221cc45fdfdcf06193837c6a8ce0b9.json +12 -0
  296. package/dist/fixtures/forge-change/recordings/safe-critic/4e4a84bfc04b9f26ca4250319a879901ff7a1c081c71e46a117675fee05026b0.json +12 -0
  297. package/dist/fixtures/forge-change/recordings/safe-critic/604af0fcdd6df6b76208fa88305fdc15c37606c2a4d1ae816477e46ac8c2dd04.json +12 -0
  298. package/dist/fixtures/forge-change/recordings/safe-critic/f0bf50af11f14c50d07904f0dffe1c8c20fb0cd89770645a8824c1d30a443955.json +12 -0
  299. package/dist/fixtures/forge-change/recordings/ship-critic/350954b58833b2c04880c67db45a1b328b7fd541d9f0d943b63905b8875488a6.json +12 -0
  300. package/dist/fixtures/forge-change/recordings/ship-critic/4af95c6c96a206777cec9de1f9c2d8c55a36ddc9b8db2f81d6eb83217b835efa.json +12 -0
  301. package/dist/fixtures/forge-change/recordings/ship-critic/76c34522a49cf7587a4e5689a5030d384603fa780b8aba97d27815cbc829683e.json +12 -0
  302. package/dist/fixtures/forge-change/recordings/ship-critic/a3b2cd1ace48587e5994333db03b34c3a0f9dec4f1932f1730ddfb687f6918c8.json +12 -0
  303. package/dist/fixtures/forge-change/recordings/ship-critic/de288a4fa64d0fc20890f9a787080ce6eac5203b7b9b72d884df11e8cf111835.json +12 -0
  304. package/dist/fixtures/forge-change/recordings/story-writer/1ddb00eac2aaf91a5ec5d9dfd220116be9f75aec6546a4a3a3b050ed89af2864.json +12 -0
  305. package/dist/packages/assistant-kit/frameworks-kit/README.md +86 -0
  306. package/dist/packages/assistant-kit/frameworks-kit/checklist.md +11 -0
  307. package/dist/packages/assistant-kit/frameworks-kit/examples/tide-lantern.yaml +56 -0
  308. package/dist/packages/assistant-kit/frameworks-kit/examples/tide-platform.yaml +43 -0
  309. package/dist/packages/assistant-kit/frameworks-kit/prompts/write-framework-model.md +12 -0
  310. package/dist/packages/assistant-kit/kit/README.md +98 -0
  311. package/dist/packages/assistant-kit/kit/c2-reference.md +334 -0
  312. package/dist/packages/assistant-kit/kit/checklist.md +39 -0
  313. package/dist/packages/assistant-kit/kit/examples/house-http-client.yaml +102 -0
  314. package/dist/packages/assistant-kit/kit/examples/tide-apigee.yaml +56 -0
  315. package/dist/packages/assistant-kit/kit/examples/tide-apim.yaml +32 -0
  316. package/dist/packages/assistant-kit/kit/examples/tide-kong.yaml +44 -0
  317. package/dist/packages/assistant-kit/kit/prompts/write-dialect.md +34 -0
  318. package/dist/packages/assistant-kit/kit/worked-example.md +198 -0
  319. package/dist/packages/conformance/sample/README.md +4 -0
  320. package/dist/packages/conformance/sample/inputs/notes.md +3 -0
  321. package/dist/packages/conformance/sample/inputs/systems.csv +3 -0
  322. package/dist/packages/conformance/sample/repo/api/greeter.proto +6 -0
  323. package/dist/packages/conformance/sample/repo/api/openapi.yaml +10 -0
  324. package/dist/packages/conformance/sample/repo/api/schema.graphql +3 -0
  325. package/dist/packages/conformance/sample/repo/db/V1__create_greeting.sql +4 -0
  326. package/dist/packages/conformance/sample/repo/package.json +7 -0
  327. package/dist/packages/conformance/sample/repo/src/main/java/sample/HelloController.java +10 -0
  328. package/dist/packages/conformance/sample/repo/web/app.ts +4 -0
  329. package/dist/packages/evals/datasets/critic-lenses.yaml +62 -0
  330. package/dist/packages/evals/datasets/dialect-writer.yaml +14 -0
  331. package/dist/packages/evals/datasets/feature-namer.yaml +34 -0
  332. package/dist/packages/evals/datasets/glossary-definer.yaml +25 -0
  333. package/dist/packages/evals/datasets/story-writer.yaml +13 -0
  334. package/dist/packages/evals/datasets/template-writer.yaml +16 -0
  335. package/dist/packages/evals/datasets/test-writer.yaml +18 -0
  336. package/dist/packages/executors/reference/reference-executor.mjs +233 -0
  337. package/dist/packages/extractors/dialects/argocd.yaml +45 -0
  338. package/dist/packages/extractors/dialects/fixtures/jaxrs/accounts-service/src/main/java/forge/accounts/AccountResource.java +47 -0
  339. package/dist/packages/extractors/dialects/fixtures/jaxrs/accounts-service/src/main/java/forge/accounts/AuditClient.java +12 -0
  340. package/dist/packages/extractors/dialects/fixtures/jaxrs/accounts-service/src/main/java/forge/accounts/LedgerClient.java +17 -0
  341. package/dist/packages/extractors/dialects/fixtures/micronaut/statements-service/src/main/java/forge/statements/LedgerClient.java +14 -0
  342. package/dist/packages/extractors/dialects/fixtures/micronaut/statements-service/src/main/java/forge/statements/RatesClient.java +11 -0
  343. package/dist/packages/extractors/dialects/fixtures/micronaut/statements-service/src/main/java/forge/statements/StatementController.java +36 -0
  344. package/dist/packages/extractors/dialects/fixtures/micronaut/statements-service/src/main/resources/application.yml +7 -0
  345. package/dist/packages/extractors/dialects/fixtures/quarkus-reactive-messaging/fraud-service/src/main/java/forge/fraud/FraudScorer.java +27 -0
  346. package/dist/packages/extractors/dialects/fixtures/quarkus-reactive-messaging/fraud-service/src/main/resources/application.properties +4 -0
  347. package/dist/packages/extractors/dialects/fixtures/terraform-aws/forge-aws-infra/envs/prod/api.tf +38 -0
  348. package/dist/packages/extractors/dialects/fixtures/terraform-aws/forge-aws-infra/envs/prod/main.tf +95 -0
  349. package/dist/packages/extractors/dialects/fixtures/terraform-aws/forge-aws-infra/envs/prod/terraform.tfvars +1 -0
  350. package/dist/packages/extractors/dialects/fixtures/terraform-aws/forge-aws-infra/envs/prod/variables.tf +4 -0
  351. package/dist/packages/extractors/dialects/fixtures/terraform-azure/forge-azure-infra/main.tf +102 -0
  352. package/dist/packages/extractors/dialects/fixtures/terraform-gcp/forge-gcp-infra/main.tf +51 -0
  353. package/dist/packages/extractors/dialects/harness.yaml +101 -0
  354. package/dist/packages/extractors/dialects/jaxrs.yaml +155 -0
  355. package/dist/packages/extractors/dialects/micronaut.yaml +207 -0
  356. package/dist/packages/extractors/dialects/quarkus-reactive-messaging.yaml +158 -0
  357. package/dist/packages/extractors/dialects/tekton.yaml +71 -0
  358. package/dist/packages/extractors/dialects/terraform-aws.yaml +267 -0
  359. package/dist/packages/extractors/dialects/terraform-azure.yaml +212 -0
  360. package/dist/packages/extractors/dialects/terraform-gcp.yaml +109 -0
  361. package/dist/packages/extractors/grammars/README.md +11 -0
  362. package/dist/packages/extractors/grammars/tree-sitter-groovy.LICENSE +21 -0
  363. package/dist/packages/extractors/grammars/tree-sitter-groovy.wasm +0 -0
  364. package/dist/packages/extractors/grammars/vendored.json +11 -0
  365. package/dist/packages/learn/lessons/architect-diagrams-and-code.yaml +69 -0
  366. package/dist/packages/learn/lessons/business-analyst-story-bar.yaml +94 -0
  367. package/dist/packages/learn/lessons/delivery-lead-release-readiness.yaml +44 -0
  368. package/dist/packages/learn/lessons/designer-features-in-user-words.yaml +57 -0
  369. package/dist/packages/learn/lessons/developer-find-your-way.yaml +60 -0
  370. package/dist/packages/learn/lessons/everyone-first-hour.yaml +74 -0
  371. package/dist/packages/learn/lessons/platform-lead-coverage-and-defences.yaml +58 -0
  372. package/dist/packages/learn/lessons/product-owner-first-change.yaml +167 -0
  373. package/dist/packages/learn/lessons/qa-tests-and-trace.yaml +53 -0
  374. package/dist/packages/learn/lessons/team-lead-initiative.yaml +146 -0
  375. package/dist/packages/naysayer/constitution/constitution.yaml +286 -0
  376. package/dist/packages/naysayer/starter/review.yaml +256 -0
  377. package/dist/packages/sdk/npm/index.js +8892 -0
  378. package/dist/packages/speckit/rules/drift.yaml +78 -0
  379. package/dist/packages/taskrun/rules/conform.yaml +38 -0
  380. package/dist/packages/testgen/rules/trace.yaml +49 -0
  381. package/dist/packages/ui/dist/assets/elk-api-tma0MCuh.js +2 -0
  382. package/dist/packages/ui/dist/assets/elk-worker.min--dAJroGl.js +6401 -0
  383. package/dist/packages/ui/dist/assets/elk-worker.min-DdYmS5kP.js +2 -0
  384. package/dist/packages/ui/dist/assets/ibm-plex-sans-cyrillic-400-normal-BTotfTJu.woff +0 -0
  385. package/dist/packages/ui/dist/assets/ibm-plex-sans-cyrillic-400-normal-DZqxrq2p.woff2 +0 -0
  386. package/dist/packages/ui/dist/assets/ibm-plex-sans-cyrillic-500-normal-ByOcLdNv.woff +0 -0
  387. package/dist/packages/ui/dist/assets/ibm-plex-sans-cyrillic-500-normal-CocWQlwt.woff2 +0 -0
  388. package/dist/packages/ui/dist/assets/ibm-plex-sans-cyrillic-600-normal-71GNu3SW.woff2 +0 -0
  389. package/dist/packages/ui/dist/assets/ibm-plex-sans-cyrillic-600-normal-BGq0mW3O.woff +0 -0
  390. package/dist/packages/ui/dist/assets/ibm-plex-sans-cyrillic-ext-400-normal-Dsrv2Tcn.woff +0 -0
  391. package/dist/packages/ui/dist/assets/ibm-plex-sans-cyrillic-ext-400-normal-g30qAdWV.woff2 +0 -0
  392. package/dist/packages/ui/dist/assets/ibm-plex-sans-cyrillic-ext-500-normal-Cs5J6C77.woff2 +0 -0
  393. package/dist/packages/ui/dist/assets/ibm-plex-sans-cyrillic-ext-500-normal-DB5PtV2g.woff +0 -0
  394. package/dist/packages/ui/dist/assets/ibm-plex-sans-cyrillic-ext-600-normal-Bz0x94Yp.woff +0 -0
  395. package/dist/packages/ui/dist/assets/ibm-plex-sans-cyrillic-ext-600-normal-DUMzJB7m.woff2 +0 -0
  396. package/dist/packages/ui/dist/assets/ibm-plex-sans-greek-400-normal-D9ESIMu3.woff +0 -0
  397. package/dist/packages/ui/dist/assets/ibm-plex-sans-greek-400-normal-_efipK4i.woff2 +0 -0
  398. package/dist/packages/ui/dist/assets/ibm-plex-sans-greek-500-normal-CuWXN6rf.woff +0 -0
  399. package/dist/packages/ui/dist/assets/ibm-plex-sans-greek-500-normal-JMMifIXV.woff2 +0 -0
  400. package/dist/packages/ui/dist/assets/ibm-plex-sans-greek-600-normal-D-CqTdkO.woff +0 -0
  401. package/dist/packages/ui/dist/assets/ibm-plex-sans-greek-600-normal-DzTrcv_p.woff2 +0 -0
  402. package/dist/packages/ui/dist/assets/ibm-plex-sans-latin-400-normal-CDDApCn2.woff2 +0 -0
  403. package/dist/packages/ui/dist/assets/ibm-plex-sans-latin-400-normal-CYLoc0-x.woff +0 -0
  404. package/dist/packages/ui/dist/assets/ibm-plex-sans-latin-500-normal-6ng42L7E.woff2 +0 -0
  405. package/dist/packages/ui/dist/assets/ibm-plex-sans-latin-500-normal-BgVn5rGT.woff +0 -0
  406. package/dist/packages/ui/dist/assets/ibm-plex-sans-latin-600-normal-Cu4Hd6ag.woff +0 -0
  407. package/dist/packages/ui/dist/assets/ibm-plex-sans-latin-600-normal-CuJfVYMP.woff2 +0 -0
  408. package/dist/packages/ui/dist/assets/ibm-plex-sans-latin-ext-400-normal-C5H60-Va.woff2 +0 -0
  409. package/dist/packages/ui/dist/assets/ibm-plex-sans-latin-ext-400-normal-RBey6euL.woff +0 -0
  410. package/dist/packages/ui/dist/assets/ibm-plex-sans-latin-ext-500-normal-D0aIdm-b.woff +0 -0
  411. package/dist/packages/ui/dist/assets/ibm-plex-sans-latin-ext-500-normal-DakdToA3.woff2 +0 -0
  412. package/dist/packages/ui/dist/assets/ibm-plex-sans-latin-ext-600-normal-DIrixKbi.woff +0 -0
  413. package/dist/packages/ui/dist/assets/ibm-plex-sans-latin-ext-600-normal-DOrvGEcy.woff2 +0 -0
  414. package/dist/packages/ui/dist/assets/ibm-plex-sans-vietnamese-400-normal-DG4YqDda.woff2 +0 -0
  415. package/dist/packages/ui/dist/assets/ibm-plex-sans-vietnamese-400-normal-fK1oJ5dG.woff +0 -0
  416. package/dist/packages/ui/dist/assets/ibm-plex-sans-vietnamese-500-normal-BEb3_waV.woff +0 -0
  417. package/dist/packages/ui/dist/assets/ibm-plex-sans-vietnamese-500-normal-e4dixQRQ.woff2 +0 -0
  418. package/dist/packages/ui/dist/assets/ibm-plex-sans-vietnamese-600-normal-DgdngZtN.woff +0 -0
  419. package/dist/packages/ui/dist/assets/ibm-plex-sans-vietnamese-600-normal-DpPYBSTl.woff2 +0 -0
  420. package/dist/packages/ui/dist/assets/index-B54fm9FQ.js +29 -0
  421. package/dist/packages/ui/dist/assets/index-DD_hufQz.css +1 -0
  422. package/dist/packages/ui/dist/assets/jetbrains-mono-cyrillic-400-normal-BEIGL1Tu.woff2 +0 -0
  423. package/dist/packages/ui/dist/assets/jetbrains-mono-cyrillic-400-normal-ugxPyKxw.woff +0 -0
  424. package/dist/packages/ui/dist/assets/jetbrains-mono-cyrillic-500-normal-DJqRU3vO.woff +0 -0
  425. package/dist/packages/ui/dist/assets/jetbrains-mono-cyrillic-500-normal-DmUKJPL_.woff2 +0 -0
  426. package/dist/packages/ui/dist/assets/jetbrains-mono-greek-400-normal-B9oWc5Lo.woff +0 -0
  427. package/dist/packages/ui/dist/assets/jetbrains-mono-greek-400-normal-C190GLew.woff2 +0 -0
  428. package/dist/packages/ui/dist/assets/jetbrains-mono-greek-500-normal-D7SFKleX.woff +0 -0
  429. package/dist/packages/ui/dist/assets/jetbrains-mono-greek-500-normal-JpySY46c.woff2 +0 -0
  430. package/dist/packages/ui/dist/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff +0 -0
  431. package/dist/packages/ui/dist/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2 +0 -0
  432. package/dist/packages/ui/dist/assets/jetbrains-mono-latin-500-normal-BWZEU5yA.woff2 +0 -0
  433. package/dist/packages/ui/dist/assets/jetbrains-mono-latin-500-normal-CJOVTJB7.woff +0 -0
  434. package/dist/packages/ui/dist/assets/jetbrains-mono-latin-ext-400-normal-Bc8Ftmh3.woff2 +0 -0
  435. package/dist/packages/ui/dist/assets/jetbrains-mono-latin-ext-400-normal-fXTG6kC5.woff +0 -0
  436. package/dist/packages/ui/dist/assets/jetbrains-mono-latin-ext-500-normal-Cut-4mMH.woff2 +0 -0
  437. package/dist/packages/ui/dist/assets/jetbrains-mono-latin-ext-500-normal-ckzbgY84.woff +0 -0
  438. package/dist/packages/ui/dist/assets/jetbrains-mono-vietnamese-400-normal-CqNFfHCs.woff +0 -0
  439. package/dist/packages/ui/dist/assets/jetbrains-mono-vietnamese-500-normal-DNRqzVM1.woff +0 -0
  440. package/dist/packages/ui/dist/assets/rajdhani-devanagari-600-normal-BtY48IV_.woff +0 -0
  441. package/dist/packages/ui/dist/assets/rajdhani-devanagari-600-normal-DhS7ScYx.woff2 +0 -0
  442. package/dist/packages/ui/dist/assets/rajdhani-devanagari-700-normal-BQQOj9BB.woff2 +0 -0
  443. package/dist/packages/ui/dist/assets/rajdhani-devanagari-700-normal-DBRwWuxA.woff +0 -0
  444. package/dist/packages/ui/dist/assets/rajdhani-latin-600-normal-CXCVEoA9.woff2 +0 -0
  445. package/dist/packages/ui/dist/assets/rajdhani-latin-600-normal-Dx02qI2_.woff +0 -0
  446. package/dist/packages/ui/dist/assets/rajdhani-latin-700-normal-BPDUZo87.woff2 +0 -0
  447. package/dist/packages/ui/dist/assets/rajdhani-latin-700-normal-e0Uj8ZlN.woff +0 -0
  448. package/dist/packages/ui/dist/assets/rajdhani-latin-ext-600-normal-BleIgkPp.woff +0 -0
  449. package/dist/packages/ui/dist/assets/rajdhani-latin-ext-600-normal-C9ZjJQAt.woff2 +0 -0
  450. package/dist/packages/ui/dist/assets/rajdhani-latin-ext-700-normal-BPaQ7tlD.woff +0 -0
  451. package/dist/packages/ui/dist/assets/rajdhani-latin-ext-700-normal-S6aYESQK.woff2 +0 -0
  452. package/dist/packages/ui/dist/favicon.svg +1 -0
  453. package/dist/packages/ui/dist/index.html +15 -0
  454. package/dist/third-party.json +575 -0
  455. package/dist/vendor/@fission-ai/openspec/bin/openspec.js +85986 -0
  456. package/dist/vendor/@fission-ai/openspec/package.json +82 -0
  457. package/dist/vendor/@fission-ai/openspec/schemas/spec-driven/schema.yaml +248 -0
  458. package/dist/vendor/@fission-ai/openspec/schemas/spec-driven/templates/design.md +21 -0
  459. package/dist/vendor/@fission-ai/openspec/schemas/spec-driven/templates/proposal.md +34 -0
  460. package/dist/vendor/@fission-ai/openspec/schemas/spec-driven/templates/spec.md +13 -0
  461. package/dist/vendor/@fission-ai/openspec/schemas/spec-driven/templates/tasks.md +11 -0
  462. package/dist/vendor/tree-sitter-wasms/out/tree-sitter-c_sharp.wasm +0 -0
  463. package/dist/vendor/tree-sitter-wasms/out/tree-sitter-go.wasm +0 -0
  464. package/dist/vendor/tree-sitter-wasms/out/tree-sitter-java.wasm +0 -0
  465. package/dist/vendor/tree-sitter-wasms/out/tree-sitter-javascript.wasm +0 -0
  466. package/dist/vendor/tree-sitter-wasms/out/tree-sitter-kotlin.wasm +0 -0
  467. package/dist/vendor/tree-sitter-wasms/out/tree-sitter-php.wasm +0 -0
  468. package/dist/vendor/tree-sitter-wasms/out/tree-sitter-python.wasm +0 -0
  469. package/dist/vendor/tree-sitter-wasms/out/tree-sitter-ruby.wasm +0 -0
  470. package/dist/vendor/tree-sitter-wasms/out/tree-sitter-rust.wasm +0 -0
  471. package/dist/vendor/tree-sitter-wasms/out/tree-sitter-scala.wasm +0 -0
  472. package/dist/vendor/tree-sitter-wasms/out/tree-sitter-tsx.wasm +0 -0
  473. package/dist/vendor/tree-sitter-wasms/out/tree-sitter-typescript.wasm +0 -0
  474. package/dist/vendor/web-tree-sitter/tree-sitter.wasm +0 -0
  475. package/package.json +36 -3
@@ -0,0 +1,1611 @@
1
+ import { createRequire as __atticusCreateRequire } from "node:module";
2
+ import { fileURLToPath as __atticusFileURLToPath } from "node:url";
3
+ var require = __atticusCreateRequire(import.meta.url);
4
+ var __atticusUrl = (p) => new URL("./" + p, import.meta.url).href;
5
+ var __atticusPath = (p) => __atticusFileURLToPath(__atticusUrl(p));
6
+ import {
7
+ changeStore
8
+ } from "./chunk-XY3P7JW7.js";
9
+ import {
10
+ ManualNotifier,
11
+ fileStepStore
12
+ } from "./chunk-7JUKDRSZ.js";
13
+ import {
14
+ readCatalog
15
+ } from "./chunk-27NKUS3X.js";
16
+ import {
17
+ readServiceRequestExports
18
+ } from "./chunk-23W7VWKR.js";
19
+ import {
20
+ Initiative,
21
+ IsoDate,
22
+ IsoDateTime,
23
+ LIFECYCLE_STATES,
24
+ RecordId,
25
+ catalogDirOf,
26
+ external_exports,
27
+ loadOrgPack,
28
+ orgPackDirOf,
29
+ parseRecord,
30
+ recordPath,
31
+ require_dist,
32
+ serializeRecord,
33
+ stateDirOf,
34
+ toCanonicalYaml
35
+ } from "./chunk-S2A7YC3Q.js";
36
+ import {
37
+ SCHEMA_VERSION
38
+ } from "./chunk-D3PO4DOZ.js";
39
+ import {
40
+ __toESM
41
+ } from "./chunk-TV45EUGM.js";
42
+
43
+ // packages/initiatives/dist/journeys.js
44
+ var import_yaml = __toESM(require_dist(), 1);
45
+ import { readdir, readFile } from "node:fs/promises";
46
+ import { join } from "node:path";
47
+ var JOURNEYS = Initiative.shape.journey.options;
48
+ var PartyRole = external_exports.union([
49
+ external_exports.enum([
50
+ /** The vendor party whose systems include the target. */
51
+ "vendor",
52
+ /** The party whose systems include the target (vendor or internal). */
53
+ "target-owner",
54
+ /** The party of each system that calls the target (one item per caller). */
55
+ "caller-owners",
56
+ /** The party of each system the target calls. */
57
+ "callee-owners",
58
+ /** The platform team's party. */
59
+ "platform",
60
+ /** For a request: the party that approves the request type (template `approvers`). */
61
+ "approver"
62
+ ]),
63
+ external_exports.string().regex(/^party:[a-z0-9][a-z0-9._-]*$/, "a role or party:<id>")
64
+ ]);
65
+ var JourneyStep = external_exports.strictObject({
66
+ id: RecordId,
67
+ /** What has to happen; {initiative}, {target}, {targetName}, {system} and {systemName} are filled in. */
68
+ what: external_exports.string().min(1),
69
+ kind: external_exports.enum(["change", "commitment", "request", "task"]),
70
+ /** For commitments and requests: who it is with. */
71
+ party: PartyRole.optional(),
72
+ /** Key in the party's typicalLeadTimes (commitments; requests use the template id). */
73
+ leadTimeKey: external_exports.string().min(1).optional(),
74
+ /** For requests: the service-desk request template (org-pack/process/snow/<id>.yaml). */
75
+ template: RecordId.optional(),
76
+ /** One item, or one per caller, callee, the target, or the systems named for the initiative. */
77
+ per: external_exports.enum(["once", "callers", "callees", "target", "systems"]).default("once"),
78
+ /** For change steps: the state the change must reach. */
79
+ milestone: external_exports.enum(["design", "build", "release-ready", "released"]).optional(),
80
+ /** For change steps: the change type the change is created with. */
81
+ changeType: RecordId.default("feature"),
82
+ /** For tasks: the role that does it. */
83
+ owner: RecordId.optional(),
84
+ /** Working days the step takes when nothing better is known. */
85
+ days: external_exports.number().int().min(0).default(5),
86
+ /** Steps that must finish first. */
87
+ after: external_exports.array(RecordId).default([])
88
+ });
89
+ var JourneyTemplate = external_exports.strictObject({
90
+ schemaVersion: external_exports.literal(1),
91
+ id: Initiative.shape.journey,
92
+ name: external_exports.string().min(1),
93
+ /** The outcome an initiative of this kind is for, in one sentence. */
94
+ outcome: external_exports.string().min(1),
95
+ phases: external_exports.array(external_exports.strictObject({
96
+ id: RecordId,
97
+ name: external_exports.string().min(1),
98
+ steps: external_exports.array(JourneyStep).min(1)
99
+ })).min(1)
100
+ }).superRefine((t, ctx) => {
101
+ const steps = t.phases.flatMap((p) => p.steps);
102
+ const ids = /* @__PURE__ */ new Set();
103
+ for (const s of steps) {
104
+ if (ids.has(s.id))
105
+ ctx.addIssue({ code: "custom", path: ["phases"], message: `step ${s.id} appears twice` });
106
+ ids.add(s.id);
107
+ if (s.kind === "change" && !s.milestone)
108
+ ctx.addIssue({
109
+ code: "custom",
110
+ path: ["phases"],
111
+ message: `change step ${s.id} needs a milestone`
112
+ });
113
+ if (s.kind === "request" && !s.template)
114
+ ctx.addIssue({
115
+ code: "custom",
116
+ path: ["phases"],
117
+ message: `request step ${s.id} needs a template`
118
+ });
119
+ if ((s.kind === "commitment" || s.kind === "request") && !s.party)
120
+ ctx.addIssue({ code: "custom", path: ["phases"], message: `step ${s.id} needs a party` });
121
+ }
122
+ for (const s of steps)
123
+ for (const a of s.after)
124
+ if (!ids.has(a))
125
+ ctx.addIssue({
126
+ code: "custom",
127
+ path: ["phases"],
128
+ message: `step ${s.id} comes after ${a}, which doesn't exist`
129
+ });
130
+ const state = /* @__PURE__ */ new Map();
131
+ const byId = new Map(steps.map((s) => [s.id, s]));
132
+ const visit = (id) => {
133
+ if (state.get(id) === 1)
134
+ return false;
135
+ if (state.get(id) === 2)
136
+ return true;
137
+ state.set(id, 1);
138
+ for (const a of byId.get(id)?.after ?? [])
139
+ if (!visit(a))
140
+ return false;
141
+ state.set(id, 2);
142
+ return true;
143
+ };
144
+ for (const s of steps)
145
+ if (!visit(s.id)) {
146
+ ctx.addIssue({
147
+ code: "custom",
148
+ path: ["phases"],
149
+ message: `the steps go round in a circle at ${s.id}`
150
+ });
151
+ break;
152
+ }
153
+ });
154
+ var BUILT_IN = [
155
+ {
156
+ schemaVersion: 1,
157
+ id: "new-feature",
158
+ name: "New feature",
159
+ outcome: "Ship a new capability in one system, with the other teams it depends on lined up in time.",
160
+ phases: [
161
+ {
162
+ id: "define",
163
+ name: "Define",
164
+ steps: [
165
+ {
166
+ id: "brief",
167
+ what: "Write and agree the brief for {targetName}",
168
+ kind: "task",
169
+ owner: "product-owner",
170
+ days: 5
171
+ },
172
+ {
173
+ id: "interfaces-confirmed",
174
+ what: "{systemName} confirms the interfaces {targetName} will use",
175
+ kind: "commitment",
176
+ party: "callee-owners",
177
+ per: "callees",
178
+ leadTimeKey: "system-card",
179
+ days: 5,
180
+ after: ["brief"]
181
+ }
182
+ ]
183
+ },
184
+ {
185
+ id: "design",
186
+ name: "Design",
187
+ steps: [
188
+ {
189
+ id: "design",
190
+ what: "Design approved for {targetName}",
191
+ kind: "change",
192
+ per: "target",
193
+ milestone: "design",
194
+ days: 5,
195
+ after: ["brief"]
196
+ }
197
+ ]
198
+ },
199
+ {
200
+ id: "build",
201
+ name: "Build",
202
+ steps: [
203
+ {
204
+ id: "build",
205
+ what: "{targetName} built and tested",
206
+ kind: "change",
207
+ per: "target",
208
+ milestone: "build",
209
+ days: 10,
210
+ after: ["design", "interfaces-confirmed"]
211
+ }
212
+ ]
213
+ },
214
+ {
215
+ id: "release",
216
+ name: "Release",
217
+ steps: [
218
+ { id: "qa", what: "QA sign-off", kind: "task", owner: "qa", days: 5, after: ["build"] },
219
+ {
220
+ id: "release",
221
+ what: "Go/no-go and release",
222
+ kind: "task",
223
+ owner: "delivery-lead",
224
+ days: 2,
225
+ after: ["qa"]
226
+ }
227
+ ]
228
+ }
229
+ ]
230
+ },
231
+ {
232
+ schemaVersion: 1,
233
+ id: "new-integration",
234
+ name: "New integration",
235
+ outcome: "Connect the named systems to a new partner or internal system, with access, network and gateway ready in time.",
236
+ phases: [
237
+ {
238
+ id: "discover",
239
+ name: "Discover",
240
+ steps: [
241
+ {
242
+ id: "partner-spec",
243
+ what: "{targetName} shares its API spec",
244
+ kind: "commitment",
245
+ party: "target-owner",
246
+ leadTimeKey: "api-spec",
247
+ days: 10
248
+ },
249
+ {
250
+ id: "access",
251
+ what: "{targetName} grants test credentials and sandbox access",
252
+ kind: "commitment",
253
+ party: "target-owner",
254
+ leadTimeKey: "sandbox-access",
255
+ days: 10
256
+ }
257
+ ]
258
+ },
259
+ {
260
+ id: "design",
261
+ name: "Design",
262
+ steps: [
263
+ {
264
+ id: "design",
265
+ what: "Design approved for the {targetName} integration in {systemName}",
266
+ kind: "change",
267
+ per: "systems",
268
+ milestone: "design",
269
+ days: 5,
270
+ after: ["partner-spec"]
271
+ }
272
+ ]
273
+ },
274
+ {
275
+ id: "build",
276
+ name: "Build",
277
+ steps: [
278
+ {
279
+ id: "gateway-route",
280
+ what: "Gateway proxy for {targetName}",
281
+ kind: "request",
282
+ template: "gateway-route",
283
+ party: "approver",
284
+ days: 5,
285
+ after: ["design"]
286
+ },
287
+ {
288
+ id: "firewall-rule",
289
+ what: "Firewall rule to {targetName}",
290
+ kind: "request",
291
+ template: "firewall-rule",
292
+ party: "approver",
293
+ days: 10,
294
+ after: ["design"]
295
+ },
296
+ {
297
+ id: "build",
298
+ what: "{systemName} built against {targetName}",
299
+ kind: "change",
300
+ per: "systems",
301
+ milestone: "build",
302
+ days: 10,
303
+ after: ["design"]
304
+ }
305
+ ]
306
+ },
307
+ {
308
+ id: "test",
309
+ name: "Test",
310
+ steps: [
311
+ {
312
+ id: "integration-test",
313
+ what: "Joint integration test with {targetName}",
314
+ kind: "commitment",
315
+ party: "target-owner",
316
+ leadTimeKey: "integration-test",
317
+ days: 5,
318
+ after: ["build", "access", "gateway-route", "firewall-rule"]
319
+ }
320
+ ]
321
+ },
322
+ {
323
+ id: "release",
324
+ name: "Release",
325
+ steps: [
326
+ {
327
+ id: "release",
328
+ what: "Go/no-go and release",
329
+ kind: "task",
330
+ owner: "delivery-lead",
331
+ days: 2,
332
+ after: ["integration-test"]
333
+ }
334
+ ]
335
+ }
336
+ ]
337
+ },
338
+ {
339
+ schemaVersion: 1,
340
+ id: "vendor-api-change",
341
+ name: "Vendor API change",
342
+ outcome: "Move every caller to a vendor's new API version before the old one is switched off.",
343
+ phases: [
344
+ {
345
+ id: "discover",
346
+ name: "Discover",
347
+ steps: [
348
+ {
349
+ id: "vendor-spec",
350
+ what: "{targetName} publishes the new API spec and changelog",
351
+ kind: "commitment",
352
+ party: "vendor",
353
+ leadTimeKey: "api-spec",
354
+ days: 10
355
+ },
356
+ {
357
+ id: "vendor-sandbox",
358
+ what: "{targetName} gives sandbox access to the new API",
359
+ kind: "commitment",
360
+ party: "vendor",
361
+ leadTimeKey: "sandbox-access",
362
+ days: 10
363
+ }
364
+ ]
365
+ },
366
+ {
367
+ id: "design",
368
+ name: "Design",
369
+ steps: [
370
+ {
371
+ id: "impact",
372
+ what: "Impact of the new {targetName} API on every caller",
373
+ kind: "task",
374
+ owner: "architect",
375
+ days: 3,
376
+ after: ["vendor-spec"]
377
+ },
378
+ {
379
+ id: "design",
380
+ what: "Design approved for moving {systemName} to the new {targetName} API",
381
+ kind: "change",
382
+ per: "callers",
383
+ milestone: "design",
384
+ days: 5,
385
+ after: ["impact"]
386
+ }
387
+ ]
388
+ },
389
+ {
390
+ id: "build",
391
+ name: "Build",
392
+ steps: [
393
+ {
394
+ id: "gateway-route",
395
+ what: "Gateway proxy for the new {targetName} API",
396
+ kind: "request",
397
+ template: "gateway-route",
398
+ party: "approver",
399
+ days: 5,
400
+ after: ["design"]
401
+ },
402
+ {
403
+ id: "firewall-rule",
404
+ what: "Firewall rule to the new {targetName} host",
405
+ kind: "request",
406
+ template: "firewall-rule",
407
+ party: "approver",
408
+ days: 10,
409
+ after: ["design"]
410
+ },
411
+ {
412
+ id: "build",
413
+ what: "{systemName} moved to the new {targetName} API",
414
+ kind: "change",
415
+ per: "callers",
416
+ milestone: "build",
417
+ days: 10,
418
+ after: ["design"]
419
+ }
420
+ ]
421
+ },
422
+ {
423
+ id: "test",
424
+ name: "Test",
425
+ steps: [
426
+ {
427
+ id: "vendor-certification",
428
+ what: "{targetName} certifies the integration in its sandbox",
429
+ kind: "commitment",
430
+ party: "vendor",
431
+ leadTimeKey: "certification",
432
+ days: 10,
433
+ after: ["build", "vendor-sandbox", "gateway-route", "firewall-rule"]
434
+ }
435
+ ]
436
+ },
437
+ {
438
+ id: "release",
439
+ name: "Release",
440
+ steps: [
441
+ {
442
+ id: "release",
443
+ what: "Go/no-go and release",
444
+ kind: "task",
445
+ owner: "delivery-lead",
446
+ days: 2,
447
+ after: ["vendor-certification"]
448
+ }
449
+ ]
450
+ }
451
+ ]
452
+ },
453
+ {
454
+ schemaVersion: 1,
455
+ id: "design-change",
456
+ name: "Design change",
457
+ outcome: "Change how one system works and bring every caller along.",
458
+ phases: [
459
+ {
460
+ id: "design",
461
+ name: "Design",
462
+ steps: [
463
+ {
464
+ id: "design",
465
+ what: "Design approved for {targetName}",
466
+ kind: "change",
467
+ per: "target",
468
+ milestone: "design",
469
+ days: 5
470
+ },
471
+ {
472
+ id: "caller-impact",
473
+ what: "{systemName} confirms the impact of the {targetName} change",
474
+ kind: "commitment",
475
+ party: "caller-owners",
476
+ per: "callers",
477
+ leadTimeKey: "system-card",
478
+ days: 5,
479
+ after: ["design"]
480
+ }
481
+ ]
482
+ },
483
+ {
484
+ id: "build",
485
+ name: "Build",
486
+ steps: [
487
+ {
488
+ id: "build-target",
489
+ what: "{targetName} built",
490
+ kind: "change",
491
+ per: "target",
492
+ milestone: "build",
493
+ days: 10,
494
+ after: ["design"]
495
+ },
496
+ {
497
+ id: "build-callers",
498
+ what: "{systemName} updated for the {targetName} change",
499
+ kind: "change",
500
+ per: "callers",
501
+ milestone: "build",
502
+ days: 10,
503
+ after: ["caller-impact"]
504
+ }
505
+ ]
506
+ },
507
+ {
508
+ id: "release",
509
+ name: "Release",
510
+ steps: [
511
+ {
512
+ id: "release",
513
+ what: "Go/no-go and release",
514
+ kind: "task",
515
+ owner: "delivery-lead",
516
+ days: 2,
517
+ after: ["build-target", "build-callers"]
518
+ }
519
+ ]
520
+ }
521
+ ]
522
+ },
523
+ {
524
+ schemaVersion: 1,
525
+ id: "migration",
526
+ name: "Migration",
527
+ outcome: "Move a system to a new platform without breaking its callers.",
528
+ phases: [
529
+ {
530
+ id: "prepare",
531
+ name: "Prepare",
532
+ steps: [
533
+ {
534
+ id: "inventory",
535
+ what: "Inventory of {targetName}'s interfaces, data and settings",
536
+ kind: "task",
537
+ owner: "architect",
538
+ days: 5
539
+ },
540
+ {
541
+ id: "platform-ready",
542
+ what: "The target platform is ready for {targetName}",
543
+ kind: "commitment",
544
+ party: "platform",
545
+ leadTimeKey: "platform-ready",
546
+ days: 15
547
+ }
548
+ ]
549
+ },
550
+ {
551
+ id: "design",
552
+ name: "Design",
553
+ steps: [
554
+ {
555
+ id: "design",
556
+ what: "Migration design approved for {targetName}",
557
+ kind: "change",
558
+ per: "target",
559
+ milestone: "design",
560
+ days: 5,
561
+ after: ["inventory"]
562
+ }
563
+ ]
564
+ },
565
+ {
566
+ id: "build",
567
+ name: "Build",
568
+ steps: [
569
+ {
570
+ id: "firewall-rule",
571
+ what: "Firewall rules for {targetName} on the new platform",
572
+ kind: "request",
573
+ template: "firewall-rule",
574
+ party: "approver",
575
+ days: 10,
576
+ after: ["design"]
577
+ },
578
+ {
579
+ id: "build",
580
+ what: "{targetName} running on the new platform",
581
+ kind: "change",
582
+ per: "target",
583
+ milestone: "build",
584
+ days: 15,
585
+ after: ["design"]
586
+ },
587
+ {
588
+ id: "cutover-agreed",
589
+ what: "{systemName} agrees the cutover window",
590
+ kind: "commitment",
591
+ party: "caller-owners",
592
+ per: "callers",
593
+ leadTimeKey: "cutover",
594
+ days: 5,
595
+ after: ["build"]
596
+ }
597
+ ]
598
+ },
599
+ {
600
+ id: "release",
601
+ name: "Cutover",
602
+ steps: [
603
+ {
604
+ id: "release",
605
+ what: "Cutover",
606
+ kind: "task",
607
+ owner: "delivery-lead",
608
+ days: 2,
609
+ after: ["platform-ready", "firewall-rule", "cutover-agreed"]
610
+ }
611
+ ]
612
+ }
613
+ ]
614
+ },
615
+ {
616
+ schemaVersion: 1,
617
+ id: "retire-system",
618
+ name: "Retire a system",
619
+ outcome: "Switch a system off after every caller has moved off it and its data is dealt with.",
620
+ phases: [
621
+ {
622
+ id: "notify",
623
+ name: "Notify",
624
+ steps: [
625
+ {
626
+ id: "callers-notified",
627
+ what: "{systemName} agrees to move off {targetName}",
628
+ kind: "commitment",
629
+ party: "caller-owners",
630
+ per: "callers",
631
+ leadTimeKey: "retire",
632
+ days: 20
633
+ },
634
+ {
635
+ id: "design",
636
+ what: "Retirement design approved for {targetName}",
637
+ kind: "change",
638
+ per: "target",
639
+ milestone: "design",
640
+ days: 5
641
+ }
642
+ ]
643
+ },
644
+ {
645
+ id: "move",
646
+ name: "Move callers",
647
+ steps: [
648
+ {
649
+ id: "caller-changes",
650
+ what: "{systemName} no longer calls {targetName}",
651
+ kind: "change",
652
+ per: "callers",
653
+ milestone: "released",
654
+ days: 10,
655
+ after: ["design", "callers-notified"]
656
+ }
657
+ ]
658
+ },
659
+ {
660
+ id: "data",
661
+ name: "Data",
662
+ steps: [
663
+ {
664
+ id: "data-retention",
665
+ what: "{targetName}'s data archived or deleted as its retention says",
666
+ kind: "commitment",
667
+ party: "target-owner",
668
+ leadTimeKey: "data-retention",
669
+ days: 10,
670
+ after: ["caller-changes"]
671
+ }
672
+ ]
673
+ },
674
+ {
675
+ id: "release",
676
+ name: "Switch off",
677
+ steps: [
678
+ {
679
+ id: "release",
680
+ what: "Switch {targetName} off",
681
+ kind: "task",
682
+ owner: "platform-lead",
683
+ days: 2,
684
+ after: ["caller-changes", "data-retention"]
685
+ }
686
+ ]
687
+ }
688
+ ]
689
+ }
690
+ ];
691
+ var BUILT_IN_JOURNEYS = BUILT_IN.map((j) => JourneyTemplate.parse(j));
692
+ async function loadJourneys(root) {
693
+ const journeys = new Map(BUILT_IN_JOURNEYS.map((j) => [j.id, { ...j, source: "built-in" }]));
694
+ const problems = [];
695
+ const dir = join(orgPackDirOf(root), "process", "journeys");
696
+ let names = [];
697
+ try {
698
+ names = (await readdir(dir)).filter((n) => /\.ya?ml$/.test(n)).sort();
699
+ } catch {
700
+ }
701
+ for (const n of names) {
702
+ const rel = `process/journeys/${n}`;
703
+ try {
704
+ const r = JourneyTemplate.safeParse((0, import_yaml.parse)(await readFile(join(dir, n), "utf8")));
705
+ if (!r.success) {
706
+ problems.push(`${rel}: ${r.error.issues.map((i) => `${i.path.join(".") || "(file)"} ${i.message}`).join("; ")}`);
707
+ continue;
708
+ }
709
+ journeys.set(r.data.id, { ...r.data, source: `org-pack/${rel}` });
710
+ } catch (e) {
711
+ problems.push(`${rel}: ${e.message.split("\n")[0]}`);
712
+ }
713
+ }
714
+ return { journeys, problems };
715
+ }
716
+ var stepsOf = (j) => j.phases.flatMap((p) => p.steps.map((s) => ({ ...s, phase: p.id })));
717
+
718
+ // packages/initiatives/dist/store.js
719
+ var import_yaml2 = __toESM(require_dist(), 1);
720
+ import { mkdir, readFile as readFile2, rename, rm, writeFile } from "node:fs/promises";
721
+ import { dirname, join as join2 } from "node:path";
722
+ var curatedDirOf = (root) => join2(catalogDirOf(root), "curated");
723
+ var initiativesDirOf = (root) => join2(stateDirOf(root), "initiatives");
724
+ var initiativeDir = (root, id) => join2(initiativesDirOf(root), id);
725
+ var planPath = (root, id) => join2(initiativeDir(root, id), "plan.yaml");
726
+ var InitiativeError = class extends Error {
727
+ code;
728
+ constructor(message, code = "invalid") {
729
+ super(message);
730
+ this.code = code;
731
+ this.name = "InitiativeError";
732
+ }
733
+ };
734
+ async function writeAtomic(path, text) {
735
+ await mkdir(dirname(path), { recursive: true });
736
+ const tmp = `${path}.tmp`;
737
+ try {
738
+ await writeFile(tmp, text, "utf8");
739
+ await rename(tmp, path);
740
+ } catch (e) {
741
+ await rm(tmp, { force: true });
742
+ throw e;
743
+ }
744
+ }
745
+ async function writeCurated(root, record) {
746
+ const p = parseRecord(record);
747
+ if (!p.ok)
748
+ throw new InitiativeError(`${record.kind} ${record.id}: ${p.issues.map((i) => `${i.path}: ${i.message}`).join("; ")}`);
749
+ const rel = recordPath(p.record);
750
+ await writeAtomic(join2(curatedDirOf(root), rel), serializeRecord(p.record));
751
+ return `catalog/curated/${rel}`;
752
+ }
753
+ async function readView(root) {
754
+ const dir = catalogDirOf(root);
755
+ const gen = await readCatalog(join2(dir, "generated"), { cacheRoot: root });
756
+ const cur = await readCatalog(join2(dir, "curated"), { cacheRoot: root });
757
+ const records = [...gen.records, ...cur.records];
758
+ const problems = [
759
+ ...gen.problems.map((p) => `catalog/generated/${p.file}: ${p.message}`),
760
+ ...cur.problems.map((p) => `catalog/curated/${p.file}: ${p.message}`)
761
+ ];
762
+ const key = (k, id) => `${k}|${id}`;
763
+ const byKey = new Map(records.map((r) => [key(r.kind, r.id), r]));
764
+ return {
765
+ records,
766
+ problems,
767
+ get: (kind, id) => byKey.get(key(kind, id)),
768
+ all: (kind) => records.filter((r) => r.kind === kind)
769
+ };
770
+ }
771
+ var manualEvidence = (by) => [
772
+ { source: "manual", by: by.replace(/^@/, "") }
773
+ ];
774
+ var PlanItem = external_exports.strictObject({
775
+ /** The step id, or `<step>.<system>` for a step done once per system. */
776
+ key: external_exports.string().min(1),
777
+ step: RecordId,
778
+ phase: RecordId,
779
+ kind: external_exports.enum(["change", "commitment", "request", "task"]),
780
+ what: external_exports.string().min(1),
781
+ /** The system the item is for, when the step is done per system. */
782
+ system: RecordId.optional(),
783
+ party: RecordId.optional(),
784
+ commitment: RecordId.optional(),
785
+ change: RecordId.optional(),
786
+ milestone: external_exports.enum(["design", "build", "release-ready", "released"]).optional(),
787
+ template: RecordId.optional(),
788
+ owner: external_exports.string().optional(),
789
+ days: external_exports.number().int().min(0),
790
+ /** Where the number of days came from, cited. */
791
+ leadTime: external_exports.string().min(1),
792
+ after: external_exports.array(external_exports.string()).default([]),
793
+ start: IsoDate,
794
+ due: IsoDate
795
+ });
796
+ var PlanFile = external_exports.strictObject({
797
+ schemaVersion: external_exports.literal(1),
798
+ initiative: RecordId,
799
+ journey: external_exports.string().min(1),
800
+ /** Where the journey template came from: built-in or an org-pack file. */
801
+ journeySource: external_exports.string().min(1),
802
+ target: RecordId,
803
+ targetRelease: IsoDate,
804
+ createdAt: IsoDateTime,
805
+ by: external_exports.string().min(1),
806
+ items: external_exports.array(PlanItem),
807
+ /** Tasks a person recorded as done: key → who and when. */
808
+ done: external_exports.record(external_exports.string(), external_exports.strictObject({ at: IsoDateTime, by: external_exports.string().min(1) })).default({}),
809
+ /** Items a person recorded as started (a request sent, a team asked): key → day. */
810
+ started: external_exports.record(external_exports.string(), IsoDate).default({}),
811
+ notes: external_exports.array(external_exports.string()).default([])
812
+ });
813
+ var PLAN_LEADING = [
814
+ "schemaVersion",
815
+ "initiative",
816
+ "journey",
817
+ "journeySource",
818
+ "target",
819
+ "targetRelease",
820
+ "createdAt",
821
+ "by",
822
+ "key",
823
+ "step",
824
+ "phase",
825
+ "kind",
826
+ "what",
827
+ "system",
828
+ "party",
829
+ "commitment",
830
+ "change",
831
+ "milestone",
832
+ "template",
833
+ "owner",
834
+ "days",
835
+ "leadTime",
836
+ "after",
837
+ "start",
838
+ "due"
839
+ ];
840
+ async function writePlan(root, plan) {
841
+ const p = PlanFile.parse(plan);
842
+ await writeAtomic(planPath(root, p.initiative), toCanonicalYaml(p, PLAN_LEADING));
843
+ return `initiatives/${p.initiative}/plan.yaml`;
844
+ }
845
+ async function readPlan(root, id) {
846
+ let text;
847
+ try {
848
+ text = await readFile2(planPath(root, id), "utf8");
849
+ } catch {
850
+ return void 0;
851
+ }
852
+ const r = PlanFile.safeParse((0, import_yaml2.parse)(text));
853
+ if (!r.success)
854
+ throw new InitiativeError(`initiatives/${id}/plan.yaml: ${r.error.issues.map((i) => `${i.path.join(".")} ${i.message}`).join("; ")}`);
855
+ return r.data;
856
+ }
857
+ var slugOf = (s) => s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80).replace(/-+$/, "");
858
+
859
+ // packages/initiatives/dist/dates.js
860
+ var DAY = 864e5;
861
+ var isIsoDay = (s) => /^\d{4}-\d{2}-\d{2}$/.test(s) && !Number.isNaN(Date.parse(s));
862
+ var toDate = (d) => /* @__PURE__ */ new Date(`${d}T00:00:00Z`);
863
+ var toDay = (d) => d.toISOString().slice(0, 10);
864
+ var isWeekday = (d) => d.getUTCDay() !== 0 && d.getUTCDay() !== 6;
865
+ var dayOf = (at) => typeof at === "string" ? at.slice(0, 10) : toDay(at);
866
+ function weekdayOnOrBefore(day) {
867
+ let d = toDate(day);
868
+ while (!isWeekday(d))
869
+ d = new Date(d.getTime() - DAY);
870
+ return toDay(d);
871
+ }
872
+ function addWorkingDays(day, n) {
873
+ let d = toDate(day);
874
+ for (let i = 0; i < n; ) {
875
+ d = new Date(d.getTime() + DAY);
876
+ if (isWeekday(d))
877
+ i++;
878
+ }
879
+ return toDay(d);
880
+ }
881
+ function subtractWorkingDays(day, n) {
882
+ let d = toDate(day);
883
+ for (let i = 0; i < n; ) {
884
+ d = new Date(d.getTime() - DAY);
885
+ if (isWeekday(d))
886
+ i++;
887
+ }
888
+ return toDay(d);
889
+ }
890
+ function workingDays(from, to) {
891
+ if (to < from)
892
+ return -workingDays(to, from);
893
+ let n = 0;
894
+ for (let d = new Date(toDate(from).getTime() + DAY); d <= toDate(to); d = new Date(d.getTime() + DAY))
895
+ if (isWeekday(d))
896
+ n++;
897
+ return n;
898
+ }
899
+ var laterOf = (a, b) => a > b ? a : b;
900
+ function parseLeadTime(text) {
901
+ const m = /^\s*(\d+(?:\.\d+)?)\s*(d|days?|wd|working days?|w|weeks?)?\s*$/i.exec(text);
902
+ if (!m)
903
+ return void 0;
904
+ const n = Number(m[1]);
905
+ const unit = (m[2] ?? "d").toLowerCase();
906
+ return Math.ceil(unit.startsWith("w") && unit !== "wd" && !unit.startsWith("working") ? n * 5 : n);
907
+ }
908
+
909
+ // packages/initiatives/dist/new.js
910
+ async function newInitiative(root, o) {
911
+ if (!JOURNEYS.includes(o.journey))
912
+ throw new InitiativeError(`There is no journey ${o.journey}. Journeys: ${JOURNEYS.join(", ")}.`, "usage");
913
+ if (!o.title.trim())
914
+ throw new InitiativeError("An initiative needs a title.", "usage");
915
+ if (o.targetRelease && !isIsoDay(o.targetRelease))
916
+ throw new InitiativeError("Give the target release as YYYY-MM-DD.", "usage");
917
+ const id = o.id ?? slugOf(o.title);
918
+ if (!/^[a-z0-9][a-z0-9._-]*$/.test(id))
919
+ throw new InitiativeError(`${id} is not a valid id (lowercase letters, digits, ".", "_" and "-").`, "usage");
920
+ const view = await readView(root);
921
+ if (view.get("Initiative", id))
922
+ throw new InitiativeError(`An initiative ${id} already exists.`, "exists");
923
+ const initiative = {
924
+ schemaVersion: 2,
925
+ kind: "Initiative",
926
+ id,
927
+ status: "current",
928
+ confidence: "asserted",
929
+ evidence: manualEvidence(o.by),
930
+ title: o.title.trim(),
931
+ journey: o.journey,
932
+ changes: [],
933
+ parties: [],
934
+ commitments: [],
935
+ ...o.targetRelease ? { targetRelease: o.targetRelease } : {},
936
+ ...o.adoEpic ? { adoEpic: o.adoEpic } : {}
937
+ };
938
+ const written = await writeCurated(root, initiative);
939
+ return { initiative, written };
940
+ }
941
+
942
+ // packages/initiatives/dist/leadtimes.js
943
+ var norm = (s) => s.toLowerCase().replace(/[^a-z0-9]+/g, "");
944
+ function median(xs) {
945
+ const s = [...xs].sort((a, b) => a - b);
946
+ const m = Math.floor(s.length / 2);
947
+ return s.length % 2 ? s[m] : (s[m - 1] + s[m]) / 2;
948
+ }
949
+ function leadTimeFor(step, party, ctx) {
950
+ const key = step.template ?? step.leadTimeKey;
951
+ if (party && key && party.typicalLeadTimes[key] !== void 0) {
952
+ const raw = party.typicalLeadTimes[key];
953
+ const days = parseLeadTime(raw);
954
+ if (days !== void 0)
955
+ return { days, source: `${party.id} typicalLeadTimes.${key} (${raw})` };
956
+ }
957
+ if (step.kind === "request" && step.template) {
958
+ const t = ctx.templates.find((x) => x.id === step.template);
959
+ const names = /* @__PURE__ */ new Set([norm(step.template), ...t ? [norm(t.requestType), norm(t.id)] : []]);
960
+ const past = ctx.requests.filter((r) => names.has(norm(r.type)) && r.opened && r.closed);
961
+ if (past.length) {
962
+ const days = past.map((r) => workingDays(r.opened, r.closed));
963
+ const med = median(days);
964
+ const files = [...new Set(past.map((r) => r.source.path))].sort().join(", ");
965
+ return {
966
+ days: Math.ceil(med),
967
+ source: `${files} (median ${med} working days over ${past.length} request${past.length === 1 ? "" : "s"}, rounded up)`
968
+ };
969
+ }
970
+ if (t)
971
+ return { days: t.leadTimeDays, source: `org-pack/process/snow/${t.id}.yaml leadTimeDays` };
972
+ }
973
+ return {
974
+ days: step.days,
975
+ source: `journey ${ctx.journey} step ${step.id} (${step.days} working days)`
976
+ };
977
+ }
978
+
979
+ // packages/initiatives/dist/plan.js
980
+ var cmp = (a, b) => a < b ? -1 : a > b ? 1 : 0;
981
+ var nowIso = (d) => d.toISOString().replace(/\.\d{3}Z$/, "Z");
982
+ var norm2 = (s) => s.toLowerCase().replace(/^party\./, "").replace(/[^a-z0-9]+/g, "");
983
+ function systemOf(view, id) {
984
+ if (view.get("System", id))
985
+ return id;
986
+ return view.get("Component", id)?.system;
987
+ }
988
+ function neighbours(view, target) {
989
+ const callers = /* @__PURE__ */ new Set();
990
+ const callees = /* @__PURE__ */ new Set();
991
+ for (const i of view.all("Interface")) {
992
+ if (i.status === "retired")
993
+ continue;
994
+ const from = systemOf(view, i.from);
995
+ const to = systemOf(view, i.to);
996
+ if (!from || !to || from === to)
997
+ continue;
998
+ if (to === target)
999
+ callers.add(from);
1000
+ if (from === target)
1001
+ callees.add(to);
1002
+ }
1003
+ return { callers: [...callers].sort(), callees: [...callees].sort() };
1004
+ }
1005
+ var partiesOf = (view, system) => view.all("Party").filter((p) => p.status !== "retired" && p.systems.includes(system)).sort((a, b) => cmp(a.id, b.id));
1006
+ function partyFor(view, role, o) {
1007
+ const parties = view.all("Party").filter((p) => p.status !== "retired");
1008
+ if (role.startsWith("party:"))
1009
+ return view.get("Party", role.slice("party:".length));
1010
+ switch (role) {
1011
+ case "vendor":
1012
+ return partiesOf(view, o.target).find((p) => p.partyKind === "vendor");
1013
+ case "target-owner":
1014
+ return partiesOf(view, o.target)[0];
1015
+ case "caller-owners":
1016
+ case "callee-owners":
1017
+ return o.system ? partiesOf(view, o.system)[0] : void 0;
1018
+ case "platform":
1019
+ return parties.sort((a, b) => cmp(a.id, b.id)).find((p) => /platform/i.test(`${p.id} ${p.name} ${p.owner ?? ""}`));
1020
+ case "approver": {
1021
+ const want = new Set((o.approvers ?? []).map(norm2));
1022
+ return parties.sort((a, b) => cmp(a.id, b.id)).find((p) => want.has(norm2(p.id)) || want.has(norm2(p.name)) || p.owner && want.has(norm2(p.owner)));
1023
+ }
1024
+ default:
1025
+ return void 0;
1026
+ }
1027
+ }
1028
+ var fill = (text, v) => text.replace(/\{(\w+)\}/g, (m, k) => v[k] ?? m);
1029
+ async function planJourney(root, initiativeId, o) {
1030
+ const now = o.now ?? /* @__PURE__ */ new Date();
1031
+ const view = await readView(root);
1032
+ const initiative = view.get("Initiative", initiativeId);
1033
+ if (!initiative)
1034
+ throw new InitiativeError(`There is no initiative ${initiativeId}.`, "not-found");
1035
+ const previous = await readPlan(root, initiativeId);
1036
+ const target = o.target ?? previous?.target;
1037
+ if (!target)
1038
+ throw new InitiativeError("Name the system the journey is about (--target <system>).", "usage");
1039
+ if (!systemOf(view, target))
1040
+ throw new InitiativeError(`${target} is not a system or component in the catalog.`, "usage");
1041
+ const targetSystem = systemOf(view, target);
1042
+ const release = o.targetRelease ?? initiative.targetRelease ?? previous?.targetRelease;
1043
+ if (!release || !isIsoDay(release))
1044
+ throw new InitiativeError("Give the target release as YYYY-MM-DD (--release).", "usage");
1045
+ const { journeys, problems } = await loadJourneys(root);
1046
+ const journey = journeys.get(initiative.journey);
1047
+ if (!journey)
1048
+ throw new InitiativeError(`No journey ${initiative.journey}: ${problems.join("; ")}`);
1049
+ const orgPack = await loadOrgPack(orgPackDirOf(root));
1050
+ const exports = await readServiceRequestExports({ root });
1051
+ const notes = [...problems];
1052
+ const { callers, callees } = neighbours(view, targetSystem);
1053
+ const named = (o.systems ?? []).map((s) => systemOf(view, s) ?? s);
1054
+ for (const s of o.systems ?? [])
1055
+ if (!systemOf(view, s))
1056
+ notes.push(`${s} is not in the catalog; its items use the id as given.`);
1057
+ const scope = {
1058
+ once: [void 0],
1059
+ target: [targetSystem],
1060
+ callers,
1061
+ callees,
1062
+ systems: named
1063
+ };
1064
+ const nameOf = (s) => view.get("System", s)?.name ?? s;
1065
+ const steps = stepsOf(journey);
1066
+ const items = [];
1067
+ const itemsOfStep = /* @__PURE__ */ new Map();
1068
+ const skipped = /* @__PURE__ */ new Set();
1069
+ steps.forEach((step, order) => {
1070
+ const systems = scope[step.per];
1071
+ if (!systems.length) {
1072
+ skipped.add(step.id);
1073
+ notes.push(`Step ${step.id} is per ${step.per.replace(/s$/, "")} and ${nameOf(targetSystem)} has none: left out.`);
1074
+ itemsOfStep.set(step.id, []);
1075
+ return;
1076
+ }
1077
+ const made = [];
1078
+ for (const system of systems) {
1079
+ const vars = {
1080
+ initiative: initiative.title,
1081
+ target: targetSystem,
1082
+ targetName: nameOf(targetSystem),
1083
+ system: system ?? targetSystem,
1084
+ systemName: system ? nameOf(system) : nameOf(targetSystem)
1085
+ };
1086
+ const template = step.template ? orgPack.serviceRequests.find((t) => t.id === step.template) : void 0;
1087
+ if (step.kind === "request" && !template)
1088
+ notes.push(`Step ${step.id} needs the request template ${step.template}, which the org pack doesn't have; the journey default is used.`);
1089
+ const party = step.party ? partyFor(view, step.party, {
1090
+ target: targetSystem,
1091
+ ...system ? { system } : {},
1092
+ approvers: template?.approvers ?? []
1093
+ }) : void 0;
1094
+ if (step.party && !party)
1095
+ notes.push(`No party for step ${step.id}${system ? ` (${system})` : ""} (${step.party}): add a Party record to catalog/curated/party/ and plan again.`);
1096
+ const lt = leadTimeFor(step, party, {
1097
+ templates: orgPack.serviceRequests,
1098
+ requests: exports.requests,
1099
+ journey: journey.id
1100
+ });
1101
+ const key = step.per === "once" ? step.id : `${step.id}.${system}`;
1102
+ const change = step.kind === "change" ? system ? `${initiative.id}-${system}` : initiative.id : void 0;
1103
+ const d = {
1104
+ order,
1105
+ key,
1106
+ step: step.id,
1107
+ phase: step.phase,
1108
+ kind: step.kind,
1109
+ what: fill(step.what, vars),
1110
+ ...system && step.per !== "once" ? { system } : {},
1111
+ ...party ? { party: party.id } : {},
1112
+ ...(step.kind === "commitment" || step.kind === "request") && party ? { commitment: `${initiative.id}.${key}` } : {},
1113
+ ...change ? { change } : {},
1114
+ ...step.milestone ? { milestone: step.milestone } : {},
1115
+ ...step.template ? { template: step.template } : {},
1116
+ ...step.owner ? { owner: step.owner } : {},
1117
+ days: lt.days,
1118
+ leadTime: lt.source,
1119
+ after: []
1120
+ };
1121
+ made.push(d);
1122
+ items.push(d);
1123
+ }
1124
+ itemsOfStep.set(step.id, made);
1125
+ });
1126
+ const stepById = new Map(steps.map((s) => [s.id, s]));
1127
+ const predecessorsOf = (stepId, seen = /* @__PURE__ */ new Set()) => {
1128
+ const out = [];
1129
+ for (const a of stepById.get(stepId)?.after ?? []) {
1130
+ if (seen.has(a))
1131
+ continue;
1132
+ seen.add(a);
1133
+ if (skipped.has(a))
1134
+ out.push(...predecessorsOf(a, seen));
1135
+ else
1136
+ out.push(a);
1137
+ }
1138
+ return out;
1139
+ };
1140
+ for (const d of items) {
1141
+ const after = [];
1142
+ for (const a of predecessorsOf(d.step)) {
1143
+ const its = itemsOfStep.get(a) ?? [];
1144
+ const same = d.system ? its.filter((x) => x.system === d.system) : [];
1145
+ for (const x of same.length ? same : its)
1146
+ if (!after.includes(x.key))
1147
+ after.push(x.key);
1148
+ }
1149
+ d.after = after;
1150
+ }
1151
+ const successors = new Map(items.map((d) => [d.key, []]));
1152
+ for (const d of items)
1153
+ for (const a of d.after)
1154
+ successors.get(a).push(d);
1155
+ const releaseDay = weekdayOnOrBefore(release);
1156
+ if (releaseDay !== release)
1157
+ notes.push(`${release} is a weekend day; the plan ends on ${releaseDay}.`);
1158
+ const dates = /* @__PURE__ */ new Map();
1159
+ const byKey = new Map(items.map((d) => [d.key, d]));
1160
+ const remaining = new Map(items.map((d) => [d.key, successors.get(d.key).length]));
1161
+ const ready = items.filter((d) => remaining.get(d.key) === 0);
1162
+ while (ready.length) {
1163
+ ready.sort((a, b) => b.order - a.order || (a.key < b.key ? 1 : -1));
1164
+ const d = ready.shift();
1165
+ const succ = successors.get(d.key);
1166
+ const due = succ.length ? succ.map((s) => dates.get(s.key).start).sort()[0] : releaseDay;
1167
+ dates.set(d.key, { start: subtractWorkingDays(due, d.days), due });
1168
+ for (const a of d.after) {
1169
+ remaining.set(a, remaining.get(a) - 1);
1170
+ if (remaining.get(a) === 0)
1171
+ ready.push(byKey.get(a));
1172
+ }
1173
+ }
1174
+ const today = now.toISOString().slice(0, 10);
1175
+ const planItems = items.sort((a, b) => a.order - b.order || cmp(a.key, b.key)).map(({ order: _o, ...d }) => ({ ...d, ...dates.get(d.key) }));
1176
+ const late = planItems.filter((i) => i.start < today);
1177
+ if (late.length)
1178
+ notes.push(`Already behind on the day it is planned: ${late.map((i) => `${i.key} (should have started ${i.start})`).join(", ")}.`);
1179
+ const plan = {
1180
+ schemaVersion: 1,
1181
+ initiative: initiative.id,
1182
+ journey: journey.id,
1183
+ journeySource: journey.source,
1184
+ target: targetSystem,
1185
+ targetRelease: release,
1186
+ createdAt: nowIso(now),
1187
+ by: o.by.replace(/^@/, ""),
1188
+ items: planItems,
1189
+ done: previous?.done ?? {},
1190
+ started: previous?.started ?? {},
1191
+ notes
1192
+ };
1193
+ const keyToRef = (k) => byKey.get(k)?.change ?? k;
1194
+ const commitments = [];
1195
+ for (const i of planItems) {
1196
+ if (!i.commitment || !i.party)
1197
+ continue;
1198
+ const party = view.get("Party", i.party);
1199
+ const existing = view.get("Commitment", i.commitment);
1200
+ const blocks = [...new Set(successors.get(i.key).map((s) => keyToRef(s.key)))];
1201
+ commitments.push({
1202
+ schemaVersion: SCHEMA_VERSION,
1203
+ kind: "Commitment",
1204
+ id: i.commitment,
1205
+ status: "current",
1206
+ confidence: "asserted",
1207
+ evidence: existing?.evidence ?? manualEvidence(o.by),
1208
+ initiative: initiative.id,
1209
+ party: party.id,
1210
+ what: i.what,
1211
+ owner: party.owner ?? party.name,
1212
+ neededBy: i.due,
1213
+ blocks,
1214
+ commitmentStatus: existing?.commitmentStatus === "done" ? "done" : "open"
1215
+ });
1216
+ }
1217
+ const changes = [];
1218
+ for (const i of planItems) {
1219
+ if (!i.change || changes.some((c) => c.id === i.change))
1220
+ continue;
1221
+ const step = stepById.get(i.step);
1222
+ const title = `${initiative.title}: ${i.system ? nameOf(i.system) : nameOf(targetSystem)}`;
1223
+ changes.push({
1224
+ id: i.change,
1225
+ title,
1226
+ type: step.changeType,
1227
+ ...i.system ? { system: i.system } : {},
1228
+ command: `atticus change new "${title}" --type ${step.changeType} --id ${i.change}${i.system ? ` --system ${i.system}` : ""}`
1229
+ });
1230
+ }
1231
+ const updated = {
1232
+ ...initiative,
1233
+ changes: [.../* @__PURE__ */ new Set([...initiative.changes, ...changes.map((c) => c.id)])],
1234
+ parties: [
1235
+ .../* @__PURE__ */ new Set([...initiative.parties, ...planItems.flatMap((i) => i.party ? [i.party] : [])])
1236
+ ],
1237
+ commitments: [.../* @__PURE__ */ new Set([...initiative.commitments, ...commitments.map((c) => c.id)])],
1238
+ targetRelease: release
1239
+ };
1240
+ const written = [];
1241
+ if (!o.dryRun) {
1242
+ written.push(await writePlan(root, plan));
1243
+ for (const c of commitments)
1244
+ written.push(await writeCurated(root, c));
1245
+ written.push(await writeCurated(root, updated));
1246
+ }
1247
+ return { initiative: updated, plan, commitments, changes, notes, written };
1248
+ }
1249
+
1250
+ // packages/initiatives/dist/status.js
1251
+ var cmp2 = (a, b) => a < b ? -1 : a > b ? 1 : 0;
1252
+ var ORDER = LIFECYCLE_STATES;
1253
+ var REACHED = {
1254
+ design: "plan",
1255
+ build: "qa",
1256
+ "release-ready": "release-ready",
1257
+ released: "released"
1258
+ };
1259
+ function reached(state, milestone) {
1260
+ if (!state || state === "returned" || state === "draft")
1261
+ return false;
1262
+ const need = REACHED[milestone];
1263
+ if (!need)
1264
+ return false;
1265
+ const rank = (s) => s === "post-release-review" ? ORDER.indexOf("released") + 0.5 : ORDER.indexOf(s);
1266
+ return rank(state) >= rank(need);
1267
+ }
1268
+ async function initiativeStatus(root, id, o = {}) {
1269
+ const today = dayOf(o.now ?? /* @__PURE__ */ new Date());
1270
+ const view = await readView(root);
1271
+ const initiative = view.get("Initiative", id);
1272
+ if (!initiative)
1273
+ throw new InitiativeError(`There is no initiative ${id}.`, "not-found");
1274
+ const plan = await readPlan(root, id);
1275
+ const store = changeStore(root);
1276
+ const notes = [];
1277
+ const changeStates = /* @__PURE__ */ new Map();
1278
+ for (const c of initiative.changes) {
1279
+ try {
1280
+ changeStates.set(c, (await store.tryRead(c))?.state);
1281
+ } catch (e) {
1282
+ changeStates.set(c, void 0);
1283
+ notes.push(`Change ${c}: ${e.message}`);
1284
+ }
1285
+ }
1286
+ const commitmentRecords = view.all("Commitment").filter((c) => c.initiative === id);
1287
+ const recordOf = new Map(commitmentRecords.map((c) => [c.id, c]));
1288
+ const items = [];
1289
+ let projectedRelease;
1290
+ if (plan) {
1291
+ const isDone = (i) => {
1292
+ if (i.kind === "change")
1293
+ return reached(changeStates.get(i.change), i.milestone);
1294
+ if (i.commitment)
1295
+ return recordOf.get(i.commitment)?.commitmentStatus === "done";
1296
+ return !!plan.done[i.key];
1297
+ };
1298
+ const byKey = new Map(plan.items.map((i) => [i.key, i]));
1299
+ const succ = new Map(plan.items.map((i) => [i.key, []]));
1300
+ for (const i of plan.items)
1301
+ for (const a of i.after)
1302
+ succ.get(a)?.push(i.key);
1303
+ const order = topo(plan.items);
1304
+ const ef = /* @__PURE__ */ new Map();
1305
+ const done = /* @__PURE__ */ new Map();
1306
+ for (const k of order) {
1307
+ const i = byKey.get(k);
1308
+ const d = isDone(i);
1309
+ done.set(k, d);
1310
+ if (d) {
1311
+ ef.set(k, today);
1312
+ continue;
1313
+ }
1314
+ const preds = i.after.map((a) => ef.get(a)).filter(Boolean);
1315
+ const startFrom = plan.started[k] ?? laterOf(today, i.start);
1316
+ const es = preds.reduce((m, p) => laterOf(m, p), startFrom);
1317
+ ef.set(k, laterOf(addWorkingDays(es, i.days), today));
1318
+ }
1319
+ const open = order.filter((k) => !done.get(k));
1320
+ const end = open.map((k) => ef.get(k)).sort().at(-1) ?? today;
1321
+ projectedRelease = end;
1322
+ const lf = /* @__PURE__ */ new Map();
1323
+ for (const k of [...order].reverse()) {
1324
+ if (done.get(k))
1325
+ continue;
1326
+ const after = succ.get(k).filter((s) => !done.get(s));
1327
+ const latest = after.length ? after.map((s) => subtractWorkingDays(lf.get(s), byKey.get(s).days)).sort()[0] : end;
1328
+ lf.set(k, latest);
1329
+ }
1330
+ for (const i of plan.items) {
1331
+ const d = done.get(i.key);
1332
+ const finish = ef.get(i.key);
1333
+ const float = d ? 0 : workingDays(finish, lf.get(i.key));
1334
+ const status2 = d ? "done" : today > i.due ? "slipped" : finish > i.due ? "at-risk" : "open";
1335
+ const lateBefore = i.after.filter((a) => !done.get(a) && ef.get(a) > byKey.get(a).due);
1336
+ const why = status2 === "done" ? "Done." : status2 === "slipped" ? `Due ${i.due} and not done.` : status2 === "at-risk" ? `Projected to finish ${finish}, after its due date ${i.due}${lateBefore.length ? `, because ${lateBefore.join(", ")} ${lateBefore.length === 1 ? "is" : "are"} late` : ""}.` : `On plan: due ${i.due}.`;
1337
+ items.push({
1338
+ key: i.key,
1339
+ kind: i.kind,
1340
+ what: i.what,
1341
+ ...i.party ? { party: i.party } : {},
1342
+ ...i.change ? { change: i.change } : {},
1343
+ ...i.commitment ? { commitment: i.commitment } : {},
1344
+ start: i.start,
1345
+ due: i.due,
1346
+ done: d,
1347
+ projectedFinish: finish,
1348
+ float,
1349
+ critical: !d && float <= 0,
1350
+ status: status2,
1351
+ why
1352
+ });
1353
+ }
1354
+ } else
1355
+ notes.push(`Initiative ${id} has no plan yet: run initiative plan.`);
1356
+ const criticalPath = [];
1357
+ const stateOf = new Map(items.map((i) => [i.key, i]));
1358
+ const planByKey = new Map((plan?.items ?? []).map((i) => [i.key, i]));
1359
+ const pick = (keys) => keys.map((k) => stateOf.get(k)).filter((s) => s && s.critical).sort((a, b) => a.projectedFinish === b.projectedFinish ? cmp2(a.key, b.key) : a.projectedFinish < b.projectedFinish ? 1 : -1)[0];
1360
+ const sinks = items.filter((i) => !items.some((j) => planByKey.get(j.key)?.after.includes(i.key)));
1361
+ let cur = pick(sinks.map((s) => s.key));
1362
+ while (cur) {
1363
+ criticalPath.unshift(cur.key);
1364
+ cur = pick(planByKey.get(cur.key).after);
1365
+ }
1366
+ const commitments = commitmentRecords.map((c) => {
1367
+ const item = items.find((i) => i.commitment === c.id);
1368
+ let status2;
1369
+ let why;
1370
+ if (c.commitmentStatus === "done")
1371
+ [status2, why] = ["done", "Done."];
1372
+ else if (item)
1373
+ [status2, why] = [item.status, item.why];
1374
+ else if (today > c.neededBy)
1375
+ [status2, why] = ["slipped", `Needed by ${c.neededBy} and not done.`];
1376
+ else if (workingDays(today, c.neededBy) <= 2)
1377
+ [status2, why] = ["at-risk", `Needed by ${c.neededBy}: two working days or less left.`];
1378
+ else
1379
+ [status2, why] = ["open", `Needed by ${c.neededBy}.`];
1380
+ return {
1381
+ id: c.id,
1382
+ what: c.what,
1383
+ party: c.party,
1384
+ neededBy: c.neededBy,
1385
+ recorded: c.commitmentStatus,
1386
+ status: status2,
1387
+ why
1388
+ };
1389
+ });
1390
+ const changes = initiative.changes.map((c) => {
1391
+ const state = changeStates.get(c);
1392
+ return {
1393
+ id: c,
1394
+ ...state ? { state } : {},
1395
+ milestones: (plan?.items ?? []).filter((i) => i.change === c).map((i) => ({
1396
+ milestone: i.milestone,
1397
+ due: i.due,
1398
+ reached: reached(state, i.milestone)
1399
+ }))
1400
+ };
1401
+ });
1402
+ const target = plan?.targetRelease ?? initiative.targetRelease;
1403
+ const allDone = items.length > 0 && items.every((i) => i.done);
1404
+ const status = !plan ? "not-planned" : allDone ? "done" : target && today > target ? "slipped" : items.some((i) => i.status === "slipped" || i.status === "at-risk") || target && projectedRelease && projectedRelease > target || commitments.some((c) => c.status === "slipped" || c.status === "at-risk") ? "at-risk" : "on-track";
1405
+ return {
1406
+ initiative: id,
1407
+ title: initiative.title,
1408
+ journey: initiative.journey,
1409
+ ...plan ? { target: plan.target } : {},
1410
+ ...target ? { targetRelease: target } : {},
1411
+ today,
1412
+ ...projectedRelease ? { projectedRelease } : {},
1413
+ status,
1414
+ items,
1415
+ criticalPath,
1416
+ commitments,
1417
+ changes,
1418
+ notes
1419
+ };
1420
+ }
1421
+ function topo(items) {
1422
+ const out = [];
1423
+ const seen = /* @__PURE__ */ new Set();
1424
+ const byKey = new Map(items.map((i) => [i.key, i]));
1425
+ const visit = (k) => {
1426
+ if (seen.has(k))
1427
+ return;
1428
+ seen.add(k);
1429
+ for (const a of byKey.get(k)?.after ?? [])
1430
+ visit(a);
1431
+ out.push(k);
1432
+ };
1433
+ for (const i of items)
1434
+ visit(i.key);
1435
+ return out;
1436
+ }
1437
+ async function recordCommitment(root, id, o) {
1438
+ const view = await readView(root);
1439
+ const c = view.get("Commitment", id);
1440
+ if (!c)
1441
+ throw new InitiativeError(`There is no commitment ${id}.`, "not-found");
1442
+ const by = o.by.replace(/^@/, "");
1443
+ const evidence = c.evidence.some((e) => e.source === "manual" && e.by === by) ? c.evidence : [...c.evidence, ...manualEvidence(by)];
1444
+ const updated = { ...c, commitmentStatus: o.status, evidence };
1445
+ return { commitment: updated, written: await writeCurated(root, updated) };
1446
+ }
1447
+
1448
+ // packages/initiatives/dist/card.js
1449
+ import { mkdir as mkdir2, writeFile as writeFile2 } from "node:fs/promises";
1450
+ import { dirname as dirname2, join as join3 } from "node:path";
1451
+ var cmp3 = (a, b) => a < b ? -1 : a > b ? 1 : 0;
1452
+ var cell = (s) => s.replace(/\|/g, "\\|").replace(/\n/g, " ");
1453
+ var op = (method, path) => method ? `${method} ${path}` : path;
1454
+ function table(header, rows) {
1455
+ if (!rows.length)
1456
+ return ["None known."];
1457
+ return [
1458
+ `| ${header.join(" | ")} |`,
1459
+ `| ${header.map(() => "---").join(" | ")} |`,
1460
+ ...rows.map((r) => `| ${r.map(cell).join(" | ")} |`)
1461
+ ];
1462
+ }
1463
+ function systemCard(view, systems, o = {}) {
1464
+ const sys = systems.map((s) => view.get("System", s)).filter((s) => !!s);
1465
+ if (!sys.length)
1466
+ throw new InitiativeError(`None of ${systems.join(", ")} is a system in the catalog.`, "not-found");
1467
+ const ids = new Set(sys.map((s) => s.id));
1468
+ const inSys = (id) => {
1469
+ const s = systemOf(view, id);
1470
+ return s !== void 0 && ids.has(s);
1471
+ };
1472
+ const label = (id) => {
1473
+ if (inSys(id))
1474
+ return id;
1475
+ const s = systemOf(view, id);
1476
+ const name = s ? view.get("System", s)?.name : void 0;
1477
+ return s && s !== id && name ? `${id} (${name})` : id;
1478
+ };
1479
+ const title = sys.map((s) => s.name).join(", ");
1480
+ const L = [`# System card: ${title}`, ""];
1481
+ if (o.header?.length)
1482
+ L.push(...o.header, "");
1483
+ L.push("Please check what we know about your system, correct anything that is wrong, and answer the open questions. Your reply goes into our intake as a document; nothing here changes without a person reviewing it.", "", "## Systems", "", ...table(["System", "Boundary", "Owner", "Repos"], sys.map((s) => [
1484
+ `${s.name} (${s.id})`,
1485
+ s.boundary,
1486
+ s.owner ?? "unknown",
1487
+ s.repos.join(", ") || "none"
1488
+ ])), "");
1489
+ const comps = view.all("Component").filter((c) => ids.has(c.system)).sort((a, b) => cmp3(a.id, b.id));
1490
+ if (comps.length)
1491
+ L.push("## Components", "", ...table(["Component", "Type", "Repo"], comps.map((c) => [c.id, c.type, c.repo ?? "unknown"])), "");
1492
+ const endpoints = view.all("Endpoint").filter((e) => inSys(e.component)).sort((a, b) => cmp3(a.id, b.id));
1493
+ L.push("## What it offers", "", ...table(["Endpoint", "Type", "Operation"], endpoints.map((e) => [e.id, e.endpointType, op(e.method, e.pathOrTopic)])), "");
1494
+ const ifs = view.all("Interface").filter((i) => i.status !== "retired");
1495
+ const row = (i) => [
1496
+ label(i.from),
1497
+ label(i.to),
1498
+ i.via,
1499
+ op(i.method, i.normalizedPath),
1500
+ i.sync
1501
+ ];
1502
+ const byPath = (a, b) => cmp3(a.from, b.from) || cmp3(a.to, b.to) || cmp3(a.normalizedPath, b.normalizedPath);
1503
+ L.push("## Who calls it", "", ...table(["From", "To", "Via", "Operation", "Sync"], ifs.filter((i) => inSys(i.to) && !inSys(i.from)).sort(byPath).map(row)), "", "## What it calls", "", ...table(["From", "To", "Via", "Operation", "Sync"], ifs.filter((i) => inSys(i.from) && !inSys(i.to)).sort(byPath).map(row)), "");
1504
+ const stores = view.all("DataStore").filter((d) => d.ownerComponent && inSys(d.ownerComponent)).sort((a, b) => cmp3(a.id, b.id));
1505
+ const tables = view.all("Table").filter((t) => stores.some((s) => s.id === t.dataStore));
1506
+ L.push("## Data it owns", "", ...table(["Store", "Type", "Tables"], stores.map((s) => [
1507
+ s.id,
1508
+ s.storeType,
1509
+ tables.filter((t) => t.dataStore === s.id).map((t) => t.id).sort().join(", ") || "none known"
1510
+ ])), "");
1511
+ const questions = view.all("OwnerQuestion").filter((q) => ids.has(q.system) && q.questionState !== "answered").sort((a, b) => cmp3(a.id, b.id));
1512
+ L.push("## Open questions", "");
1513
+ if (questions.length)
1514
+ for (const q of questions)
1515
+ L.push(`- (${q.id}) ${q.question} Needed: ${q.neededFact}. Asked of: ${q.owner} (${q.questionState})`);
1516
+ else
1517
+ L.push("None recorded.");
1518
+ L.push("", "## How to reply", "", "Reply in any form: edit this page, send a document or an e-mail. The reply is saved into the metarepo with `atticus intake add <file>`; it is read like any other document and every fact in it is checked against code.", "");
1519
+ return L.join("\n");
1520
+ }
1521
+ var nowIso2 = (d) => d.toISOString().replace(/\.\d{3}Z$/, "Z");
1522
+ async function requestFromTeam(root, initiativeId, partyId, o) {
1523
+ const now = o.now ?? /* @__PURE__ */ new Date();
1524
+ const today = dayOf(now);
1525
+ const by = o.by.replace(/^@/, "");
1526
+ const view = await readView(root);
1527
+ const initiative = view.get("Initiative", initiativeId);
1528
+ if (!initiative)
1529
+ throw new InitiativeError(`There is no initiative ${initiativeId}.`, "not-found");
1530
+ const party = view.get("Party", partyId);
1531
+ if (!party)
1532
+ throw new InitiativeError(`There is no party ${partyId}.`, "not-found");
1533
+ const systems = o.systems ?? party.systems;
1534
+ if (!systems.length)
1535
+ throw new InitiativeError(`Party ${partyId} names no systems; add them to its record or pass --system.`, "usage");
1536
+ const raw = party.typicalLeadTimes["system-card"];
1537
+ const days = (raw ? parseLeadTime(raw) : void 0) ?? 5;
1538
+ const due = addWorkingDays(today, days);
1539
+ const slug = partyId.replace(/^party\./, "");
1540
+ const cardRel = `initiatives/${initiativeId}/requests/${slug}.md`;
1541
+ const card = systemCard(view, systems, {
1542
+ header: [
1543
+ `For: ${initiative.title} (initiative ${initiative.id})`,
1544
+ `Asked of: ${party.name} (${party.id}), by ${by} on ${today}`,
1545
+ `Reply by: ${due}`
1546
+ ]
1547
+ });
1548
+ const cardFile = join3(initiativeDir(root, initiativeId), "requests", `${slug}.md`);
1549
+ await mkdir2(dirname2(cardFile), { recursive: true });
1550
+ await writeFile2(cardFile, card, "utf8");
1551
+ const commitment = {
1552
+ schemaVersion: 2,
1553
+ kind: "Commitment",
1554
+ id: `${initiativeId}.request.${slug}`,
1555
+ status: "current",
1556
+ confidence: "asserted",
1557
+ evidence: manualEvidence(by),
1558
+ initiative: initiative.id,
1559
+ party: party.id,
1560
+ what: `${party.name} replies to the system card for ${systems.join(", ")}`,
1561
+ owner: party.owner ?? party.name,
1562
+ neededBy: due,
1563
+ blocks: [...initiative.changes],
1564
+ commitmentStatus: "open"
1565
+ };
1566
+ const written = [cardRel, await writeCurated(root, commitment)];
1567
+ const updated = {
1568
+ ...initiative,
1569
+ parties: [.../* @__PURE__ */ new Set([...initiative.parties, party.id])],
1570
+ commitments: [.../* @__PURE__ */ new Set([...initiative.commitments, commitment.id])]
1571
+ };
1572
+ written.push(await writeCurated(root, updated));
1573
+ const notification = {
1574
+ channel: party.channel ?? "email",
1575
+ title: `System card: ${systems.join(", ")} (reply by ${due})`,
1576
+ body: [
1577
+ `Hello ${party.name},`,
1578
+ "",
1579
+ `For ${initiative.title} we need you to check what we know about ${systems.join(", ")} and answer the open questions on the attached system card by ${due}.`,
1580
+ "Reply in any form; we take your reply in as a document and check every fact against code.",
1581
+ "",
1582
+ `Sent by ${by}.`
1583
+ ].join("\n"),
1584
+ link: cardRel,
1585
+ ...party.contacts.length ? { mentions: party.contacts } : {}
1586
+ };
1587
+ const store = o.steps ?? fileStepStore(root);
1588
+ const notifier = new ManualNotifier({ store, root, now: () => nowIso2(now) });
1589
+ const sent = await notifier.send(notification, { by, at: nowIso2(now), ref: commitment.id });
1590
+ const stepId = sent.id.replace(/^manual:/, "");
1591
+ const step = await store.get(stepId);
1592
+ written.push(`steps/${step.id}.yaml`);
1593
+ return { card, cardPath: cardRel, commitment, notification, step, written };
1594
+ }
1595
+
1596
+ export {
1597
+ dayOf,
1598
+ addWorkingDays,
1599
+ workingDays,
1600
+ laterOf,
1601
+ JOURNEYS,
1602
+ InitiativeError,
1603
+ readView,
1604
+ readPlan,
1605
+ leadTimeFor,
1606
+ newInitiative,
1607
+ planJourney,
1608
+ initiativeStatus,
1609
+ recordCommitment,
1610
+ requestFromTeam
1611
+ };