@khoavu882/doflow 0.0.0-stage → 2.0.0-beta.4

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 (409) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +132 -2
  3. package/bin/doflow.js +44 -0
  4. package/core/.antigravity-plugin/hooks.json +39 -0
  5. package/core/.antigravity-plugin/mcp_config.json +18 -0
  6. package/core/.antigravity-plugin/plugin.json +31 -0
  7. package/core/.claude-plugin/marketplace.json +20 -0
  8. package/core/.claude-plugin/plugin.json +21 -0
  9. package/core/.codex-plugin/marketplace.json +20 -0
  10. package/core/.codex-plugin/plugin.json +35 -0
  11. package/core/.plugin/plugin.json +19 -0
  12. package/core/harnesses/antigravity/hooks/pre-implementation-gate.sh +9 -0
  13. package/core/harnesses/antigravity/hooks/stop-check.sh +10 -0
  14. package/core/harnesses/claude/hooks/lib.sh +304 -0
  15. package/core/harnesses/claude/hooks/mcp-tool-guard.sh +20 -0
  16. package/core/harnesses/claude/hooks/permission-audit.sh +47 -0
  17. package/core/harnesses/claude/hooks/post-compact.sh +74 -0
  18. package/core/harnesses/claude/hooks/post-edit-lint.sh +36 -0
  19. package/core/harnesses/claude/hooks/post-tool-failure.sh +47 -0
  20. package/core/harnesses/claude/hooks/pre-bash-guard.sh +20 -0
  21. package/core/harnesses/claude/hooks/pre-compact.sh +43 -0
  22. package/core/harnesses/claude/hooks/pre-implement-gate.sh +21 -0
  23. package/core/harnesses/claude/hooks/session-end.sh +89 -0
  24. package/core/harnesses/claude/hooks/session-start.sh +5 -0
  25. package/core/harnesses/claude/hooks/skill-config-audit.sh +39 -0
  26. package/core/harnesses/claude/hooks/stop-check.sh +5 -0
  27. package/core/harnesses/claude/hooks/subagent-audit.sh +7 -0
  28. package/core/harnesses/claude/hooks/user-prompt-submit.sh +5 -0
  29. package/core/harnesses/claude/settings/keybindings.json +20 -0
  30. package/core/harnesses/claude/settings/settings.json +201 -0
  31. package/core/harnesses/claude/statusline/doflow-statusline.sh +49 -0
  32. package/core/harnesses/codex/agents/core-implementer.toml +7 -0
  33. package/core/harnesses/codex/agents/quality-guardian.toml +8 -0
  34. package/core/harnesses/codex/agents/research-writer.toml +8 -0
  35. package/core/harnesses/codex/agents/spec-analyst.toml +8 -0
  36. package/core/harnesses/codex/agents/system-architect.toml +9 -0
  37. package/core/harnesses/codex/config/config.toml +10 -0
  38. package/core/harnesses/codex/hooks/hooks.json +122 -0
  39. package/core/harnesses/codex/hooks/lib.sh +335 -0
  40. package/core/harnesses/codex/hooks/mcp-tool-guard.sh +18 -0
  41. package/core/harnesses/codex/hooks/post-edit-lint.impl.sh +52 -0
  42. package/core/harnesses/codex/hooks/post-edit-lint.sh +6 -0
  43. package/core/harnesses/codex/hooks/pre-bash-guard.sh +18 -0
  44. package/core/harnesses/codex/hooks/pre-compact.impl.sh +46 -0
  45. package/core/harnesses/codex/hooks/pre-compact.sh +9 -0
  46. package/core/harnesses/codex/hooks/pre-implement-gate.sh +19 -0
  47. package/core/harnesses/codex/hooks/session-end.impl.sh +92 -0
  48. package/core/harnesses/codex/hooks/session-end.sh +5 -0
  49. package/core/harnesses/codex/hooks/session-start.sh +5 -0
  50. package/core/harnesses/codex/hooks/stop-check.sh +8 -0
  51. package/core/harnesses/codex/hooks/subagent-audit.sh +8 -0
  52. package/core/harnesses/codex/hooks/user-prompt-submit.sh +6 -0
  53. package/core/harnesses/gemini/hooks/hooks.json +77 -0
  54. package/core/harnesses/gemini/hooks/lib.sh +302 -0
  55. package/core/harnesses/gemini/hooks/mcp-tool-guard.sh +21 -0
  56. package/core/harnesses/gemini/hooks/post-edit-lint.sh +39 -0
  57. package/core/harnesses/gemini/hooks/pre-bash-guard.sh +21 -0
  58. package/core/harnesses/gemini/hooks/pre-compact.sh +38 -0
  59. package/core/harnesses/gemini/hooks/pre-implement-gate.sh +22 -0
  60. package/core/harnesses/gemini/hooks/session-end.impl.sh +89 -0
  61. package/core/harnesses/gemini/hooks/session-end.sh +5 -0
  62. package/core/harnesses/gemini/hooks/session-start.sh +5 -0
  63. package/core/harnesses/gemini/settings/adapter-defaults.json +4 -0
  64. package/core/harnesses/kiro/agents/doflow.json +58 -0
  65. package/core/harnesses/kiro/hooks/doflow.json +53 -0
  66. package/core/harnesses/kiro/hooks/lib.sh +324 -0
  67. package/core/harnesses/kiro/hooks/mcp-tool-guard.sh +9 -0
  68. package/core/harnesses/kiro/hooks/pre-bash-guard.sh +9 -0
  69. package/core/harnesses/kiro/hooks/pre-implement-gate.sh +9 -0
  70. package/core/harnesses/kiro/hooks/session-start.sh +9 -0
  71. package/core/harnesses/kiro/hooks/stop-check.sh +43 -0
  72. package/core/harnesses/shared/hooks/ENVELOPE_MIGRATION.md +39 -0
  73. package/core/harnesses/shared/hooks/adapters/antigravity.js +111 -0
  74. package/core/harnesses/shared/hooks/adapters/arg-fields.js +19 -0
  75. package/core/harnesses/shared/hooks/adapters/gemini.js +114 -0
  76. package/core/harnesses/shared/hooks/hooks.json +47 -0
  77. package/core/harnesses/shared/hooks/policies/blocked-patterns.conf +91 -0
  78. package/core/harnesses/shared/hooks/policies/capture-failure.sh +97 -0
  79. package/core/harnesses/shared/hooks/policies/deny-json.sh +29 -0
  80. package/core/harnesses/shared/hooks/policies/lib.sh +501 -0
  81. package/core/harnesses/shared/hooks/policies/mcp-policy.conf +21 -0
  82. package/core/harnesses/shared/hooks/policies/mcp-tool-guard.sh +91 -0
  83. package/core/harnesses/shared/hooks/policies/pre-bash-guard.sh +328 -0
  84. package/core/harnesses/shared/hooks/policies/pre-implementation-gate.sh +496 -0
  85. package/core/harnesses/shared/hooks/policies/prompt-nudge.jq +131 -0
  86. package/core/harnesses/shared/hooks/policies/session-context.sh +141 -0
  87. package/core/harnesses/shared/hooks/policies/stop-check.sh +264 -0
  88. package/core/harnesses/shared/hooks/policies/subagent-audit.sh +46 -0
  89. package/core/harnesses/shared/hooks/policies/user-prompt-submit.sh +235 -0
  90. package/core/harnesses/shared/hooks/stream-hook-runner.js +590 -0
  91. package/core/harnesses/shared/locator/doflow-run +87 -0
  92. package/core/registry/advice.json +101 -0
  93. package/core/registry/assets.json +792 -0
  94. package/core/registry/capabilities.json +120 -0
  95. package/core/registry/contracts.json +189 -0
  96. package/core/registry/external-tools.json +191 -0
  97. package/core/registry/harnesses.json +2062 -0
  98. package/core/registry/lifecycle.json +231 -0
  99. package/core/registry/mcp.json +18 -0
  100. package/core/registry/models.json +79 -0
  101. package/core/registry/readiness-templates.json +118 -0
  102. package/core/registry/routes.json +47 -0
  103. package/core/registry/storage.json +1061 -0
  104. package/core/registry/verification.json +258 -0
  105. package/core/registry/workflows.json +790 -0
  106. package/core/shared/agent-specs/core-implementer.md +73 -0
  107. package/core/shared/agent-specs/quality-guardian.md +28 -0
  108. package/core/shared/agent-specs/research-writer.md +31 -0
  109. package/core/shared/agent-specs/spec-analyst.md +33 -0
  110. package/core/shared/agent-specs/system-architect.md +29 -0
  111. package/core/shared/guidance/DOFLOW_CORE.md +8 -0
  112. package/core/shared/guidance/FLAGS.md +25 -0
  113. package/core/shared/guidance/PRINCIPLES.md +61 -0
  114. package/core/shared/guidance/VERSION +1 -0
  115. package/core/shared/guidance/mcp/MCP_Context7.md +18 -0
  116. package/core/shared/guidance/mcp/MCP_Sequential.md +17 -0
  117. package/core/shared/guidance/modes/MODE_Brainstorming.md +46 -0
  118. package/core/shared/guidance/modes/MODE_DeepResearch.md +69 -0
  119. package/core/shared/guidance/modes/MODE_Introspection.md +33 -0
  120. package/core/shared/guidance/modes/MODE_Orchestration.md +57 -0
  121. package/core/shared/guidance/modes/MODE_Task_Management.md +74 -0
  122. package/core/shared/guidance/pointers/claude-gemini.md +2 -0
  123. package/core/shared/guidance/pointers/codex.md +6 -0
  124. package/core/shared/guidance/references/ARTIFACT_FORMAT.md +373 -0
  125. package/core/shared/guidance/references/ARTIFACT_VOICE.md +104 -0
  126. package/core/shared/guidance/references/CONSTITUTION_BASE.md +47 -0
  127. package/core/shared/guidance/references/DIAGRAM_GUIDE.md +161 -0
  128. package/core/shared/guidance/references/DOFLOW_CHAIN.md +87 -0
  129. package/core/shared/guidance/references/EVIDENCE_LEDGER.md +93 -0
  130. package/core/shared/guidance/references/MODEL_SELECTION.md +74 -0
  131. package/core/shared/guidance/references/ORCHESTRATION.md +36 -0
  132. package/core/shared/guidance/references/RESEARCH_CONFIG.md +21 -0
  133. package/core/shared/guidance/references/WORKFLOW_HANDOFF.md +81 -0
  134. package/core/shared/guidance/rules/RULE_01_SAFETY.md +25 -0
  135. package/core/shared/guidance/rules/RULE_02_WORKFLOW.md +23 -0
  136. package/core/shared/guidance/rules/RULE_03_QUALITY.md +14 -0
  137. package/core/shared/guidance/rules/RULE_04_QUESTIONS.md +46 -0
  138. package/core/shared/scripts/doflow/assets/mermaid-theme.json +46 -0
  139. package/core/shared/scripts/doflow/bash/do-exec-paths.sh +167 -0
  140. package/core/shared/scripts/doflow/bash/do-git-state.sh +546 -0
  141. package/core/shared/scripts/doflow/bash/do-parallel-check.sh +208 -0
  142. package/core/shared/scripts/doflow/bash/do-paths.sh +347 -0
  143. package/core/shared/scripts/doflow/bash/do-prereqs.sh +66 -0
  144. package/core/shared/scripts/doflow/bash/do-review-package.sh +127 -0
  145. package/core/shared/scripts/doflow/bash/do-task-brief.sh +698 -0
  146. package/core/shared/scripts/doflow/bash/render-audit.sh +224 -0
  147. package/core/shared/scripts/doflow/bash/render-diagrams.sh +177 -0
  148. package/core/shared/scripts/doflow/bash/render-puml.sh +223 -0
  149. package/core/shared/scripts/doflow/bash/sync-context.sh +66 -0
  150. package/core/shared/scripts/doflow/bash/validate-artifacts.sh +526 -0
  151. package/core/shared/scripts/doflow/bin/doflow-run +592 -0
  152. package/core/shared/skills/do/SKILL.md +128 -0
  153. package/core/shared/skills/do/references/estimation.md +13 -0
  154. package/core/shared/skills/do/references/pm_routing.md +25 -0
  155. package/core/shared/skills/do/references/tool_matrix.md +52 -0
  156. package/core/shared/skills/do-brainstorm/SKILL.md +252 -0
  157. package/core/shared/skills/do-code-review/README.md +49 -0
  158. package/core/shared/skills/do-code-review/SKILL.md +333 -0
  159. package/core/shared/skills/do-code-review/assets/sample_c_clean.c +71 -0
  160. package/core/shared/skills/do-code-review/assets/sample_c_smells.c +66 -0
  161. package/core/shared/skills/do-code-review/assets/sample_cpp_shift.cpp +19 -0
  162. package/core/shared/skills/do-code-review/assets/sample_csharp_clean.cs +100 -0
  163. package/core/shared/skills/do-code-review/assets/sample_csharp_smells.cs +78 -0
  164. package/core/shared/skills/do-code-review/assets/sample_java_clean.java +55 -0
  165. package/core/shared/skills/do-code-review/assets/sample_java_smells.java +56 -0
  166. package/core/shared/skills/do-code-review/assets/sample_json_clean.json +7 -0
  167. package/core/shared/skills/do-code-review/assets/sample_markdown_clean.md +30 -0
  168. package/core/shared/skills/do-code-review/assets/sample_markdown_smells.md +29 -0
  169. package/core/shared/skills/do-code-review/assets/sample_shell_heredoc.sh +38 -0
  170. package/core/shared/skills/do-code-review/assets/sample_shell_smells.sh +15 -0
  171. package/core/shared/skills/do-code-review/assets/sample_typescript_strings.ts +36 -0
  172. package/core/shared/skills/do-code-review/assets/sample_yaml_smells.yaml +6 -0
  173. package/core/shared/skills/do-code-review/content-types/config.md +83 -0
  174. package/core/shared/skills/do-code-review/content-types/markdown.md +132 -0
  175. package/core/shared/skills/do-code-review/expected_outputs/sample_c_clean_quality.json +79 -0
  176. package/core/shared/skills/do-code-review/expected_outputs/sample_c_smells_quality.json +169 -0
  177. package/core/shared/skills/do-code-review/expected_outputs/sample_cpp_shift_quality.json +49 -0
  178. package/core/shared/skills/do-code-review/expected_outputs/sample_csharp_clean_quality.json +149 -0
  179. package/core/shared/skills/do-code-review/expected_outputs/sample_csharp_smells_quality.json +157 -0
  180. package/core/shared/skills/do-code-review/expected_outputs/sample_java_clean_quality.json +67 -0
  181. package/core/shared/skills/do-code-review/expected_outputs/sample_java_smells_quality.json +97 -0
  182. package/core/shared/skills/do-code-review/expected_outputs/sample_json_clean_quality.json +33 -0
  183. package/core/shared/skills/do-code-review/expected_outputs/sample_markdown_clean_quality.json +1 -0
  184. package/core/shared/skills/do-code-review/expected_outputs/sample_markdown_smells_quality.json +16 -0
  185. package/core/shared/skills/do-code-review/expected_outputs/sample_shell_heredoc_quality.json +54 -0
  186. package/core/shared/skills/do-code-review/expected_outputs/sample_shell_smells_quality.json +91 -0
  187. package/core/shared/skills/do-code-review/expected_outputs/sample_typescript_strings_quality.json +60 -0
  188. package/core/shared/skills/do-code-review/expected_outputs/sample_yaml_smells_quality.json +46 -0
  189. package/core/shared/skills/do-code-review/languages/c.md +103 -0
  190. package/core/shared/skills/do-code-review/languages/cpp.md +103 -0
  191. package/core/shared/skills/do-code-review/languages/csharp.md +97 -0
  192. package/core/shared/skills/do-code-review/languages/dart.md +108 -0
  193. package/core/shared/skills/do-code-review/languages/go.md +92 -0
  194. package/core/shared/skills/do-code-review/languages/java.md +103 -0
  195. package/core/shared/skills/do-code-review/languages/kotlin.md +88 -0
  196. package/core/shared/skills/do-code-review/languages/php.md +109 -0
  197. package/core/shared/skills/do-code-review/languages/python.md +94 -0
  198. package/core/shared/skills/do-code-review/languages/ruby.md +105 -0
  199. package/core/shared/skills/do-code-review/languages/rust.md +99 -0
  200. package/core/shared/skills/do-code-review/languages/shell.md +90 -0
  201. package/core/shared/skills/do-code-review/languages/swift.md +88 -0
  202. package/core/shared/skills/do-code-review/languages/typescript.md +97 -0
  203. package/core/shared/skills/do-code-review/review-policy.json +47 -0
  204. package/core/shared/skills/do-code-review/rules/universal.md +49 -0
  205. package/core/shared/skills/do-code-review/scripts/code_quality_checker.py +1696 -0
  206. package/core/shared/skills/do-code-review/scripts/doc_quality_checker.py +532 -0
  207. package/core/shared/skills/do-code-review/scripts/pr_analyzer.py +620 -0
  208. package/core/shared/skills/do-code-review/scripts/review_report_generator.py +505 -0
  209. package/core/shared/skills/do-constitution/SKILL.md +72 -0
  210. package/core/shared/skills/do-design/SKILL.md +212 -0
  211. package/core/shared/skills/do-diagnose/SKILL.md +156 -0
  212. package/core/shared/skills/do-diagnose/references/code_audit.md +15 -0
  213. package/core/shared/skills/do-diagnose/references/refactoring.md +12 -0
  214. package/core/shared/skills/do-diagnose/references/root_cause.md +17 -0
  215. package/core/shared/skills/do-document/SKILL.md +81 -0
  216. package/core/shared/skills/do-document/references/api-reference.md +42 -0
  217. package/core/shared/skills/do-document/references/deep_research.md +18 -0
  218. package/core/shared/skills/do-document/references/embedded-research.md +11 -0
  219. package/core/shared/skills/do-document/references/implementation-flow.md +105 -0
  220. package/core/shared/skills/do-document/references/index_generator.md +9 -0
  221. package/core/shared/skills/do-document/references/user-guide.md +22 -0
  222. package/core/shared/skills/do-execute-plan/SKILL.md +261 -0
  223. package/core/shared/skills/do-execute-plan/references/handoff_record.md +57 -0
  224. package/core/shared/skills/do-execute-plan/references/parallel_dispatch.md +92 -0
  225. package/core/shared/skills/do-execute-plan/references/readiness_gate.md +155 -0
  226. package/core/shared/skills/do-execute-plan/references/run_position.md +63 -0
  227. package/core/shared/skills/do-execute-plan/references/scaffold.md +441 -0
  228. package/core/shared/skills/do-execute-plan/references/task_attempts.md +41 -0
  229. package/core/shared/skills/do-flow/SKILL.md +186 -0
  230. package/core/shared/skills/do-flow/references/task_classes.md +134 -0
  231. package/core/shared/skills/do-git/SKILL.md +115 -0
  232. package/core/shared/skills/do-git/references/hotfix-ritual.md +44 -0
  233. package/core/shared/skills/do-git/references/lifecycle-policy.md +54 -0
  234. package/core/shared/skills/do-git/references/release-ritual.md +64 -0
  235. package/core/shared/skills/do-implement/SKILL.md +222 -0
  236. package/core/shared/skills/do-plan/SKILL.md +219 -0
  237. package/core/shared/skills/do-test/SKILL.md +113 -0
  238. package/core/shared/templates/doflow/constitution-template.md +28 -0
  239. package/core/shared/templates/doflow/data-model-template.md +169 -0
  240. package/core/shared/templates/doflow/design-template.md +193 -0
  241. package/core/shared/templates/doflow/external-contract-template.md +35 -0
  242. package/core/shared/templates/doflow/intent-template.md +45 -0
  243. package/core/shared/templates/doflow/plan-template.md +151 -0
  244. package/core/shared/templates/doflow/question-log-template.md +51 -0
  245. package/core/shared/templates/doflow/requirement-template.md +126 -0
  246. package/core/shared/templates/doflow/specs-template.md +55 -0
  247. package/core/shared/templates/doflow/state-template.md +59 -0
  248. package/core/shared/workflows/do-flow-chain.md +17 -0
  249. package/package.json +48 -4
  250. package/src/adapters/antigravity/index.js +631 -0
  251. package/src/adapters/claude/index.js +548 -0
  252. package/src/adapters/claude/mcp.js +94 -0
  253. package/src/adapters/codex/agents.js +208 -0
  254. package/src/adapters/codex/config.js +272 -0
  255. package/src/adapters/codex/hooks.js +203 -0
  256. package/src/adapters/codex/index.js +707 -0
  257. package/src/adapters/codex/mcp.js +271 -0
  258. package/src/adapters/codex/native-projection.js +34 -0
  259. package/src/adapters/copilot/index.js +413 -0
  260. package/src/adapters/copy-tree.js +620 -0
  261. package/src/adapters/gemini/hooks.js +210 -0
  262. package/src/adapters/gemini/index.js +390 -0
  263. package/src/adapters/hook-commands.js +60 -0
  264. package/src/adapters/index.js +106 -0
  265. package/src/adapters/kiro/index.js +310 -0
  266. package/src/adapters/mcp-entries.js +331 -0
  267. package/src/adapters/opencode/index.js +466 -0
  268. package/src/adapters/pi/index.js +279 -0
  269. package/src/adapters/pi/json-members.js +185 -0
  270. package/src/adapters/pi/mcp.js +373 -0
  271. package/src/adapters/resolve-source.js +19 -0
  272. package/src/cli/commands/install.js +218 -0
  273. package/src/cli/commands/list-backups.js +21 -0
  274. package/src/cli/commands/reconcile.js +120 -0
  275. package/src/cli/commands/remove.js +82 -0
  276. package/src/cli/commands/rollback.js +172 -0
  277. package/src/cli/commands/self-update.js +33 -0
  278. package/src/cli/commands/status.js +138 -0
  279. package/src/cli/commands/tools.js +92 -0
  280. package/src/cli/commands/update.js +162 -0
  281. package/src/cli/index.js +568 -0
  282. package/src/cli/runtime-commands.js +281 -0
  283. package/src/cli/shared.js +218 -0
  284. package/src/helper/bash-helper.js +34 -0
  285. package/src/helper/git.js +24 -0
  286. package/src/helper/guardrails.js +49 -0
  287. package/src/helper/harness-paths.js +140 -0
  288. package/src/helper/marker-merge.js +116 -0
  289. package/src/helper/prompt.js +61 -0
  290. package/src/helper/repo-root.js +29 -0
  291. package/src/helper/settings-merge.js +151 -0
  292. package/src/helper/settings-scope.js +33 -0
  293. package/src/helper/toml.js +244 -0
  294. package/src/install/backup-set.js +149 -0
  295. package/src/install/backup.js +724 -0
  296. package/src/install/context.js +58 -0
  297. package/src/install/manifest.js +145 -0
  298. package/src/install/mcp.js +254 -0
  299. package/src/install/paths.js +84 -0
  300. package/src/install/targets.js +90 -0
  301. package/src/install/tool-lifecycle.js +151 -0
  302. package/src/lifecycle/bash-availability.js +25 -0
  303. package/src/lifecycle/index.js +812 -0
  304. package/src/lifecycle/mcp-index.js +28 -0
  305. package/src/lifecycle/policies.js +73 -0
  306. package/src/lifecycle/view.js +175 -0
  307. package/src/registry/index.js +611 -0
  308. package/src/release/build-package.js +91 -0
  309. package/src/release/changelog-section.js +70 -0
  310. package/src/release/sync-plugin-versions.js +66 -0
  311. package/src/runtime/advice/cli.js +283 -0
  312. package/src/runtime/advice/client.js +324 -0
  313. package/src/runtime/advice/config.js +189 -0
  314. package/src/runtime/advice/doctor.js +169 -0
  315. package/src/runtime/advice/endpoint-guard.js +134 -0
  316. package/src/runtime/advice/kinds.js +154 -0
  317. package/src/runtime/advice/providers/ollama-systemone.js +209 -0
  318. package/src/runtime/advice/record.js +166 -0
  319. package/src/runtime/advice/registry.js +170 -0
  320. package/src/runtime/advice/strength.js +66 -0
  321. package/src/runtime/brief-tools.js +342 -0
  322. package/src/runtime/c4-project.js +371 -0
  323. package/src/runtime/capability-router.js +484 -0
  324. package/src/runtime/checkouts.js +170 -0
  325. package/src/runtime/claims.js +468 -0
  326. package/src/runtime/cli-result.js +55 -0
  327. package/src/runtime/cli.js +678 -0
  328. package/src/runtime/command-detect.js +516 -0
  329. package/src/runtime/context-pack.js +492 -0
  330. package/src/runtime/decision-register.js +493 -0
  331. package/src/runtime/evidence-ledger.js +338 -0
  332. package/src/runtime/failure/capture.js +272 -0
  333. package/src/runtime/failure/classifier.js +68 -0
  334. package/src/runtime/failure/cli.js +178 -0
  335. package/src/runtime/failure/home.js +64 -0
  336. package/src/runtime/failure/store.js +226 -0
  337. package/src/runtime/feature-resolve.js +79 -0
  338. package/src/runtime/freshness.js +177 -0
  339. package/src/runtime/health.js +863 -0
  340. package/src/runtime/history-compactor.js +237 -0
  341. package/src/runtime/implementation-gate.js +321 -0
  342. package/src/runtime/inventory/coverage.js +218 -0
  343. package/src/runtime/inventory/identity.js +65 -0
  344. package/src/runtime/inventory/index.js +705 -0
  345. package/src/runtime/inventory/precedence.js +134 -0
  346. package/src/runtime/inventory/read-scopes.js +131 -0
  347. package/src/runtime/inventory/siblings.js +192 -0
  348. package/src/runtime/knowledge/chunker.js +124 -0
  349. package/src/runtime/knowledge/hybrid.js +149 -0
  350. package/src/runtime/knowledge/index-store.js +145 -0
  351. package/src/runtime/knowledge/retrieval.js +194 -0
  352. package/src/runtime/leak-scan.js +185 -0
  353. package/src/runtime/lifecycle/cli.js +276 -0
  354. package/src/runtime/lifecycle/event-store.js +340 -0
  355. package/src/runtime/lifecycle/fold.js +353 -0
  356. package/src/runtime/lifecycle/followup.js +432 -0
  357. package/src/runtime/lifecycle/goal.js +249 -0
  358. package/src/runtime/lifecycle/intent-writer.js +86 -0
  359. package/src/runtime/lifecycle/overview.js +292 -0
  360. package/src/runtime/lifecycle/release.js +241 -0
  361. package/src/runtime/lifecycle/report-store.js +221 -0
  362. package/src/runtime/lifecycle/retention.js +212 -0
  363. package/src/runtime/lifecycle/root.js +71 -0
  364. package/src/runtime/lifecycle/status.js +353 -0
  365. package/src/runtime/lifecycle/store-upkeep.js +393 -0
  366. package/src/runtime/locator-resolve.js +158 -0
  367. package/src/runtime/mask.js +210 -0
  368. package/src/runtime/mcp-consultations.js +412 -0
  369. package/src/runtime/mcp-reach.js +157 -0
  370. package/src/runtime/model-router.js +153 -0
  371. package/src/runtime/outcome.js +467 -0
  372. package/src/runtime/reach.js +148 -0
  373. package/src/runtime/readiness-record.js +150 -0
  374. package/src/runtime/readiness.js +435 -0
  375. package/src/runtime/recovery.js +282 -0
  376. package/src/runtime/research-request.js +231 -0
  377. package/src/runtime/retrieval-plan.js +578 -0
  378. package/src/runtime/scaffold/artifacts.js +217 -0
  379. package/src/runtime/scaffold/fingerprint.js +56 -0
  380. package/src/runtime/scaffold/generate.js +911 -0
  381. package/src/runtime/scaffold/languages.js +245 -0
  382. package/src/runtime/storage/cli.js +64 -0
  383. package/src/runtime/storage/engine.js +249 -0
  384. package/src/runtime/storage/registry.js +130 -0
  385. package/src/runtime/storage/roots.js +63 -0
  386. package/src/runtime/storage/rules.js +282 -0
  387. package/src/runtime/storage/upkeep.js +243 -0
  388. package/src/runtime/storage/work-status.js +326 -0
  389. package/src/runtime/task-attempts.js +415 -0
  390. package/src/runtime/task-classifier.js +550 -0
  391. package/src/runtime/task-scope.js +130 -0
  392. package/src/runtime/task-state.js +176 -0
  393. package/src/runtime/trace/indicators.js +235 -0
  394. package/src/runtime/trace/ledger.js +626 -0
  395. package/src/runtime/trace/render.js +76 -0
  396. package/src/runtime/trace/views.js +459 -0
  397. package/src/runtime/verification/contract-runner.js +341 -0
  398. package/src/runtime/verification/engine.js +1461 -0
  399. package/src/runtime/verification/registry.js +130 -0
  400. package/src/runtime/verification/scope-bound.js +418 -0
  401. package/src/runtime/verification/test-selection.js +172 -0
  402. package/src/runtime/workflow-engine.js +588 -0
  403. package/src/runtime/workflow-orchestrator.js +953 -0
  404. package/src/runtime/worktree.js +340 -0
  405. package/src/state/index.js +193 -0
  406. package/src/state/lockfile.js +136 -0
  407. package/src/state/run-lock.js +408 -0
  408. package/types/node-commonjs.d.ts +68 -0
  409. package/types/runtime.d.ts +91 -0
@@ -0,0 +1,371 @@
1
+ 'use strict';
2
+
3
+ // TypeScript migration (agent-docs/BRIEF_GOAL_DOFLOW.md): run directly by Node native type-stripping.
4
+
5
+ /**
6
+ * Project a C4-PlantUML source into the Mermaid flowchart that stands for it (035 IC-002/IC-004).
7
+ *
8
+ * Lives in the JS runtime, not beside the shell helpers, because G12 keeps this repo to ONE runtime
9
+ * implementation: `core/` carries pure bash plus Node, and Python outside the skill-owned analyzers
10
+ * is how a shadow tree grew the first time, one individually-defensible module at a time. The first
11
+ * draft of this projector was that module. `render-puml.sh` shells out to node here, the same way
12
+ * `render-audit.sh` already does.
13
+ *
14
+ * The projection is LOSSY BY DESIGN and deterministic. It keeps nodes, edges, labels, and boundaries
15
+ * with their nesting.
16
+ * It drops element type, technology, description, sprite, tag, link and the legend -- seven things a
17
+ * reader opens the rendered image for, which is why the emitted block names its source.
18
+ *
19
+ * It REFUSES rather than degrades. A macro neither recognized nor explicitly skipped stops the
20
+ * projection, naming the macro, the file and the line. Skipping would emit a diagram carrying fewer
21
+ * elements than its source with nothing revealing the loss.
22
+ *
23
+ * The recognized set was verified by exercising every candidate against PlantUML 1.2026.8's own
24
+ * syntax check, not transcribed from documentation -- which is how the RelIndex family was found
25
+ * absent from all six bundled includes despite appearing in the published API reference.
26
+ */
27
+
28
+ const crypto = require('node:crypto');
29
+ const fs = require('node:fs');
30
+
31
+ /** 20 element macros. Each projects to one node; the variant carries type the projection drops. */
32
+ const ELEMENTS = new Set([
33
+ 'Person', 'Person_Ext',
34
+ 'System', 'System_Ext', 'SystemDb', 'SystemDb_Ext', 'SystemQueue', 'SystemQueue_Ext',
35
+ 'Container', 'Container_Ext', 'ContainerDb', 'ContainerDb_Ext', 'ContainerQueue', 'ContainerQueue_Ext',
36
+ 'Component', 'Component_Ext', 'ComponentDb', 'ComponentDb_Ext', 'ComponentQueue', 'ComponentQueue_Ext',
37
+ ]);
38
+
39
+ /** 4 boundary macros. Each opens a brace block and projects to one subgraph. */
40
+ const BOUNDARIES = new Set(['System_Boundary', 'Container_Boundary', 'Enterprise_Boundary', 'Boundary']);
41
+
42
+ /**
43
+ * 18 relationship macros. All share ($from, $to, $label, $techn, ...), so one shape matches the
44
+ * family, and the direction suffix is a PlantUML layout hint that does NOT survive the projection --
45
+ * Mermaid declares its own direction, and carrying the hint through would be importing another
46
+ * renderer's layout, which the diagram guide lists as an anti-pattern.
47
+ */
48
+ const RELATIONS = new Set([
49
+ 'Rel', 'Rel_D', 'Rel_Down', 'Rel_U', 'Rel_Up', 'Rel_L', 'Rel_Left', 'Rel_R', 'Rel_Right',
50
+ 'Rel_Back', 'Rel_Back_Neighbor', 'Rel_Neighbor',
51
+ 'BiRel', 'BiRel_Neighbor', 'BiRel_D', 'BiRel_U', 'BiRel_L', 'BiRel_R',
52
+ ]);
53
+
54
+ /** Explicit, never a prefix match: adding a styling macro is a decision, not a silent no-op. */
55
+ const SKIPPED = new Set([
56
+ 'SHOW_LEGEND', 'SHOW_FLOATING_LEGEND', 'LAYOUT_TOP_DOWN', 'LAYOUT_LEFT_RIGHT', 'LAYOUT_LANDSCAPE',
57
+ 'LAYOUT_WITH_LEGEND', 'HIDE_STEREOTYPE', 'SHOW_PERSON_OUTLINE', 'UpdateElementStyle',
58
+ 'UpdateRelStyle', 'UpdateLayoutConfig', 'UpdateBoundaryStyle', 'AddElementTag', 'AddRelTag',
59
+ 'AddBoundaryTag', 'SetDefaultLegendEntries', 'title', 'caption', 'header', 'footer', 'skinparam',
60
+ 'scale', 'legend', 'endlegend',
61
+ ]);
62
+
63
+ // Anchored as a PREFIX, not as a whole line: `parse` applies it at successive offsets so a line
64
+ // carrying more than one construct -- `System_Boundary(b, "B") { Container(x, "X") }` -- is read
65
+ // whole. Matching once per line dropped everything after the first macro and then captured the NEXT
66
+ // line's element into the boundary the lost `}` never closed.
67
+ const CALL = /^([A-Za-z_][A-Za-z0-9_]*)\s*\(/;
68
+
69
+ class Refused extends Error {}
70
+
71
+ /**
72
+ * Split a macro's arguments on commas outside quotes, stopping at its closing paren.
73
+ *
74
+ * Only TRAILING empties are dropped. Filtering every empty argument shifts the later ones left, so
75
+ * `Rel(a, b, "", "HTTPS")` projected the technology as the edge label: a plausible diagram, exit 0,
76
+ * and nothing in the output revealing the substitution. Position IS meaning in a C4 macro -- every
77
+ * relationship shares ($from, $to, $label, $techn, ...) -- so an omitted middle argument has to stay
78
+ * omitted in place rather than closing the gap.
79
+ *
80
+ * A backslash escapes the next character inside a quoted argument, so a label may contain the quote
81
+ * character itself. What survives is escaped for the target grammar by `escapeLabel` at emit time.
82
+ *
83
+ * Returns the arguments AND how many characters the call occupied, so the caller can resume scanning
84
+ * after the closing paren rather than assuming the macro owned the rest of its line.
85
+ */
86
+ function splitArgs(text ) {
87
+ const args = [];
88
+ let buf = '';
89
+ let depth = 0;
90
+ let quote = null;
91
+ let consumed = text.length;
92
+ let closed = false;
93
+ for (let i = 0; i < text.length; i += 1) {
94
+ const ch = text[i];
95
+ if (quote) {
96
+ if (ch === '\\' && i + 1 < text.length) { buf += text[i + 1]; i += 1; }
97
+ else if (ch === quote) quote = null;
98
+ else buf += ch;
99
+ } else if (ch === '"') quote = ch;
100
+ else if (ch === '(') { depth += 1; buf += ch; }
101
+ else if (ch === ')' && depth === 0) { consumed = i + 1; closed = true; break; }
102
+ else if (ch === ')') { depth -= 1; buf += ch; }
103
+ else if (ch === ',' && depth === 0) { args.push(buf.trim()); buf = ''; }
104
+ else buf += ch;
105
+ }
106
+ args.push(buf.trim());
107
+ while (args.length && args[args.length - 1] === '') args.pop();
108
+ return { args, consumed, closed };
109
+ }
110
+
111
+ /**
112
+ * Remove PlantUML comments from one line, carrying block state across lines in `state`.
113
+ *
114
+ * ONE notion of what is inside a string, shared with `splitArgs` above: a double-quoted argument is
115
+ * opaque to comment syntax, everything outside one is not. Deciding that question twice -- once in a
116
+ * quote-blind line pass and once in the argument splitter -- is what let a literal `/'` inside a
117
+ * label open a block comment and silently swallow the rest of the source at exit 0. That is the
118
+ * projection's defining failure, and it arrived through the fix for the mirror of itself.
119
+ *
120
+ * `'` outside a quote runs to end of line, and `/' ... '/` spans lines; both are PlantUML's own
121
+ * rules. `state.openedAt` records where an unclosed block began so `parse` can name it.
122
+ *
123
+ * It also reports whether the line CONTINUES onto the next -- a trailing backslash outside any
124
+ * quote. That decision belongs here rather than in a pre-pass over the raw line, because a pre-pass
125
+ * cannot tell a continuation from a backslash inside a label: joining on the raw text turned
126
+ * `Container(a, "path \` + newline + `more")` into the label `path more`. That is the third time a
127
+ * line-level transform running ahead of quote state has silently rewritten a label, so the transform
128
+ * moved in here rather than being fixed again where it stood.
129
+ */
130
+ function stripComments(raw , state , lineno ) {
131
+ let out = '';
132
+ let quote = null;
133
+ let i = 0;
134
+ let continues = false;
135
+ while (i < raw.length) {
136
+ const ch = raw[i];
137
+ if (state.inBlock) {
138
+ if (ch === "'" && raw[i + 1] === '/') { state.inBlock = false; i += 2; } else i += 1;
139
+ } else if (quote) {
140
+ out += ch;
141
+ continues = false;
142
+ if (ch === '\\' && i + 1 < raw.length) { out += raw[i + 1]; i += 2; continue; }
143
+ if (ch === quote) quote = null;
144
+ i += 1;
145
+ } else if (ch === '/' && raw[i + 1] === "'") {
146
+ state.inBlock = true;
147
+ state.openedAt = lineno;
148
+ i += 2;
149
+ } else if (ch === "'") {
150
+ break;
151
+ } else {
152
+ if (ch === '"') quote = ch;
153
+ out += ch;
154
+ if (ch === '\\') continues = true;
155
+ else if (!/\s/.test(ch)) continues = false;
156
+ i += 1;
157
+ }
158
+ }
159
+ return { text: continues ? out.replace(/\\\s*$/, ' ') : out, continues };
160
+ }
161
+
162
+ /** Mermaid delimits a node label with double quotes; an unescaped one inside ends it early and the
163
+ * rest of the fence stops parsing. `&quot;` is the entity Mermaid documents for this. */
164
+ function escapeLabel(text ) {
165
+ return String(text).replace(/"/g, '&quot;');
166
+ }
167
+
168
+ /**
169
+ * Mermaid takes the alias as a node id, and an id it cannot lex fails the WHOLE diagram rather than
170
+ * the one node -- so this refuses here rather than emitting a fence someone finds broken at render
171
+ * time.
172
+ *
173
+ * Measured against mermaid-cli 11.16 across fifteen spellings, not assumed. Two lessons are baked
174
+ * into the shape below. A C-style identifier -- the first guess -- refuses `a.b`, `1abc` and
175
+ * `a_b-c`, which all render fine. And permitting any run of dots and dashes is worse than wrong:
176
+ * `a--b` is a parse error, but `a---b` and `a-.-b` RENDER, as two nodes joined by a link, because
177
+ * Mermaid reads them as its own open-link and dotted-link syntax. An alias that quietly becomes an
178
+ * edge is the silent-wrong-diagram this projector exists to refuse.
179
+ *
180
+ * So: word-character runs joined by SINGLE dots or dashes. That refuses every dangerous spelling
181
+ * measured and permits every plausible one. It also refuses `-a`, `.a`, `a..b` and a lone `-` or
182
+ * `.`, which do render -- none is a plausible C4 alias, and the cost of permitting them is a class
183
+ * of silent misreading rather than a diagnostic.
184
+ */
185
+ const ALIAS = /^[A-Za-z0-9_]+([.-][A-Za-z0-9_]+)*$/;
186
+
187
+ /** Every refusal carries the file and line, so the one place that formats it owns both. */
188
+ function refuse(ctx , lineno , message ) {
189
+ throw new Refused(`${ctx.sourcePath}:${lineno}: ${message}`);
190
+ }
191
+
192
+ function requireAlias(ctx , alias , lineno , role ) {
193
+ if (!ALIAS.test(alias)) {
194
+ refuse(ctx, lineno, `${role} '${alias}' is not a usable node id. Mermaid fails the whole diagram `
195
+ + 'on one it cannot lex, and silently reads one carrying `--` or `-.-` as a LINK instead, '
196
+ + 'drawing a different diagram that looks fine. Neither is worth emitting.');
197
+ }
198
+ }
199
+
200
+ function acceptElement(ctx , name , args , lineno ) {
201
+ if (args.length < 2) refuse(ctx, lineno, `${name} needs an alias and a label`);
202
+ requireAlias(ctx, args[0], lineno, 'alias');
203
+ if (ctx.nodes.has(args[0])) {
204
+ refuse(ctx, lineno, `alias '${args[0]}' is already defined. The projector refuses rather than `
205
+ + 'keeping the last definition, which would drop an element the source declares.');
206
+ }
207
+ ctx.nodes.set(args[0], args[1]);
208
+ if (ctx.stack.length) ctx.stack[ctx.stack.length - 1].members.push(args[0]);
209
+ }
210
+
211
+ // A boundary opened inside another is that one's CHILD, not a second root. Pushing every boundary
212
+ // onto one flat list rendered the outer one as an empty subgraph and hoisted the inner one to the
213
+ // top level -- dropping a containment the source states and Mermaid supports.
214
+ function acceptBoundary(ctx , name , args , lineno ) {
215
+ if (args.length < 2) refuse(ctx, lineno, `${name} needs an alias and a label`);
216
+ requireAlias(ctx, args[0], lineno, 'boundary alias');
217
+ const b = { alias: args[0], label: args[1], members: [], children: [] };
218
+ if (ctx.stack.length) ctx.stack[ctx.stack.length - 1].children.push(b); else ctx.boundaries.push(b);
219
+ ctx.stack.push(b);
220
+ }
221
+
222
+ function acceptRelation(ctx , name , args , lineno ) {
223
+ if (args.length < 2) refuse(ctx, lineno, `${name} needs a source and a target`);
224
+ requireAlias(ctx, args[0], lineno, 'relation source');
225
+ requireAlias(ctx, args[1], lineno, 'relation target');
226
+ ctx.edges.push({ from: args[0], to: args[1], label: args[2] || '', bi: name.startsWith('BiRel') });
227
+ }
228
+
229
+ function accept(ctx , name , args , lineno ) {
230
+ if (SKIPPED.has(name)) return;
231
+ if (ELEMENTS.has(name)) acceptElement(ctx, name, args, lineno);
232
+ else if (BOUNDARIES.has(name)) acceptBoundary(ctx, name, args, lineno);
233
+ else if (RELATIONS.has(name)) acceptRelation(ctx, name, args, lineno);
234
+ else {
235
+ refuse(ctx, lineno, `unrecognized macro '${name}'. The projector refuses rather than skipping `
236
+ + 'it, because a skipped macro would silently shrink the diagram. Add it to the recognized '
237
+ + 'set in src/runtime/c4-project.js if the bundled library defines it.');
238
+ }
239
+ }
240
+
241
+ /**
242
+ * Fold the raw lines into logical ones, each tagged with the line it OPENED on.
243
+ *
244
+ * Every raw line goes through stripComments IN ORDER -- block-comment state is a property of the
245
+ * raw line, so it has to advance one raw line at a time -- and the scanner's own `continues` flag
246
+ * is what joins them. A trailing backslash inside a quoted label is therefore not a continuation,
247
+ * and the call it leaves unterminated refuses in the scan rather than absorbing the next line.
248
+ */
249
+ function toLogicalLines(text , state ) {
250
+ const rawLines = text.split('\n');
251
+ const logical = [];
252
+ let pending = null;
253
+ for (let n = 0; n < rawLines.length; n += 1) {
254
+ const stripped = stripComments(rawLines[n], state, n + 1);
255
+ if (pending === null) pending = { raw: stripped.text, lineno: n + 1 };
256
+ else pending.raw += stripped.text;
257
+ if (stripped.continues && n + 1 < rawLines.length) continue;
258
+ logical.push(pending);
259
+ pending = null;
260
+ }
261
+ if (pending !== null) logical.push(pending);
262
+ return logical;
263
+ }
264
+
265
+ /** Read every construct one logical line carries, in order. */
266
+ function scanLine(ctx , line , lineno ) {
267
+ if (!line || /^[#@!]/.test(line)) return;
268
+ // A line is scanned for constructs only when it BEGINS with one. Scanning every offset of every
269
+ // line turned any free text containing `word (` into a macro candidate, so `title My Diagram
270
+ // (v2)` refused as an unrecognized macro 'Diagram'.
271
+ if (!CALL.test(line) && line[0] !== '}' && line[0] !== '{') return;
272
+ let i = 0;
273
+ while (i < line.length) {
274
+ const ch = line[i];
275
+ if (ch === '}') { ctx.stack.pop(); i += 1; continue; }
276
+ if (ch === '{' || ch === ' ' || ch === '\t') { i += 1; continue; }
277
+ const m = CALL.exec(line.slice(i));
278
+ if (!m) {
279
+ // Text trailing a construct is prose and is ignored, the way a line OPENING with prose
280
+ // already is. But stopping blind would silently drop a recognized macro sitting after
281
+ // something unparseable, so that one case refuses instead of vanishing. Only a SEPARATOR
282
+ // hides a construct: if the gap carries any word character it is prose, and prose mentioning
283
+ // `Rel(a)` must be ignored the way prose is everywhere else.
284
+ const rest = line.slice(i);
285
+ const hit = [...rest.matchAll(/([A-Za-z_][A-Za-z0-9_]*)\s*\(/g)]
286
+ .find(([, n] ) => ELEMENTS.has(n) || BOUNDARIES.has(n) || RELATIONS.has(n));
287
+ const dropped = hit && !/[A-Za-z0-9]/.test(rest.slice(0, hit.index)) ? hit[1] : null;
288
+ if (dropped) {
289
+ refuse(ctx, lineno, `${dropped}(...) follows text on this line that is not a construct, `
290
+ + 'so it would be dropped from the projection. Put it on its own line.');
291
+ }
292
+ break;
293
+ }
294
+ const { args, consumed, closed } = splitArgs(line.slice(i + m[0].length));
295
+ if (!closed) {
296
+ refuse(ctx, lineno, `the call to ${m[1]} is never closed. Its arguments used to be truncated `
297
+ + 'silently at the end of the line, so a label split across two lines lost everything '
298
+ + 'after the first.');
299
+ }
300
+ accept(ctx, m[1], args, lineno);
301
+ i += m[0].length + consumed;
302
+ }
303
+ }
304
+
305
+ function parse(text , sourcePath ) {
306
+ const ctx = { sourcePath, nodes: new Map(), edges: [], boundaries: [], stack: [] };
307
+ const state = { inBlock: false, openedAt: 0 };
308
+ for (const entry of toLogicalLines(text, state)) scanLine(ctx, entry.raw.trim(), entry.lineno);
309
+ // An unclosed block comment used to swallow every later declaration and still exit 0 -- the same
310
+ // silent shrinking the unrecognized-macro refusal exists to deny. A malformed source refuses.
311
+ if (state.inBlock) {
312
+ refuse(ctx, state.openedAt, 'block comment opened here is never closed, so everything after it '
313
+ + "would be dropped from the projection. Close it with '/ or delete it.");
314
+ }
315
+ return { nodes: ctx.nodes, edges: ctx.edges, boundaries: ctx.boundaries };
316
+ }
317
+
318
+ function emit({ nodes, edges, boundaries } , sourceRel , digest ) {
319
+ const grouped = new Set ();
320
+ const collect = (list ) => {
321
+ for (const b of list) {
322
+ for (const a of b.members) grouped.add(a);
323
+ collect(b.children);
324
+ }
325
+ };
326
+ collect(boundaries);
327
+ const out = [
328
+ `<!-- generated from ${sourceRel} by \`doflow-run render-puml\` -- do not edit by hand`,
329
+ ` source-hash: ${digest} -->`,
330
+ '```mermaid',
331
+ 'flowchart TB',
332
+ ];
333
+ const renderBoundary = (b , indent ) => {
334
+ out.push(`${indent}subgraph ${b.alias}["${escapeLabel(b.label)}"]`);
335
+ for (const a of b.members) out.push(`${indent} ${a}["${escapeLabel(nodes.get(a) ?? a)}"]`);
336
+ for (const child of b.children) renderBoundary(child, `${indent} `);
337
+ out.push(`${indent}end`);
338
+ };
339
+ for (const b of boundaries) renderBoundary(b, ' ');
340
+ for (const [alias, label] of nodes) if (!grouped.has(alias)) out.push(` ${alias}["${escapeLabel(label)}"]`);
341
+ for (const e of edges) {
342
+ const arrow = e.bi ? '<-->' : '-->';
343
+ out.push(e.label
344
+ ? ` ${e.from} ${arrow}|"${escapeLabel(e.label)}"| ${e.to}`
345
+ : ` ${e.from} ${arrow} ${e.to}`);
346
+ }
347
+ out.push('```', '<!-- end generated -->');
348
+ return `${out.join('\n')}\n`;
349
+ }
350
+
351
+ function project(text , sourceRel = '<source>') {
352
+ const digest = crypto.createHash('sha256').update(text, 'utf8').digest('hex').slice(0, 12);
353
+ return { block: emit(parse(text, sourceRel), sourceRel, digest), digest };
354
+ }
355
+
356
+ module.exports = {
357
+ project, parse, splitArgs, stripComments, ELEMENTS, BOUNDARIES, RELATIONS, SKIPPED, Refused,
358
+ };
359
+
360
+ if (require.main === module) {
361
+ const file = process.argv[2];
362
+ if (!file) { process.stderr.write('usage: c4-project.ts <file.puml>\n'); process.exit(2); }
363
+ let text ;
364
+ try { text = fs.readFileSync(file, 'utf8'); }
365
+ catch (err ) { process.stderr.write(`c4-project: cannot read ${file}: ${err.message}\n`); process.exit(2); }
366
+ try { process.stdout.write(project(text, file).block); }
367
+ catch (err ) {
368
+ if (err instanceof Refused) { process.stderr.write(`c4-project: ${err.message}\n`); process.exit(1); }
369
+ throw err;
370
+ }
371
+ }