raga-cli 0.0.0-stage → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (487) hide show
  1. package/CHANGELOG.md +118 -0
  2. package/LICENSE +21 -0
  3. package/README.md +162 -2
  4. package/bundled-skills/AGENTS.md +5 -0
  5. package/bundled-skills/README.md +25 -0
  6. package/bundled-skills/agents/comment-sicko.json +9 -0
  7. package/bundled-skills/agents/comment-sicko.md +28 -0
  8. package/bundled-skills/agents/model-roles.json +41 -0
  9. package/bundled-skills/agents/poteto-agent.json +9 -0
  10. package/bundled-skills/agents/poteto-agent.md +4 -0
  11. package/bundled-skills/agents/worker.json +8 -0
  12. package/bundled-skills/agents/worker.md +1 -0
  13. package/bundled-skills/bundle.json +1514 -0
  14. package/bundled-skills/dependencies.json +40 -0
  15. package/bundled-skills/docs/guide/01-setup.md +3 -0
  16. package/bundled-skills/docs/guide/02-peak.md +135 -0
  17. package/bundled-skills/docs/guide/03-understand.md +79 -0
  18. package/bundled-skills/docs/guide/04-design.md +133 -0
  19. package/bundled-skills/docs/guide/05-build-and-clean.md +83 -0
  20. package/bundled-skills/docs/guide/06-verify-and-ship.md +166 -0
  21. package/bundled-skills/docs/guide/07-overnight.md +118 -0
  22. package/bundled-skills/docs/guide/08-principles.md +72 -0
  23. package/bundled-skills/docs/guide/09-make-it-yours.md +96 -0
  24. package/bundled-skills/docs/guide/10-recipes-and-pitfalls.md +180 -0
  25. package/bundled-skills/docs/guide/README.md +38 -0
  26. package/bundled-skills/docs/guide/images/design.jpg +0 -0
  27. package/bundled-skills/docs/guide/images/overnight.jpg +0 -0
  28. package/bundled-skills/docs/guide/images/recipes.jpg +0 -0
  29. package/bundled-skills/docs/guide/images/router.jpg +0 -0
  30. package/bundled-skills/docs/guide/images/understanding.jpg +0 -0
  31. package/bundled-skills/docs/guide/images/verification.jpg +0 -0
  32. package/bundled-skills/licenses/commander +22 -0
  33. package/bundled-skills/licenses/cursor-team-kit +21 -0
  34. package/bundled-skills/licenses/no-mistakes +21 -0
  35. package/bundled-skills/licenses/pstack +21 -0
  36. package/bundled-skills/skills/bend/SKILL.md +58 -0
  37. package/bundled-skills/skills/bend/bend_tool.py +144 -0
  38. package/bundled-skills/skills/peak/SKILL.md +184 -0
  39. package/bundled-skills/skills/peak/playbooks/authoring-a-skill.md +12 -0
  40. package/bundled-skills/skills/peak/playbooks/autonomous-run.md +13 -0
  41. package/bundled-skills/skills/peak/playbooks/autopilot-full.md +25 -0
  42. package/bundled-skills/skills/peak/playbooks/autopilot-stack.md +12 -0
  43. package/bundled-skills/skills/peak/playbooks/babysit.md +18 -0
  44. package/bundled-skills/skills/peak/playbooks/bug-fix.md +15 -0
  45. package/bundled-skills/skills/peak/playbooks/eval.md +25 -0
  46. package/bundled-skills/skills/peak/playbooks/feature.md +21 -0
  47. package/bundled-skills/skills/peak/playbooks/hillclimb.md +21 -0
  48. package/bundled-skills/skills/peak/playbooks/investigation.md +14 -0
  49. package/bundled-skills/skills/peak/playbooks/multi-phase-plan.md +155 -0
  50. package/bundled-skills/skills/peak/playbooks/opening-a-pr.md +34 -0
  51. package/bundled-skills/skills/peak/playbooks/orchestrate.md +112 -0
  52. package/bundled-skills/skills/peak/playbooks/pause-safely.md +10 -0
  53. package/bundled-skills/skills/peak/playbooks/perf-issue.md +25 -0
  54. package/bundled-skills/skills/peak/playbooks/prototype.md +14 -0
  55. package/bundled-skills/skills/peak/playbooks/refactoring.md +16 -0
  56. package/bundled-skills/skills/peak/playbooks/runtime-forensics.md +11 -0
  57. package/bundled-skills/skills/peak/playbooks/session-pickup.md +11 -0
  58. package/bundled-skills/skills/peak/playbooks/shipping.md +12 -0
  59. package/bundled-skills/skills/peak/playbooks/trace-forensics.md +14 -0
  60. package/bundled-skills/skills/peak/playbooks/visual-parity.md +11 -0
  61. package/bundled-skills/skills/peak/playbooks/worktree-cleanup.md +6 -0
  62. package/bundled-skills/skills/peak/references/architect/SKILL.md +81 -0
  63. package/bundled-skills/skills/peak/references/architect/references/design-red-flags.md +57 -0
  64. package/bundled-skills/skills/peak/references/architect/references/rationale-template.md +35 -0
  65. package/bundled-skills/skills/peak/references/architect/references/runner-prompt.md +20 -0
  66. package/bundled-skills/skills/peak/references/arena/SKILL.md +50 -0
  67. package/bundled-skills/skills/peak/references/automate-me/SKILL.md +106 -0
  68. package/bundled-skills/skills/peak/references/benchmark-checklist/SKILL.md +41 -0
  69. package/bundled-skills/skills/peak/references/blast-radius/SKILL.md +52 -0
  70. package/bundled-skills/skills/peak/references/bro/SKILL.md +9 -0
  71. package/bundled-skills/skills/peak/references/control-cli/SKILL.md +111 -0
  72. package/bundled-skills/skills/peak/references/control-ui/SKILL.md +111 -0
  73. package/bundled-skills/skills/peak/references/correct/SKILL.md +34 -0
  74. package/bundled-skills/skills/peak/references/create-formal-verification-skill/SKILL.md +43 -0
  75. package/bundled-skills/skills/peak/references/create-skill/SKILL.md +14 -0
  76. package/bundled-skills/skills/peak/references/create-verification-skill/SKILL.md +46 -0
  77. package/bundled-skills/skills/peak/references/create-verification-skill/references/feature-map-example/README.md +47 -0
  78. package/bundled-skills/skills/peak/references/create-verification-skill/references/feature-map-example/create-note.md +39 -0
  79. package/bundled-skills/skills/peak/references/create-verification-skill/references/feature-map-example/search.md +45 -0
  80. package/bundled-skills/skills/peak/references/deslop/SKILL.md +24 -0
  81. package/bundled-skills/skills/peak/references/figure-it-out/SKILL.md +54 -0
  82. package/bundled-skills/skills/peak/references/how/SKILL.md +38 -0
  83. package/bundled-skills/skills/peak/references/how/references/explainer-prompt.md +55 -0
  84. package/bundled-skills/skills/peak/references/how/references/explorer-prompt.md +35 -0
  85. package/bundled-skills/skills/peak/references/in-your-own-words/SKILL.md +9 -0
  86. package/bundled-skills/skills/peak/references/interrogate/SKILL.md +76 -0
  87. package/bundled-skills/skills/peak/references/interrogate/references/code-quality-review.md +47 -0
  88. package/bundled-skills/skills/peak/references/interrogate/references/lead-judgment.md +39 -0
  89. package/bundled-skills/skills/peak/references/interrogate/references/reviewer-prompt.md +62 -0
  90. package/bundled-skills/skills/peak/references/interrogate/references/rubric.md +77 -0
  91. package/bundled-skills/skills/peak/references/ketchup/SKILL.md +45 -0
  92. package/bundled-skills/skills/peak/references/maintain-formal-verification-skill/SKILL.md +60 -0
  93. package/bundled-skills/skills/peak/references/maintain-verification-skill/SKILL.md +41 -0
  94. package/bundled-skills/skills/peak/references/no-comments/SKILL.md +26 -0
  95. package/bundled-skills/skills/peak/references/no-mistakes/SKILL.md +20 -0
  96. package/bundled-skills/skills/peak/references/no-mistakes/upstream/SKILL.md +394 -0
  97. package/bundled-skills/skills/peak/references/peak-setup/SKILL.md +18 -0
  98. package/bundled-skills/skills/peak/references/poteto-help/SKILL.md +16 -0
  99. package/bundled-skills/skills/peak/references/poteto-help/references/prompting.md +51 -0
  100. package/bundled-skills/skills/peak/references/poteto-help/references/recipes.md +51 -0
  101. package/bundled-skills/skills/peak/references/principle-attack-the-premise/SKILL.md +23 -0
  102. package/bundled-skills/skills/peak/references/principle-boundary-discipline/SKILL.md +36 -0
  103. package/bundled-skills/skills/peak/references/principle-build-the-lever/SKILL.md +25 -0
  104. package/bundled-skills/skills/peak/references/principle-encode-lessons-in-structure/SKILL.md +13 -0
  105. package/bundled-skills/skills/peak/references/principle-exhaust-the-design-space/SKILL.md +11 -0
  106. package/bundled-skills/skills/peak/references/principle-experience-first/SKILL.md +21 -0
  107. package/bundled-skills/skills/peak/references/principle-explain-the-number/SKILL.md +19 -0
  108. package/bundled-skills/skills/peak/references/principle-fix-root-causes/SKILL.md +23 -0
  109. package/bundled-skills/skills/peak/references/principle-foundational-thinking/SKILL.md +23 -0
  110. package/bundled-skills/skills/peak/references/principle-guard-the-context-window/SKILL.md +14 -0
  111. package/bundled-skills/skills/peak/references/principle-laziness-protocol/SKILL.md +12 -0
  112. package/bundled-skills/skills/peak/references/principle-make-operations-idempotent/SKILL.md +24 -0
  113. package/bundled-skills/skills/peak/references/principle-migrate-callers-then-delete-legacy-apis/SKILL.md +16 -0
  114. package/bundled-skills/skills/peak/references/principle-minimize-reader-load/SKILL.md +20 -0
  115. package/bundled-skills/skills/peak/references/principle-model-the-domain/SKILL.md +26 -0
  116. package/bundled-skills/skills/peak/references/principle-never-block-on-the-human/SKILL.md +17 -0
  117. package/bundled-skills/skills/peak/references/principle-outcome-oriented-execution/SKILL.md +23 -0
  118. package/bundled-skills/skills/peak/references/principle-prove-it-works/SKILL.md +24 -0
  119. package/bundled-skills/skills/peak/references/principle-redesign-from-first-principles/SKILL.md +18 -0
  120. package/bundled-skills/skills/peak/references/principle-separate-before-serializing-shared-state/SKILL.md +18 -0
  121. package/bundled-skills/skills/peak/references/principle-sequence-verifiable-units/SKILL.md +19 -0
  122. package/bundled-skills/skills/peak/references/principle-subtract-before-you-add/SKILL.md +20 -0
  123. package/bundled-skills/skills/peak/references/principle-test-behavior-not-implementation/SKILL.md +22 -0
  124. package/bundled-skills/skills/peak/references/principle-type-system-discipline/SKILL.md +15 -0
  125. package/bundled-skills/skills/peak/references/raga-runtime/SKILL.md +51 -0
  126. package/bundled-skills/skills/peak/references/raga-runtime/managed-tools.mjs +34 -0
  127. package/bundled-skills/skills/peak/references/raga-runtime/raga_runtime.py +55 -0
  128. package/bundled-skills/skills/peak/references/recall/SKILL.md +37 -0
  129. package/bundled-skills/skills/peak/references/reflect/SKILL.md +63 -0
  130. package/bundled-skills/skills/peak/references/reflect/references/divergent-reviewer.md +38 -0
  131. package/bundled-skills/skills/peak/references/reflect/references/judgment-reviewer.md +37 -0
  132. package/bundled-skills/skills/peak/references/reflect/references/synthesizer.md +56 -0
  133. package/bundled-skills/skills/peak/references/reflect/references/tooling-reviewer.md +48 -0
  134. package/bundled-skills/skills/peak/references/reviewer-triage.md +142 -0
  135. package/bundled-skills/skills/peak/references/sharpen/SKILL.md +18 -0
  136. package/bundled-skills/skills/peak/references/show-me-your-work/SKILL.md +84 -0
  137. package/bundled-skills/skills/peak/references/show-me-your-work/references/decision-log-template.tsv +1 -0
  138. package/bundled-skills/skills/peak/references/show-me-your-work/scripts/log.sh +42 -0
  139. package/bundled-skills/skills/peak/references/statechart/SKILL.md +38 -0
  140. package/bundled-skills/skills/peak/references/statechart/scripts/chart-to-tla.mjs +236 -0
  141. package/bundled-skills/skills/peak/references/statechart/scripts/compare-charts.mjs +104 -0
  142. package/bundled-skills/skills/peak/references/statechart/scripts/lib.mjs +725 -0
  143. package/bundled-skills/skills/peak/references/statechart/scripts/model/OutputFolder.cfg +6 -0
  144. package/bundled-skills/skills/peak/references/statechart/scripts/model/OutputFolder.map.mjs +106 -0
  145. package/bundled-skills/skills/peak/references/statechart/scripts/model/OutputFolder.tla +176 -0
  146. package/bundled-skills/skills/peak/references/statechart/scripts/statechart.mjs +749 -0
  147. package/bundled-skills/skills/peak/references/statechart/scripts/test/statechart.test.mjs +2790 -0
  148. package/bundled-skills/skills/peak/references/statechart/scripts/test/sync.mmd +19 -0
  149. package/bundled-skills/skills/peak/references/statechart/scripts/test/upload.mmd +16 -0
  150. package/bundled-skills/skills/peak/references/statechart/scripts/tlc-to-chart.mjs +1347 -0
  151. package/bundled-skills/skills/peak/references/swarm/SKILL.md +43 -0
  152. package/bundled-skills/skills/peak/references/tdd/SKILL.md +44 -0
  153. package/bundled-skills/skills/peak/references/teach/SKILL.md +23 -0
  154. package/bundled-skills/skills/peak/references/technical-writing/SKILL.md +108 -0
  155. package/bundled-skills/skills/peak/references/typescript-best-practices/SKILL.md +33 -0
  156. package/bundled-skills/skills/peak/references/typescript-best-practices/references/patterns.md +328 -0
  157. package/bundled-skills/skills/peak/references/unslop/SKILL.md +64 -0
  158. package/bundled-skills/skills/peak/references/verify-this/SKILL.md +76 -0
  159. package/bundled-skills/skills/peak/references/why/SKILL.md +100 -0
  160. package/bundled-skills/skills/peak/references/why/references/epistemics.md +71 -0
  161. package/bundled-skills/skills/peak/references/why/references/investigator-prompt.md +84 -0
  162. package/bundled-skills/skills/peak/references/why/references/source-playbook.md +17 -0
  163. package/bundled-skills/skills/peak/references/why/references/sources/code-archaeology.md +51 -0
  164. package/bundled-skills/skills/peak/references/why/references/sources/databricks.md +70 -0
  165. package/bundled-skills/skills/peak/references/why/references/sources/datadog.md +97 -0
  166. package/bundled-skills/skills/peak/references/why/references/sources/incident-postmortem.md +5 -0
  167. package/bundled-skills/skills/peak/references/why/references/sources/linear.md +48 -0
  168. package/bundled-skills/skills/peak/references/why/references/sources/notion.md +55 -0
  169. package/bundled-skills/skills/peak/references/why/references/sources/sentry.md +66 -0
  170. package/bundled-skills/skills/peak/references/why/references/sources/slack.md +17 -0
  171. package/bundled-skills/skills/peak/references/why/references/synthesizer-prompt.md +129 -0
  172. package/bundled-skills/skills/peak/scripts/check-plan.mjs +205 -0
  173. package/bundled-skills/skills/peak/scripts/check-plan.test.ts +96 -0
  174. package/bundled-skills/skills/peak/scripts/orch/orch.test.ts +761 -0
  175. package/bundled-skills/skills/peak/scripts/orch/orch.ts +588 -0
  176. package/bundled-skills/skills/peak/scripts/orch/store.ts +1676 -0
  177. package/bundled-skills/skills/peak/scripts/vendor/commander/LICENSE +22 -0
  178. package/bundled-skills/skills/peak/scripts/vendor/commander/esm.mjs +16 -0
  179. package/bundled-skills/skills/peak/scripts/vendor/commander/index.js +24 -0
  180. package/bundled-skills/skills/peak/scripts/vendor/commander/lib/argument.js +149 -0
  181. package/bundled-skills/skills/peak/scripts/vendor/commander/lib/command.js +2778 -0
  182. package/bundled-skills/skills/peak/scripts/vendor/commander/lib/error.js +39 -0
  183. package/bundled-skills/skills/peak/scripts/vendor/commander/lib/help.js +747 -0
  184. package/bundled-skills/skills/peak/scripts/vendor/commander/lib/option.js +379 -0
  185. package/bundled-skills/skills/peak/scripts/vendor/commander/lib/suggestSimilar.js +101 -0
  186. package/bundled-skills/skills/peak/scripts/vendor/commander/package.json +1 -0
  187. package/bundled-skills/skills/peak/scripts/vendor/commander/typings/esm.d.mts +3 -0
  188. package/bundled-skills/skills/peak/scripts/vendor/commander/typings/index.d.ts +1113 -0
  189. package/bundled-skills/skills/peak/scripts/watch-pr/cli.test.ts +224 -0
  190. package/bundled-skills/skills/peak/scripts/watch-pr/cli.ts +223 -0
  191. package/bundled-skills/skills/peak/scripts/watch-pr/fakes.test-helper.ts +129 -0
  192. package/bundled-skills/skills/peak/scripts/watch-pr/github.test.ts +436 -0
  193. package/bundled-skills/skills/peak/scripts/watch-pr/github.ts +718 -0
  194. package/bundled-skills/skills/peak/scripts/watch-pr/policy.test.ts +420 -0
  195. package/bundled-skills/skills/peak/scripts/watch-pr/policy.ts +836 -0
  196. package/bundled-skills/skills/peak/scripts/watch-pr/render.ts +169 -0
  197. package/bundled-skills/skills/peak/scripts/watch-pr/tsconfig.json +13 -0
  198. package/bundled-skills/skills/peak/scripts/watch-pr/types.compile.ts +93 -0
  199. package/bundled-skills/skills/peak/scripts/watch-pr/types.ts +413 -0
  200. package/bundled-skills/skills/peak/scripts/watch-pr/watch-pr +4 -0
  201. package/bundled-skills/skills/peak/scripts/worktree-audit.sh +4 -0
  202. package/bundled-skills/skills/raga-artifacts/SKILL.md +117 -0
  203. package/bundled-skills/skills/raga-artifacts/artifact.mjs +254 -0
  204. package/bundled-skills/skills/raga-artifacts/artifact_tool.py +55 -0
  205. package/bundled-skills/skills/raga-artifacts/diagrams.md +641 -0
  206. package/bundled-skills/skills/raga-artifacts/templates/doc.html +124 -0
  207. package/bundled-skills/skills/raga-artifacts/templates/slides.html +138 -0
  208. package/dist/bundle/chunks/anthropic-messages-BMDYDGHW.js +6 -0
  209. package/dist/bundle/chunks/anthropic.js +68 -0
  210. package/dist/bundle/chunks/azure-openai-responses-Q7EZTEHK.js +2 -0
  211. package/dist/bundle/chunks/bedrock-converse-stream.js +86 -0
  212. package/dist/bundle/chunks/chunk-3MNXTBQ3.js +2 -0
  213. package/dist/bundle/chunks/chunk-3V45WARH.js +7 -0
  214. package/dist/bundle/chunks/chunk-5AGIVGSV.js +6 -0
  215. package/dist/bundle/chunks/chunk-6QGV3IWD.js +6 -0
  216. package/dist/bundle/chunks/chunk-7CBJINYJ.js +20 -0
  217. package/dist/bundle/chunks/chunk-7DDKXS2Q.js +2 -0
  218. package/dist/bundle/chunks/chunk-7ZC4UXSL.js +2 -0
  219. package/dist/bundle/chunks/chunk-CF5GWZHW.js +31 -0
  220. package/dist/bundle/chunks/chunk-ENUUAC3O.js +131 -0
  221. package/dist/bundle/chunks/chunk-F7LFZTHT.js +1591 -0
  222. package/dist/bundle/chunks/chunk-G54UBZTF.js +44 -0
  223. package/dist/bundle/chunks/chunk-H76KZMOI.js +2 -0
  224. package/dist/bundle/chunks/chunk-IXDQLPKS.js +11 -0
  225. package/dist/bundle/chunks/chunk-JLV25LHE.js +2 -0
  226. package/dist/bundle/chunks/chunk-JQDZ4Z7L.js +2 -0
  227. package/dist/bundle/chunks/chunk-JXWJOIH4.js +2 -0
  228. package/dist/bundle/chunks/chunk-KNY3PXQI.js +2 -0
  229. package/dist/bundle/chunks/chunk-L2ZPNLYD.js +2 -0
  230. package/dist/bundle/chunks/chunk-LPXNMA2W.js +2 -0
  231. package/dist/bundle/chunks/chunk-LVVZS2NO.js +12 -0
  232. package/dist/bundle/chunks/chunk-LX24DVQ5.js +2 -0
  233. package/dist/bundle/chunks/chunk-NP6TH6UT.js +64 -0
  234. package/dist/bundle/chunks/chunk-OPPYO2IE.js +2 -0
  235. package/dist/bundle/chunks/chunk-P2QCWBFM.js +9 -0
  236. package/dist/bundle/chunks/chunk-P7FPUEYA.js +2 -0
  237. package/dist/bundle/chunks/chunk-PGXDEOVV.js +2 -0
  238. package/dist/bundle/chunks/chunk-PJACZCIR.js +2 -0
  239. package/dist/bundle/chunks/chunk-PMRZO46Y.js +2 -0
  240. package/dist/bundle/chunks/chunk-PRRNXB7S.js +2 -0
  241. package/dist/bundle/chunks/chunk-Q4U25BSY.js +2 -0
  242. package/dist/bundle/chunks/chunk-RDZVAGPR.js +2 -0
  243. package/dist/bundle/chunks/chunk-RFPFZTK2.js +7 -0
  244. package/dist/bundle/chunks/chunk-RP2WKNT7.js +4 -0
  245. package/dist/bundle/chunks/chunk-S5J3UB5O.js +75 -0
  246. package/dist/bundle/chunks/chunk-TEPMHNKQ.js +2 -0
  247. package/dist/bundle/chunks/chunk-TMTOQ7H7.js +2 -0
  248. package/dist/bundle/chunks/chunk-UKVNB6C4.js +2 -0
  249. package/dist/bundle/chunks/chunk-USJZMAIR.js +2 -0
  250. package/dist/bundle/chunks/chunk-UTB4DTYQ.js +2 -0
  251. package/dist/bundle/chunks/chunk-WJGLPWUE.js +16 -0
  252. package/dist/bundle/chunks/cli-QLDCDYOR.js +51 -0
  253. package/dist/bundle/chunks/cloudflare-workers-ai-system-one-S6CT2FXS.js +2 -0
  254. package/dist/bundle/chunks/codemode-worker.js +478 -0
  255. package/dist/bundle/chunks/easter-egg-3d-NPDBBPPF.js +2 -0
  256. package/dist/bundle/chunks/execute-WPTMS4XG.js +505 -0
  257. package/dist/bundle/chunks/github-copilot.js +2 -0
  258. package/dist/bundle/chunks/google-generative-ai-35NZKG6S.js +2 -0
  259. package/dist/bundle/chunks/google-vertex-P33AHYYX.js +2 -0
  260. package/dist/bundle/chunks/https-proxy-agent-LVOO5TPL.js +13 -0
  261. package/dist/bundle/chunks/image-resize-worker.js +2 -0
  262. package/dist/bundle/chunks/jiti-loader-GL4HJFAD.js +21 -0
  263. package/dist/bundle/chunks/jiti-static-loader-2RCDI6B4.js +2 -0
  264. package/dist/bundle/chunks/kimi-coding.js +2 -0
  265. package/dist/bundle/chunks/lib-4AVRLBHM.js +9 -0
  266. package/dist/bundle/chunks/llama-cpp-classify-U4EH6TAM.js +22 -0
  267. package/dist/bundle/chunks/meta.js +2 -0
  268. package/dist/bundle/chunks/mistral-conversations-J62DPS2P.js +5 -0
  269. package/dist/bundle/chunks/multipart-parser-FMGQ7342.js +3 -0
  270. package/dist/bundle/chunks/node-AUOGOBCN.js +2 -0
  271. package/dist/bundle/chunks/node-KCMANYC2.js +16 -0
  272. package/dist/bundle/chunks/openai-chatgpt.js +68 -0
  273. package/dist/bundle/chunks/openai-codex-responses-4HXATL2M.js +10 -0
  274. package/dist/bundle/chunks/openai-codex.js +68 -0
  275. package/dist/bundle/chunks/openai-completions-75YYY35N.js +7 -0
  276. package/dist/bundle/chunks/openai-decisions-HEBEVGA2.js +5 -0
  277. package/dist/bundle/chunks/openai-responses-UWNAKTBV.js +4 -0
  278. package/dist/bundle/chunks/openrouter-images-HVOPXKHS.js +2 -0
  279. package/dist/bundle/chunks/openrouter.js +68 -0
  280. package/dist/bundle/chunks/pi-messages-DG7CALOV.js +8 -0
  281. package/dist/bundle/chunks/radius.js +68 -0
  282. package/dist/bundle/chunks/runtime-N5MUH2WA.js +2 -0
  283. package/dist/bundle/chunks/src-QKGKDFSU.js +4 -0
  284. package/dist/bundle/chunks/typesafe-system-one-24HEGHNN.js +2 -0
  285. package/dist/bundle/chunks/virtual-modules-4I6Y6DPQ.js +2 -0
  286. package/dist/bundle/chunks/xai.js +2 -0
  287. package/dist/bundle/cli-runtime.js +3 -0
  288. package/dist/bundle/cli.js +5 -0
  289. package/dist/bundle/index.js +2 -0
  290. package/dist/bundle/raga-runtime.js +3 -0
  291. package/dist/bundle/raga.js +5 -0
  292. package/dist/bundle/rpc-entry.js +3 -0
  293. package/dist/core/export-html/template.css +1085 -0
  294. package/dist/core/export-html/template.html +56 -0
  295. package/dist/core/export-html/template.js +2044 -0
  296. package/dist/core/export-html/vendor/highlight.min.js +1213 -0
  297. package/dist/core/export-html/vendor/marked-cjk-friendly.min.js +6 -0
  298. package/dist/core/export-html/vendor/marked.min.js +79 -0
  299. package/dist/modes/interactive/assets/clankolas.png +0 -0
  300. package/dist/modes/interactive/theme/dark.json +78 -0
  301. package/dist/modes/interactive/theme/light.json +78 -0
  302. package/docs/cli-integration.md +106 -0
  303. package/docs/cli.md +343 -0
  304. package/docs/codemode.md +230 -0
  305. package/docs/compaction.md +489 -0
  306. package/docs/configuration.md +62 -0
  307. package/docs/containerization.md +183 -0
  308. package/docs/custom-provider.md +227 -0
  309. package/docs/docs.json +220 -0
  310. package/docs/environment-variables.md +101 -0
  311. package/docs/extensions.md +400 -0
  312. package/docs/how-pi-works.md +49 -0
  313. package/docs/images/doom-extension.png +0 -0
  314. package/docs/images/exy.png +0 -0
  315. package/docs/images/interactive-mode.png +0 -0
  316. package/docs/images/tree-view.png +0 -0
  317. package/docs/index.md +39 -0
  318. package/docs/json.md +226 -0
  319. package/docs/keybindings.md +195 -0
  320. package/docs/llama-cpp.md +121 -0
  321. package/docs/mcp.md +272 -0
  322. package/docs/message-types.md +279 -0
  323. package/docs/models-configuration.md +196 -0
  324. package/docs/models.md +225 -0
  325. package/docs/nvidia-rtx-llama-cpp.md +96 -0
  326. package/docs/packages.md +129 -0
  327. package/docs/prompt-templates.md +59 -0
  328. package/docs/providers.md +247 -0
  329. package/docs/quickstart.md +136 -0
  330. package/docs/rpc-commands.md +860 -0
  331. package/docs/rpc-extension-ui.md +200 -0
  332. package/docs/rpc.md +193 -0
  333. package/docs/sdk.md +149 -0
  334. package/docs/security.md +99 -0
  335. package/docs/session-format.md +293 -0
  336. package/docs/sessions.md +66 -0
  337. package/docs/settings.md +185 -0
  338. package/docs/shell-aliases.md +93 -0
  339. package/docs/skills.md +93 -0
  340. package/docs/slash-commands.md +61 -0
  341. package/docs/terminal-setup.md +233 -0
  342. package/docs/termux.md +117 -0
  343. package/docs/themes.md +138 -0
  344. package/docs/tmux.md +55 -0
  345. package/docs/tui.md +195 -0
  346. package/docs/usage.md +94 -0
  347. package/docs/virtual-models.md +114 -0
  348. package/docs/windows.md +81 -0
  349. package/examples/README.md +36 -0
  350. package/examples/extensions/README.md +214 -0
  351. package/examples/extensions/auto-commit-on-exit.ts +49 -0
  352. package/examples/extensions/bash-spawn-hook.ts +30 -0
  353. package/examples/extensions/bookmark.ts +50 -0
  354. package/examples/extensions/border-status-editor.ts +150 -0
  355. package/examples/extensions/built-in-tool-renderer.ts +225 -0
  356. package/examples/extensions/claude-rules.ts +86 -0
  357. package/examples/extensions/commands.ts +72 -0
  358. package/examples/extensions/confirm-destructive.ts +59 -0
  359. package/examples/extensions/custom-compaction.ts +117 -0
  360. package/examples/extensions/custom-footer.ts +64 -0
  361. package/examples/extensions/custom-header.ts +73 -0
  362. package/examples/extensions/custom-provider-anthropic/index.ts +617 -0
  363. package/examples/extensions/custom-provider-anthropic/package-lock.json +24 -0
  364. package/examples/extensions/custom-provider-anthropic/package.json +19 -0
  365. package/examples/extensions/custom-provider-gitlab-duo/index.ts +405 -0
  366. package/examples/extensions/custom-provider-gitlab-duo/package.json +16 -0
  367. package/examples/extensions/custom-provider-gitlab-duo/test.ts +82 -0
  368. package/examples/extensions/debug-provider.ts +90 -0
  369. package/examples/extensions/dirty-repo-guard.ts +56 -0
  370. package/examples/extensions/doom-overlay/README.md +46 -0
  371. package/examples/extensions/doom-overlay/doom/build/doom.js +21 -0
  372. package/examples/extensions/doom-overlay/doom/build/doom.wasm +0 -0
  373. package/examples/extensions/doom-overlay/doom/build.sh +152 -0
  374. package/examples/extensions/doom-overlay/doom/doomgeneric_pi.c +72 -0
  375. package/examples/extensions/doom-overlay/doom-component.ts +132 -0
  376. package/examples/extensions/doom-overlay/doom-engine.ts +173 -0
  377. package/examples/extensions/doom-overlay/doom-keys.ts +104 -0
  378. package/examples/extensions/doom-overlay/index.ts +74 -0
  379. package/examples/extensions/doom-overlay/wad-finder.ts +55 -0
  380. package/examples/extensions/dynamic-resources/SKILL.md +8 -0
  381. package/examples/extensions/dynamic-resources/dynamic.json +81 -0
  382. package/examples/extensions/dynamic-resources/dynamic.md +5 -0
  383. package/examples/extensions/dynamic-resources/index.ts +15 -0
  384. package/examples/extensions/dynamic-tools.ts +74 -0
  385. package/examples/extensions/entry-renderer.ts +41 -0
  386. package/examples/extensions/event-bus.ts +43 -0
  387. package/examples/extensions/file-trigger.ts +41 -0
  388. package/examples/extensions/git-checkpoint.ts +53 -0
  389. package/examples/extensions/git-merge-and-resolve.ts +115 -0
  390. package/examples/extensions/github-issue-autocomplete.ts +185 -0
  391. package/examples/extensions/gondolin/index.ts +531 -0
  392. package/examples/extensions/gondolin/package-lock.json +175 -0
  393. package/examples/extensions/gondolin/package.json +19 -0
  394. package/examples/extensions/handoff.ts +190 -0
  395. package/examples/extensions/hello.ts +26 -0
  396. package/examples/extensions/hidden-thinking-label.ts +53 -0
  397. package/examples/extensions/inline-bash.ts +94 -0
  398. package/examples/extensions/input-transform-streaming.ts +39 -0
  399. package/examples/extensions/input-transform.ts +43 -0
  400. package/examples/extensions/interactive-shell.ts +196 -0
  401. package/examples/extensions/jev-router.ts +113 -0
  402. package/examples/extensions/mac-system-theme.ts +47 -0
  403. package/examples/extensions/message-renderer.ts +59 -0
  404. package/examples/extensions/minimal-mode.ts +353 -0
  405. package/examples/extensions/modal-editor.ts +85 -0
  406. package/examples/extensions/model-status.ts +31 -0
  407. package/examples/extensions/notify.ts +57 -0
  408. package/examples/extensions/overlay-qa-tests.ts +1450 -0
  409. package/examples/extensions/overlay-test.ts +153 -0
  410. package/examples/extensions/permission-gate.ts +34 -0
  411. package/examples/extensions/pirate.ts +47 -0
  412. package/examples/extensions/plan-mode/README.md +66 -0
  413. package/examples/extensions/plan-mode/index.ts +394 -0
  414. package/examples/extensions/plan-mode/utils.ts +168 -0
  415. package/examples/extensions/preset.ts +436 -0
  416. package/examples/extensions/project-trust.ts +64 -0
  417. package/examples/extensions/prompt-customizer.ts +49 -0
  418. package/examples/extensions/protected-paths.ts +30 -0
  419. package/examples/extensions/provider-payload.ts +18 -0
  420. package/examples/extensions/qna.ts +118 -0
  421. package/examples/extensions/question.ts +286 -0
  422. package/examples/extensions/questionnaire.ts +448 -0
  423. package/examples/extensions/rainbow-editor.ts +88 -0
  424. package/examples/extensions/reload-runtime.ts +37 -0
  425. package/examples/extensions/rpc-demo.ts +118 -0
  426. package/examples/extensions/sandbox/index.ts +326 -0
  427. package/examples/extensions/sandbox/package-lock.json +92 -0
  428. package/examples/extensions/sandbox/package.json +19 -0
  429. package/examples/extensions/send-user-message.ts +97 -0
  430. package/examples/extensions/session-name.ts +27 -0
  431. package/examples/extensions/shutdown-command.ts +63 -0
  432. package/examples/extensions/snake.ts +343 -0
  433. package/examples/extensions/space-invaders.ts +560 -0
  434. package/examples/extensions/ssh.ts +220 -0
  435. package/examples/extensions/status-line.ts +32 -0
  436. package/examples/extensions/structured-output.ts +65 -0
  437. package/examples/extensions/subagent/README.md +177 -0
  438. package/examples/extensions/subagent/agents/planner.md +37 -0
  439. package/examples/extensions/subagent/agents/reviewer.md +35 -0
  440. package/examples/extensions/subagent/agents/scout.md +50 -0
  441. package/examples/extensions/subagent/agents/worker.md +24 -0
  442. package/examples/extensions/subagent/agents.ts +157 -0
  443. package/examples/extensions/subagent/index.ts +1038 -0
  444. package/examples/extensions/subagent/prompts/implement-and-review.md +10 -0
  445. package/examples/extensions/subagent/prompts/implement.md +10 -0
  446. package/examples/extensions/subagent/prompts/scout-and-plan.md +9 -0
  447. package/examples/extensions/summarize.ts +199 -0
  448. package/examples/extensions/system-prompt-header.ts +17 -0
  449. package/examples/extensions/tic-tac-toe.ts +1008 -0
  450. package/examples/extensions/timed-confirm.ts +70 -0
  451. package/examples/extensions/titlebar-spinner.ts +58 -0
  452. package/examples/extensions/todo.ts +297 -0
  453. package/examples/extensions/tool-override.ts +144 -0
  454. package/examples/extensions/tools.ts +146 -0
  455. package/examples/extensions/trigger-compact.ts +50 -0
  456. package/examples/extensions/truncated-tool.ts +195 -0
  457. package/examples/extensions/widget-placement.ts +9 -0
  458. package/examples/extensions/with-deps/index.ts +32 -0
  459. package/examples/extensions/with-deps/package-lock.json +31 -0
  460. package/examples/extensions/with-deps/package.json +22 -0
  461. package/examples/extensions/working-indicator.ts +123 -0
  462. package/examples/extensions/working-message-test.ts +25 -0
  463. package/examples/rpc-client.ts +35 -0
  464. package/examples/rpc-extension-ui.ts +661 -0
  465. package/examples/sdk/01-minimal.ts +26 -0
  466. package/examples/sdk/02-custom-model.ts +49 -0
  467. package/examples/sdk/03-custom-prompt.ts +75 -0
  468. package/examples/sdk/04-skills.ts +55 -0
  469. package/examples/sdk/05-tools.ts +48 -0
  470. package/examples/sdk/06-extensions.ts +99 -0
  471. package/examples/sdk/07-context-files.ts +47 -0
  472. package/examples/sdk/08-prompt-templates.ts +51 -0
  473. package/examples/sdk/09-api-keys-and-oauth.ts +34 -0
  474. package/examples/sdk/10-settings.ts +53 -0
  475. package/examples/sdk/11-sessions.ts +52 -0
  476. package/examples/sdk/12-full-control.ts +74 -0
  477. package/examples/sdk/13-session-runtime.ts +67 -0
  478. package/examples/sdk/14-codemode-mcp.ts +61 -0
  479. package/examples/sdk/README.md +141 -0
  480. package/package.json +21 -5
  481. package/python/raga_rlm/__init__.py +352 -0
  482. package/python/raga_rlm/mlx_models.py +265 -0
  483. package/python/raga_rlm/repl.py +920 -0
  484. package/schemas/keybindings.schema.json +441 -0
  485. package/schemas/models.schema.json +1211 -0
  486. package/schemas/settings.schema.json +829 -0
  487. package/schemas/theme.schema.json +365 -0
@@ -0,0 +1,749 @@
1
+ #!/usr/bin/env node
2
+ import { spawnSync } from "node:child_process";
3
+ import fs from "node:fs";
4
+ import os from "node:os";
5
+ import path from "node:path";
6
+ import process from "node:process";
7
+ import { fileURLToPath, pathToFileURL } from "node:url";
8
+ import { checkTlcOutput, findTlc, parseDot } from "./lib.mjs";
9
+
10
+ const here = path.dirname(fileURLToPath(import.meta.url));
11
+
12
+ const USAGE = {
13
+ "from-spec":
14
+ "node statechart.mjs from-spec SPEC.tla [--fixed FIXED.tla | --against AGREED.tla] [--label TEXT] [--map FILE] [--expect-broken RULE]... [--title TEXT] [--out DIR] [--png]",
15
+ "from-chart":
16
+ "node statechart.mjs from-chart CHART.mmd [--module NAME] [--expect-broken RULE]... [--title TEXT] [--out DIR] [--png]",
17
+ };
18
+ const usage = (lines) => `Usage: ${lines.join("\n ")}`;
19
+
20
+ const FROM_SPEC = `from-spec SPEC.tla
21
+ Checks each INVARIANT in SPEC.cfg in a separate TLC run. TLC stops at the first rule that a state
22
+ breaks, and the separate runs find the rest. Each run also has the rule as a CONSTRAINT, so TLC
23
+ stops each path at its first state that breaks the rule, and a rule that stays broken reports
24
+ only the step that broke it. SPEC.cfg sits next to the spec and has SPECIFICATION and one
25
+ INVARIANT line per rule. One more run dumps the state graph, and then the command draws the
26
+ charts. TLC names each step after the innermost named action that takes it, so give each kind of
27
+ step its own named action. The command warns when steps carry the name of the whole next-state
28
+ action.
29
+
30
+ --fixed FIXED.tla The model of the open fix. It is a copy of the spec with its own file and
31
+ module name, such as SpecFixed.tla with MODULE SpecFixed. The command checks
32
+ it the same way, with FIXED.cfg, or with SPEC.cfg when there is no FIXED.cfg.
33
+ The charts then mark each bad state fixed or still wrong.
34
+ --against AGREED.tla
35
+ The spec that SPEC.tla must follow, when SPEC.tla models the code. It needs
36
+ its own file and module name. The command checks it with AGREED.cfg, or with
37
+ SPEC.cfg when there is no AGREED.cfg. SPEC.tla may add variables, record
38
+ fields, and actions that AGREED.tla does not have. The comparison leaves them
39
+ out. Do not use it with --fixed.
40
+ --label TEXT The name of the --fixed or --against model in the charts and the stories.
41
+ Default: "the fix", or "the spec".
42
+ --map FILE The labels for each model state and step. Default: SPEC.map.mjs next to the
43
+ spec. When the file does not exist, the command writes one to fill in and
44
+ exits 2. Its comments say what each function gets.`;
45
+
46
+ const FROM_CHART = `from-chart CHART.mmd
47
+ Writes NAME.tla, NAME.cfg, and NAME.map.mjs next to the chart. When NAME.tla already exists, it
48
+ writes none of them. Then it checks the spec as from-spec does, and compares the chart that the
49
+ spec draws with CHART.mmd.
50
+
51
+ --module NAME The TLA+ module name. Default: the chart's file name in CamelCase, such as
52
+ NotesApp for notes-app.mmd.
53
+
54
+ The chart is a Mermaid stateDiagram-v2. Each transition label is one action. For parallel
55
+ regions, split one top-level composite with --, and put each part in a named composite, such as
56
+ state Connection { ... }. Each region is one variable. A step moves every region whose current
57
+ state has a transition with the step's label, and the other regions stay where they are. Each
58
+ rule is one comment line:
59
+ %% never NAME: A & B -- the rule in one sentence
60
+ Each name after the colon is a state caption or a composite, and each comes from a different
61
+ region. A composite stands for every state in it. The command refuses final, choice, fork, and
62
+ history states, and regions below the top level.`;
63
+
64
+ const COMMON = `Both commands
65
+ --expect-broken RULE
66
+ A rule that is known to break. Repeat it, or list rules with commas, as in
67
+ A,B. The command then exits 0 when exactly these rules break, and the --fixed
68
+ or --against model breaks no other rule.
69
+ --title TEXT The chart title. Each bug chart adds ", bug N".
70
+ --out DIR The output folder. Default: NAME-statechart next to the input. A run writes its
71
+ files in a temporary folder, and then replaces the whole output folder with
72
+ it. When runs overlap, the output folder has the files of the run that
73
+ finished last. The command does not use an output folder that has files that
74
+ it did not write.
75
+ --png Also render each chart to PNG with the managed MERMAID_CLI executable.
76
+ -h, --help Print this help, and exit 0.
77
+
78
+ Output
79
+ The command prints whether each rule holds, the chart's counts, and one story per bug.
80
+ from-chart also prints the comparison. The command writes these files in the output folder:
81
+ chart.mmd The overview.
82
+ bug-N.mmd Only the steps of bug N, numbered. Bugs are numbered by fewest reader steps,
83
+ then fewest model steps, then rule name, then cause. Bugs that only the
84
+ --fixed or --against model has come last.
85
+ bug-N-developer.mmd, bug-N-layered.mmd
86
+ The path of bug N through the developer's states, when the mapping exports
87
+ detail().
88
+ stories.md One entry per bug: the rule, why it breaks, the shortest path in reader
89
+ steps, and what the --fixed or --against model does instead.
90
+ summary.json The counts behind the chart.
91
+ tlc/ The config and the TLC output of each run. When the overview has regions,
92
+ from-spec also writes tlc/regions-all.mmd, the regions with every arrow, and
93
+ tlc/regions-proof.mmd, every state and step of TLC's graph in one region.
94
+ compare-charts.mjs tlc/regions-all.mmd tlc/regions-proof.mmd repeats the
95
+ proof.
96
+ *.png Each chart as a PNG, with --png. A run without --png deletes them.
97
+
98
+ Reading a chart
99
+ from-spec draws the overview as two parallel regions when every state reads "context: progress":
100
+ the contexts on one side, the progress on the other, both at the same time. It does so only when
101
+ that has fewer states, and when the regions combine back into exactly every state and step of
102
+ TLC's graph. Otherwise it puts the states of one context in a box named context, and prints why.
103
+ Regions draw only the arrows of the shortest way to each state, of each bug path, and of the
104
+ nearest step with each label. The script checks that these arrows make no step that TLC's graph
105
+ does not have.
106
+ An arrow from a box's border leaves from every state in the box.
107
+ In regions, a step leaves every region that has it. "[when A]" or "[unless A]" says which states
108
+ of the other region the step needs. A loop says the region may also stay.
109
+ Other words in [ ] come from the mapping's guard(), and "after N s" from its timer(). TLC does
110
+ not check them, and has no clock, so a reviewer checks them against the code.
111
+ Gray states work. Red states break a rule. With --fixed, red states stay wrong with the fix, and
112
+ green states are fixed by it or exist only with it. With --against, red states break a rule in
113
+ either model, and green states exist only in the spec.
114
+ When the mapping exports group(), the fill is the state's group, which the legend names, and the
115
+ status is a thick red or green border on top. tlc-to-chart.mjs --help tells more.
116
+ A state is bad when it breaks a rule, or when every path from the start to it passes a state
117
+ that breaks one. TLC stops each path at the first state that breaks the rule, so a rule that
118
+ stays broken colors only the states where it first breaks and the states after them that no
119
+ path without a bug reaches.
120
+ A thick blue border and numbered labels mark the bug. Mermaid state diagrams cannot color an
121
+ edge.
122
+ A label "with the fix, STEP" or "in the spec, STEP" is a step that only the other model takes. On
123
+ a bug's path it leaves the state before the first step that the other model shows the reader
124
+ differently, and ends where that model goes instead. "with the fix, STEP cannot happen" or "in
125
+ the spec, STEP cannot happen" loops on the state where that model stops the step. Outside
126
+ regions, two states have at most one arrow between them. Its lines are the numbered steps, then
127
+ SPEC.tla's steps, then the other model's steps, with a blank line between each group.
128
+ An edge lists every step that takes it, most common first. Words that the steps share at the
129
+ start are written once, as in "you tap Pay or Back".
130
+
131
+ Regenerate
132
+ With --expect-broken, one script rebuilds every chart and stops on any change:
133
+ set -e
134
+ node statechart.mjs from-spec Code.tla --against Agreed.tla --expect-broken NoLostUpload --png
135
+
136
+ TLC
137
+ TLA2TOOLS is the path to tla2tools.jar, and JAVA is the java binary (default: java, Java 11 or
138
+ later). Download tla2tools.jar from https://github.com/tlaplus/tlaplus/releases/download/v1.8.0/tla2tools.jar. When TLA2TOOLS
139
+ is not set, the command says where to get TLC and exits 2.
140
+
141
+ Exit codes
142
+ 0 Every rule holds, or exactly the --expect-broken rules break. from-chart also draws CHART.mmd
143
+ back unchanged.
144
+ 1 Another rule is broken, an expected rule holds, or the chart that the spec draws is not
145
+ CHART.mmd. The output says which.
146
+ 2 The command cannot finish: a bad argument, a missing file, a chart or TLC output that it
147
+ cannot read, no TLC, a helper script that cannot start, an output folder with files that the
148
+ command did not write, an input file that changed during the run, a new mapping to fill in,
149
+ or a chart that --png cannot render. When a chart does not render, the command keeps the
150
+ files it wrote and exits 2, whatever the rules give. Otherwise, exit 2 does not change the
151
+ output folder, unless the command moved it aside and cannot put it back. Then the message
152
+ names the folder's new path. When TLC stops on an error, the message names TLC's output, in a
153
+ temporary folder that the command keeps.`;
154
+
155
+ const HELP = {
156
+ "": `${usage([...Object.values(USAGE), "node statechart.mjs [from-spec|from-chart] --help"])}
157
+
158
+ Draws a Mermaid statechart of what an app's user sees, from TLC's state graph of a TLA+ spec. The
159
+ help calls that user the reader.
160
+
161
+ ${FROM_SPEC}
162
+
163
+ ${FROM_CHART}
164
+
165
+ ${COMMON}`,
166
+ "from-spec": `${usage([USAGE["from-spec"]])}\n\n${FROM_SPEC}\n\n${COMMON}`,
167
+ "from-chart": `${usage([USAGE["from-chart"]])}\n\n${FROM_CHART}\n\n${COMMON}`,
168
+ };
169
+
170
+ const more = (cmd) =>
171
+ `Run node statechart.mjs ${cmd ? `${cmd} ` : ""}--help for the flags, the output, and the exit codes.`;
172
+
173
+ class CannotFinish extends Error {}
174
+ class TlcStopped extends CannotFinish {}
175
+
176
+ const COMMANDS = {
177
+ "from-spec": {
178
+ flags: ["--map", "--fixed", "--against", "--label", "--expect-broken", "--title", "--out"],
179
+ run: fromSpec,
180
+ },
181
+ "from-chart": { flags: ["--module", "--expect-broken", "--title", "--out"], run: fromChart },
182
+ };
183
+
184
+ function parseArgs([command, ...rest]) {
185
+ if (command === "-h" || command === "--help") return { help: HELP[""] };
186
+ if (!Object.hasOwn(COMMANDS, command))
187
+ throw new CannotFinish(`${usage(Object.values(USAGE))}\n${more()}`);
188
+ const flags = { "expect-broken": new Set() };
189
+ let input;
190
+ for (let i = 0; i < rest.length; i++) {
191
+ const a = rest[i];
192
+ if (a === "-h" || a === "--help") return { help: HELP[command] };
193
+ if (a === "--png") flags.png = true;
194
+ else if (COMMANDS[command].flags.includes(a)) {
195
+ if (i + 1 === rest.length) throw new CannotFinish(`${a} needs a value. ${more(command)}`);
196
+ const name = a.slice(2);
197
+ if (flags[name] instanceof Set) for (const v of rest[++i].split(",")) flags[name].add(v);
198
+ else flags[name] = rest[++i];
199
+ } else if (!a.startsWith("-") && input === undefined) input = a;
200
+ else throw new CannotFinish(`unknown argument ${a}. ${more(command)}`);
201
+ }
202
+ if (input === undefined) throw new CannotFinish(`${usage([USAGE[command]])}\n${more(command)}`);
203
+ return { command, input, flags };
204
+ }
205
+
206
+ const rel = (file) => path.relative(process.cwd(), file) || ".";
207
+ const cfgOf = (spec) => spec.replace(/\.tla$/, ".cfg");
208
+
209
+ function findTools() {
210
+ try {
211
+ return findTlc();
212
+ } catch (e) {
213
+ throw new CannotFinish(e.message);
214
+ }
215
+ }
216
+
217
+ function script(name, scriptArgs, about, { okExits = [0] } = {}) {
218
+ const r = spawnSync(process.execPath, [path.join(here, name), ...scriptArgs], {
219
+ encoding: "utf8",
220
+ });
221
+ if (r.error) throw new CannotFinish(`cannot run ${name}: ${r.error.message}`);
222
+ if (okExits.includes(r.status)) return r;
223
+ const thrown = r.stderr.match(/^Error: (.*)$/m)?.[1];
224
+ throw new CannotFinish(thrown ? `${rel(about)}: ${thrown}` : r.stderr.trim());
225
+ }
226
+
227
+ const KEYWORD =
228
+ /^(SPECIFICATION|INIT|NEXT|CONSTANTS?|INVARIANTS?|PROPERTY|PROPERTIES|SYMMETRY|VIEW|CONSTRAINTS?|ACTION_CONSTRAINTS?|CHECK_DEADLOCK|POSTCONDITION|ALIAS)$/;
229
+
230
+ function splitRules(cfg) {
231
+ const words = cfg
232
+ .replace(/\(\*[^]*?\*\)/g, " ")
233
+ .replace(/\\\*.*/g, " ")
234
+ .split(/\s+/)
235
+ .filter(Boolean);
236
+ const kept = [];
237
+ const rules = [];
238
+ let section = "";
239
+ for (const w of words) {
240
+ if (KEYWORD.test(w)) section = w;
241
+ if (!/^INVARIANTS?$/.test(section)) kept.push(KEYWORD.test(w) && kept.length ? `\n${w}` : w);
242
+ else if (w !== section && !rules.includes(w)) rules.push(w);
243
+ }
244
+ return { cfgWithoutRules: `${kept.join(" ")}\n`, rules };
245
+ }
246
+
247
+ function tlc(tools, spec, cfg, base, dump) {
248
+ fs.writeFileSync(`${base}.cfg`, cfg);
249
+ const metadir = fs.mkdtempSync(path.join(os.tmpdir(), "tlc-"));
250
+ // TLC writes the standard modules, such as Naturals.tla, to java.io.tmpdir under fixed names,
251
+ // so runs that share that folder can read a module while another run rewrites it.
252
+ const javaTmp = path.join(metadir, "tmp");
253
+ fs.mkdirSync(javaTmp);
254
+ // -deadlock: a UI at rest has nothing left to do, which TLC would report as a deadlock.
255
+ const r = spawnSync(
256
+ tools.java,
257
+ [
258
+ `-Djava.io.tmpdir=${javaTmp}`,
259
+ "-cp",
260
+ tools.jar,
261
+ "tlc2.TLC",
262
+ "-metadir",
263
+ metadir,
264
+ "-deadlock",
265
+ "-continue",
266
+ ...(dump ? ["-dump", "dot,actionlabels", path.resolve(dump)] : []),
267
+ "-config",
268
+ path.resolve(`${base}.cfg`),
269
+ path.basename(spec),
270
+ ],
271
+ { cwd: path.dirname(path.resolve(spec)), encoding: "utf8", maxBuffer: 1 << 30 },
272
+ );
273
+ fs.rmSync(metadir, { recursive: true, force: true });
274
+ if (r.error) throw new CannotFinish(`cannot run TLC: ${r.error.message}`);
275
+ fs.writeFileSync(`${base}.out`, r.stdout);
276
+ try {
277
+ checkTlcOutput(r.stdout, `${base}.out`);
278
+ } catch (e) {
279
+ throw new TlcStopped(e.message);
280
+ }
281
+ return r.stdout;
282
+ }
283
+
284
+ function warnUnnamedSteps(spec, cfg, dot) {
285
+ const text = fs
286
+ .readFileSync(spec, "utf8")
287
+ .replace(/\(\*[^]*?\*\)/g, " ")
288
+ .replace(/\\\*.*/g, " ");
289
+ const specName = /^SPECIFICATION\s+(\w+)/m.exec(cfg)?.[1];
290
+ const specBody = specName && new RegExp(`^${specName}\\s*==(.*(\\n[ \\t]+.*)*)`, "m").exec(text);
291
+ const next =
292
+ /^NEXT\s+(\w+)/m.exec(cfg)?.[1] ?? /\[\]\s*\[\s*(\w+)\s*\]_/.exec(specBody?.[1] ?? text)?.[1];
293
+ const graph = parseDot(fs.readFileSync(dot, "utf8"));
294
+ const unnamed = [...graph.edges, ...graph.loops].filter((e) => e.action === next).length;
295
+ if (unnamed > 0)
296
+ console.error(
297
+ `${rel(spec)}: ${unnamed} ${unnamed === 1 ? "step has" : "steps have"} the name ${next}, the whole next-state action, because TLC names a step after the innermost named action that takes it. If the reader must tell these steps apart, give each part of ${next} its own name, as in Pay == ... and ${next} == Pay \\/ Charge.`,
298
+ );
299
+ }
300
+
301
+ function readModel(spec, cfgFile) {
302
+ if (!fs.existsSync(spec)) throw new CannotFinish(`${rel(spec)} does not exist`);
303
+ if (!fs.existsSync(cfgFile))
304
+ throw new CannotFinish(
305
+ `${rel(cfgFile)} does not exist. It needs SPECIFICATION and one INVARIANT line per rule.`,
306
+ );
307
+ return { spec, cfgFile, ...splitRules(fs.readFileSync(cfgFile, "utf8")) };
308
+ }
309
+
310
+ function readInput(spec, expected) {
311
+ const model = readModel(spec, cfgOf(spec));
312
+ const unknown = [...expected].filter((r) => !model.rules.includes(r));
313
+ if (unknown.length)
314
+ throw new CannotFinish(
315
+ `--expect-broken ${unknown.join(", ")}: not a rule in ${rel(model.cfgFile)}, whose rules are ${model.rules.join(", ") || "none"}.`,
316
+ );
317
+ return model;
318
+ }
319
+
320
+ function check(tools, { spec, cfgFile, cfgWithoutRules, rules }, work, expected) {
321
+ const name = path.basename(spec, ".tla");
322
+ const tlcDir = path.join(work, "tlc");
323
+ const dot = path.join(tlcDir, `${name}.dot`);
324
+ tlc(tools, spec, cfgWithoutRules, path.join(tlcDir, name), dot);
325
+ warnUnnamedSteps(spec, cfgWithoutRules, dot);
326
+ console.log(`TLC on ${path.basename(spec)}:`);
327
+ if (rules.length === 0)
328
+ console.log(` ${path.basename(cfgFile)} has no INVARIANT, so no rule is checked.`);
329
+ // With -continue TLC reports every bad state. The CONSTRAINT stops each path at its first bad
330
+ // state, so a rule that stays broken reports only the step that broke it, not every later state.
331
+ const traces = rules.map((rule) => {
332
+ const file = path.join(tlcDir, `${name}-${rule}`);
333
+ const cfg = `${cfgWithoutRules}INVARIANT ${rule}\nCONSTRAINT ${rule}\n`;
334
+ const broken = /^Error: Invariant /m.test(tlc(tools, spec, cfg, file));
335
+ console.log(
336
+ ` ${rule} ${broken ? (expected.has(rule) ? "is broken (expected)" : "is broken") : "holds"}.`,
337
+ );
338
+ return { file: `${file}.out`, rule, broken };
339
+ });
340
+ return { spec, dot, traces, broken: traces.some((t) => t.broken) };
341
+ }
342
+
343
+ function rulesAsExpected(now, other, expected) {
344
+ const brokenIn = (m) => (m?.traces ?? []).filter((t) => t.broken).map((t) => t.rule);
345
+ if (expected.size === 0) return !now.broken && !other?.broken;
346
+ const unexpected = [...new Set([...brokenIn(now), ...brokenIn(other)])].filter(
347
+ (r) => !expected.has(r),
348
+ );
349
+ const holds = [...expected].filter((r) => !brokenIn(now).includes(r));
350
+ if (unexpected.length) console.log(`\nBroken but not expected: ${unexpected.join(", ")}.`);
351
+ if (holds.length) console.log(`\nExpected to break but holds: ${holds.join(", ")}.`);
352
+ if (!unexpected.length && !holds.length)
353
+ console.log(`\nBroken as expected: ${[...expected].join(", ")}.`);
354
+ return !unexpected.length && !holds.length;
355
+ }
356
+
357
+ const SCAFFOLD = (name, graph) => {
358
+ const vars = Object.keys([...graph.nodes.values()][0]?.vars ?? {});
359
+ const actions = [...new Set([...graph.edges, ...graph.loops].map((e) => e.action))].sort();
360
+ return `// Chart labels for ${name}, for statechart.mjs. Write labels in plain words, not variable or action names.
361
+ // v, before, and after map each variable to its value. Strings, numbers, and booleans keep their kind.
362
+ // Sequences, tuples, and sets become arrays, indexed from 0. Records and functions become objects.
363
+ // Variables: ${vars.join(", ")}.
364
+
365
+ // The actions the reader takes. facts.settled is true when only these are enabled, and the overview
366
+ // keeps the shortest path to each settled state, plus every bug path.
367
+ export const readerActions = [];
368
+
369
+ // The label for one model state. facts.enabled is the set of actions the state enables,
370
+ // including steps that change no variable. Write it as "context: progress", such as
371
+ // "Offline: upload queued": the chart puts the states of one context in one box.
372
+ // Do not claim a result that a pending step can still change, such as "upload failed" while a
373
+ // retry is still queued.
374
+ export function state(v, facts) {
375
+ return JSON.stringify(v);
376
+ }
377
+
378
+ // The names of the two parallel regions, when the overview draws them: contexts, then progress.
379
+ // export const regionNames = ["Network", "What happened to the file"];
380
+
381
+ // The group of one model state, in words the reader sees, such as "Upload done". The chart fills
382
+ // the states of one group with one color, and the legend names the groups. TLC still decides
383
+ // which states break a rule, and draws them with a thick red border on top of the group color.
384
+ // groupColors gives a group a light color. Groups without one take a palette color.
385
+ // export function group(v, facts) {}
386
+ // export const groupColors = { "Upload done": "#d1f2eb" };
387
+
388
+ // The label for one step. A step that leaves the reader in the same state is not drawn,
389
+ // unless the reader takes it on a bug path. "" draws no label, and a numbered bug step shows the action.
390
+ const STEPS = {
391
+ ${actions.map((a) => `\t${a}: ${JSON.stringify(a)},`).join("\n")}
392
+ };
393
+ export function step(action, before, after) {
394
+ return STEPS[action] ?? action;
395
+ }
396
+
397
+ // When the step can happen, in plain words, such as "offline or disk full". The chart shows
398
+ // "step [words]". "" adds nothing.
399
+ // export function guard(action, before, after) {}
400
+
401
+ // For a timer step, how many seconds the code waits, from the constant in the code. The chart
402
+ // shows "after N s, step". Return nothing for other steps.
403
+ // export function timer(action, before, after) {}
404
+
405
+ // Why a bad state is bad, in words a product manager reads, such as "the laptop went offline, and
406
+ // the app drops an upload it cannot send". No variable, function, or event names.
407
+ // Counterexamples that break one rule with one cause are one bug, so two bugs that end on the
408
+ // same screen stay apart only if their causes differ. Return null to group by the end state.
409
+ // export function cause(v, facts, invariant) {}
410
+
411
+ // The developer's words for one model state. With it, each bug is also drawn through these states.
412
+ // export function detail(v, facts) {}
413
+
414
+ // The legend's words for each status, in place of the defaults. Group entries keep their names.
415
+ // export const legend = { works: "Works on main", wrong: "Wrong on main", fixed: "Fixed in the open PR" };
416
+ `;
417
+ };
418
+
419
+ async function draw({ now, other, map, work, out, title, comparing }) {
420
+ const shown = published(work, out);
421
+ const mapping = await import(pathToFileURL(path.resolve(map)).href);
422
+ const from = ["--dot", now.dot, "--map", map, "--spec", now.spec];
423
+ from.push(...now.traces.flatMap((t) => ["--traces", t.file]));
424
+ if (other) {
425
+ from.push(`--${other.role}-dot`, other.dot, "--spec", other.spec);
426
+ from.push(...other.traces.flatMap((t) => [`--${other.role}-traces`, t.file]));
427
+ if (other.label !== undefined) from.push("--label", other.label);
428
+ }
429
+ if (comparing) from.push("--full-labels", "--flat");
430
+ else if (mapping.readerActions?.length) from.push("--cover");
431
+ const titled = (suffix) => (title ? ["--title", `${title}${suffix}`] : []);
432
+
433
+ const files = {
434
+ overview: path.join(work, "chart.mmd"),
435
+ stories: path.join(work, "stories.md"),
436
+ summary: path.join(work, "summary.json"),
437
+ };
438
+ const proof = path.join(work, "tlc", "regions-proof.mmd");
439
+ const everyArrow = path.join(work, "tlc", "regions-all.mmd");
440
+ script(
441
+ "tlc-to-chart.mjs",
442
+ [
443
+ ...from,
444
+ ...(comparing ? [] : ["--regions", "--proof", proof, "--regions-all", everyArrow]),
445
+ ...titled(""),
446
+ "--highlight",
447
+ "0",
448
+ "--out",
449
+ files.overview,
450
+ "--story",
451
+ files.stories,
452
+ "--summary",
453
+ files.summary,
454
+ ],
455
+ map,
456
+ );
457
+ const summary = JSON.parse(fs.readFileSync(files.summary, "utf8"));
458
+ const charts = [files.overview];
459
+ for (const c of summary.classes) {
460
+ const views = typeof mapping.detail === "function" ? ["", "-developer", "-layered"] : [""];
461
+ for (const view of views) {
462
+ const file = path.join(work, `bug-${c.n}${view}.mmd`);
463
+ const shape = [...(view ? ["--view", view.slice(1)] : []), "--path-only"];
464
+ script(
465
+ "tlc-to-chart.mjs",
466
+ [...from, ...shape, ...titled(`, bug ${c.n}`), "--highlight", String(c.n), "--out", file],
467
+ map,
468
+ );
469
+ charts.push(file);
470
+ }
471
+ }
472
+
473
+ const { works, wrong, fixed: fixedCount } = summary.chartStatus;
474
+ const L = summary.second?.label;
475
+ console.log(
476
+ `\nChart: ${summary.chartStates} states and ${summary.chartTransitions} transitions from ${summary.modelStates} model states.`,
477
+ );
478
+ const r = summary.regions;
479
+ if (r?.drawn)
480
+ console.log(
481
+ `It has 2 parallel regions, of ${r.states[0]} and ${r.states[1]} states. Proof: their ${r.all} arrows together make exactly the ${r.flat.states} states and ${r.flat.transitions} labeled steps of ${shown(proof)}, and the ${r.transitions} drawn arrows make only steps among them. ${shown(everyArrow)} has all ${r.all} arrows.`,
482
+ );
483
+ else if (r) console.log(`It has no parallel regions, because ${r.why}.`);
484
+ const breaks = `${wrong} ${wrong === 1 ? "breaks" : "break"} a rule`;
485
+ console.log(
486
+ other?.role === "fixed"
487
+ ? `${works} work today, ${wrong} still wrong with ${L}, ${fixedCount} fixed or new with ${L}.\n`
488
+ : other?.role === "against"
489
+ ? `${works} work, ${breaks}, ${fixedCount} only in ${L}.\n`
490
+ : `${works} work, ${breaks}.\n`,
491
+ );
492
+ if (summary.codeLike.length)
493
+ console.log(
494
+ `These labels or causes read like code. Write them in the reader's words in ${rel(map)}:\n${summary.codeLike.map((t) => ` ${t}`).join("\n")}\n`,
495
+ );
496
+ console.log(
497
+ summary.classes.length
498
+ ? fs.readFileSync(files.stories, "utf8").trimEnd()
499
+ : "No rule is broken.",
500
+ );
501
+ return { files, charts };
502
+ }
503
+
504
+ function render(charts, shown) {
505
+ const pngs = [];
506
+ for (const chart of charts) {
507
+ const png = chart.replace(/\.mmd$/, ".png");
508
+ const r = spawnSync(
509
+ process.env.MERMAID_CLI || "mmdc",
510
+ [ "-i", chart, "-o", png, "-s", "2"],
511
+ {
512
+ encoding: "utf8",
513
+ },
514
+ );
515
+ if (r.status === 0) pngs.push(png);
516
+ else
517
+ console.error(
518
+ `could not render ${shown(chart)}: ${(r.stderr || r.error?.message || "").trim()}`,
519
+ );
520
+ }
521
+ return pngs;
522
+ }
523
+
524
+ function finish({ work, out, inputs }, { files, charts }, ok, png) {
525
+ const pngs = png ? render(charts, published(work, out)) : [];
526
+ publish(work, out, inputs);
527
+ const written = [...charts, ...pngs, files.stories, files.summary]
528
+ .map((f) => path.basename(f))
529
+ .join(", ");
530
+ console.log(`\nWrote ${written} in ${rel(out)}.`);
531
+ if (png && pngs.length < charts.length) return 2;
532
+ return ok ? 0 : 1;
533
+ }
534
+
535
+ const published = (work, out) => (file) => rel(path.join(out, path.relative(work, file)));
536
+
537
+ const OWN =
538
+ /^((chart|bug-\d+(-developer|-layered)?)\.(mmd|png)|stories\.md|summary\.json|tlc|\.DS_Store)$/;
539
+
540
+ function foreign(dir) {
541
+ try {
542
+ return fs
543
+ .readdirSync(dir)
544
+ .filter((f) => !OWN.test(f))
545
+ .sort();
546
+ } catch (e) {
547
+ if (e.code === "ENOENT") return [];
548
+ throw new CannotFinish(`cannot use ${rel(dir)} as the output folder: ${e.message}`);
549
+ }
550
+ }
551
+
552
+ function refuseForeign(out, files = foreign(out)) {
553
+ const [first, ...others] = files;
554
+ if (first)
555
+ throw new CannotFinish(
556
+ `${rel(out)} has ${others.length ? `${others.length + 1} files that this command did not write, such as ${first}` : `a file that this command did not write: ${first}`}. A run puts its files in place of the whole output folder, so pass --out with a new folder.`,
557
+ );
558
+ }
559
+
560
+ function outDir(flagged, input, name) {
561
+ const out = flagged ?? path.join(path.dirname(input), `${name}-statechart`);
562
+ refuseForeign(out);
563
+ return out;
564
+ }
565
+
566
+ const fingerprint = (file) => {
567
+ try {
568
+ const { ino, ctimeNs } = fs.statSync(file, { bigint: true });
569
+ return `${ino} ${ctimeNs} ${fs.readFileSync(file, "base64")}`;
570
+ } catch {
571
+ return null;
572
+ }
573
+ };
574
+
575
+ function snapshot(files, inputs = new Map()) {
576
+ for (const f of files) if (f && !inputs.has(f)) inputs.set(f, fingerprint(f));
577
+ return inputs;
578
+ }
579
+
580
+ async function inWorkFolder(body) {
581
+ const work = fs.mkdtempSync(path.join(os.tmpdir(), "statechart-"));
582
+ fs.mkdirSync(path.join(work, "tlc"));
583
+ let keep = false;
584
+ try {
585
+ return await body(work);
586
+ } catch (e) {
587
+ keep = e instanceof TlcStopped;
588
+ throw e;
589
+ } finally {
590
+ if (!keep) fs.rmSync(work, { recursive: true, force: true });
591
+ }
592
+ }
593
+
594
+ const moved = (from, to, ...missed) => {
595
+ try {
596
+ fs.renameSync(from, to);
597
+ return true;
598
+ } catch (e) {
599
+ if (missed.includes(e.code)) return false;
600
+ throw e;
601
+ }
602
+ };
603
+
604
+ function publish(work, out, inputs) {
605
+ const parent = path.dirname(path.resolve(out));
606
+ fs.mkdirSync(parent, { recursive: true });
607
+ const next = fs.mkdtempSync(path.join(parent, `.${path.basename(out)}-`));
608
+ const old = `${next}-old`;
609
+ let aside = false;
610
+ try {
611
+ fs.cpSync(work, next, { recursive: true });
612
+ const changed = [...inputs].find(([f, was]) => fingerprint(f) !== was)?.[0];
613
+ if (changed)
614
+ throw new CannotFinish(
615
+ `${rel(changed)} changed while this run read it, so the run left ${rel(out)} as it was. Run the command again.`,
616
+ );
617
+ refuseForeign(out);
618
+ while (!moved(next, out, "ENOTEMPTY", "EEXIST")) {
619
+ if (aside) {
620
+ refuseForeign(out);
621
+ fs.rmSync(old, { recursive: true, force: true });
622
+ aside = false;
623
+ }
624
+ aside = moved(out, old, "ENOENT");
625
+ if (aside) refuseForeign(out, foreign(old));
626
+ }
627
+ } catch (e) {
628
+ const back = !aside || putBack(old, out);
629
+ fs.rmSync(next, { recursive: true, force: true });
630
+ const why = e instanceof CannotFinish ? e.message : `cannot replace ${rel(out)}: ${e.message}.`;
631
+ if (!back)
632
+ throw new CannotFinish(
633
+ `${why} This run moved the previous ${rel(out)} to ${rel(old)} and could not put it back.`,
634
+ );
635
+ throw e instanceof CannotFinish
636
+ ? e
637
+ : new CannotFinish(`${why} The run left ${rel(out)} as it was.`);
638
+ }
639
+ if (aside) fs.rmSync(old, { recursive: true, force: true });
640
+ }
641
+
642
+ function putBack(old, out) {
643
+ try {
644
+ return moved(old, out, "ENOTEMPTY", "EEXIST");
645
+ } catch {
646
+ return false;
647
+ }
648
+ }
649
+
650
+ function secondModel(input, { fixed, against, label }) {
651
+ if (fixed && against)
652
+ throw new CannotFinish(`use --fixed or --against, not both. ${more("from-spec")}`);
653
+ if (!fixed && !against) {
654
+ if (label === undefined) return null;
655
+ throw new CannotFinish(
656
+ `--label names the --fixed or --against model; it needs one of them. ${more("from-spec")}`,
657
+ );
658
+ }
659
+ const [role, spec] = fixed ? ["fixed", fixed] : ["against", against];
660
+ const name = path.basename(input, ".tla");
661
+ // TLC's output files are named after the spec, so a second model with the same name overwrites them.
662
+ if (path.basename(spec, ".tla") === name)
663
+ throw new CannotFinish(
664
+ `${rel(spec)} needs its own file and module name, such as ${name}${fixed ? "Fixed" : "Agreed"}.tla.`,
665
+ );
666
+ const cfg = fs.existsSync(cfgOf(spec)) ? cfgOf(spec) : cfgOf(input);
667
+ return { role, label, model: readModel(spec, cfg) };
668
+ }
669
+
670
+ async function fromSpec(input, { "expect-broken": expected, ...flags }) {
671
+ const name = path.basename(input, ".tla");
672
+ const map = flags.map ?? path.join(path.dirname(input), `${name}.map.mjs`);
673
+ const secondSpec = flags.fixed ?? flags.against;
674
+ const inputs = snapshot([input, cfgOf(input), map, secondSpec, secondSpec && cfgOf(secondSpec)]);
675
+ const second = secondModel(input, flags);
676
+ const tools = findTools();
677
+ const model = readInput(input, expected);
678
+ const out = outDir(flags.out, input, name);
679
+ return inWorkFolder(async (work) => {
680
+ const now = check(tools, model, work, expected);
681
+ if (!fs.existsSync(map)) {
682
+ fs.writeFileSync(map, SCAFFOLD(name, parseDot(fs.readFileSync(now.dot, "utf8"))));
683
+ throw new CannotFinish(
684
+ `\nWrote ${rel(map)}. Fill in its labels, then run this command again.`,
685
+ );
686
+ }
687
+ const other = second && {
688
+ role: second.role,
689
+ label: second.label,
690
+ ...check(tools, second.model, work, expected),
691
+ };
692
+ const drawn = await draw({ now, other, map, work, out, title: flags.title });
693
+ return finish({ work, out, inputs }, drawn, rulesAsExpected(now, other, expected), flags.png);
694
+ });
695
+ }
696
+
697
+ async function fromChart(input, { "expect-broken": expected, ...flags }) {
698
+ const name =
699
+ flags.module ??
700
+ path
701
+ .basename(input, path.extname(input))
702
+ .replace(/(^|[^A-Za-z0-9]+)([A-Za-z0-9])/g, (_, __, c) => c.toUpperCase());
703
+ if (!/^[A-Za-z][A-Za-z0-9_]*$/.test(name))
704
+ throw new CannotFinish(`cannot make a TLA+ module name from ${input}; add --module NAME`);
705
+ const spec = path.join(path.dirname(input), `${name}.tla`);
706
+ const map = spec.replace(/\.tla$/, ".map.mjs");
707
+ const inputs = snapshot([input]);
708
+ if (fs.existsSync(spec)) {
709
+ console.log(`Kept ${rel(spec)}. Delete it to write the spec again from ${rel(input)}.`);
710
+ } else {
711
+ script("chart-to-tla.mjs", [input, "--module", name], input);
712
+ console.log(`Wrote ${name}.tla, ${name}.cfg, and ${name}.map.mjs from ${rel(input)}.`);
713
+ }
714
+ snapshot([spec, cfgOf(spec), map], inputs);
715
+ const tools = findTools();
716
+ const model = readInput(spec, expected);
717
+ const out = outDir(flags.out, input, name);
718
+ return inWorkFolder(async (work) => {
719
+ const now = check(tools, model, work, expected);
720
+ const drawn = await draw({ now, map, work, out, title: flags.title, comparing: true });
721
+ const compared = script("compare-charts.mjs", [input, drawn.files.overview], input, {
722
+ okExits: [0, 1],
723
+ });
724
+ if (compared.status === 0) console.log(`\nThe spec draws ${rel(input)} back unchanged.`);
725
+ else
726
+ console.log(
727
+ `\nThe spec does not draw ${rel(input)}:\n${compared.stdout.trimEnd().replace(/^/gm, " ")}`,
728
+ );
729
+ return finish(
730
+ { work, out, inputs },
731
+ drawn,
732
+ rulesAsExpected(now, null, expected) && compared.status === 0,
733
+ flags.png,
734
+ );
735
+ });
736
+ }
737
+
738
+ try {
739
+ const { help, command, input, flags } = parseArgs(process.argv.slice(2));
740
+ if (help) {
741
+ console.log(help);
742
+ process.exit(0);
743
+ }
744
+ process.exit(await COMMANDS[command].run(input, flags));
745
+ } catch (e) {
746
+ if (!(e instanceof CannotFinish)) throw e;
747
+ console.error(e.message);
748
+ process.exit(2);
749
+ }