@mutagent/helix 0.1.0-alpha.14

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 (357) hide show
  1. package/.claude/skills/mutagent-helix/SKILL.md +113 -0
  2. package/.claude/skills/mutagent-helix/scripts/cli/codex-transcode.ts +143 -0
  3. package/.claude/skills/mutagent-helix/scripts/cli/doctor.ts +111 -0
  4. package/.claude/skills/mutagent-helix/scripts/cli/init.ts +382 -0
  5. package/.claude/skills/mutagent-helix/scripts/cli/run.sh +61 -0
  6. package/CLAUDE.md +193 -0
  7. package/LICENSE +201 -0
  8. package/NOTICE +22 -0
  9. package/README.md +209 -0
  10. package/assets/adl-loop.svg +162 -0
  11. package/assets/system-status.svg +422 -0
  12. package/bin/mutagent-cli.mjs +9950 -0
  13. package/bin/mutagent-helix.mjs +78 -0
  14. package/mutagent-agentspec/.claude/skills/mutagent-agentspec/CLAUDE.md +28 -0
  15. package/mutagent-agentspec/.claude/skills/mutagent-agentspec/SKILL.md +138 -0
  16. package/mutagent-agentspec/.claude/skills/mutagent-agentspec/assets/templates/agentspec.yaml.tpl +247 -0
  17. package/mutagent-agentspec/.claude/skills/mutagent-agentspec/references/frameworks/doc-pins.md +53 -0
  18. package/mutagent-agentspec/.claude/skills/mutagent-agentspec/references/principles.md +91 -0
  19. package/mutagent-agentspec/.claude/skills/mutagent-agentspec/references/requirements.yaml +295 -0
  20. package/mutagent-agentspec/.claude/skills/mutagent-agentspec/references/workflows/orchestrator-protocol.md +302 -0
  21. package/mutagent-agentspec/.claude/skills/mutagent-agentspec/scripts/cli/doctor.ts +116 -0
  22. package/mutagent-agentspec/.claude/skills/mutagent-agentspec/scripts/cli/init.ts +230 -0
  23. package/mutagent-agentspec/.claude/skills/mutagent-agentspec/scripts/cli/run.sh +60 -0
  24. package/mutagent-agentspec/.claude/skills/mutagent-agentspec/scripts/config/resolve-spec-dir.ts +199 -0
  25. package/mutagent-agentspec/.claude/skills/mutagent-agentspec/scripts/contract/agentspec.schema.ts +455 -0
  26. package/mutagent-agentspec/.claude/skills/mutagent-agentspec/scripts/setup/detect.ts +67 -0
  27. package/mutagent-agentspec/.claude/skills/mutagent-agentspec/scripts/validate/validate-spec.ts +93 -0
  28. package/mutagent-agentspec/LICENSE +201 -0
  29. package/mutagent-agentspec/NOTICE +19 -0
  30. package/mutagent-agentspec/README.md +44 -0
  31. package/mutagent-builder/.claude/skills/mutagent-builder/SKILL.md +100 -0
  32. package/mutagent-builder/.claude/skills/mutagent-builder/assets/agents/ai-architect.md +312 -0
  33. package/mutagent-builder/.claude/skills/mutagent-builder/assets/agents/ai-engineer.md +357 -0
  34. package/mutagent-builder/.claude/skills/mutagent-builder/assets/templates/build-report.md.tpl +39 -0
  35. package/mutagent-builder/.claude/skills/mutagent-builder/references/principles.md +31 -0
  36. package/mutagent-builder/.claude/skills/mutagent-builder/references/workflows/build-protocol.md +61 -0
  37. package/mutagent-builder/.claude/skills/mutagent-builder/references/workflows/improve-handoff.md +23 -0
  38. package/mutagent-builder/.claude/skills/mutagent-builder/scripts/cli/run.sh +60 -0
  39. package/mutagent-builder/.claude/skills/mutagent-builder/scripts/handoff/validate-build-input.ts +72 -0
  40. package/mutagent-builder/.claude/skills/mutagent-builder/scripts/sync-spec/check-sync-spec.ts +499 -0
  41. package/mutagent-builder/.claude/skills/mutagent-builder/scripts/verify/spec-impl-coverage.ts +182 -0
  42. package/mutagent-builder/CLAUDE.md +25 -0
  43. package/mutagent-builder/README.md +26 -0
  44. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/README.md +192 -0
  45. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/SKILL.md +352 -0
  46. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/agents/ai-architect.md +256 -0
  47. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/agents/ai-engineer.md +344 -0
  48. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/agents/diagnostics-analyzer.md +576 -0
  49. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/agents/discovery.md +425 -0
  50. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/templates/audit.json.tpl +24 -0
  51. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/templates/audit.md.tpl +49 -0
  52. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/templates/config.yaml.tpl +100 -0
  53. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/templates/pr-body.md.tpl +56 -0
  54. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/templates/report.html.tpl +327 -0
  55. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/templates/shared/README.md +27 -0
  56. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/templates/shared/iter-N-handover.md.tpl +125 -0
  57. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/templates/shared/self-diagnosis-contract.v0.1.0.yaml.tpl +234 -0
  58. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/templates/shared/spec.yaml.tpl +152 -0
  59. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/templates/shared/team.yaml.tpl +127 -0
  60. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/templates/shared/wave-N-dashboard.html.tpl +1712 -0
  61. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/wireframes/diagnostics/WF-2.1-nl-query.md +59 -0
  62. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/wireframes/diagnostics/WF-2.2-tier0-progress.md +58 -0
  63. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/wireframes/diagnostics/WF-2.3-analysis-progress.md +44 -0
  64. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/wireframes/diagnostics/WF-2.4-html-report.md +61 -0
  65. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/wireframes/diagnostics/WF-2.5-rca-detail.md +69 -0
  66. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/wireframes/diagnostics/WF-2.6-stale-warning.md +53 -0
  67. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/wireframes/onboarding/WF-1.1-welcome.md +60 -0
  68. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/wireframes/onboarding/WF-1.2-source-platform-picker.md +41 -0
  69. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/wireframes/onboarding/WF-1.3-source-auth.md +75 -0
  70. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/wireframes/onboarding/WF-1.4-target-picker.md +48 -0
  71. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/wireframes/onboarding/WF-1.5-ask-tool.md +43 -0
  72. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/wireframes/onboarding/WF-1.6-config-review.md +57 -0
  73. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/wireframes/onboarding/WF-1.7-filter-defaults.md +52 -0
  74. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/assets/wireframes/onboarding/WF-1.8-first-run.md +59 -0
  75. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/examples/sample-findings.json +92 -0
  76. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/examples/sample-meta.json +47 -0
  77. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/adapter-strategy.md +75 -0
  78. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/config-migration.md +84 -0
  79. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/config.md +159 -0
  80. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/filter-search-matrix.md +66 -0
  81. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/harness-knowledge.md +22 -0
  82. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/memory-format.md +78 -0
  83. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/onboarding-decisions.yaml +187 -0
  84. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/operation-inventory.md +59 -0
  85. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/overview.md +167 -0
  86. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/reference.md +119 -0
  87. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/script-index.md +101 -0
  88. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/source-adapter-contract.md +93 -0
  89. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/source-platforms/claude-code-transcripts.md +66 -0
  90. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/source-platforms/codex-transcripts.md +78 -0
  91. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/source-platforms/codex.md +145 -0
  92. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/source-platforms/install-paths.md +57 -0
  93. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/source-platforms/langfuse.md +178 -0
  94. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/source-platforms/local-jsonl.md +55 -0
  95. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/source-platforms/openobserve.md +102 -0
  96. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/source-platforms/otel.md +63 -0
  97. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/target-platforms/cloud-rest.md +84 -0
  98. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/target-platforms/local-claude.md +65 -0
  99. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/target-platforms/local-cloud-agent-sdk.md +92 -0
  100. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/target-platforms/local-codex.md +72 -0
  101. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/target-platforms/local-cursor.md +108 -0
  102. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/target-platforms/local-mastra.md +77 -0
  103. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/target-platforms/local-opencode.md +70 -0
  104. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/workflows/apply-pr-comment-format.md +82 -0
  105. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/workflows/diagnostics.md +35 -0
  106. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/workflows/handover-contract.md +247 -0
  107. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/workflows/onboarding.md +300 -0
  108. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/workflows/orchestrator-protocol.md +1861 -0
  109. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/workflows/rca.md +331 -0
  110. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/workflows/rendering-anatomy.md +314 -0
  111. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/workflows/schedule-prep.md +100 -0
  112. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/workflows/scope-model.md +128 -0
  113. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/references/workflows/verification-methodology.md +174 -0
  114. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/aggregate/sort-findings.ts +0 -0
  115. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/awareness/blind-spots.ts +167 -0
  116. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/awareness/llm-sample.ts +681 -0
  117. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/cli/doctor.ts +215 -0
  118. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/cli/init.ts +1013 -0
  119. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/cli/install-agents.ts +350 -0
  120. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/cli/run.sh +61 -0
  121. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/cli/shared-templates.ts +79 -0
  122. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/config/load.ts +392 -0
  123. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/config/resolve-credential.ts +120 -0
  124. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/config/schema.ts +641 -0
  125. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/config/validate.ts +134 -0
  126. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/context/build-diagnosis-context.ts +417 -0
  127. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/context/load-context.ts +105 -0
  128. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/contract/types.ts +166 -0
  129. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/enrich/build-render-input.ts +1964 -0
  130. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/enrich/corpus-severity.ts +172 -0
  131. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/enrich/dismissal-match.ts +270 -0
  132. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/enrich/rank-remedies.ts +75 -0
  133. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/hooks/install-hooks.sh +46 -0
  134. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/hooks/pre-push.sh +78 -0
  135. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/invocation/parse-brief.ts +188 -0
  136. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/library/match.ts +114 -0
  137. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/library/paths.ts +95 -0
  138. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/library/store.ts +535 -0
  139. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/library/types.ts +181 -0
  140. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/lint/template-inline-js.ts +267 -0
  141. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/memory/append.ts +188 -0
  142. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/memory/read.ts +218 -0
  143. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/normalize/platforms/entity-context.ts +686 -0
  144. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/normalize/read-unitf.ts +267 -0
  145. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/normalize/trace.ts +1078 -0
  146. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/normalize/unitf-adapter.ts +0 -0
  147. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/normalize/unitf-types.ts +213 -0
  148. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/report/persist-selections.ts +174 -0
  149. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/report/render.ts +3254 -0
  150. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/run/diagnose.ts +64 -0
  151. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/run/session.ts +167 -0
  152. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/sample/caps.ts +345 -0
  153. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/sample/deep-read-gate.ts +424 -0
  154. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/sample/representative.ts +584 -0
  155. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/scan/objection.ts +224 -0
  156. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/scan/trajectory.ts +489 -0
  157. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/self-diagnostics/dispatch.ts +135 -0
  158. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/self-diagnostics/probe.ts +170 -0
  159. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/setup/detect.ts +307 -0
  160. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/setup/ensure-cli.ts +315 -0
  161. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/setup/reconfigure.ts +77 -0
  162. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/setup/verify-agents.ts +207 -0
  163. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/slicer.ts +166 -0
  164. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/source/adapters/claude-code.ts +17 -0
  165. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/source/adapters/codex.ts +11 -0
  166. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/source/adapters/langfuse.ts +17 -0
  167. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/source/adapters/local-jsonl.ts +12 -0
  168. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/source/adapters/otel.ts +12 -0
  169. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/source/index.ts +54 -0
  170. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/source/registry.ts +45 -0
  171. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/source/types.ts +86 -0
  172. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/stale-detector.ts +74 -0
  173. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/test/render-playwright.cli.ts +477 -0
  174. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/tier0/claude-code.ts +133 -0
  175. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/tier0/langfuse.ts +143 -0
  176. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/tier0-scan.ts +423 -0
  177. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/validate/completeness-check.ts +436 -0
  178. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/validate/doc-refs.ts +190 -0
  179. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/validate/finalize-gate.ts +417 -0
  180. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/validate/findings-contract.ts +628 -0
  181. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/validate/render-js-syntax.ts +188 -0
  182. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/validate/report-checklist.yaml +217 -0
  183. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/validate/trace-shape.ts +262 -0
  184. package/mutagent-diagnostics/.claude/skills/mutagent-diagnostics/scripts/validate/wave6-checklist.ts +326 -0
  185. package/mutagent-diagnostics/CLAUDE.md +41 -0
  186. package/mutagent-diagnostics/LICENSE +201 -0
  187. package/mutagent-diagnostics/NOTICE +18 -0
  188. package/mutagent-diagnostics/README.md +343 -0
  189. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/SKILL.md +548 -0
  190. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/assets/agents/audit-executor.md +169 -0
  191. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/assets/agents/dataset-builder.md +160 -0
  192. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/assets/agents/discovery.md +425 -0
  193. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/assets/agents/evaluator.md +1108 -0
  194. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/assets/brand/theme.css +213 -0
  195. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/assets/brand/wordmark.html +9 -0
  196. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/lenses/context-flow-lens.md +85 -0
  197. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/lenses/data-lens.md +47 -0
  198. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/lenses/decision-lens.md +48 -0
  199. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/lenses/methodology-critic-lens.md +53 -0
  200. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/lenses/trajectory-lens.md +44 -0
  201. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/references/build-review-interface.md +83 -0
  202. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/references/edd-loop.md +134 -0
  203. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/references/error-analysis.md +113 -0
  204. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/references/eval-audit.md +154 -0
  205. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/references/eval-stage.md +168 -0
  206. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/references/generate-synthetic-data.md +81 -0
  207. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/references/grounded-adjudication.md +221 -0
  208. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/references/memory-format.md +65 -0
  209. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/references/methodology.md +201 -0
  210. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/references/operation-inventory.md +197 -0
  211. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/references/validate-evaluator.md +125 -0
  212. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/references/workflows/orchestrator-protocol.md +300 -0
  213. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/references/write-judge-prompt.md +123 -0
  214. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/schemas/behavior-tree.schema.yaml +73 -0
  215. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/schemas/dataset.schema.yaml +66 -0
  216. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/schemas/edd-change-request.schema.yaml +114 -0
  217. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/schemas/eval-matrix.schema.yaml +74 -0
  218. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/schemas/flow-graph.schema.yaml +69 -0
  219. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/schemas/flow-profile.schema.yaml +49 -0
  220. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/schemas/methodology-review.schema.yaml +40 -0
  221. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/schemas/scorecard.schema.yaml +85 -0
  222. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/agent-dispatch.ts +0 -0
  223. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/aggregate-discover.ts +543 -0
  224. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/artifact-paths.ts +115 -0
  225. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/assemble-scorecard.ts +172 -0
  226. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/build-dataset.ts +186 -0
  227. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/build-evals.ts +93 -0
  228. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/build-review-ui.ts +393 -0
  229. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/check-method-router.ts +170 -0
  230. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/cli/aggregate.ts +112 -0
  231. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/cli/audit-run.ts +182 -0
  232. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/cli/doctor.ts +211 -0
  233. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/cli/dogfood.ts +133 -0
  234. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/cli/init.ts +601 -0
  235. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/cli/methodology-review.ts +122 -0
  236. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/cli/prep.ts +295 -0
  237. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/cli/profile-subject.ts +165 -0
  238. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/cli/run.sh +56 -0
  239. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/cli/variance-check.ts +105 -0
  240. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/code-eval.ts +248 -0
  241. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/code-quality-verdict.ts +285 -0
  242. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/codegen-evals.ts +173 -0
  243. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/cold-start-project.ts +151 -0
  244. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/cold-start-sampler.ts +267 -0
  245. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/config/load.ts +343 -0
  246. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/config/schema.ts +380 -0
  247. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/contracts/agentspec-evals.ts +85 -0
  248. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/contracts/dataset.ts +149 -0
  249. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/contracts/eval-engine.ts +118 -0
  250. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/contracts/eval-matrix.ts +577 -0
  251. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/contracts/eval-types.ts +1074 -0
  252. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/contracts/flow-graph.ts +194 -0
  253. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/contracts/types.ts +303 -0
  254. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/contracts/validation.ts +193 -0
  255. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/derive-dataset.ts +152 -0
  256. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/determine-outcome.ts +219 -0
  257. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/diff-discriminate.ts +160 -0
  258. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/discover-criteria.ts +348 -0
  259. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/edd/change-request.ts +232 -0
  260. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/edd/edd-types.ts +210 -0
  261. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/edd/variance-gate.ts +186 -0
  262. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/emit-completeness.ts +111 -0
  263. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/eval-engine.ts +160 -0
  264. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/evaluate.ts +333 -0
  265. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/flow-graph.ts +230 -0
  266. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/judge-prompt-template.ts +253 -0
  267. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/judge-provider.ts +135 -0
  268. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/lint-grounding.ts +229 -0
  269. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/lint-uniformity.ts +168 -0
  270. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/living-suite.ts +109 -0
  271. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/load-bundle.ts +203 -0
  272. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/load-profile-vocab.ts +64 -0
  273. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/load-profile.ts +106 -0
  274. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/mask.ts +138 -0
  275. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/materialize-dataset.ts +113 -0
  276. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/matrix-judge.ts +750 -0
  277. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/memory/append.ts +215 -0
  278. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/memory/read.ts +168 -0
  279. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/persist-eval-criteria.ts +232 -0
  280. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/prep-tasks.ts +125 -0
  281. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/profile-subject.ts +310 -0
  282. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/publish-report.ts +131 -0
  283. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/read-unitf-traces.ts +81 -0
  284. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/render-build-cards.ts +195 -0
  285. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/render-discover-report.ts +1640 -0
  286. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/render-eval-report.ts +3838 -0
  287. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/render-report.ts +212 -0
  288. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/resolve-credential.ts +110 -0
  289. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/resolve-ref.ts +98 -0
  290. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/result-verify.ts +129 -0
  291. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/route-failures.ts +330 -0
  292. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/run-deterministic.ts +367 -0
  293. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/run-evaluate.ts +719 -0
  294. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/run-judge.ts +155 -0
  295. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/run-pipeline.ts +175 -0
  296. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/sample-traces.ts +210 -0
  297. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/self-audit.ts +387 -0
  298. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/source-map.ts +106 -0
  299. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/subject-profile.ts +134 -0
  300. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/substrate.ts +162 -0
  301. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/sync-eval-criteria.ts +244 -0
  302. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/ui-slots.ts +119 -0
  303. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/unitf-to-evaltrace.ts +284 -0
  304. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/validate-judge.ts +358 -0
  305. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/scripts/variance-compare.ts +177 -0
  306. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/subjects/mutagent-diagnostics/behavior-tree.yaml +140 -0
  307. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/subjects/mutagent-diagnostics/eval-matrix.yaml +1270 -0
  308. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/subjects/mutagent-diagnostics/methodology-review.yaml +105 -0
  309. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/workflows/audit.workflow.js +82 -0
  310. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/workflows/data-leak.workflow.js +236 -0
  311. package/mutagent-evaluator/.claude/skills/mutagent-evaluator/workflows/variance.workflow.js +163 -0
  312. package/mutagent-evaluator/CLAUDE.md +45 -0
  313. package/mutagent-evaluator/LICENSE +201 -0
  314. package/mutagent-evaluator/NOTICE +23 -0
  315. package/mutagent-evaluator/README.md +88 -0
  316. package/mutagent-optimize/.claude/skills/mutagent-optimize/SKILL.md +287 -0
  317. package/mutagent-optimize/.claude/skills/mutagent-optimize/scripts/contracts/amend-request.ts +503 -0
  318. package/mutagent-optimize/.claude/skills/mutagent-optimize/scripts/improve-loop-run.ts +304 -0
  319. package/mutagent-optimize/.claude/skills/mutagent-optimize/scripts/loop-state-cli.ts +300 -0
  320. package/mutagent-optimize/.claude/skills/mutagent-optimize/scripts/loop-state.ts +440 -0
  321. package/mutagent-optimize/CLAUDE.md +49 -0
  322. package/mutagent-optimize/README.md +26 -0
  323. package/mutagent-orchestrator/CLAUDE.md +102 -0
  324. package/mutagent-orchestrator/README.md +20 -0
  325. package/mutagent-orchestrator/assets/agents/discovery.md +425 -0
  326. package/mutagent-orchestrator/assets/agents/dogfood-monitor.md +266 -0
  327. package/mutagent-orchestrator/assets/agents/monitor.md +258 -0
  328. package/mutagent-orchestrator/orchestrator.md +782 -0
  329. package/mutagent-orchestrator/references/MONITORING.md +209 -0
  330. package/mutagent-orchestrator/references/config-fields.md +132 -0
  331. package/mutagent-orchestrator/references/config-migration.md +132 -0
  332. package/mutagent-orchestrator/references/index-registry.md +92 -0
  333. package/mutagent-orchestrator/routing.yaml +391 -0
  334. package/mutagent-orchestrator/scripts/config-schema.ts +1010 -0
  335. package/mutagent-orchestrator/scripts/dispatch.ts +439 -0
  336. package/mutagent-orchestrator/scripts/dogfood/extract-feedback.ts +203 -0
  337. package/mutagent-orchestrator/scripts/dogfood/reconstruct-trajectory.ts +327 -0
  338. package/mutagent-orchestrator/scripts/dogfood/render-dogfood-report.ts +347 -0
  339. package/mutagent-orchestrator/scripts/dogfood/resolve-subagents.ts +160 -0
  340. package/mutagent-orchestrator/scripts/dogfood/run-report.ts +264 -0
  341. package/mutagent-orchestrator/scripts/dogfood/slack-thread.ts +106 -0
  342. package/mutagent-orchestrator/scripts/dogfood/types.ts +257 -0
  343. package/mutagent-orchestrator/scripts/eval-routing.ts +753 -0
  344. package/mutagent-orchestrator/scripts/gate.ts +219 -0
  345. package/mutagent-orchestrator/scripts/handover-contract.ts +362 -0
  346. package/mutagent-orchestrator/scripts/index/build-index.ts +351 -0
  347. package/mutagent-orchestrator/scripts/index/render-index.ts +110 -0
  348. package/mutagent-orchestrator/scripts/monitor/slack-notify.ts +111 -0
  349. package/mutagent-orchestrator/scripts/monitor/triggers.ts +162 -0
  350. package/mutagent-orchestrator/scripts/onboarding-check.ts +369 -0
  351. package/mutagent-orchestrator/scripts/render-roster.ts +308 -0
  352. package/mutagent-orchestrator/scripts/resolve-credential.ts +185 -0
  353. package/mutagent-orchestrator/scripts/resolve-paths.ts +114 -0
  354. package/mutagent-orchestrator/scripts/slack/format.ts +63 -0
  355. package/mutagent-orchestrator/scripts/slack/post.ts +115 -0
  356. package/mutagent-orchestrator/scripts/sync-index.ts +311 -0
  357. package/package.json +64 -0
@@ -0,0 +1,304 @@
1
+ /**
2
+ * scripts/improve-loop-run.ts — the deterministic improve-loop FSM harness.
3
+ * ---------------------------------------------------------------------------
4
+ * ⚠️ THIS IS NOT THE INTERACTIVE RUNTIME. The interactive `*optimize` loop is
5
+ * conducted by the TOP-LEVEL SESSION (Model B) — the session is the only thing
6
+ * that can Task-dispatch sub-agents, so the SESSION conducts the loop per the
7
+ * SKILL.md "runtime conduct" procedure, calling the pure decisions one-shot via
8
+ * `scripts/loop-state-cli.ts` between dispatches. There is deliberately NO
9
+ * production `CrewBindings` implementation that `await`s Task dispatches (a
10
+ * sub-agent cannot spawn sub-agents; a TS `while` awaiting dispatches is the wrong
11
+ * shape for the interactive runtime). See CLAUDE.md "Two runtimes".
12
+ *
13
+ * What this file IS — two legitimate NON-interactive uses of the SAME FSM:
14
+ * (a) the UNIT-TEST HARNESS — tests drive the ring with a scripted fake crew to
15
+ * prove the loop-state decisions end-to-end (tests/improve-loop-run.test.ts).
16
+ * (b) a future HEADLESS VERIFICATION driver (Model A / SimuLatte sim-run) — a
17
+ * deterministic child-spawn run for CI/regression, NOT a live operator loop.
18
+ *
19
+ * INVARIANT (for both uses): the driver is deterministic TypeScript, NEVER an LLM.
20
+ * LLM work happens only inside the crew, reached through the INJECTED `CrewBindings`
21
+ * seam. Every time-like input (`now`, `monotonic`) + the crew + the fs writer are
22
+ * injected, so the same (config, crew, clock) always yields the same trajectory +
23
+ * terminator. The crew seam is a TEST/verification abstraction — the interactive
24
+ * "crew binding" is the SKILL.md procedure (an agent action), not a TS object.
25
+ */
26
+
27
+ import {
28
+ ArchitectVerdict,
29
+ GateVerdict,
30
+ LoopPhase,
31
+ Terminator,
32
+ assertGoalLegal,
33
+ checkTerminators,
34
+ initLoopState,
35
+ recordIteration,
36
+ } from "./loop-state.ts";
37
+ import type {
38
+ ArchitectVerdictValue,
39
+ GateVerdictValue,
40
+ LoopConfig,
41
+ LoopState,
42
+ TerminatorValue,
43
+ } from "./loop-state.ts";
44
+ import type { AmendRequest } from "./contracts/amend-request.ts";
45
+
46
+ /** What one crew phase needs. */
47
+ export interface TurnContext {
48
+ iteration: number;
49
+ /** the best (kept) score so far — the crew may use it for the amend brief. */
50
+ bestScore: number;
51
+ /** the prior diagnose remedy fed into this Build turn (empty on the first). */
52
+ remedy: string;
53
+ /**
54
+ * Wave-2 W2I2 (unify amend formats) — the OPTIONAL structured amend request that
55
+ * fed this Build turn, normalized to the unified `AmendRequest` superset. Both the
56
+ * evaluator (EddChangeRequest) and diagnostics (Remedy) dialects map INTO this one
57
+ * shape via scripts/contracts/amend-request.ts, so the S1 build handover reads a
58
+ * single contract regardless of emitter. ADDITIVE: absent on legacy string-only
59
+ * turns (`remedy` is the collapsed NL brief via `amendToBuildRemedy`), so the FSM
60
+ * + existing harness tests are unchanged.
61
+ */
62
+ amend?: AmendRequest;
63
+ }
64
+
65
+ /** The evaluator's re-eval outcome for one turn. */
66
+ export interface EvalOutcome {
67
+ score: number;
68
+ gate: GateVerdictValue;
69
+ criteriaPassed: string[];
70
+ varianceRegressed: boolean;
71
+ /**
72
+ * CODE-TARGET (Wave-2 W2I1) — the deterministic test-suite gate for a `code`
73
+ * subject: `true` iff the subject's OWN test suite ran green this turn. OPTIONAL:
74
+ * a non-code target omits it (undefined). Under a `code-quality` goal the
75
+ * BOTH-gate requires this strictly `true` AND `gate === PASS` to converge. In the
76
+ * interactive runtime this signal originates in S1 (ai-engineer's code-target TDD
77
+ * inner loop); the crew seam surfaces it here for the non-interactive harness.
78
+ */
79
+ testsGreen?: boolean;
80
+ }
81
+
82
+ /**
83
+ * The crew seam for the NON-interactive uses only (unit test · future headless
84
+ * verification). The interactive runtime has NO such TS binding — the session
85
+ * conducts and Task-dispatches the real sub-agents per SKILL.md. Kept abstract so
86
+ * the FSM is driveable by a scripted fake crew (no LLM, no sub-agents) in tests,
87
+ * or by a headless child-spawn binding (Model A / sim-run) for CI regression.
88
+ */
89
+ export interface CrewBindings {
90
+ /** S1 — ai-engineer #apply (worktree-scoped WRITE). Returns the applied diff summary. */
91
+ build(ctx: TurnContext): Promise<{ appliedDiff: string }>;
92
+ /** S2 — ai-architect PROCEED|STEER|ABORT on the applied change. */
93
+ verify(ctx: TurnContext): Promise<ArchitectVerdictValue>;
94
+ /** S3+S4 — evaluator re-eval swing → score + GATE verdict. */
95
+ evaluate(ctx: TurnContext): Promise<EvalOutcome>;
96
+ /** S5 — analyzer RCA on the new failures (feeds the next Build). Only on a FAIL gate. */
97
+ diagnose(ctx: TurnContext): Promise<{ remedy: string }>;
98
+ }
99
+
100
+ /** Everything injected → determinism (mirrors sim-run.ts RunOptions). */
101
+ export interface RunOptions {
102
+ runId: string;
103
+ crew: CrewBindings;
104
+ /** injected ISO clock (audit stamps). */
105
+ now: () => string;
106
+ /** injected monotonic ms (budget accounting) — NOT wall-clock. */
107
+ monotonic: () => number;
108
+ /** where loop-state.json + the report are written. */
109
+ projectRoot: string;
110
+ /** fs writer seam (tests capture without touching disk). */
111
+ writeFile: (path: string, contents: string) => void;
112
+ mkdirp: (path: string) => void;
113
+ /** wirecard sink (default: console.info via the CLI). */
114
+ out: (line: string) => void;
115
+ /** emit the living HTML report. */
116
+ html?: boolean;
117
+ }
118
+
119
+ export interface RunResult {
120
+ state: LoopState;
121
+ terminator: TerminatorValue;
122
+ /** the final wirecard (also emitted via opts.out during the run). */
123
+ wirecard: string;
124
+ /** the report HTML (present when opts.html). */
125
+ reportHtml?: string;
126
+ }
127
+
128
+ const runDir = (projectRoot: string, runId: string): string =>
129
+ `${projectRoot}/.mutagent/optimize/runs/${runId}`;
130
+
131
+ /**
132
+ * Run the bounded improve loop. Deterministic given (config, crew, clock).
133
+ * Throws (goal-legality) if the config is not bounded.
134
+ */
135
+ export async function runImproveLoop(config: LoopConfig, opts: RunOptions): Promise<RunResult> {
136
+ // Refuses an un-yardsticked loop: unbounded config OR an unresolved natural-language
137
+ // goal (Wave-2 W2I10). A headless run has NO human to confirm-freeze an NL goal, so an
138
+ // unfrozen NL goal throws here — the driver never runs a free-text goal unbounded (it
139
+ // must be a structured goal or a pre-frozen NL criterion). See assertGoalLegal.
140
+ assertGoalLegal(config);
141
+ const dir = runDir(opts.projectRoot, opts.runId);
142
+ opts.mkdirp(dir);
143
+
144
+ const start = opts.monotonic();
145
+ let state = initLoopState();
146
+ let remedy = "";
147
+ let terminator: TerminatorValue | null = null;
148
+ let lastVerify: ArchitectVerdictValue = ArchitectVerdict.Proceed;
149
+
150
+ // hard iteration ceiling belt-and-suspenders (checkTerminators also enforces it)
151
+ while (terminator === null && state.iteration < config.maxIters + 1) {
152
+ const iteration = state.iteration + 1;
153
+ const ctx: TurnContext = { iteration, bestScore: state.bestScore, remedy };
154
+
155
+ // S1 BUILD (ai-engineer #apply, worktree-scoped)
156
+ await opts.crew.build(ctx);
157
+
158
+ // S2 VERIFY (ai-architect)
159
+ lastVerify = await opts.crew.verify(ctx);
160
+
161
+ let evalOut: EvalOutcome;
162
+ if (lastVerify === ArchitectVerdict.Abort) {
163
+ // ABORT ends the turn with no eval — record a non-improving turn at the best score.
164
+ evalOut = { score: state.bestScore === Number.NEGATIVE_INFINITY ? 0 : state.bestScore, gate: GateVerdict.Fail, criteriaPassed: [], varianceRegressed: false };
165
+ } else if (lastVerify === ArchitectVerdict.Steer) {
166
+ // STEER — the change needs rework; count a non-improving turn, re-build next iteration.
167
+ evalOut = { score: state.bestScore === Number.NEGATIVE_INFINITY ? 0 : state.bestScore, gate: GateVerdict.Fail, criteriaPassed: [], varianceRegressed: false };
168
+ } else {
169
+ // S3+S4 EVAL + GATE (evaluator re-eval swing)
170
+ evalOut = await opts.crew.evaluate(ctx);
171
+ }
172
+
173
+ const budgetSpentMs = opts.monotonic() - start;
174
+ state = recordIteration(state, config, {
175
+ verify: lastVerify,
176
+ gate: evalOut.gate,
177
+ score: evalOut.score,
178
+ varianceRegressed: evalOut.varianceRegressed,
179
+ budgetSpentMs,
180
+ // CODE-TARGET (Wave-2 W2I1) — threaded verbatim (undefined for non-code turns
181
+ // + for ABORT/STEER turns that never reached eval). The BOTH-gate lives in
182
+ // loop-state's goalMet(code-quality); the driver only carries the signal.
183
+ testsGreen: evalOut.testsGreen,
184
+ });
185
+
186
+ // persist the cursor + emit the wirecard every iteration
187
+ opts.writeFile(`${dir}/loop-state.json`, JSON.stringify(state, null, 2) + "\n");
188
+ opts.out(renderWirecard(state, config, lastVerify, false));
189
+
190
+ terminator = checkTerminators(state, config, lastVerify, new Set(evalOut.criteriaPassed));
191
+ if (terminator !== null) break;
192
+
193
+ // S5 DIAGNOSE — a FAIL gate that is still continuing gets RCA to feed the next Build.
194
+ if (evalOut.gate === GateVerdict.Fail && lastVerify === ArchitectVerdict.Proceed) {
195
+ remedy = (await opts.crew.diagnose(ctx)).remedy;
196
+ } else {
197
+ remedy = "";
198
+ }
199
+ }
200
+
201
+ // by construction the loop only exits via a terminator; default to MaxIters.
202
+ const finalTerminator = terminator ?? Terminator.MaxIters;
203
+ state = { ...state, terminator: finalTerminator, phase: LoopPhase.Terminal };
204
+ opts.writeFile(`${runDir(opts.projectRoot, opts.runId)}/loop-state.json`, JSON.stringify(state, null, 2) + "\n");
205
+
206
+ const wirecard = renderWirecard(state, config, lastVerify, true);
207
+ opts.out(wirecard);
208
+
209
+ let reportHtml: string | undefined;
210
+ if (opts.html) {
211
+ reportHtml = renderReportHtml(state, config, opts.runId, opts.now());
212
+ opts.writeFile(`${runDir(opts.projectRoot, opts.runId)}/optimize-report.html`, reportHtml);
213
+ }
214
+
215
+ return { state, terminator: finalTerminator, wirecard, reportHtml };
216
+ }
217
+
218
+ /** The periodic terminal dashboard — iteration · phase · per-gate · Δ · terminator. */
219
+ export function renderWirecard(
220
+ state: LoopState,
221
+ config: LoopConfig,
222
+ lastVerify: ArchitectVerdictValue,
223
+ terminal: boolean,
224
+ ): string {
225
+ const last = state.history[state.history.length - 1];
226
+ const lines: string[] = [];
227
+ lines.push(
228
+ `┌─ optimize ${terminal ? "· TERMINAL" : ""} ─ iter ${state.iteration}/${config.maxIters} · phase ${state.phase}`,
229
+ );
230
+ if (last) {
231
+ // CODE-TARGET (Wave-2 W2I1) — surface the deterministic test-suite gate ONLY when
232
+ // it was recorded (a `code` subject turn). Absent ⇒ the line is byte-identical to
233
+ // pre-W2I1 for every non-code target.
234
+ const testsCell =
235
+ last.testsGreen === undefined ? "" : ` · tests ${last.testsGreen ? "GREEN" : "red"}`;
236
+ lines.push(
237
+ `│ verify ${lastVerify} · gate ${last.gate}${testsCell} · score ${last.score.toFixed(3)} · Δ ${last.delta >= 0 ? "+" : ""}${last.delta.toFixed(3)} · ${last.improved ? "IMPROVED" : "flat"}`,
238
+ );
239
+ }
240
+ lines.push(
241
+ `│ best ${state.bestScore === Number.NEGATIVE_INFINITY ? "—" : state.bestScore.toFixed(3)} · no-improve ${state.noImprovementCount}/${config.noImprovementStreak} · budget ${Math.round(state.budgetSpentMs)}ms/${config.budgetMs}ms`,
242
+ );
243
+ if (terminal && state.terminator) {
244
+ lines.push(`└─ TERMINATED: ${state.terminator} (goal: ${goalLabel(config)})`);
245
+ } else {
246
+ lines.push(`└─ goal: ${goalLabel(config)}`);
247
+ }
248
+ return lines.join("\n");
249
+ }
250
+
251
+ function goalLabel(config: LoopConfig): string {
252
+ switch (config.goal.kind) {
253
+ case "eval-pass":
254
+ return "eval-pass (GATE PASS)";
255
+ case "criterion":
256
+ return `criterion:${config.goal.id}`;
257
+ case "delta":
258
+ return `delta:${config.goal.min}`;
259
+ case "code-quality":
260
+ return "code-quality (tests-green + quality verdict)";
261
+ case "nl":
262
+ // NATURAL-LANGUAGE goal (Wave-2 W2I10). A headless run can only reach here with a
263
+ // FROZEN NL goal — an unfrozen one is rejected by assertGoalLegal above (no human
264
+ // to confirm-freeze headless), so the driver refuses rather than run unbounded.
265
+ return config.goal.resolved
266
+ ? `nl→criterion:${config.goal.resolved.criterionIds.join(",")} ("${config.goal.text}")`
267
+ : `nl (UNRESOLVED: "${config.goal.text}")`;
268
+ default: {
269
+ const _never: never = config.goal;
270
+ throw new Error(`unknown goal ${JSON.stringify(_never)}`);
271
+ }
272
+ }
273
+ }
274
+
275
+ /** The living HTML report — per-iteration score trajectory + terminator + Δ. */
276
+ export function renderReportHtml(state: LoopState, config: LoopConfig, runId: string, at: string): string {
277
+ const rows = state.history
278
+ .map(
279
+ (r) =>
280
+ `<tr><td>${r.iteration}</td><td>${r.verify}</td><td>${r.gate}</td><td>${r.score.toFixed(3)}</td><td>${r.delta >= 0 ? "+" : ""}${r.delta.toFixed(3)}</td><td>${r.improved ? "✓" : "·"}</td></tr>`,
281
+ )
282
+ .join("\n");
283
+ const best = state.bestScore === Number.NEGATIVE_INFINITY ? "—" : state.bestScore.toFixed(3);
284
+ return `<!doctype html>
285
+ <meta charset="utf-8">
286
+ <title>optimize · ${runId}</title>
287
+ <style>
288
+ body{font-family:ui-monospace,Menlo,monospace;background:#0b0a12;color:#e9e6f4;margin:0;padding:24px}
289
+ h1{font-size:18px;color:#a78bfa} .meta{color:#918bab;font-size:12px}
290
+ table{border-collapse:collapse;margin-top:16px;font-size:13px}
291
+ th,td{border:1px solid #2b2640;padding:6px 12px;text-align:right}
292
+ th{background:#15121d;color:#a78bfa} .term{margin-top:14px;color:#4ade80}
293
+ </style>
294
+ <h1>mutagent-optimize · ⑤ IMPROVE loop</h1>
295
+ <div class="meta">run ${runId} · rendered ${at} · goal ${goalLabel(config)} · best ${best}</div>
296
+ <table>
297
+ <thead><tr><th>iter</th><th>verify</th><th>gate</th><th>score</th><th>Δ</th><th>improved</th></tr></thead>
298
+ <tbody>
299
+ ${rows}
300
+ </tbody>
301
+ </table>
302
+ <div class="term">TERMINATED: ${state.terminator ?? "—"} · ${state.iteration} iteration(s) · best ${best}</div>
303
+ `;
304
+ }
@@ -0,0 +1,300 @@
1
+ /**
2
+ * scripts/loop-state-cli.ts — the ONE-SHOT decision CLI for the improve loop.
3
+ * ---------------------------------------------------------------------------
4
+ * WHY: the interactive `*optimize` loop is conducted by the TOP-LEVEL SESSION
5
+ * (only the session can Task-dispatch sub-agents; a sub-agent cannot). The session
6
+ * is an AGENT, not a TS program — it cannot `import` the pure decision functions
7
+ * in `loop-state.ts`. This CLI EXPOSES those functions one-shot so the conducting
8
+ * session can call them BETWEEN Task dispatches (write loop-state.json → shell this
9
+ * CLI to decide terminator / next phase / improvement → act on the printed result).
10
+ *
11
+ * It is PURE: reads state/config from JSON files + flags, prints a machine-readable
12
+ * result, no clock / no network. `budget-ms` (elapsed wall time) is INJECTED by the
13
+ * conductor. Mirrors the diagnostics `orchestrator-protocol` inline model: the
14
+ * session conducts; deterministic decisions are shelled to a script.
15
+ *
16
+ * bun run scripts/loop-state-cli.ts <command> [args]
17
+ * init
18
+ * assert-goal-legal <config.json> [--subject-kind <code|agent|skill|platform>]
19
+ * parse-goal <raw> # "<free text>" | eval-pass | criterion:<id> | delta:<n> | code-quality → Goal JSON
20
+ * freeze-goal <config.json> --criterion <id> [--criterion <id> …] # freeze a natural-language goal → a criterion SET (repeat --criterion, or a comma list "a,b") → updated config JSON
21
+ * record-iteration <state.json> <config.json> --verify <PROCEED|STEER|ABORT> --gate <PASS|FAIL> --score <n> --variance-regressed <true|false> --budget-ms <n> [--tests-green <true|false>]
22
+ * check-terminators <state.json> <config.json> --last-verify <PROCEED|STEER|ABORT> [--criteria a,b]
23
+ * next-phase <phase> [--verify <..>] [--gate <..>]
24
+ * is-improvement --delta <n> --noise-floor <n> --variance-regressed <true|false>
25
+ * goal-met <config.json> <record.json> [--criteria a,b]
26
+ * accept-amend <input.json> --dialect <eval|diagnostics|amend> [--subject <s>] [--brief]
27
+ */
28
+
29
+ import { readFileSync } from "node:fs";
30
+
31
+ import {
32
+ assertGoalAllowedForSubject,
33
+ assertGoalLegal,
34
+ assertSubjectKind,
35
+ checkTerminators,
36
+ freezeNlGoal,
37
+ goalMet,
38
+ initLoopState,
39
+ isImprovement,
40
+ nextPhase,
41
+ parseGoal,
42
+ recordIteration,
43
+ } from "./loop-state.ts";
44
+ import type {
45
+ ArchitectVerdictValue,
46
+ GateVerdictValue,
47
+ IterationRecord,
48
+ LoopConfig,
49
+ LoopPhaseValue,
50
+ LoopState,
51
+ } from "./loop-state.ts";
52
+ import {
53
+ amendToBuildRemedy,
54
+ eddChangeRequestToAmend,
55
+ remedyToAmend,
56
+ validateAmendRequest,
57
+ } from "./contracts/amend-request.ts";
58
+ import type { AmendRequest, EddChangeRequestLike, RemedyLike } from "./contracts/amend-request.ts";
59
+
60
+ export interface CliResult {
61
+ out: string;
62
+ code: number;
63
+ }
64
+
65
+ interface ParsedArgs {
66
+ positionals: string[];
67
+ flags: Record<string, string>;
68
+ /**
69
+ * All occurrences of each flag, in order — so a REPEATED flag (e.g. `--criterion a
70
+ * --criterion b`) is not lost to last-wins. `flags` keeps its last-wins string for the
71
+ * single-value callers; `lists` is the additive multi-value view (used by freeze-goal).
72
+ */
73
+ lists: Record<string, string[]>;
74
+ }
75
+
76
+ function parseArgs(argv: string[]): ParsedArgs {
77
+ const positionals: string[] = [];
78
+ const flags: Record<string, string> = {};
79
+ const lists: Record<string, string[]> = {};
80
+ for (let i = 0; i < argv.length; i++) {
81
+ const a = argv[i]!;
82
+ if (a.startsWith("--")) {
83
+ const key = a.slice(2);
84
+ const next = argv[i + 1];
85
+ let value: string;
86
+ if (next === undefined || next.startsWith("--")) {
87
+ value = "true";
88
+ } else {
89
+ value = next;
90
+ i++;
91
+ }
92
+ flags[key] = value;
93
+ (lists[key] ??= []).push(value);
94
+ } else {
95
+ positionals.push(a);
96
+ }
97
+ }
98
+ return { positionals, flags, lists };
99
+ }
100
+
101
+ function readJson<T>(path: string): T {
102
+ return JSON.parse(readFileSync(path, "utf-8")) as T;
103
+ }
104
+
105
+ /**
106
+ * Revive a LoopState read from JSON. `bestScore`'s "no kept iteration yet" sentinel
107
+ * is `Number.NEGATIVE_INFINITY`, which `JSON.stringify` writes as `null`; restore it
108
+ * so recordIteration's first-turn detection holds across the JSON round-trip. Pure
109
+ * boundary fix — loop-state.ts is unchanged.
110
+ */
111
+ function readState(path: string): LoopState {
112
+ const raw = readJson<LoopState & { bestScore: number | null }>(path);
113
+ return { ...raw, bestScore: raw.bestScore === null ? Number.NEGATIVE_INFINITY : raw.bestScore };
114
+ }
115
+
116
+ function requireFlag(flags: Record<string, string>, key: string): string {
117
+ const v = flags[key];
118
+ if (v === undefined) throw new Error(`missing required flag --${key}`);
119
+ return v;
120
+ }
121
+
122
+ function requirePositional(pos: string[], i: number, name: string): string {
123
+ const v = pos[i];
124
+ if (v === undefined) throw new Error(`missing required argument <${name}>`);
125
+ return v;
126
+ }
127
+
128
+ function parseCriteria(flags: Record<string, string>): Set<string> {
129
+ const raw = flags["criteria"];
130
+ return new Set(raw ? raw.split(",").map((s) => s.trim()).filter(Boolean) : []);
131
+ }
132
+
133
+ const USAGE = [
134
+ "loop-state-cli — one-shot decisions for the improve loop (the conducting session shells this)",
135
+ "commands: init · assert-goal-legal · parse-goal · freeze-goal · record-iteration · check-terminators · next-phase · is-improvement · goal-met · accept-amend",
136
+ "see the file header for exact args.",
137
+ ].join("\n");
138
+
139
+ /**
140
+ * Run one CLI invocation. PURE w.r.t. the process: returns { out, code } instead
141
+ * of writing/exiting, so tests call it directly. The import.meta.main shell prints
142
+ * + exits with the result.
143
+ */
144
+ export function runLoopStateCli(argv: string[]): CliResult {
145
+ const [command, ...rest] = argv;
146
+ const { positionals, flags, lists } = parseArgs(rest);
147
+
148
+ try {
149
+ switch (command) {
150
+ case undefined:
151
+ case "--help":
152
+ case "-h":
153
+ case "help":
154
+ return { out: USAGE, code: command === undefined ? 1 : 0 };
155
+
156
+ case "init":
157
+ return { out: JSON.stringify(initLoopState()), code: 0 };
158
+
159
+ case "assert-goal-legal": {
160
+ const config = readJson<LoopConfig>(requirePositional(positionals, 0, "config.json"));
161
+ try {
162
+ assertGoalLegal(config);
163
+ // OPTIONAL subject-kind gate (Wave-2 W2I10): when the caller names the subject
164
+ // kind, additionally enforce that the goal is applicable to it (e.g. a
165
+ // `code-quality` goal is illegal on a non-code subject). Folds the subject-kind
166
+ // → goal disambiguation into the SAME entry gate the session already calls.
167
+ // VALIDATE the raw flag FIRST (Wave-2 follow-up): a bogus value used to cast
168
+ // through silently (`as SubjectKind`) and — unless the goal was code-quality —
169
+ // pass with exit 0. assertSubjectKind rejects an unrecognized value LOUD
170
+ // (fail-closed) so an invalid `--subject-kind` never slips past.
171
+ const subjectKind = flags["subject-kind"];
172
+ if (subjectKind !== undefined) {
173
+ assertSubjectKind(subjectKind);
174
+ assertGoalAllowedForSubject(config.goal, subjectKind);
175
+ }
176
+ return { out: "ok — goal-legal (observable goal + hard terminators + scope)", code: 0 };
177
+ } catch (e) {
178
+ return { out: `ILLEGAL: ${e instanceof Error ? e.message : String(e)}`, code: 1 };
179
+ }
180
+ }
181
+
182
+ case "parse-goal": {
183
+ // Parse the `--goal` arg into a Goal (Wave-2 W2I10). Free text → an UNRESOLVED
184
+ // natural-language goal (illegal until frozen); structured shapes → their kind.
185
+ const raw = requirePositional(positionals, 0, "raw-goal");
186
+ return { out: JSON.stringify(parseGoal(raw)), code: 0 };
187
+ }
188
+
189
+ case "freeze-goal": {
190
+ // Freeze a natural-language goal to a concrete criterion SET (Wave-2 W2I10; OT-4) —
191
+ // the session INTERPRETS + CONFIRMS the free text (agent reasoning at entry), then
192
+ // shells this pure transform to record the frozen decision on the config, making it
193
+ // goal-legal. A real NL goal usually decomposes into MULTIPLE binary criteria, so
194
+ // this accepts repeated `--criterion` flags AND a comma list ("a,b"); freezeNlGoal
195
+ // splits + trims. Prints the UPDATED config JSON (overwrite config.json with it).
196
+ const config = readJson<LoopConfig>(requirePositional(positionals, 0, "config.json"));
197
+ const criterionIds = lists["criterion"];
198
+ if (criterionIds === undefined) throw new Error("missing required flag --criterion");
199
+ const frozen = freezeNlGoal(config.goal, criterionIds);
200
+ return { out: JSON.stringify({ ...config, goal: frozen }), code: 0 };
201
+ }
202
+
203
+ case "record-iteration": {
204
+ const state = readState(requirePositional(positionals, 0, "state.json"));
205
+ const config = readJson<LoopConfig>(requirePositional(positionals, 1, "config.json"));
206
+ const next = recordIteration(state, config, {
207
+ verify: requireFlag(flags, "verify") as ArchitectVerdictValue,
208
+ gate: requireFlag(flags, "gate") as GateVerdictValue,
209
+ score: Number(requireFlag(flags, "score")),
210
+ varianceRegressed: requireFlag(flags, "variance-regressed") === "true",
211
+ budgetSpentMs: Number(requireFlag(flags, "budget-ms")),
212
+ // CODE-TARGET (Wave-2 W2I1) — OPTIONAL. Present only when the session
213
+ // conducts a `code` subject round: it records the deterministic
214
+ // test-suite gate so the `code-quality` goal's BOTH-gate can AND it with
215
+ // the quality verdict. Absent ⇒ undefined (non-code turn, unchanged).
216
+ ...(flags["tests-green"] === undefined
217
+ ? {}
218
+ : { testsGreen: flags["tests-green"] === "true" }),
219
+ });
220
+ return { out: JSON.stringify(next), code: 0 };
221
+ }
222
+
223
+ case "check-terminators": {
224
+ const state = readState(requirePositional(positionals, 0, "state.json"));
225
+ const config = readJson<LoopConfig>(requirePositional(positionals, 1, "config.json"));
226
+ const term = checkTerminators(
227
+ state,
228
+ config,
229
+ requireFlag(flags, "last-verify") as ArchitectVerdictValue,
230
+ parseCriteria(flags),
231
+ );
232
+ // A stop-reason exits NON-ZERO so a shell `if` can branch; "continue" is exit 0.
233
+ return term === null ? { out: "continue", code: 0 } : { out: term, code: 3 };
234
+ }
235
+
236
+ case "next-phase": {
237
+ const phase = requirePositional(positionals, 0, "phase") as LoopPhaseValue;
238
+ const next = nextPhase(
239
+ phase,
240
+ flags["verify"] as ArchitectVerdictValue | undefined,
241
+ flags["gate"] as GateVerdictValue | undefined,
242
+ );
243
+ return { out: next, code: 0 };
244
+ }
245
+
246
+ case "is-improvement": {
247
+ const ok = isImprovement(
248
+ Number(requireFlag(flags, "delta")),
249
+ Number(requireFlag(flags, "noise-floor")),
250
+ requireFlag(flags, "variance-regressed") === "true",
251
+ );
252
+ return { out: ok ? "true" : "false", code: ok ? 0 : 1 };
253
+ }
254
+
255
+ case "goal-met": {
256
+ const config = readJson<LoopConfig>(requirePositional(positionals, 0, "config.json"));
257
+ const rec = readJson<IterationRecord>(requirePositional(positionals, 1, "record.json"));
258
+ const ok = goalMet(config.goal, rec, parseCriteria(flags));
259
+ return { out: ok ? "true" : "false", code: ok ? 0 : 1 };
260
+ }
261
+
262
+ case "accept-amend": {
263
+ // Wave-2 W2I2 (unify amend formats): the CONSUMER accept-gate. Reads either amend
264
+ // dialect (or an already-unified amend) and normalizes to the ONE `AmendRequest`
265
+ // superset the ⑤ IMPROVE S1 build handover reads. --brief prints the collapsed NL
266
+ // build brief instead of the JSON (what the existing string seam consumes).
267
+ const inputPath = requirePositional(positionals, 0, "input.json");
268
+ const dialect = requireFlag(flags, "dialect");
269
+ let amend: AmendRequest;
270
+ if (dialect === "eval") {
271
+ amend = eddChangeRequestToAmend(readJson<EddChangeRequestLike>(inputPath));
272
+ } else if (dialect === "diagnostics") {
273
+ const subject = requireFlag(flags, "subject");
274
+ amend = remedyToAmend(readJson<RemedyLike>(inputPath), subject);
275
+ } else if (dialect === "amend") {
276
+ amend = validateAmendRequest(readJson<unknown>(inputPath));
277
+ } else {
278
+ return { out: `accept-amend: --dialect must be eval|diagnostics|amend (got "${dialect}")`, code: 2 };
279
+ }
280
+ // Belt-and-braces: the normalized amend must itself satisfy the accept-gate.
281
+ validateAmendRequest(amend);
282
+ if (flags["brief"] === "true") return { out: amendToBuildRemedy(amend), code: 0 };
283
+ return { out: JSON.stringify(amend), code: 0 };
284
+ }
285
+
286
+ default:
287
+ return { out: `unknown command '${command}'\n${USAGE}`, code: 2 };
288
+ }
289
+ } catch (e) {
290
+ return { out: `ERROR: ${e instanceof Error ? e.message : String(e)}`, code: 2 };
291
+ }
292
+ }
293
+
294
+ // ── CLI shell (the only impure edge) ──────────────────────────────────────────
295
+ if (import.meta.main) {
296
+ const result = runLoopStateCli(process.argv.slice(2));
297
+ if (result.code === 0 || result.code === 3) console.info(result.out);
298
+ else console.error(result.out);
299
+ process.exit(result.code);
300
+ }