@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,1013 @@
1
+ /**
2
+ * scripts/cli/init.ts
3
+ * CLI entrypoint: runtime detection + setup routing + cross-platform installer (Phase 3-E)
4
+ * Invoked as: pnpx @mutagent/diagnostics init
5
+ *
6
+ * W9-10: single --mode flag dispatches all internal functions (no new files).
7
+ *
8
+ * Modes (via --mode <value> or legacy flag aliases):
9
+ * --mode init (DEFAULT) — install skill+agents for detected platforms, then emit
10
+ * InitDescriptor JSON. pnpx invocation is this mode.
11
+ * --mode install — cross-platform installer only (OQ-8); alias: --install
12
+ * --mode reconfigure — re-run onboarding; alias: --reconfigure
13
+ *
14
+ * Other flags (work across modes):
15
+ * --yes Non-interactive: select all detected platforms
16
+ * --force Force-overwrite during install
17
+ * --ensure-cli <p> Probe source-platform CLI gate (PR-021); runs before mode dispatch
18
+ * --help Show usage
19
+ *
20
+ * Phase 3-E (OQ-8): cross-platform installer (--mode install)
21
+ * 1. Probe filesystem for platform markers: ~/.claude/ → Claude Code, ~/.codex/ → Codex,
22
+ * .cursor/ in cwd → Cursor. Detection uses home/env markers; the INSTALL TARGET is
23
+ * a separate concern (see install scope below).
24
+ * 2. Surface multi-select (chat-fallback per PR-010) with detected platforms pre-checked
25
+ * 3. Install to confirmed platforms: copy skill dir + install-agents.ts + doctor.ts verify
26
+ * 4. Exit 0 on full success, 1 on any platform failure (continue others)
27
+ *
28
+ * Install scope (W9-fix — operator directive: respect the project working directory):
29
+ * project (DEFAULT) — install into the directory the user ran `pnpx … init` in:
30
+ * Claude Code → <cwd>/.claude/skills|agents, Codex → <cwd>/.codex/skills|agents.
31
+ * global (--global) — install into the home dir (legacy behaviour):
32
+ * Claude Code → ~/.claude/…, Codex → ~/.codex/….
33
+ * Cursor is always cwd-relative (.cursor/ in the project).
34
+ * DETECTION (does the platform exist on this machine?) still consults the home/env
35
+ * markers — a platform stays installable into the project even when only the global
36
+ * marker exists (the user is clearly using Claude Code).
37
+ *
38
+ * W9-10 init mode (--mode init = default):
39
+ * Runs the cross-platform install (same as --mode install), then emits InitDescriptor
40
+ * JSON so callers know setup + agent state. This is what pnpx @mutagent/diagnostics init
41
+ * does — one command installs skill+agents AND returns setup state.
42
+ *
43
+ * Self-contained templates (npm public release):
44
+ * The shared install-time templates (self-diagnosis-contract, spec.yaml, team.yaml,
45
+ * iter-handover, wave-dashboard) are BUNDLED into the skill tree at
46
+ * assets/templates/shared/ — see scripts/cli/shared-templates.ts. There is NO
47
+ * peer-install of and NO dependency on `@mutagent/templates`. Because the bundled
48
+ * directory lives inside the skill tree, the cpSync skill-dir copy below carries it
49
+ * to every platform automatically, so `init` works OFFLINE from the package alone.
50
+ */
51
+
52
+ import {
53
+ existsSync, readdirSync, lstatSync, realpathSync,
54
+ mkdirSync, cpSync,
55
+ } from "fs";
56
+ import { join, resolve, basename } from "path";
57
+ import { homedir } from "os";
58
+ import { execSync } from "child_process";
59
+ import { detectSetup, detectSourceCli } from "../setup/detect.ts";
60
+ import type { SetupState } from "../setup/detect.ts";
61
+ import { runCliInstall } from "../setup/ensure-cli.ts";
62
+ import type { CliEnsurePlan, CliProbe } from "../setup/ensure-cli.ts";
63
+ import type { SourcePlatform } from "../normalize/trace.ts";
64
+ import { verifyAgents } from "../setup/verify-agents.ts";
65
+ import type { AgentBoundaryState } from "../setup/verify-agents.ts";
66
+ import { installAgents, transcodeAgentFile } from "./install-agents.ts";
67
+ import { SHARED_TEMPLATE_FILES } from "./shared-templates.ts";
68
+
69
+ // ── Existing types (backward compat) ──────────────────────────────────────────
70
+
71
+ export type Runtime = "claude-code" | "codex" | "cursor" | "opencode" | "generic";
72
+
73
+ export interface InitDescriptor {
74
+ runtime: Runtime;
75
+ projectRoot: string;
76
+ setupState: SetupState;
77
+ /**
78
+ * P2 pivot: "diagnostics" is retired. Use "protocol" for complete state.
79
+ * "protocol" = load references/workflows/orchestrator-protocol.md and follow inline.
80
+ * The parent session is the orchestrator — do NOT dispatch a coordinator sub-agent.
81
+ */
82
+ nextAction: "onboarding" | "protocol" | "reconfigure";
83
+ message: string;
84
+ /** F-SELF-01 / R-SELF-01-a — true if the host's .claude/agents/ is missing our agents */
85
+ agentsInstalled: boolean;
86
+ /** Hint command to install agents if agentsInstalled === false */
87
+ agentsInstallHint?: string;
88
+ /**
89
+ * R-SELF-01-d: Agent-spin verification boundary.
90
+ * "ready" = all 3 agents present + valid frontmatter + no restart required
91
+ * "pending-restart" = files installed but session not restarted yet
92
+ * "missing" = one or more agents not installed
93
+ * "invalid" = file present but frontmatter name wrong or unreadable
94
+ */
95
+ agentsBoundary: AgentBoundaryState;
96
+ }
97
+
98
+ // ── W9-10: mode type ──────────────────────────────────────────────────────────
99
+
100
+ /** Single dispatch flag — all internal functions route through this. */
101
+ export type InitMode = "init" | "install" | "reconfigure";
102
+
103
+ // ── W9-fix: install scope ─────────────────────────────────────────────────────
104
+
105
+ /**
106
+ * Install scope — WHERE skill+agent files land.
107
+ * "project" (DEFAULT) → the directory the user invoked from (process.cwd()).
108
+ * "global" → the home directory (~/.claude, ~/.codex). Opt-in via --global.
109
+ *
110
+ * Distinct from install-agents' InstallScope ("project" | "user"); we map
111
+ * global → install-agents "user" when handing off agent installation.
112
+ */
113
+ export type Scope = "project" | "global";
114
+
115
+ /**
116
+ * Resolve install scope from argv. DEFAULT is "project" — the bug this fixes was
117
+ * a hard-coded global target, so project-local must be the default. `--global`
118
+ * opts back into the home-dir install.
119
+ */
120
+ export function resolveScope(argv: string[]): Scope {
121
+ return argv.includes("--global") ? "global" : "project";
122
+ }
123
+
124
+ /** Flags that consume the FOLLOWING argv token as their value (so it isn't a positional). */
125
+ const VALUE_FLAGS = new Set(["--mode", "--ensure-cli"]);
126
+
127
+ /**
128
+ * Extract bare positional args, skipping flags AND the value token that immediately
129
+ * follows a value-flag. Without this, `init --mode install` mistook "install" (the
130
+ * --mode VALUE) for the projectRoot positional → project-local install targeted a
131
+ * relative "install" dir instead of the user's cwd (W9-fix: surfaced once cwd mattered).
132
+ */
133
+ export function parsePositionals(argv: string[]): string[] {
134
+ const positionals: string[] = [];
135
+ for (let i = 0; i < argv.length; i++) {
136
+ const tok = argv[i]!;
137
+ if (tok.startsWith("--")) {
138
+ if (VALUE_FLAGS.has(tok)) i++; // skip this flag's value token
139
+ continue;
140
+ }
141
+ positionals.push(tok);
142
+ }
143
+ return positionals;
144
+ }
145
+
146
+ /**
147
+ * Resolve --mode flag from argv. Legacy flags (--install, --reconfigure) map to
148
+ * their --mode equivalents for backward compatibility.
149
+ *
150
+ * Priority: explicit --mode <value> > legacy alias > default ("init").
151
+ */
152
+ export function resolveMode(argv: string[]): InitMode {
153
+ const modeIdx = argv.indexOf("--mode");
154
+ if (modeIdx !== -1) {
155
+ const val = argv[modeIdx + 1];
156
+ if (val === "init" || val === "install" || val === "reconfigure") {
157
+ return val;
158
+ }
159
+ process.stderr.write(
160
+ `[init] WARNING: unknown --mode value "${val ?? ""}"; falling back to "init".\n`
161
+ );
162
+ }
163
+ // Legacy aliases
164
+ if (argv.includes("--install")) return "install";
165
+ if (argv.includes("--reconfigure")) return "reconfigure";
166
+ return "init";
167
+ }
168
+
169
+ /**
170
+ * Detect the host coding-agent runtime from environment cues.
171
+ * Used to set ask_tool.runtime in config.yaml.
172
+ */
173
+ export function detectRuntime(): Runtime {
174
+ // Claude Code: CLAUDE_CODE env var or claude-code process parent
175
+ if (process.env.CLAUDE_CODE || process.env.ANTHROPIC_API_KEY) {
176
+ return "claude-code";
177
+ }
178
+
179
+ // Codex CLI: OPENAI_API_KEY + absence of Claude indicators + codex process
180
+ if (process.env.OPENAI_API_KEY && !process.env.ANTHROPIC_API_KEY) {
181
+ return "codex";
182
+ }
183
+
184
+ // Cursor: CURSOR_* env vars
185
+ if (process.env.CURSOR_WORKSPACE_ID || process.env.CURSOR_VERSION) {
186
+ return "cursor";
187
+ }
188
+
189
+ // OpenCode: OPENCODE_* env vars (TBD — placeholder)
190
+ if (process.env.OPENCODE_SESSION_ID) {
191
+ return "opencode";
192
+ }
193
+
194
+ return "generic";
195
+ }
196
+
197
+ /**
198
+ * Check whether our diagnostics-* agents are installed.
199
+ *
200
+ * W9-fix (scope-respecting, project-first): the bug this fixes was counting the
201
+ * GLOBAL ~/.claude/agents as satisfying a PROJECT install — so when the home dir
202
+ * already had our agents (e.g. dev symlinks), `pnpx … init` reported
203
+ * already-installed and SKIPPED the project install entirely.
204
+ * - scope "project" (DEFAULT) → check ONLY <projectRoot>/.claude/agents.
205
+ * - scope "global" → check ONLY ~/.claude/agents.
206
+ * A project install must never be considered satisfied by the home dir.
207
+ *
208
+ * Returns true if the diagnostics-owned leaf agent(s) are present (globbed from
209
+ * assets/agents/*.md). The apply-worker is RETIRED (M9) — apply delegates to the
210
+ * shared mutagent-cli apply + a spawned ai-engineer; diagnostics-orchestrator is an
211
+ * inline protocol now.
212
+ *
213
+ * @param projectRoot - The user's project root (install target in project scope).
214
+ * @param scope - "project" (DEFAULT) | "global".
215
+ */
216
+ export function checkAgentsInstalled(projectRoot: string, scope: Scope = "project"): boolean {
217
+ // Realpath-resolve through any symlink chain (sibling of F-SELF-05 cwd-leak family)
218
+ const scriptDir = realpathSync(import.meta.dirname ?? import.meta.url.replace(/^file:\/\//, "").replace(/\/[^/]+$/, ""));
219
+ const skillAgentsDir = resolve(scriptDir, "../..", "assets", "agents");
220
+ if (!existsSync(skillAgentsDir)) return false;
221
+ const expected = readdirSync(skillAgentsDir).filter((f) => f.endsWith(".md"));
222
+ if (expected.length === 0) return false;
223
+
224
+ // Project-first: ONLY the scoped dir counts. Home never satisfies a project install.
225
+ const scopedDir =
226
+ scope === "global"
227
+ ? join(homedir(), ".claude", "agents")
228
+ : join(projectRoot, ".claude", "agents");
229
+ for (const dir of [scopedDir]) {
230
+ if (!existsSync(dir)) continue;
231
+ const allPresent = expected.every((f) => {
232
+ const dest = join(dir, f);
233
+ if (!existsSync(dest)) return false;
234
+ const stat = lstatSync(dest);
235
+ if (!stat.isSymbolicLink()) return true; // assume operator chose copy install
236
+ // Compare CANONICAL paths — symlink literal target may differ representationally
237
+ try {
238
+ const canonical = realpathSync(dest);
239
+ const expectedCanonical = realpathSync(join(skillAgentsDir, f));
240
+ return canonical === expectedCanonical;
241
+ } catch {
242
+ return false; // dangling
243
+ }
244
+ });
245
+ if (allPresent) return true;
246
+ }
247
+ return false;
248
+ }
249
+
250
+ export function createInitDescriptor(
251
+ projectRoot: string,
252
+ reconfigure = false,
253
+ scope: Scope = "project"
254
+ ): InitDescriptor {
255
+ const runtime = detectRuntime();
256
+ const setup = detectSetup(projectRoot);
257
+ // W9-fix: project-first agent check — home dir never satisfies a project install.
258
+ const agentsInstalled = checkAgentsInstalled(projectRoot, scope);
259
+
260
+ // R-SELF-01-d: verify agent boundary state (frontmatter + presence + restart status)
261
+ // M9/M10: the apply-worker is retired; the diagnostics-owned agents are the analyzer (RCA)
262
+ // + the vendored ai-engineer (WRITE) + ai-architect (VERIFY) that drive the shared apply.
263
+ // Try project scope first, fall back to user scope
264
+ let verifyResult = verifyAgents(projectRoot, "project");
265
+ const projectAllMissing =
266
+ verifyResult.analyzer === "missing" &&
267
+ verifyResult.aiEngineer === "missing" &&
268
+ verifyResult.aiArchitect === "missing";
269
+ if (projectAllMissing) {
270
+ const userResult = verifyAgents(projectRoot, "user");
271
+ const userHasSome =
272
+ userResult.analyzer !== "missing" ||
273
+ userResult.aiEngineer !== "missing" ||
274
+ userResult.aiArchitect !== "missing";
275
+ if (userHasSome) {
276
+ verifyResult = userResult;
277
+ }
278
+ }
279
+
280
+ // Compute overall agentsBoundary: worst state wins across the leaf worker(s)
281
+ const allStates: AgentBoundaryState[] = [
282
+ verifyResult.analyzer,
283
+ verifyResult.aiEngineer,
284
+ verifyResult.aiArchitect,
285
+ ];
286
+ let agentsBoundary: AgentBoundaryState = "ready";
287
+ if (allStates.includes("missing")) agentsBoundary = "missing";
288
+ else if (allStates.includes("invalid")) agentsBoundary = "invalid";
289
+ else if (allStates.includes("pending-restart")) agentsBoundary = "pending-restart";
290
+
291
+ let nextAction: InitDescriptor["nextAction"];
292
+ let message: string;
293
+
294
+ if (reconfigure) {
295
+ nextAction = "reconfigure";
296
+ message = "Re-onboarding requested. Load references/workflows/onboarding.md to begin.";
297
+ } else if (setup.state === "complete") {
298
+ // P2 pivot: orchestrator is now inline. Load orchestrator-protocol.md — do NOT dispatch sub-agent.
299
+ nextAction = "protocol";
300
+ message = "Setup complete. Load references/workflows/orchestrator-protocol.md and follow inline. Do NOT dispatch a coordinator sub-agent.";
301
+ } else if (setup.state === "partial") {
302
+ nextAction = "onboarding";
303
+ message = `Partial config detected. Missing fields: ${setup.missingFields.join(", ")}. Load references/workflows/onboarding.md.`;
304
+ } else {
305
+ nextAction = "onboarding";
306
+ message = "No config found. Load references/workflows/onboarding.md to begin setup.";
307
+ }
308
+
309
+ // Surface agent install requirement (F-SELF-01 / R-SELF-01-a)
310
+ const descriptor: InitDescriptor = {
311
+ runtime,
312
+ projectRoot,
313
+ setupState: setup.state,
314
+ nextAction,
315
+ message,
316
+ agentsInstalled,
317
+ agentsBoundary,
318
+ };
319
+ if (!agentsInstalled) {
320
+ descriptor.agentsInstallHint =
321
+ `bun scripts/cli/run.sh scripts/cli/install-agents.ts "${projectRoot}" [--scope=project|user]`;
322
+ descriptor.message +=
323
+ `\n\ndiagnostics-* agents NOT installed in .claude/agents/ — analyzer dispatches will fall back to subagent_type=general-purpose. Run: ${descriptor.agentsInstallHint}` +
324
+ `\n(After install, restart your Claude Code session — the subagent_type registry caches at boot.)`;
325
+ }
326
+ if (agentsBoundary === "pending-restart") {
327
+ descriptor.message +=
328
+ `\n\nRESTART REQUIRED: diagnostics-* agents were installed but the session has not been restarted.` +
329
+ ` The subagent_type registry is loaded at boot. Restart now, then re-run init to confirm agentsBoundary=ready.`;
330
+ }
331
+ if (agentsBoundary === "invalid") {
332
+ descriptor.message +=
333
+ `\n\nAGENT VALIDATION FAILED: one or more installed agent files have invalid frontmatter.` +
334
+ ` Re-run install-agents.ts with --force to replace them.`;
335
+ }
336
+ return descriptor;
337
+ }
338
+
339
+ // ── Phase 3-E: Cross-platform filesystem detection (OQ-8) ────────────────────
340
+
341
+ export type PlatformId = "claude-code" | "codex" | "cursor";
342
+ export type BindingFormat = "md" | "toml" | "mdc";
343
+
344
+ export interface DetectedPlatform {
345
+ id: PlatformId;
346
+ label: string;
347
+ /** Human-readable description of what was probed. */
348
+ detectionMarker: string;
349
+ /** Whether the platform's marker was found on this machine. */
350
+ detected: boolean;
351
+ /** Where the skill directory should be installed. */
352
+ skillInstallPath: string;
353
+ /** Where agent files should be installed, or null if not applicable. */
354
+ agentsInstallPath: string | null;
355
+ /** File format for agent/skill bindings on this platform. */
356
+ bindingFormat: BindingFormat;
357
+ }
358
+
359
+ /**
360
+ * Probe the filesystem for installed coding-agent platforms.
361
+ * Detection order per OQ-8: Claude Code → Codex → Cursor.
362
+ * Uses os.homedir() — never literal ~/. (homedir-cross-platform gotcha §8)
363
+ *
364
+ * DETECTION vs INSTALL TARGET (W9-fix): `detected`/`detectionMarker` always probe the
365
+ * home/env marker (does the platform exist on this machine?). The INSTALL TARGET
366
+ * (`skillInstallPath` / `agentsInstallPath`) follows `scope`:
367
+ * "project" (DEFAULT) → <cwd>/.claude|.codex/… "global" → <home>/.claude|.codex/…
368
+ * A platform stays installable into the project even when only the global marker
369
+ * exists — the user is clearly using that runtime.
370
+ *
371
+ * @param cwd - The directory the user invoked from (process.cwd()). Install target
372
+ * root in project scope; also the CWD-relative probe root for Cursor.
373
+ * @param scope - "project" (DEFAULT, cwd-relative) | "global" (home-relative). The bug
374
+ * this signature fixes was a hard-coded global target.
375
+ */
376
+ export function detectInstalledPlatforms(
377
+ cwd: string = process.cwd(),
378
+ scope: Scope = "project"
379
+ ): DetectedPlatform[] {
380
+ const home = homedir();
381
+ // Install-target roots follow scope; detection markers always use home.
382
+ const claudeRoot = scope === "global" ? join(home, ".claude") : join(cwd, ".claude");
383
+ const codexRoot = scope === "global" ? join(home, ".codex") : join(cwd, ".codex");
384
+ return [
385
+ {
386
+ id: "claude-code",
387
+ label: "Claude Code",
388
+ detectionMarker: join(home, ".claude"),
389
+ detected: existsSync(join(home, ".claude")),
390
+ skillInstallPath: join(claudeRoot, "skills", "mutagent-diagnostics"),
391
+ agentsInstallPath: join(claudeRoot, "agents"),
392
+ bindingFormat: "md",
393
+ },
394
+ {
395
+ id: "codex",
396
+ label: "Codex",
397
+ detectionMarker: join(home, ".codex"),
398
+ detected: existsSync(join(home, ".codex")),
399
+ skillInstallPath: join(codexRoot, "skills", "mutagent-diagnostics"),
400
+ agentsInstallPath: join(codexRoot, "agents"),
401
+ bindingFormat: "toml",
402
+ },
403
+ {
404
+ id: "cursor",
405
+ label: "Cursor",
406
+ detectionMarker: join(cwd, ".cursor"),
407
+ detected: existsSync(join(cwd, ".cursor")),
408
+ skillInstallPath: join(cwd, ".cursor", "rules"),
409
+ agentsInstallPath: null, // no agent primitive yet
410
+ bindingFormat: "mdc",
411
+ },
412
+ ];
413
+ }
414
+
415
+ // ── Platform install implementation ───────────────────────────────────────────
416
+
417
+ export interface PlatformInstallResult {
418
+ platform: PlatformId;
419
+ success: boolean;
420
+ steps: Array<{ step: string; ok: boolean; note?: string }>;
421
+ errors: string[];
422
+ }
423
+
424
+ /**
425
+ * Install mutagent-diagnostics to a single detected platform.
426
+ * Performs: copy skill dir → install agents (with optional TOML transcode) → doctor verify.
427
+ *
428
+ * @param platform - The platform to install to (its install paths already follow scope).
429
+ * @param skillSourceDir - The source skill directory (defaults to SKILL_DIR from script location).
430
+ * @param force - Overwrite existing files.
431
+ * @param scope - Install scope ("project" DEFAULT | "global"). Drives the install-agents
432
+ * handoff: project → install-agents "project" scope rooted at `cwd`;
433
+ * global → install-agents "user" scope (~/.claude/agents).
434
+ * @param cwd - The project root the user invoked from (process.cwd()). Used as the
435
+ * install-agents projectRoot in project scope. NOT the skill/script dir
436
+ * (F-SELF-05 cwd-leak family — the source dir is resolved separately).
437
+ */
438
+ export function installToPlatform(
439
+ platform: DetectedPlatform,
440
+ skillSourceDir: string,
441
+ force = false,
442
+ scope: Scope = "project",
443
+ cwd: string = process.cwd()
444
+ ): PlatformInstallResult {
445
+ const result: PlatformInstallResult = {
446
+ platform: platform.id,
447
+ success: false,
448
+ steps: [],
449
+ errors: [],
450
+ };
451
+
452
+ // ── Step 1: Copy skill directory ──────────────────────────────────────────
453
+ const skillDest = platform.skillInstallPath;
454
+ try {
455
+ if (existsSync(skillDest) && !force) {
456
+ result.steps.push({
457
+ step: "copy-skill",
458
+ ok: true,
459
+ note: `Skill already exists at ${skillDest} (use --force to overwrite)`,
460
+ });
461
+ } else {
462
+ mkdirSync(skillDest, { recursive: true });
463
+ cpSync(skillSourceDir, skillDest, { recursive: true, force: true });
464
+ result.steps.push({ step: "copy-skill", ok: true, note: `Copied to ${skillDest}` });
465
+ }
466
+ } catch (err) {
467
+ const msg = `Failed to copy skill to ${skillDest}: ${err instanceof Error ? err.message : String(err)}`;
468
+ result.steps.push({ step: "copy-skill", ok: false, note: msg });
469
+ result.errors.push(msg);
470
+ return result;
471
+ }
472
+
473
+ // ── Step 1b: Verify bundled shared templates landed (offline self-contained) ──
474
+ // The shared install-time templates are bundled at assets/templates/shared/ and
475
+ // carried by the cpSync above (they live inside the skill tree — no peer-install,
476
+ // no @mutagent/templates dependency). Confirm they materialised at the dest so a
477
+ // partial/interrupted copy surfaces here rather than at first runtime use.
478
+ const sharedDest = join(skillDest, "assets", "templates", "shared");
479
+ const missingShared = SHARED_TEMPLATE_FILES.filter(
480
+ (f) => !existsSync(join(sharedDest, f))
481
+ );
482
+ result.steps.push({
483
+ step: "verify-shared-templates",
484
+ ok: missingShared.length === 0,
485
+ note:
486
+ missingShared.length === 0
487
+ ? `${SHARED_TEMPLATE_FILES.length} bundled shared template(s) present at ${sharedDest}`
488
+ : `MISSING bundled shared template(s): ${missingShared.join(", ")}`,
489
+ });
490
+ if (missingShared.length > 0) {
491
+ result.errors.push(
492
+ `bundled shared templates missing after copy: ${missingShared.join(", ")}`
493
+ );
494
+ }
495
+
496
+ // ── Step 2: Install agents ─────────────────────────────────────────────────
497
+ const agentsDir = platform.agentsInstallPath;
498
+ if (agentsDir !== null) {
499
+ const agentsSrcDir = join(skillSourceDir, "assets", "agents");
500
+ if (existsSync(agentsSrcDir)) {
501
+ const agentFiles = readdirSync(agentsSrcDir).filter((f) => f.endsWith(".md"));
502
+ try {
503
+ mkdirSync(agentsDir, { recursive: true });
504
+ if (platform.id === "codex") {
505
+ // MD→TOML transcode for Codex
506
+ for (const fname of agentFiles) {
507
+ const src = join(agentsSrcDir, fname);
508
+ const destName = basename(fname, ".md") + ".toml";
509
+ const dest = join(agentsDir, destName);
510
+ transcodeAgentFile(src, dest, "codex");
511
+ }
512
+ result.steps.push({
513
+ step: "install-agents",
514
+ ok: true,
515
+ note: `Transcoded ${agentFiles.length} agent(s) to TOML in ${agentsDir}`,
516
+ });
517
+ } else {
518
+ // Claude Code: symlink via existing installAgents.
519
+ // W9-fix: scope-respecting target. project → install into <cwd>/.claude/agents
520
+ // (install-agents "project" scope, rooted at the user's invocation dir);
521
+ // global → ~/.claude/agents (install-agents "user" scope). Previously this
522
+ // hard-coded "user", so a project install leaked agents into the home dir.
523
+ const agentsScope = scope === "global" ? "user" : "project";
524
+ const installResult = installAgents(cwd, agentsScope, force);
525
+ const hadErrors = installResult.errors.length > 0;
526
+ result.steps.push({
527
+ step: "install-agents",
528
+ ok: !hadErrors,
529
+ note: hadErrors
530
+ ? `Errors: ${installResult.errors.join("; ")}`
531
+ : `${installResult.entries.filter((e) => e.action !== "skipped").length} agent(s) installed`,
532
+ });
533
+ if (hadErrors) {
534
+ result.errors.push(...installResult.errors);
535
+ }
536
+ }
537
+ } catch (err) {
538
+ const msg = `Failed to install agents to ${agentsDir}: ${err instanceof Error ? err.message : String(err)}`;
539
+ result.steps.push({ step: "install-agents", ok: false, note: msg });
540
+ result.errors.push(msg);
541
+ }
542
+ } else {
543
+ result.steps.push({ step: "install-agents", ok: true, note: "No assets/agents/ dir — skipped" });
544
+ }
545
+ } else {
546
+ result.steps.push({
547
+ step: "install-agents",
548
+ ok: true,
549
+ note: `${platform.label} has no agent primitive — agents skipped`,
550
+ });
551
+ }
552
+
553
+ // ── Step 3: Post-install doctor verify ────────────────────────────────────
554
+ const scriptDir = realpathSync(import.meta.dirname ?? import.meta.url.replace(/^file:\/\//, "").replace(/\/[^/]+$/, ""));
555
+ const doctorScript = join(scriptDir, "doctor.ts");
556
+ const runSh = join(scriptDir, "run.sh");
557
+ try {
558
+ if (existsSync(doctorScript) && existsSync(runSh)) {
559
+ const raw = execSync(`bash "${runSh}" "${doctorScript}"`, {
560
+ encoding: "utf8",
561
+ timeout: 15000,
562
+ });
563
+ const report = JSON.parse(raw) as { runtime: string };
564
+ result.steps.push({
565
+ step: "doctor-verify",
566
+ ok: true,
567
+ note: `Runtime: ${report.runtime}`,
568
+ });
569
+ } else {
570
+ result.steps.push({
571
+ step: "doctor-verify",
572
+ ok: true,
573
+ note: "doctor.ts not found — skipped",
574
+ });
575
+ }
576
+ } catch (err) {
577
+ const msg = `Doctor verify failed: ${err instanceof Error ? err.message : String(err)}`;
578
+ result.steps.push({ step: "doctor-verify", ok: false, note: msg });
579
+ // Doctor failure is non-fatal — log but don't block
580
+ process.stderr.write(`[init] ⚠ ${msg}\n`);
581
+ }
582
+
583
+ result.success = result.errors.length === 0;
584
+ return result;
585
+ }
586
+
587
+ // ── W9-10: internal mode implementations ─────────────────────────────────────
588
+
589
+ /**
590
+ * mode=install — cross-platform installer (Phase 3-E).
591
+ * Detects platforms, prompts for selection (or auto-selects with --yes), installs.
592
+ * Returns exit code: 0 = all ok, 1 = any platform failure.
593
+ */
594
+ export async function runModeInstall(
595
+ skillDir: string,
596
+ autoYes: boolean,
597
+ force: boolean,
598
+ scope: Scope = "project",
599
+ cwd: string = process.cwd()
600
+ ): Promise<number> {
601
+ const platforms = detectInstalledPlatforms(cwd, scope);
602
+ const selectedIds = await promptPlatformSelection(platforms, autoYes);
603
+
604
+ if (selectedIds.length === 0) {
605
+ process.stderr.write("[init] No platforms selected — nothing to install.\n");
606
+ return 0;
607
+ }
608
+
609
+ process.stdout.write(
610
+ `[init] Install scope: ${scope}${scope === "project" ? ` (${cwd})` : " (home dir)"}\n`
611
+ );
612
+
613
+ let anyFailure = false;
614
+ for (const id of selectedIds) {
615
+ const platform = platforms.find((p) => p.id === id)!;
616
+ process.stdout.write(`\n[init] Installing to ${platform.label}...\n`);
617
+ const result = installToPlatform(platform, skillDir, force, scope, cwd);
618
+ for (const step of result.steps) {
619
+ const icon = step.ok ? " ok" : " FAIL";
620
+ process.stdout.write(`${icon} ${step.step}: ${step.note ?? ""}\n`);
621
+ }
622
+ if (result.success) {
623
+ process.stdout.write(`[init] ${platform.label}: install complete.\n`);
624
+ if (platform.id === "claude-code") {
625
+ process.stdout.write(
626
+ " Restart your Claude Code session — the subagent_type registry caches at boot.\n"
627
+ );
628
+ }
629
+ } else {
630
+ process.stderr.write(`[init] ${platform.label}: FAILED — ${result.errors.join("; ")}\n`);
631
+ anyFailure = true;
632
+ }
633
+ }
634
+
635
+ return anyFailure ? 1 : 0;
636
+ }
637
+
638
+ /**
639
+ * mode=init (W9-10 default) — install skill+agents, then emit InitDescriptor JSON.
640
+ * This is the pnpx @mutagent/diagnostics init path: one command installs AND
641
+ * returns setup state so the agent knows whether to run onboarding or diagnostics.
642
+ */
643
+ export async function runModeInit(
644
+ skillDir: string,
645
+ projectRoot: string,
646
+ autoYes: boolean,
647
+ force: boolean,
648
+ scope: Scope = "project"
649
+ ): Promise<number> {
650
+ // Install to all detected platforms (non-interactive if --yes).
651
+ // projectRoot IS the user's invocation cwd — pass it as the install cwd so
652
+ // project-scope installs land in the project, not the skill/script dir.
653
+ await runModeInstall(skillDir, autoYes, force, scope, projectRoot);
654
+ // Always emit InitDescriptor — install failures are non-fatal for setup routing
655
+ const descriptor = createInitDescriptor(projectRoot, false, scope);
656
+ process.stdout.write(JSON.stringify(descriptor, null, 2) + "\n");
657
+ return 0;
658
+ }
659
+
660
+ /**
661
+ * mode=reconfigure — back up config and signal agent to re-run onboarding.
662
+ * The heavy lifting (asking questions, writing config) is handled by the agent
663
+ * reading SKILL.md + references/workflows/onboarding.md inline. This mode emits
664
+ * a thin route-signal so callers know a reconfigure pass is required.
665
+ */
666
+ export function runModeReconfigure(projectRoot: string): number {
667
+ // Thin route-signal: delegate to createInitDescriptor with reconfigure=true
668
+ const descriptor = createInitDescriptor(projectRoot, true);
669
+ process.stdout.write(JSON.stringify(descriptor, null, 2) + "\n");
670
+ return 0;
671
+ }
672
+
673
+ // ── Chat-fallback multi-select (PR-010) ───────────────────────────────────────
674
+
675
+ /**
676
+ * Chat-fallback multi-select: print detected platforms and ask user to confirm.
677
+ * When AskUserQuestion is available (Claude Code native), callers should use that instead.
678
+ * This function is the text-based fallback for direct CLI invocation.
679
+ *
680
+ * @param platforms - All probed platforms (detected and undetected).
681
+ * @param autoYes - If true, skip prompt and select all detected platforms.
682
+ * @returns Array of confirmed platform IDs.
683
+ */
684
+ export async function promptPlatformSelection(
685
+ platforms: DetectedPlatform[],
686
+ autoYes: boolean
687
+ ): Promise<PlatformId[]> {
688
+ const detected = platforms.filter((p) => p.detected);
689
+ const undetected = platforms.filter((p) => !p.detected);
690
+
691
+ process.stdout.write("\n mutagent-diagnostics — Cross-Platform Install\n");
692
+ process.stdout.write(" ──────────────────────────────────────────────\n");
693
+ process.stdout.write(" Detected platforms:\n");
694
+
695
+ if (detected.length === 0) {
696
+ process.stdout.write(" (none — no platform markers found)\n");
697
+ process.stdout.write(
698
+ "\n No platforms detected. Install at least one of:\n" +
699
+ " Claude Code: https://claude.ai/claude-code\n" +
700
+ " Codex CLI: npm install -g @openai/codex\n" +
701
+ " Cursor: https://cursor.com\n"
702
+ );
703
+ return [];
704
+ }
705
+
706
+ detected.forEach((p, i) => {
707
+ process.stdout.write(` [${i + 1}] ${p.label} (${p.detectionMarker}) detected\n`);
708
+ });
709
+
710
+ if (undetected.length > 0) {
711
+ process.stdout.write(" Not detected:\n");
712
+ undetected.forEach((p) => {
713
+ process.stdout.write(` ${p.label} (${p.detectionMarker})\n`);
714
+ });
715
+ }
716
+
717
+ if (autoYes) {
718
+ process.stdout.write(`\n --yes: installing all ${detected.length} detected platform(s).\n`);
719
+ return detected.map((p) => p.id);
720
+ }
721
+
722
+ process.stdout.write(
723
+ `\n Install to which platforms? [all/${detected.map((_, i) => i + 1).join(",")}] (default: all): `
724
+ );
725
+
726
+ // Read a single line from stdin
727
+ const line = await new Promise<string>((resolve) => {
728
+ let buf = "";
729
+ process.stdin.setEncoding("utf8");
730
+ process.stdin.once("data", (chunk: unknown) => {
731
+ buf += String(chunk);
732
+ resolve(buf.trim());
733
+ });
734
+ process.stdin.resume();
735
+ });
736
+
737
+ if (!line || line.toLowerCase() === "all" || line === "") {
738
+ return detected.map((p) => p.id);
739
+ }
740
+
741
+ // Parse comma-separated numbers like "1,2" or "1"
742
+ const indices = line
743
+ .split(",")
744
+ .map((s) => parseInt(s.trim(), 10) - 1)
745
+ .filter((i) => i >= 0 && i < detected.length);
746
+
747
+ if (indices.length === 0) {
748
+ process.stdout.write(" No valid selection — defaulting to all detected.\n");
749
+ return detected.map((p) => p.id);
750
+ }
751
+
752
+ return indices.map((i) => detected[i]!.id);
753
+ }
754
+
755
+ // ── Source-platform CLI ensure (approve-to-install gate, PR-021) ──────────────
756
+
757
+ /**
758
+ * Outcome of the ensure-source-cli flow. Records WHAT happened to the CLI so the
759
+ * caller can persist "CLI absent — REST fallback in use" into the config/notes.
760
+ */
761
+ export type EnsureCliOutcome =
762
+ | "not-required" // platform needs no CLI
763
+ | "already-present" // CLI was already on PATH
764
+ | "installed" // user APPROVED → install ran and succeeded
765
+ | "install-failed" // user approved but the install command failed
766
+ | "declined" // user DECLINED → continue with REST/file fallback
767
+ | "no-installer"; // CLI missing, nothing installable → REST/file fallback
768
+
769
+ export interface EnsureCliResult {
770
+ platform: SourcePlatform;
771
+ plan: CliEnsurePlan;
772
+ outcome: EnsureCliOutcome;
773
+ /** True only when the CLI is usable afterward (present or freshly installed). */
774
+ cliAvailable: boolean;
775
+ /** Human-readable line for the onboarding transcript + config notes. */
776
+ note: string;
777
+ }
778
+
779
+ /**
780
+ * Approval callback. Returns true to APPROVE the install, false to DECLINE.
781
+ *
782
+ * Platform-portable by design: callers inject the right asker —
783
+ * - Claude Code: an adapter backed by the AskUserQuestion tool, OR
784
+ * - chat-based runtimes (Codex/Cursor/OpenCode/generic): the chat y/N fallback
785
+ * `promptInstallApprovalChat` below.
786
+ * The ensure-cli orchestration NEVER asks on its own — it always calls this callback,
787
+ * which makes the no-silent-install rule structurally enforced and unit-testable.
788
+ */
789
+ // eslint-disable-next-line no-unused-vars
790
+ export type ApproveInstallFn = (plan: CliEnsurePlan) => Promise<boolean>;
791
+
792
+ /**
793
+ * Chat-based y/N approval fallback (PR-010 portable-ask). Prints the docs link +
794
+ * the install command, then reads a single y/N line from stdin. DEFAULT IS NO —
795
+ * an empty line / EOF / anything not starting with "y" DECLINES. This guarantees
796
+ * that a non-interactive or accidental Enter NEVER triggers an install.
797
+ *
798
+ * Claude Code callers should NOT use this — they pass an AskUserQuestion-backed
799
+ * approver instead (see onboarding.md Phase 2).
800
+ */
801
+ export async function promptInstallApprovalChat(plan: CliEnsurePlan): Promise<boolean> {
802
+ process.stdout.write(
803
+ `\n ${plan.spec.label} is not installed.\n` +
804
+ ` Official docs: ${plan.docsUrl}\n` +
805
+ ` Suggested install: ${plan.installCommand}\n` +
806
+ `\n Install it now? This will run the command above on your machine. [y/N]: `
807
+ );
808
+ const line = await new Promise<string>((resolve) => {
809
+ process.stdin.setEncoding("utf8");
810
+ process.stdin.once("data", (chunk: unknown) => {
811
+ resolve(String(chunk).trim());
812
+ });
813
+ process.stdin.resume();
814
+ });
815
+ // DEFAULT NO: only an explicit yes approves.
816
+ return line.toLowerCase().startsWith("y");
817
+ }
818
+
819
+ /**
820
+ * Ensure the chosen source platform's CLI is available for onboarding.
821
+ *
822
+ * Flow (operator directive — NO silent/automatic install on ANY path):
823
+ * 1. plan = detectSourceCli(platform) — pure probe, never installs.
824
+ * 2. not-required / present → return immediately (cliAvailable reflects reality).
825
+ * 3. missing-no-installer → surface docs + REST/file fallback; do NOT ask, do NOT install.
826
+ * 4. missing-installable → print docs + install command, then ASK via `approve`.
827
+ * - approve() === true → run the documented install (runCliInstall).
828
+ * - approve() === false → DECLINE: continue with REST/file fallback; record CLI absent.
829
+ *
830
+ * There is exactly ONE code path that installs (step 4 after approve() returns true).
831
+ * `runCliInstall` is never reached otherwise.
832
+ *
833
+ * @param platform - The chosen source platform.
834
+ * @param approve - Approval callback (AskUserQuestion adapter or chat y/N fallback).
835
+ * @param probe - Injectable PATH probe (for deterministic tests).
836
+ */
837
+ export async function ensureSourceCli(
838
+ platform: SourcePlatform,
839
+ approve: ApproveInstallFn,
840
+ probe?: CliProbe
841
+ ): Promise<EnsureCliResult> {
842
+ const plan = detectSourceCli(platform, probe);
843
+
844
+ if (plan.status === "not-required") {
845
+ return {
846
+ platform, plan, outcome: "not-required", cliAvailable: false,
847
+ note: `${plan.spec.label}: no CLI required. Docs: ${plan.docsUrl}`,
848
+ };
849
+ }
850
+
851
+ if (plan.status === "present") {
852
+ return {
853
+ platform, plan, outcome: "already-present", cliAvailable: true,
854
+ note: `${plan.spec.label} already installed. Docs: ${plan.docsUrl}`,
855
+ };
856
+ }
857
+
858
+ if (plan.status === "missing-no-installer") {
859
+ return {
860
+ platform, plan, outcome: "no-installer", cliAvailable: false,
861
+ note:
862
+ `${plan.spec.label} not installed and not auto-installable. ` +
863
+ `Continuing with fallback. Docs: ${plan.docsUrl}. ${plan.spec.fallbackNote}`,
864
+ };
865
+ }
866
+
867
+ // status === "missing-installable" → MUST ask before installing.
868
+ const approved = await approve(plan);
869
+ if (!approved) {
870
+ return {
871
+ platform, plan, outcome: "declined", cliAvailable: false,
872
+ note:
873
+ `${plan.spec.label} install DECLINED by user. Continuing with REST/file fallback. ` +
874
+ `Docs: ${plan.docsUrl}. ${plan.spec.fallbackNote}`,
875
+ };
876
+ }
877
+
878
+ // Approved → run the documented install. This is the ONLY install path.
879
+ const installResult = runCliInstall(plan);
880
+ if (installResult.ok) {
881
+ return {
882
+ platform, plan, outcome: "installed", cliAvailable: true,
883
+ note: `${plan.spec.label} installed (user-approved): \`${installResult.command}\`.`,
884
+ };
885
+ }
886
+ return {
887
+ platform, plan, outcome: "install-failed", cliAvailable: false,
888
+ note:
889
+ `${plan.spec.label} install was approved but FAILED: ${installResult.error ?? "unknown error"}. ` +
890
+ `Falling back to REST/file. Docs: ${plan.docsUrl}. ${plan.spec.fallbackNote}`,
891
+ };
892
+ }
893
+
894
+ // ── Usage text ────────────────────────────────────────────────────────────────
895
+
896
+ const USAGE = `
897
+ mutagent-diagnostics init — cross-platform skill installer + setup routing
898
+
899
+ USAGE
900
+ pnpx @mutagent/diagnostics init [--mode <mode>] [options]
901
+
902
+ MODES (--mode flag, W9-10)
903
+ --mode init DEFAULT — install skill+agents to detected platforms, then emit
904
+ InitDescriptor JSON with setup state (onboarding/protocol/reconfigure)
905
+ --mode install Cross-platform installer only (no descriptor output)
906
+ --mode reconfigure Emit reconfigure-signal descriptor; agent re-runs onboarding inline
907
+
908
+ Legacy aliases (backward compat):
909
+ --install → same as --mode install
910
+ --reconfigure → same as --mode reconfigure
911
+
912
+ INSTALL SCOPE (install/init modes)
913
+ (default) PROJECT-LOCAL — install into the directory you ran init in:
914
+ Claude Code → <cwd>/.claude/… Codex → <cwd>/.codex/…
915
+ --global HOME DIR — install into ~/.claude/… and ~/.codex/… (legacy behaviour)
916
+ (Cursor is always project-local: .cursor/ in the current directory.)
917
+
918
+ OPTIONS
919
+ --global Install into the home dir instead of the project (default: project-local)
920
+ --yes Non-interactive: select all detected platforms (install/init modes)
921
+ --force Force-overwrite existing skill/agent files during install
922
+ --ensure-cli <p> Probe source-platform CLI gate; never auto-installs (PR-021)
923
+ --help Show this message
924
+
925
+ PLATFORM DETECTION (install/init modes)
926
+ Detection probes home/env markers (does the runtime exist?); the INSTALL TARGET
927
+ follows the scope above — a platform stays installable into your project even
928
+ when only the global marker exists.
929
+ Claude Code detected if ~/.claude/ exists
930
+ Codex detected if ~/.codex/ exists
931
+ Cursor detected if .cursor/ exists in current directory (project-scoped)
932
+
933
+ EXAMPLES
934
+ pnpx @mutagent/diagnostics init # project-local install + descriptor (default)
935
+ pnpx @mutagent/diagnostics init --global # install into the home dir instead
936
+ pnpx @mutagent/diagnostics init --yes # install all detected, non-interactive
937
+ pnpx @mutagent/diagnostics init --mode install # installer only
938
+ pnpx @mutagent/diagnostics init --mode reconfigure # signal reconfigure
939
+ pnpx @mutagent/diagnostics init --install --yes # legacy alias for --mode install --yes
940
+
941
+ DOCS
942
+ references/source-platforms/install-paths.md — install paths per platform
943
+ references/source-platforms/codex.md — Codex TOML format
944
+ references/target-platforms/local-cursor.md — Cursor binding status (apply target)
945
+ `.trim();
946
+
947
+ // ── CLI entrypoint ────────────────────────────────────────────────────────────
948
+
949
+ if (import.meta.main) {
950
+ const argv = process.argv.slice(2);
951
+
952
+ // --help
953
+ if (argv.includes("--help") || argv.includes("-h")) {
954
+ process.stdout.write(USAGE + "\n");
955
+ process.exit(0);
956
+ }
957
+
958
+ // --ensure-cli <platform>: probe source-platform CLI + approve-to-install gate (PR-021)
959
+ // Handled before mode dispatch — it's a utility, not a mode.
960
+ const ensureIdx = argv.indexOf("--ensure-cli");
961
+ if (ensureIdx !== -1) {
962
+ const platform = argv[ensureIdx + 1] as SourcePlatform | undefined;
963
+ if (!platform) {
964
+ process.stderr.write(
965
+ "[init] ERROR: --ensure-cli requires a source platform argument.\n" +
966
+ " usage: init --ensure-cli <langfuse|otel|local-jsonl|claude-code|codex>\n"
967
+ );
968
+ process.exit(2);
969
+ }
970
+ // Chat-based approval fallback (this is a direct CLI invocation, not Claude Code).
971
+ // Claude Code callers drive ensureSourceCli() directly with an AskUserQuestion adapter.
972
+ const result = await ensureSourceCli(platform, promptInstallApprovalChat);
973
+ process.stdout.write(`\n[init] ${result.note}\n`);
974
+ process.stdout.write(JSON.stringify({
975
+ platform: result.platform,
976
+ outcome: result.outcome,
977
+ cliAvailable: result.cliAvailable,
978
+ status: result.plan.status,
979
+ docsUrl: result.plan.docsUrl,
980
+ }, null, 2) + "\n");
981
+ // Exit 0 for every NON-error outcome (declined is a valid user choice → REST fallback).
982
+ process.exit(result.outcome === "install-failed" ? 1 : 0);
983
+ }
984
+
985
+ // Resolve mode (W9-10 single dispatch flag) + install scope (W9-fix)
986
+ const mode = resolveMode(argv);
987
+ const scope = resolveScope(argv);
988
+ const autoYes = argv.includes("--yes");
989
+ const force = argv.includes("--force");
990
+
991
+ // The skill SOURCE dir is resolved from import.meta (stays correct through symlink
992
+ // chains). The install TARGET root is the user's invocation cwd — NEVER the script
993
+ // dir (F-SELF-05 cwd-leak family). projectRoot = explicit positional arg, else cwd.
994
+ const scriptDir = realpathSync(import.meta.dirname ?? import.meta.url.replace(/^file:\/\//, "").replace(/\/[^/]+$/, ""));
995
+ const skillDir = resolve(scriptDir, "../..");
996
+ // parsePositionals skips value-flag tokens (--mode <v>, --ensure-cli <v>) so the
997
+ // --mode VALUE is never mistaken for projectRoot. Falls back to the invocation cwd.
998
+ const projectRoot = parsePositionals(argv)[0] ?? process.cwd();
999
+
1000
+ if (mode === "install") {
1001
+ const code = await runModeInstall(skillDir, autoYes, force, scope, projectRoot);
1002
+ process.exit(code);
1003
+ }
1004
+
1005
+ if (mode === "reconfigure") {
1006
+ const code = runModeReconfigure(projectRoot);
1007
+ process.exit(code);
1008
+ }
1009
+
1010
+ // mode === "init" (default) — W9-10: install + emit descriptor
1011
+ const code = await runModeInit(skillDir, projectRoot, autoYes, force, scope);
1012
+ process.exit(code);
1013
+ }