@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,2902 @@
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
+ parseXml
8
+ } from "./chunk-MC3H7736.js";
9
+ import {
10
+ ZipError,
11
+ peekZip,
12
+ readZip,
13
+ require_dist
14
+ } from "./chunk-S2A7YC3Q.js";
15
+ import {
16
+ __toESM
17
+ } from "./chunk-TV45EUGM.js";
18
+
19
+ // packages/ingestors/dist/labels.js
20
+ var DEFAULT_LEGEND = { new: ["New"], modify: ["Modify"], retire: ["Retire"] };
21
+ var METHODS = /* @__PURE__ */ new Set(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]);
22
+ var PATTERN = /^[A-Z][A-Z0-9]*(\.[A-Z0-9]+)+$/;
23
+ var KINDS = ["new", "modify", "retire"];
24
+ var escape = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
25
+ function edgeParts(text) {
26
+ const toks = text.split(" ").filter(Boolean);
27
+ const out = {};
28
+ if (toks[0] && PATTERN.test(toks[0]))
29
+ out.pattern = toks.shift();
30
+ if (toks[0] && METHODS.has(toks[0].toUpperCase()) && toks[1]) {
31
+ out.method = toks[0].toUpperCase();
32
+ out.path = toks[1];
33
+ } else if (toks.length === 1 && /^[A-Za-z0-9][\w.-]*$/.test(toks[0]))
34
+ out.topic = toks[0];
35
+ return out;
36
+ }
37
+ function legendWord(value, words2) {
38
+ const v = value?.trim().toLowerCase();
39
+ if (!v)
40
+ return void 0;
41
+ for (const k of KINDS)
42
+ if (v === k || words2[k].some((w) => w.toLowerCase() === v))
43
+ return k;
44
+ return void 0;
45
+ }
46
+ function legendOf(given, text, words2) {
47
+ let legend = given;
48
+ let rest = text;
49
+ for (const k of KINDS) {
50
+ for (const w of words2[k]) {
51
+ const re = new RegExp(`\\s*[[(]\\s*${escape(w)}\\s*[\\])]\\s*`, "i");
52
+ if (re.test(rest)) {
53
+ legend ??= k;
54
+ rest = rest.replace(re, " ").trim();
55
+ }
56
+ }
57
+ }
58
+ return { ...legend ? { legend } : {}, text: rest };
59
+ }
60
+ var squash = (s) => s.replace(/\s+/g, " ").trim();
61
+
62
+ // packages/ingestors/dist/record.js
63
+ import { createHash } from "node:crypto";
64
+ var slug = (s) => s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
65
+ var fileBase = (fileName) => fileName.split(/[\\/]/).pop() ?? fileName;
66
+ function extOf(fileName) {
67
+ const base = fileBase(fileName);
68
+ const dot = base.lastIndexOf(".");
69
+ return dot > 0 ? base.slice(dot).toLowerCase() : "";
70
+ }
71
+ var DOUBLE = /\.(drawio\.xml|lucid\.csv|figma\.json)$/i;
72
+ function stem(fileName) {
73
+ const base = fileBase(fileName);
74
+ if (DOUBLE.test(base))
75
+ return base.replace(DOUBLE, "");
76
+ const dot = base.lastIndexOf(".");
77
+ return dot > 0 ? base.slice(0, dot) : base;
78
+ }
79
+ function documentId(fileName) {
80
+ const s = slug(stem(fileName)).slice(0, 110);
81
+ return `doc.${s || "file"}`;
82
+ }
83
+ function isoDate(value) {
84
+ if (value instanceof Date && !Number.isNaN(value.getTime()))
85
+ return value.toISOString().slice(0, 10);
86
+ if (typeof value !== "string")
87
+ return void 0;
88
+ const m = /^(\d{4})-(\d{2})-(\d{2})/.exec(value.trim());
89
+ if (!m)
90
+ return void 0;
91
+ const d = /* @__PURE__ */ new Date(`${m[1]}-${m[2]}-${m[3]}T00:00:00Z`);
92
+ return !Number.isNaN(d.getTime()) && d.toISOString().startsWith(m[0]) ? m[0] : void 0;
93
+ }
94
+ function sourceDocument(fileName, content, docType, source, meta = {}) {
95
+ const clean = (s) => s && s.trim() ? s.trim() : void 0;
96
+ const version = clean(meta.version);
97
+ const author = clean(meta.author);
98
+ return {
99
+ schemaVersion: 1,
100
+ kind: "SourceDocument",
101
+ id: documentId(fileName),
102
+ status: "current",
103
+ confidence: "verified",
104
+ ...meta.flags?.length ? { flags: meta.flags } : {},
105
+ path: fileName,
106
+ docType,
107
+ ...version ? { version } : {},
108
+ ...author ? { author } : {},
109
+ ...meta.date ? { date: meta.date } : {},
110
+ hash: createHash("sha256").update(content).digest("hex"),
111
+ recordsProduced: [],
112
+ evidence: [{ source, path: fileName }]
113
+ };
114
+ }
115
+ var utf8 = (b) => {
116
+ const s = new TextDecoder("utf-8").decode(b);
117
+ return s.charCodeAt(0) === 65279 ? s.slice(1) : s;
118
+ };
119
+
120
+ // packages/reconcile/dist/aliases.js
121
+ var slug2 = (s) => s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
122
+ var words = (s) => new Set(slug2(s).split("-").filter((w) => w.length > 1));
123
+ function curatedAliases(records) {
124
+ const out = /* @__PURE__ */ new Map();
125
+ for (const r of records) {
126
+ if (r.kind !== "CuratedDecision" || r.action !== "alias")
127
+ continue;
128
+ const names = Array.isArray(r.value) ? r.value : [r.value];
129
+ for (const n of names)
130
+ if (typeof n === "string")
131
+ out.set(n.toLowerCase(), r.target);
132
+ }
133
+ return out;
134
+ }
135
+ function resolveNames(names, records, systems) {
136
+ const curated = curatedAliases(records);
137
+ const components = records.filter((r) => r.kind === "Component");
138
+ const ids = /* @__PURE__ */ new Set([
139
+ ...components.map((c) => c.id),
140
+ ...records.filter((r) => r.kind === "System").map((r) => r.id),
141
+ ...systems.map((s) => s.id)
142
+ ]);
143
+ const componentsOf = (sys) => components.filter((c) => c.system === sys).map((c) => c.id);
144
+ const profileName = /* @__PURE__ */ new Map();
145
+ for (const s of systems)
146
+ for (const n of [s.name, ...s.aliases])
147
+ profileName.set(n.toLowerCase(), s.id);
148
+ const out = /* @__PURE__ */ new Map();
149
+ for (const name of names) {
150
+ if (out.has(name))
151
+ continue;
152
+ const key = name.toLowerCase();
153
+ const c = curated.get(key);
154
+ if (c) {
155
+ out.set(name, { name, id: c, how: "curated", similar: [] });
156
+ continue;
157
+ }
158
+ if (ids.has(slug2(name))) {
159
+ out.set(name, { name, id: slug2(name), how: "exact", similar: [] });
160
+ continue;
161
+ }
162
+ const sys = profileName.get(key);
163
+ if (sys) {
164
+ const comps = componentsOf(sys);
165
+ out.set(name, {
166
+ name,
167
+ id: comps.length === 1 ? comps[0] : sys,
168
+ how: "profile",
169
+ similar: []
170
+ });
171
+ continue;
172
+ }
173
+ const w = words(name);
174
+ const similar = [...ids].map((id) => ({ id, score: [...words(id)].filter((x) => w.has(x)).length })).filter((x) => x.score > 0).sort((a, b) => b.score - a.score || (a.id < b.id ? -1 : 1)).slice(0, 3).map((x) => x.id);
175
+ out.set(name, { name, similar });
176
+ }
177
+ return out;
178
+ }
179
+
180
+ // packages/reconcile/dist/drawio.js
181
+ import { createHash as createHash2 } from "node:crypto";
182
+ import { inflateRawSync } from "node:zlib";
183
+ var DEFAULT_LEGEND2 = { new: ["New"], modify: ["Modify"], retire: ["Retire"] };
184
+ var METHODS2 = /* @__PURE__ */ new Set(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]);
185
+ var PATTERN2 = /^[A-Z][A-Z0-9]*(\.[A-Z0-9]+)+$/;
186
+ var ENTITIES = {
187
+ nbsp: " ",
188
+ amp: "&",
189
+ lt: "<",
190
+ gt: ">",
191
+ quot: '"',
192
+ apos: "'"
193
+ };
194
+ function labelText(value) {
195
+ return value.replace(/<br\s*\/?>/gi, " ").replace(/<[^>]+>/g, " ").replace(/&(#\d+|#x[0-9a-f]+|[a-z]+);/gi, (m, e) => {
196
+ if (e.startsWith("#x"))
197
+ return String.fromCodePoint(parseInt(e.slice(2), 16));
198
+ if (e.startsWith("#"))
199
+ return String.fromCodePoint(parseInt(e.slice(1), 10));
200
+ return ENTITIES[e.toLowerCase()] ?? m;
201
+ }).replace(/\s+/g, " ").trim();
202
+ }
203
+ function parseStyle(style) {
204
+ const out = {};
205
+ for (const part of (style ?? "").split(";")) {
206
+ if (!part)
207
+ continue;
208
+ const eq = part.indexOf("=");
209
+ if (eq < 0)
210
+ out[part] = "1";
211
+ else
212
+ out[part.slice(0, eq)] = part.slice(eq + 1);
213
+ }
214
+ return out;
215
+ }
216
+ function legendOf2(style, text, words2) {
217
+ const fromStyle = style.legend?.toLowerCase();
218
+ let legend = fromStyle === "new" || fromStyle === "modify" || fromStyle === "retire" ? fromStyle : void 0;
219
+ let rest = text;
220
+ for (const k of ["new", "modify", "retire"]) {
221
+ for (const w of words2[k]) {
222
+ const re = new RegExp(`\\s*[[(]\\s*${w.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\s*[\\])]\\s*`, "i");
223
+ if (re.test(rest)) {
224
+ legend ??= k;
225
+ rest = rest.replace(re, " ").trim();
226
+ }
227
+ }
228
+ }
229
+ return { ...legend ? { legend } : {}, text: rest };
230
+ }
231
+ function pages(doc) {
232
+ if (doc.name === "mxGraphModel")
233
+ return [{ name: "", model: doc }];
234
+ if (doc.name !== "mxfile")
235
+ return [];
236
+ const out = [];
237
+ for (const d of doc.children.filter((c) => c.name === "diagram")) {
238
+ const name = d.attrs.name ?? d.attrs.id ?? "";
239
+ let model = d.children.find((c) => c.name === "mxGraphModel");
240
+ if (!model && d.text.trim()) {
241
+ const xml = decodeURIComponent(inflateRawSync(Buffer.from(d.text.trim(), "base64")).toString("utf8"));
242
+ const parsed = parseXml(xml);
243
+ if (parsed?.name === "mxGraphModel")
244
+ model = parsed;
245
+ }
246
+ if (model)
247
+ out.push({ name, model });
248
+ }
249
+ return out;
250
+ }
251
+ function cells(model) {
252
+ const root = model.children.find((c) => c.name === "root");
253
+ const out = [];
254
+ for (const el of root?.children ?? []) {
255
+ const cell = el.name === "mxCell" ? el : el.children.find((c) => c.name === "mxCell");
256
+ if (!cell)
257
+ continue;
258
+ const id = el.attrs.id ?? cell.attrs.id;
259
+ if (!id)
260
+ continue;
261
+ out.push({
262
+ id,
263
+ value: el.name === "mxCell" ? cell.attrs.value ?? "" : el.attrs.label ?? el.attrs.value ?? "",
264
+ ...cell.attrs.parent ? { parent: cell.attrs.parent } : {},
265
+ ...cell.attrs.source ? { source: cell.attrs.source } : {},
266
+ ...cell.attrs.target ? { target: cell.attrs.target } : {},
267
+ vertex: cell.attrs.vertex === "1",
268
+ edge: cell.attrs.edge === "1",
269
+ style: parseStyle(cell.attrs.style),
270
+ line: el.line
271
+ });
272
+ }
273
+ return out;
274
+ }
275
+ function edgeParts2(text) {
276
+ const toks = text.split(" ").filter(Boolean);
277
+ const out = {};
278
+ if (toks[0] && PATTERN2.test(toks[0]))
279
+ out.pattern = toks.shift();
280
+ if (toks[0] && METHODS2.has(toks[0].toUpperCase()) && toks[1]) {
281
+ out.method = toks[0].toUpperCase();
282
+ out.path = toks[1];
283
+ } else if (toks.length === 1 && /^[A-Za-z0-9][\w.-]*$/.test(toks[0]))
284
+ out.topic = toks[0];
285
+ return out;
286
+ }
287
+ function readDrawio(xml, legendWords = DEFAULT_LEGEND2) {
288
+ const doc = parseXml(xml);
289
+ const diagram = { nodes: [], edges: [], problems: [] };
290
+ if (!doc)
291
+ return diagram;
292
+ for (const { name: page, model } of pages(doc)) {
293
+ const all = cells(model);
294
+ const byId = new Map(all.map((c) => [c.id, c]));
295
+ const nodeOf = /* @__PURE__ */ new Map();
296
+ for (const c of all) {
297
+ if (!c.vertex || c.style.edgeLabel !== void 0 || byId.get(c.parent ?? "")?.edge)
298
+ continue;
299
+ const { legend, text } = legendOf2(c.style, labelText(c.value), legendWords);
300
+ if (!text)
301
+ continue;
302
+ const n = {
303
+ cell: c.id,
304
+ label: text,
305
+ page,
306
+ line: c.line,
307
+ ...legend ? { legend } : {},
308
+ style: c.style
309
+ };
310
+ diagram.nodes.push(n);
311
+ nodeOf.set(c.id, n);
312
+ }
313
+ const boxOf = (id) => {
314
+ for (let cur = id ? byId.get(id) : void 0, hops = 0; cur && hops < 50; cur = cur.parent ? byId.get(cur.parent) : void 0, hops++) {
315
+ const n = nodeOf.get(cur.id);
316
+ if (n && !n.style.group)
317
+ return n;
318
+ }
319
+ return void 0;
320
+ };
321
+ for (const c of all.filter((x) => x.edge)) {
322
+ const childText = all.filter((x) => x.parent === c.id && x.vertex).map((x) => labelText(x.value)).filter(Boolean);
323
+ const raw = [labelText(c.value), ...childText].filter(Boolean).join(" ");
324
+ const { legend, text } = legendOf2(c.style, raw, legendWords);
325
+ const from = boxOf(c.source);
326
+ const to = boxOf(c.target);
327
+ if (!from || !to) {
328
+ diagram.problems.push({
329
+ cell: c.id,
330
+ message: !from && !to ? "edge connects no boxes" : !from ? "edge has no source box" : "edge has no target box"
331
+ });
332
+ continue;
333
+ }
334
+ diagram.edges.push({
335
+ cell: c.id,
336
+ from: from.label,
337
+ to: to.label,
338
+ label: text,
339
+ ...edgeParts2(text),
340
+ ...legend ? { legend } : {},
341
+ page,
342
+ line: c.line
343
+ });
344
+ }
345
+ }
346
+ return diagram;
347
+ }
348
+ var slug3 = (s) => s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
349
+ var drawioIngestor = {
350
+ id: "drawio",
351
+ version: "0.1.0",
352
+ sniff(fileName, head) {
353
+ if (/\.drawio(\.xml)?$/i.test(fileName))
354
+ return 1;
355
+ return /^\s*(<\?xml[^>]*>\s*)?<mxfile/.test(new TextDecoder().decode(head.slice(0, 200))) ? 0.9 : 0;
356
+ },
357
+ async *ingest(fileName, content) {
358
+ const base = fileName.split(/[\\/]/).pop().replace(/\.drawio(\.xml)?$/i, "").replace(/\.xml$/i, "");
359
+ const record = {
360
+ schemaVersion: 1,
361
+ kind: "SourceDocument",
362
+ id: `doc.${slug3(base)}`,
363
+ status: "current",
364
+ confidence: "verified",
365
+ path: fileName,
366
+ docType: "diagram",
367
+ hash: createHash2("sha256").update(content).digest("hex"),
368
+ recordsProduced: [],
369
+ evidence: [{ source: "diagram", path: fileName }]
370
+ };
371
+ yield record;
372
+ }
373
+ };
374
+
375
+ // packages/reconcile/dist/reconcile.js
376
+ var VIA = {
377
+ gateway: "through the gateway",
378
+ direct: "directly",
379
+ "event-bus": "over the event bus",
380
+ pubsub: "over pub/sub",
381
+ mq: "over a queue",
382
+ sftp: "by file transfer",
383
+ other: "another way"
384
+ };
385
+ var viaText = (v) => VIA[v] ?? `via ${v}`;
386
+ var normPath = (p) => p.replace(/\{[^}]*\}/g, "{}").replace(/\/+$/, "") || "/";
387
+ function distance(a, b) {
388
+ const d = Array.from({ length: a.length + 1 }, (_, i) => [i, ...Array(b.length).fill(0)]);
389
+ for (let j = 1; j <= b.length; j++)
390
+ d[0][j] = j;
391
+ for (let i = 1; i <= a.length; i++)
392
+ for (let j = 1; j <= b.length; j++)
393
+ d[i][j] = Math.min(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + (a[i - 1] === b[j - 1] ? 0 : 1));
394
+ return d[a.length][b.length];
395
+ }
396
+ function reconcile(input) {
397
+ const { diagram, file, records } = input;
398
+ const items = [];
399
+ const add = (i) => {
400
+ const { key, ...rest } = i;
401
+ items.push({ id: `${i.type}.${slug2(key)}`, ...rest });
402
+ };
403
+ const place = (cell, page, line) => ({ file, page, cell, line });
404
+ const names = resolveNames([
405
+ .../* @__PURE__ */ new Set([
406
+ ...diagram.nodes.map((n) => n.label),
407
+ ...diagram.edges.flatMap((e) => [e.from, e.to])
408
+ ])
409
+ ], records, input.systems);
410
+ const idOf = (name) => names.get(name)?.id;
411
+ const components = new Map(records.filter((r) => r.kind === "Component").map((r) => [r.id, r]));
412
+ const systemIds = /* @__PURE__ */ new Set([
413
+ ...records.filter((r) => r.kind === "System").map((r) => r.id),
414
+ ...input.systems.map((s) => s.id)
415
+ ]);
416
+ const systemOf = (id) => components.get(id)?.system ?? (systemIds.has(id) ? id : void 0);
417
+ const boundaryOf = (id) => {
418
+ const s = records.find((r) => r.kind === "System" && r.id === systemOf(id));
419
+ return s?.boundary;
420
+ };
421
+ const same = (drawn, end) => drawn === end || systemIds.has(drawn) && !components.has(drawn) && systemOf(end) === drawn;
422
+ const interfaces = records.filter((r) => r.kind === "Interface");
423
+ const routes = new Map(records.filter((r) => r.kind === "GatewayRoute").map((r) => [r.id, r.basepath]));
424
+ const tables = records.filter((r) => r.kind === "Table");
425
+ const stores = new Map(records.filter((r) => r.kind === "DataStore").map((r) => [r.id, r.ownerComponent]));
426
+ const patterns = new Map(input.patterns.map((p) => [p.code, p]));
427
+ for (const n of diagram.nodes) {
428
+ const res = names.get(n.label);
429
+ if (res.how === "profile")
430
+ add({
431
+ key: n.label,
432
+ type: "alias-needed",
433
+ name: n.label,
434
+ summary: `The diagram's "${n.label}" was matched to ${res.id} through the profile; confirm it so later diagrams match it directly.`,
435
+ diagram: place(n.cell, n.page, n.line),
436
+ records: [res.id],
437
+ suggestion: {
438
+ text: `Confirm "${n.label}" is ${res.id}`,
439
+ action: "alias",
440
+ target: res.id,
441
+ value: n.label
442
+ }
443
+ });
444
+ else if (!res.id && !n.legend && diagram.edges.some((e) => e.from === n.label || e.to === n.label))
445
+ add({
446
+ key: n.label,
447
+ type: "unknown-box",
448
+ name: n.label,
449
+ summary: `The diagram's "${n.label}" matches nothing in the catalog${res.similar.length ? ` (similar: ${res.similar.join(", ")})` : ""}.`,
450
+ diagram: place(n.cell, n.page, n.line),
451
+ records: res.similar,
452
+ suggestion: res.similar.length ? {
453
+ text: `If "${n.label}" is ${res.similar[0]}, record the alias`,
454
+ action: "alias",
455
+ target: res.similar[0],
456
+ value: n.label
457
+ } : { text: `Say what "${n.label}" is, or mark it New if it doesn't exist yet` }
458
+ });
459
+ }
460
+ const matched = /* @__PURE__ */ new Set();
461
+ const explainedAccess = /* @__PURE__ */ new Set();
462
+ const matches = [];
463
+ const label = (e) => `${e.from} \u2192 ${e.to}${e.label ? ` (${e.label})` : ""}`;
464
+ for (const e of diagram.edges) {
465
+ const where = place(e.cell, e.page, e.line);
466
+ if (e.pattern && !patterns.has(e.pattern)) {
467
+ const near = [...patterns.keys()].map((c) => ({ c, d: distance(c, e.pattern) })).sort((a, b) => a.d - b.d)[0];
468
+ add({
469
+ key: e.cell,
470
+ type: "unknown-pattern",
471
+ summary: `Edge ${label(e)} names pattern ${e.pattern}, which the org pack doesn't have.`,
472
+ diagram: where,
473
+ records: [],
474
+ suggestion: {
475
+ text: near && near.d <= 2 ? `Did you mean ${near.c}?` : `Use one of: ${[...patterns.keys()].join(", ")}`
476
+ }
477
+ });
478
+ }
479
+ const from = idOf(e.from);
480
+ const to = idOf(e.to);
481
+ const candidates = from && to ? interfaces.filter((i) => {
482
+ if (!same(from, i.from) || !same(to, i.to))
483
+ return false;
484
+ if (e.topic)
485
+ return i.sync === "async" && i.normalizedPath === e.topic;
486
+ if (e.path) {
487
+ const grpc = /^\/?([\w.]+\.[\w]+)\/(\w+)$/.exec(e.path);
488
+ if (grpc && (!e.method || e.method === "POST") && i.normalizedPath === `${grpc[1]}/${grpc[2]}`)
489
+ return true;
490
+ if (e.method && i.method && e.method !== i.method.toUpperCase())
491
+ return false;
492
+ const p = normPath(e.path);
493
+ const base = i.route ? routes.get(i.route) : void 0;
494
+ return p === i.normalizedPath || base !== void 0 && p === normPath(base) + i.normalizedPath;
495
+ }
496
+ return true;
497
+ }) : [];
498
+ if (candidates.length > 0) {
499
+ for (const i of candidates)
500
+ matched.add(i.id);
501
+ matches.push({ cell: e.cell, interfaces: candidates.map((i) => i.id).sort() });
502
+ const p = e.pattern ? patterns.get(e.pattern) : void 0;
503
+ for (const i of candidates) {
504
+ if (p) {
505
+ const via = p.detection.via.length > 0 ? p.detection.via : p.route !== "jdbc" && p.route !== "other" ? [p.route] : [];
506
+ const diffs = [];
507
+ if (via.length > 0 && !via.includes(i.via))
508
+ diffs.push(`${p.code} goes ${via.map(viaText).join(" or ")}, the code calls ${viaText(i.via)}`);
509
+ const sync = p.detection.sync ?? (p.interaction === "data-access" ? void 0 : p.interaction);
510
+ if (sync && sync !== i.sync)
511
+ diffs.push(`${p.code} is ${sync}, the code is ${i.sync}`);
512
+ const tb = p.detection.targetBoundary;
513
+ if (tb && boundaryOf(i.to) && tb !== boundaryOf(i.to))
514
+ diffs.push(`${p.code} targets a ${tb} system, ${i.to} is ${boundaryOf(i.to)}`);
515
+ if (diffs.length > 0)
516
+ add({
517
+ key: `${e.cell}-${i.id}`,
518
+ type: "pattern-mismatch",
519
+ summary: `Edge ${label(e)}: ${diffs.join("; ")}. The code is what runs; fix the design or the code.`,
520
+ diagram: where,
521
+ records: [i.id],
522
+ suggestion: {
523
+ text: `Redraw the edge to match the code, or plan a change that routes it as ${p.code} says`
524
+ }
525
+ });
526
+ else if (i.pattern && i.pattern.code !== p.code)
527
+ add({
528
+ key: `${e.cell}-${i.id}`,
529
+ type: "pattern-differs",
530
+ summary: `Edge ${label(e)} is drawn as ${p.code}; the code looks like ${i.pattern.code}.`,
531
+ diagram: where,
532
+ records: [i.id],
533
+ suggestion: {
534
+ text: `Confirm which pattern applies`,
535
+ action: "assert",
536
+ target: i.id,
537
+ value: { pattern: { code: p.code, source: "asserted" } }
538
+ }
539
+ });
540
+ }
541
+ if (e.legend === "modify" || e.legend === "retire")
542
+ add({
543
+ key: `${e.cell}-${i.id}`,
544
+ type: "planned",
545
+ legend: e.legend,
546
+ summary: `Edge ${label(e)} is marked ${e.legend}: add it to a change as planned-${e.legend}.`,
547
+ diagram: where,
548
+ records: [i.id],
549
+ suggestion: { text: `Add ${i.id} to a change as planned-${e.legend}` }
550
+ });
551
+ }
552
+ continue;
553
+ }
554
+ if (e.legend) {
555
+ add({
556
+ key: e.cell,
557
+ type: "planned",
558
+ legend: e.legend,
559
+ summary: `Edge ${label(e)} is marked ${e.legend} and isn't in code yet: it becomes a planned-${e.legend} interface in a change.`,
560
+ diagram: where,
561
+ records: [],
562
+ suggestion: { text: `Add ${label(e)} to a change as a planned-${e.legend} interface` }
563
+ });
564
+ continue;
565
+ }
566
+ if (!from || !to) {
567
+ add({
568
+ key: e.cell,
569
+ type: "diagram-only",
570
+ summary: `Edge ${label(e)} can't be checked: ${!from ? e.from : e.to} isn't in the catalog.`,
571
+ diagram: where,
572
+ records: []
573
+ });
574
+ continue;
575
+ }
576
+ const owned = tables.filter((t) => {
577
+ const owner = t.ownerComponent ?? stores.get(t.dataStore);
578
+ return owner !== void 0 && same(to, owner) && (t.readers.some((c) => same(from, c)) || t.writers.some((c) => same(from, c)));
579
+ });
580
+ if (owned.length > 0 && e.pattern && patterns.get(e.pattern)?.interaction === "data-access") {
581
+ for (const t of owned)
582
+ explainedAccess.add(`${from}|${t.id}`);
583
+ matches.push({ cell: e.cell, interfaces: [], tables: owned.map((t) => t.id).sort() });
584
+ continue;
585
+ }
586
+ if (owned.length > 0) {
587
+ for (const t of owned)
588
+ explainedAccess.add(`${from}|${t.id}`);
589
+ const jdbc = input.patterns.find((p) => p.interaction === "data-access" && p.status !== "deprecated");
590
+ add({
591
+ key: e.cell,
592
+ type: "drawn-call-reads-database",
593
+ summary: `Edge ${label(e)} is drawn as a call to ${to}, but in code ${from} ${owned.every((t) => t.readers.some((c) => same(from, c))) ? "reads" : "uses"} ${to}'s database directly (${owned.map((t) => t.id).join(", ")})${jdbc ? `: that is ${jdbc.code}, not ${e.pattern ?? "a call"}` : ""}.`,
594
+ diagram: where,
595
+ records: owned.map((t) => t.id),
596
+ suggestion: {
597
+ text: `Redraw it as ${jdbc?.code ?? "direct database access"}, or plan a change to go through ${to}'s API`
598
+ }
599
+ });
600
+ continue;
601
+ }
602
+ const reverse = interfaces.filter((i) => same(to, i.from) && same(from, i.to));
603
+ if (reverse.length > 0) {
604
+ add({
605
+ key: e.cell,
606
+ type: "direction-differs",
607
+ summary: `Edge ${label(e)} is drawn from ${from} to ${to}; in code ${to} calls ${from}.`,
608
+ diagram: where,
609
+ records: reverse.map((i) => i.id).sort()
610
+ });
611
+ continue;
612
+ }
613
+ add({
614
+ key: e.cell,
615
+ type: "diagram-only",
616
+ summary: `Edge ${label(e)} is drawn, but no such call is in the code.`,
617
+ diagram: where,
618
+ records: [],
619
+ suggestion: {
620
+ text: "Remove it from the diagram, mark it New, or point Atticus at the repo that makes the call"
621
+ }
622
+ });
623
+ }
624
+ const onDiagram = new Set([...names.values()].flatMap((n) => n.id ? [n.id] : []));
625
+ const touches = (id) => [...onDiagram].some((d) => same(d, id));
626
+ for (const i of interfaces.filter((x) => !matched.has(x.id) && x.status !== "retired").sort((a, b) => a.id < b.id ? -1 : 1)) {
627
+ if (!touches(i.from) && !touches(i.to))
628
+ continue;
629
+ const what = i.sync === "async" ? `publishes ${i.normalizedPath} to` : `calls`;
630
+ add({
631
+ key: i.id,
632
+ type: "code-only",
633
+ summary: `In code ${i.from} ${what} ${i.to}${i.sync === "async" ? "" : ` (${i.method ?? ""} ${i.normalizedPath}`.trimEnd() + ")"}${i.confidence === "inferred" ? ", seen at one end only" : ""}; the diagram doesn't show it.`,
634
+ records: [i.id],
635
+ suggestion: {
636
+ text: `Add it to the diagram, or record why it is left out`,
637
+ action: "suppress",
638
+ target: i.id,
639
+ value: { diagram: file }
640
+ }
641
+ });
642
+ }
643
+ for (const t of tables) {
644
+ const owner = t.ownerComponent ?? stores.get(t.dataStore);
645
+ for (const c of [.../* @__PURE__ */ new Set([...t.readers, ...t.writers])].sort()) {
646
+ if (!owner || c === owner || explainedAccess.has(`${c}|${t.id}`) || !touches(c) || !touches(owner))
647
+ continue;
648
+ add({
649
+ key: `${c}-${t.id}`,
650
+ type: "code-only",
651
+ summary: `In code ${c} uses ${owner}'s table ${t.id} directly; the diagram doesn't show it.`,
652
+ records: [t.id, c]
653
+ });
654
+ }
655
+ }
656
+ return { items, matches, names: [...names.values()] };
657
+ }
658
+
659
+ // packages/ingestors/dist/lucid.js
660
+ function parseCsv(text) {
661
+ const out = [];
662
+ let cells2 = [];
663
+ let cell = "";
664
+ let quoted = false;
665
+ let line = 1;
666
+ let start = 1;
667
+ let any = false;
668
+ const endRecord = () => {
669
+ cells2.push(cell);
670
+ if (any || cells2.length > 1 || cell !== "")
671
+ out.push({ line: start, cells: cells2 });
672
+ cells2 = [];
673
+ cell = "";
674
+ any = false;
675
+ };
676
+ for (let i = 0; i < text.length; i++) {
677
+ const c = text[i];
678
+ if (quoted) {
679
+ if (c === '"') {
680
+ if (text[i + 1] === '"') {
681
+ cell += '"';
682
+ i++;
683
+ } else
684
+ quoted = false;
685
+ } else {
686
+ if (c === "\n")
687
+ line++;
688
+ cell += c;
689
+ }
690
+ continue;
691
+ }
692
+ if (c === '"') {
693
+ quoted = true;
694
+ any = true;
695
+ } else if (c === ",") {
696
+ cells2.push(cell);
697
+ cell = "";
698
+ any = true;
699
+ } else if (c === "\r" && text[i + 1] === "\n")
700
+ continue;
701
+ else if (c === "\n" || c === "\r") {
702
+ endRecord();
703
+ line++;
704
+ start = line;
705
+ } else
706
+ cell += c;
707
+ }
708
+ if (cell !== "" || cells2.length || any)
709
+ endRecord();
710
+ return out;
711
+ }
712
+ var norm = (s) => s.trim().toLowerCase();
713
+ function readLucidCsv(text, legendWords = DEFAULT_LEGEND) {
714
+ const diagram = { nodes: [], edges: [], problems: [] };
715
+ const rows = parseCsv(text.charCodeAt(0) === 65279 ? text.slice(1) : text);
716
+ const header = rows.shift();
717
+ const col = /* @__PURE__ */ new Map();
718
+ header?.cells.forEach((h, i) => col.set(norm(h), i));
719
+ if (!col.has("id")) {
720
+ diagram.problems.push({ cell: "", message: "not a Lucidchart export: no Id column" });
721
+ return diagram;
722
+ }
723
+ const textCols = [...col.entries()].filter(([h]) => /^text area \d+$/.test(h)).sort((a, b) => Number(a[0].slice(10)) - Number(b[0].slice(10))).map(([, i]) => i);
724
+ const get = (r, name) => {
725
+ const i = col.get(name);
726
+ return i === void 0 ? "" : (r.cells[i] ?? "").trim();
727
+ };
728
+ const textOf2 = (r) => labelText(textCols.map((i) => r.cells[i] ?? "").filter((t) => t.trim()).join(" "));
729
+ const pages2 = /* @__PURE__ */ new Map();
730
+ for (const r of rows)
731
+ if (norm(get(r, "name")) === "page")
732
+ pages2.set(get(r, "id"), textOf2(r));
733
+ const isLine = (r) => norm(get(r, "name")) === "line" || !!get(r, "line source") || !!get(r, "line destination");
734
+ const byId = new Map(rows.map((r) => [get(r, "id"), r]));
735
+ const nodeOf = /* @__PURE__ */ new Map();
736
+ for (const r of rows) {
737
+ const kind = norm(get(r, "name"));
738
+ if (kind === "document" || kind === "page" || isLine(r))
739
+ continue;
740
+ const { legend, text: label } = legendOf(legendWord(get(r, "legend"), legendWords), textOf2(r), legendWords);
741
+ if (!label)
742
+ continue;
743
+ const library = get(r, "shape library");
744
+ const n = {
745
+ cell: get(r, "id"),
746
+ label,
747
+ page: pages2.get(get(r, "page id")) ?? "",
748
+ line: r.line,
749
+ ...legend ? { legend } : {},
750
+ style: { shape: get(r, "name"), ...library ? { library } : {} }
751
+ };
752
+ diagram.nodes.push(n);
753
+ nodeOf.set(n.cell, n);
754
+ }
755
+ const boxOf = (id) => {
756
+ const seen = /* @__PURE__ */ new Set();
757
+ for (let cur = id; cur && !seen.has(cur); ) {
758
+ seen.add(cur);
759
+ const n = nodeOf.get(cur);
760
+ if (n)
761
+ return n;
762
+ const r = byId.get(cur);
763
+ cur = r ? (get(r, "contained by") || get(r, "group")).split(/[;,\s]+/)[0] : void 0;
764
+ }
765
+ return void 0;
766
+ };
767
+ for (const r of rows.filter(isLine)) {
768
+ const id = get(r, "id");
769
+ const src = get(r, "line source");
770
+ const dst = get(r, "line destination");
771
+ const from = src ? boxOf(src) : void 0;
772
+ const to = dst ? boxOf(dst) : void 0;
773
+ if (!from || !to) {
774
+ diagram.problems.push({
775
+ cell: id,
776
+ message: !from && !to ? "edge connects no boxes" : !from ? "edge has no source box" : "edge has no target box"
777
+ });
778
+ continue;
779
+ }
780
+ const { legend, text: label } = legendOf(legendWord(get(r, "legend"), legendWords), textOf2(r), legendWords);
781
+ diagram.edges.push({
782
+ cell: id,
783
+ from: from.label,
784
+ to: to.label,
785
+ label,
786
+ ...edgeParts(label),
787
+ ...legend ? { legend } : {},
788
+ page: pages2.get(get(r, "page id")) ?? "",
789
+ line: r.line
790
+ });
791
+ }
792
+ return diagram;
793
+ }
794
+
795
+ // packages/ingestors/dist/mermaid.js
796
+ var SHAPES = [
797
+ ["(((", ")))", "double-circle"],
798
+ ["([", "])", "stadium"],
799
+ ["[[", "]]", "subroutine"],
800
+ ["[(", ")]", "cylinder"],
801
+ ["((", "))", "circle"],
802
+ ["{{", "}}", "hexagon"],
803
+ ["[/", "/]", "parallelogram"],
804
+ ["[/", "\\]", "trapezoid"],
805
+ ["[\\", "\\]", "parallelogram-alt"],
806
+ ["[\\", "/]", "trapezoid-alt"],
807
+ [">", "]", "asymmetric"],
808
+ ["[", "]", "rect"],
809
+ ["(", ")", "rounded"],
810
+ ["{", "}", "diamond"]
811
+ ];
812
+ var LINK = /^(?:<|o|x)?(?:-{2,}>|-{2,}[ox](?![\w])|-{3,}|={2,}>|={2,}[ox](?![\w])|={3,}|-\.+->|-\.+-|~{3,})/;
813
+ var LINK_TEXT = /^(?:<|o|x)?(?:--|==|-\.)\s+(.+?)\s+(?:-{2,}>|-{2,}[ox](?![\w])|-{3,}|={2,}>|={2,}[ox](?![\w])|={3,}|\.+->|\.+-)/;
814
+ var ID = /^[A-Za-z0-9_]+/;
815
+ function frontMatterTitle(lines) {
816
+ if (lines[0]?.trim() !== "---")
817
+ return { skip: 0 };
818
+ const end = lines.findIndex((l, i) => i > 0 && l.trim() === "---");
819
+ if (end < 0)
820
+ return { skip: 0 };
821
+ let title;
822
+ for (const l of lines.slice(1, end)) {
823
+ const m = /^title:\s*(.*)$/.exec(l.trim());
824
+ if (m)
825
+ title = m[1].replace(/^(["'])(.*)\1$/, "$2").trim();
826
+ }
827
+ return { ...title ? { title } : {}, skip: end + 1 };
828
+ }
829
+ function blocks(text) {
830
+ const lines = text.replace(/^\uFEFF/, "").split(/\r?\n/);
831
+ const fm = frontMatterTitle(lines);
832
+ const fenced = lines.some((l) => /^\s*(`{3,}|~{3,})\s*mermaid\s*$/.test(l));
833
+ if (!fenced)
834
+ return [{ lines: lines.slice(fm.skip), first: fm.skip + 1, page: fm.title ?? "" }];
835
+ const out = [];
836
+ let heading = fm.title ?? "";
837
+ let fence;
838
+ let mermaid;
839
+ for (let i = fm.skip; i < lines.length; i++) {
840
+ const l = lines[i];
841
+ if (fence) {
842
+ if (l.trim().startsWith(fence) && /^\s*(`+|~+)\s*$/.test(l)) {
843
+ if (mermaid)
844
+ out.push(mermaid);
845
+ fence = void 0;
846
+ mermaid = void 0;
847
+ } else
848
+ mermaid?.lines.push(l);
849
+ continue;
850
+ }
851
+ const open = /^\s*(`{3,}|~{3,})\s*(\S*)/.exec(l);
852
+ if (open) {
853
+ fence = open[1];
854
+ if (open[2] === "mermaid")
855
+ mermaid = { lines: [], first: i + 2, page: heading };
856
+ continue;
857
+ }
858
+ const h = /^#{1,6}\s+(.*?)\s*#*\s*$/.exec(l);
859
+ if (h && !fm.title)
860
+ heading = h[1];
861
+ }
862
+ return out;
863
+ }
864
+ function statements(line) {
865
+ const out = [];
866
+ let depth = 0;
867
+ let quote = false;
868
+ let pipe = false;
869
+ let cur = "";
870
+ for (const c of line) {
871
+ if (c === '"')
872
+ quote = !quote;
873
+ else if (!quote) {
874
+ if (c === "|")
875
+ pipe = !pipe;
876
+ else if (!pipe && "[({".includes(c))
877
+ depth++;
878
+ else if (!pipe && "])}".includes(c))
879
+ depth = Math.max(0, depth - 1);
880
+ else if (c === ";" && depth === 0 && !pipe) {
881
+ out.push(cur);
882
+ cur = "";
883
+ continue;
884
+ }
885
+ }
886
+ cur += c;
887
+ }
888
+ out.push(cur);
889
+ return out.map((s) => s.trim()).filter(Boolean);
890
+ }
891
+ var unquote = (s) => {
892
+ const t = s.trim();
893
+ if (t.length >= 2 && t.startsWith('"') && t.endsWith('"'))
894
+ return t.slice(1, -1);
895
+ if (t.length >= 2 && t.startsWith("`") && t.endsWith("`"))
896
+ return t.slice(1, -1);
897
+ return t;
898
+ };
899
+ function parseNode(s) {
900
+ const id = ID.exec(s);
901
+ if (!id)
902
+ return void 0;
903
+ let rest = s.slice(id[0].length);
904
+ const node = { id: id[0], classes: [] };
905
+ if (rest.startsWith("@{")) {
906
+ let q = false;
907
+ let end = -1;
908
+ for (let i = 2; i < rest.length; i++) {
909
+ if (rest[i] === '"')
910
+ q = !q;
911
+ else if (!q && rest[i] === "}") {
912
+ end = i;
913
+ break;
914
+ }
915
+ }
916
+ if (end < 0)
917
+ return void 0;
918
+ for (const m of rest.slice(2, end).matchAll(/(\w+)\s*:\s*("([^"]*)"|'([^']*)'|[^,]+)/g)) {
919
+ const v = (m[3] ?? m[4] ?? m[2]).trim();
920
+ if (m[1] === "label")
921
+ node.label = v;
922
+ else if (m[1] === "shape")
923
+ node.shape = v;
924
+ }
925
+ rest = rest.slice(end + 1);
926
+ } else {
927
+ for (const [open, close, shape] of SHAPES) {
928
+ if (!rest.startsWith(open))
929
+ continue;
930
+ const body = rest.slice(open.length);
931
+ let end = -1;
932
+ let label = "";
933
+ if (body.startsWith('"')) {
934
+ const q = body.indexOf('"', 1);
935
+ if (q > 0 && body.slice(q + 1).trimStart().startsWith(close)) {
936
+ label = body.slice(1, q);
937
+ end = body.indexOf(close, q + 1);
938
+ }
939
+ } else {
940
+ end = body.indexOf(close);
941
+ label = end >= 0 ? body.slice(0, end) : "";
942
+ }
943
+ if (end < 0)
944
+ continue;
945
+ node.label = unquote(label);
946
+ node.shape = shape;
947
+ rest = body.slice(end + close.length);
948
+ break;
949
+ }
950
+ }
951
+ const cls = /^:::([\w-]+)/.exec(rest);
952
+ if (cls) {
953
+ node.classes.push(cls[1]);
954
+ rest = rest.slice(cls[0].length);
955
+ }
956
+ return { node, rest };
957
+ }
958
+ function parseLink(s) {
959
+ let rest = s;
960
+ let id;
961
+ const named = /^([A-Za-z0-9_]+)@(?=[-=.<ox~])/.exec(rest);
962
+ if (named) {
963
+ id = named[1];
964
+ rest = rest.slice(named[0].length);
965
+ }
966
+ const plain = LINK.exec(rest);
967
+ if (plain) {
968
+ rest = rest.slice(plain[0].length);
969
+ let text = "";
970
+ const piped = /^\s*\|([^|]*)\|/.exec(rest);
971
+ if (piped) {
972
+ text = piped[1];
973
+ rest = rest.slice(piped[0].length);
974
+ }
975
+ return { link: { ...id ? { id } : {}, text: unquote(text) }, rest };
976
+ }
977
+ const middle = LINK_TEXT.exec(rest);
978
+ if (middle) {
979
+ return {
980
+ link: { ...id ? { id } : {}, text: unquote(middle[1]) },
981
+ rest: rest.slice(middle[0].length)
982
+ };
983
+ }
984
+ return void 0;
985
+ }
986
+ function parseChain(s) {
987
+ const groups = [];
988
+ const links = [];
989
+ let rest = s.trim();
990
+ const group = () => {
991
+ const g = [];
992
+ for (; ; ) {
993
+ const n = parseNode(rest);
994
+ if (!n)
995
+ return false;
996
+ g.push(n.node);
997
+ rest = n.rest.trimStart();
998
+ if (!rest.startsWith("&"))
999
+ break;
1000
+ rest = rest.slice(1).trimStart();
1001
+ }
1002
+ groups.push(g);
1003
+ return true;
1004
+ };
1005
+ if (!group())
1006
+ return void 0;
1007
+ while (rest) {
1008
+ const l = parseLink(rest);
1009
+ if (!l)
1010
+ return void 0;
1011
+ links.push(l.link);
1012
+ rest = l.rest.trimStart();
1013
+ if (!group())
1014
+ return void 0;
1015
+ }
1016
+ return { groups, links };
1017
+ }
1018
+ function readMermaid(text, legendWords = DEFAULT_LEGEND) {
1019
+ const diagram = { nodes: [], edges: [], problems: [] };
1020
+ let found = false;
1021
+ for (const block of blocks(text)) {
1022
+ const fm = frontMatterTitle(block.lines);
1023
+ const page = fm.title ?? block.page;
1024
+ const nodes = /* @__PURE__ */ new Map();
1025
+ const edges = [];
1026
+ const classOf = /* @__PURE__ */ new Map();
1027
+ let header = false;
1028
+ let count = 0;
1029
+ const mention = (n, line, extra = {}) => {
1030
+ let st = nodes.get(n.id);
1031
+ if (!st) {
1032
+ st = { cell: n.id, line, page, style: { ...extra }, classes: [] };
1033
+ nodes.set(n.id, st);
1034
+ }
1035
+ if (n.label !== void 0 && st.label === void 0)
1036
+ st.label = n.label;
1037
+ if (n.shape && !st.style.shape && !st.style.subgraph)
1038
+ st.style.shape = n.shape;
1039
+ st.classes.push(...n.classes);
1040
+ };
1041
+ for (let i = fm.skip; i < block.lines.length; i++) {
1042
+ const raw = block.lines[i].trim();
1043
+ const line = block.first + i;
1044
+ if (!raw || raw.startsWith("%%"))
1045
+ continue;
1046
+ for (const st of statements(raw)) {
1047
+ if (!header) {
1048
+ if (!/^(flowchart|graph)\b/i.test(st))
1049
+ break;
1050
+ header = true;
1051
+ found = true;
1052
+ continue;
1053
+ }
1054
+ if (/^end$/i.test(st))
1055
+ continue;
1056
+ if (/^(classDef|style|linkStyle|click|direction|accTitle|accDescr)\b/.test(st))
1057
+ continue;
1058
+ const cls = /^class\s+([\w,\s]+?)\s+([\w-]+)$/.exec(st);
1059
+ if (cls) {
1060
+ for (const id of cls[1].split(",").map((x) => x.trim()))
1061
+ classOf.set(id, [...classOf.get(id) ?? [], cls[2]]);
1062
+ continue;
1063
+ }
1064
+ const sub = /^subgraph\s+(.+)$/i.exec(st);
1065
+ if (sub) {
1066
+ const n = parseNode(sub[1].trim());
1067
+ const ref2 = n && !n.rest.trim() ? n.node : { id: sub[1].trim(), label: unquote(sub[1]), classes: [] };
1068
+ mention({ ...ref2, shape: void 0 }, line, { subgraph: "1" });
1069
+ continue;
1070
+ }
1071
+ const chain = parseChain(st);
1072
+ if (!chain) {
1073
+ diagram.problems.push({ cell: `L${line}`, message: "line not understood" });
1074
+ continue;
1075
+ }
1076
+ chain.groups.forEach((g) => g.forEach((n) => mention(n, line)));
1077
+ chain.links.forEach((l, k) => {
1078
+ for (const a of chain.groups[k])
1079
+ for (const b of chain.groups[k + 1]) {
1080
+ count++;
1081
+ edges.push({
1082
+ cell: l.id ?? `e${count}`,
1083
+ from: a.id,
1084
+ to: b.id,
1085
+ text: l.text,
1086
+ line
1087
+ });
1088
+ }
1089
+ });
1090
+ }
1091
+ if (!header)
1092
+ break;
1093
+ }
1094
+ if (!header)
1095
+ continue;
1096
+ const label = (id) => {
1097
+ const n = nodes.get(id);
1098
+ return labelText(n.label ?? n.cell) || n.cell;
1099
+ };
1100
+ const classLegend = (id, own = []) => {
1101
+ for (const c of [...own, ...classOf.get(id) ?? []]) {
1102
+ const l = legendWord(c, legendWords);
1103
+ if (l)
1104
+ return l;
1105
+ }
1106
+ return void 0;
1107
+ };
1108
+ const labels = /* @__PURE__ */ new Map();
1109
+ for (const n of nodes.values()) {
1110
+ const { legend, text: lbl } = legendOf(classLegend(n.cell, n.classes), label(n.cell), legendWords);
1111
+ labels.set(n.cell, lbl);
1112
+ diagram.nodes.push({
1113
+ cell: n.cell,
1114
+ label: lbl,
1115
+ page: n.page,
1116
+ line: n.line,
1117
+ ...legend ? { legend } : {},
1118
+ style: n.style
1119
+ });
1120
+ }
1121
+ for (const e of edges) {
1122
+ const { legend, text: lbl } = legendOf(classLegend(e.cell), labelText(e.text), legendWords);
1123
+ diagram.edges.push({
1124
+ cell: e.cell,
1125
+ from: labels.get(e.from),
1126
+ to: labels.get(e.to),
1127
+ label: lbl,
1128
+ ...edgeParts(lbl),
1129
+ ...legend ? { legend } : {},
1130
+ page,
1131
+ line: e.line
1132
+ });
1133
+ }
1134
+ }
1135
+ if (!found)
1136
+ diagram.problems.push({ cell: "", message: "no flowchart or graph diagram found" });
1137
+ return diagram;
1138
+ }
1139
+
1140
+ // packages/ingestors/dist/xml.js
1141
+ var NAMED = { lt: "<", gt: ">", amp: "&", quot: '"', apos: "'" };
1142
+ function decodeEntities(s, named = NAMED) {
1143
+ return s.replace(/&(#\d+|#x[0-9a-f]+|[a-z][a-z0-9]*);/gi, (m, e) => {
1144
+ if (e[0] === "#") {
1145
+ const cp = e[1] === "x" || e[1] === "X" ? parseInt(e.slice(2), 16) : parseInt(e.slice(1), 10);
1146
+ return cp > 0 && cp <= 1114111 ? String.fromCodePoint(cp) : m;
1147
+ }
1148
+ return named[e] ?? named[e.toLowerCase()] ?? m;
1149
+ });
1150
+ }
1151
+ function parseXmlTree(src) {
1152
+ const root = { name: "#document", attrs: {}, children: [], line: 1 };
1153
+ const stack = [root];
1154
+ let i = 0;
1155
+ let line = 1;
1156
+ const advance = (to) => {
1157
+ for (let k = i; k < to; k++)
1158
+ if (src.charCodeAt(k) === 10)
1159
+ line++;
1160
+ i = to;
1161
+ };
1162
+ const addText = (t) => {
1163
+ if (!t)
1164
+ return;
1165
+ const top = stack.at(-1);
1166
+ if (top === root)
1167
+ return;
1168
+ const last = top.children.at(-1);
1169
+ if (typeof last === "string")
1170
+ top.children[top.children.length - 1] = last + t;
1171
+ else
1172
+ top.children.push(t);
1173
+ };
1174
+ while (i < src.length) {
1175
+ const lt = src.indexOf("<", i);
1176
+ if (lt === -1) {
1177
+ addText(decodeEntities(src.slice(i)));
1178
+ break;
1179
+ }
1180
+ addText(decodeEntities(src.slice(i, lt)));
1181
+ advance(lt);
1182
+ if (src.startsWith("<!--", i)) {
1183
+ const end2 = src.indexOf("-->", i);
1184
+ advance(end2 === -1 ? src.length : end2 + 3);
1185
+ continue;
1186
+ }
1187
+ if (src.startsWith("<![CDATA[", i)) {
1188
+ const end2 = src.indexOf("]]>", i);
1189
+ addText(src.slice(i + 9, end2 === -1 ? src.length : end2));
1190
+ advance(end2 === -1 ? src.length : end2 + 3);
1191
+ continue;
1192
+ }
1193
+ if (src.startsWith("<?", i)) {
1194
+ const end2 = src.indexOf("?>", i);
1195
+ advance(end2 === -1 ? src.length : end2 + 2);
1196
+ continue;
1197
+ }
1198
+ if (src.startsWith("<!", i)) {
1199
+ let depth = 0;
1200
+ let k = i + 2;
1201
+ for (; k < src.length; k++) {
1202
+ const c = src[k];
1203
+ if (c === "[")
1204
+ depth++;
1205
+ else if (c === "]")
1206
+ depth--;
1207
+ else if (c === ">" && depth <= 0)
1208
+ break;
1209
+ }
1210
+ advance(Math.min(k + 1, src.length));
1211
+ continue;
1212
+ }
1213
+ let end = i + 1;
1214
+ let quote = "";
1215
+ for (; end < src.length; end++) {
1216
+ const c = src[end];
1217
+ if (quote) {
1218
+ if (c === quote)
1219
+ quote = "";
1220
+ } else if (c === '"' || c === "'")
1221
+ quote = c;
1222
+ else if (c === ">")
1223
+ break;
1224
+ }
1225
+ if (end >= src.length)
1226
+ break;
1227
+ const tag = src.slice(i + 1, end);
1228
+ const startLine = line;
1229
+ advance(end + 1);
1230
+ if (tag.startsWith("/")) {
1231
+ const name = localName(tag.slice(1).trim());
1232
+ for (let k = stack.length - 1; k > 0; k--) {
1233
+ if (stack[k].name === name) {
1234
+ stack.length = k;
1235
+ break;
1236
+ }
1237
+ }
1238
+ continue;
1239
+ }
1240
+ const selfClosing = tag.endsWith("/");
1241
+ const body = selfClosing ? tag.slice(0, -1) : tag;
1242
+ const m = /^([^\s/>]+)([\s\S]*)$/.exec(body.trim());
1243
+ if (!m)
1244
+ continue;
1245
+ const attrs = {};
1246
+ for (const a of m[2].matchAll(/([^\s=]+)\s*=\s*("([^"]*)"|'([^']*)')/g))
1247
+ attrs[a[1]] = decodeEntities(a[3] ?? a[4] ?? "");
1248
+ const el = { name: localName(m[1]), attrs, children: [], line: startLine };
1249
+ stack.at(-1).children.push(el);
1250
+ if (!selfClosing)
1251
+ stack.push(el);
1252
+ }
1253
+ return root.children.find((c) => typeof c !== "string");
1254
+ }
1255
+ var localName = (q) => q.replace(/^.*:/, "");
1256
+ function attr(el, name) {
1257
+ if (el.attrs[name] !== void 0)
1258
+ return el.attrs[name];
1259
+ for (const [k, v] of Object.entries(el.attrs))
1260
+ if (localName(k) === name)
1261
+ return v;
1262
+ return void 0;
1263
+ }
1264
+ function relId(el) {
1265
+ for (const [k, v] of Object.entries(el.attrs))
1266
+ if (/^[^:]+:id$/.test(k))
1267
+ return v;
1268
+ return void 0;
1269
+ }
1270
+ var elements = (el) => (el?.children ?? []).filter((c) => typeof c !== "string");
1271
+ var child = (el, name) => elements(el).find((c) => c.name === name);
1272
+ var childrenNamed = (el, name) => elements(el).filter((c) => c.name === name);
1273
+ function findAll(el, name, intoMatches = false) {
1274
+ const out = [];
1275
+ const walk = (n) => {
1276
+ for (const c of elements(n)) {
1277
+ if (c.name === name) {
1278
+ out.push(c);
1279
+ if (!intoMatches)
1280
+ continue;
1281
+ }
1282
+ walk(c);
1283
+ }
1284
+ };
1285
+ if (el)
1286
+ walk(el);
1287
+ return out;
1288
+ }
1289
+ function textOf(el) {
1290
+ if (!el)
1291
+ return "";
1292
+ return el.children.map((c) => typeof c === "string" ? c : textOf(c)).join("");
1293
+ }
1294
+ function relationships(xml) {
1295
+ const out = /* @__PURE__ */ new Map();
1296
+ const doc = xml ? parseXmlTree(xml) : void 0;
1297
+ for (const r of childrenNamed(doc, "Relationship")) {
1298
+ const id = r.attrs.Id;
1299
+ const target = r.attrs.Target;
1300
+ if (id && target && r.attrs.TargetMode !== "External")
1301
+ out.set(id, target);
1302
+ }
1303
+ return out;
1304
+ }
1305
+ function resolvePart(fromFolder, target) {
1306
+ const parts = target.startsWith("/") ? [] : fromFolder.split("/").filter(Boolean);
1307
+ for (const seg of target.split("/")) {
1308
+ if (!seg || seg === ".")
1309
+ continue;
1310
+ if (seg === "..")
1311
+ parts.pop();
1312
+ else
1313
+ parts.push(seg);
1314
+ }
1315
+ return parts.join("/");
1316
+ }
1317
+
1318
+ // packages/ingestors/dist/vsdx.js
1319
+ function shapeText(el) {
1320
+ const t = child(el, "Text");
1321
+ if (!t)
1322
+ return "";
1323
+ const walk = (n) => n.children.map((c) => typeof c === "string" ? c : walk(c)).join("");
1324
+ return squash(walk(t));
1325
+ }
1326
+ function dataLegend(el, words2) {
1327
+ for (const section of childrenNamed(el, "Section")) {
1328
+ if (section.attrs.N !== "Property")
1329
+ continue;
1330
+ for (const row of childrenNamed(section, "Row")) {
1331
+ const cells2 = new Map(childrenNamed(row, "Cell").map((c) => [c.attrs.N, c]));
1332
+ const label = cells2.get("Label")?.attrs.V;
1333
+ if (row.attrs.N?.toLowerCase() !== "legend" && label?.toLowerCase() !== "legend")
1334
+ continue;
1335
+ const value = cells2.get("Value");
1336
+ const v = value?.attrs.V ?? (value ? squash(value.children.join(" ")) : void 0);
1337
+ const legend = legendWord(v, words2);
1338
+ if (legend)
1339
+ return legend;
1340
+ }
1341
+ }
1342
+ return void 0;
1343
+ }
1344
+ function shapesOf(container, parent, masters, words2, out) {
1345
+ const list = [];
1346
+ for (const el of childrenNamed(child(container, "Shapes"), "Shape")) {
1347
+ const cells2 = {};
1348
+ for (const c of childrenNamed(el, "Cell"))
1349
+ if (c.attrs.N && c.attrs.V !== void 0)
1350
+ cells2[c.attrs.N] = c.attrs.V;
1351
+ const masterName = el.attrs.Master ? masters.get(el.attrs.Master) : void 0;
1352
+ const s = {
1353
+ el,
1354
+ id: el.attrs.ID ?? "",
1355
+ ...parent ? { parent } : {},
1356
+ children: [],
1357
+ text: shapeText(el),
1358
+ ...masterName ? { master: masterName } : {},
1359
+ group: el.attrs.Type === "Group",
1360
+ oneD: "BeginX" in cells2 || "EndX" in cells2,
1361
+ ...(() => {
1362
+ const l = dataLegend(el, words2);
1363
+ return l ? { legend: l } : {};
1364
+ })(),
1365
+ cells: cells2
1366
+ };
1367
+ out.push(s);
1368
+ list.push(s);
1369
+ s.children = shapesOf(el, s, masters, words2, out);
1370
+ }
1371
+ return list;
1372
+ }
1373
+ function readVsdx(bytes, legendWords = DEFAULT_LEGEND, limits = {}) {
1374
+ const zip = readZip(bytes, limits);
1375
+ const diagram = { nodes: [], edges: [], problems: [] };
1376
+ const masters = /* @__PURE__ */ new Map();
1377
+ for (const m of findAll(parseXmlTree(zip.text("visio/masters/masters.xml") ?? ""), "Master"))
1378
+ if (m.attrs.ID)
1379
+ masters.set(m.attrs.ID, m.attrs.NameU ?? m.attrs.Name ?? "");
1380
+ const rels = relationships(zip.text("visio/pages/_rels/pages.xml.rels"));
1381
+ const listed = [];
1382
+ childrenNamed(parseXmlTree(zip.text("visio/pages/pages.xml") ?? ""), "Page").forEach((p, i) => {
1383
+ const rel = child(p, "Rel");
1384
+ const rid = rel ? relId(rel) : void 0;
1385
+ const target = rid ? rels.get(rid) : void 0;
1386
+ if (!target)
1387
+ return;
1388
+ listed.push({
1389
+ id: p.attrs.ID ?? String(i),
1390
+ name: p.attrs.Name ?? p.attrs.NameU ?? "",
1391
+ part: resolvePart("visio/pages", target)
1392
+ });
1393
+ });
1394
+ const pageNo = (n) => Number(/page(\d+)\.xml$/.exec(n)?.[1] ?? 0);
1395
+ for (const part of zip.names.filter((n) => /^visio\/pages\/page\d+\.xml$/.test(n)).sort((a, b) => pageNo(a) - pageNo(b)))
1396
+ if (!listed.some((l) => l.part === part))
1397
+ listed.push({ id: String(pageNo(part)), name: "", part });
1398
+ const pages2 = listed.filter((p) => zip.has(p.part));
1399
+ if (!pages2.length) {
1400
+ diagram.problems.push({ cell: "", message: "no pages found in the Visio file" });
1401
+ return diagram;
1402
+ }
1403
+ for (const page of pages2) {
1404
+ const doc = parseXmlTree(zip.text(page.part) ?? "");
1405
+ const all = [];
1406
+ shapesOf(doc, void 0, masters, legendWords, all);
1407
+ const byId = new Map(all.map((s) => [s.id, s]));
1408
+ const ends = /* @__PURE__ */ new Map();
1409
+ for (const c of findAll(child(doc, "Connects"), "Connect")) {
1410
+ const from = c.attrs.FromSheet;
1411
+ const to = c.attrs.ToSheet;
1412
+ if (!from || !to)
1413
+ continue;
1414
+ const e = ends.get(from) ?? {};
1415
+ if (c.attrs.FromCell === "BeginX")
1416
+ e.begin = to;
1417
+ else if (c.attrs.FromCell === "EndX")
1418
+ e.end = to;
1419
+ else
1420
+ continue;
1421
+ ends.set(from, e);
1422
+ }
1423
+ const isConnector = (s) => ends.has(s.id) || s.oneD;
1424
+ const cell = (s) => `${page.id}.${s.id}`;
1425
+ const nodeOf = /* @__PURE__ */ new Map();
1426
+ for (const s of all) {
1427
+ if (isConnector(s))
1428
+ continue;
1429
+ const { legend, text } = legendOf(s.legend, s.text, legendWords);
1430
+ if (!text)
1431
+ continue;
1432
+ const style = {};
1433
+ if (s.master)
1434
+ style.master = s.master;
1435
+ if (s.cells.PinX !== void 0)
1436
+ style.x = s.cells.PinX;
1437
+ if (s.cells.PinY !== void 0)
1438
+ style.y = s.cells.PinY;
1439
+ if (s.group)
1440
+ style.group = "1";
1441
+ const n = {
1442
+ cell: cell(s),
1443
+ label: text,
1444
+ page: page.name,
1445
+ line: s.el.line,
1446
+ ...legend ? { legend } : {},
1447
+ style
1448
+ };
1449
+ diagram.nodes.push(n);
1450
+ nodeOf.set(s, n);
1451
+ }
1452
+ const boxOf = (id) => {
1453
+ const start = id ? byId.get(id) : void 0;
1454
+ for (let cur = start; cur; cur = cur.parent) {
1455
+ const n = nodeOf.get(cur);
1456
+ if (n)
1457
+ return n;
1458
+ }
1459
+ if (!start)
1460
+ return void 0;
1461
+ const inside = [];
1462
+ const walk = (s) => s.children.forEach((c) => {
1463
+ const n = nodeOf.get(c);
1464
+ if (n)
1465
+ inside.push(n);
1466
+ else
1467
+ walk(c);
1468
+ });
1469
+ walk(start);
1470
+ return inside.length === 1 ? inside[0] : void 0;
1471
+ };
1472
+ for (const s of all.filter(isConnector)) {
1473
+ const e = ends.get(s.id) ?? {};
1474
+ const from = boxOf(e.begin);
1475
+ const to = boxOf(e.end);
1476
+ if (!from || !to) {
1477
+ diagram.problems.push({
1478
+ cell: cell(s),
1479
+ message: !from && !to ? "edge connects no boxes" : !from ? "edge has no source box" : "edge has no target box"
1480
+ });
1481
+ continue;
1482
+ }
1483
+ const { legend, text } = legendOf(s.legend, s.text, legendWords);
1484
+ diagram.edges.push({
1485
+ cell: cell(s),
1486
+ from: from.label,
1487
+ to: to.label,
1488
+ label: text,
1489
+ ...edgeParts(text),
1490
+ ...legend ? { legend } : {},
1491
+ page: page.name,
1492
+ line: s.el.line
1493
+ });
1494
+ }
1495
+ }
1496
+ return diagram;
1497
+ }
1498
+
1499
+ // packages/ingestors/dist/diagram.js
1500
+ function readDiagram(fileName, bytes, legendWords = DEFAULT_LEGEND) {
1501
+ const ext = extOf(fileName);
1502
+ if (/\.drawio(\.xml)?$/i.test(fileBase(fileName)))
1503
+ return readDrawio(utf8(bytes), legendWords);
1504
+ if (ext === ".vsdx")
1505
+ return readVsdx(bytes, legendWords);
1506
+ if (ext === ".csv")
1507
+ return readLucidCsv(utf8(bytes), legendWords);
1508
+ if (ext === ".mmd" || ext === ".mermaid")
1509
+ return readMermaid(utf8(bytes), legendWords);
1510
+ if (ext === ".md" || ext === ".markdown") {
1511
+ const text = utf8(bytes);
1512
+ return /^\s*(`{3,}|~{3,})\s*mermaid\s*$/m.test(text) ? readMermaid(text, legendWords) : void 0;
1513
+ }
1514
+ return void 0;
1515
+ }
1516
+
1517
+ // packages/ingestors/dist/markup.js
1518
+ var import_yaml = __toESM(require_dist(), 1);
1519
+
1520
+ // packages/ingestors/dist/text-model.js
1521
+ var ReadError = class extends Error {
1522
+ name = "ReadError";
1523
+ };
1524
+ var Sections = class {
1525
+ list = [];
1526
+ lines = [];
1527
+ cur = { heading: "", level: 0, text: "" };
1528
+ firstLine;
1529
+ heading(heading, level, at = {}) {
1530
+ this.flush();
1531
+ this.cur = { heading, level, text: "", ...at };
1532
+ }
1533
+ /** Add a line of text; `line` is where it is in the file (an untitled section starts there). */
1534
+ add(text, line) {
1535
+ if (this.firstLine === void 0 && line !== void 0 && text.trim())
1536
+ this.firstLine = line;
1537
+ this.lines.push(text);
1538
+ }
1539
+ /** Take back the last line added (Markdown: a setext underline turns it into a heading). */
1540
+ popLine() {
1541
+ return this.lines.pop();
1542
+ }
1543
+ /** Close the current section. One with neither heading nor text is dropped. */
1544
+ flush() {
1545
+ const text = trimBlankLines(this.lines);
1546
+ const untitled = this.cur.heading === "";
1547
+ if (!(untitled && !text)) {
1548
+ const line = this.cur.line ?? (untitled ? this.firstLine : void 0);
1549
+ this.list.push({ ...this.cur, text, ...line !== void 0 ? { line } : {} });
1550
+ }
1551
+ this.lines = [];
1552
+ this.firstLine = void 0;
1553
+ }
1554
+ done() {
1555
+ this.flush();
1556
+ return this.list;
1557
+ }
1558
+ };
1559
+ function trimBlankLines(lines) {
1560
+ const l = lines.map((x) => x.replace(/\s+$/, ""));
1561
+ while (l.length && !l[0])
1562
+ l.shift();
1563
+ while (l.length && !l.at(-1))
1564
+ l.pop();
1565
+ return l.join("\n");
1566
+ }
1567
+
1568
+ // packages/ingestors/dist/markup.js
1569
+ var str = (v) => {
1570
+ if (typeof v === "string")
1571
+ return v.trim() || void 0;
1572
+ if (Array.isArray(v)) {
1573
+ const parts = v.filter((x) => typeof x === "string" && !!x.trim());
1574
+ return parts.length ? parts.join(", ") : void 0;
1575
+ }
1576
+ return void 0;
1577
+ };
1578
+ function tableCells(line) {
1579
+ let t = line.trim();
1580
+ if (t.startsWith("|"))
1581
+ t = t.slice(1);
1582
+ if (t.endsWith("|") && !t.endsWith("\\|"))
1583
+ t = t.slice(0, -1);
1584
+ return t.split(/(?<!\\)\|/).map((c) => c.trim().replace(/\\\|/g, "|"));
1585
+ }
1586
+ var TABLE_SEP = /^\s*\|?\s*:?-+:?\s*(\|\s*:?-+:?\s*)*\|?\s*$/;
1587
+ function readMarkdown(src) {
1588
+ const lines = src.replace(/^\uFEFF/, "").split(/\r?\n/);
1589
+ const notes = [];
1590
+ const meta = {};
1591
+ let title;
1592
+ let start = 0;
1593
+ if (lines[0]?.trim() === "---") {
1594
+ const end = lines.findIndex((l, i) => i > 0 && (l.trim() === "---" || l.trim() === "..."));
1595
+ if (end > 0) {
1596
+ start = end + 1;
1597
+ try {
1598
+ const fm = (0, import_yaml.parse)(lines.slice(1, end).join("\n"), { schema: "failsafe" });
1599
+ if (fm && typeof fm === "object" && !Array.isArray(fm)) {
1600
+ const o = fm;
1601
+ title = str(o.title);
1602
+ const version = str(o.version);
1603
+ const author = str(o.author ?? o.authors);
1604
+ const date = isoDate(str(o.date));
1605
+ if (version)
1606
+ meta.version = version;
1607
+ if (author)
1608
+ meta.author = author;
1609
+ if (date)
1610
+ meta.date = date;
1611
+ }
1612
+ } catch {
1613
+ notes.push("The front matter could not be read, so its fields were skipped.");
1614
+ }
1615
+ }
1616
+ }
1617
+ const s = new Sections();
1618
+ const tables = [];
1619
+ let fence;
1620
+ let table;
1621
+ let prevPara = false;
1622
+ for (let i = start; i < lines.length; i++) {
1623
+ const l = lines[i];
1624
+ const lineNo = i + 1;
1625
+ if (fence) {
1626
+ s.add(l, lineNo);
1627
+ const close = /^ {0,3}(`{3,}|~{3,})\s*$/.exec(l);
1628
+ if (close && close[1][0] === fence.char && close[1].length >= fence.len)
1629
+ fence = void 0;
1630
+ prevPara = false;
1631
+ continue;
1632
+ }
1633
+ const open = /^ {0,3}(`{3,}|~{3,})/.exec(l);
1634
+ if (open) {
1635
+ fence = { char: open[1][0], len: open[1].length };
1636
+ table = void 0;
1637
+ s.add(l, lineNo);
1638
+ prevPara = false;
1639
+ continue;
1640
+ }
1641
+ const atx = /^ {0,3}(#{1,6})(?:[ \t]+(.*?))?(?:[ \t]+#+)?[ \t]*$/.exec(l);
1642
+ if (atx) {
1643
+ s.heading((atx[2] ?? "").trim(), atx[1].length, { line: lineNo });
1644
+ table = void 0;
1645
+ prevPara = false;
1646
+ continue;
1647
+ }
1648
+ const setext = /^ {0,3}(=+|-+)[ \t]*$/.exec(l);
1649
+ if (setext && prevPara) {
1650
+ const text = s.popLine();
1651
+ s.heading((text ?? "").trim(), setext[1][0] === "=" ? 1 : 2, { line: lineNo - 1 });
1652
+ prevPara = false;
1653
+ continue;
1654
+ }
1655
+ const next = lines[i + 1] ?? "";
1656
+ if (table) {
1657
+ if (l.trim() && l.includes("|")) {
1658
+ if (!TABLE_SEP.test(l))
1659
+ table.push(tableCells(l));
1660
+ } else
1661
+ table = void 0;
1662
+ } else if (l.includes("|") && next.includes("-") && TABLE_SEP.test(next)) {
1663
+ table = [tableCells(l)];
1664
+ tables.push(table);
1665
+ }
1666
+ s.add(l, lineNo);
1667
+ prevPara = !!l.trim() && !table;
1668
+ }
1669
+ return { ...title ? { title } : {}, sections: s.done(), tables, meta, notes };
1670
+ }
1671
+ function readPlainText(src) {
1672
+ const s = new Sections();
1673
+ src.replace(/^\uFEFF/, "").split(/\r\n|\r|\n/).forEach((l, i) => s.add(l, i + 1));
1674
+ return { sections: s.done(), tables: [], meta: {}, notes: [] };
1675
+ }
1676
+ var HTML_ENTITIES = {
1677
+ lt: "<",
1678
+ gt: ">",
1679
+ amp: "&",
1680
+ quot: '"',
1681
+ apos: "'",
1682
+ nbsp: " ",
1683
+ ndash: "\u2013",
1684
+ mdash: "\u2014",
1685
+ hellip: "\u2026",
1686
+ lsquo: "\u2018",
1687
+ rsquo: "\u2019",
1688
+ ldquo: "\u201C",
1689
+ rdquo: "\u201D",
1690
+ laquo: "\xAB",
1691
+ raquo: "\xBB",
1692
+ bull: "\u2022",
1693
+ middot: "\xB7",
1694
+ copy: "\xA9",
1695
+ reg: "\xAE",
1696
+ trade: "\u2122",
1697
+ deg: "\xB0",
1698
+ times: "\xD7",
1699
+ euro: "\u20AC",
1700
+ pound: "\xA3",
1701
+ aacute: "\xE1",
1702
+ agrave: "\xE0",
1703
+ acirc: "\xE2",
1704
+ auml: "\xE4",
1705
+ aring: "\xE5",
1706
+ ccedil: "\xE7",
1707
+ eacute: "\xE9",
1708
+ egrave: "\xE8",
1709
+ ecirc: "\xEA",
1710
+ euml: "\xEB",
1711
+ iacute: "\xED",
1712
+ iuml: "\xEF",
1713
+ ntilde: "\xF1",
1714
+ oacute: "\xF3",
1715
+ ocirc: "\xF4",
1716
+ ouml: "\xF6",
1717
+ oslash: "\xF8",
1718
+ uacute: "\xFA",
1719
+ uuml: "\xFC",
1720
+ szlig: "\xDF"
1721
+ };
1722
+ var BLOCK = new Set("p div br li ul ol dl dt dd tr table thead tbody tfoot section article header footer nav main aside blockquote pre hr figure figcaption form fieldset address caption h1 h2 h3 h4 h5 h6".split(" "));
1723
+ var blank = (m) => m.replace(/[^\n]/g, "");
1724
+ function readHtml(src) {
1725
+ const meta = {};
1726
+ const titleM = /<title\b[^>]*>([\s\S]*?)<\/title>/i.exec(src);
1727
+ const title = titleM ? decodeEntities(titleM[1].replace(/<[^>]*>/g, " "), HTML_ENTITIES).replace(/\s+/g, " ").trim() : void 0;
1728
+ for (const m of src.matchAll(/<meta\b[^>]*>/gi)) {
1729
+ const tag2 = m[0];
1730
+ const name = /\b(?:name|property)\s*=\s*["']([^"']+)["']/i.exec(tag2)?.[1]?.toLowerCase();
1731
+ const content = /\bcontent\s*=\s*["']([^"']*)["']/i.exec(tag2)?.[1];
1732
+ if (!name || content === void 0)
1733
+ continue;
1734
+ const value = decodeEntities(content, HTML_ENTITIES).trim();
1735
+ if (name === "author" && value)
1736
+ meta.author ??= value;
1737
+ if (["date", "dcterms.date", "article:published_time"].includes(name))
1738
+ meta.date ??= isoDate(value);
1739
+ }
1740
+ if (!meta.date)
1741
+ delete meta.date;
1742
+ const clean = src.replace(/<!--[\s\S]*?-->/g, blank).replace(/<!\[CDATA\[[\s\S]*?\]\]>/g, blank).replace(/<![^>]*>|<\?[\s\S]*?\?>/g, blank).replace(/<(script|style|noscript|template|svg)\b[\s\S]*?<\/\1\s*>/gi, blank).replace(/<head\b[\s\S]*?<\/head\s*>/gi, blank);
1743
+ const s = new Sections();
1744
+ const tables = [];
1745
+ let line = "";
1746
+ let lineStart;
1747
+ let heading;
1748
+ let table;
1749
+ let row;
1750
+ let cell;
1751
+ let pos = 0;
1752
+ let lineNo = 1;
1753
+ const lineAt = (to) => {
1754
+ for (; pos < to; pos++)
1755
+ if (clean.charCodeAt(pos) === 10)
1756
+ lineNo++;
1757
+ return lineNo;
1758
+ };
1759
+ const flush = () => {
1760
+ const t = line.replace(/\s+/g, " ").trim();
1761
+ if (t)
1762
+ s.add(t, lineStart);
1763
+ line = "";
1764
+ lineStart = void 0;
1765
+ };
1766
+ const tag = /<(\/?)([a-zA-Z][a-zA-Z0-9]*)\b[^>]*>/g;
1767
+ let last = 0;
1768
+ const text = (raw, at) => {
1769
+ const t = decodeEntities(raw, HTML_ENTITIES);
1770
+ if (heading)
1771
+ heading.text += t;
1772
+ else if (cell !== void 0)
1773
+ cell += t;
1774
+ else if (table)
1775
+ return;
1776
+ else {
1777
+ if (t.trim() && lineStart === void 0)
1778
+ lineStart = lineAt(at + raw.search(/\S/));
1779
+ line += t;
1780
+ }
1781
+ };
1782
+ for (let m = tag.exec(clean); m; m = tag.exec(clean)) {
1783
+ text(clean.slice(last, m.index), last);
1784
+ last = tag.lastIndex;
1785
+ const close = m[1] === "/";
1786
+ const name = m[2].toLowerCase();
1787
+ const h = /^h([1-6])$/.exec(name);
1788
+ if (h) {
1789
+ if (!close) {
1790
+ flush();
1791
+ heading = { level: Number(h[1]), text: "", line: lineAt(m.index) };
1792
+ } else if (heading) {
1793
+ s.heading(heading.text.replace(/\s+/g, " ").trim(), heading.level, { line: heading.line });
1794
+ heading = void 0;
1795
+ }
1796
+ continue;
1797
+ }
1798
+ if (name === "table") {
1799
+ flush();
1800
+ if (!close) {
1801
+ table = [];
1802
+ tables.push(table);
1803
+ } else
1804
+ table = void 0;
1805
+ continue;
1806
+ }
1807
+ if (table && name === "tr") {
1808
+ if (!close)
1809
+ row = [];
1810
+ else if (row) {
1811
+ if (row.length) {
1812
+ table.push(row);
1813
+ s.add(row.join(" "));
1814
+ }
1815
+ row = void 0;
1816
+ }
1817
+ continue;
1818
+ }
1819
+ if (table && (name === "td" || name === "th")) {
1820
+ if (!close)
1821
+ cell = "";
1822
+ else if (cell !== void 0) {
1823
+ row?.push(cell.replace(/\s+/g, " ").trim());
1824
+ cell = void 0;
1825
+ }
1826
+ continue;
1827
+ }
1828
+ if (name === "br" && heading)
1829
+ heading.text += " ";
1830
+ else if (name === "br" && cell !== void 0)
1831
+ cell += " ";
1832
+ else if (BLOCK.has(name) && !heading && cell === void 0)
1833
+ flush();
1834
+ }
1835
+ text(clean.slice(last), last);
1836
+ flush();
1837
+ return {
1838
+ ...title ? { title } : {},
1839
+ sections: s.done(),
1840
+ tables: tables.filter((t) => t.length),
1841
+ meta,
1842
+ notes: []
1843
+ };
1844
+ }
1845
+
1846
+ // packages/ingestors/dist/office.js
1847
+ function coreProps(zip) {
1848
+ const doc = parseXmlTree(zip.text("docProps/core.xml") ?? "");
1849
+ const get = (name) => {
1850
+ const t = textOf(child(doc, name)).trim();
1851
+ return t || void 0;
1852
+ };
1853
+ const meta = {};
1854
+ const author = get("creator");
1855
+ const version = get("version");
1856
+ const date = isoDate(get("modified")) ?? isoDate(get("created"));
1857
+ if (author)
1858
+ meta.author = author;
1859
+ if (version)
1860
+ meta.version = version;
1861
+ if (date)
1862
+ meta.date = date;
1863
+ const title = get("title");
1864
+ return { ...title ? { title } : {}, meta };
1865
+ }
1866
+ function need(zip, part) {
1867
+ const text = zip.text(part);
1868
+ if (text === void 0)
1869
+ throw new ReadError(`${part} is missing`);
1870
+ const doc = parseXmlTree(text);
1871
+ if (!doc)
1872
+ throw new ReadError(`${part} is not XML`);
1873
+ return doc;
1874
+ }
1875
+ function wordText(p) {
1876
+ let out = "";
1877
+ const walk = (n) => {
1878
+ for (const c of elements(n)) {
1879
+ if (c.name === "t")
1880
+ out += textOf(c);
1881
+ else if (c.name === "tab")
1882
+ out += " ";
1883
+ else if (c.name === "br" || c.name === "cr")
1884
+ out += "\n";
1885
+ else if (c.name === "noBreakHyphen")
1886
+ out += "-";
1887
+ else if (c.name !== "pPr" && c.name !== "rPr" && c.name !== "del")
1888
+ walk(c);
1889
+ }
1890
+ };
1891
+ walk(p);
1892
+ return out;
1893
+ }
1894
+ function wordStyles(zip) {
1895
+ const levels = /* @__PURE__ */ new Map();
1896
+ const doc = parseXmlTree(zip.text("word/styles.xml") ?? "");
1897
+ for (const s of childrenNamed(doc, "style")) {
1898
+ const id = attr(s, "styleId");
1899
+ if (!id)
1900
+ continue;
1901
+ const name = (attr(child(s, "name") ?? s, "val") ?? "").toLowerCase();
1902
+ const outline = attr(child(child(s, "pPr"), "outlineLvl") ?? s, "val");
1903
+ const h = /^heading (\d)$/.exec(name) ?? /^Heading(\d)$/.exec(id);
1904
+ if (name === "title" || id === "Title")
1905
+ levels.set(id, 0);
1906
+ else if (h)
1907
+ levels.set(id, Number(h[1]));
1908
+ else if (outline !== void 0 && /^\d$/.test(outline))
1909
+ levels.set(id, Number(outline) + 1);
1910
+ }
1911
+ return levels;
1912
+ }
1913
+ function readDocx(zip) {
1914
+ const doc = need(zip, "word/document.xml");
1915
+ const levels = wordStyles(zip);
1916
+ const { title, meta } = coreProps(zip);
1917
+ const s = new Sections();
1918
+ const tables = [];
1919
+ const levelOf = (p) => {
1920
+ const pPr = child(p, "pPr");
1921
+ const pStyle = child(pPr, "pStyle");
1922
+ const style = pStyle ? attr(pStyle, "val") : void 0;
1923
+ if (style && levels.has(style))
1924
+ return levels.get(style);
1925
+ const style2 = style ? /^Heading(\d)$/.exec(style) : null;
1926
+ if (style2)
1927
+ return Number(style2[1]);
1928
+ const outline = child(pPr, "outlineLvl");
1929
+ const v = outline ? attr(outline, "val") : void 0;
1930
+ return v !== void 0 && /^\d$/.test(v) ? Number(v) + 1 : void 0;
1931
+ };
1932
+ const block = (container) => {
1933
+ for (const el of elements(container)) {
1934
+ if (el.name === "p") {
1935
+ const text = wordText(el);
1936
+ const level = levelOf(el);
1937
+ if (level !== void 0 && text.trim())
1938
+ s.heading(text.trim(), level);
1939
+ else if (text.trim())
1940
+ s.add(text);
1941
+ } else if (el.name === "tbl") {
1942
+ const rows = findAll(el, "tr").map((tr) => findAll(tr, "tc").map((tc) => findAll(tc, "p").map(wordText).map((t) => t.trim()).filter(Boolean).join(" ")));
1943
+ if (rows.length) {
1944
+ tables.push(rows);
1945
+ for (const r of rows)
1946
+ s.add(r.join(" "));
1947
+ }
1948
+ } else if (el.name === "sdt")
1949
+ block(child(el, "sdtContent"));
1950
+ else if (el.name === "customXml" || el.name === "smartTag")
1951
+ block(el);
1952
+ }
1953
+ };
1954
+ block(child(doc, "body"));
1955
+ return { ...title ? { title } : {}, sections: s.done(), tables, meta, notes: [] };
1956
+ }
1957
+ function drawingParagraphs(body) {
1958
+ return findAll(body, "p").map((p) => {
1959
+ let out = "";
1960
+ const walk = (n) => {
1961
+ for (const c of elements(n)) {
1962
+ if (c.name === "t")
1963
+ out += textOf(c);
1964
+ else if (c.name === "br")
1965
+ out += "\n";
1966
+ else if (c.name === "tab")
1967
+ out += " ";
1968
+ else if (c.name !== "pPr" && c.name !== "rPr" && c.name !== "endParaRPr")
1969
+ walk(c);
1970
+ }
1971
+ };
1972
+ walk(p);
1973
+ return out;
1974
+ });
1975
+ }
1976
+ function slideParts(zip) {
1977
+ const rels = relationships(zip.text("ppt/_rels/presentation.xml.rels"));
1978
+ const pres = parseXmlTree(zip.text("ppt/presentation.xml") ?? "");
1979
+ const parts = [];
1980
+ for (const id of findAll(child(pres, "sldIdLst"), "sldId")) {
1981
+ const target = rels.get(relId(id) ?? "");
1982
+ if (target)
1983
+ parts.push(resolvePart("ppt", target));
1984
+ }
1985
+ const num = (n) => Number(/slide(\d+)\.xml$/.exec(n)?.[1] ?? 0);
1986
+ const rest = zip.names.filter((n) => /^ppt\/slides\/slide\d+\.xml$/.test(n) && !parts.includes(n)).sort((a, b) => num(a) - num(b));
1987
+ return [...parts, ...rest].filter((p) => zip.has(p));
1988
+ }
1989
+ function readPptx(zip) {
1990
+ const parts = slideParts(zip);
1991
+ if (!parts.length && !zip.has("ppt/presentation.xml"))
1992
+ throw new ReadError("ppt/presentation.xml is missing");
1993
+ const { title, meta } = coreProps(zip);
1994
+ const s = new Sections();
1995
+ const tables = [];
1996
+ parts.forEach((part, i) => {
1997
+ const doc = parseXmlTree(zip.text(part) ?? "");
1998
+ let heading = "";
1999
+ const lines = [];
2000
+ const walk = (n) => {
2001
+ for (const c of elements(n)) {
2002
+ if (c.name === "sp") {
2003
+ const ph = findAll(child(c, "nvSpPr"), "ph")[0];
2004
+ const type = ph?.attrs.type;
2005
+ const paras = drawingParagraphs(child(c, "txBody"));
2006
+ if ((type === "title" || type === "ctrTitle") && !heading)
2007
+ heading = paras.join(" ").replace(/\s+/g, " ").trim();
2008
+ else
2009
+ lines.push(...paras.filter((p) => p.trim()));
2010
+ } else if (c.name === "graphicFrame") {
2011
+ for (const tbl of findAll(c, "tbl")) {
2012
+ const rows = findAll(tbl, "tr").map((tr) => findAll(tr, "tc").map((tc) => drawingParagraphs(child(tc, "txBody")).map((t) => t.trim()).filter(Boolean).join(" ")));
2013
+ if (rows.length) {
2014
+ tables.push(rows);
2015
+ lines.push(...rows.map((r) => r.join(" ")));
2016
+ }
2017
+ }
2018
+ } else
2019
+ walk(c);
2020
+ }
2021
+ };
2022
+ const tree = child(child(doc, "cSld"), "spTree") ?? doc;
2023
+ if (tree)
2024
+ walk(tree);
2025
+ s.heading(heading, 1, { page: i + 1 });
2026
+ for (const l of lines)
2027
+ s.add(l);
2028
+ });
2029
+ return { ...title ? { title } : {}, sections: s.done(), tables, meta, notes: [] };
2030
+ }
2031
+ var colIndex = (ref2) => {
2032
+ const letters = /^[A-Z]+/i.exec(ref2)?.[0].toUpperCase() ?? "";
2033
+ let n = 0;
2034
+ for (const ch of letters)
2035
+ n = n * 26 + (ch.charCodeAt(0) - 64);
2036
+ return n - 1;
2037
+ };
2038
+ var stringItem = (si) => elements(si).flatMap((c) => c.name === "t" ? [c] : c.name === "r" ? childrenNamed(c, "t") : []).map(textOf).join("");
2039
+ function readXlsx(zip) {
2040
+ const wb = need(zip, "xl/workbook.xml");
2041
+ const rels = relationships(zip.text("xl/_rels/workbook.xml.rels"));
2042
+ const shared = childrenNamed(parseXmlTree(zip.text("xl/sharedStrings.xml") ?? ""), "si").map(stringItem);
2043
+ const { title, meta } = coreProps(zip);
2044
+ const s = new Sections();
2045
+ const tables = [];
2046
+ findAll(child(wb, "sheets"), "sheet").forEach((sheet, i) => {
2047
+ const target = rels.get(relId(sheet) ?? "");
2048
+ const part = target ? resolvePart("xl", target) : void 0;
2049
+ const doc = part ? parseXmlTree(zip.text(part) ?? "") : void 0;
2050
+ const rows = [];
2051
+ let prev;
2052
+ for (const row of findAll(child(doc, "sheetData"), "row")) {
2053
+ const r = Number(row.attrs.r) || (prev ?? 0) + 1;
2054
+ if (prev !== void 0)
2055
+ for (let k = prev + 1; k < r; k++)
2056
+ rows.push([]);
2057
+ prev = r;
2058
+ const cells2 = [];
2059
+ let next = 0;
2060
+ for (const c of childrenNamed(row, "c")) {
2061
+ const at = c.attrs.r ? colIndex(c.attrs.r) : next;
2062
+ const v = textOf(child(c, "v"));
2063
+ let value;
2064
+ switch (c.attrs.t) {
2065
+ case "s":
2066
+ value = shared[Number(v)] ?? "";
2067
+ break;
2068
+ case "inlineStr":
2069
+ value = stringItem(child(c, "is"));
2070
+ break;
2071
+ case "b":
2072
+ value = v === "1" ? "TRUE" : v === "0" ? "FALSE" : v;
2073
+ break;
2074
+ default:
2075
+ value = v;
2076
+ }
2077
+ while (cells2.length < at)
2078
+ cells2.push("");
2079
+ cells2[at] = value;
2080
+ next = at + 1;
2081
+ }
2082
+ while (cells2.length && cells2.at(-1) === "")
2083
+ cells2.pop();
2084
+ rows.push(cells2);
2085
+ }
2086
+ tables.push(rows);
2087
+ s.heading(sheet.attrs.name ?? `Sheet ${i + 1}`, 1, { page: i + 1 });
2088
+ for (const r of rows)
2089
+ s.add(r.join(" "));
2090
+ });
2091
+ return { ...title ? { title } : {}, sections: s.done(), tables, meta, notes: [] };
2092
+ }
2093
+
2094
+ // packages/ingestors/dist/pdf.js
2095
+ import { constants, inflateSync } from "node:zlib";
2096
+ var NO_TEXT = "No text was found in this PDF. It may be a scanned image, so a person needs to read it.";
2097
+ var MAX_STREAM = 64 * 1024 * 1024;
2098
+ var refs = (s) => [...s.matchAll(/(\d+)\s+\d+\s+R\b/g)].map((m) => Number(m[1]));
2099
+ var ref = (dict, key) => {
2100
+ const m = new RegExp(`/${key}\\s+(\\d+)\\s+\\d+\\s+R\\b`).exec(dict);
2101
+ return m ? Number(m[1]) : void 0;
2102
+ };
2103
+ var isType = (dict, type) => new RegExp(`/Type\\s*/${type}(?![A-Za-z])`).test(dict);
2104
+ function decodeStream(o) {
2105
+ if (!o.stream)
2106
+ return void 0;
2107
+ const filter = /\/Filter\s*(\[[^\]]*\]|\/\w+)/.exec(o.dict)?.[1];
2108
+ if (!filter)
2109
+ return o.stream;
2110
+ const names = filter.match(/\/\w+/g) ?? [];
2111
+ if (names.length !== 1 || names[0] !== "/FlateDecode")
2112
+ return void 0;
2113
+ try {
2114
+ return inflateSync(o.stream, { maxOutputLength: MAX_STREAM });
2115
+ } catch {
2116
+ try {
2117
+ return inflateSync(o.stream, {
2118
+ finishFlush: constants.Z_SYNC_FLUSH,
2119
+ maxOutputLength: MAX_STREAM
2120
+ });
2121
+ } catch {
2122
+ return void 0;
2123
+ }
2124
+ }
2125
+ }
2126
+ function objects(src, bytes) {
2127
+ const out = /* @__PURE__ */ new Map();
2128
+ const re = /(\d+)\s+(\d+)\s+obj\b/g;
2129
+ for (let m = re.exec(src); m; m = re.exec(src)) {
2130
+ const start = re.lastIndex;
2131
+ const end = src.indexOf("endobj", start);
2132
+ const body = src.slice(start, end < 0 ? src.length : end);
2133
+ const s = /\bstream\r?\n/.exec(body);
2134
+ const obj = { dict: s ? body.slice(0, s.index) : body };
2135
+ if (s) {
2136
+ const dataStart = start + s.index + s[0].length;
2137
+ const len = /\/Length\s+(\d+)(?!\s+\d+\s+R)/.exec(obj.dict);
2138
+ let dataEnd = -1;
2139
+ if (len) {
2140
+ const e = dataStart + Number(len[1]);
2141
+ if (/^\s*endstream/.test(src.slice(e, e + 30)))
2142
+ dataEnd = e;
2143
+ }
2144
+ if (dataEnd < 0) {
2145
+ const es = src.indexOf("endstream", dataStart);
2146
+ dataEnd = es < 0 ? dataStart : es;
2147
+ while (dataEnd > dataStart && (src[dataEnd - 1] === "\n" || src[dataEnd - 1] === "\r"))
2148
+ dataEnd--;
2149
+ }
2150
+ obj.stream = bytes.subarray(dataStart, dataEnd);
2151
+ }
2152
+ out.set(Number(m[1]), obj);
2153
+ if (end > 0)
2154
+ re.lastIndex = end;
2155
+ }
2156
+ for (const o of [...out.values()]) {
2157
+ if (!isType(o.dict, "ObjStm"))
2158
+ continue;
2159
+ const data = decodeStream(o)?.toString("latin1");
2160
+ const n = Number(/\/N\s+(\d+)/.exec(o.dict)?.[1] ?? 0);
2161
+ const first = Number(/\/First\s+(\d+)/.exec(o.dict)?.[1] ?? 0);
2162
+ if (!data || !n)
2163
+ continue;
2164
+ const head = data.slice(0, first).trim().split(/\s+/).map(Number);
2165
+ for (let k = 0; k < n; k++) {
2166
+ const num = head[2 * k];
2167
+ const off = first + head[2 * k + 1];
2168
+ const nextOff = k + 1 < n ? first + head[2 * k + 3] : data.length;
2169
+ if (!out.has(num))
2170
+ out.set(num, { dict: data.slice(off, nextOff) });
2171
+ }
2172
+ }
2173
+ return out;
2174
+ }
2175
+ function literalBytes(s) {
2176
+ const out = [];
2177
+ for (let i = 0; i < s.length; i++) {
2178
+ const c = s[i];
2179
+ if (c !== "\\") {
2180
+ out.push(c.charCodeAt(0) & 255);
2181
+ continue;
2182
+ }
2183
+ const n = s[++i];
2184
+ if (n === void 0)
2185
+ break;
2186
+ const simple = { n: 10, r: 13, t: 9, b: 8, f: 12 };
2187
+ if (n in simple)
2188
+ out.push(simple[n]);
2189
+ else if (/[0-7]/.test(n)) {
2190
+ let oct = n;
2191
+ while (oct.length < 3 && /[0-7]/.test(s[i + 1] ?? ""))
2192
+ oct += s[++i];
2193
+ out.push(parseInt(oct, 8) & 255);
2194
+ } else if (n === "\r") {
2195
+ if (s[i + 1] === "\n")
2196
+ i++;
2197
+ } else if (n !== "\n")
2198
+ out.push(n.charCodeAt(0) & 255);
2199
+ }
2200
+ return out;
2201
+ }
2202
+ function bytesText(b) {
2203
+ let s;
2204
+ if (b[0] === 254 && b[1] === 255) {
2205
+ s = "";
2206
+ for (let i = 2; i + 1 < b.length; i += 2)
2207
+ s += String.fromCharCode(b[i] << 8 | b[i + 1]);
2208
+ } else
2209
+ s = String.fromCharCode(...b);
2210
+ let out = "";
2211
+ for (const ch of s) {
2212
+ const c = ch.charCodeAt(0);
2213
+ if (c >= 32 ? c !== 127 : c === 9 || c === 10 || c === 13)
2214
+ out += ch;
2215
+ }
2216
+ return out;
2217
+ }
2218
+ function readLiteral(src, i) {
2219
+ let depth = 1;
2220
+ let k = i;
2221
+ for (; k < src.length; k++) {
2222
+ const c = src[k];
2223
+ if (c === "\\")
2224
+ k++;
2225
+ else if (c === "(")
2226
+ depth++;
2227
+ else if (c === ")" && --depth === 0)
2228
+ break;
2229
+ }
2230
+ return [src.slice(i, k), k + 1];
2231
+ }
2232
+ function hexBytes(h) {
2233
+ const clean = h.replace(/[^0-9a-fA-F]/g, "");
2234
+ const even = clean.length % 2 ? clean + "0" : clean;
2235
+ const out = [];
2236
+ for (let i = 0; i < even.length; i += 2)
2237
+ out.push(parseInt(even.slice(i, i + 2), 16));
2238
+ return out;
2239
+ }
2240
+ function contentText(src) {
2241
+ const lines = [];
2242
+ let cur = "";
2243
+ const newline = () => {
2244
+ if (cur.trim())
2245
+ lines.push(cur.replace(/\s+/g, " ").trim());
2246
+ cur = "";
2247
+ };
2248
+ const show = (tok) => {
2249
+ if (tok?.t === "str")
2250
+ cur += bytesText(tok.v);
2251
+ else if (tok?.t === "arr")
2252
+ for (const x of tok.v) {
2253
+ if (x.t === "str")
2254
+ cur += bytesText(x.v);
2255
+ else if (x.t === "num" && x.v < -200)
2256
+ cur += " ";
2257
+ }
2258
+ };
2259
+ const stack = [];
2260
+ const arrays = [];
2261
+ const push = (tok) => arrays.length ? arrays.at(-1).push(tok) : stack.push(tok);
2262
+ let lastY;
2263
+ let i = 0;
2264
+ while (i < src.length) {
2265
+ const c = src[i];
2266
+ if (/\s/.test(c)) {
2267
+ i++;
2268
+ } else if (c === "%") {
2269
+ const e = src.indexOf("\n", i);
2270
+ i = e < 0 ? src.length : e + 1;
2271
+ } else if (c === "(") {
2272
+ const [body, next] = readLiteral(src, i + 1);
2273
+ push({ t: "str", v: literalBytes(body) });
2274
+ i = next;
2275
+ } else if (c === "<" && src[i + 1] === "<") {
2276
+ i += 2;
2277
+ } else if (c === ">" && src[i + 1] === ">") {
2278
+ i += 2;
2279
+ } else if (c === "<") {
2280
+ const e = src.indexOf(">", i);
2281
+ push({ t: "str", v: hexBytes(src.slice(i + 1, e < 0 ? src.length : e)) });
2282
+ i = e < 0 ? src.length : e + 1;
2283
+ } else if (c === "[") {
2284
+ arrays.push([]);
2285
+ i++;
2286
+ } else if (c === "]") {
2287
+ const a = arrays.pop() ?? [];
2288
+ push({ t: "arr", v: a });
2289
+ i++;
2290
+ } else if (c === "/") {
2291
+ const m = /^\/[^\s/[\]()<>{}%]*/.exec(src.slice(i, i + 128));
2292
+ push({ t: "other" });
2293
+ i += m[0].length;
2294
+ } else {
2295
+ const m = /^[+-]?(\d+\.?\d*|\.\d+)/.exec(src.slice(i, i + 32));
2296
+ if (m) {
2297
+ push({ t: "num", v: Number(m[0]) });
2298
+ i += m[0].length;
2299
+ continue;
2300
+ }
2301
+ const w = /^[A-Za-z'"*0-9]+/.exec(src.slice(i, i + 32));
2302
+ const op = w ? w[0] : c;
2303
+ i += op.length;
2304
+ const num = (k) => {
2305
+ const t = stack[stack.length - k];
2306
+ return t?.t === "num" ? t.v : 0;
2307
+ };
2308
+ switch (op) {
2309
+ case "BT":
2310
+ case "ET":
2311
+ case "T*":
2312
+ newline();
2313
+ break;
2314
+ case "Td":
2315
+ case "TD":
2316
+ if (num(1) !== 0)
2317
+ newline();
2318
+ break;
2319
+ case "Tm": {
2320
+ const y = num(1);
2321
+ if (lastY !== void 0 && y !== lastY)
2322
+ newline();
2323
+ lastY = y;
2324
+ break;
2325
+ }
2326
+ case "Tj":
2327
+ case "TJ":
2328
+ show(stack.at(-1));
2329
+ break;
2330
+ case "'":
2331
+ newline();
2332
+ show(stack.at(-1));
2333
+ break;
2334
+ case '"':
2335
+ newline();
2336
+ show(stack.at(-1));
2337
+ break;
2338
+ case "ID": {
2339
+ const e = src.slice(i).search(/\sEI(\s|$)/);
2340
+ i = e < 0 ? src.length : i + e + 3;
2341
+ break;
2342
+ }
2343
+ }
2344
+ if (op === "BT")
2345
+ lastY = void 0;
2346
+ stack.length = 0;
2347
+ }
2348
+ }
2349
+ newline();
2350
+ return lines;
2351
+ }
2352
+ function dictString(dict, key) {
2353
+ const m = new RegExp(`/${key}\\s*([(<])`).exec(dict);
2354
+ if (!m)
2355
+ return void 0;
2356
+ const at = m.index + m[0].length;
2357
+ if (m[1] === "(")
2358
+ return bytesText(literalBytes(readLiteral(dict, at)[0])).trim() || void 0;
2359
+ const e = dict.indexOf(">", at);
2360
+ return bytesText(hexBytes(dict.slice(at, e < 0 ? dict.length : e))).trim() || void 0;
2361
+ }
2362
+ function pdfDate(s) {
2363
+ const m = s ? /^(?:D:)?(\d{4})(\d{2})?(\d{2})?/.exec(s) : null;
2364
+ if (!m)
2365
+ return void 0;
2366
+ return `${m[1]}-${m[2] ?? "01"}-${m[3] ?? "01"}`;
2367
+ }
2368
+ function readPdf(bytes) {
2369
+ const buf = Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength);
2370
+ const src = buf.toString("latin1");
2371
+ const objs = objects(src, buf);
2372
+ const trailers = [...src.matchAll(/trailer\s*(<<[\s\S]*?>>)/g)].map((m) => m[1]);
2373
+ for (const o of objs.values())
2374
+ if (isType(o.dict, "XRef"))
2375
+ trailers.push(o.dict);
2376
+ const latestFirst = [...trailers].reverse();
2377
+ const trailerRef = (key) => {
2378
+ for (const t of latestFirst) {
2379
+ const r = ref(t, key);
2380
+ if (r !== void 0)
2381
+ return r;
2382
+ }
2383
+ return void 0;
2384
+ };
2385
+ const meta = {};
2386
+ const notes = [];
2387
+ if (trailers.some((t) => /\/Encrypt\b/.test(t))) {
2388
+ notes.push("This PDF is encrypted, so its text was not read. A person needs to read it.");
2389
+ return { sections: [], tables: [], meta: { flags: ["needs-reading"] }, notes };
2390
+ }
2391
+ const infoNo = trailerRef("Info");
2392
+ const info = infoNo !== void 0 ? objs.get(infoNo)?.dict : void 0;
2393
+ const title = info ? dictString(info, "Title") : void 0;
2394
+ if (info) {
2395
+ const author = dictString(info, "Author");
2396
+ const date = pdfDate(dictString(info, "ModDate")) ?? pdfDate(dictString(info, "CreationDate"));
2397
+ if (author)
2398
+ meta.author = author;
2399
+ if (date && /^\d{4}-\d{2}-\d{2}$/.test(date))
2400
+ meta.date = date;
2401
+ }
2402
+ const pages2 = [];
2403
+ let rootNo = trailerRef("Root");
2404
+ if (rootNo === void 0) {
2405
+ for (const [n, o] of objs)
2406
+ if (isType(o.dict, "Catalog"))
2407
+ rootNo ??= n;
2408
+ }
2409
+ const seen = /* @__PURE__ */ new Set();
2410
+ const walk = (n, depth) => {
2411
+ const o = objs.get(n);
2412
+ if (!o || seen.has(n) || depth > 64)
2413
+ return;
2414
+ seen.add(n);
2415
+ if (isType(o.dict, "Pages")) {
2416
+ const kids = /\/Kids\s*\[([^\]]*)\]/.exec(o.dict)?.[1] ?? "";
2417
+ for (const k of refs(kids))
2418
+ walk(k, depth + 1);
2419
+ } else if (isType(o.dict, "Page"))
2420
+ pages2.push(n);
2421
+ };
2422
+ const pagesRoot = rootNo !== void 0 ? ref(objs.get(rootNo)?.dict ?? "", "Pages") : void 0;
2423
+ if (pagesRoot !== void 0)
2424
+ walk(pagesRoot, 0);
2425
+ if (!pages2.length) {
2426
+ for (const [n, o] of [...objs].sort((a, b) => a[0] - b[0]))
2427
+ if (isType(o.dict, "Page"))
2428
+ pages2.push(n);
2429
+ }
2430
+ const s = new Sections();
2431
+ pages2.forEach((n, i) => {
2432
+ const dict = objs.get(n).dict;
2433
+ const contents = /\/Contents\s*(\[[^\]]*\]|\d+\s+\d+\s+R)/.exec(dict)?.[1] ?? "";
2434
+ let streams = refs(contents);
2435
+ if (streams.length === 1 && !objs.get(streams[0])?.stream)
2436
+ streams = refs(objs.get(streams[0])?.dict ?? "");
2437
+ const text = streams.map((r) => objs.get(r)).map((o) => o ? decodeStream(o)?.toString("latin1") : void 0).filter((t) => t !== void 0).flatMap(contentText);
2438
+ s.heading("", 0, { page: i + 1 });
2439
+ for (const l of text)
2440
+ s.add(l);
2441
+ });
2442
+ const sections = s.done();
2443
+ if (!sections.length) {
2444
+ notes.push(NO_TEXT);
2445
+ meta.flags = ["needs-reading"];
2446
+ }
2447
+ return { ...title ? { title } : {}, sections, tables: [], meta, notes };
2448
+ }
2449
+
2450
+ // packages/ingestors/dist/documents.js
2451
+ var BY_EXT = {
2452
+ ".md": "markdown",
2453
+ ".markdown": "markdown",
2454
+ ".html": "html",
2455
+ ".htm": "html",
2456
+ ".txt": "text",
2457
+ ".text": "text",
2458
+ ".docx": "docx",
2459
+ ".pptx": "pptx",
2460
+ ".xlsx": "xlsx",
2461
+ ".pdf": "pdf"
2462
+ };
2463
+ var DOC_TYPE = {
2464
+ markdown: "document",
2465
+ html: "document",
2466
+ text: "document",
2467
+ docx: "document",
2468
+ pptx: "presentation",
2469
+ xlsx: "spreadsheet",
2470
+ pdf: "document"
2471
+ };
2472
+ function officeFormat(head) {
2473
+ const peek = peekZip(head);
2474
+ if (!peek)
2475
+ return void 0;
2476
+ const text = `${peek.name}
2477
+ ${peek.content}`;
2478
+ if (/wordprocessingml|^word\//m.test(text))
2479
+ return "docx";
2480
+ if (/presentationml|^ppt\//m.test(text))
2481
+ return "pptx";
2482
+ if (/spreadsheetml|^xl\//m.test(text))
2483
+ return "xlsx";
2484
+ if (/ms-visio|^visio\//m.test(text))
2485
+ return "vsdx";
2486
+ return void 0;
2487
+ }
2488
+ function documentFormat(fileName, head) {
2489
+ const byExt = BY_EXT[extOf(fileName)];
2490
+ if (byExt)
2491
+ return byExt;
2492
+ if (new TextDecoder("latin1").decode(head.slice(0, 1024)).includes("%PDF-"))
2493
+ return "pdf";
2494
+ const office = officeFormat(head);
2495
+ return office && office !== "vsdx" ? office : void 0;
2496
+ }
2497
+ function parse(format, bytes, limits) {
2498
+ switch (format) {
2499
+ case "markdown":
2500
+ return readMarkdown(utf8(bytes));
2501
+ case "html":
2502
+ return readHtml(utf8(bytes));
2503
+ case "text":
2504
+ return readPlainText(utf8(bytes));
2505
+ case "pdf":
2506
+ return readPdf(bytes);
2507
+ case "docx":
2508
+ return readDocx(readZip(bytes, limits));
2509
+ case "pptx":
2510
+ return readPptx(readZip(bytes, limits));
2511
+ case "xlsx":
2512
+ return readXlsx(readZip(bytes, limits));
2513
+ }
2514
+ }
2515
+ var HEADING_TITLE = /* @__PURE__ */ new Set(["markdown", "html", "docx", "pptx"]);
2516
+ function readDocument(fileName, bytes, limits = {}) {
2517
+ const format = documentFormat(fileName, bytes.slice(0, 4096));
2518
+ if (!format)
2519
+ throw new Error(`${fileBase(fileName)} is not a document type Atticus reads.`);
2520
+ let parsed;
2521
+ try {
2522
+ parsed = parse(format, bytes, limits);
2523
+ } catch (err) {
2524
+ if (!(err instanceof ZipError || err instanceof ReadError))
2525
+ throw err;
2526
+ parsed = {
2527
+ sections: [],
2528
+ tables: [],
2529
+ meta: {},
2530
+ notes: [`This file could not be read as a .${format}: ${err.message}.`]
2531
+ };
2532
+ }
2533
+ const firstHeading = HEADING_TITLE.has(format) ? parsed.sections.find((s) => s.heading)?.heading : void 0;
2534
+ const text = {
2535
+ title: parsed.title ?? firstHeading ?? stem(fileName),
2536
+ sections: parsed.sections,
2537
+ ...parsed.tables.length ? { tables: parsed.tables } : {}
2538
+ };
2539
+ return {
2540
+ format,
2541
+ record: sourceDocument(fileName, bytes, DOC_TYPE[format], "document", parsed.meta),
2542
+ text,
2543
+ notes: parsed.notes
2544
+ };
2545
+ }
2546
+
2547
+ // packages/ingestors/dist/image.js
2548
+ var NEEDS_READING_FLAG = "needs-reading";
2549
+ var REASON = "Edges in a picture are read later, by AI or a person, and each edge is asserted only after a person confirms it.";
2550
+ var EXT = {
2551
+ ".png": "png",
2552
+ ".jpg": "jpeg",
2553
+ ".jpeg": "jpeg",
2554
+ ".gif": "gif",
2555
+ ".webp": "webp",
2556
+ ".svg": "svg"
2557
+ };
2558
+ var IMAGE_EXTENSIONS = Object.keys(EXT);
2559
+ function imageFormat(head) {
2560
+ const b = head;
2561
+ const ascii = (from, to) => String.fromCharCode(...b.slice(from, to));
2562
+ if (b.length >= 8 && b[0] === 137 && ascii(1, 4) === "PNG" && b[4] === 13 && b[5] === 10)
2563
+ return "png";
2564
+ if (b.length >= 3 && b[0] === 255 && b[1] === 216 && b[2] === 255)
2565
+ return "jpeg";
2566
+ if (b.length >= 6 && /^GIF8[79]a$/.test(ascii(0, 6)))
2567
+ return "gif";
2568
+ if (b.length >= 12 && ascii(0, 4) === "RIFF" && ascii(8, 12) === "WEBP")
2569
+ return "webp";
2570
+ const text = new TextDecoder().decode(b.slice(0, 1024));
2571
+ if (/^\s*(<\?xml[^>]*\?>\s*)?(<!--[\s\S]*?-->\s*|<!DOCTYPE[^>]*>\s*)*<svg[\s>]/i.test(text))
2572
+ return "svg";
2573
+ return void 0;
2574
+ }
2575
+ function size(format, b) {
2576
+ const be16 = (i) => b[i] << 8 | b[i + 1];
2577
+ const le16 = (i) => b[i] | b[i + 1] << 8;
2578
+ const le24 = (i) => b[i] | b[i + 1] << 8 | b[i + 2] << 16;
2579
+ const be32 = (i) => (b[i] << 24 | b[i + 1] << 16 | b[i + 2] << 8 | b[i + 3]) >>> 0;
2580
+ try {
2581
+ if (format === "png" && b.length >= 24)
2582
+ return { width: be32(16), height: be32(20) };
2583
+ if (format === "gif" && b.length >= 10)
2584
+ return { width: le16(6), height: le16(8) };
2585
+ if (format === "jpeg") {
2586
+ for (let i = 2; i + 9 < b.length; ) {
2587
+ if (b[i] !== 255)
2588
+ return {};
2589
+ const marker = b[i + 1];
2590
+ if (marker >= 192 && marker <= 207 && ![196, 200, 204].includes(marker))
2591
+ return { height: be16(i + 5), width: be16(i + 7) };
2592
+ i += 2 + be16(i + 2);
2593
+ }
2594
+ return {};
2595
+ }
2596
+ if (format === "webp" && b.length >= 30) {
2597
+ const chunk = String.fromCharCode(...b.slice(12, 16));
2598
+ if (chunk === "VP8X")
2599
+ return { width: le24(24) + 1, height: le24(27) + 1 };
2600
+ if (chunk === "VP8 ")
2601
+ return { width: le16(26) & 16383, height: le16(28) & 16383 };
2602
+ if (chunk === "VP8L") {
2603
+ const bits = b[21] | b[22] << 8 | b[23] << 16 | b[24] << 24;
2604
+ return { width: (bits & 16383) + 1, height: (bits >>> 14 & 16383) + 1 };
2605
+ }
2606
+ }
2607
+ } catch {
2608
+ return {};
2609
+ }
2610
+ return {};
2611
+ }
2612
+ function svgLabels(svg) {
2613
+ const out = [];
2614
+ for (const t of findAll(svg, "text")) {
2615
+ const parts = t.children.map((c) => typeof c === "string" ? c : textOf(c));
2616
+ const label = squash(parts.join(" "));
2617
+ if (label && !out.includes(label))
2618
+ out.push(label);
2619
+ }
2620
+ return out;
2621
+ }
2622
+ var px = (v) => {
2623
+ const m = v ? /^\s*(\d+(?:\.\d+)?)\s*(px)?\s*$/.exec(v) : null;
2624
+ return m ? Number(m[1]) : void 0;
2625
+ };
2626
+ function readImage(fileName, bytes) {
2627
+ const notes = [];
2628
+ const byExt = EXT[extOf(fileName)];
2629
+ const byBytes = imageFormat(bytes.slice(0, 1024));
2630
+ const format = byBytes ?? "unknown";
2631
+ if (!byBytes)
2632
+ notes.push("The content is not a picture format Atticus recognises.");
2633
+ else if (byExt && byExt !== byBytes)
2634
+ notes.push(`The file name says ${byExt} but the content is ${byBytes}.`);
2635
+ let dims = {};
2636
+ let candidateLabels = [];
2637
+ if (format === "svg") {
2638
+ const svg = parseXmlTree(utf8(bytes));
2639
+ if (svg) {
2640
+ const width = px(svg.attrs.width);
2641
+ const height = px(svg.attrs.height);
2642
+ dims = { ...width ? { width } : {}, ...height ? { height } : {} };
2643
+ candidateLabels = svgLabels(svg);
2644
+ }
2645
+ } else if (format !== "unknown")
2646
+ dims = size(format, bytes);
2647
+ return {
2648
+ record: sourceDocument(fileName, bytes, "image", "diagram", { flags: [NEEDS_READING_FLAG] }),
2649
+ image: { format, ...dims },
2650
+ needsReading: { reason: REASON, candidateLabels, confirmed: false },
2651
+ notes
2652
+ };
2653
+ }
2654
+
2655
+ // packages/ingestors/dist/figma.js
2656
+ var FIG_MAGIC = "fig-kiwi";
2657
+ var LINK2 = /https:\/\/(?:www\.)?figma\.com\/[^\s"'<>]+/;
2658
+ function looksLikeFigma(head) {
2659
+ const text = new TextDecoder().decode(head.slice(0, 4096));
2660
+ if (text.startsWith(FIG_MAGIC))
2661
+ return "binary";
2662
+ if (/^\s*\{/.test(text) && /"document"\s*:/.test(text) && /"type"\s*:\s*"DOCUMENT"/.test(text))
2663
+ return "json";
2664
+ if (LINK2.test(text) && text.length < 4096 && !/^\s*</.test(text))
2665
+ return "link";
2666
+ return void 0;
2667
+ }
2668
+ function readFigma(fileName, bytes) {
2669
+ const kind = looksLikeFigma(bytes);
2670
+ const notes = [];
2671
+ let title;
2672
+ let version;
2673
+ let date;
2674
+ let link;
2675
+ const pages2 = [];
2676
+ if (kind === "json") {
2677
+ try {
2678
+ const doc = JSON.parse(utf8(bytes));
2679
+ if (typeof doc.name === "string" && doc.name.trim())
2680
+ title = doc.name.trim();
2681
+ if (typeof doc.version === "string" || typeof doc.version === "number")
2682
+ version = String(doc.version);
2683
+ date = isoDate(doc.lastModified);
2684
+ for (const c of doc.document?.children ?? [])
2685
+ if (c?.type === "CANVAS" && typeof c.name === "string")
2686
+ pages2.push(c.name);
2687
+ } catch {
2688
+ notes.push("The Figma export is not valid JSON, so only the file itself is recorded.");
2689
+ }
2690
+ } else if (kind === "link")
2691
+ link = LINK2.exec(utf8(bytes))[0];
2692
+ else if (kind !== "binary")
2693
+ notes.push("This does not look like a Figma file, export or link.");
2694
+ return {
2695
+ record: sourceDocument(fileName, bytes, "design", "document", {
2696
+ ...version ? { version } : {},
2697
+ ...date ? { date } : {}
2698
+ }),
2699
+ ...title ? { title } : {},
2700
+ pages: pages2,
2701
+ ...link ? { link } : {},
2702
+ notes
2703
+ };
2704
+ }
2705
+
2706
+ // packages/ingestors/dist/ingestors.js
2707
+ var VERSION = "0.1.0";
2708
+ var headText = (head) => new TextDecoder().decode(head.slice(0, 4096));
2709
+ function diagramIngestor(id, sniff, check) {
2710
+ return {
2711
+ id,
2712
+ version: VERSION,
2713
+ sniff,
2714
+ async *ingest(fileName, content, ctx) {
2715
+ const problem = check(content);
2716
+ if (problem)
2717
+ ctx.warn(problem, fileName);
2718
+ yield sourceDocument(fileName, content, "diagram", "diagram");
2719
+ }
2720
+ };
2721
+ }
2722
+ var isLucidHeader = (head) => {
2723
+ const first = headText(head).replace(/^\uFEFF/, "").split(/\r?\n/)[0].toLowerCase();
2724
+ const cols = first.split(",").map((c) => c.trim().replace(/^"|"$/g, ""));
2725
+ return cols.includes("id") && cols.includes("line source") && cols.includes("line destination");
2726
+ };
2727
+ var lucidIngestor = diagramIngestor("lucid", (fileName, head) => isLucidHeader(head) ? extOf(fileName) === ".csv" ? 1 : 0.9 : 0, (content) => {
2728
+ const d = readLucidCsv(utf8(content));
2729
+ return d.problems.find((p) => p.cell === "") ? "This file is not a Lucidchart CSV export." : void 0;
2730
+ });
2731
+ var visioIngestor = diagramIngestor("visio", (fileName, head) => extOf(fileName) === ".vsdx" ? 1 : officeFormat(head) === "vsdx" ? 0.9 : 0, (content) => {
2732
+ try {
2733
+ const d = readVsdx(content);
2734
+ return d.problems.find((p) => p.cell === "") ? "No pages were found in this Visio file." : void 0;
2735
+ } catch (err) {
2736
+ if (err instanceof ZipError)
2737
+ return `This file could not be read as a .vsdx: ${err.message}.`;
2738
+ throw err;
2739
+ }
2740
+ });
2741
+ function mermaidHeader(text) {
2742
+ const lines = text.replace(/^\uFEFF/, "").split(/\r?\n/);
2743
+ let i = 0;
2744
+ if (lines[0]?.trim() === "---") {
2745
+ const end = lines.findIndex((l, k) => k > 0 && l.trim() === "---");
2746
+ i = end > 0 ? end + 1 : 0;
2747
+ }
2748
+ for (; i < lines.length; i++) {
2749
+ const l = lines[i].trim();
2750
+ if (l && !l.startsWith("%%"))
2751
+ return l;
2752
+ }
2753
+ return "";
2754
+ }
2755
+ var mermaidIngestor = diagramIngestor("mermaid", (fileName, head) => {
2756
+ const ext = extOf(fileName);
2757
+ if (ext === ".mmd" || ext === ".mermaid")
2758
+ return 1;
2759
+ return /^(flowchart|graph)\b/i.test(mermaidHeader(headText(head))) ? 0.8 : 0;
2760
+ }, (content) => readMermaid(utf8(content)).problems.find((p) => p.cell === "") ? "No Mermaid flowchart was found in this file." : void 0);
2761
+ var imageIngestor = {
2762
+ id: "image",
2763
+ version: VERSION,
2764
+ sniff(fileName, head) {
2765
+ if (IMAGE_EXTENSIONS.includes(extOf(fileName)))
2766
+ return 1;
2767
+ return imageFormat(head) ? 0.9 : 0;
2768
+ },
2769
+ async *ingest(fileName, content, ctx) {
2770
+ const r = readImage(fileName, content);
2771
+ for (const n of r.notes)
2772
+ ctx.warn(n, fileName);
2773
+ yield r.record;
2774
+ }
2775
+ };
2776
+ function documentIngestor(format, extensions, bySniff) {
2777
+ return {
2778
+ id: format,
2779
+ version: VERSION,
2780
+ sniff(fileName, head) {
2781
+ if (extensions.includes(extOf(fileName)))
2782
+ return 1;
2783
+ if (documentFormat(fileName, head) === format)
2784
+ return bySniff(head) || 0.9;
2785
+ return bySniff(head);
2786
+ },
2787
+ async *ingest(fileName, content, ctx) {
2788
+ const r = readDocument(fileName, content);
2789
+ for (const n of r.notes)
2790
+ ctx.warn(n, fileName);
2791
+ yield r.record;
2792
+ }
2793
+ };
2794
+ }
2795
+ var none = () => 0;
2796
+ var markdownIngestor = documentIngestor("markdown", [".md", ".markdown"], none);
2797
+ var htmlIngestor = documentIngestor("html", [".html", ".htm"], (head) => /^\s*(<!doctype html|<html[\s>])/i.test(headText(head)) ? 0.8 : 0);
2798
+ var textIngestor = documentIngestor("text", [".txt", ".text"], none);
2799
+ var docxIngestor = documentIngestor("docx", [".docx"], none);
2800
+ var pptxIngestor = documentIngestor("pptx", [".pptx"], none);
2801
+ var xlsxIngestor = documentIngestor("xlsx", [".xlsx"], none);
2802
+ var pdfIngestor = documentIngestor("pdf", [".pdf"], (head) => new TextDecoder("latin1").decode(head.slice(0, 1024)).includes("%PDF-") ? 0.95 : 0);
2803
+ var figmaIngestor = {
2804
+ id: "figma",
2805
+ version: VERSION,
2806
+ sniff(fileName, head) {
2807
+ const ext = extOf(fileName);
2808
+ if (ext === ".fig")
2809
+ return 1;
2810
+ const kind = looksLikeFigma(head);
2811
+ if (kind === "binary")
2812
+ return 0.95;
2813
+ if (kind === "json")
2814
+ return 0.9;
2815
+ if (kind === "link" && [".url", ".webloc", ".figma"].includes(ext))
2816
+ return 0.9;
2817
+ return 0;
2818
+ },
2819
+ async *ingest(fileName, content, ctx) {
2820
+ const r = readFigma(fileName, content);
2821
+ for (const n of r.notes)
2822
+ ctx.warn(n, fileName);
2823
+ yield r.record;
2824
+ }
2825
+ };
2826
+ function listIngestors() {
2827
+ return [
2828
+ drawioIngestor,
2829
+ lucidIngestor,
2830
+ visioIngestor,
2831
+ mermaidIngestor,
2832
+ imageIngestor,
2833
+ markdownIngestor,
2834
+ htmlIngestor,
2835
+ textIngestor,
2836
+ docxIngestor,
2837
+ pptxIngestor,
2838
+ xlsxIngestor,
2839
+ pdfIngestor,
2840
+ figmaIngestor
2841
+ ];
2842
+ }
2843
+ function pickIngestor(fileName, head) {
2844
+ let best;
2845
+ let score = 0;
2846
+ for (const i of listIngestors()) {
2847
+ const s = i.sniff(fileName, head);
2848
+ if (s > score) {
2849
+ best = i;
2850
+ score = s;
2851
+ }
2852
+ }
2853
+ return best;
2854
+ }
2855
+
2856
+ export {
2857
+ curatedAliases,
2858
+ resolveNames,
2859
+ readDrawio,
2860
+ drawioIngestor,
2861
+ reconcile,
2862
+ DEFAULT_LEGEND,
2863
+ edgeParts,
2864
+ legendWord,
2865
+ legendOf,
2866
+ fileBase,
2867
+ extOf,
2868
+ stem,
2869
+ documentId,
2870
+ isoDate,
2871
+ sourceDocument,
2872
+ utf8,
2873
+ parseCsv,
2874
+ readLucidCsv,
2875
+ readMermaid,
2876
+ readVsdx,
2877
+ readDiagram,
2878
+ ReadError,
2879
+ officeFormat,
2880
+ documentFormat,
2881
+ readDocument,
2882
+ NEEDS_READING_FLAG,
2883
+ IMAGE_EXTENSIONS,
2884
+ imageFormat,
2885
+ readImage,
2886
+ looksLikeFigma,
2887
+ readFigma,
2888
+ lucidIngestor,
2889
+ visioIngestor,
2890
+ mermaidIngestor,
2891
+ imageIngestor,
2892
+ markdownIngestor,
2893
+ htmlIngestor,
2894
+ textIngestor,
2895
+ docxIngestor,
2896
+ pptxIngestor,
2897
+ xlsxIngestor,
2898
+ pdfIngestor,
2899
+ figmaIngestor,
2900
+ listIngestors,
2901
+ pickIngestor
2902
+ };