@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,188 @@
1
+ /**
2
+ * scripts/validate/render-js-syntax.ts
3
+ * W12-02 (P7 / propose PR-050): Inline-JS syntax gate for RENDERED HTML.
4
+ *
5
+ * Data-shape gates (completeness-check, findings-contract) cannot catch
6
+ * interactivity-breaking JavaScript — a single asymmetric-escape in a template
7
+ * literal (W12-01: `/\r?\\n/` emitting a literal-CR regex) produces a
8
+ * SyntaxError that silently kills the whole live-preview IIFE, so check/uncheck
9
+ * + Copy go dead while every data gate still passes.
10
+ *
11
+ * This gate extracts every executable `<script>` body from a rendered HTML file
12
+ * and parses each with `new Function(body)` — which throws on SyntaxError
13
+ * WITHOUT executing the body (no DOM, no side effects). Non-executable scripts
14
+ * (external `src=`, `application/ld+json`, `text/plain` payloads) are skipped.
15
+ *
16
+ * Export: `checkRenderJsSyntax(html): RenderJsSyntaxResult` (pure function).
17
+ * CLI: `if (import.meta.main)` — exit 0 on all-parse, exit 1 + offending
18
+ * script index/snippet on any parse error.
19
+ *
20
+ * Type A — Pure Script (deterministic; CLI file read only).
21
+ */
22
+
23
+ // ── Result shapes ─────────────────────────────────────────────────────────────
24
+
25
+ /** One inline-JS parse error, keyed to the script's position in the document. */
26
+ export interface RenderJsSyntaxError {
27
+ /** 0-based index of the executable script among all parsed scripts. */
28
+ scriptIndex: number;
29
+ /** The SyntaxError message from `new Function`. */
30
+ message: string;
31
+ /** A short snippet of the offending body (first ~200 chars, single-lined). */
32
+ snippet: string;
33
+ }
34
+
35
+ /** Outcome of the inline-JS syntax gate. */
36
+ export interface RenderJsSyntaxResult {
37
+ /** True when every executable `<script>` body parses. */
38
+ pass: boolean;
39
+ /** Count of executable `<script>` bodies that were parsed. */
40
+ scriptsChecked: number;
41
+ /** Parse errors (empty when pass). */
42
+ errors: RenderJsSyntaxError[];
43
+ }
44
+
45
+ // ── Script extraction ─────────────────────────────────────────────────────────
46
+
47
+ /**
48
+ * `type` attribute values that mark a `<script>` as NON-executable data, not JS.
49
+ * These bodies are intentionally not valid JS (JSON-LD, plain-text payloads) and
50
+ * must NOT be parsed by this gate.
51
+ */
52
+ const NON_JS_SCRIPT_TYPES: ReadonlySet<string> = new Set([
53
+ "application/ld+json",
54
+ "application/json",
55
+ "text/plain",
56
+ "text/template",
57
+ "text/html",
58
+ ]);
59
+
60
+ /** Matches a whole `<script ...>...</script>` element (greedy-safe, non-nested). */
61
+ const SCRIPT_ELEMENT_RE = /<script\b([^>]*)>([\s\S]*?)<\/script>/gi;
62
+ /** Extracts a `src="..."` / `src='...'` attribute value. */
63
+ const SRC_ATTR_RE = /\bsrc\s*=\s*["']([^"']*)["']/i;
64
+ /** Extracts a `type="..."` / `type='...'` attribute value. */
65
+ const TYPE_ATTR_RE = /\btype\s*=\s*["']([^"']*)["']/i;
66
+
67
+ /**
68
+ * Extract every EXECUTABLE inline-script body from a rendered HTML string.
69
+ *
70
+ * Skips:
71
+ * - external scripts (`<script src=...>`) — no inline body to parse
72
+ * - data scripts (`type` in NON_JS_SCRIPT_TYPES) — intentionally non-JS
73
+ * - empty / whitespace-only bodies
74
+ *
75
+ * Returns the bodies in document order.
76
+ */
77
+ export function extractInlineScriptBodies(html: string): string[] {
78
+ const bodies: string[] = [];
79
+ SCRIPT_ELEMENT_RE.lastIndex = 0;
80
+ let match: RegExpExecArray | null;
81
+ while ((match = SCRIPT_ELEMENT_RE.exec(html)) !== null) {
82
+ const attrs = match[1] ?? "";
83
+ const body = match[2] ?? "";
84
+
85
+ // External script — no inline body to parse.
86
+ if (SRC_ATTR_RE.test(attrs)) continue;
87
+
88
+ // Non-executable data script (JSON-LD, text/plain payload, etc.).
89
+ const typeMatch = TYPE_ATTR_RE.exec(attrs);
90
+ if (typeMatch) {
91
+ const declaredType = typeMatch[1].trim().toLowerCase();
92
+ // Anything that isn't an explicit JS module/classic type is treated as
93
+ // data when it appears in the NON_JS set; module/text-javascript fall
94
+ // through to be parsed.
95
+ if (NON_JS_SCRIPT_TYPES.has(declaredType)) continue;
96
+ }
97
+
98
+ if (body.trim().length === 0) continue;
99
+
100
+ bodies.push(body);
101
+ }
102
+ return bodies;
103
+ }
104
+
105
+ // ── Gate ──────────────────────────────────────────────────────────────────────
106
+
107
+ /** Single-line, length-bounded snippet for error reporting. */
108
+ function snippetOf(body: string): string {
109
+ const flat = body.replace(/\s+/g, " ").trim();
110
+ return flat.length > 200 ? `${flat.slice(0, 200)}…` : flat;
111
+ }
112
+
113
+ /**
114
+ * W12-02: Parse every executable inline-script body in a rendered HTML document.
115
+ * Pure function — same input, same output. Uses `new Function(body)` which
116
+ * throws on SyntaxError WITHOUT executing the body.
117
+ */
118
+ export function checkRenderJsSyntax(html: string): RenderJsSyntaxResult {
119
+ const bodies = extractInlineScriptBodies(html);
120
+ const errors: RenderJsSyntaxError[] = [];
121
+
122
+ bodies.forEach((body, scriptIndex) => {
123
+ try {
124
+ // `new Function(body)` parses the body and throws on SyntaxError WITHOUT
125
+ // executing it (no call site) — exactly the parse-only check we want.
126
+ new Function(body);
127
+ } catch (err) {
128
+ errors.push({
129
+ scriptIndex,
130
+ message: err instanceof Error ? err.message : String(err),
131
+ snippet: snippetOf(body),
132
+ });
133
+ }
134
+ });
135
+
136
+ return {
137
+ pass: errors.length === 0,
138
+ scriptsChecked: bodies.length,
139
+ errors,
140
+ };
141
+ }
142
+
143
+ // ── CLI entrypoint ─────────────────────────────────────────────────────────────
144
+
145
+ if (import.meta.main) {
146
+ const { readFileSync } = await import("fs");
147
+ const { resolve } = await import("path");
148
+
149
+ const argv = process.argv.slice(2);
150
+ const htmlPath = argv[0];
151
+
152
+ if (!htmlPath) {
153
+ process.stderr.write(
154
+ "Usage: bun scripts/validate/render-js-syntax.ts <rendered-report.html>\n" +
155
+ "\n" +
156
+ "Parses every executable inline <script> body in a rendered HTML report\n" +
157
+ "(via new Function — no execution). Exit 0 = all parse, Exit 1 = SyntaxError.\n"
158
+ );
159
+ process.exit(1);
160
+ }
161
+
162
+ let html: string;
163
+ try {
164
+ html = readFileSync(resolve(htmlPath), "utf8");
165
+ } catch (err) {
166
+ process.stderr.write(`Error reading ${htmlPath}: ${err}\n`);
167
+ process.exit(1);
168
+ }
169
+
170
+ const result = checkRenderJsSyntax(html);
171
+
172
+ if (result.pass) {
173
+ process.stdout.write(
174
+ `[render-js-syntax] PASS — ${result.scriptsChecked} inline script(s) parse cleanly.\n`
175
+ );
176
+ process.exit(0);
177
+ } else {
178
+ process.stderr.write(
179
+ `[render-js-syntax] FAIL — ${result.errors.length} inline script(s) failed to parse ` +
180
+ `(of ${result.scriptsChecked} checked):\n`
181
+ );
182
+ result.errors.forEach((e) => {
183
+ process.stderr.write(` script #${e.scriptIndex}: ${e.message}\n`);
184
+ process.stderr.write(` ${e.snippet}\n`);
185
+ });
186
+ process.exit(1);
187
+ }
188
+ }
@@ -0,0 +1,217 @@
1
+ # scripts/validate/report-checklist.yaml
2
+ # W14 (F1) — OUTPUT-side finalization checklist.
3
+ #
4
+ # WHAT THIS IS
5
+ # A declarative, one-row-per-section completeness contract for the *rendered*
6
+ # `report.html` string. The INPUT side is already gated by
7
+ # `scripts/validate/completeness-check.ts` (RenderInput JSON, the D-6 render-contract
8
+ # pass). THIS file drives the OUTPUT side: `scripts/validate/finalize-gate.ts` parses
9
+ # the produced HTML and asserts, per section, that the data actually LANDED in the
10
+ # document — catching the bug class where the renderer emitted a soft fallback
11
+ # (`RANK n/a`, `cost:n/a`), a raw `undefined`/`NaN`, a raw-JSON entity prompt, or an
12
+ # internal node that survived the client strip.
13
+ #
14
+ # WHY DETERMINISTIC-ONLY
15
+ # No LLM, no spend, runs every render. DOM/regex/string assertions only (operator
16
+ # decision 2). Each row is a pure predicate over the HTML body.
17
+ #
18
+ # SELF-HEAL (operator decision 3)
19
+ # Each row carries `source` (the producer to backtrace to — from
20
+ # references/script-index.md, the backtrace table) and `heal` (the re-run action).
21
+ # On a CRIT gap the orchestrator (Step 9.9) backtraces via `source`, re-runs that
22
+ # producer, re-builds render-input, re-renders, and re-checks. Bounded: max 2 rounds,
23
+ # then escalate LOUD. NEVER infinite-loop, NEVER silently emit an incomplete report.
24
+ #
25
+ # SCHEMA (per row)
26
+ # section : stable id (one of the section ids below)
27
+ # require : tokens/markers that MUST be present AND non-empty in the section's HTML
28
+ # forbid : tokens that MUST NOT appear (e.g. 'undefined', 'NaN', 'RANK n/a')
29
+ # tier : CRIT (blocks "done") | WARN (loud banner, still emit)
30
+ # okEmpty : a condition string naming WHEN absence is LEGITIMATE (prevents false-block)
31
+ # source : the producer/step to backtrace to (matches script-index.md `Step` column)
32
+ # heal : the self-heal action to run when this row's data is missing
33
+ #
34
+ # SCOPING NOTE (forbid tokens)
35
+ # `forbid` scanning runs over the rendered body with <code>, <pre>, and diff blocks
36
+ # (.r-diff-grid) STRIPPED first — those legitimately contain literal `undefined` /
37
+ # `NaN` / `{"prompt"` as quoted evidence/diff content. The finalize-gate strips them
38
+ # before applying body-level forbids; section-scoped forbids run on the section slice
39
+ # with the same strip.
40
+
41
+ # ─────────────────────────────────────────────────────────────────────────────
42
+ # GLOBAL CRIT ROWS — whole-body invariants (operator decision F1: "Global CRIT rows")
43
+ # ─────────────────────────────────────────────────────────────────────────────
44
+
45
+ # SD-8: `null` is scoped to STRUCTURAL slots only. The finalize-gate forbid scan is a
46
+ # literal substring match (`surface.includes(token)`), so a bare `null` token CRIT-fails
47
+ # on prose like "the tool returned null" — observability-hygiene language, not a render
48
+ # bug. `undefined`/`NaN` keep their bare form (they never appear in legitimate prose).
49
+ # For `null` we instead enumerate the token flanked by each structural delimiter
50
+ # (`>` `<` `:` `,` `=` `"`) on either side, so a structural-slot leak (text node
51
+ # `>null<`, JSON `:null,`, attribute `="null"`) still fires while a prose mention does
52
+ # not. Inline JS / <pre> / <code> are already stripped before the scan (stripQuotedRegions).
53
+ - section: global-no-undefined
54
+ require: []
55
+ forbid:
56
+ - "undefined"
57
+ - "NaN"
58
+ # `null` in a structural slot — flanked by a structural delimiter on either side.
59
+ - ">null"
60
+ - "null<"
61
+ - ":null"
62
+ - "null:"
63
+ - ",null"
64
+ - "null,"
65
+ - "=null"
66
+ - "null="
67
+ - '"null'
68
+ - 'null"'
69
+ - "<null"
70
+ - "null>"
71
+ tier: CRIT
72
+ okEmpty: never
73
+ source: "8.5 build-render-input.ts (enricher backfills the field a producer forgot)"
74
+ heal: "re-run Step 8.5 enrich → re-render → re-check (the literal is a forgotten field; the enricher is the backfill point)"
75
+
76
+ - section: global-client-no-internal
77
+ require: []
78
+ # When audience=client, the renderer must emit ZERO internal nodes (it builds them
79
+ # as "" — NODE-STRIP by omission). Any surviving internal marker is a leak.
80
+ forbid: ['class="internal"', 'class="internal-banner"', 'class="internal active"', "Methodology [INTERNAL]", "INTERNAL-ONLY"]
81
+ tier: CRIT
82
+ okEmpty: "audience=internal (internal reports legitimately carry these nodes)"
83
+ source: "9 render.ts (audience gate — methodologyPanelHtml/internalBannerHtml must be '' for client)"
84
+ heal: "re-render with the resolved audience (Step 9 --audience); a client leak means audience was mis-resolved — re-run resolveEffectiveAudience and re-render"
85
+
86
+ - section: global-remedy-triad
87
+ require: []
88
+ # Every remedy header badge triad must be real, not the badgeField() 'n/a' fallback.
89
+ forbid: ["RANK n/a", "cost:n/a", "correct:n/a", "cost:undefined", "RANK undefined", "b-cost-na"]
90
+ tier: CRIT
91
+ okEmpty: "no findings (clean run — no remedy cards exist)"
92
+ source: "8.5 rank-remedies.ts (enricher derives rank from cost×correctness; cost/correctness are analyzer-supplied, gated at Step 7.1)"
93
+ heal: "re-run Step 7.1 findings-contract → Step 8.5 rank-remedies → re-render (missing rank/cost/correctness on a remedy)"
94
+
95
+ # ─────────────────────────────────────────────────────────────────────────────
96
+ # PER-SECTION ROWS
97
+ # ─────────────────────────────────────────────────────────────────────────────
98
+
99
+ - section: entity-card
100
+ require: ['class="entity"', "DIAGNOSED ENTITY", "Type"]
101
+ # Entity prompt must be humanized prose, never a raw analyzer JSON blob.
102
+ forbid: ['{"prompt"', '{"messages"', '"role":"system"']
103
+ tier: CRIT
104
+ # The entity card lives in the Overview tab, only built on findings-bearing runs
105
+ # (mirrors completeness-check.ts: zero-finding runs are exempt from section checks).
106
+ okEmpty: "no findings (entity card only built on findings-bearing runs)"
107
+ source: "3.7 normalize/platforms/*.ts → EntityContext (deterministic extraction, no LLM)"
108
+ heal: "re-run Step 3.7 normalize (--out-entity) → Step 8.5a build EntityContext → re-render (entity card starved or prompt not humanized)"
109
+
110
+ - section: big-stat
111
+ require: ['class="big-stat"', 'class="s"']
112
+ forbid: ["undefined", "NaN"]
113
+ tier: CRIT
114
+ okEmpty: "no findings (Overview big-stat row only built on findings-bearing runs)"
115
+ source: "8.5 build-render-input.ts (derives the 6-tile bigStat from tier0 + deepRead)"
116
+ heal: "re-run Step 8.5 enrich (bigStat derivation) → re-render"
117
+
118
+ - section: deep-read-tile
119
+ require: ['class="deep-read-tile"', "coverage confidence"]
120
+ forbid: ["undefined", "NaN"]
121
+ tier: WARN
122
+ okEmpty: "runMeta.deepRead absent (pre-Wave-9 / backward-compat run — tile omitted)"
123
+ source: "6 deep-read-gate.ts → runMeta.deepRead (escalation telemetry)"
124
+ heal: "re-run Step 6 deep-read-gate → assign runMeta.deepRead → re-render"
125
+
126
+ - section: signal-census
127
+ require: ["Signal / failure-mode", "Present?", "Measure", "Decision"]
128
+ forbid: ["undefined", "NaN"]
129
+ tier: CRIT
130
+ okEmpty: "no findings (census table only built on findings-bearing runs)"
131
+ source: "8.5 build-render-input.ts (signal-census reconciliation from tier0 + primarySignal)"
132
+ heal: "re-run Step 8.5 enrich (signal census) → re-render"
133
+
134
+ - section: heatmap
135
+ require: ['class="heat"', "timeline heatmap"]
136
+ forbid: ["undefined", "NaN"]
137
+ tier: WARN
138
+ okEmpty: "no findings OR methodologyAudit (no runtime traces → no latency heatmap)"
139
+ source: "8.5 build-render-input.ts (24h heatmap from trace timestamps)"
140
+ heal: "re-run Step 8.5 enrich (heatmap derivation) → re-render"
141
+
142
+ - section: funnel
143
+ require: ['class="funnel"']
144
+ forbid: ["undefined", "NaN"]
145
+ tier: WARN
146
+ okEmpty: "scanFunnel absent (backward-compat — funnel falls back to 3-segment or omits)"
147
+ source: "5 slicer.ts / representative.ts → scanFunnel (total→tier0→sample→deep-read)"
148
+ heal: "re-run Step 5 sampling → assign scanFunnel → re-render"
149
+
150
+ - section: finding-panel
151
+ # Finding panels carry the WHAT/WHY/WHERE taxonomy strip + a Problem block.
152
+ require: ['class="taxonomy"', "WHAT", "Problem"]
153
+ forbid: ["undefined", "NaN"]
154
+ tier: CRIT
155
+ okEmpty: "0 findings on a clean run (legitimate zero-finding diagnosis — no panels expected)"
156
+ source: "6 analyzer dispatch → 7 aggregate/sort-findings.ts → Finding[]"
157
+ heal: "re-run Step 6 analyzer dispatch → Step 7 aggregate → Step 8.5 enrich → re-render (findings lost between aggregate and render)"
158
+
159
+ - section: remedy-card
160
+ # NB: `class="remedy` (no closing quote) matches both `class="remedy"` and the
161
+ # recommended-variant `class="remedy recommended"`.
162
+ require: ['class="remedy', "rank-pill", "remedy-meta"]
163
+ forbid: ["RANK n/a", "cost:n/a", "correct:n/a", "RANK undefined"]
164
+ tier: CRIT
165
+ okEmpty: "no findings (no remedy cards on a clean run)"
166
+ source: "8.5 rank-remedies.ts (rank derived) + Step 7.1 findings-contract (cost/correctness present)"
167
+ heal: "re-run Step 7.1 findings-contract → Step 8.5 rank-remedies → re-render"
168
+
169
+ # ── Methodology sub-sections (INTERNAL audience only) ────────────────────────
170
+ # These rows are scoped to the Methodology [INTERNAL] tab. They are evaluated ONLY
171
+ # when audience=internal (okEmpty covers the client case — the whole tab is stripped).
172
+ # The renderer emits a LOUD `loud-missing-widget` marker when a widget's data was not
173
+ # threaded into runMeta; that marker is itself a CRIT forbid (a forgotten-data tell).
174
+
175
+ - section: methodology-tier-pie
176
+ require: []
177
+ forbid: ['data-widget="tier-coverage pie (tierBreakdown)"']
178
+ tier: CRIT
179
+ okEmpty: "audience=client (Methodology tab stripped) OR runMeta.tierBreakdown threaded (widget rendered, no loud marker)"
180
+ source: "8.5 build-render-input.ts F4 widget-threading → runMeta.tierBreakdown"
181
+ heal: "thread runMeta.tierBreakdown at Step 8.5 (F4 table) → re-render"
182
+
183
+ - section: methodology-selection
184
+ require: []
185
+ forbid: ['data-widget="signal-selection trace (signalSelectionTrace)"']
186
+ tier: CRIT
187
+ okEmpty: "audience=client OR runMeta.signalSelectionTrace threaded"
188
+ source: "8.5 build-render-input.ts F4 widget-threading → runMeta.signalSelectionTrace / selectionRules"
189
+ heal: "thread runMeta.signalSelectionTrace + selectionRules at Step 8.5 (F4 table) → re-render"
190
+
191
+ - section: methodology-awareness
192
+ require: []
193
+ forbid: ['data-widget="awareness sample + blind-spots"']
194
+ tier: CRIT
195
+ okEmpty: "audience=client OR awareness threaded OR awareness SKIPPED under documented exemption (library priors)"
196
+ source: "3.5 awareness/llm-sample.ts + blind-spots.ts → runMeta.awarenessSample / blindSpots"
197
+ heal: "re-run Step 3.5 awareness → assign runMeta.awarenessSample + blindSpots at Step 8.5 → re-render"
198
+
199
+ - section: methodology-blind-spots
200
+ require: []
201
+ # blind-spots share the awareness widget marker; kept as a distinct row so a gap
202
+ # backtraces to the blind-spots producer specifically.
203
+ forbid: ['data-widget="awareness sample + blind-spots"']
204
+ tier: WARN
205
+ okEmpty: "audience=client OR blindSpots threaded OR awareness SKIPPED (priors)"
206
+ source: "3.5 awareness/blind-spots.ts → runMeta.blindSpots"
207
+ heal: "re-run Step 3.5 blind-spots → assign runMeta.blindSpots at Step 8.5 → re-render"
208
+
209
+ # ── Decisions / copy-back tab (always emitted) ───────────────────────────────
210
+
211
+ - section: decisions-copyback
212
+ require: ["Decisions", 'id="lp-body"', 'id="general-feedback"']
213
+ forbid: ["undefined", "NaN"]
214
+ tier: CRIT
215
+ okEmpty: never
216
+ source: "9 render.ts renderDecisionsTab + renderLivePreviewScript (copy-back HITL surface — PR-014)"
217
+ heal: "re-render (the Decisions tab is template-stamped; absence means a render/template regression — re-run Step 9 render)"
@@ -0,0 +1,262 @@
1
+ /**
2
+ * scripts/validate/trace-shape.ts
3
+ * F-SELF-08: Validate that raw trace data conforms to TraceMetadata shape before
4
+ * feeding into tier0-scan or per-platform normalizers.
5
+ *
6
+ * This is NOT a normalizer — it validates that objects already normalized by a
7
+ * per-platform module (or manually constructed) meet the structural contract
8
+ * required by the rest of the diagnostics pipeline.
9
+ *
10
+ * Usage: bun scripts/cli/run.sh scripts/validate/trace-shape.ts <traces.json>
11
+ *
12
+ * Exit 0 = all traces valid.
13
+ * Exit 1 = one or more traces have structural violations (details on stderr).
14
+ *
15
+ * Type A — Pure Script (deterministic, no I/O except argument file)
16
+ */
17
+
18
+ import { readFileSync } from "fs";
19
+ import type { TraceMetadata } from "../normalize/trace.ts";
20
+
21
+ export interface TraceShapeViolation {
22
+ traceIndex: number;
23
+ traceId?: string;
24
+ field: string;
25
+ message: string;
26
+ }
27
+
28
+ export interface TraceShapeResult {
29
+ valid: boolean;
30
+ totalTraces: number;
31
+ invalidCount: number;
32
+ violations: TraceShapeViolation[];
33
+ }
34
+
35
+ /**
36
+ * Validate a single trace object against the TraceMetadata structural contract.
37
+ * Returns a list of violations (empty = valid).
38
+ */
39
+ export function validateTraceShape(
40
+ raw: unknown,
41
+ index: number
42
+ ): TraceShapeViolation[] {
43
+ const violations: TraceShapeViolation[] = [];
44
+
45
+ // Must be a non-null object
46
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
47
+ violations.push({
48
+ traceIndex: index,
49
+ field: "(root)",
50
+ message: `Expected object, got ${Array.isArray(raw) ? "array" : typeof raw}`,
51
+ });
52
+ return violations; // No point checking fields on non-objects
53
+ }
54
+
55
+ const t = raw as Record<string, unknown>;
56
+
57
+ // ── Required fields ────────────────────────────────────────────────────────
58
+
59
+ if (typeof t.traceId !== "string" || t.traceId.trim() === "") {
60
+ violations.push({
61
+ traceIndex: index,
62
+ traceId: typeof t.traceId === "string" ? t.traceId : undefined,
63
+ field: "traceId",
64
+ message: "Required string field is missing or empty",
65
+ });
66
+ }
67
+
68
+ if (typeof t.sessionId !== "string" || t.sessionId.trim() === "") {
69
+ violations.push({
70
+ traceIndex: index,
71
+ traceId: typeof t.traceId === "string" ? t.traceId : undefined,
72
+ field: "sessionId",
73
+ message: "Required string field is missing or empty",
74
+ });
75
+ }
76
+
77
+ if (typeof t.hasError !== "boolean") {
78
+ violations.push({
79
+ traceIndex: index,
80
+ traceId: typeof t.traceId === "string" ? t.traceId : undefined,
81
+ field: "hasError",
82
+ message: `Required boolean field is ${t.hasError === undefined ? "missing" : `type "${typeof t.hasError}"`}`,
83
+ });
84
+ }
85
+
86
+ if (typeof t.hasFeedback !== "boolean") {
87
+ violations.push({
88
+ traceIndex: index,
89
+ traceId: typeof t.traceId === "string" ? t.traceId : undefined,
90
+ field: "hasFeedback",
91
+ message: `Required boolean field is ${t.hasFeedback === undefined ? "missing" : `type "${typeof t.hasFeedback}"`}`,
92
+ });
93
+ }
94
+
95
+ const validPlatforms = new Set(["langfuse", "otel", "local-jsonl", "claude-code", "codex"]);
96
+ if (typeof t.sourcePlatform !== "string" || !validPlatforms.has(t.sourcePlatform)) {
97
+ violations.push({
98
+ traceIndex: index,
99
+ traceId: typeof t.traceId === "string" ? t.traceId : undefined,
100
+ field: "sourcePlatform",
101
+ message: `Expected one of ${[...validPlatforms].join(", ")}, got ${JSON.stringify(t.sourcePlatform)}`,
102
+ });
103
+ }
104
+
105
+ // ── Optional fields — type-check only if present ───────────────────────────
106
+
107
+ if (t.latencyMs !== undefined && typeof t.latencyMs !== "number") {
108
+ violations.push({
109
+ traceIndex: index,
110
+ traceId: typeof t.traceId === "string" ? t.traceId : undefined,
111
+ field: "latencyMs",
112
+ message: `Optional field present but wrong type: expected number, got "${typeof t.latencyMs}"`,
113
+ });
114
+ }
115
+
116
+ if (t.rawScore !== undefined && typeof t.rawScore !== "number") {
117
+ violations.push({
118
+ traceIndex: index,
119
+ traceId: typeof t.traceId === "string" ? t.traceId : undefined,
120
+ field: "rawScore",
121
+ message: `Optional field present but wrong type: expected number, got "${typeof t.rawScore}"`,
122
+ });
123
+ }
124
+
125
+ if (t.normalizedScore !== undefined) {
126
+ if (typeof t.normalizedScore !== "number") {
127
+ violations.push({
128
+ traceIndex: index,
129
+ traceId: typeof t.traceId === "string" ? t.traceId : undefined,
130
+ field: "normalizedScore",
131
+ message: `Optional field present but wrong type: expected number, got "${typeof t.normalizedScore}"`,
132
+ });
133
+ } else if (t.normalizedScore < 0 || t.normalizedScore > 1) {
134
+ violations.push({
135
+ traceIndex: index,
136
+ traceId: typeof t.traceId === "string" ? t.traceId : undefined,
137
+ field: "normalizedScore",
138
+ message: `normalizedScore must be in [0, 1], got ${t.normalizedScore}`,
139
+ });
140
+ }
141
+ }
142
+
143
+ if (t.tags !== undefined) {
144
+ if (!Array.isArray(t.tags)) {
145
+ violations.push({
146
+ traceIndex: index,
147
+ traceId: typeof t.traceId === "string" ? t.traceId : undefined,
148
+ field: "tags",
149
+ message: `Optional field present but wrong type: expected string[], got "${typeof t.tags}"`,
150
+ });
151
+ } else if (t.tags.some((tag: unknown) => typeof tag !== "string")) {
152
+ violations.push({
153
+ traceIndex: index,
154
+ traceId: typeof t.traceId === "string" ? t.traceId : undefined,
155
+ field: "tags",
156
+ message: "tags array contains non-string elements",
157
+ });
158
+ }
159
+ }
160
+
161
+ // R-SELF-06-a: validate apiErrors shape if present
162
+ if (t.apiErrors !== undefined) {
163
+ if (!Array.isArray(t.apiErrors)) {
164
+ violations.push({
165
+ traceIndex: index,
166
+ traceId: typeof t.traceId === "string" ? t.traceId : undefined,
167
+ field: "apiErrors",
168
+ message: `Expected array, got "${typeof t.apiErrors}"`,
169
+ });
170
+ } else {
171
+ for (let i = 0; i < t.apiErrors.length; i++) {
172
+ const e = t.apiErrors[i] as Record<string, unknown>;
173
+ if (typeof e.retryAttempt !== "number") {
174
+ violations.push({
175
+ traceIndex: index,
176
+ traceId: typeof t.traceId === "string" ? t.traceId : undefined,
177
+ field: `apiErrors[${i}].retryAttempt`,
178
+ message: `Expected number, got "${typeof e.retryAttempt}"`,
179
+ });
180
+ }
181
+ if (typeof e.maxRetries !== "number") {
182
+ violations.push({
183
+ traceIndex: index,
184
+ traceId: typeof t.traceId === "string" ? t.traceId : undefined,
185
+ field: `apiErrors[${i}].maxRetries`,
186
+ message: `Expected number, got "${typeof e.maxRetries}"`,
187
+ });
188
+ }
189
+ if (typeof e.timestamp !== "string") {
190
+ violations.push({
191
+ traceIndex: index,
192
+ traceId: typeof t.traceId === "string" ? t.traceId : undefined,
193
+ field: `apiErrors[${i}].timestamp`,
194
+ message: `Expected string, got "${typeof e.timestamp}"`,
195
+ });
196
+ }
197
+ }
198
+ }
199
+ }
200
+
201
+ return violations;
202
+ }
203
+
204
+ /**
205
+ * Validate an array of raw trace objects.
206
+ * Returns a summary result with all violations.
207
+ */
208
+ export function validateTraceShapes(raws: unknown[]): TraceShapeResult {
209
+ const allViolations: TraceShapeViolation[] = [];
210
+ for (let i = 0; i < raws.length; i++) {
211
+ const v = validateTraceShape(raws[i], i);
212
+ allViolations.push(...v);
213
+ }
214
+ const invalidSet = new Set(allViolations.map((v) => v.traceIndex));
215
+ return {
216
+ valid: allViolations.length === 0,
217
+ totalTraces: raws.length,
218
+ invalidCount: invalidSet.size,
219
+ violations: allViolations,
220
+ };
221
+ }
222
+
223
+ /**
224
+ * Guard: throws if any violations found. Useful at normalizer output boundaries.
225
+ */
226
+ export function assertTraceShapes(traces: unknown[]): asserts traces is TraceMetadata[] {
227
+ const result = validateTraceShapes(traces);
228
+ if (!result.valid) {
229
+ const lines = result.violations.map(
230
+ (v) => ` [trace #${v.traceIndex}${v.traceId ? ` (${v.traceId})` : ""}] ${v.field}: ${v.message}`
231
+ );
232
+ throw new Error(`TraceMetadata shape validation failed (${result.invalidCount} invalid traces):\n${lines.join("\n")}`);
233
+ }
234
+ }
235
+
236
+ // CLI entrypoint
237
+ if (import.meta.main) {
238
+ const inputPath = process.argv[2];
239
+ if (!inputPath) {
240
+ process.stderr.write("Usage: bun scripts/cli/run.sh scripts/validate/trace-shape.ts <traces.json>\n");
241
+ process.exit(1);
242
+ }
243
+
244
+ try {
245
+ const raw = JSON.parse(readFileSync(inputPath, "utf8"));
246
+ if (!Array.isArray(raw)) {
247
+ process.stderr.write("Error: input file must contain a JSON array\n");
248
+ process.exit(1);
249
+ }
250
+ const result = validateTraceShapes(raw);
251
+ process.stdout.write(JSON.stringify(result, null, 2) + "\n");
252
+ if (!result.valid) {
253
+ process.stderr.write(`Validation failed: ${result.invalidCount}/${result.totalTraces} traces have violations\n`);
254
+ process.exit(1);
255
+ }
256
+ process.stderr.write(`Validation passed: ${result.totalTraces} traces OK\n`);
257
+ process.exit(0);
258
+ } catch (err) {
259
+ process.stderr.write(`Error: ${err}\n`);
260
+ process.exit(1);
261
+ }
262
+ }