dsh-pstack 0.2.0-beta.1 → 0.2.0-beta.3

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 (261) hide show
  1. package/LICENSE +2 -3
  2. package/README.md +135 -84
  3. package/README.zh.md +185 -0
  4. package/cordis.patch.yml +97 -27
  5. package/dist/host-contract-CUPSpeNk.d.mts +22 -0
  6. package/dist/index.d.mts +49 -238
  7. package/dist/index.mjs +250 -123
  8. package/dist/models.d.mts +44 -0
  9. package/dist/models.mjs +201 -0
  10. package/dist/paths-BT77khwm.mjs +48 -0
  11. package/dist/pstack/LICENSE +21 -0
  12. package/dist/pstack/README.md +291 -0
  13. package/dist/pstack/agents/poteto-agent.md +9 -0
  14. package/{assets → dist/pstack}/docs/guide/01-setup.md +13 -11
  15. package/{assets → dist/pstack}/docs/guide/02-poteto-mode.md +4 -4
  16. package/{assets → dist/pstack}/docs/guide/04-design.md +4 -4
  17. package/{assets → dist/pstack}/docs/guide/05-build-and-clean.md +2 -2
  18. package/{assets → dist/pstack}/docs/guide/06-verify-and-ship.md +13 -3
  19. package/{assets → dist/pstack}/docs/guide/07-overnight.md +15 -13
  20. package/{assets → dist/pstack}/docs/guide/09-make-it-yours.md +6 -2
  21. package/{assets → dist/pstack}/docs/guide/10-recipes-and-pitfalls.md +7 -5
  22. package/{assets → dist/pstack}/docs/guide/README.md +1 -1
  23. package/dist/pstack/docs/harness/dsh.md +98 -0
  24. package/{assets → dist/pstack}/skills/architect/SKILL.md +12 -12
  25. package/dist/pstack/skills/arena/SKILL.md +50 -0
  26. package/{assets → dist/pstack}/skills/automate-me/SKILL.md +14 -14
  27. package/{assets → dist/pstack}/skills/benchmark-checklist/SKILL.md +1 -1
  28. package/{assets → dist/pstack}/skills/blast-radius/SKILL.md +4 -6
  29. package/{assets → dist/pstack}/skills/correct/SKILL.md +1 -1
  30. package/{assets → dist/pstack}/skills/create-formal-verification-skill/SKILL.md +4 -2
  31. package/{assets → dist/pstack}/skills/create-verification-skill/SKILL.md +5 -5
  32. package/dist/pstack/skills/figure-it-out/SKILL.md +54 -0
  33. package/dist/pstack/skills/how/SKILL.md +38 -0
  34. package/{assets → dist/pstack}/skills/in-your-own-words/SKILL.md +1 -1
  35. package/dist/pstack/skills/interrogate/SKILL.md +33 -0
  36. package/{assets → dist/pstack}/skills/ketchup/SKILL.md +3 -5
  37. package/dist/pstack/skills/ketchup-video/SKILL.md +29 -0
  38. package/{assets → dist/pstack}/skills/maintain-formal-verification-skill/SKILL.md +1 -1
  39. package/{assets → dist/pstack}/skills/maintain-verification-skill/SKILL.md +3 -3
  40. package/dist/pstack/skills/make-bot-ui/SKILL.md +117 -0
  41. package/dist/pstack/skills/no-comments/SKILL.md +26 -0
  42. package/{assets → dist/pstack}/skills/poteto-help/SKILL.md +34 -31
  43. package/{assets → dist/pstack}/skills/poteto-help/references/prompting.md +1 -1
  44. package/{assets → dist/pstack}/skills/poteto-help/references/recipes.md +3 -3
  45. package/{assets → dist/pstack}/skills/poteto-mode/SKILL.md +20 -19
  46. package/dist/pstack/skills/poteto-mode/playbooks/authoring-a-skill.md +12 -0
  47. package/dist/pstack/skills/poteto-mode/playbooks/autonomous-run.md +13 -0
  48. package/dist/pstack/skills/poteto-mode/playbooks/autopilot-full.md +25 -0
  49. package/dist/pstack/skills/poteto-mode/playbooks/autopilot-stack.md +8 -0
  50. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/babysit.md +4 -4
  51. package/dist/pstack/skills/poteto-mode/playbooks/bug-fix.md +15 -0
  52. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/eval.md +3 -3
  53. package/dist/pstack/skills/poteto-mode/playbooks/feature.md +21 -0
  54. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/hillclimb.md +3 -3
  55. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/investigation.md +2 -2
  56. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/multi-phase-plan.md +23 -23
  57. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/opening-a-pr.md +6 -6
  58. package/dist/pstack/skills/poteto-mode/playbooks/orchestrate.md +25 -0
  59. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/pause-safely.md +2 -2
  60. package/dist/pstack/skills/poteto-mode/playbooks/perf-issue.md +25 -0
  61. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/prototype.md +4 -4
  62. package/dist/pstack/skills/poteto-mode/playbooks/refactoring.md +16 -0
  63. package/dist/pstack/skills/poteto-mode/playbooks/runtime-forensics.md +11 -0
  64. package/dist/pstack/skills/poteto-mode/playbooks/session-pickup.md +11 -0
  65. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/shipping.md +2 -2
  66. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/trace-forensics.md +2 -2
  67. package/dist/pstack/skills/poteto-mode/playbooks/visual-parity.md +11 -0
  68. package/dist/pstack/skills/poteto-mode/playbooks/worktree-cleanup.md +12 -0
  69. package/{assets → dist/pstack}/skills/poteto-mode/scripts/check-plan.mjs +6 -8
  70. package/dist/pstack/skills/poteto-mode/scripts/check-plan.test.mjs +128 -0
  71. package/{assets/skills/poteto-mode/scripts/check-plan.test.mjs → dist/pstack/skills/poteto-mode/scripts/expect.mjs} +12 -101
  72. package/dist/pstack/skills/poteto-mode/scripts/support.mjs +93 -0
  73. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/cli.mjs +123 -0
  74. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/cli.test.mjs +217 -0
  75. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/fakes.test-helper.mjs +119 -0
  76. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/github.mjs +626 -0
  77. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/github.test.mjs +521 -0
  78. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/policy.mjs +657 -0
  79. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/policy.test.mjs +523 -0
  80. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/render.mjs +106 -0
  81. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/types.mjs +9 -0
  82. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/watch-pr.mjs +5 -0
  83. package/{assets → dist/pstack}/skills/poteto-mode/scripts/worktree-audit.mjs +15 -22
  84. package/dist/pstack/skills/poteto-mode/scripts/worktree-audit.test.mjs +134 -0
  85. package/{assets → dist/pstack}/skills/principle-attack-the-premise/SKILL.md +1 -1
  86. package/{assets → dist/pstack}/skills/principle-boundary-discipline/SKILL.md +1 -1
  87. package/{assets → dist/pstack}/skills/principle-encode-lessons-in-structure/SKILL.md +1 -1
  88. package/{assets → dist/pstack}/skills/principle-exhaust-the-design-space/SKILL.md +1 -1
  89. package/{assets → dist/pstack}/skills/principle-experience-first/SKILL.md +1 -1
  90. package/{assets → dist/pstack}/skills/principle-explain-the-number/SKILL.md +3 -2
  91. package/{assets → dist/pstack}/skills/principle-fix-root-causes/SKILL.md +1 -1
  92. package/{assets → dist/pstack}/skills/principle-laziness-protocol/SKILL.md +1 -1
  93. package/{assets → dist/pstack}/skills/principle-make-operations-idempotent/SKILL.md +1 -1
  94. package/{assets → dist/pstack}/skills/principle-migrate-callers-then-delete-legacy-apis/SKILL.md +1 -1
  95. package/{assets → dist/pstack}/skills/principle-minimize-reader-load/SKILL.md +1 -1
  96. package/{assets → dist/pstack}/skills/principle-model-the-domain/SKILL.md +1 -1
  97. package/{assets → dist/pstack}/skills/principle-never-block-on-the-human/SKILL.md +1 -1
  98. package/{assets → dist/pstack}/skills/principle-outcome-oriented-execution/SKILL.md +1 -1
  99. package/{assets → dist/pstack}/skills/principle-prove-it-works/SKILL.md +2 -2
  100. package/{assets → dist/pstack}/skills/principle-redesign-from-first-principles/SKILL.md +1 -1
  101. package/{assets → dist/pstack}/skills/principle-separate-before-serializing-shared-state/SKILL.md +1 -1
  102. package/{assets → dist/pstack}/skills/principle-sequence-verifiable-units/SKILL.md +1 -1
  103. package/{assets → dist/pstack}/skills/principle-subtract-before-you-add/SKILL.md +1 -1
  104. package/{assets → dist/pstack}/skills/principle-test-behavior-not-implementation/SKILL.md +1 -1
  105. package/{assets → dist/pstack}/skills/principle-type-system-discipline/SKILL.md +1 -1
  106. package/dist/pstack/skills/recall/SKILL.md +37 -0
  107. package/dist/pstack/skills/reflect/SKILL.md +71 -0
  108. package/{assets → dist/pstack}/skills/reflect/references/divergent-reviewer.md +4 -4
  109. package/{assets → dist/pstack}/skills/reflect/references/judgment-reviewer.md +2 -2
  110. package/{assets → dist/pstack}/skills/reflect/references/synthesizer.md +5 -5
  111. package/{assets → dist/pstack}/skills/reflect/references/tooling-reviewer.md +2 -2
  112. package/dist/pstack/skills/setup-pstack/SKILL.md +80 -0
  113. package/{assets → dist/pstack}/skills/sharpen/SKILL.md +1 -1
  114. package/{assets → dist/pstack}/skills/show-me-your-work/SKILL.md +8 -8
  115. package/{assets → dist/pstack}/skills/show-me-your-work/scripts/log.mjs +1 -3
  116. package/dist/pstack/skills/show-me-your-work/scripts/log.test.mjs +56 -0
  117. package/dist/pstack/skills/statechart/SKILL.md +82 -0
  118. package/dist/pstack/skills/statechart/references/render.md +93 -0
  119. package/dist/pstack/skills/statechart/scripts/backends/cfg.mjs +31 -0
  120. package/dist/pstack/skills/statechart/scripts/backends/mermaid.mjs +186 -0
  121. package/dist/pstack/skills/statechart/scripts/backends/plain-text.mjs +62 -0
  122. package/dist/pstack/skills/statechart/scripts/backends/report.mjs +84 -0
  123. package/dist/pstack/skills/statechart/scripts/frontends/config.mjs +268 -0
  124. package/dist/pstack/skills/statechart/scripts/frontends/dot.mjs +67 -0
  125. package/dist/pstack/skills/statechart/scripts/frontends/marks.mjs +94 -0
  126. package/dist/pstack/skills/statechart/scripts/frontends/messages.mjs +48 -0
  127. package/dist/pstack/skills/statechart/scripts/frontends/spec.mjs +101 -0
  128. package/dist/pstack/skills/statechart/scripts/frontends/trace.mjs +39 -0
  129. package/dist/pstack/skills/statechart/scripts/frontends/value.mjs +180 -0
  130. package/dist/pstack/skills/statechart/scripts/frontends/verdict.mjs +40 -0
  131. package/dist/pstack/skills/statechart/scripts/frontends/view.mjs +99 -0
  132. package/dist/pstack/skills/statechart/scripts/ir.mjs +277 -0
  133. package/dist/pstack/skills/statechart/scripts/passes/annotate.mjs +92 -0
  134. package/dist/pstack/skills/statechart/scripts/passes/label.mjs +210 -0
  135. package/dist/pstack/skills/statechart/scripts/passes/lift.mjs +84 -0
  136. package/dist/pstack/skills/statechart/scripts/passes/loop-check.mjs +47 -0
  137. package/dist/pstack/skills/statechart/scripts/passes/paths.mjs +72 -0
  138. package/dist/pstack/skills/statechart/scripts/passes/reach.mjs +135 -0
  139. package/dist/pstack/skills/statechart/scripts/passes/region-check.mjs +82 -0
  140. package/dist/pstack/skills/statechart/scripts/passes/regions.mjs +268 -0
  141. package/dist/pstack/skills/statechart/scripts/pipeline.mjs +72 -0
  142. package/dist/pstack/skills/statechart/scripts/run.mjs +440 -0
  143. package/dist/pstack/skills/statechart/scripts/statechart.mjs +155 -0
  144. package/dist/pstack/skills/statechart/scripts/statechart.test.mjs +198 -0
  145. package/dist/pstack/skills/statechart/scripts/worker.mjs +31 -0
  146. package/dist/pstack/skills/swarm/SKILL.md +43 -0
  147. package/{assets → dist/pstack}/skills/tdd/SKILL.md +1 -1
  148. package/{assets → dist/pstack}/skills/teach/SKILL.md +2 -2
  149. package/{assets → dist/pstack}/skills/technical-writing/SKILL.md +1 -1
  150. package/{assets → dist/pstack}/skills/typescript-best-practices/SKILL.md +3 -6
  151. package/{assets → dist/pstack}/skills/why/SKILL.md +8 -8
  152. package/dist/script.d.mts +9 -111
  153. package/dist/script.mjs +32 -329
  154. package/dist/skill.d.mts +38 -0
  155. package/dist/skill.mjs +183 -0
  156. package/dist/skills/authored/decision-audit/SKILL.md +99 -0
  157. package/dist/skills/authored/decision-audit/SKILL.zh.md +99 -0
  158. package/dist/skills/authored/decision-audit/references/recover-commit.md +17 -0
  159. package/dist/skills/authored/decision-audit/references/recover-commit.zh.md +17 -0
  160. package/dist/skills/authored/decision-write/SKILL.md +131 -0
  161. package/dist/skills/authored/decision-write/SKILL.zh.md +131 -0
  162. package/dist/skills/authored/decision-write/references/land.md +48 -0
  163. package/dist/skills/authored/decision-write/references/land.zh.md +48 -0
  164. package/dist/skills/authored/setup-project-docs/SKILL.md +58 -0
  165. package/dist/skills/authored/setup-project-docs/SKILL.zh.md +58 -0
  166. package/dist/skills/authored/setup-project-docs/references/decision-conventions.md +11 -0
  167. package/dist/skills/authored/setup-project-docs/references/decision-conventions.zh.md +11 -0
  168. package/dist/skills/vendored/retro/SKILL.md +44 -0
  169. package/dist/skills/vendored/retro/agents/openai.yaml +5 -0
  170. package/dist/skills/vendored/writing-for-agents/SKILL-MECHANICS.md +22 -0
  171. package/dist/skills/vendored/writing-for-agents/SKILL.md +81 -0
  172. package/dist/skills/vendored/writing-for-agents/agents/openai.yaml +3 -0
  173. package/dist/subagent.d.mts +56 -193
  174. package/dist/subagent.mjs +443 -741
  175. package/locale/en.json +3 -2
  176. package/locale/zh.json +3 -2
  177. package/package.json +63 -66
  178. package/assets/agents/poteto-agent.md +0 -8
  179. package/assets/docs/harness/dsh.md +0 -60
  180. package/assets/docs/pstack-models.example.md +0 -54
  181. package/assets/skills/arena/SKILL.md +0 -50
  182. package/assets/skills/figure-it-out/SKILL.md +0 -54
  183. package/assets/skills/how/SKILL.md +0 -38
  184. package/assets/skills/interrogate/SKILL.md +0 -71
  185. package/assets/skills/interrogate/references/code-quality-review.md +0 -47
  186. package/assets/skills/interrogate/references/lead-judgment.md +0 -39
  187. package/assets/skills/interrogate/references/reviewer-prompt.md +0 -62
  188. package/assets/skills/interrogate/references/rubric.md +0 -77
  189. package/assets/skills/no-comments/SKILL.md +0 -26
  190. package/assets/skills/poteto-mode/playbooks/authoring-a-skill.md +0 -12
  191. package/assets/skills/poteto-mode/playbooks/autonomous-run.md +0 -15
  192. package/assets/skills/poteto-mode/playbooks/autopilot-full.md +0 -25
  193. package/assets/skills/poteto-mode/playbooks/autopilot-stack.md +0 -12
  194. package/assets/skills/poteto-mode/playbooks/bug-fix.md +0 -15
  195. package/assets/skills/poteto-mode/playbooks/feature.md +0 -21
  196. package/assets/skills/poteto-mode/playbooks/orchestrate.md +0 -112
  197. package/assets/skills/poteto-mode/playbooks/perf-issue.md +0 -25
  198. package/assets/skills/poteto-mode/playbooks/refactoring.md +0 -16
  199. package/assets/skills/poteto-mode/playbooks/runtime-forensics.md +0 -11
  200. package/assets/skills/poteto-mode/playbooks/session-pickup.md +0 -11
  201. package/assets/skills/poteto-mode/playbooks/visual-parity.md +0 -11
  202. package/assets/skills/poteto-mode/playbooks/worktree-cleanup.md +0 -20
  203. package/assets/skills/poteto-mode/scripts/orch/orch.mjs +0 -4282
  204. package/assets/skills/poteto-mode/scripts/orch/orch.test.mjs +0 -2042
  205. package/assets/skills/poteto-mode/scripts/watch-pr/cli.test.mjs +0 -5101
  206. package/assets/skills/poteto-mode/scripts/watch-pr/github.test.mjs +0 -1177
  207. package/assets/skills/poteto-mode/scripts/watch-pr/policy.test.mjs +0 -1441
  208. package/assets/skills/poteto-mode/scripts/watch-pr/watch-pr.mjs +0 -4601
  209. package/assets/skills/recall/SKILL.md +0 -37
  210. package/assets/skills/reflect/SKILL.md +0 -69
  211. package/assets/skills/setup-pstack/SKILL.md +0 -67
  212. package/assets/skills/swarm/SKILL.md +0 -43
  213. package/dist/frontmatter-BQX3ekwP.mjs +0 -229
  214. package/dist/frontmatter-BQX3ekwP.mjs.map +0 -1
  215. package/dist/history.d.mts +0 -429
  216. package/dist/history.mjs +0 -1129
  217. package/dist/history.mjs.map +0 -1
  218. package/dist/host-contract-o47JH_r8.d.mts +0 -527
  219. package/dist/index.mjs.map +0 -1
  220. package/dist/paths-D_JlVmBk.mjs +0 -42
  221. package/dist/paths-D_JlVmBk.mjs.map +0 -1
  222. package/dist/script.mjs.map +0 -1
  223. package/dist/subagent.mjs.map +0 -1
  224. /package/{static/icon.png → assets/logo.png} +0 -0
  225. /package/{assets → dist/pstack}/agents/comment-sicko.md +0 -0
  226. /package/{assets → dist/pstack}/docs/guide/03-understand.md +0 -0
  227. /package/{assets → dist/pstack}/docs/guide/08-principles.md +0 -0
  228. /package/{assets → dist/pstack}/docs/guide/images/design.jpg +0 -0
  229. /package/{assets → dist/pstack}/docs/guide/images/overnight.jpg +0 -0
  230. /package/{assets → dist/pstack}/docs/guide/images/recipes.jpg +0 -0
  231. /package/{assets → dist/pstack}/docs/guide/images/router.jpg +0 -0
  232. /package/{assets → dist/pstack}/docs/guide/images/understanding.jpg +0 -0
  233. /package/{assets → dist/pstack}/docs/guide/images/verification.jpg +0 -0
  234. /package/{assets → dist/pstack}/skills/architect/references/design-red-flags.md +0 -0
  235. /package/{assets → dist/pstack}/skills/architect/references/rationale-template.md +0 -0
  236. /package/{assets → dist/pstack}/skills/architect/references/runner-prompt.md +0 -0
  237. /package/{assets → dist/pstack}/skills/bro/SKILL.md +0 -0
  238. /package/{assets → dist/pstack}/skills/create-verification-skill/references/feature-map-example/README.md +0 -0
  239. /package/{assets → dist/pstack}/skills/create-verification-skill/references/feature-map-example/create-note.md +0 -0
  240. /package/{assets → dist/pstack}/skills/create-verification-skill/references/feature-map-example/search.md +0 -0
  241. /package/{assets → dist/pstack}/skills/how/references/explainer-prompt.md +0 -0
  242. /package/{assets → dist/pstack}/skills/how/references/explorer-prompt.md +0 -0
  243. /package/{assets → dist/pstack}/skills/poteto-mode/references/bugbot-triage.md +0 -0
  244. /package/{assets → dist/pstack}/skills/principle-build-the-lever/SKILL.md +0 -0
  245. /package/{assets → dist/pstack}/skills/principle-foundational-thinking/SKILL.md +0 -0
  246. /package/{assets → dist/pstack}/skills/principle-guard-the-context-window/SKILL.md +0 -0
  247. /package/{assets → dist/pstack}/skills/show-me-your-work/references/decision-log-template.tsv +0 -0
  248. /package/{assets → dist/pstack}/skills/typescript-best-practices/references/patterns.md +0 -0
  249. /package/{assets → dist/pstack}/skills/unslop/SKILL.md +0 -0
  250. /package/{assets → dist/pstack}/skills/why/references/epistemics.md +0 -0
  251. /package/{assets → dist/pstack}/skills/why/references/investigator-prompt.md +0 -0
  252. /package/{assets → dist/pstack}/skills/why/references/source-playbook.md +0 -0
  253. /package/{assets → dist/pstack}/skills/why/references/sources/code-archaeology.md +0 -0
  254. /package/{assets → dist/pstack}/skills/why/references/sources/databricks.md +0 -0
  255. /package/{assets → dist/pstack}/skills/why/references/sources/datadog.md +0 -0
  256. /package/{assets → dist/pstack}/skills/why/references/sources/incident-postmortem.md +0 -0
  257. /package/{assets → dist/pstack}/skills/why/references/sources/linear.md +0 -0
  258. /package/{assets → dist/pstack}/skills/why/references/sources/notion.md +0 -0
  259. /package/{assets → dist/pstack}/skills/why/references/sources/sentry.md +0 -0
  260. /package/{assets → dist/pstack}/skills/why/references/sources/slack.md +0 -0
  261. /package/{assets → dist/pstack}/skills/why/references/synthesizer-prompt.md +0 -0
@@ -0,0 +1,440 @@
1
+ import { LEVEL, PART, hasSection, must, ruleKey, stateRules } from "./ir.mjs";
2
+ import { plainText } from "./backends/plain-text.mjs";
3
+ import { boundRun, chartRun, configText } from "./backends/cfg.mjs";
4
+ import { readConfig } from "./frontends/config.mjs";
5
+ import { parseDot } from "./frontends/dot.mjs";
6
+ import { readMessages } from "./frontends/messages.mjs";
7
+ import { readCounterexample, readMarks } from "./frontends/marks.mjs";
8
+ import { initialOnlyProperties, readChecks, readSany, readSpec } from "./frontends/spec.mjs";
9
+ import { readTrace } from "./frontends/trace.mjs";
10
+ import { readVerdict } from "./frontends/verdict.mjs";
11
+ import { addPast, deadEnds, finder, lasso, mark } from "./passes/annotate.mjs";
12
+ import { pathGraph } from "./passes/paths.mjs";
13
+ import fs from "node:fs";
14
+ import os from "node:os";
15
+ import path from "node:path";
16
+ import { execFile, spawn } from "node:child_process";
17
+ import { inspect } from "node:util";
18
+ import { Buffer } from "node:buffer";
19
+ import { randomBytes } from "node:crypto";
20
+ // runtime/skills/statechart/scripts/run.ts
21
+ function* fileLines(file) {
22
+ const fd = fs.openSync(file, "r");
23
+ try {
24
+ let buf = Buffer.allocUnsafe(PART);
25
+ let kept = 0;
26
+ for (;;) {
27
+ if (kept === buf.length) buf = Buffer.concat([buf], buf.length * 2);
28
+ const n = fs.readSync(fd, buf, kept, buf.length - kept, null);
29
+ if (!n) break;
30
+ const end = kept + n;
31
+ const cut = buf.lastIndexOf(10, end - 1);
32
+ if (cut === -1) {
33
+ kept = end;
34
+ continue;
35
+ }
36
+ yield* buf.toString("utf8", 0, cut).split("\n");
37
+ kept = buf.copy(buf, 0, cut + 1, end);
38
+ }
39
+ yield buf.toString("utf8", 0, kept);
40
+ } finally {
41
+ fs.closeSync(fd);
42
+ }
43
+ }
44
+ const TLC_TOOL = "http:tla2tools[url=https://github.com/tlaplus/tlaplus/releases/download/v1.7.4/tla2tools.jar,checksum=sha256:936a262061c914694dfd669a543be24573c45d5aa0ff20a8b96b23d01e050e88]@1.7.4";
45
+ const JAVA_TOOL = "java@temurin-25";
46
+ const PINNED_FLAGS = [
47
+ "-workers",
48
+ "1",
49
+ "-fp",
50
+ "0",
51
+ "-lncheck",
52
+ "final"
53
+ ];
54
+ const runChild = (file, args, options) => new Promise((resolve) => {
55
+ execFile(file, args, {
56
+ encoding: "utf8",
57
+ maxBuffer: 1 << 30,
58
+ ...options
59
+ }, (error, stdout, stderr) => resolve({
60
+ status: error ? typeof error.code === "number" ? error.code : null : 0,
61
+ stdout,
62
+ stderr,
63
+ error: typeof error?.code === "string" ? error : void 0
64
+ }));
65
+ });
66
+ const killGroup = (pid) => new Promise((resolve) => spawn("/bin/sh", [
67
+ "-c",
68
+ "kill -s KILL -- \"-$1\"",
69
+ "sh",
70
+ String(pid)
71
+ ], { stdio: "ignore" }).on("exit", resolve));
72
+ const messageOf = (error) => typeof error === "object" && error !== null && "message" in error && typeof error.message === "string" ? error.message : inspect(error);
73
+ const joined = (files) => {
74
+ const fds = [];
75
+ const sizes = [];
76
+ for (const f of files) {
77
+ const fd = fs.openSync(f, "r");
78
+ fds.push(fd);
79
+ sizes.push(fs.fstatSync(fd).size);
80
+ }
81
+ return { *[Symbol.iterator]() {
82
+ for (let f = 0; f < fds.length; f++) for (let pos = 0; pos < sizes[f];) {
83
+ const buf = Buffer.allocUnsafe(Math.min(PART, sizes[f] - pos));
84
+ const n = fs.readSync(fds[f], buf, 0, buf.length, pos);
85
+ if (!n) break;
86
+ pos += n;
87
+ yield buf.subarray(0, n);
88
+ }
89
+ } };
90
+ };
91
+ const utf8 = new TextDecoder("utf-8", { ignoreBOM: true });
92
+ function* outputLines(output) {
93
+ let rest = /* @__PURE__ */ new Uint8Array(0);
94
+ for (const part of output) {
95
+ const buf = rest.length ? Buffer.concat([rest, part]) : part;
96
+ const cut = buf.lastIndexOf(10);
97
+ if (cut === -1) {
98
+ rest = buf;
99
+ continue;
100
+ }
101
+ yield* utf8.decode(buf.subarray(0, cut)).split("\n");
102
+ rest = buf.subarray(cut + 1);
103
+ }
104
+ yield utf8.decode(rest);
105
+ }
106
+ const messagesOf = (output) => ({ [Symbol.iterator]: () => readMessages(outputLines(output)) });
107
+ const runToFiles = (file, args, { out, ...options }) => new Promise((resolve) => {
108
+ const files = [`${out}.stdout`, `${out}.stderr`];
109
+ const fds = [];
110
+ for (const f of files) fds.push(fs.openSync(f, "w"));
111
+ let child;
112
+ try {
113
+ child = spawn(file, args, {
114
+ ...options,
115
+ stdio: ["ignore", ...fds]
116
+ });
117
+ } finally {
118
+ for (const fd of fds) fs.closeSync(fd);
119
+ }
120
+ let error;
121
+ const settle = (code) => resolve({
122
+ status: error ? null : code,
123
+ stdout: files[0],
124
+ output: joined(files),
125
+ error
126
+ });
127
+ child.on("error", (e) => {
128
+ error = e;
129
+ if (child.pid === void 0) settle(null);
130
+ });
131
+ child.on("close", (code) => {
132
+ if (child.pid !== void 0) settle(code);
133
+ });
134
+ });
135
+ async function findTlc(cwd) {
136
+ const { TLA2TOOLS, JAVA } = process.env;
137
+ if (TLA2TOOLS) return {
138
+ jar: TLA2TOOLS,
139
+ java: JAVA || "java"
140
+ };
141
+ const mise = (...args) => runChild("mise", args, {
142
+ cwd,
143
+ env: {
144
+ ...process.env,
145
+ MISE_CEILING_PATHS: cwd
146
+ }
147
+ });
148
+ const where = () => Promise.all([mise("where", TLC_TOOL), mise("which", "java", "--tool", JAVA_TOOL)]);
149
+ let found = await where();
150
+ if (found.some((r) => r.status !== 0)) {
151
+ const r = await mise("install", JAVA_TOOL, TLC_TOOL);
152
+ if (r.status !== 0) throw new Error(`Cannot find TLC: mise install failed: ${r.error?.message ?? r.stderr.trim()}\nOr set TLA2TOOLS to the path of tla2tools.jar, and JAVA to a java binary (Java 11 or later).`);
153
+ found = await where();
154
+ }
155
+ return {
156
+ jar: path.join(found[0].stdout.trim(), "tla2tools.jar"),
157
+ java: JAVA || found[1].stdout.trim()
158
+ };
159
+ }
160
+ const exitClass = (status) => status === 0 ? 0 : status === 11 || status === 12 || status === 13 ? 1 : 2;
161
+ const tail = (r) => {
162
+ if (r.error) return r.error.message;
163
+ const kept = [];
164
+ let size = 0;
165
+ for (const chunk of plainText(messagesOf(r.output))) {
166
+ kept.push(chunk);
167
+ size += chunk.length;
168
+ while (size - kept[0].length >= 1 << 28) size -= kept.shift().length;
169
+ }
170
+ return kept.join("").trim().split("\n").slice(-30).join("\n");
171
+ };
172
+ const stopOf = (r) => {
173
+ const errors = [];
174
+ for (const m of r.error ? [] : messagesOf(r.output)) if (typeof m !== "string" && (m.level === LEVEL.ERROR || m.level === LEVEL.TLCBUG || errors.length && m.level === LEVEL.STATE)) errors.push(m);
175
+ if (!errors.length) return {
176
+ status: r.status,
177
+ message: tail(r)
178
+ };
179
+ const lines = [...plainText(errors)].join("").trim().split("\n");
180
+ if (lines.length > 40) lines.splice(40, Infinity, `... ${lines.length - 40} more lines`);
181
+ return {
182
+ status: r.status,
183
+ message: lines.join("\n")
184
+ };
185
+ };
186
+ const names = (rules, kind) => {
187
+ const found = [];
188
+ for (const rule of rules) if (rule.kind === kind) found.push(rule.name);
189
+ return found;
190
+ };
191
+ const brokenRule = (rules, broke) => {
192
+ if (broke.kind === "temporal") return void 0;
193
+ for (const rule of rules) if (rule.kind === broke.kind && (broke.kind === "deadlock" || rule.name === broke.name)) return rule;
194
+ if (broke.kind === "invariant") {
195
+ for (const rule of rules) if (rule.kind === "property" && rule.name === broke.name) return rule;
196
+ }
197
+ };
198
+ function* only(marks, rules) {
199
+ for (const { values, broken } of marks) {
200
+ const kept = [];
201
+ for (const name of broken) if (rules.has(name)) kept.push(name);
202
+ if (kept.length) yield {
203
+ values,
204
+ broken: kept
205
+ };
206
+ }
207
+ }
208
+ async function check(specFile, configFile) {
209
+ const cfg = readConfig({
210
+ file: configFile,
211
+ text: fs.readFileSync(configFile, "utf8")
212
+ });
213
+ const checks = readChecks({
214
+ configFile,
215
+ config: cfg
216
+ });
217
+ const folder = path.dirname(path.resolve(specFile));
218
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), "statechart-"));
219
+ try {
220
+ const tlc = await findTlc(dir);
221
+ const config = (name, sections, extra) => {
222
+ fs.writeFileSync(path.join(dir, `${name}.cfg`), configText(sections, extra));
223
+ return [
224
+ `-metadir`,
225
+ path.join(dir, `meta-${name}`),
226
+ "-config",
227
+ path.join(dir, `${name}.cfg`)
228
+ ];
229
+ };
230
+ const runJava = (name, main, args, jvm = []) => {
231
+ const tmp = path.join(dir, `tmp-${name}`);
232
+ fs.mkdirSync(tmp);
233
+ return runToFiles(tlc.java, [
234
+ `-Djava.io.tmpdir=${tmp}`,
235
+ `-DTLA-Library=${folder}`,
236
+ ...jvm,
237
+ "-cp",
238
+ tlc.jar,
239
+ main,
240
+ ...args
241
+ ], {
242
+ cwd: dir,
243
+ out: path.join(dir, name),
244
+ env: process.platform === "darwin" ? process.env : {
245
+ ...process.env,
246
+ LC_ALL: "C.UTF-8"
247
+ }
248
+ });
249
+ };
250
+ const xml = await runJava("sany", "tla2sany.xml.XMLExporter", [
251
+ "-o",
252
+ "-I",
253
+ folder,
254
+ path.resolve(specFile)
255
+ ], ["-XX:TieredStopAtLevel=1"]);
256
+ if (xml.status !== 0) throw new Error(`SANY could not read ${specFile} (exit ${xml.status}):\n${tail(xml)}`);
257
+ const sany = readSany(fs.readFileSync(xml.stdout, "utf8"));
258
+ const module = path.basename(specFile, ".tla");
259
+ const spec = {
260
+ ...readSpec({
261
+ module,
262
+ sany,
263
+ checks
264
+ }),
265
+ folder
266
+ };
267
+ const rules = stateRules(spec);
268
+ const all = [...rules];
269
+ for (const name of spec.properties) all.push({
270
+ kind: "property",
271
+ name
272
+ });
273
+ const verdicts = /* @__PURE__ */ new Map();
274
+ const decide = (rule, outcome, r) => verdicts.set(ruleKey(rule), {
275
+ rule,
276
+ outcome,
277
+ messages: r && messagesOf(r.output)
278
+ });
279
+ const judge = async () => {
280
+ const groups = [all];
281
+ let first;
282
+ let stop;
283
+ const states = {
284
+ distinct: 0,
285
+ initial: 0,
286
+ complete: false,
287
+ cut: false
288
+ };
289
+ for (let k = 1; groups.length;) {
290
+ const group = [];
291
+ for (const rule of groups[0]) if (!verdicts.has(ruleKey(rule))) group.push(rule);
292
+ if (first && !group.length) {
293
+ groups.shift();
294
+ continue;
295
+ }
296
+ const name = `verdict-${k++}`;
297
+ const extra = [];
298
+ const invariants = names(group, "invariant");
299
+ const properties = names(group, "property");
300
+ if (invariants.length) extra.push(`INVARIANT ${invariants.join(" ")}`);
301
+ if (properties.length) extra.push(`PROPERTY ${properties.join(" ")}`);
302
+ const bounded = first !== void 0 && !states.complete;
303
+ if (bounded) extra.push("CONSTRAINT ChartBound");
304
+ const r = await runJava(name, "tlc2.TLC", [
305
+ "-tool",
306
+ ...PINNED_FLAGS,
307
+ ...names(group, "deadlock").length ? [] : ["-deadlock"],
308
+ ...config(name, spec.written, extra),
309
+ bounded ? "ChartBound" : spec.module
310
+ ]);
311
+ first ??= r;
312
+ const { broke, distinct, initial } = readVerdict(messagesOf(r.output));
313
+ states.distinct = Math.max(states.distinct, distinct);
314
+ states.initial = Math.max(states.initial, initial);
315
+ const rule = broke && brokenRule(group, broke);
316
+ const cut = bounded && distinct >= 1e5;
317
+ if (exitClass(r.status) === 2) {
318
+ stop = stopOf(r);
319
+ break;
320
+ } else if (rule) decide(rule, "broken", r);
321
+ else if (cut && (r.status === 0 || broke?.kind === "temporal")) {
322
+ states.cut = true;
323
+ for (const rule of group) decide(rule, "not checked");
324
+ } else if (r.status === 0) {
325
+ states.complete = true;
326
+ for (const rule of group) decide(rule, "holds");
327
+ } else if (broke && properties.length) {
328
+ if (broke.kind === "temporal") {
329
+ states.complete = true;
330
+ for (const rule of group) if (rule.kind !== "property") decide(rule, "holds");
331
+ }
332
+ const pending = [];
333
+ const rest = [];
334
+ for (const rule of group) if (rule.kind === "property") pending.push([rule]);
335
+ else if (!verdicts.has(ruleKey(rule))) rest.push(rule);
336
+ if (pending.length === 1) decide(pending[0][0], "broken", r);
337
+ else groups.splice(0, 1, rest, ...pending);
338
+ } else throw new Error(`TLC exited ${r.status} on ${specFile}, but its output names no rule that broke:\n${tail(r)}`);
339
+ }
340
+ for (const rule of all) if (!verdicts.has(ruleKey(rule))) decide(rule, "not checked");
341
+ return {
342
+ first,
343
+ stop,
344
+ states
345
+ };
346
+ };
347
+ fs.writeFileSync(path.join(dir, "ChartBound.tla"), boundRun(spec.module));
348
+ const judged = await judge();
349
+ const exit = exitClass(judged.first.status);
350
+ const failed = (r) => /* @__PURE__ */ new Error(`TLC could not check ${specFile} (exit ${r.status}):\n${stopOf(r).message}`);
351
+ const initialOnly = initialOnlyProperties(sany, spec);
352
+ const propertiesWith = (bugOf) => {
353
+ const properties = [];
354
+ for (const rule of all) {
355
+ if (rule.kind !== "property") continue;
356
+ const v = must(verdicts, ruleKey(rule));
357
+ properties.push({
358
+ ...v,
359
+ bug: v.outcome === "broken" && v.messages ? bugOf(readTrace(v.messages)) : void 0,
360
+ initialOnly: initialOnly.has(rule.name)
361
+ });
362
+ }
363
+ return properties;
364
+ };
365
+ if (exit === 2) throw failed(judged.first);
366
+ const checked = [];
367
+ for (const rule of rules) checked.push(must(verdicts, ruleKey(rule)));
368
+ const common = {
369
+ spec,
370
+ exit,
371
+ stop: judged.stop,
372
+ states: judged.states,
373
+ messages: messagesOf(judged.first.output),
374
+ rules: checked
375
+ };
376
+ if (judged.states.distinct <= 500) {
377
+ const tag = `chart-${randomBytes(16).toString("hex")}`;
378
+ fs.writeFileSync(path.join(dir, "ChartRun.tla"), chartRun(spec, tag));
379
+ const drawn = await runJava("ChartRun", "tlc2.TLC", [
380
+ "-tool",
381
+ ...PINNED_FLAGS,
382
+ "-deadlock",
383
+ ...config("ChartRun", spec.written, ["INVARIANT ChartMark", "CONSTRAINT ChartBudget"]),
384
+ "-dump",
385
+ "dot,actionlabels",
386
+ path.join(dir, "graph"),
387
+ "ChartRun"
388
+ ]);
389
+ const file = path.join(dir, "graph.dot");
390
+ if (!fs.existsSync(file)) throw failed(drawn);
391
+ if (readVerdict(messagesOf(drawn.output)).distinct <= 500) {
392
+ const graph = parseDot(fileLines(file));
393
+ const find = finder(graph, spec.variables);
394
+ const drawing = drawn.status === 0 ? void 0 : { status: drawn.status };
395
+ const broken = /* @__PURE__ */ new Set();
396
+ for (const { rule, outcome } of verdicts.values()) if (rule.kind === "invariant" && outcome === "broken") broken.add(rule.name);
397
+ const marks = only(readMarks(readMessages(fileLines(drawn.stdout)), tag), broken);
398
+ const past = mark(graph, marks, spec.variables, rules, find);
399
+ const excludes = hasSection(spec, "ACTION_CONSTRAINT");
400
+ for (const rule of rules) {
401
+ const { outcome, messages } = must(verdicts, ruleKey(rule));
402
+ if (rule.kind === "deadlock" && outcome === "broken" && !drawing && !hasSection(spec, "CONSTRAINT", "ACTION_CONSTRAINT")) deadEnds(graph, rule);
403
+ if (outcome !== "broken" || !messages) continue;
404
+ const counterexample = readCounterexample(messages);
405
+ if (!drawing || lasso(graph, {
406
+ seq: counterexample,
407
+ loop: void 0
408
+ }, spec.variables, find)) addPast(graph, counterexample, spec.variables, rule, past, excludes, find);
409
+ }
410
+ const properties = propertiesWith((trace) => lasso(graph, trace, spec.variables, find));
411
+ return {
412
+ ...common,
413
+ graph,
414
+ paths: void 0,
415
+ properties,
416
+ drawing
417
+ };
418
+ }
419
+ }
420
+ const drawn = pathGraph(spec.variables);
421
+ const paths = [];
422
+ for (const rule of rules) {
423
+ const { outcome, messages } = must(verdicts, ruleKey(rule));
424
+ if (outcome === "broken" && messages) paths.push(drawn.bug(rule, readCounterexample(messages)));
425
+ }
426
+ return {
427
+ ...common,
428
+ graph: drawn.graph,
429
+ paths,
430
+ properties: propertiesWith(drawn.lasso),
431
+ drawing: void 0
432
+ };
433
+ } finally {
434
+ fs.rmSync(dir, {
435
+ recursive: true,
436
+ force: true
437
+ });
438
+ }
439
+ }
440
+ export { PINNED_FLAGS, check, fileLines, killGroup, messageOf };
@@ -0,0 +1,155 @@
1
+ #!/usr/bin/env node
2
+ import { killGroup, messageOf } from "./run.mjs";
3
+ import fs from "node:fs";
4
+ import os from "node:os";
5
+ import path from "node:path";
6
+ import { spawn } from "node:child_process";
7
+ import { parseArgs } from "node:util";
8
+ // runtime/skills/statechart/scripts/statechart.ts
9
+ const USAGE = `Usage: statechart SPEC.tla [--config FILE] [--view FILE] [--out DIR]
10
+
11
+ Checks SPEC.tla with TLC and draws its state graph as Mermaid. Above 500 states, the chart
12
+ draws only the paths to the rules that break, and with no rule broken there is no chart.mmd.
13
+ --config FILE TLC config. Default: SPEC.cfg beside the spec.
14
+ --view FILE A module that exports state(vars) and, if you want, step(action, from, to),
15
+ group(vars), colors, and title. state() returns a string for a flat chart, an
16
+ array for parent states, or an object for regions. Default: each state's values.
17
+ colors gives each group blue, orange, purple, yellow, teal, tan, or pink.
18
+ --out DIR Where to write report.md, chart.mmd, tlc.out, and tlc-RULE.out for each
19
+ property that breaks and each rule that breaks off the chart. The folder must
20
+ be new or empty. Default: SPEC-chart.
21
+ Exit code: TLC's own on the config as written: 0 when every rule holds, 1 when a rule breaks,
22
+ and 2 when TLC stops with an error, a signal kills the check, or the command cannot run. 130 or
23
+ 143 when SIGINT or SIGTERM stops the check. Only exits 0 and 1 write output.`;
24
+ let stop;
25
+ const stopped = new Promise((resolve) => {
26
+ for (const name of ["SIGINT", "SIGTERM"]) process.on(name, () => {
27
+ stop ??= name;
28
+ resolve();
29
+ });
30
+ });
31
+ let flags;
32
+ let specFile;
33
+ try {
34
+ const args = parseArgs({
35
+ allowPositionals: true,
36
+ options: {
37
+ config: { type: "string" },
38
+ view: { type: "string" },
39
+ out: { type: "string" }
40
+ }
41
+ });
42
+ flags = args.values;
43
+ [specFile] = args.positionals;
44
+ if (args.positionals.length !== 1) throw new Error("Give one SPEC.tla.");
45
+ } catch (error) {
46
+ console.error(`${messageOf(error)}\n\n${USAGE}`);
47
+ process.exit(2);
48
+ }
49
+ const codeOf = (error) => error instanceof Error && "code" in error ? error.code : void 0;
50
+ try {
51
+ const configFile = flags.config ?? specFile.replace(/\.tla$/, ".cfg");
52
+ if (!fs.existsSync(configFile)) throw new Error(`Cannot find the TLC config ${configFile}. Pass --config FILE.`);
53
+ const out = flags.out ?? specFile.replace(/\.tla$/, "-chart");
54
+ let entries = [];
55
+ let dest;
56
+ try {
57
+ entries = fs.readdirSync(out);
58
+ dest = fs.realpathSync(out);
59
+ } catch (error) {
60
+ if (codeOf(error) !== "ENOENT") throw new Error(`${out} cannot be the output folder. ${messageOf(error)}. Pass --out with a new folder.`, { cause: error });
61
+ if (fs.lstatSync(out, { throwIfNoEntry: false })) throw new Error(`${out} cannot be the output folder. It is a broken link. Pass --out with a new folder.`, { cause: error });
62
+ dest = path.resolve(out);
63
+ }
64
+ if (entries.length) throw new Error(`${out} is not empty. It has ${entries.sort()[0]}. The command writes only to a new or empty folder. Pass --out with a new folder.`);
65
+ let base = path.dirname(dest);
66
+ while (!fs.existsSync(base)) base = path.dirname(base);
67
+ const stage = fs.mkdtempSync(path.join(base, `.${path.basename(dest)}.statechart-`));
68
+ const done = path.join(stage, "done");
69
+ let tmp;
70
+ let janitor;
71
+ let exitCode;
72
+ try {
73
+ tmp = fs.mkdtempSync(path.join(os.tmpdir(), "statechart-"));
74
+ const runtime = process.versions.deno ? [
75
+ "run",
76
+ "--quiet",
77
+ "--no-prompt",
78
+ "--allow-read",
79
+ "--allow-write",
80
+ "--allow-run",
81
+ "--allow-env"
82
+ ] : process.execArgv;
83
+ const worker = spawn(process.execPath, [
84
+ ...runtime,
85
+ path.join(import.meta.dirname, import.meta.url.endsWith(".ts") ? "worker.ts" : "worker.mjs"),
86
+ stage,
87
+ specFile,
88
+ configFile,
89
+ ...flags.view ? [flags.view] : []
90
+ ], {
91
+ detached: true,
92
+ stdio: [
93
+ "ignore",
94
+ "inherit",
95
+ "inherit"
96
+ ],
97
+ env: {
98
+ ...process.env,
99
+ TMPDIR: tmp
100
+ }
101
+ });
102
+ janitor = spawn("/bin/sh", [
103
+ "-c",
104
+ "while read -r line; do :; done; kill -s KILL -- \"-$1\"; rm -rf -- \"$2\" \"$3\"",
105
+ "sh",
106
+ String(worker.pid),
107
+ stage,
108
+ tmp
109
+ ], {
110
+ detached: true,
111
+ stdio: [
112
+ "pipe",
113
+ "ignore",
114
+ "ignore"
115
+ ]
116
+ });
117
+ const exited = new Promise((resolve) => worker.on("exit", (code) => resolve(code ?? 2)));
118
+ await Promise.race([stopped, exited]);
119
+ await killGroup(worker.pid);
120
+ const verdict = await exited;
121
+ if (stop) {
122
+ console.error(`${stop} stopped the check, so the command wrote nothing.`);
123
+ exitCode = 128 + os.constants.signals[stop];
124
+ } else if (worker.signalCode) {
125
+ console.error(`${worker.signalCode} killed the check, so the command wrote nothing.`);
126
+ exitCode = 2;
127
+ } else if ((verdict === 0 || verdict === 1) && fs.existsSync(done)) {
128
+ fs.mkdirSync(path.dirname(dest), { recursive: true });
129
+ try {
130
+ fs.renameSync(done, dest);
131
+ } catch (error) {
132
+ if (codeOf(error) !== "ENOTEMPTY" && codeOf(error) !== "EEXIST") throw error;
133
+ throw new Error(`${path.join(out, fs.readdirSync(dest).sort()[0])} appeared while the check ran, so the command wrote nothing. Pass --out with a new folder.`, { cause: error });
134
+ }
135
+ process.stdout.write(fs.readFileSync(path.join(dest, "report.md")));
136
+ console.log(`\nWrote ${out}`);
137
+ exitCode = verdict;
138
+ } else exitCode = 2;
139
+ } finally {
140
+ fs.rmSync(stage, {
141
+ recursive: true,
142
+ force: true
143
+ });
144
+ if (tmp) fs.rmSync(tmp, {
145
+ recursive: true,
146
+ force: true
147
+ });
148
+ janitor?.kill("SIGKILL");
149
+ }
150
+ process.exit(exitCode);
151
+ } catch (error) {
152
+ console.error(messageOf(error));
153
+ process.exit(2);
154
+ }
155
+ export {};