@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,1142 @@
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
+ parseRecord
8
+ } from "./chunk-S2A7YC3Q.js";
9
+
10
+ // packages/sdk/dist/parse-cache.js
11
+ import { createHash } from "node:crypto";
12
+ var DEFAULT_PARSE_CACHE_LIMITS = {
13
+ maxChars: 8e6,
14
+ maxEntries: 2e4,
15
+ maxNativeChars: 1e6,
16
+ maxNativeEntries: 2e3,
17
+ maxTextChars: 16e6
18
+ };
19
+ function refuse() {
20
+ throw new TypeError("a parsed value is shared by every reader and can't be changed; copy it");
21
+ }
22
+ function deepFreeze(value) {
23
+ const stack = [value];
24
+ const seen = /* @__PURE__ */ new Set();
25
+ while (stack.length > 0) {
26
+ const v = stack.pop();
27
+ if (v === null || typeof v !== "object" || seen.has(v))
28
+ continue;
29
+ seen.add(v);
30
+ if (ArrayBuffer.isView(v) || v instanceof ArrayBuffer)
31
+ continue;
32
+ if (v instanceof Map) {
33
+ for (const [k, x] of v)
34
+ stack.push(k, x);
35
+ for (const m of ["set", "delete", "clear"])
36
+ Object.defineProperty(v, m, { value: refuse });
37
+ } else if (v instanceof Set) {
38
+ for (const x of v)
39
+ stack.push(x);
40
+ for (const m of ["add", "delete", "clear"])
41
+ Object.defineProperty(v, m, { value: refuse });
42
+ }
43
+ for (const k of Object.keys(v))
44
+ stack.push(v[k]);
45
+ Object.freeze(v);
46
+ }
47
+ return value;
48
+ }
49
+ var hash = (text) => createHash("sha1").update(text).digest("base64");
50
+ function createParseCache(limits = {}) {
51
+ const l = { ...DEFAULT_PARSE_CACHE_LIMITS, ...limits };
52
+ const values = { map: /* @__PURE__ */ new Map(), chars: 0, maxChars: l.maxChars, maxEntries: l.maxEntries };
53
+ const native = {
54
+ map: /* @__PURE__ */ new Map(),
55
+ chars: 0,
56
+ maxChars: l.maxNativeChars,
57
+ maxEntries: l.maxNativeEntries
58
+ };
59
+ const texts = /* @__PURE__ */ new Map();
60
+ const reading = /* @__PURE__ */ new Map();
61
+ let textChars = 0;
62
+ let disposed = false;
63
+ const st = { hits: 0, misses: 0, evictions: 0, textHits: 0, textReads: 0 };
64
+ const byKind = {};
65
+ const count = (kind, hit) => {
66
+ const k = byKind[kind] ??= { hits: 0, misses: 0 };
67
+ if (hit) {
68
+ k.hits++;
69
+ st.hits++;
70
+ } else {
71
+ k.misses++;
72
+ st.misses++;
73
+ }
74
+ };
75
+ const free = (e) => {
76
+ if (e.done && e.dispose)
77
+ e.dispose(e.value);
78
+ };
79
+ const remove = (e) => {
80
+ if (e.pool.map.get(e.key) !== e)
81
+ return;
82
+ e.pool.map.delete(e.key);
83
+ e.pool.chars -= e.weight;
84
+ e.gone = true;
85
+ if (e.pins === 0)
86
+ free(e);
87
+ };
88
+ const trim = (pool) => {
89
+ if (pool.chars <= pool.maxChars && pool.map.size <= pool.maxEntries)
90
+ return;
91
+ for (const e of [...pool.map.values()]) {
92
+ if (pool.chars <= pool.maxChars && pool.map.size <= pool.maxEntries)
93
+ break;
94
+ if (e.pins > 0 || !e.done)
95
+ continue;
96
+ remove(e);
97
+ st.evictions++;
98
+ }
99
+ };
100
+ const touch = (e) => {
101
+ e.pool.map.delete(e.key);
102
+ e.pool.map.set(e.key, e);
103
+ };
104
+ const entry = (kind, path, text, o) => {
105
+ const pool = o.pool === "native" ? native : values;
106
+ const key = `${kind}\0${path}\0${text.length}\0${hash(text)}`;
107
+ const found = pool.map.get(key);
108
+ if (found && found.text === text) {
109
+ touch(found);
110
+ count(kind, true);
111
+ return { e: found, hit: true };
112
+ }
113
+ if (found)
114
+ remove(found);
115
+ count(kind, false);
116
+ const e = {
117
+ key,
118
+ text,
119
+ weight: o.weight ?? text.length,
120
+ pool,
121
+ done: false,
122
+ pins: 0,
123
+ gone: false,
124
+ ...o.dispose ? { dispose: o.dispose } : {}
125
+ };
126
+ if (!disposed && pool.maxChars > 0 && pool.maxEntries > 0 && e.weight <= pool.maxChars) {
127
+ pool.map.set(key, e);
128
+ pool.chars += e.weight;
129
+ } else
130
+ e.gone = true;
131
+ return { e, hit: false };
132
+ };
133
+ const settle = (e, value, freeze) => {
134
+ e.value = freeze ? deepFreeze(value) : value;
135
+ e.done = true;
136
+ delete e.pending;
137
+ };
138
+ const fail = (e) => {
139
+ if (e.pool.map.get(e.key) === e) {
140
+ e.pool.map.delete(e.key);
141
+ e.pool.chars -= e.weight;
142
+ }
143
+ e.gone = true;
144
+ };
145
+ const valueOf = async (e, hit, parse, o) => {
146
+ if (hit)
147
+ return e.done ? e.value : await e.pending;
148
+ const p = (async () => parse(e.text))();
149
+ e.pending = p;
150
+ try {
151
+ const v = await p;
152
+ settle(e, v, o.freeze !== false);
153
+ return e.value;
154
+ } catch (err) {
155
+ fail(e);
156
+ throw err;
157
+ }
158
+ };
159
+ return {
160
+ get(kind, path, text, parse, o = {}) {
161
+ const { e, hit } = entry(kind, path, text, o);
162
+ if (hit && e.done)
163
+ return e.value;
164
+ if (hit)
165
+ throw new Error(`${kind} of ${path} is being parsed asynchronously; use getAsync`);
166
+ let v;
167
+ try {
168
+ v = parse(text);
169
+ } catch (err) {
170
+ fail(e);
171
+ throw err;
172
+ }
173
+ settle(e, v, o.freeze !== false);
174
+ trim(e.pool);
175
+ return e.value;
176
+ },
177
+ async getAsync(kind, path, text, parse, o = {}) {
178
+ const { e, hit } = entry(kind, path, text, o);
179
+ const v = await valueOf(e, hit, parse, o);
180
+ trim(e.pool);
181
+ return v;
182
+ },
183
+ async use(kind, path, text, parse, use, o = {}) {
184
+ const { e, hit } = entry(kind, path, text, o);
185
+ e.pins++;
186
+ try {
187
+ const v = await valueOf(e, hit, parse, o);
188
+ return await use(v);
189
+ } finally {
190
+ e.pins--;
191
+ if (e.pins === 0 && e.gone)
192
+ free(e);
193
+ else
194
+ trim(e.pool);
195
+ }
196
+ },
197
+ async text(path, read) {
198
+ const t = texts.get(path);
199
+ if (t !== void 0) {
200
+ st.textHits++;
201
+ texts.delete(path);
202
+ texts.set(path, t);
203
+ return t;
204
+ }
205
+ const inFlight = reading.get(path);
206
+ if (inFlight) {
207
+ st.textHits++;
208
+ return inFlight;
209
+ }
210
+ st.textReads++;
211
+ const p = read();
212
+ reading.set(path, p);
213
+ let text;
214
+ try {
215
+ text = await p;
216
+ } finally {
217
+ reading.delete(path);
218
+ }
219
+ if (disposed || l.maxTextChars <= 0 || text.length > l.maxTextChars)
220
+ return text;
221
+ texts.set(path, text);
222
+ textChars += text.length;
223
+ for (const [p2, x] of texts) {
224
+ if (textChars <= l.maxTextChars)
225
+ break;
226
+ texts.delete(p2);
227
+ textChars -= x.length;
228
+ }
229
+ return text;
230
+ },
231
+ stats() {
232
+ return {
233
+ ...st,
234
+ entries: values.map.size,
235
+ chars: values.chars,
236
+ nativeEntries: native.map.size,
237
+ nativeChars: native.chars,
238
+ texts: texts.size,
239
+ byKind: structuredClone(byKind)
240
+ };
241
+ },
242
+ dispose() {
243
+ disposed = true;
244
+ for (const pool of [values, native])
245
+ for (const e of [...pool.map.values()])
246
+ remove(e);
247
+ texts.clear();
248
+ textChars = 0;
249
+ }
250
+ };
251
+ }
252
+ function withParseCache(repo, cache) {
253
+ const wrapped = Object.create(repo);
254
+ Object.defineProperties(wrapped, {
255
+ parseCache: { value: cache, enumerable: true },
256
+ readText: { value: (path) => cache.text(path, () => repo.readText(path)) }
257
+ });
258
+ return wrapped;
259
+ }
260
+
261
+ // packages/sdk/dist/plugin.js
262
+ function defineExtractor(extractor) {
263
+ if (!/^[a-z][a-z0-9-]*$/.test(extractor.id)) {
264
+ throw new Error(`extractor id "${extractor.id}" must be a lowercase slug`);
265
+ }
266
+ if (!/^\d+\.\d+\.\d+(-[0-9a-z.-]+)?$/i.test(extractor.version)) {
267
+ throw new Error(`extractor version "${extractor.version}" must be semver`);
268
+ }
269
+ if (extractor.claims.length === 0) {
270
+ throw new Error(`extractor "${extractor.id}" must claim at least one file glob`);
271
+ }
272
+ return extractor;
273
+ }
274
+ async function runExtractor(extractor, repo, options = {}) {
275
+ const out = { records: [], rejected: [], warnings: [] };
276
+ const ctx = {
277
+ dialects: options.dialects ?? [],
278
+ scannedAt: options.scannedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
279
+ warn: (message, path) => out.warnings.push(path ? { message, path } : { message })
280
+ };
281
+ const own = repo.parseCache ? void 0 : createParseCache();
282
+ const r = own ? withParseCache(repo, own) : repo;
283
+ try {
284
+ for await (const emitted of extractor.scan(r, ctx)) {
285
+ const result = parseRecord(emitted);
286
+ if (result.ok)
287
+ out.records.push(result.record);
288
+ else
289
+ out.rejected.push({ record: emitted, issues: result.issues });
290
+ }
291
+ } finally {
292
+ own?.dispose();
293
+ }
294
+ return out;
295
+ }
296
+ function memoryRepo(name, commit, files) {
297
+ const paths = Object.keys(files).sort();
298
+ return {
299
+ name,
300
+ commit,
301
+ async *listFiles(globs) {
302
+ const matchers = globs.map(globToRegExp);
303
+ for (const p of paths)
304
+ if (matchers.some((m) => m.test(p)))
305
+ yield p;
306
+ },
307
+ async readText(path) {
308
+ const text = files[path];
309
+ if (text === void 0)
310
+ throw new Error(`no such file: ${path}`);
311
+ return text;
312
+ }
313
+ };
314
+ }
315
+ function globToRegExp(glob) {
316
+ let re = "";
317
+ for (let i = 0; i < glob.length; i++) {
318
+ const c = glob[i];
319
+ if (c === "*") {
320
+ if (glob[i + 1] === "*") {
321
+ const slash = glob[i + 2] === "/";
322
+ re += slash ? "(?:.*/)?" : ".*";
323
+ i += slash ? 2 : 1;
324
+ } else
325
+ re += "[^/]*";
326
+ } else if (c === "?")
327
+ re += "[^/]";
328
+ else
329
+ re += c.replace(/[.+^${}()|[\]\\]/g, "\\$&");
330
+ }
331
+ return new RegExp(`^${re}$`);
332
+ }
333
+
334
+ // packages/sdk/dist/fs-repo.js
335
+ import { lstat, readdir, readFile, realpath, stat } from "node:fs/promises";
336
+ import { join, relative, resolve, sep } from "node:path";
337
+ var DEFAULT_IGNORES = [
338
+ ".git",
339
+ "node_modules",
340
+ "target",
341
+ "build",
342
+ "dist",
343
+ "out",
344
+ ".gradle",
345
+ ".idea",
346
+ ".vscode",
347
+ "__pycache__",
348
+ ".venv"
349
+ ];
350
+ function tooLargeMessage(bytes, maxBytes) {
351
+ const mb = maxBytes / 1024 / 1024;
352
+ return `left out: ${bytes} bytes is over the ${Number.isInteger(mb) ? `${mb} MB` : `${maxBytes} bytes`} a file may be`;
353
+ }
354
+ var RepoReadError = class extends Error {
355
+ path;
356
+ constructor(message, path) {
357
+ super(message);
358
+ this.path = path;
359
+ this.name = "RepoReadError";
360
+ }
361
+ };
362
+ function fsRepo(name, dir, commit, options = {}) {
363
+ const root = resolve(dir);
364
+ const ignore = new Set(options.ignore ?? DEFAULT_IGNORES);
365
+ const maxBytes = options.maxFileBytes ?? 5 * 1024 * 1024;
366
+ let cache;
367
+ const sizes = /* @__PURE__ */ new Map();
368
+ const skipped = /* @__PURE__ */ new Map();
369
+ async function walk(abs, out) {
370
+ const entries = await readdir(abs, { withFileTypes: true });
371
+ for (const e of entries) {
372
+ if (e.isSymbolicLink())
373
+ continue;
374
+ const full = join(abs, e.name);
375
+ if (e.isDirectory()) {
376
+ if (!ignore.has(e.name))
377
+ await walk(full, out);
378
+ } else if (e.isFile()) {
379
+ out.push(relative(root, full).split(sep).join("/"));
380
+ }
381
+ }
382
+ }
383
+ async function allFiles() {
384
+ if (!cache) {
385
+ const out = [];
386
+ await walk(root, out);
387
+ cache = out.sort();
388
+ }
389
+ return cache;
390
+ }
391
+ async function safePath(path) {
392
+ if (path.startsWith("/") || /^[A-Za-z]:/.test(path) || path.includes("\\") || path.split("/").includes("..")) {
393
+ throw new RepoReadError(`path must be repo-relative with forward slashes: ${path}`, path);
394
+ }
395
+ const abs = join(root, ...path.split("/"));
396
+ const info = await lstat(abs).catch(() => void 0);
397
+ if (!info || !info.isFile())
398
+ throw new RepoReadError(`no such file: ${path}`, path);
399
+ if (info.isSymbolicLink())
400
+ throw new RepoReadError(`symbolic links are not read: ${path}`, path);
401
+ const real = await realpath(abs);
402
+ const realRoot = await realpath(root);
403
+ if (real !== realRoot && !real.startsWith(realRoot + sep)) {
404
+ throw new RepoReadError(`path leaves the repo: ${path}`, path);
405
+ }
406
+ if (info.size > maxBytes)
407
+ throw new RepoReadError(`file is larger than ${maxBytes} bytes: ${path}`, path);
408
+ return abs;
409
+ }
410
+ return {
411
+ name,
412
+ commit,
413
+ async *listFiles(globs) {
414
+ const matchers = globs.map(globToRegExp);
415
+ for (const p of await allFiles()) {
416
+ if (!matchers.some((m) => m.test(p)))
417
+ continue;
418
+ if (!sizes.has(p))
419
+ sizes.set(p, (await stat(join(root, ...p.split("/"))).catch(() => void 0))?.size ?? 0);
420
+ const bytes = sizes.get(p);
421
+ if (bytes > maxBytes) {
422
+ skipped.set(p, bytes);
423
+ continue;
424
+ }
425
+ yield p;
426
+ }
427
+ },
428
+ maxFileBytes: maxBytes,
429
+ skippedFiles() {
430
+ return [...skipped].sort(([a], [b]) => a < b ? -1 : 1).map(([path, bytes]) => ({ path, bytes }));
431
+ },
432
+ async readText(path) {
433
+ const text = await readFile(await safePath(path), "utf8");
434
+ return text.charCodeAt(0) === 65279 ? text.slice(1) : text;
435
+ }
436
+ };
437
+ }
438
+
439
+ // packages/sdk/dist/cache.js
440
+ import { createHash as createHash2 } from "node:crypto";
441
+ import { mkdir, readdir as readdir2, readFile as readFile2, rename, rm, writeFile } from "node:fs/promises";
442
+ import { join as join2 } from "node:path";
443
+ var sha256 = (s) => createHash2("sha256").update(s).digest("hex");
444
+ function cacheKeyHash(key) {
445
+ return sha256(JSON.stringify([
446
+ key.repo,
447
+ key.commit,
448
+ key.extractor,
449
+ key.version,
450
+ [...key.dialects].sort(),
451
+ key.config ?? ""
452
+ ]));
453
+ }
454
+ function configHash(parts) {
455
+ const sorted = Object.keys(parts).sort().map((k) => [k, parts[k]]);
456
+ return sha256(JSON.stringify(sorted)).slice(0, 16);
457
+ }
458
+ function memoryScanCache() {
459
+ const map = /* @__PURE__ */ new Map();
460
+ return {
461
+ async get(key) {
462
+ const v = map.get(cacheKeyHash(key));
463
+ return v ? JSON.parse(v) : void 0;
464
+ },
465
+ async put(key, value) {
466
+ map.set(cacheKeyHash(key), JSON.stringify(value));
467
+ },
468
+ size: () => map.size
469
+ };
470
+ }
471
+ var SAFE = /^[A-Za-z0-9._@-]+$/;
472
+ function fsScanCache(dir) {
473
+ const fileFor = (key) => {
474
+ for (const part of [key.repo, key.commit, key.extractor, key.version]) {
475
+ if (!SAFE.test(part))
476
+ throw new Error(`unsafe cache key part: ${part}`);
477
+ }
478
+ const h = cacheKeyHash(key);
479
+ return {
480
+ h,
481
+ path: join2(dir, key.repo, key.commit, `${key.extractor}@${key.version}.${h.slice(0, 16)}.json`)
482
+ };
483
+ };
484
+ return {
485
+ async get(key) {
486
+ const { h, path } = fileFor(key);
487
+ let file;
488
+ try {
489
+ file = JSON.parse(await readFile2(path, "utf8"));
490
+ } catch {
491
+ return void 0;
492
+ }
493
+ if (file.format !== 1 || file.keyHash !== h)
494
+ return void 0;
495
+ if (sha256(JSON.stringify(file.value)) !== file.checksum)
496
+ return void 0;
497
+ const records = [];
498
+ for (const r of file.value.records) {
499
+ const parsed = parseRecord(r);
500
+ if (!parsed.ok)
501
+ return void 0;
502
+ records.push(parsed.record);
503
+ }
504
+ return { ...file.value, records };
505
+ },
506
+ async put(key, value) {
507
+ const { h, path } = fileFor(key);
508
+ const file = {
509
+ format: 1,
510
+ key,
511
+ keyHash: h,
512
+ checksum: sha256(JSON.stringify(value)),
513
+ value
514
+ };
515
+ await mkdir(join2(path, ".."), { recursive: true });
516
+ const tmp = `${path}.${process.pid}.${Date.now()}.tmp`;
517
+ await writeFile(tmp, JSON.stringify(file), "utf8");
518
+ await rename(tmp, path);
519
+ },
520
+ async prune(repo, keepCommits) {
521
+ if (!SAFE.test(repo))
522
+ throw new Error(`unsafe repo name: ${repo}`);
523
+ const keep = new Set(keepCommits);
524
+ let removed = 0;
525
+ let commits;
526
+ try {
527
+ commits = await readdir2(join2(dir, repo));
528
+ } catch {
529
+ return 0;
530
+ }
531
+ for (const c of commits) {
532
+ if (!keep.has(c)) {
533
+ await rm(join2(dir, repo, c), { recursive: true, force: true });
534
+ removed++;
535
+ }
536
+ }
537
+ return removed;
538
+ }
539
+ };
540
+ }
541
+
542
+ // packages/sdk/dist/runner.js
543
+ var EVIDENCE_FROM_REPO = /* @__PURE__ */ new Set([
544
+ "code",
545
+ "config",
546
+ "spec",
547
+ "gateway",
548
+ "event-config",
549
+ "infrastructure",
550
+ "pipeline",
551
+ "migration"
552
+ ]);
553
+ function stampEvidence(record, repo, extractor, scannedAt) {
554
+ if (record === null || typeof record !== "object")
555
+ return record;
556
+ const r = record;
557
+ if (!Array.isArray(r.evidence))
558
+ return record;
559
+ return {
560
+ ...r,
561
+ evidence: r.evidence.map((e) => {
562
+ if (e === null || typeof e !== "object")
563
+ return e;
564
+ const ev = { ...e };
565
+ if (typeof ev.source !== "string" || !EVIDENCE_FROM_REPO.has(ev.source))
566
+ return ev;
567
+ ev.repo ??= repo.name;
568
+ if (ev.repo === repo.name) {
569
+ ev.commit ??= repo.commit;
570
+ ev.scannedAt ??= scannedAt;
571
+ }
572
+ ev.extractor ??= extractor;
573
+ return ev;
574
+ })
575
+ };
576
+ }
577
+ async function hasClaimedFiles(repo, claims) {
578
+ for await (const _ of repo.listFiles(claims))
579
+ return true;
580
+ return false;
581
+ }
582
+ function compareRecords(a, b) {
583
+ const ka = `${a.r.kind}\0${a.r.id}\0${a.x}`;
584
+ const kb = `${b.r.kind}\0${b.r.id}\0${b.x}`;
585
+ return ka < kb ? -1 : ka > kb ? 1 : 0;
586
+ }
587
+ async function scanRepo(options) {
588
+ const own = options.repo.parseCache ? void 0 : createParseCache();
589
+ try {
590
+ return await scanWith(own ? { ...options, repo: withParseCache(options.repo, own) } : options);
591
+ } finally {
592
+ own?.dispose();
593
+ }
594
+ }
595
+ async function scanWith(options) {
596
+ const { repo } = options;
597
+ const dialects = [...options.dialects ?? []].sort();
598
+ const scannedAt = options.scannedAt ?? (/* @__PURE__ */ new Date()).toISOString();
599
+ const useCache = options.cache !== void 0 && !options.dirty;
600
+ const seenIds = /* @__PURE__ */ new Set();
601
+ for (const x of options.extractors) {
602
+ if (seenIds.has(x.id))
603
+ throw new Error(`extractor ${x.id} is registered twice`);
604
+ seenIds.add(x.id);
605
+ }
606
+ const out = {
607
+ repo: repo.name,
608
+ commit: repo.commit,
609
+ scannedAt,
610
+ records: [],
611
+ runs: [],
612
+ warnings: [],
613
+ rejected: []
614
+ };
615
+ const collected = [];
616
+ for (const extractor of [...options.extractors].sort((a, b) => a.id.localeCompare(b.id))) {
617
+ const tag = `${extractor.id}@${extractor.version}`;
618
+ const started = Date.now();
619
+ const run = {
620
+ extractor: extractor.id,
621
+ version: extractor.version,
622
+ status: "ran",
623
+ records: 0,
624
+ rejected: 0,
625
+ warnings: 0,
626
+ durationMs: 0
627
+ };
628
+ const key = {
629
+ repo: repo.name,
630
+ commit: repo.commit,
631
+ extractor: extractor.id,
632
+ version: extractor.version,
633
+ dialects,
634
+ config: [
635
+ options.configFor?.(extractor) ?? "",
636
+ JSON.stringify(options.repoInfo ?? {}),
637
+ // A changed framework model means a different reading of the same code.
638
+ options.frameworks?.length ? JSON.stringify(options.frameworks) : ""
639
+ ].join("|")
640
+ };
641
+ try {
642
+ const hit = useCache ? await options.cache.get(key) : void 0;
643
+ if (hit) {
644
+ run.status = "cached";
645
+ run.records = hit.records.length;
646
+ run.rejected = hit.rejected;
647
+ run.warnings = hit.warnings.length;
648
+ for (const r of hit.records)
649
+ collected.push({ r, x: extractor.id });
650
+ for (const w of hit.warnings)
651
+ out.warnings.push({ extractor: extractor.id, ...w });
652
+ } else if (!await hasClaimedFiles(repo, extractor.claims)) {
653
+ run.status = "skipped";
654
+ } else {
655
+ const records = [];
656
+ const warnings = [];
657
+ const ids = /* @__PURE__ */ new Set();
658
+ let rejected = 0;
659
+ const info = options.repoInfo ?? {};
660
+ const ctx = {
661
+ dialects,
662
+ ...info.component ? { component: info.component } : {},
663
+ ...info.system ? { system: info.system } : {},
664
+ ...info.repoType ? { repoType: info.repoType } : {},
665
+ ...info.modules?.length ? { modules: info.modules } : {},
666
+ ...options.frameworks?.length ? { frameworks: options.frameworks } : {},
667
+ scannedAt,
668
+ warn: (message, path) => warnings.push(path === void 0 ? { message } : { message, path })
669
+ };
670
+ const claimed = extractor.claims.map(globToRegExp);
671
+ const skippedNow = () => repo.skippedFiles?.().filter((f) => claimed.some((m) => m.test(f.path))) ?? [];
672
+ for await (const emitted of extractor.scan(repo, ctx)) {
673
+ const parsed = parseRecord(stampEvidence(emitted, repo, tag, scannedAt));
674
+ if (!parsed.ok) {
675
+ rejected++;
676
+ out.rejected.push({ extractor: extractor.id, record: emitted, issues: parsed.issues });
677
+ continue;
678
+ }
679
+ const id = `${parsed.record.kind}/${parsed.record.id}`;
680
+ if (ids.has(id)) {
681
+ warnings.push({ message: `emitted ${id} more than once; kept the first` });
682
+ continue;
683
+ }
684
+ ids.add(id);
685
+ records.push(parsed.record);
686
+ }
687
+ for (const f of skippedNow())
688
+ warnings.push({
689
+ message: tooLargeMessage(f.bytes, repo.maxFileBytes),
690
+ path: f.path
691
+ });
692
+ run.records = records.length;
693
+ run.rejected = rejected;
694
+ run.warnings = warnings.length;
695
+ for (const r of records)
696
+ collected.push({ r, x: extractor.id });
697
+ for (const w of warnings)
698
+ out.warnings.push({ extractor: extractor.id, ...w });
699
+ if (useCache)
700
+ await options.cache.put(key, { records, warnings, rejected });
701
+ }
702
+ } catch (err) {
703
+ run.status = "failed";
704
+ run.error = err instanceof Error ? err.message : String(err);
705
+ for (let i = collected.length - 1; i >= 0; i--)
706
+ if (collected[i].x === extractor.id)
707
+ collected.splice(i, 1);
708
+ for (let i = out.warnings.length - 1; i >= 0; i--)
709
+ if (out.warnings[i].extractor === extractor.id)
710
+ out.warnings.splice(i, 1);
711
+ for (let i = out.rejected.length - 1; i >= 0; i--)
712
+ if (out.rejected[i].extractor === extractor.id)
713
+ out.rejected.splice(i, 1);
714
+ run.rejected = 0;
715
+ run.warnings = 0;
716
+ run.records = 0;
717
+ }
718
+ run.durationMs = Date.now() - started;
719
+ out.runs.push(run);
720
+ }
721
+ out.records = collected.sort(compareRecords).map((c) => c.r);
722
+ return out;
723
+ }
724
+
725
+ // packages/sdk/dist/sandbox.js
726
+ import { createHash as createHash3 } from "node:crypto";
727
+ import { readFile as readFile3 } from "node:fs/promises";
728
+ import { join as join3 } from "node:path";
729
+ import { Worker } from "node:worker_threads";
730
+ var PLUGIN_EXTRACTOR_PREFIX = "plugin-";
731
+ var MAX_RECORDS = 1e5;
732
+ function pluginEntryHash(text) {
733
+ return createHash3("sha256").update(text.replace(/\r\n/g, "\n"), "utf8").digest("hex");
734
+ }
735
+ async function readPinnedEntry(dir, manifest) {
736
+ if (!manifest.sha256)
737
+ return { ok: false, message: "isn't pinned: run atticus plugin pin once it is reviewed" };
738
+ let source;
739
+ try {
740
+ source = await readFile3(join3(dir, ...manifest.entry.split("/")), "utf8");
741
+ } catch (e) {
742
+ return { ok: false, message: `can't read ${manifest.entry}: ${e.message}` };
743
+ }
744
+ if (pluginEntryHash(source) !== manifest.sha256)
745
+ return {
746
+ ok: false,
747
+ message: `${manifest.entry} changed after it was pinned: its sha256 isn't the one in plugin.yaml. Review the change, then run atticus plugin pin`
748
+ };
749
+ return { ok: true, source };
750
+ }
751
+ var PluginRunError = class extends Error {
752
+ reason;
753
+ constructor(message, reason) {
754
+ super(message);
755
+ this.reason = reason;
756
+ this.name = "PluginRunError";
757
+ }
758
+ };
759
+ function insideRepo(p) {
760
+ return p.length > 0 && !p.startsWith("/") && !/^[A-Za-z]:/.test(p) && !p.includes("\\") && !p.includes("\0") && !p.split("/").includes("..");
761
+ }
762
+ var HARDEN = String.raw` "use strict";
763
+ const g = globalThis;
764
+ const send = host;
765
+ const blocked = (what) => {
766
+ send("violation", 0, String(what));
767
+ return new Error("blocked: " + what + " is not allowed in a scanner plugin");
768
+ };
769
+ // Code from strings: the constructors every function reaches, and eval.
770
+ const compileStub = function () { throw blocked("compile code from a string (eval or Function)"); };
771
+ for (const f of [function () {}, async function () {}, function* () {}, async function* () {}])
772
+ Object.defineProperty(Object.getPrototypeOf(f), "constructor", { value: compileStub });
773
+ Object.defineProperty(g, "Function", { value: compileStub });
774
+ Object.defineProperty(g, "eval", { value: compileStub });
775
+ // Node's way out of the sandbox, if it were there: reported when touched.
776
+ for (const name of ["require", "process", "module", "exports", "Buffer", "fetch", "XMLHttpRequest",
777
+ "WebSocket", "setTimeout", "setInterval", "setImmediate", "queueMicrotask", "WebAssembly",
778
+ "SharedArrayBuffer", "Atomics"]) {
779
+ Object.defineProperty(g, name, { get() { throw blocked("use " + name); }, configurable: false });
780
+ }
781
+ // The same commit must read the same (ADR 0074): no clock, no randomness.
782
+ Object.defineProperty(g, "Date", { get() { throw blocked("use Date (the scan's time is ctx.scannedAt)"); }, configurable: false });
783
+ Object.defineProperty(Math, "random", { value: function () { throw blocked("use Math.random"); } });
784
+ const noop = () => undefined;
785
+ Object.defineProperty(g, "console", { value: Object.freeze({ log: noop, info: noop, warn: noop, error: noop, debug: noop }) });
786
+ // Freeze what the plugin and this bootstrap share, so neither can be changed under the other.
787
+ const seen = new Set();
788
+ const freeze = (o) => {
789
+ if ((typeof o !== "object" && typeof o !== "function") || o === null || seen.has(o)) return;
790
+ seen.add(o);
791
+ Object.freeze(o);
792
+ for (const k of Reflect.ownKeys(o)) {
793
+ const d = Object.getOwnPropertyDescriptor(o, k);
794
+ if (d && "value" in d) freeze(d.value);
795
+ }
796
+ freeze(Object.getPrototypeOf(o));
797
+ };
798
+ for (const k of Reflect.ownKeys(g)) {
799
+ const d = Object.getOwnPropertyDescriptor(g, k);
800
+ if (d && "value" in d) freeze(d.value);
801
+ }
802
+ for (const f of [function () {}, async function () {}, function* () {}, async function* () {}])
803
+ freeze(Object.getPrototypeOf(f));
804
+ for (const f of [function* () {}, async function* () {}]) freeze(Object.getPrototypeOf(f()));
805
+ freeze(Object.getPrototypeOf([][Symbol.iterator]()));
806
+ freeze(Object.getPrototypeOf(new Map()[Symbol.iterator]()));
807
+ freeze(Object.getPrototypeOf(new Set()[Symbol.iterator]()));
808
+ freeze(Object.getPrototypeOf(""[Symbol.iterator]()));
809
+ freeze(Object.getPrototypeOf(/x/[Symbol.matchAll]("")));
810
+ Object.freeze(g);
811
+
812
+ const parse = JSON.parse;
813
+ const stringify = JSON.stringify;
814
+ const pending = new Map();
815
+ let next = 0;
816
+ const ask = (op, arg) =>
817
+ new Promise((resolve, reject) => {
818
+ const id = ++next;
819
+ pending.set(id, { resolve, reject });
820
+ send(op, id, arg);
821
+ });
822
+ function answer(id, ok, text) {
823
+ const p = pending.get(id);
824
+ if (!p) return;
825
+ pending.delete(id);
826
+ if (ok) p.resolve(parse(text));
827
+ else p.reject(new Error(text));
828
+ }
829
+ `;
830
+ var EXTRACTOR_DRIVER = String.raw` async function drive(x, input) {
831
+ const data = parse(input);
832
+ if (!x || typeof x !== "object" || typeof x.scan !== "function")
833
+ throw new Error("the entry file's default export isn't an extractor (id, version, claims, scan)");
834
+ send("meta", 0, stringify({ id: String(x.id), version: String(x.version) }));
835
+ const repo = Object.freeze({
836
+ name: data.repo.name,
837
+ commit: data.repo.commit,
838
+ listFiles: async function* (globs) {
839
+ const list = await ask("list", stringify(Array.from(globs, (s) => String(s))));
840
+ for (const p of list) yield p;
841
+ },
842
+ readText: (path) => ask("read", String(path)),
843
+ });
844
+ const ctx = Object.freeze({
845
+ ...data.ctx,
846
+ warn: (message, path) =>
847
+ send("warn", 0, stringify(path === undefined ? { message: String(message) } : { message: String(message), path: String(path) })),
848
+ });
849
+ for await (const r of x.scan(repo, ctx)) send("record", 0, stringify(r));
850
+ }
851
+ function run(x, input) {
852
+ drive(x, input).then(
853
+ () => send("done", 0, ""),
854
+ (e) => send("error", 0, String(e && e.message !== undefined ? e.message : e)),
855
+ );
856
+ }
857
+ `;
858
+ var TRANSLATOR_DRIVER = String.raw` function run(x, input) {
859
+ Promise.resolve()
860
+ .then(() => {
861
+ const data = parse(input);
862
+ if (!x || typeof x !== "object") throw new Error("the entry file has no default export");
863
+ send("meta", 0, stringify({ id: String(x.id), version: String(x.version) }));
864
+ if (typeof x[data.fn] !== "function")
865
+ throw new Error("the entry file's default export has no " + data.fn + " function");
866
+ return x[data.fn](data.arg);
867
+ })
868
+ .then(
869
+ (r) => send("result", 0, stringify(r === undefined ? null : r)),
870
+ (e) => send("error", 0, String(e && e.message !== undefined ? e.message : e)),
871
+ );
872
+ }
873
+ `;
874
+ var bootstrapWith = (driver) => `(function (host) {
875
+ ${HARDEN}${driver} return Object.freeze({ answer, run });
876
+ })`;
877
+ var BOOTSTRAP = bootstrapWith(EXTRACTOR_DRIVER);
878
+ var TRANSLATOR_BOOTSTRAP = bootstrapWith(TRANSLATOR_DRIVER);
879
+ var WORKER = String.raw`"use strict";
880
+ const vm = require("node:vm");
881
+ const { parentPort, workerData } = require("node:worker_threads");
882
+ const { source, identifier, input, bootstrap } = workerData;
883
+ const post = (m) => parentPort.postMessage(m);
884
+ const context = vm.createContext(
885
+ vm.constants && vm.constants.DONT_CONTEXTIFY !== undefined ? vm.constants.DONT_CONTEXTIFY : {},
886
+ { name: identifier, codeGeneration: { strings: false, wasm: false } },
887
+ );
888
+ // Errors thrown into plugin code are made in its context, never the worker's.
889
+ const makeError = vm.runInContext("(m) => new Error(m)", context);
890
+ let bridge;
891
+ const host = (op, id, arg) => {
892
+ try {
893
+ if (typeof op !== "string" || typeof id !== "number" || typeof arg !== "string") return;
894
+ post({ t: op, id, arg });
895
+ } catch {
896
+ // Never throw a worker error into the plugin's context.
897
+ }
898
+ };
899
+ parentPort.on("message", (m) => {
900
+ if (m && m.t === "answer") bridge.answer(m.id, m.ok, m.text);
901
+ });
902
+ (async () => {
903
+ try {
904
+ bridge = vm.runInContext(bootstrap, context)(host);
905
+ const refuse = (spec) => {
906
+ post({ t: "violation", id: 0, arg: "import " + String(spec) });
907
+ throw makeError("blocked: import " + String(spec) + " is not allowed in a scanner plugin");
908
+ };
909
+ const mod = new vm.SourceTextModule(source, {
910
+ context,
911
+ identifier,
912
+ importModuleDynamically: (spec) => refuse(spec),
913
+ });
914
+ await mod.link((spec) => refuse(spec));
915
+ await mod.evaluate();
916
+ bridge.run(mod.namespace.default, input);
917
+ } catch (e) {
918
+ post({ t: "error", id: 0, arg: String(e && e.message !== undefined ? e.message : e) });
919
+ }
920
+ })();
921
+ `;
922
+ function contextData(ctx) {
923
+ return {
924
+ dialects: [...ctx.dialects],
925
+ scannedAt: ctx.scannedAt,
926
+ ...ctx.component !== void 0 ? { component: ctx.component } : {},
927
+ ...ctx.system !== void 0 ? { system: ctx.system } : {},
928
+ ...ctx.repoType !== void 0 ? { repoType: ctx.repoType } : {},
929
+ ...ctx.modules ? { modules: ctx.modules } : {},
930
+ ...ctx.frameworks ? { frameworks: ctx.frameworks } : {}
931
+ };
932
+ }
933
+ function spawnSandbox(o) {
934
+ const memoryMb = o.limits.memoryMb;
935
+ return new Worker(WORKER, {
936
+ eval: true,
937
+ workerData: {
938
+ source: o.source,
939
+ identifier: `plugin:${o.id}/${o.entry ?? "index.js"}`,
940
+ input: o.input,
941
+ bootstrap: o.bootstrap
942
+ },
943
+ execArgv: ["--experimental-vm-modules", "--no-warnings"],
944
+ argv: [],
945
+ env: {},
946
+ stdout: true,
947
+ stderr: true,
948
+ stdin: false,
949
+ trackUnmanagedFds: true,
950
+ resourceLimits: {
951
+ maxOldGenerationSizeMb: memoryMb,
952
+ maxYoungGenerationSizeMb: Math.max(4, Math.min(16, Math.floor(memoryMb / 4))),
953
+ codeRangeSizeMb: 16,
954
+ stackSizeMb: 4
955
+ },
956
+ name: `atticus-plugin-${o.id}`
957
+ });
958
+ }
959
+ function runInWorker(p, repo, ctx) {
960
+ const records = [];
961
+ const emits = new Set(p.emits);
962
+ const memoryMb = p.limits.memoryMb;
963
+ return new Promise((resolve2, reject) => {
964
+ let settled = false;
965
+ const worker = spawnSandbox({
966
+ ...p,
967
+ input: JSON.stringify({
968
+ repo: { name: repo.name, commit: repo.commit },
969
+ ctx: contextData(ctx)
970
+ }),
971
+ bootstrap: BOOTSTRAP
972
+ });
973
+ worker.stdout.resume();
974
+ worker.stderr.resume();
975
+ const finish = (err) => {
976
+ if (settled)
977
+ return;
978
+ settled = true;
979
+ clearTimeout(timer);
980
+ void worker.terminate();
981
+ if (err)
982
+ reject(err);
983
+ else
984
+ resolve2(records);
985
+ };
986
+ const timer = setTimeout(() => finish(new PluginRunError(`stopped after ${p.limits.timeoutMs} ms, its time limit`, "timeout")), p.limits.timeoutMs);
987
+ const outside = (what, path) => finish(new PluginRunError(`blocked: tried to ${what} ${JSON.stringify(path)}, which is outside the repo`, "blocked"));
988
+ const answer = (id, ok, text) => {
989
+ if (!settled)
990
+ worker.postMessage({ t: "answer", id, ok, text });
991
+ };
992
+ worker.on("message", (m) => {
993
+ if (settled)
994
+ return;
995
+ void (async () => {
996
+ switch (m.t) {
997
+ case "list": {
998
+ const globs = JSON.parse(m.arg);
999
+ const bad = globs.find((g) => typeof g !== "string" || !insideRepo(g));
1000
+ if (bad !== void 0)
1001
+ return outside("list", String(bad));
1002
+ try {
1003
+ const out = [];
1004
+ for await (const f of repo.listFiles(globs))
1005
+ out.push(f);
1006
+ answer(m.id, true, JSON.stringify(out));
1007
+ } catch (e) {
1008
+ answer(m.id, false, e.message);
1009
+ }
1010
+ return;
1011
+ }
1012
+ case "read": {
1013
+ if (!insideRepo(m.arg))
1014
+ return outside("read", m.arg);
1015
+ try {
1016
+ answer(m.id, true, JSON.stringify(await repo.readText(m.arg)));
1017
+ } catch (e) {
1018
+ answer(m.id, false, e.message);
1019
+ }
1020
+ return;
1021
+ }
1022
+ case "meta": {
1023
+ const meta = JSON.parse(m.arg);
1024
+ if (meta.id !== p.id || meta.version !== p.version)
1025
+ finish(new PluginRunError(`the entry file exports ${meta.id} ${meta.version}, but its manifest says ${p.id} ${p.version}`, "invalid"));
1026
+ return;
1027
+ }
1028
+ case "record": {
1029
+ const r = JSON.parse(m.arg);
1030
+ if (!emits.has(String(r?.kind)))
1031
+ return finish(new PluginRunError(`emitted a ${String(r?.kind)} record; its manifest allows ${[...emits].join(", ")}`, "invalid"));
1032
+ if (records.length >= MAX_RECORDS)
1033
+ return finish(new PluginRunError(`emitted more than ${MAX_RECORDS} records`, "invalid"));
1034
+ records.push(r);
1035
+ return;
1036
+ }
1037
+ case "warn": {
1038
+ const w = JSON.parse(m.arg);
1039
+ ctx.warn(w.message, w.path);
1040
+ return;
1041
+ }
1042
+ case "violation":
1043
+ return finish(new PluginRunError(`blocked: tried to ${m.arg}`, "blocked"));
1044
+ case "error":
1045
+ return finish(new PluginRunError(`failed: ${m.arg}`, "failed"));
1046
+ case "done":
1047
+ return finish();
1048
+ }
1049
+ })().catch((e) => finish(new PluginRunError(`failed: ${e.message}`, "failed")));
1050
+ });
1051
+ worker.on("error", (e) => finish(e.code === "ERR_WORKER_OUT_OF_MEMORY" ? new PluginRunError(`stopped: it used more than its ${memoryMb} MB memory limit`, "memory") : new PluginRunError(`failed: ${e.message}`, "failed")));
1052
+ worker.on("exit", (code) => finish(new PluginRunError(`stopped before it finished (exit code ${code})`, "failed")));
1053
+ });
1054
+ }
1055
+ var MAX_RESULT_CHARS = 32 * 1024 * 1024;
1056
+ function runTranslator(p, fn, arg) {
1057
+ return new Promise((resolve2, reject) => {
1058
+ let settled = false;
1059
+ const worker = spawnSandbox({
1060
+ ...p,
1061
+ input: JSON.stringify({ fn, arg: arg ?? null }),
1062
+ bootstrap: TRANSLATOR_BOOTSTRAP
1063
+ });
1064
+ worker.stdout.resume();
1065
+ worker.stderr.resume();
1066
+ const finish = (err, value) => {
1067
+ if (settled)
1068
+ return;
1069
+ settled = true;
1070
+ clearTimeout(timer);
1071
+ void worker.terminate();
1072
+ if (err)
1073
+ reject(err);
1074
+ else
1075
+ resolve2(value);
1076
+ };
1077
+ const timer = setTimeout(() => finish(new PluginRunError(`stopped after ${p.limits.timeoutMs} ms, its time limit`, "timeout")), p.limits.timeoutMs);
1078
+ worker.on("message", (m) => {
1079
+ if (settled)
1080
+ return;
1081
+ switch (m.t) {
1082
+ case "meta": {
1083
+ const meta = JSON.parse(m.arg);
1084
+ if (meta.id !== p.id || meta.version !== p.version)
1085
+ finish(new PluginRunError(`the entry file exports ${meta.id} ${meta.version}, but its manifest says ${p.id} ${p.version}`, "invalid"));
1086
+ return;
1087
+ }
1088
+ case "result":
1089
+ if (m.arg.length > MAX_RESULT_CHARS)
1090
+ return finish(new PluginRunError("gave back more than 32 MB", "invalid"));
1091
+ return finish(void 0, JSON.parse(m.arg));
1092
+ case "violation":
1093
+ return finish(new PluginRunError(`blocked: tried to ${m.arg}`, "blocked"));
1094
+ case "error":
1095
+ return finish(new PluginRunError(`failed: ${m.arg}`, "failed"));
1096
+ default:
1097
+ return finish(new PluginRunError(`blocked: tried to ${m.t}`, "blocked"));
1098
+ }
1099
+ });
1100
+ worker.on("error", (e) => finish(e.code === "ERR_WORKER_OUT_OF_MEMORY" ? new PluginRunError(`stopped: it used more than its ${p.limits.memoryMb} MB memory limit`, "memory") : new PluginRunError(`failed: ${e.message}`, "failed")));
1101
+ worker.on("exit", (code) => finish(new PluginRunError(`stopped before it finished (exit code ${code})`, "failed")));
1102
+ });
1103
+ }
1104
+ function sandboxedExtractor(p) {
1105
+ return {
1106
+ id: `${PLUGIN_EXTRACTOR_PREFIX}${p.id}`,
1107
+ version: p.version,
1108
+ // What the plugin reads is up to it, through the handle: the run is never skipped.
1109
+ claims: ["**/*"],
1110
+ async *scan(repo, ctx) {
1111
+ for (const r of await runInWorker(p, repo, ctx))
1112
+ yield r;
1113
+ }
1114
+ };
1115
+ }
1116
+
1117
+ export {
1118
+ DEFAULT_PARSE_CACHE_LIMITS,
1119
+ deepFreeze,
1120
+ createParseCache,
1121
+ withParseCache,
1122
+ defineExtractor,
1123
+ runExtractor,
1124
+ memoryRepo,
1125
+ globToRegExp,
1126
+ DEFAULT_IGNORES,
1127
+ tooLargeMessage,
1128
+ RepoReadError,
1129
+ fsRepo,
1130
+ cacheKeyHash,
1131
+ configHash,
1132
+ memoryScanCache,
1133
+ fsScanCache,
1134
+ stampEvidence,
1135
+ scanRepo,
1136
+ PLUGIN_EXTRACTOR_PREFIX,
1137
+ pluginEntryHash,
1138
+ readPinnedEntry,
1139
+ PluginRunError,
1140
+ runTranslator,
1141
+ sandboxedExtractor
1142
+ };