dsh-pstack 0.2.0-beta.1 → 0.2.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 (275) hide show
  1. package/LICENSE +2 -3
  2. package/README.md +148 -84
  3. package/README.zh.md +198 -0
  4. package/assets/pstack-config-entry.png +0 -0
  5. package/cordis.patch.yml +105 -27
  6. package/dist/client.mjs +2341 -0
  7. package/dist/client.mjs.map +1 -0
  8. package/dist/host-contract-CUPSpeNk.d.mts +22 -0
  9. package/dist/index.d.mts +49 -238
  10. package/dist/index.mjs +250 -123
  11. package/dist/models.d.mts +44 -0
  12. package/dist/models.mjs +201 -0
  13. package/dist/paths-BT77khwm.mjs +48 -0
  14. package/dist/pstack/LICENSE +21 -0
  15. package/dist/pstack/README.md +291 -0
  16. package/dist/pstack/agents/poteto-agent.md +9 -0
  17. package/{assets → dist/pstack}/docs/guide/01-setup.md +13 -11
  18. package/{assets → dist/pstack}/docs/guide/02-poteto-mode.md +4 -4
  19. package/{assets → dist/pstack}/docs/guide/04-design.md +4 -4
  20. package/{assets → dist/pstack}/docs/guide/05-build-and-clean.md +2 -2
  21. package/{assets → dist/pstack}/docs/guide/06-verify-and-ship.md +13 -3
  22. package/{assets → dist/pstack}/docs/guide/07-overnight.md +15 -13
  23. package/{assets → dist/pstack}/docs/guide/09-make-it-yours.md +6 -2
  24. package/{assets → dist/pstack}/docs/guide/10-recipes-and-pitfalls.md +7 -5
  25. package/{assets → dist/pstack}/docs/guide/README.md +1 -1
  26. package/dist/pstack/docs/harness/dsh.md +98 -0
  27. package/{assets → dist/pstack}/skills/architect/SKILL.md +12 -12
  28. package/dist/pstack/skills/arena/SKILL.md +50 -0
  29. package/{assets → dist/pstack}/skills/automate-me/SKILL.md +14 -14
  30. package/{assets → dist/pstack}/skills/benchmark-checklist/SKILL.md +1 -1
  31. package/{assets → dist/pstack}/skills/blast-radius/SKILL.md +4 -6
  32. package/{assets → dist/pstack}/skills/correct/SKILL.md +1 -1
  33. package/{assets → dist/pstack}/skills/create-formal-verification-skill/SKILL.md +4 -2
  34. package/{assets → dist/pstack}/skills/create-verification-skill/SKILL.md +5 -5
  35. package/dist/pstack/skills/figure-it-out/SKILL.md +54 -0
  36. package/dist/pstack/skills/how/SKILL.md +38 -0
  37. package/{assets → dist/pstack}/skills/in-your-own-words/SKILL.md +1 -1
  38. package/dist/pstack/skills/interrogate/SKILL.md +33 -0
  39. package/{assets → dist/pstack}/skills/ketchup/SKILL.md +3 -5
  40. package/dist/pstack/skills/ketchup-video/SKILL.md +29 -0
  41. package/{assets → dist/pstack}/skills/maintain-formal-verification-skill/SKILL.md +1 -1
  42. package/{assets → dist/pstack}/skills/maintain-verification-skill/SKILL.md +3 -3
  43. package/dist/pstack/skills/make-bot-ui/SKILL.md +117 -0
  44. package/dist/pstack/skills/no-comments/SKILL.md +26 -0
  45. package/{assets → dist/pstack}/skills/poteto-help/SKILL.md +34 -31
  46. package/{assets → dist/pstack}/skills/poteto-help/references/prompting.md +1 -1
  47. package/{assets → dist/pstack}/skills/poteto-help/references/recipes.md +3 -3
  48. package/{assets → dist/pstack}/skills/poteto-mode/SKILL.md +20 -19
  49. package/dist/pstack/skills/poteto-mode/playbooks/authoring-a-skill.md +12 -0
  50. package/dist/pstack/skills/poteto-mode/playbooks/autonomous-run.md +13 -0
  51. package/dist/pstack/skills/poteto-mode/playbooks/autopilot-full.md +25 -0
  52. package/dist/pstack/skills/poteto-mode/playbooks/autopilot-stack.md +8 -0
  53. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/babysit.md +4 -4
  54. package/dist/pstack/skills/poteto-mode/playbooks/bug-fix.md +15 -0
  55. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/eval.md +3 -3
  56. package/dist/pstack/skills/poteto-mode/playbooks/feature.md +21 -0
  57. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/hillclimb.md +3 -3
  58. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/investigation.md +2 -2
  59. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/multi-phase-plan.md +23 -23
  60. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/opening-a-pr.md +6 -6
  61. package/dist/pstack/skills/poteto-mode/playbooks/orchestrate.md +25 -0
  62. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/pause-safely.md +2 -2
  63. package/dist/pstack/skills/poteto-mode/playbooks/perf-issue.md +25 -0
  64. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/prototype.md +4 -4
  65. package/dist/pstack/skills/poteto-mode/playbooks/refactoring.md +16 -0
  66. package/dist/pstack/skills/poteto-mode/playbooks/runtime-forensics.md +11 -0
  67. package/dist/pstack/skills/poteto-mode/playbooks/session-pickup.md +11 -0
  68. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/shipping.md +2 -2
  69. package/{assets → dist/pstack}/skills/poteto-mode/playbooks/trace-forensics.md +2 -2
  70. package/dist/pstack/skills/poteto-mode/playbooks/visual-parity.md +11 -0
  71. package/dist/pstack/skills/poteto-mode/playbooks/worktree-cleanup.md +12 -0
  72. package/{assets → dist/pstack}/skills/poteto-mode/scripts/check-plan.mjs +6 -8
  73. package/dist/pstack/skills/poteto-mode/scripts/check-plan.test.mjs +128 -0
  74. package/{assets/skills/poteto-mode/scripts/check-plan.test.mjs → dist/pstack/skills/poteto-mode/scripts/expect.mjs} +12 -101
  75. package/dist/pstack/skills/poteto-mode/scripts/support.mjs +93 -0
  76. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/cli.mjs +123 -0
  77. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/cli.test.mjs +217 -0
  78. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/fakes.test-helper.mjs +119 -0
  79. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/github.mjs +626 -0
  80. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/github.test.mjs +521 -0
  81. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/policy.mjs +657 -0
  82. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/policy.test.mjs +523 -0
  83. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/render.mjs +106 -0
  84. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/types.mjs +9 -0
  85. package/dist/pstack/skills/poteto-mode/scripts/watch-pr/watch-pr.mjs +5 -0
  86. package/{assets → dist/pstack}/skills/poteto-mode/scripts/worktree-audit.mjs +15 -22
  87. package/dist/pstack/skills/poteto-mode/scripts/worktree-audit.test.mjs +134 -0
  88. package/{assets → dist/pstack}/skills/principle-attack-the-premise/SKILL.md +1 -1
  89. package/{assets → dist/pstack}/skills/principle-boundary-discipline/SKILL.md +1 -1
  90. package/{assets → dist/pstack}/skills/principle-encode-lessons-in-structure/SKILL.md +1 -1
  91. package/{assets → dist/pstack}/skills/principle-exhaust-the-design-space/SKILL.md +1 -1
  92. package/{assets → dist/pstack}/skills/principle-experience-first/SKILL.md +1 -1
  93. package/{assets → dist/pstack}/skills/principle-explain-the-number/SKILL.md +3 -2
  94. package/{assets → dist/pstack}/skills/principle-fix-root-causes/SKILL.md +1 -1
  95. package/{assets → dist/pstack}/skills/principle-laziness-protocol/SKILL.md +1 -1
  96. package/{assets → dist/pstack}/skills/principle-make-operations-idempotent/SKILL.md +1 -1
  97. package/{assets → dist/pstack}/skills/principle-migrate-callers-then-delete-legacy-apis/SKILL.md +1 -1
  98. package/{assets → dist/pstack}/skills/principle-minimize-reader-load/SKILL.md +1 -1
  99. package/{assets → dist/pstack}/skills/principle-model-the-domain/SKILL.md +1 -1
  100. package/{assets → dist/pstack}/skills/principle-never-block-on-the-human/SKILL.md +1 -1
  101. package/{assets → dist/pstack}/skills/principle-outcome-oriented-execution/SKILL.md +1 -1
  102. package/{assets → dist/pstack}/skills/principle-prove-it-works/SKILL.md +2 -2
  103. package/{assets → dist/pstack}/skills/principle-redesign-from-first-principles/SKILL.md +1 -1
  104. package/{assets → dist/pstack}/skills/principle-separate-before-serializing-shared-state/SKILL.md +1 -1
  105. package/{assets → dist/pstack}/skills/principle-sequence-verifiable-units/SKILL.md +1 -1
  106. package/{assets → dist/pstack}/skills/principle-subtract-before-you-add/SKILL.md +1 -1
  107. package/{assets → dist/pstack}/skills/principle-test-behavior-not-implementation/SKILL.md +1 -1
  108. package/{assets → dist/pstack}/skills/principle-type-system-discipline/SKILL.md +1 -1
  109. package/dist/pstack/skills/recall/SKILL.md +37 -0
  110. package/dist/pstack/skills/reflect/SKILL.md +71 -0
  111. package/{assets → dist/pstack}/skills/reflect/references/divergent-reviewer.md +4 -4
  112. package/{assets → dist/pstack}/skills/reflect/references/judgment-reviewer.md +2 -2
  113. package/{assets → dist/pstack}/skills/reflect/references/synthesizer.md +5 -5
  114. package/{assets → dist/pstack}/skills/reflect/references/tooling-reviewer.md +2 -2
  115. package/dist/pstack/skills/setup-pstack/SKILL.md +80 -0
  116. package/{assets → dist/pstack}/skills/sharpen/SKILL.md +1 -1
  117. package/{assets → dist/pstack}/skills/show-me-your-work/SKILL.md +8 -8
  118. package/{assets → dist/pstack}/skills/show-me-your-work/scripts/log.mjs +1 -3
  119. package/dist/pstack/skills/show-me-your-work/scripts/log.test.mjs +56 -0
  120. package/dist/pstack/skills/statechart/SKILL.md +82 -0
  121. package/dist/pstack/skills/statechart/references/render.md +93 -0
  122. package/dist/pstack/skills/statechart/scripts/backends/cfg.mjs +31 -0
  123. package/dist/pstack/skills/statechart/scripts/backends/mermaid.mjs +186 -0
  124. package/dist/pstack/skills/statechart/scripts/backends/plain-text.mjs +62 -0
  125. package/dist/pstack/skills/statechart/scripts/backends/report.mjs +84 -0
  126. package/dist/pstack/skills/statechart/scripts/frontends/config.mjs +268 -0
  127. package/dist/pstack/skills/statechart/scripts/frontends/dot.mjs +67 -0
  128. package/dist/pstack/skills/statechart/scripts/frontends/marks.mjs +94 -0
  129. package/dist/pstack/skills/statechart/scripts/frontends/messages.mjs +48 -0
  130. package/dist/pstack/skills/statechart/scripts/frontends/spec.mjs +101 -0
  131. package/dist/pstack/skills/statechart/scripts/frontends/trace.mjs +39 -0
  132. package/dist/pstack/skills/statechart/scripts/frontends/value.mjs +180 -0
  133. package/dist/pstack/skills/statechart/scripts/frontends/verdict.mjs +40 -0
  134. package/dist/pstack/skills/statechart/scripts/frontends/view.mjs +99 -0
  135. package/dist/pstack/skills/statechart/scripts/ir.mjs +277 -0
  136. package/dist/pstack/skills/statechart/scripts/passes/annotate.mjs +92 -0
  137. package/dist/pstack/skills/statechart/scripts/passes/label.mjs +210 -0
  138. package/dist/pstack/skills/statechart/scripts/passes/lift.mjs +84 -0
  139. package/dist/pstack/skills/statechart/scripts/passes/loop-check.mjs +47 -0
  140. package/dist/pstack/skills/statechart/scripts/passes/paths.mjs +72 -0
  141. package/dist/pstack/skills/statechart/scripts/passes/reach.mjs +135 -0
  142. package/dist/pstack/skills/statechart/scripts/passes/region-check.mjs +82 -0
  143. package/dist/pstack/skills/statechart/scripts/passes/regions.mjs +268 -0
  144. package/dist/pstack/skills/statechart/scripts/pipeline.mjs +72 -0
  145. package/dist/pstack/skills/statechart/scripts/run.mjs +440 -0
  146. package/dist/pstack/skills/statechart/scripts/statechart.mjs +155 -0
  147. package/dist/pstack/skills/statechart/scripts/statechart.test.mjs +198 -0
  148. package/dist/pstack/skills/statechart/scripts/worker.mjs +31 -0
  149. package/dist/pstack/skills/swarm/SKILL.md +43 -0
  150. package/{assets → dist/pstack}/skills/tdd/SKILL.md +1 -1
  151. package/{assets → dist/pstack}/skills/teach/SKILL.md +2 -2
  152. package/{assets → dist/pstack}/skills/technical-writing/SKILL.md +1 -1
  153. package/{assets → dist/pstack}/skills/typescript-best-practices/SKILL.md +3 -6
  154. package/{assets → dist/pstack}/skills/why/SKILL.md +8 -8
  155. package/dist/remote.d.mts +27 -0
  156. package/dist/remote.mjs +234 -0
  157. package/dist/role-config-NNn5r1JX.mjs +415 -0
  158. package/dist/role-manifest-C3fUzjLI.d.mts +19 -0
  159. package/dist/role-wire-DZwTn2wF.d.mts +55 -0
  160. package/dist/roles.d.mts +18 -0
  161. package/dist/roles.mjs +323 -0
  162. package/dist/script.d.mts +9 -111
  163. package/dist/script.mjs +32 -329
  164. package/dist/skill.d.mts +38 -0
  165. package/dist/skill.mjs +183 -0
  166. package/dist/skills/authored/decision-audit/SKILL.md +103 -0
  167. package/dist/skills/authored/decision-audit/SKILL.zh.md +103 -0
  168. package/dist/skills/authored/decision-audit/references/recover-commit.md +17 -0
  169. package/dist/skills/authored/decision-audit/references/recover-commit.zh.md +17 -0
  170. package/dist/skills/authored/decision-write/SKILL.md +133 -0
  171. package/dist/skills/authored/decision-write/SKILL.zh.md +133 -0
  172. package/dist/skills/authored/decision-write/references/land.md +48 -0
  173. package/dist/skills/authored/decision-write/references/land.zh.md +48 -0
  174. package/dist/skills/authored/decision-write/references/scope.md +16 -0
  175. package/dist/skills/authored/decision-write/references/scope.zh.md +16 -0
  176. package/dist/skills/authored/docs-drift/SKILL.md +120 -0
  177. package/dist/skills/authored/docs-drift/SKILL.zh.md +120 -0
  178. package/dist/skills/authored/setup-project-docs/SKILL.md +63 -0
  179. package/dist/skills/authored/setup-project-docs/SKILL.zh.md +63 -0
  180. package/dist/skills/authored/setup-project-docs/references/decision-conventions.md +13 -0
  181. package/dist/skills/authored/setup-project-docs/references/decision-conventions.zh.md +13 -0
  182. package/dist/skills/vendored/retro/SKILL.md +44 -0
  183. package/dist/skills/vendored/retro/agents/openai.yaml +5 -0
  184. package/dist/skills/vendored/writing-for-agents/SKILL-MECHANICS.md +22 -0
  185. package/dist/skills/vendored/writing-for-agents/SKILL.md +81 -0
  186. package/dist/skills/vendored/writing-for-agents/agents/openai.yaml +3 -0
  187. package/dist/subagent.d.mts +54 -206
  188. package/dist/subagent.mjs +258 -963
  189. package/locale/en.json +3 -2
  190. package/locale/zh.json +3 -2
  191. package/package.json +93 -66
  192. package/assets/agents/poteto-agent.md +0 -8
  193. package/assets/docs/harness/dsh.md +0 -60
  194. package/assets/docs/pstack-models.example.md +0 -54
  195. package/assets/skills/arena/SKILL.md +0 -50
  196. package/assets/skills/figure-it-out/SKILL.md +0 -54
  197. package/assets/skills/how/SKILL.md +0 -38
  198. package/assets/skills/interrogate/SKILL.md +0 -71
  199. package/assets/skills/interrogate/references/code-quality-review.md +0 -47
  200. package/assets/skills/interrogate/references/lead-judgment.md +0 -39
  201. package/assets/skills/interrogate/references/reviewer-prompt.md +0 -62
  202. package/assets/skills/interrogate/references/rubric.md +0 -77
  203. package/assets/skills/no-comments/SKILL.md +0 -26
  204. package/assets/skills/poteto-mode/playbooks/authoring-a-skill.md +0 -12
  205. package/assets/skills/poteto-mode/playbooks/autonomous-run.md +0 -15
  206. package/assets/skills/poteto-mode/playbooks/autopilot-full.md +0 -25
  207. package/assets/skills/poteto-mode/playbooks/autopilot-stack.md +0 -12
  208. package/assets/skills/poteto-mode/playbooks/bug-fix.md +0 -15
  209. package/assets/skills/poteto-mode/playbooks/feature.md +0 -21
  210. package/assets/skills/poteto-mode/playbooks/orchestrate.md +0 -112
  211. package/assets/skills/poteto-mode/playbooks/perf-issue.md +0 -25
  212. package/assets/skills/poteto-mode/playbooks/refactoring.md +0 -16
  213. package/assets/skills/poteto-mode/playbooks/runtime-forensics.md +0 -11
  214. package/assets/skills/poteto-mode/playbooks/session-pickup.md +0 -11
  215. package/assets/skills/poteto-mode/playbooks/visual-parity.md +0 -11
  216. package/assets/skills/poteto-mode/playbooks/worktree-cleanup.md +0 -20
  217. package/assets/skills/poteto-mode/scripts/orch/orch.mjs +0 -4282
  218. package/assets/skills/poteto-mode/scripts/orch/orch.test.mjs +0 -2042
  219. package/assets/skills/poteto-mode/scripts/watch-pr/cli.test.mjs +0 -5101
  220. package/assets/skills/poteto-mode/scripts/watch-pr/github.test.mjs +0 -1177
  221. package/assets/skills/poteto-mode/scripts/watch-pr/policy.test.mjs +0 -1441
  222. package/assets/skills/poteto-mode/scripts/watch-pr/watch-pr.mjs +0 -4601
  223. package/assets/skills/recall/SKILL.md +0 -37
  224. package/assets/skills/reflect/SKILL.md +0 -69
  225. package/assets/skills/setup-pstack/SKILL.md +0 -67
  226. package/assets/skills/swarm/SKILL.md +0 -43
  227. package/dist/frontmatter-BQX3ekwP.mjs +0 -229
  228. package/dist/frontmatter-BQX3ekwP.mjs.map +0 -1
  229. package/dist/history.d.mts +0 -429
  230. package/dist/history.mjs +0 -1129
  231. package/dist/history.mjs.map +0 -1
  232. package/dist/host-contract-o47JH_r8.d.mts +0 -527
  233. package/dist/index.mjs.map +0 -1
  234. package/dist/paths-D_JlVmBk.mjs +0 -42
  235. package/dist/paths-D_JlVmBk.mjs.map +0 -1
  236. package/dist/script.mjs.map +0 -1
  237. package/dist/subagent.mjs.map +0 -1
  238. /package/{static/icon.png → assets/logo.png} +0 -0
  239. /package/{assets → dist/pstack}/agents/comment-sicko.md +0 -0
  240. /package/{assets → dist/pstack}/docs/guide/03-understand.md +0 -0
  241. /package/{assets → dist/pstack}/docs/guide/08-principles.md +0 -0
  242. /package/{assets → dist/pstack}/docs/guide/images/design.jpg +0 -0
  243. /package/{assets → dist/pstack}/docs/guide/images/overnight.jpg +0 -0
  244. /package/{assets → dist/pstack}/docs/guide/images/recipes.jpg +0 -0
  245. /package/{assets → dist/pstack}/docs/guide/images/router.jpg +0 -0
  246. /package/{assets → dist/pstack}/docs/guide/images/understanding.jpg +0 -0
  247. /package/{assets → dist/pstack}/docs/guide/images/verification.jpg +0 -0
  248. /package/{assets → dist/pstack}/skills/architect/references/design-red-flags.md +0 -0
  249. /package/{assets → dist/pstack}/skills/architect/references/rationale-template.md +0 -0
  250. /package/{assets → dist/pstack}/skills/architect/references/runner-prompt.md +0 -0
  251. /package/{assets → dist/pstack}/skills/bro/SKILL.md +0 -0
  252. /package/{assets → dist/pstack}/skills/create-verification-skill/references/feature-map-example/README.md +0 -0
  253. /package/{assets → dist/pstack}/skills/create-verification-skill/references/feature-map-example/create-note.md +0 -0
  254. /package/{assets → dist/pstack}/skills/create-verification-skill/references/feature-map-example/search.md +0 -0
  255. /package/{assets → dist/pstack}/skills/how/references/explainer-prompt.md +0 -0
  256. /package/{assets → dist/pstack}/skills/how/references/explorer-prompt.md +0 -0
  257. /package/{assets → dist/pstack}/skills/poteto-mode/references/bugbot-triage.md +0 -0
  258. /package/{assets → dist/pstack}/skills/principle-build-the-lever/SKILL.md +0 -0
  259. /package/{assets → dist/pstack}/skills/principle-foundational-thinking/SKILL.md +0 -0
  260. /package/{assets → dist/pstack}/skills/principle-guard-the-context-window/SKILL.md +0 -0
  261. /package/{assets → dist/pstack}/skills/show-me-your-work/references/decision-log-template.tsv +0 -0
  262. /package/{assets → dist/pstack}/skills/typescript-best-practices/references/patterns.md +0 -0
  263. /package/{assets → dist/pstack}/skills/unslop/SKILL.md +0 -0
  264. /package/{assets → dist/pstack}/skills/why/references/epistemics.md +0 -0
  265. /package/{assets → dist/pstack}/skills/why/references/investigator-prompt.md +0 -0
  266. /package/{assets → dist/pstack}/skills/why/references/source-playbook.md +0 -0
  267. /package/{assets → dist/pstack}/skills/why/references/sources/code-archaeology.md +0 -0
  268. /package/{assets → dist/pstack}/skills/why/references/sources/databricks.md +0 -0
  269. /package/{assets → dist/pstack}/skills/why/references/sources/datadog.md +0 -0
  270. /package/{assets → dist/pstack}/skills/why/references/sources/incident-postmortem.md +0 -0
  271. /package/{assets → dist/pstack}/skills/why/references/sources/linear.md +0 -0
  272. /package/{assets → dist/pstack}/skills/why/references/sources/notion.md +0 -0
  273. /package/{assets → dist/pstack}/skills/why/references/sources/sentry.md +0 -0
  274. /package/{assets → dist/pstack}/skills/why/references/sources/slack.md +0 -0
  275. /package/{assets → dist/pstack}/skills/why/references/synthesizer-prompt.md +0 -0
@@ -0,0 +1,186 @@
1
+ import { append, byText, tupleKey } from "../ir.mjs";
2
+ // runtime/skills/statechart/scripts/backends/mermaid.ts
3
+ const BLANK = /\p{White_Space}/u;
4
+ const SAFE = /^[\p{L}\p{N} !'()+,\-./=?[\]"_|@{}:\\^%<>]$/u;
5
+ const HAZARD = /:(?=:|$|\S*#)|\\(?=n)|%(?=%)|<(?=[\p{L}/!?])|_(?![\p{L}\p{N}])|(?<![\p{L}\p{N}])_/giu;
6
+ const DIRECTION = /(direction)\s+(?=LR|RL|TB|BT)/gi;
7
+ const DOUBLE_BRACKET = /\[(?=\[)/g;
8
+ const C4 = /C4(?=Container|Component|Dynamic|Deployment)/g;
9
+ const UNDRAWN = /[\0\x80-\x9f]/;
10
+ const REWRITTEN = ["fl°", "¶ß"];
11
+ const MARKER = /(?<=marker-end=)"/g;
12
+ const firstOf = /* @__PURE__ */ new Map();
13
+ for (const pair of REWRITTEN) {
14
+ const [first, second] = [...pair].map((c) => c.codePointAt(0) ?? 0);
15
+ firstOf.set(second, first);
16
+ }
17
+ const KEPT = 0;
18
+ const BLANKED = 1;
19
+ const DROPPED = 2;
20
+ const CODED = 3;
21
+ const JOINS = 4;
22
+ const kindOf = (n) => {
23
+ const c = String.fromCodePoint(n);
24
+ const kind = c === " " ? KEPT : BLANK.test(c) ? BLANKED : UNDRAWN.test(c) ? DROPPED : SAFE.test(c) ? KEPT : CODED;
25
+ return firstOf.has(n) ? kind | JOINS : kind;
26
+ };
27
+ const ASCII = Uint8Array.from({ length: 128 }, (_, n) => kindOf(n));
28
+ const wide = /* @__PURE__ */ new Map();
29
+ const kindAt = (n) => {
30
+ if (n < 128) return ASCII[n];
31
+ let kind = wide.get(n);
32
+ if (kind === void 0) wide.set(n, kind = kindOf(n));
33
+ return kind;
34
+ };
35
+ const encode = (s, ref) => {
36
+ let out = "";
37
+ let run = 0;
38
+ let last = -1;
39
+ for (let i = 0; i < s.length;) {
40
+ let n = s.charCodeAt(i);
41
+ let width = 1;
42
+ if (n >= 55296 && n <= 57343) {
43
+ const low = s.charCodeAt(i + 1);
44
+ if (n <= 56319 && low >= 56320 && low <= 57343) {
45
+ n = 65536 + (n - 55296 << 10) + (low - 56320);
46
+ width = 2;
47
+ } else n = 65533;
48
+ }
49
+ let kind = kindAt(n);
50
+ if (kind === DROPPED) {
51
+ out += s.slice(run, i);
52
+ run = i + width;
53
+ } else {
54
+ const joined = kind >= JOINS && firstOf.get(n) === last;
55
+ kind &= -5;
56
+ if (joined || kind !== KEPT) {
57
+ out += s.slice(run, i);
58
+ if (joined) out += ref(8288);
59
+ if (kind === KEPT) run = i;
60
+ else {
61
+ out += kind === BLANKED ? " " : ref(n);
62
+ run = i + width;
63
+ }
64
+ }
65
+ last = n;
66
+ }
67
+ i += width;
68
+ }
69
+ return out + s.slice(run);
70
+ };
71
+ const code = (s, ref) => encode(s, ref).replace(MARKER, `${ref(8288)}"`).replace(HAZARD, (c) => ref(c.charCodeAt(0)));
72
+ const esc = (s, quoted = false) => {
73
+ const plain = code(s, (n) => `#${n};`);
74
+ const out = quoted ? plain.replaceAll("\"", "#34;") : plain;
75
+ if (!out.trim()) return "#32;";
76
+ const turned = out.replace(DIRECTION, "$1#32;");
77
+ const opened = turned.includes("[[") ? turned.replace(DOUBLE_BRACKET, "#91;") : turned;
78
+ return opened.includes("C4") ? opened.replace(C4, "C#52;") : opened;
79
+ };
80
+ const or = (names) => [...names].sort(byText).join(" or ");
81
+ const MARK_STYLES = {
82
+ breaks: "fill:#ffecee,stroke:#e72e3b,stroke-width:2.5px,color:#cd2834",
83
+ mayBreak: "fill:#fff3e6,stroke:#e8730c,stroke-width:2.5px,color:#b85a06"
84
+ };
85
+ function mermaidLines(chart) {
86
+ let next = 0;
87
+ const marks = [];
88
+ const used = /* @__PURE__ */ new Set();
89
+ const rules = {
90
+ breaks: /* @__PURE__ */ new Set(),
91
+ mayBreak: /* @__PURE__ */ new Set()
92
+ };
93
+ const region = (r) => {
94
+ const out = [];
95
+ const topIds = /* @__PURE__ */ new Map();
96
+ const nestedIds = /* @__PURE__ */ new Map();
97
+ const id = (path) => {
98
+ const top = path.length === 1;
99
+ const named = top ? topIds : nestedIds;
100
+ const k = top ? path[0] : tupleKey(path);
101
+ let s = named.get(k);
102
+ if (s === void 0) named.set(k, s = `s${next++}`);
103
+ return s;
104
+ };
105
+ const known = /* @__PURE__ */ new Map();
106
+ const idOf = (path) => {
107
+ let s = known.get(path);
108
+ if (s === void 0) known.set(path, s = id(path));
109
+ return s;
110
+ };
111
+ const tree = (prefix, indent, below) => {
112
+ const heads = /* @__PURE__ */ new Map();
113
+ for (const s of below) append(heads, s.path[prefix.length], s);
114
+ for (const [head, under] of heads) {
115
+ const path = [...prefix, head];
116
+ let leaf;
117
+ const inner = [];
118
+ for (const s of under) if (s.path.length > path.length) inner.push(s);
119
+ else leaf = s;
120
+ if (inner.length) {
121
+ out.push(`${indent}state "${esc(head, true)}" as ${id(path)} {`);
122
+ tree(path, indent + " ", inner);
123
+ out.push(`${indent}}`);
124
+ } else if (leaf) {
125
+ const sid = idOf(leaf.path);
126
+ out.push(`${indent}${sid}: ${esc(head)}`);
127
+ let mark = leaf.breaks.length && !leaf.works ? "mayBreak" : void 0;
128
+ if (mark) {
129
+ for (const b of leaf.breaks) if (b.always) mark = "breaks";
130
+ }
131
+ if (mark) for (const b of leaf.breaks) rules[mark].add(b.rule.name);
132
+ const trail = [leaf.lead && "bugPath", leaf.repeats && "repeats"];
133
+ const color = leaf.group === void 0 ? void 0 : chart.colors[String(leaf.group)];
134
+ for (const cls of [
135
+ color,
136
+ mark,
137
+ ...trail
138
+ ]) if (cls) {
139
+ used.add(cls);
140
+ marks.push(` class ${sid} ${cls}`);
141
+ }
142
+ }
143
+ }
144
+ };
145
+ tree([], " ", r.states);
146
+ for (const s of r.states) if (s.start) out.push(` [*] --> ${idOf(s.path)}`);
147
+ for (const s of r.steps) out.push(` ${idOf(s.from)} --> ${idOf(s.to)}: ${esc(s.label + (s.when ? ` [${s.when}]` : ""))}`);
148
+ return out;
149
+ };
150
+ let body;
151
+ if (chart.regions.length > 1) {
152
+ body = [` state "At the same time" as all {`];
153
+ for (const [i, r] of chart.regions.entries()) {
154
+ if (i) body.push(" --");
155
+ body.push(` state "${esc(r.name, true)}" as r${i} {`);
156
+ for (const line of region(r)) body.push(` ${line}`);
157
+ body.push(" }");
158
+ }
159
+ body.push(" }");
160
+ } else body = region(chart.regions[0]);
161
+ const legend = [];
162
+ for (const entry of [
163
+ ...Object.entries(chart.colors),
164
+ [`Breaks ${or(rules.breaks)}`, "breaks"],
165
+ [`Breaks ${or(rules.mayBreak)} in some cases`, "mayBreak"],
166
+ [`Path to the ${or(chart.paths)} bug`, "bugPath"],
167
+ [`Repeats forever, so ${or(chart.loops)} breaks`, "repeats"]
168
+ ]) if (used.has(entry[1])) legend.push(entry);
169
+ const lines = [];
170
+ const title = chart.title && code(chart.title, (n) => `fl°°${n}¶ß`).replaceAll("<", "fl°°60¶ß");
171
+ if (title) lines.push("---", `title: ${JSON.stringify(title)}`, "---");
172
+ lines.push("stateDiagram-v2");
173
+ if (chart.regions.length > 1) lines.push(" direction LR");
174
+ if (legend.length) {
175
+ lines.push(` state "Legend" as legend {`);
176
+ for (const [i, [text]] of legend.entries()) lines.push(` lg${i}: ${esc(text)}`);
177
+ lines.push(" }");
178
+ for (const [i, [, cls]] of legend.entries()) lines.push(` class lg${i} ${cls}`);
179
+ }
180
+ for (const line of body) lines.push(line);
181
+ for (const [cls, style] of Object.entries(MARK_STYLES)) if (used.has(cls)) lines.push(` classDef ${cls} ${style}`);
182
+ for (const line of marks) lines.push(line);
183
+ return lines;
184
+ }
185
+ const mermaid = (chart) => mermaidLines(chart).join("\n");
186
+ export { mermaid, mermaidLines };
@@ -0,0 +1,62 @@
1
+ import { EC, LEVEL } from "../ir.mjs";
2
+ // runtime/skills/statechart/scripts/backends/plain-text.ts
3
+ const PREFIX = {
4
+ [LEVEL.ERROR]: "Error: ",
5
+ [LEVEL.TLCBUG]: "TLC Bug: ",
6
+ [LEVEL.WARNING]: "Warning: ",
7
+ [LEVEL.STATE]: "State "
8
+ };
9
+ const MINUTE = 6e4;
10
+ const HOUR = 36e5;
11
+ const DAY = 864e5;
12
+ const pad = (n) => String(n).padStart(2, "0");
13
+ function runtime(ms) {
14
+ const t = new Date(ms > DAY ? ms - DAY : ms);
15
+ const [hh, mm, ss] = [
16
+ t.getUTCHours(),
17
+ t.getUTCMinutes(),
18
+ t.getUTCSeconds()
19
+ ].map(pad);
20
+ if (ms > DAY) return `${Math.floor((t.getTime() - Date.UTC(t.getUTCFullYear(), 0, 1)) / DAY) + 1}d ${hh}h`;
21
+ if (ms > HOUR) return `${hh}h ${mm}min`;
22
+ if (ms > MINUTE) return `${mm}min ${ss}s`;
23
+ return `${ss}s`;
24
+ }
25
+ const firstLine = ({ code, level }, line) => {
26
+ if (code === EC.TLC_BACK_TO_STATE) return line.replace(/^(\d+): Back to state: /, "Back to state $1: ");
27
+ if (code === EC.TLC_FINISHED) return line.replace(/^Finished in (\d+)ms/, (_, ms) => `Finished in ${runtime(Number(ms))}`);
28
+ return (PREFIX[level] ?? "") + line;
29
+ };
30
+ const render = (m) => (m.beforeMarker ?? "") + firstLine(m, m.body.map((part) => typeof part === "string" ? part : render(part)).join("\n"));
31
+ function* printed(parts) {
32
+ let warned = false;
33
+ let progress;
34
+ for (const part of parts) {
35
+ if (progress?.body.length && (typeof part === "string" || part.code !== EC.TLC_STATS)) yield render(progress);
36
+ progress = void 0;
37
+ if (typeof part === "string") {
38
+ yield part;
39
+ continue;
40
+ }
41
+ if (part.code === EC.TLC_SANY_START || part.code === EC.TLC_SANY_END) continue;
42
+ if (part.code === EC.TLC_PROGRESS_STATS) progress = part;
43
+ else if (part.body.length) yield render(part);
44
+ if (part.level === LEVEL.WARNING && !warned) {
45
+ yield "(Use the -nowarning option to disable this warning.)";
46
+ warned = true;
47
+ }
48
+ }
49
+ if (progress?.body.length) yield render(progress);
50
+ }
51
+ function* plainText(parts) {
52
+ let chunk = "";
53
+ for (const line of printed(parts)) {
54
+ chunk += `${line}\n`;
55
+ if (chunk.length >= 16777216) {
56
+ yield chunk;
57
+ chunk = "";
58
+ }
59
+ }
60
+ if (chunk) yield chunk;
61
+ }
62
+ export { plainText, runtime };
@@ -0,0 +1,84 @@
1
+ import { RERUN_STATES, hasSection, list, must, ruleKey } from "../ir.mjs";
2
+ // runtime/skills/statechart/scripts/backends/report.ts
3
+ const stepsOf = (story) => {
4
+ const path = [];
5
+ for (const { step, state } of story) {
6
+ const parts = [];
7
+ for (const [name, names] of Object.entries(state)) parts.push((name ? `${name} ` : "") + names.join(" / "));
8
+ path.push({
9
+ step,
10
+ state: parts.join(", ")
11
+ });
12
+ }
13
+ return path;
14
+ };
15
+ const forever = (loop, stutters) => {
16
+ const quoted = /* @__PURE__ */ new Set();
17
+ for (const p of loop) quoted.add(`"${p.state}"`);
18
+ const runs = [...quoted];
19
+ if (stutters) return `The run stops in ${runs[0]} forever.`;
20
+ return runs.length === 1 ? `The run stays in ${runs[0]} forever.` : `The run loops through ${list(runs)} forever.`;
21
+ };
22
+ const fenced = (text) => [
23
+ "```",
24
+ text,
25
+ "```"
26
+ ].join("\n");
27
+ function report({ spec, graph, paths, rules, properties, stop, drawing, states }, found, chart, stories) {
28
+ let size = 0;
29
+ let arrows = 0;
30
+ for (const r of chart?.regions ?? []) {
31
+ size += r.states.length;
32
+ arrows += r.steps.length;
33
+ }
34
+ let past = 0;
35
+ let pastSteps = 0;
36
+ let excluded = 0;
37
+ for (const s of graph.states.values()) if (s.excluded) excluded++;
38
+ else if (s.past) past++;
39
+ for (const t of graph.steps) if (must(graph.states, t.to).past) pastSteps++;
40
+ const includes = (n) => chart ? `, and the chart includes ${n === 1 ? "it" : "them"}` : "";
41
+ const out = [
42
+ `# ${spec.module}`,
43
+ "",
44
+ paths ? `TLC reached ${states.complete && !states.cut && states.distinct > 500 ? `${states.distinct.toLocaleString("en-US")} states, more than` : "more states than"} the chart budget of 500, so ${chart ? `the chart draws only the bug paths: ${size} states and ${arrows} arrows` : "the command wrote no chart.mmd"}.` : `TLC reached ${graph.states.size - past - excluded} states and ${graph.steps.length - pastSteps} steps. The chart draws ${size} states and ${arrows} arrows.`
45
+ ];
46
+ if (drawing) out.push(`TLC stopped the drawing run with exit ${drawing.status}, so the chart draws only the states that it reached before it stopped.`);
47
+ if (!paths && !drawing && graph.states.size === past + excluded) out.push(states.initial ? "Every initial state is outside the constraints, so TLC explores none of them." : "TLC found no state that satisfies Init, so no state can break a rule.");
48
+ if (past) out.push(`${past === 1 ? "1 state outside the constraints ends" : `${past} states outside the constraints each end`} a rule's path${includes(past)}. TLC checks the rules in a state outside the constraints, but it does not explore past it.`);
49
+ if (excluded) out.push(`${excluded === 1 ? "1 step that the constraints exclude ends" : `${excluded} steps that the constraints exclude each end`} a rule's path${includes(excluded)}. TLC checks the rules after such a step, but it does not take the step.`);
50
+ if (chart?.inside) out.push(`The chart does not draw ${chart.inside} steps that stay in one chart state.`);
51
+ if (chart?.quiet) out.push(`The view hides ${chart.quiet} steps, so the chart does not draw them.`);
52
+ for (const { rule, outcome } of rules) if (!paths && rule.kind === "deadlock" && outcome === "broken" && (drawing || hasSection(spec, "CONSTRAINT", "ACTION_CONSTRAINT"))) out.push(drawing ? "The chart marks only the deadlock that TLC reports, because the drawing run stopped before it reached every state." : "The chart marks only the deadlock that TLC reports. Under a CONSTRAINT or an ACTION_CONSTRAINT, a state with no step in the chart can still have steps that the constraints leave out, and TLC does not count it as a deadlock.");
53
+ if (chart?.lie) out.push(`${chart.lie} So the chart draws parent states in place of regions.`);
54
+ out.push(...chart?.notes ?? []);
55
+ const merged = [];
56
+ for (const k of ["VIEW", "SYMMETRY"]) if (hasSection(spec, k)) merged.push(k);
57
+ if (chart && merged.length) out.push(`With ${list(merged)}, TLC keeps one representative for each group of states that it counts as the same. An arrow can lead to the representative rather than to the state that the step reaches.`);
58
+ for (const bug of found) {
59
+ const steps = `${bug.path.length} step${bug.path.length === 1 ? "" : "s"}`;
60
+ out.push("", `## ${bug.rule.name} breaks`);
61
+ out.push(bug.rule.kind === "property" ? `TLC's counterexample is in tlc-${bug.rule.name}.out. It has ${steps}:` : `The shortest path has ${steps}:`);
62
+ const path = stepsOf(must(stories, bug));
63
+ for (const [i, p] of path.entries()) out.push(`${i}. ${p.step ? `${p.step}: ` : ""}${p.state}`);
64
+ if (bug.loop !== void 0) out.push(forever(path.slice(bug.loop), bug.stutters));
65
+ }
66
+ const drawn = /* @__PURE__ */ new Set();
67
+ for (const b of found) drawn.add(ruleKey(b.rule));
68
+ const holds = [];
69
+ const unchecked = [];
70
+ for (const { rule, outcome, messages } of [...rules, ...properties]) if (outcome === "holds") holds.push(rule.name);
71
+ else if (outcome === "not checked") unchecked.push(rule.name);
72
+ else if (messages && !drawn.has(ruleKey(rule))) out.push("", `## ${rule.name} breaks`, `TLC found a counterexample. It is in tlc-${rule.name}.out.`);
73
+ if (holds.length) out.push("", "## Rules that hold", holds.join(", "));
74
+ if (unchecked.length) out.push("", "## Rules not checked", unchecked.join(", "));
75
+ if (unchecked.length && states.cut) out.push(`After the first break, each TLC run stops at ${RERUN_STATES.toLocaleString("en-US")} distinct states. A run reached that bound before it checked ${unchecked.length === 1 ? "this rule" : "these rules"} in every state.`);
76
+ if (stop) out.push(...unchecked.length ? [`TLC stopped with exit ${stop.status} before it checked ${unchecked.length === 1 ? "this rule" : "these rules"}:`] : [
77
+ "",
78
+ "## TLC stopped",
79
+ `TLC stopped with exit ${stop.status}:`
80
+ ], fenced(stop.message));
81
+ for (const p of properties) if (p.outcome === "holds" && p.initialOnly) out.push(`TLC checked ${p.rule.name} only in the initial states, because it has no [], <>, or ~>. List it as an INVARIANT to check every state.`);
82
+ return out.join("\n");
83
+ }
84
+ export { report };
@@ -0,0 +1,268 @@
1
+ import { CHECK_DEADLOCK } from "../ir.mjs";
2
+ // runtime/skills/statechart/scripts/frontends/config.ts
3
+ const isListField = (field) => field === "invariants" || field === "properties" || field === "constraints" || field === "actionConstraints";
4
+ const SECTIONS = /* @__PURE__ */ new Map();
5
+ for (const section of [
6
+ {
7
+ key: "CONSTANT",
8
+ plural: "CONSTANTS"
9
+ },
10
+ {
11
+ key: CHECK_DEADLOCK,
12
+ field: "checkDeadlock"
13
+ },
14
+ {
15
+ key: "INIT",
16
+ field: "init",
17
+ undefinedNoun: "initial predicate"
18
+ },
19
+ {
20
+ key: "NEXT",
21
+ field: "next",
22
+ undefinedNoun: "next state action"
23
+ },
24
+ {
25
+ key: "SPECIFICATION",
26
+ field: "spec",
27
+ undefinedNoun: "name"
28
+ },
29
+ {
30
+ key: "VIEW",
31
+ field: "view",
32
+ undefinedNoun: "view function"
33
+ },
34
+ {
35
+ key: "SYMMETRY",
36
+ field: "symmetry",
37
+ undefinedNoun: "symmetry function"
38
+ },
39
+ {
40
+ key: "TYPE",
41
+ field: "type"
42
+ },
43
+ {
44
+ key: "TYPE_CONSTRAINT",
45
+ field: "typeConstraint"
46
+ },
47
+ {
48
+ key: "INVARIANT",
49
+ plural: "INVARIANTS",
50
+ field: "invariants",
51
+ undefinedNoun: "invariant"
52
+ },
53
+ {
54
+ key: "PROPERTY",
55
+ plural: "PROPERTIES",
56
+ field: "properties",
57
+ undefinedNoun: "property"
58
+ },
59
+ {
60
+ key: "CONSTRAINT",
61
+ plural: "CONSTRAINTS",
62
+ field: "constraints",
63
+ undefinedNoun: "constraint"
64
+ },
65
+ {
66
+ key: "ACTION_CONSTRAINT",
67
+ plural: "ACTION_CONSTRAINTS",
68
+ field: "actionConstraints",
69
+ undefinedNoun: "action constraint"
70
+ }
71
+ ]) {
72
+ SECTIONS.set(section.key, section);
73
+ if (section.plural) SECTIONS.set(section.plural, section);
74
+ }
75
+ const NAME = /^\w*[A-Za-z]\w*$/;
76
+ const WORD = /\w+/y;
77
+ const CONFIG_HOLDS = "A config can hold only names, numbers, strings, comments, and the symbols { } ( ) [ ] , = ! <-.";
78
+ const shown = (c) => {
79
+ const code = c.codePointAt(0) ?? 0;
80
+ const hex = `U+${code.toString(16).toUpperCase().padStart(4, "0")}`;
81
+ if (code < 32 || code === 127) return hex;
82
+ return code < 127 ? `"${c}"` : `"${c}" (${hex})`;
83
+ };
84
+ function tokenizeConfig(text, cannot) {
85
+ if (text.startsWith("")) throw cannot(1, "The file starts with a byte order mark. Save it as UTF-8 without one.");
86
+ const tokens = [];
87
+ let line = 1;
88
+ let last = 1;
89
+ let i = 0;
90
+ const skip = (to) => {
91
+ for (; i < to; i++) {
92
+ last = line;
93
+ if (text[i] === "\n" || text[i] === "\r" && text[i + 1] !== "\n") line++;
94
+ }
95
+ };
96
+ const push = (image) => {
97
+ tokens.push({
98
+ image,
99
+ line
100
+ });
101
+ skip(i + image.length);
102
+ };
103
+ while (i < text.length) {
104
+ const c = text[i];
105
+ const two = text.slice(i, i + 2);
106
+ const start = line;
107
+ if (c === " " || c === " " || c === "\n" || c === "\r") skip(i + 1);
108
+ else if (two === "\\*") {
109
+ const end = text.slice(i).search(/[\n\r]/);
110
+ skip(end < 0 ? text.length : i + end);
111
+ } else if (two === "(*") {
112
+ const marks = /\(\*|\*\)/g;
113
+ let depth = 0;
114
+ do {
115
+ marks.lastIndex = i;
116
+ const m = marks.exec(text);
117
+ if (!m) throw cannot(start, "A comment starts here and does not end.");
118
+ depth += m[0] === "(*" ? 1 : -1;
119
+ skip(m.index + 2);
120
+ } while (depth);
121
+ } else if (c === "\"") {
122
+ let j = i + 1;
123
+ while (text[j] !== "\"") {
124
+ const ch = text[j];
125
+ if (ch === void 0) throw cannot(start, "A string starts here and does not end.");
126
+ if (ch === "\n" || ch === "\r") throw cannot(start, "A string starts here and does not end on its line. Write \\n for a line break in a string.");
127
+ if (ch === "\0") throw cannot(start, "A string has the character U+0000.");
128
+ if (ch === "\\" && text[j + 1] !== void 0 && !"\"\\ntrf".includes(text[j + 1])) throw cannot(start, `A string has a backslash before ${shown(text[j + 1])}. A string can use only the escapes \\" \\\\ \\n \\t \\r \\f.`);
129
+ j += ch === "\\" ? 2 : 1;
130
+ }
131
+ push(text.slice(i, j + 1));
132
+ } else if (/\w/.test(c)) {
133
+ WORD.lastIndex = i;
134
+ const word = WORD.exec(text)?.[0] ?? c;
135
+ if (/^[WS]F_/.test(word)) throw cannot(start, `TLC reads ${word.slice(0, 3)} at the start of a word as a TLA+ keyword, so it cannot read ${word} as a name.`);
136
+ if (!/[A-Za-z]/.test(word) && word !== "_") {
137
+ if (/\D/.test(word)) throw cannot(start, `TLC splits ${word} into ${word.match(/\d+|_/g)?.join(" ")}, because a name needs a letter.`);
138
+ if (Number(word) > 2147483647) throw cannot(start, `TLC cannot read a number above 2147483647, such as ${word}.`);
139
+ }
140
+ push(word);
141
+ } else if (two === "<-") push(two);
142
+ else if ([
143
+ "[]",
144
+ "]_",
145
+ "==",
146
+ "=<",
147
+ "!!"
148
+ ].includes(two)) throw cannot(start, `TLC reads ${two} as one TLA+ symbol, and a config cannot hold it.`);
149
+ else if ("{}()[],=!".includes(c)) push(c);
150
+ else {
151
+ const ch = String.fromCodePoint(text.codePointAt(i) ?? 0);
152
+ const where = ch > "" ? " outside a string" : "";
153
+ throw cannot(start, `It cannot read the character ${shown(ch)}${where}. ${CONFIG_HOLDS}`);
154
+ }
155
+ }
156
+ return {
157
+ tokens,
158
+ end: last
159
+ };
160
+ }
161
+ function readConfig({ file, text }) {
162
+ const refuse = (line, words) => /* @__PURE__ */ new Error(`TLC refuses the config ${file} at line ${line}. ${words}`);
163
+ const cannot = (line, words) => /* @__PURE__ */ new Error(`The command cannot read the config ${file} at line ${line}. ${words}`);
164
+ const { tokens, end } = tokenizeConfig(text, cannot);
165
+ const eof = {
166
+ image: "",
167
+ line: end
168
+ };
169
+ let at = 0;
170
+ const next = () => tokens[at++] ?? eof;
171
+ let deferred;
172
+ const defer = (error) => deferred ??= error;
173
+ const defined = (t, undefinedNoun) => {
174
+ if (!NAME.test(t.image)) defer(refuse(t.line, `The ${undefinedNoun} ${t.image} specified in the configuration file is not defined in the specification.`));
175
+ };
176
+ const name = (t, what) => {
177
+ if (SECTIONS.has(t.image)) defer(cannot(t.line, `TLC would read the keyword ${t.image} as ${what}.`));
178
+ else if (!NAME.test(t.image)) defer(cannot(t.line, `TLC would read ${t.image} as ${what}, and it is not a name.`));
179
+ };
180
+ const value = (t) => {
181
+ if (t === eof) throw refuse(t.line, "It was expecting a value, but did not find it.");
182
+ if (t.image === "{") {
183
+ t = next();
184
+ if (t.image === "}") return;
185
+ value(t);
186
+ while ((t = next()).image === ",") value(next());
187
+ if (t.image !== "}") throw refuse(t.line, "It was expecting }, but did not find it.");
188
+ } else if (SECTIONS.has(t.image)) defer(cannot(t.line, `TLC would read the keyword ${t.image} as a value.`));
189
+ else if (!NAME.test(t.image) && !/^(\d+|".*")$/.test(t.image)) defer(cannot(t.line, `TLC would read ${t.image} as a value. A value is a name, a number, a string, or a set in braces.`));
190
+ };
191
+ const constant = (t, loc) => {
192
+ name(t, "a constant name");
193
+ for (t = next(); t.image === "!"; t = next()) name(t = next(), "a constant name");
194
+ if (t.image === "<-") {
195
+ t = next();
196
+ if (t.image === "[") {
197
+ t = next();
198
+ if (t === eof) throw refuse(t.line, "Expected an identifier after <-[.");
199
+ name(t, "a module name");
200
+ t = next();
201
+ if (t.image !== "]") throw refuse(t.line, "It was expecting ], but did not find it.");
202
+ t = next();
203
+ if (t === eof) throw refuse(t.line, "Expected an identifier after <-[mod].");
204
+ } else if (t === eof) throw refuse(t.line, "Expected an identifier after <-.");
205
+ name(t, "the name after <-");
206
+ return;
207
+ }
208
+ if (t.image === "(") {
209
+ value(next());
210
+ while ((t = next()).image === ",") value(next());
211
+ if (t.image !== ")") throw refuse(loc, "TLC gives no reason here. An operator's arguments are one or more values in ( ), with commas between them.");
212
+ t = next();
213
+ }
214
+ if (t.image !== "=") throw refuse(t.line, "It was expecting = or <-, but did not find it.");
215
+ t = next();
216
+ if (t.image === "[") {
217
+ t = next();
218
+ if (t === eof) throw refuse(t.line, "Expected an identifier after =[.");
219
+ name(t, "a module name");
220
+ t = next();
221
+ if (t.image !== "]") throw refuse(t.line, "It was expecting ], but did not find it.");
222
+ t = next();
223
+ }
224
+ value(t);
225
+ };
226
+ const config = {
227
+ sections: [],
228
+ invariants: [],
229
+ properties: [],
230
+ constraints: [],
231
+ actionConstraints: []
232
+ };
233
+ for (let t = next(); t !== eof;) {
234
+ const keyword = t;
235
+ const section = SECTIONS.get(keyword.image);
236
+ if (!section) throw refuse(t.line, "It was expecting a keyword, but did not find it.");
237
+ const { key, field, undefinedNoun } = section;
238
+ const begin = at;
239
+ if (field === void 0) for (t = next(); t !== eof && !SECTIONS.has(t.image); t = next()) constant(t, keyword.line);
240
+ else if (isListField(field)) for (t = next(); t !== eof && !SECTIONS.has(t.image); t = next()) {
241
+ config[field].push(t.image);
242
+ defined(t, undefinedNoun);
243
+ }
244
+ else {
245
+ t = next();
246
+ if (t === eof) throw refuse(keyword.line, `The keyword ${keyword.image} was not followed by an identifier.`);
247
+ if (field === "checkDeadlock" && t.image !== "TRUE" && t.image !== "FALSE") throw refuse(t.line, "It was expecting TRUE or FALSE, but did not find it.");
248
+ if (config[field] !== void 0) throw refuse(keyword.line, `The keyword ${keyword.image} appeared twice.`);
249
+ if (field === "checkDeadlock") config[field] = t.image === "TRUE";
250
+ else {
251
+ config[field] = t.image;
252
+ if (SECTIONS.has(t.image)) defer(cannot(t.line, `TLC would read the keyword ${t.image} as the name after ${key}.`));
253
+ else if (undefinedNoun) defined(t, undefinedNoun);
254
+ }
255
+ t = next();
256
+ }
257
+ const images = [];
258
+ for (let k = begin; k < (t === eof ? tokens.length : at - 1); k++) images.push(tokens[k].image);
259
+ config.sections.push({
260
+ key,
261
+ line: keyword.line,
262
+ tokens: images
263
+ });
264
+ }
265
+ if (deferred) throw deferred;
266
+ return config;
267
+ }
268
+ export { NAME, readConfig };
@@ -0,0 +1,67 @@
1
+ import { parseValue } from "./value.mjs";
2
+ // runtime/skills/statechart/scripts/frontends/dot.ts
3
+ const unescapeDot = (s) => {
4
+ let i = s.indexOf("\\");
5
+ if (i === -1) return s;
6
+ let out = "";
7
+ let from = 0;
8
+ for (; i !== -1 && i + 1 < s.length; i = s.indexOf("\\", i)) {
9
+ const c = s[i + 1];
10
+ if (c === "\n" || c === "\r" || c === "\u2028" || c === "\u2029") {
11
+ i++;
12
+ continue;
13
+ }
14
+ out += s.slice(from, i) + (c === "n" ? "\n" : c);
15
+ i += 2;
16
+ from = i;
17
+ }
18
+ return out + s.slice(from);
19
+ };
20
+ const parseState = (label, parsed = /* @__PURE__ */ new Map()) => {
21
+ const pairs = [];
22
+ for (const part of (label.startsWith("/\\ ") ? label.slice(3) : label).split("\n/\\ ")) {
23
+ let pair = parsed.get(part);
24
+ if (!pair) {
25
+ const [, name, value] = /^(\w+)\s*=\s*([\s\S]*)$/.exec(part) ?? [];
26
+ if (!name) throw new Error(`cannot read the TLC state line "${part}"`);
27
+ parsed.set(part, pair = [name, parseValue(value)]);
28
+ }
29
+ pairs.push(pair);
30
+ }
31
+ return Object.fromEntries(pairs);
32
+ };
33
+ const linesOf = (input) => typeof input === "string" ? input.split("\n") : input;
34
+ function parseDot(input) {
35
+ const states = /* @__PURE__ */ new Map();
36
+ const steps = /* @__PURE__ */ new Map();
37
+ const parsed = /* @__PURE__ */ new Map();
38
+ const owned = /* @__PURE__ */ new Map();
39
+ const own = (s) => {
40
+ let copy = owned.get(s);
41
+ if (copy === void 0) owned.set(copy = String(JSON.parse(JSON.stringify(s))), copy);
42
+ return copy;
43
+ };
44
+ for (const line of linesOf(input)) {
45
+ const edge = /^(-?\d+) -> (-?\d+) \[label="([^"]*)"/.exec(line);
46
+ if (edge) {
47
+ steps.set(edge.slice(1).join(" "), {
48
+ from: own(edge[1]),
49
+ to: own(edge[2]),
50
+ action: own(edge[3])
51
+ });
52
+ continue;
53
+ }
54
+ const node = /^(-?\d+) \[label="((?:[^"\\]|\\.)*)"(,style = filled)?/.exec(line);
55
+ if (node) states.set(own(node[1]), {
56
+ vars: parseState(unescapeDot(node[2]), parsed),
57
+ start: !!node[3],
58
+ breaks: []
59
+ });
60
+ }
61
+ for (const loose of steps.values()) if (!states.has(loose.from) || !states.has(loose.to)) throw new Error(`The TLC graph dump has a step ${loose.action} to or from a state that it does not list.`);
62
+ return {
63
+ states,
64
+ steps: [...steps.values()]
65
+ };
66
+ }
67
+ export { linesOf, parseDot, parseState };