@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,125 @@
1
+ /**
2
+ * scripts/prep-tasks.ts — the deterministic PREP half of the agent-dispatch engine.
3
+ * ---------------------------------------------------------------------------
4
+ * The agent-dispatch substrate splits judging into PREP (this file) + DISPATCH
5
+ * (the parent session, per references/workflows/orchestrator-protocol.md) +
6
+ * AGGREGATE (run-pipeline.ts reading the verdict files). PREP emits one
7
+ * task-spec file per judging unit — the EXACT (system, user) prompt a dispatched
8
+ * leaf subagent must reason over, keyed by a content-hash so AGGREGATE re-derives
9
+ * the same key from the prompt alone.
10
+ *
11
+ * There is a HARD STAGE BARRIER (the same dependency diagnostics has between its
12
+ * deep-read and its analyzer fan-out): the determiner labels (EV-042) must be
13
+ * REAL before the *build-evals judge prompts can be built, because the judge
14
+ * few-shot block is drawn from the determiner-labeled TRAIN split. So PREP runs
15
+ * in two stages:
16
+ *
17
+ * Stage A — prepDeterminerTasks (no label dependency; pure per-trace prompt).
18
+ * → dispatch error-analyst → collect determiner verdict files.
19
+ * Stage B — prepJudgeTasks (REQUIRES stage-A verdicts collected; replays
20
+ * the pipeline with a capturing judge so the emitted judge prompts
21
+ * are byte-identical to what AGGREGATE will build).
22
+ *
23
+ * PURE except for fs (writes task-spec files; reads stage-A verdict files). No
24
+ * clock / random / network. Model intent SACRED: the pinned envelope is carried
25
+ * on every task spec for the host runtime to honor.
26
+ */
27
+ import { existsSync, readFileSync } from "node:fs";
28
+ import { join } from "node:path";
29
+ import { extractOutcomeSignals, type JudgeInvoke } from "./determine-outcome.ts";
30
+ import { buildOutcomePrompt } from "./judge-prompt-template.ts";
31
+ import {
32
+ writeJudgeTask,
33
+ verdictFileName,
34
+ type JudgeTaskSpec,
35
+ type PinnedEnvelope,
36
+ } from "./agent-dispatch.ts";
37
+ import { runEvalPipeline } from "./run-pipeline.ts";
38
+ import type { PipelineOptions } from "./run-pipeline.ts";
39
+ import type { EvalTrace, SubjectVocab } from "./contracts/eval-types.ts";
40
+
41
+ /** A PREP placeholder verdict — lets the pipeline complete during stage-B capture; never reported. */
42
+ const PREP_PLACEHOLDER = JSON.stringify({
43
+ critique: "PREP placeholder — awaiting the dispatched subagent's verdict file",
44
+ result: "pass",
45
+ confidence: 0,
46
+ });
47
+
48
+ /**
49
+ * Stage A PREP — emit one determiner (EV-042) task-spec per trace. The
50
+ * determiner prompt has NO label dependency (it reads the trace's own event +
51
+ * trajectory + terminal state), so these can be emitted + dispatched first.
52
+ * The dispatched error-analyst writes each verdict file; AGGREGATE-A reads them.
53
+ */
54
+ export function prepDeterminerTasks(
55
+ traces: EvalTrace[],
56
+ opts: { dir: string; pin: PinnedEnvelope; vocab: SubjectVocab },
57
+ ): JudgeTaskSpec[] {
58
+ return traces.map((trace) => {
59
+ const { system, user } = buildOutcomePrompt(
60
+ trace,
61
+ extractOutcomeSignals(trace, opts.vocab),
62
+ opts.vocab,
63
+ );
64
+ return writeJudgeTask(opts.dir, {
65
+ unit: { kind: "discover", traceId: trace.id },
66
+ system,
67
+ user,
68
+ pin: opts.pin,
69
+ });
70
+ });
71
+ }
72
+
73
+ /**
74
+ * A capturing JudgeInvoke: when a prompt's verdict file is already present
75
+ * (stage-A determiner verdicts), READ it; otherwise CAPTURE the prompt as a
76
+ * judge task-spec and return a deterministic placeholder so the pipeline runs to
77
+ * completion. Replaying the real pipeline with this judge emits the *build-evals
78
+ * judge prompts using the REAL determiner labels — guaranteeing they are
79
+ * byte-identical to the prompts AGGREGATE will build (same code, same labels).
80
+ */
81
+ export function createCapturingJudge(opts: {
82
+ verdictDir: string;
83
+ taskDir: string;
84
+ pin: PinnedEnvelope;
85
+ }): { judge: JudgeInvoke; captured: JudgeTaskSpec[] } {
86
+ const captured: JudgeTaskSpec[] = [];
87
+ const judge: JudgeInvoke = (system, user) => {
88
+ const vpath = join(opts.verdictDir, verdictFileName(system, user));
89
+ if (existsSync(vpath)) return Promise.resolve(readFileSync(vpath, "utf8"));
90
+ captured.push(
91
+ // D4 — the criterion judging axis (*build-evals / Step-2b). `kind` now matches the
92
+ // command (was mis-tagged "evaluate" pre-merge). ENVELOPE-ONLY retag: `unit` is not
93
+ // part of promptHash(system, user), so the rendered prompt + its key (8b58d9ca) are
94
+ // invariant — only the task.json envelope carries the new {kind, axis}.
95
+ writeJudgeTask(opts.taskDir, {
96
+ unit: { kind: "build-evals", axis: "criterion" },
97
+ system,
98
+ user,
99
+ pin: opts.pin,
100
+ }),
101
+ );
102
+ return Promise.resolve(PREP_PLACEHOLDER);
103
+ };
104
+ return { judge, captured };
105
+ }
106
+
107
+ /**
108
+ * Stage B PREP — emit the *build-evals / *evaluate judge (EV-043/048) task-specs.
109
+ * REQUIRES the stage-A determiner verdict files to already be collected in
110
+ * `verdictDir` (else the determiner prompts would themselves be captured with
111
+ * placeholder labels, corrupting the judge few-shot). Replays runEvalPipeline
112
+ * with the capturing judge and returns the captured judge tasks for dispatch.
113
+ */
114
+ export async function prepJudgeTasks(
115
+ traces: EvalTrace[],
116
+ opts: { verdictDir: string; taskDir: string; pin: PinnedEnvelope; pipeline: PipelineOptions },
117
+ ): Promise<JudgeTaskSpec[]> {
118
+ const { judge, captured } = createCapturingJudge({
119
+ verdictDir: opts.verdictDir,
120
+ taskDir: opts.taskDir,
121
+ pin: opts.pin,
122
+ });
123
+ await runEvalPipeline(traces, judge, opts.pipeline);
124
+ return captured;
125
+ }
@@ -0,0 +1,310 @@
1
+ /**
2
+ * scripts/profile-subject.ts — EV-049 subject auto-gen (NEVER hand-authored).
3
+ * ---------------------------------------------------------------------------
4
+ * Generate a subject profile from a trace sample (code/platform/trace
5
+ * exploration). For sample this is the EV-049 "scroll the traces, infer the
6
+ * invoked tools" path: the 35-tool inventory falls out of
7
+ * observations[].type=="TOOL" (sample-findings §1). Also infers the event-kind
8
+ * taxonomy, the observation-count clusters, and a platform marker.
9
+ *
10
+ * This is the PURE trace-exploration core (a distinct file from the v1
11
+ * cli/profile-subject.ts, which profiles a skill/agent from its source for the
12
+ * `*audit` surface). PURE + deterministic: tools ranked by frequency then name;
13
+ * no clock / random / network.
14
+ */
15
+ import {
16
+ classifyEvent,
17
+ } from "./determine-outcome.ts";
18
+ import {
19
+ UNCLASSIFIED_EVENT,
20
+ parseSubjectVocab,
21
+ type EvalTrace,
22
+ type EventTagRule,
23
+ type SubjectVocab,
24
+ } from "./contracts/eval-types.ts";
25
+ import { buildFlowGraph } from "./flow-graph.ts";
26
+ import {
27
+ parseExpectedFlow,
28
+ type ExpectedFlow,
29
+ type ExpectedFlowEdge,
30
+ type FlowGraph,
31
+ } from "./contracts/flow-graph.ts";
32
+
33
+ export interface ToolStat {
34
+ name: string;
35
+ count: number;
36
+ }
37
+
38
+ export interface SubjectProfile {
39
+ subjectName: string;
40
+ traceCount: number;
41
+ toolInventory: ToolStat[];
42
+ /**
43
+ * The SUBJECT VOCABULARY the engine reads (EV-002 / EV-049). Either AUTHORED
44
+ * (passed to `profileSubject`) or best-effort auto-generated from the traces.
45
+ * The determiner reads its tag→kind rules / tool names from HERE, never from a
46
+ * module constant.
47
+ */
48
+ vocab: SubjectVocab;
49
+ /** event-kind distribution over the sample (counts), keyed by the vocab kinds. */
50
+ eventTaxonomy: Record<string, number>;
51
+ /** observation-count -> number of traces with that count (discrete clusters). */
52
+ obsCountClusters: Record<number, number>;
53
+ platform: string;
54
+ /**
55
+ * The agent-shaped EXPECTED-FLOW spec (EV-037) the context-flow audit diffs
56
+ * against. AUTHORED when supplied (validated) — the canonical path for
57
+ * fidelity — else best-effort auto-generated from the traces (EV-049): the
58
+ * modal producer→consumer threadings the subject normally exhibits. The
59
+ * semantic fields the trace alone can't carry (which tools DISPATCH sub-agents
60
+ * · which slots the subject's HTML SHOULD render) are left empty with a TODO,
61
+ * exactly like the vocab's recovery/send/guard fields.
62
+ */
63
+ expectedFlow: ExpectedFlow;
64
+ }
65
+
66
+ /** Tool inventory ranked by frequency desc, then name asc (deterministic). */
67
+ export function inferToolInventory(traces: EvalTrace[]): ToolStat[] {
68
+ const counts = new Map<string, number>();
69
+ for (const t of traces) {
70
+ for (const o of t.observations) {
71
+ if (o.type === "TOOL" && typeof o.name === "string") {
72
+ counts.set(o.name, (counts.get(o.name) ?? 0) + 1);
73
+ }
74
+ }
75
+ }
76
+ return [...counts.entries()]
77
+ .map(([name, count]) => ({ name, count }))
78
+ .sort((a, b) => (b.count - a.count !== 0 ? b.count - a.count : a.name.localeCompare(b.name)));
79
+ }
80
+
81
+ function promptOf(trace: EvalTrace): string {
82
+ return typeof trace.input?.prompt === "string" ? trace.input.prompt : "";
83
+ }
84
+
85
+ /**
86
+ * Pull a single message's textual content out of the loosely-typed payload. The
87
+ * AI-SDK / Langfuse shape carries `content` either as a plain string OR as an
88
+ * array of content parts (`{type:"text", text}` / `{text}`). Returns the joined
89
+ * text, or "" when nothing textual is present. PURE — read-only narrowing.
90
+ */
91
+ function messageContentText(content: unknown): string {
92
+ if (typeof content === "string") return content;
93
+ if (Array.isArray(content)) {
94
+ return content
95
+ .map((part) =>
96
+ typeof part === "string"
97
+ ? part
98
+ : part && typeof part === "object" && typeof (part as { text?: unknown }).text === "string"
99
+ ? (part as { text: string }).text
100
+ : "",
101
+ )
102
+ .join("");
103
+ }
104
+ return "";
105
+ }
106
+
107
+ /**
108
+ * Coerce an observation `input` to a message list. The AI-SDK GENERATION span
109
+ * carries its prompt EITHER as a bare message array (`[{role,content},…]`) OR as
110
+ * `{messages:[…]}`. Returns the message array, or `[]` when the input is neither
111
+ * shape. PURE — read-only narrowing over the `unknown` payload.
112
+ */
113
+ function messagesOf(input: unknown): unknown[] {
114
+ if (Array.isArray(input)) return input;
115
+ if (input && typeof input === "object") {
116
+ const m = (input as { messages?: unknown }).messages;
117
+ if (Array.isArray(m)) return m;
118
+ }
119
+ return [];
120
+ }
121
+
122
+ /**
123
+ * RECONSTRUCT the subject's SYSTEM PROMPT from the trace batch (UI-14). The agent
124
+ * never hands us its prompt in the trace-only path, but every LLM call carries it:
125
+ * each GENERATION observation's `input` is the message list sent to the model, and
126
+ * its first `role:"system"` message IS the system prompt. We scan observations in
127
+ * order and return the FIRST non-empty system-message content found across the
128
+ * batch (deterministic: trace order, then observation order).
129
+ *
130
+ * Handles the langfuse / AI-SDK shapes: `input` as a bare message array OR
131
+ * `{messages:[…]}`; the system `content` as a string OR an array of text parts.
132
+ *
133
+ * NEVER confabulates: when no observation carries a `role:"system"` message the
134
+ * function returns `undefined` (the caller keeps the prompt UNAVAILABLE). PURE —
135
+ * no clock / random / network.
136
+ */
137
+ export function inferSystemPrompt(traces: EvalTrace[]): string | undefined {
138
+ for (const t of traces) {
139
+ for (const o of t.observations) {
140
+ for (const msg of messagesOf(o.input)) {
141
+ if (msg && typeof msg === "object" && (msg as { role?: unknown }).role === "system") {
142
+ const text = messageContentText((msg as { content?: unknown }).content).trim();
143
+ if (text.length > 0) return text;
144
+ }
145
+ }
146
+ }
147
+ }
148
+ return undefined;
149
+ }
150
+
151
+ /**
152
+ * Auto-infer the subject's event-tag rules from the traces (EV-049,
153
+ * subject-agnostic extraction). Scans each prompt for opening tags `<{name}` and
154
+ * collects the distinct tag names, ranked by per-trace presence (desc) then name
155
+ * (asc). Tags present in EVERY trace are treated as ubiquitous WRAPPERS (e.g. a
156
+ * `<current_time>` envelope) and dropped — they don't partition the sample into
157
+ * event kinds. Each surviving tag becomes a `{kind: tag, tag}` rule.
158
+ *
159
+ * TODO(EV-049): stem-collapse (e.g. `opportunity_update` → `opportunity`) needs
160
+ * subject semantics the trace alone doesn't carry — supply an AUTHORED vocab
161
+ * (profileSubject's 2nd arg) when canonical kind names matter.
162
+ */
163
+ export function inferEventTags(traces: EvalTrace[]): EventTagRule[] {
164
+ const presence = new Map<string, number>();
165
+ for (const t of traces) {
166
+ const prompt = promptOf(t);
167
+ const seen = new Set<string>();
168
+ for (const m of prompt.matchAll(/<([a-zA-Z][\w-]*)/g)) seen.add(m[1]);
169
+ for (const tag of seen) presence.set(tag, (presence.get(tag) ?? 0) + 1);
170
+ }
171
+ const total = traces.length;
172
+ return [...presence.entries()]
173
+ .filter(([, n]) => total <= 1 || n < total) // drop ubiquitous wrappers
174
+ .sort((a, b) => (b[1] - a[1] !== 0 ? b[1] - a[1] : a[0].localeCompare(b[0])))
175
+ .map(([tag]) => ({ kind: tag, tag }));
176
+ }
177
+
178
+ /**
179
+ * Best-effort auto-generated subject vocab when no AUTHORED vocab is supplied.
180
+ * Event tags are inferred from the traces; the SEMANTIC fields (which tools are
181
+ * "recovery" / which tool is the "send" action / the guard counter attribute)
182
+ * are left empty with a TODO — they need subject semantics the trace alone
183
+ * doesn't carry, so they are supplied via an authored vocab until that inference
184
+ * lands. The ENGINE reads the vocab off the profile either way (EV-002).
185
+ */
186
+ function inferVocab(traces: EvalTrace[]): SubjectVocab {
187
+ return {
188
+ recoveryTools: [], // TODO(EV-049): infer recovery-tool semantics from traces.
189
+ eventTags: inferEventTags(traces),
190
+ sendTool: "", // TODO(EV-049): infer the primary send-action tool from traces.
191
+ guardCounterAttr: null, // TODO(EV-049): infer the guard counter attribute.
192
+ };
193
+ }
194
+
195
+ /** Event-kind distribution over the sample, using the subject's tag rules. */
196
+ export function inferEventTaxonomy(
197
+ traces: EvalTrace[],
198
+ vocab: SubjectVocab,
199
+ ): Record<string, number> {
200
+ const tax: Record<string, number> = { [UNCLASSIFIED_EVENT]: 0 };
201
+ for (const rule of vocab.eventTags) tax[rule.kind] = 0;
202
+ for (const t of traces) {
203
+ const kind = classifyEvent(promptOf(t), vocab);
204
+ tax[kind] = (tax[kind] ?? 0) + 1;
205
+ }
206
+ return tax;
207
+ }
208
+
209
+ /** Name-keyed expected-flow edges from one graph's THREADED data-handoffs. */
210
+ export function expectedEdgesFromGraph(graph: FlowGraph): ExpectedFlowEdge[] {
211
+ const nameById = new Map(graph.nodes.map((n) => [n.id, n.name]));
212
+ const out: ExpectedFlowEdge[] = [];
213
+ for (const e of graph.edges) {
214
+ const fromTool = nameById.get(e.from) ?? "";
215
+ const toTool = nameById.get(e.to) ?? "";
216
+ if (fromTool.length === 0 || toTool.length === 0) continue; // unnamed → not normative
217
+ out.push({ fromTool, toTool, slot: e.slot });
218
+ }
219
+ return out;
220
+ }
221
+
222
+ /**
223
+ * Auto-infer the subject's EXPECTED-FLOW from the trace sample (EV-049,
224
+ * subject-agnostic). The expected threadings = the UNION of producer→consumer
225
+ * data-handoffs actually observed across the sample (deduped, deterministically
226
+ * ordered) — the "normal" flow that SHOULD keep happening (a regression
227
+ * baseline). The semantic fields the trace cannot carry are left empty with a
228
+ * TODO: `dispatchToolNames` (which tools dispatch sub-agents) and
229
+ * `expectedUiSlots` (which slots the subject's HTML artifact SHOULD render) need
230
+ * subject semantics — supply an AUTHORED expected-flow when they matter.
231
+ */
232
+ export function inferExpectedFlow(traces: EvalTrace[]): ExpectedFlow {
233
+ const seen = new Map<string, ExpectedFlowEdge>();
234
+ for (const t of traces) {
235
+ const graph = buildFlowGraph(t);
236
+ for (const edge of expectedEdgesFromGraph(graph)) {
237
+ const key = `${edge.fromTool}␟${edge.toTool}␟${edge.slot ?? ""}`;
238
+ if (!seen.has(key)) seen.set(key, edge);
239
+ }
240
+ }
241
+ const edges = [...seen.values()].sort((a, b) =>
242
+ a.fromTool !== b.fromTool
243
+ ? a.fromTool.localeCompare(b.fromTool)
244
+ : a.toTool !== b.toTool
245
+ ? a.toTool.localeCompare(b.toTool)
246
+ : (a.slot ?? "").localeCompare(b.slot ?? ""),
247
+ );
248
+ return {
249
+ dispatchToolNames: [], // TODO(EV-037): infer sub-agent dispatch semantics; authored until then.
250
+ edges,
251
+ expectedUiSlots: [], // TODO(EV-037): the HTML render slots aren't in agent traces; authored.
252
+ };
253
+ }
254
+
255
+ /** Discrete observation-count clusters: obsCount -> #traces (sample's 4/14/28/44). */
256
+ function inferObsClusters(traces: EvalTrace[]): Record<number, number> {
257
+ const clusters: Record<number, number> = {};
258
+ for (const t of traces) {
259
+ const n = t.observations.length;
260
+ clusters[n] = (clusters[n] ?? 0) + 1;
261
+ }
262
+ return clusters;
263
+ }
264
+
265
+ /** Platform marker from generation-span names (closed, explicit — no fuzzing). */
266
+ export function inferPlatform(traces: EvalTrace[]): string {
267
+ for (const t of traces) {
268
+ for (const o of t.observations) {
269
+ const name = typeof o.name === "string" ? o.name : "";
270
+ if (/^ai\.generateText\b/.test(name) || /^agent\.step\./.test(name)) {
271
+ return "vercel-ai-sdk";
272
+ }
273
+ }
274
+ }
275
+ return "unknown";
276
+ }
277
+
278
+ /** The subject name = the (uniform) trace.name, else "unknown-subject". */
279
+ function inferSubjectName(traces: EvalTrace[]): string {
280
+ const first = traces.find((t) => typeof t.name === "string" && t.name.length > 0);
281
+ return first?.name ?? "unknown-subject";
282
+ }
283
+
284
+ /**
285
+ * Assemble the full subject profile. PURE + deterministic. The subject VOCAB is
286
+ * AUTHORED when supplied (validated against the schema) — the canonical path for
287
+ * fidelity — else best-effort auto-inferred from the traces (EV-049). The engine
288
+ * reads its subject vocabulary off `profile.vocab` (EV-002), never a module
289
+ * constant.
290
+ */
291
+ export function profileSubject(
292
+ traces: EvalTrace[],
293
+ authoredVocab?: SubjectVocab,
294
+ authoredFlow?: ExpectedFlow,
295
+ ): SubjectProfile {
296
+ const vocab =
297
+ authoredVocab !== undefined ? parseSubjectVocab(authoredVocab) : inferVocab(traces);
298
+ const expectedFlow =
299
+ authoredFlow !== undefined ? parseExpectedFlow(authoredFlow) : inferExpectedFlow(traces);
300
+ return {
301
+ subjectName: inferSubjectName(traces),
302
+ traceCount: traces.length,
303
+ toolInventory: inferToolInventory(traces),
304
+ vocab,
305
+ eventTaxonomy: inferEventTaxonomy(traces, vocab),
306
+ obsCountClusters: inferObsClusters(traces),
307
+ platform: inferPlatform(traces),
308
+ expectedFlow,
309
+ };
310
+ }
@@ -0,0 +1,131 @@
1
+ /**
2
+ * scripts/publish-report.ts — UI-13: the publish-time STRIPPER (client-safe HTML).
3
+ * ---------------------------------------------------------------------------
4
+ * The eval-report (`render-eval-report.ts`) is INTERNAL-grade: it carries a §5
5
+ * Self-Eval [INTERNAL] calibration panel + `data-strip="strip-for-client"` markers
6
+ * + raw triggering INPUT (§2) and verbatim EVIDENCE (§4) that may contain PII when
7
+ * the source batch was NOT pre-sanitized. Those markers were declarative ONLY — no
8
+ * code enforced them. This module enforces them:
9
+ *
10
+ * stripForClient(html, opts) →
11
+ * ALWAYS removes · the §5 internal panel (`<section id="t5">…`)
12
+ * · the internal tab-button (`.tab-btn.internal`)
13
+ * · every `data-strip="strip-for-client"` node
14
+ * PII gate (unless opts.assumeSanitized) →
15
+ * · BLANKS the raw triggering inputs embedded in the §2 ledger
16
+ * data blob (`data-pii="ledger"` script: `"input":"…"` → "")
17
+ * · REDACTS the §4 verbatim-evidence regions (`data-pii="evidence"`)
18
+ *
19
+ * The result is a CLIENT-SAFE HTML string: no §5/INTERNAL content, and (by default)
20
+ * no raw PII dumped onto the public tabs. Pass `{ assumeSanitized: true }` (CLI:
21
+ * `--assume-sanitized`) ONLY for a batch you have CONFIRMED carries no PII — then the
22
+ * raw input + verbatim evidence are preserved.
23
+ *
24
+ * PURE + deterministic: a string→string transform, no clock/random, no I/O (the CLI
25
+ * wrapper at the bottom does the read/write). Idempotent: stripping an already-
26
+ * stripped HTML is a no-op (the markers are gone, the regexes match nothing).
27
+ */
28
+
29
+ export interface StripOptions {
30
+ /** When TRUE, the batch is asserted PII-free: raw input + verbatim evidence are
31
+ * PRESERVED (only the §5 internal panel is stripped). DEFAULT false — the PII
32
+ * gate redacts raw input + evidence so an un-sanitized batch never leaks. */
33
+ assumeSanitized?: boolean;
34
+ }
35
+
36
+ /** The placeholder substituted for a redacted PII region (publish, un-sanitized). */
37
+ export const PII_REDACTION =
38
+ "⟨redacted on publish — raw content withheld; re-run with --assume-sanitized for a confirmed-PII-free batch⟩";
39
+
40
+ /**
41
+ * Strip the INTERNAL surfaces (and, unless `assumeSanitized`, the raw PII) from a
42
+ * rendered eval-report → a client-safe HTML string. See the module header.
43
+ */
44
+ export function stripForClient(html: string, opts: StripOptions = {}): string {
45
+ let out = html;
46
+
47
+ // 1) ALWAYS — remove the §5 Self-Eval [INTERNAL] panel (whole <section id="t5">).
48
+ out = out.replace(/<section\b[^>]*\bid="t5"[^>]*>[\s\S]*?<\/section>/g, "");
49
+
50
+ // 2) ALWAYS — remove the internal tab-button (.tab-btn.internal → data-tab="t5").
51
+ out = out.replace(/<button\b[^>]*\bclass="tab-btn internal"[^>]*>[\s\S]*?<\/button>/g, "");
52
+
53
+ // 3) ALWAYS — remove every node explicitly marked `data-strip="strip-for-client"`
54
+ // (tag-agnostic; matches the element + its content). Any leftover after (1).
55
+ out = out.replace(
56
+ /<(\w+)\b[^>]*\bdata-strip="strip-for-client"[^>]*>[\s\S]*?<\/\1>/g,
57
+ "",
58
+ );
59
+
60
+ // 4) PII GATE — unless the batch is asserted sanitized, scrub the raw PII.
61
+ if (opts.assumeSanitized !== true) {
62
+ // 4a) BLANK the raw triggering INPUTs embedded in the §2 ledger data blob. The
63
+ // blob is the `data-pii="ledger"` <script>; within it, every `"input":"…"`
64
+ // JSON value (the verbatim user/agent prompt) is emptied. The JSON-string
65
+ // pattern `"(?:[^"\\]|\\.)*"` correctly spans escaped quotes.
66
+ out = out.replace(
67
+ /(<script\b[^>]*\bdata-pii="ledger"[^>]*>)([\s\S]*?)(<\/script>)/g,
68
+ (_m, open: string, body: string, close: string) =>
69
+ open + body.replace(/"input":"(?:[^"\\]|\\.)*"/g, '"input":""') + close,
70
+ );
71
+
72
+ // 4b) REDACT the §4 verbatim-evidence regions (`data-pii="evidence"`): replace
73
+ // the element's INNER content with the redaction placeholder (keep the tags
74
+ // so the layout is intact). No nested same-tag inside these cells.
75
+ out = out.replace(
76
+ /(<(\w+)\b[^>]*\bdata-pii="evidence"[^>]*>)[\s\S]*?(<\/\2>)/g,
77
+ (_m, open: string, _tag: string, close: string) => open + PII_REDACTION + close,
78
+ );
79
+ }
80
+
81
+ return out;
82
+ }
83
+
84
+ // ── CLI entrypoint ──────────────────────────────────────────────────────────
85
+ //
86
+ // bun scripts/publish-report.ts <report.html> [out.client.html] [--assume-sanitized]
87
+ // Reads a rendered eval-report, strips the INTERNAL surfaces (+ PII unless the flag),
88
+ // and writes the client-safe HTML. Default out = `<input>.client.html`.
89
+
90
+ declare const Bun: { argv: string[] } | undefined;
91
+
92
+ async function main(): Promise<void> {
93
+ const argv = typeof Bun !== "undefined" ? Bun.argv.slice(2) : process.argv.slice(2);
94
+ const flags = new Set(argv.filter((a) => a.startsWith("--")));
95
+ const positional = argv.filter((a) => !a.startsWith("--"));
96
+ const [inputPath, outArg] = positional;
97
+ if (!inputPath) {
98
+ console.error(
99
+ "usage: publish-report.ts <report.html> [out.client.html] [--assume-sanitized]",
100
+ );
101
+ process.exit(2);
102
+ return;
103
+ }
104
+ const { readFileSync, writeFileSync } = await import("node:fs");
105
+ const assumeSanitized = flags.has("--assume-sanitized");
106
+ const html = readFileSync(inputPath, "utf8");
107
+ const client = stripForClient(html, { assumeSanitized });
108
+ const outPath = outArg ?? inputPath.replace(/\.html$/i, "") + ".client.html";
109
+ writeFileSync(outPath, client);
110
+ console.info(
111
+ JSON.stringify(
112
+ {
113
+ input: inputPath,
114
+ output: outPath,
115
+ assumeSanitized,
116
+ strippedInternalPanel: !client.includes('id="t5"'),
117
+ piiGated: !assumeSanitized,
118
+ },
119
+ null,
120
+ 2,
121
+ ),
122
+ );
123
+ process.exit(0);
124
+ }
125
+
126
+ const isMain =
127
+ typeof import.meta !== "undefined" &&
128
+ (import.meta as unknown as { main?: boolean }).main === true;
129
+ if (isMain) {
130
+ void main();
131
+ }
@@ -0,0 +1,81 @@
1
+ /**
2
+ * scripts/read-unitf-traces.ts — the STRANGLER entry point.
3
+ * ---------------------------------------------------------------------------
4
+ * Loads a handed-over UniTF `.jsonl` (one `UnifiedTrace` record per line,
5
+ * produced by `mutagent-cli trace fetch --export …`) → `EvalTrace[]` via the
6
+ * `projectUnitfToEvalTrace` adapter. This is now the ONLY trace-intake path — it
7
+ * replaced (and the flip DELETED) the former `ingest-sources.ts` fetcher-registry
8
+ * + `load-traces.ts` `mapRecord` stack: fetch/normalize now lives ENTIRELY in
9
+ * `mutagent-cli`; the evaluator reads a PATH and never fetches.
10
+ *
11
+ * Tolerant by design (mirrors `parseNdjsonTraces`): blank lines are skipped,
12
+ * malformed lines are SKIPPED + COUNTED (surfaced, never swallowed — a large
13
+ * export must not abort on one bad line). `parseUnitfJsonl` is PURE; only
14
+ * `readUnitfAsEvalTraces` touches the filesystem.
15
+ */
16
+ import type { EvalTrace } from "./contracts/eval-types.ts";
17
+ import {
18
+ projectUnitfToEvalTrace,
19
+ type UnifiedTraceLike,
20
+ } from "./unitf-to-evaltrace.ts";
21
+
22
+ export interface ParsedUnitfTraces {
23
+ traces: EvalTrace[];
24
+ /** lines that failed to parse OR lacked the minimal UniTF shape (surfaced). */
25
+ skipped: number;
26
+ }
27
+
28
+ /**
29
+ * A parsed JSON line is a usable UniTF record when it is an object carrying a
30
+ * non-empty `traceId` and a `spans` array — the minimal shape the projection
31
+ * reads. A line that parses as JSON but is not a UniTF record is counted as
32
+ * skipped (never silently coerced). PURE.
33
+ */
34
+ function asUnitfRecord(value: unknown): UnifiedTraceLike | null {
35
+ if (value === null || typeof value !== "object") return null;
36
+ const rec = value as Record<string, unknown>;
37
+ if (typeof rec.traceId !== "string" || rec.traceId.length === 0) return null;
38
+ if (!Array.isArray(rec.spans)) return null;
39
+ return rec as unknown as UnifiedTraceLike;
40
+ }
41
+
42
+ /**
43
+ * Parse UniTF JSONL text → EvalTrace[]. One record per line; blank lines
44
+ * skipped; malformed / non-UniTF lines skipped + counted. PURE + deterministic.
45
+ */
46
+ export function parseUnitfJsonl(text: string): ParsedUnitfTraces {
47
+ const traces: EvalTrace[] = [];
48
+ let skipped = 0;
49
+ for (const line of text.split("\n")) {
50
+ const trimmed = line.trim();
51
+ if (trimmed.length === 0) continue;
52
+ let parsed: unknown;
53
+ try {
54
+ parsed = JSON.parse(trimmed);
55
+ } catch {
56
+ skipped += 1;
57
+ continue;
58
+ }
59
+ const rec = asUnitfRecord(parsed);
60
+ if (rec === null) {
61
+ skipped += 1;
62
+ continue;
63
+ }
64
+ traces.push(projectUnitfToEvalTrace(rec));
65
+ }
66
+ return { traces, skipped };
67
+ }
68
+
69
+ /**
70
+ * Read a handed-over UniTF `.jsonl` file → EvalTrace[] via the projection. The
71
+ * effectful entry point the evaluator calls in place of `ingestSources`. THROWS
72
+ * only when the path is missing/unreadable — a malformed LINE inside is tolerated
73
+ * (skipped + counted), never fatal.
74
+ */
75
+ export async function readUnitfAsEvalTraces(
76
+ jsonlPath: string,
77
+ ): Promise<ParsedUnitfTraces> {
78
+ const { readFileSync } = await import("node:fs");
79
+ const text = readFileSync(jsonlPath, "utf8");
80
+ return parseUnitfJsonl(text);
81
+ }