@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,284 @@
1
+ /**
2
+ * scripts/unitf-to-evaltrace.ts — the STRANGLER projection adapter.
3
+ * ---------------------------------------------------------------------------
4
+ * Projects one UniTF `UnifiedTrace` record → the evaluator's in-package
5
+ * `EvalTrace` shape (MIGRATION-diagnostics-evaluator.md §3.2). This REPLACED (and
6
+ * the flip DELETED) `load-traces.ts` `mapRecord` (raw Langfuse → EvalTrace):
7
+ * instead of mapping a raw platform record, the evaluator reads a PRE-NORMALIZED
8
+ * UniTF JSONL handed over by `mutagent-cli` and projects each record here. All
9
+ * downstream (sample-traces / profile-subject / discover / judge / scorecard)
10
+ * consumes the resulting `EvalTrace[]` UNCHANGED.
11
+ *
12
+ * STANDALONE — the UniTF type shape is PORTED (a minimal structural subset), NOT
13
+ * imported from `@mutagent/tools`. The boundary between the CLI and this skill is
14
+ * the JSONL file on disk, never a source import (avoids a cross-package cycle;
15
+ * see the migration doc §6.1 "Circular import" risk row). Only the fields the
16
+ * projection actually reads are ported.
17
+ *
18
+ * PURE + deterministic: no clock, no random, no I/O. (The effectful JSONL read
19
+ * lives in `read-unitf-traces.ts`, which calls this.)
20
+ */
21
+ import type { EvalTrace, TraceObservation } from "./contracts/eval-types.ts";
22
+
23
+ // ── Ported minimal UniTF shape (structural subset of @mutagent/tools unitf.ts) ──
24
+ //
25
+ // Intentionally a LOOSE structural mirror — a `UnifiedTrace` handed over on disk
26
+ // carries the full frozen schema, but the projection reads only these fields.
27
+ // Kept in-package so the skill never source-imports the tools package.
28
+
29
+ /** The message-style role a UniTF span may carry (transcript projection). */
30
+ export type UnitfRole = "user" | "assistant" | "system" | "tool" | "toolResult";
31
+
32
+ /** The OTel-aligned span kind. Kept as the literal union the projection branches on. */
33
+ export type UnitfSpanKind =
34
+ | "llm"
35
+ | "tool"
36
+ | "retrieval"
37
+ | "agent"
38
+ | "event"
39
+ | "span";
40
+
41
+ /** The OTel-aligned status a UniTF span (and the trace) may carry. */
42
+ export type UnitfStatus = "ok" | "error" | "unknown";
43
+
44
+ /** Token usage split (structural subset of @mutagent/tools `TokensSchema`). */
45
+ export interface UnitfTokens {
46
+ input?: number;
47
+ output?: number;
48
+ total?: number;
49
+ }
50
+
51
+ /** One UniTF span (unifies a message AND an observation). Structural subset. */
52
+ export interface UnitfSpan {
53
+ name: string;
54
+ kind: UnitfSpanKind;
55
+ role?: UnitfRole;
56
+ /** XF-FIX Finding C — span-level status, used to derive the trace `errored` flag. */
57
+ status?: UnitfStatus;
58
+ input?: unknown;
59
+ output?: unknown;
60
+ }
61
+
62
+ /** A raw platform score, carried through verbatim (Langfuse-style). */
63
+ export interface UnitfScore {
64
+ name: string;
65
+ value?: number | string | boolean;
66
+ comment?: string;
67
+ dataType?: string;
68
+ }
69
+
70
+ /** The `ext.eval` fidelity block the fidelity gate reads. Structural subset. */
71
+ export interface UnitfEvalExt {
72
+ incomplete?: boolean;
73
+ incompleteReason?: string;
74
+ }
75
+
76
+ /** The derived `computed` convenience block (structural subset). NEVER authoritative —
77
+ * read only as a fallback, exactly as the diagnostics adapter does. */
78
+ export interface UnitfComputed {
79
+ hasError?: boolean;
80
+ totalTokens?: number;
81
+ }
82
+
83
+ /** One UniTF record. Structural subset of the frozen `UnifiedTrace` contract. */
84
+ export interface UnifiedTraceLike {
85
+ traceId: string;
86
+ agentName?: string;
87
+ latencyMs?: number;
88
+ costUsd?: number;
89
+ tags?: string[];
90
+ scores?: UnitfScore[];
91
+ spans: UnitfSpan[];
92
+ /** XF-FIX Finding C — top-level trace status (`ok|error|unknown`). */
93
+ status?: UnitfStatus;
94
+ /** XF-FIX Finding D — trace-level token usage. */
95
+ tokens?: UnitfTokens;
96
+ /** XF-FIX Finding D — derived convenience block (hasError / totalTokens fallbacks). */
97
+ computed?: UnitfComputed;
98
+ ext?: {
99
+ eval?: UnitfEvalExt;
100
+ };
101
+ }
102
+
103
+ // ── Text derivation (ported from @mutagent/tools derive.ts `asText`) ─────────
104
+ //
105
+ // A span's input/output is `unknown` — real exports carry nested payloads. The
106
+ // evaluator's `EvalTrace.input.prompt` / `output.response` are strings, so a
107
+ // deterministic best-effort stringify is needed. Mirrors the tools-package
108
+ // `asText` (pull a known text-ish field, else stable JSON) so a value projected
109
+ // here matches what a diagnostics `messagesView` would render.
110
+
111
+ /** Best-effort deterministic stringify of a span payload. PURE. */
112
+ function asText(v: unknown): string {
113
+ if (v === undefined || v === null) return "";
114
+ if (typeof v === "string") return v;
115
+ if (typeof v === "number" || typeof v === "boolean") return String(v);
116
+ if (typeof v === "object") {
117
+ const o = v as Record<string, unknown>;
118
+ for (const k of ["text", "content", "response", "prompt", "message"]) {
119
+ if (typeof o[k] === "string") return o[k] as string;
120
+ }
121
+ try {
122
+ return JSON.stringify(v);
123
+ } catch {
124
+ return "";
125
+ }
126
+ }
127
+ return "";
128
+ }
129
+
130
+ // ── Role kind-fallback (XF-FIX Finding A) ────────────────────────────────────
131
+ //
132
+ // ROOT CAUSE of the Langfuse loss: `langfuse.ts obsToSpan` never sets `span.role`
133
+ // (a Langfuse observation carries no message role). The old projection derived
134
+ // the prompt from `role∈{user,system}` and the response from `role==="assistant"
135
+ // && kind==="llm"` — BOTH miss on a role-less span ⇒ `input.prompt` / `output.
136
+ // response` were empty for EVERY Langfuse trace. Diagnostics never had this bug:
137
+ // its `unitf-adapter.ts` `spanMessageRole` falls back to `kind` when `role` is
138
+ // absent. This mirrors that fallback so the evaluator lane survives the identical
139
+ // role-less input Diagnostics already reads fine (reader-side fix — the shared
140
+ // `langfuse.ts` producer is deliberately NOT touched, keeping the clean
141
+ // Diagnostics lane untouched).
142
+
143
+ /**
144
+ * The span's effective message role. When an explicit `role` is present it wins;
145
+ * otherwise it is inferred from `kind` (a role-less `llm`/`agent` span — the
146
+ * Langfuse GENERATION shape — reads as `assistant`; a `tool` span as `tool`).
147
+ * MIRRORS diagnostics `unitf-adapter.ts` `spanMessageRole`. PURE.
148
+ *
149
+ * NOTE: inference never yields `user`/`system` (a role-less span is never a user
150
+ * turn), so prompt detection still requires an EXPLICIT user/system role — the
151
+ * Langfuse prompt is recovered from the GENERATION span's own `input` instead
152
+ * (see the response-span input fallback in the projection).
153
+ */
154
+ function effectiveRole(span: UnitfSpan): UnitfRole {
155
+ if (span.role !== undefined) return span.role;
156
+ switch (span.kind) {
157
+ case "llm":
158
+ case "agent":
159
+ return "assistant";
160
+ case "tool":
161
+ return "tool";
162
+ default:
163
+ return "assistant";
164
+ }
165
+ }
166
+
167
+ // ── Token total fallback (XF-FIX Finding D) ──────────────────────────────────
168
+ //
169
+ // MIRRORS diagnostics `unitf-adapter.ts` `fallbackTotalTokens` so both lanes
170
+ // report the SAME total: prefer `tokens.total`, else `input + output` when either
171
+ // is present, else undefined (NEVER 0 — an absent count stays absent).
172
+
173
+ /** Best-effort trace total from a `UnitfTokens` split. PURE; undefined-safe. */
174
+ function fallbackTotalTokens(t: UnitfTokens | undefined): number | undefined {
175
+ if (t === undefined) return undefined;
176
+ if (t.total !== undefined) return t.total;
177
+ if (t.input !== undefined || t.output !== undefined) {
178
+ return (t.input ?? 0) + (t.output ?? 0);
179
+ }
180
+ return undefined;
181
+ }
182
+
183
+ /**
184
+ * Project a UniTF record → EvalTrace (migration doc §3.2 mapping table).
185
+ *
186
+ * id ← ut.traceId
187
+ * name ← ut.agentName
188
+ * output ← first EFFECTIVE-assistant llm span → { response: <text of span.output> }
189
+ * (XF-FIX A: role-less GENERATION spans read as assistant via kind)
190
+ * input ← first user|system span's input, ELSE the response span's own
191
+ * input → { prompt } (XF-FIX A: recovers the Langfuse prompt)
192
+ * observations ← ut.spans → { type: kind.toUpperCase(), name, input, output }
193
+ * errored/status ← computed.hasError ?? (status==="error" || any span error) / ut.status (XF-FIX C)
194
+ * tokens/totalTokens← ut.tokens split / computed.totalTokens ?? tokens.total ?? in+out (XF-FIX D)
195
+ * scores ← ut.scores (verbatim)
196
+ * tags ← ut.tags
197
+ * latencyMs/costUsd← ut.latencyMs / ut.costUsd
198
+ * incomplete ← ut.ext.eval.incomplete ?? false (the §9.4.2 fidelity marker)
199
+ * incompleteReason ← ut.ext.eval.incompleteReason
200
+ *
201
+ * PURE + deterministic — same record ⇒ same EvalTrace.
202
+ */
203
+ export function projectUnitfToEvalTrace(ut: UnifiedTraceLike): EvalTrace {
204
+ const observations: TraceObservation[] = ut.spans.map((span) => {
205
+ const obs: TraceObservation = { type: span.kind.toUpperCase() };
206
+ if (span.name !== undefined) obs.name = span.name;
207
+ if (span.input !== undefined) obs.input = span.input;
208
+ if (span.output !== undefined) obs.output = span.output;
209
+ return obs;
210
+ });
211
+
212
+ const out: EvalTrace = {
213
+ id: ut.traceId,
214
+ observations,
215
+ };
216
+
217
+ if (ut.agentName !== undefined) out.name = ut.agentName;
218
+
219
+ // output ← first assistant LLM span's output, wrapped to { response }. The
220
+ // assistant role is now EFFECTIVE (XF-FIX Finding A): a role-less GENERATION
221
+ // span (kind==="llm", the Langfuse shape) reads as assistant via `effectiveRole`,
222
+ // so its output is picked up instead of being silently dropped.
223
+ const responseSpan = ut.spans.find(
224
+ (s) => effectiveRole(s) === "assistant" && s.kind === "llm",
225
+ );
226
+ if (responseSpan !== undefined && responseSpan.output !== undefined) {
227
+ out.output = { response: asText(responseSpan.output) };
228
+ }
229
+
230
+ // input ← first user|system span's input, wrapped to { prompt }. A role-less
231
+ // span never infers to user/system, so when there is no explicit user/system
232
+ // turn (again the Langfuse shape — one GENERATION span carrying prompt in its
233
+ // OWN `input` and response in `output`) the prompt is recovered from the
234
+ // response span's `input`. Without this fallback `input.prompt` was empty for
235
+ // EVERY Langfuse trace (Finding A).
236
+ const promptSpan = ut.spans.find(
237
+ (s) => effectiveRole(s) === "user" || effectiveRole(s) === "system",
238
+ );
239
+ if (promptSpan !== undefined && promptSpan.input !== undefined) {
240
+ out.input = { prompt: asText(promptSpan.input) };
241
+ } else if (responseSpan !== undefined && responseSpan.input !== undefined) {
242
+ out.input = { prompt: asText(responseSpan.input) };
243
+ }
244
+
245
+ // Finding C — carry structured error/status so an error-KIND criterion has a
246
+ // field to read (previously error state survived only as textual span output).
247
+ // `errored` mirrors diagnostics `computed.hasError ?? status==="error"`, extended
248
+ // to also honor any span-level error. Always set (false = grounded not-errored).
249
+ if (ut.status !== undefined) out.status = ut.status;
250
+ out.errored =
251
+ ut.computed?.hasError ??
252
+ (ut.status === "error" || ut.spans.some((s) => s.status === "error"));
253
+
254
+ // Finding D — carry token usage (undefined-safe; never coerced to 0) so a
255
+ // token-budget criterion is supported at intake, alongside the already-carried
256
+ // costUsd + latencyMs. `totalTokens` uses the diagnostics fallback chain.
257
+ if (ut.tokens !== undefined) {
258
+ const tk: { input?: number; output?: number; total?: number } = {};
259
+ if (typeof ut.tokens.input === "number") tk.input = ut.tokens.input;
260
+ if (typeof ut.tokens.output === "number") tk.output = ut.tokens.output;
261
+ if (typeof ut.tokens.total === "number") tk.total = ut.tokens.total;
262
+ if (tk.input !== undefined || tk.output !== undefined || tk.total !== undefined) {
263
+ out.tokens = tk;
264
+ }
265
+ }
266
+ const totalTokens = ut.computed?.totalTokens ?? fallbackTotalTokens(ut.tokens);
267
+ if (totalTokens !== undefined) out.totalTokens = totalTokens;
268
+
269
+ if (ut.scores !== undefined) out.scores = ut.scores;
270
+ if (ut.tags !== undefined) {
271
+ out.tags = ut.tags.filter((t): t is string => typeof t === "string");
272
+ }
273
+ if (typeof ut.latencyMs === "number") out.latencyMs = ut.latencyMs;
274
+ if (typeof ut.costUsd === "number") out.costUsd = ut.costUsd;
275
+
276
+ // §9.4.2 fidelity marker — projected DIRECTLY from ext.eval so an incomplete
277
+ // trace never reaches the criteria walk unflagged.
278
+ const incomplete = ut.ext?.eval?.incomplete ?? false;
279
+ if (incomplete) out.incomplete = true;
280
+ const reason = ut.ext?.eval?.incompleteReason;
281
+ if (typeof reason === "string" && reason.length > 0) out.incompleteReason = reason;
282
+
283
+ return out;
284
+ }
@@ -0,0 +1,358 @@
1
+ /**
2
+ * scripts/validate-judge.ts — EV-044 `*validate` (Type A — Code-only, pure math).
3
+ * ---------------------------------------------------------------------------
4
+ * Calibrate a judge against human labels (the rubric is `references/validate-
5
+ * evaluator.md`; this is the deterministic STATS that implement it):
6
+ * - 2×2 confusion matrix → TPR / TNR (NOT raw accuracy — misleading under
7
+ * class imbalance);
8
+ * - split-disjointness + TEST-ONCE guards (dev for iteration, test measured
9
+ * exactly once — looking at test then iterating is data leakage);
10
+ * - Rogan-Gladen bias correction θ = (p_obs + TNR − 1) / (TPR + TNR − 1)
11
+ * with clip to [0,1] and `invalid` when the denominator ≈ 0 (judge no better
12
+ * than random);
13
+ * - a DETERMINISTIC bootstrap CI (seeded LCG resample — NO Math.random, so the
14
+ * interval is byte-identical across reruns, C-PIN-adjacent);
15
+ * - graceful degradation: a criterion with < MIN_LABELS human labels (or TPR/
16
+ * TNR below target) stays `unvalidated` and is reported BIAS-CORRECTED, never
17
+ * blocking — the autonomous loop has no human to wait on.
18
+ *
19
+ * Austerity: NO judge prompt, NO LLM — this PREPs/AGGREGATEs the numbers; the
20
+ * verdicts it consumes come from the dispatched eval-judge (read back from
21
+ * verdict files). The pinned judge model is recorded on the result (a model
22
+ * change invalidates the numbers — re-validate). PURE — no clock/random/network.
23
+ */
24
+ import { OutcomeVerdict, type OutcomeVerdictValue } from "./contracts/eval-types.ts";
25
+ import {
26
+ HumanVerdict,
27
+ ValidationStatus,
28
+ type ConfidenceInterval,
29
+ type ConfusionMatrix,
30
+ type HumanLabel,
31
+ type ValidationResult,
32
+ } from "./contracts/validation.ts";
33
+
34
+ // ── calibration thresholds (validate-evaluator.md) ───────────────────────────
35
+ /** Below this many labels the CIs get wide → the judge stays `unvalidated`. */
36
+ export const MIN_LABELS = 60;
37
+ /** Target TPR/TNR (validate-evaluator.md step 5); below → `unvalidated`. */
38
+ export const TARGET_TPR = 0.9;
39
+ export const TARGET_TNR = 0.9;
40
+ /** Rogan-Gladen denominator floor — below this the judge is ≈ random → invalid. */
41
+ export const RG_DENOM_MIN = 1e-6;
42
+
43
+ // ── binary class projection (defer / uncertain are excluded) ─────────────────
44
+ type BinaryClass = "pass" | "fail";
45
+
46
+ /** Project a human verdict to the binary class, or null for `defer`. */
47
+ function humanBinary(v: HumanLabel["label"]): BinaryClass | null {
48
+ if (v === HumanVerdict.Pass) return "pass";
49
+ if (v === HumanVerdict.Fail) return "fail";
50
+ return null; // defer — no ground truth
51
+ }
52
+
53
+ /** Project a judge verdict to the binary class, or null for `uncertain`. */
54
+ function judgeBinary(v: OutcomeVerdictValue): BinaryClass | null {
55
+ if (v === OutcomeVerdict.Pass) return "pass";
56
+ if (v === OutcomeVerdict.Fail) return "fail";
57
+ return null; // uncertain — excluded from confusion math
58
+ }
59
+
60
+ /** One judge prediction for a trace (read back from a verdict file). */
61
+ export interface JudgePred {
62
+ traceId: string;
63
+ result: OutcomeVerdictValue;
64
+ }
65
+
66
+ /** A paired human/judge binary judgment for one trace (defer/uncertain dropped). */
67
+ export interface LabeledPair {
68
+ traceId: string;
69
+ human: BinaryClass;
70
+ judge: BinaryClass;
71
+ }
72
+
73
+ // ── split-disjointness + test-once guards ────────────────────────────────────
74
+
75
+ /**
76
+ * Assert no traceId is assigned to more than one split (train/dev/test must
77
+ * partition cleanly — an overlap is leakage). THROWS on a conflict. PURE.
78
+ */
79
+ export function assertSplitsDisjoint(labels: HumanLabel[]): void {
80
+ const splitOf = new Map<string, string>();
81
+ for (const l of labels) {
82
+ if (l.split === undefined) continue;
83
+ const prior = splitOf.get(l.traceId);
84
+ if (prior !== undefined && prior !== l.split) {
85
+ throw new Error(
86
+ `assertSplitsDisjoint: trace '${l.traceId}' is in both '${prior}' and '${l.split}' ` +
87
+ "splits — train/dev/test must be disjoint (data leakage).",
88
+ );
89
+ }
90
+ splitOf.set(l.traceId, l.split);
91
+ }
92
+ }
93
+
94
+ /**
95
+ * Enforce the test-once rule: the held-out test split is measured EXACTLY once.
96
+ * THROWS if a prior test measurement is already recorded. The caller persists
97
+ * the flag in run state; this guards the transition. PURE.
98
+ */
99
+ export function assertTestUsedOnce(testAlreadyMeasured: boolean): void {
100
+ if (testAlreadyMeasured) {
101
+ throw new Error(
102
+ "assertTestUsedOnce: the test split was already measured — re-running on test after " +
103
+ "seeing results is data leakage (validate-evaluator.md step 6). Go back to dev.",
104
+ );
105
+ }
106
+ }
107
+
108
+ // ── pairing + confusion matrix ───────────────────────────────────────────────
109
+
110
+ /**
111
+ * Pair human labels with judge predictions by traceId, dropping `defer` /
112
+ * `uncertain` (no ground truth / no judge call). Optionally restrict to one
113
+ * split. DETERMINISTIC (ordered by traceId). PURE.
114
+ */
115
+ export function pairLabels(
116
+ human: HumanLabel[],
117
+ judge: JudgePred[],
118
+ split?: "train" | "dev" | "test",
119
+ ): LabeledPair[] {
120
+ const judgeById = new Map(judge.map((j) => [j.traceId, j.result]));
121
+ const out: LabeledPair[] = [];
122
+ for (const l of human) {
123
+ if (split !== undefined && l.split !== split) continue;
124
+ const h = humanBinary(l.label);
125
+ if (h === null) continue;
126
+ const jr = judgeById.get(l.traceId);
127
+ if (jr === undefined) continue;
128
+ const j = judgeBinary(jr);
129
+ if (j === null) continue;
130
+ out.push({ traceId: l.traceId, human: h, judge: j });
131
+ }
132
+ return out.sort((a, b) => a.traceId.localeCompare(b.traceId));
133
+ }
134
+
135
+ /** Build a 2×2 confusion matrix from paired judgments (Pass = positive). PURE. */
136
+ export function confusionMatrix(pairs: LabeledPair[]): ConfusionMatrix {
137
+ const cm: ConfusionMatrix = { tp: 0, fp: 0, tn: 0, fn: 0 };
138
+ for (const p of pairs) {
139
+ if (p.human === "pass" && p.judge === "pass") cm.tp++;
140
+ else if (p.human === "fail" && p.judge === "pass") cm.fp++;
141
+ else if (p.human === "fail" && p.judge === "fail") cm.tn++;
142
+ else cm.fn++; // human pass, judge fail
143
+ }
144
+ return cm;
145
+ }
146
+
147
+ /** TPR = tp / (tp + fn); null when there are no human-Pass examples. PURE. */
148
+ export function tprOf(cm: ConfusionMatrix): number | null {
149
+ const denom = cm.tp + cm.fn;
150
+ return denom === 0 ? null : cm.tp / denom;
151
+ }
152
+
153
+ /** TNR = tn / (tn + fp); null when there are no human-Fail examples. PURE. */
154
+ export function tnrOf(cm: ConfusionMatrix): number | null {
155
+ const denom = cm.tn + cm.fp;
156
+ return denom === 0 ? null : cm.tn / denom;
157
+ }
158
+
159
+ // ── Rogan-Gladen bias correction ─────────────────────────────────────────────
160
+
161
+ function clip01(x: number): number {
162
+ return x < 0 ? 0 : x > 1 ? 1 : x;
163
+ }
164
+
165
+ export interface RoganGladen {
166
+ /** the bias-corrected true rate, clipped to [0,1]; null when invalid. */
167
+ corrected: number | null;
168
+ /** false when TPR+TNR−1 ≈ 0 (judge no better than random → uncorrectable). */
169
+ valid: boolean;
170
+ }
171
+
172
+ /**
173
+ * Rogan-Gladen correction: θ = (p_obs + TNR − 1) / (TPR + TNR − 1). Clipped to
174
+ * [0,1]. INVALID (corrected=null) when the denominator's magnitude is below
175
+ * `denomMin` — the judge is no better than random, so the raw rate cannot be
176
+ * de-biased. PURE.
177
+ */
178
+ export function roganGladen(
179
+ pObs: number,
180
+ tpr: number,
181
+ tnr: number,
182
+ denomMin = RG_DENOM_MIN,
183
+ ): RoganGladen {
184
+ const denom = tpr + tnr - 1;
185
+ if (Math.abs(denom) < denomMin) return { corrected: null, valid: false };
186
+ return { corrected: clip01((pObs + tnr - 1) / denom), valid: true };
187
+ }
188
+
189
+ /** Observed judge Pass-rate over unlabeled predictions (p_obs); null if none. PURE. */
190
+ export function observedPassRate(preds: JudgePred[]): number | null {
191
+ let pass = 0;
192
+ let total = 0;
193
+ for (const p of preds) {
194
+ const b = judgeBinary(p.result);
195
+ if (b === null) continue;
196
+ total++;
197
+ if (b === "pass") pass++;
198
+ }
199
+ return total === 0 ? null : pass / total;
200
+ }
201
+
202
+ // ── deterministic bootstrap CI (seeded LCG — no Math.random) ─────────────────
203
+
204
+ /** A small seeded LCG → [0,1). Deterministic; NEVER Math.random (byte-identity). */
205
+ function lcg(seed: number): () => number {
206
+ let s = seed >>> 0;
207
+ return () => {
208
+ // Numerical Recipes LCG constants.
209
+ s = (Math.imul(s, 1664525) + 1013904223) >>> 0;
210
+ return s / 0x100000000;
211
+ };
212
+ }
213
+
214
+ /** Percentile of an ASCENDING-sorted array (linear interpolation). PURE. */
215
+ export function percentile(sortedAsc: number[], p: number): number {
216
+ if (sortedAsc.length === 0) return NaN;
217
+ if (sortedAsc.length === 1) return sortedAsc[0];
218
+ const idx = clip01(p) * (sortedAsc.length - 1);
219
+ const lo = Math.floor(idx);
220
+ const hi = Math.ceil(idx);
221
+ if (lo === hi) return sortedAsc[lo];
222
+ return sortedAsc[lo] + (sortedAsc[hi] - sortedAsc[lo]) * (idx - lo);
223
+ }
224
+
225
+ export interface BootstrapOptions {
226
+ iterations?: number;
227
+ /** 2-sided level (default 0.95). */
228
+ level?: number;
229
+ /** LCG seed — fixed by default so the CI is reproducible (C-PIN). */
230
+ seed?: number;
231
+ }
232
+
233
+ /**
234
+ * Bootstrap a CI for the Rogan-Gladen corrected rate: resample the labeled pairs
235
+ * (with replacement, deterministic LCG) `iterations` times, recompute TPR/TNR/θ
236
+ * per resample, and take the level-tailed percentiles of the valid θ values.
237
+ * Returns undefined when too few valid resamples exist. `pObs` is fixed (the
238
+ * production observation), only the calibration sample is resampled. PURE.
239
+ */
240
+ export function bootstrapCorrectedCI(
241
+ pairs: LabeledPair[],
242
+ pObs: number,
243
+ opts: BootstrapOptions = {},
244
+ ): ConfidenceInterval | undefined {
245
+ const iterations = opts.iterations ?? 1000;
246
+ const level = opts.level ?? 0.95;
247
+ const n = pairs.length;
248
+ if (n < 2) return undefined;
249
+ const rand = lcg(opts.seed ?? 0x2545f491);
250
+ const thetas: number[] = [];
251
+ for (let it = 0; it < iterations; it++) {
252
+ const cm: ConfusionMatrix = { tp: 0, fp: 0, tn: 0, fn: 0 };
253
+ for (let k = 0; k < n; k++) {
254
+ const p = pairs[Math.floor(rand() * n)];
255
+ if (p.human === "pass" && p.judge === "pass") cm.tp++;
256
+ else if (p.human === "fail" && p.judge === "pass") cm.fp++;
257
+ else if (p.human === "fail" && p.judge === "fail") cm.tn++;
258
+ else cm.fn++;
259
+ }
260
+ const tpr = tprOf(cm);
261
+ const tnr = tnrOf(cm);
262
+ if (tpr === null || tnr === null) continue;
263
+ const rg = roganGladen(pObs, tpr, tnr);
264
+ if (rg.corrected !== null) thetas.push(rg.corrected);
265
+ }
266
+ if (thetas.length < 2) return undefined;
267
+ thetas.sort((a, b) => a - b);
268
+ const tail = (1 - level) / 2;
269
+ return { lo: percentile(thetas, tail), hi: percentile(thetas, 1 - tail), level };
270
+ }
271
+
272
+ // ── top-level orchestration ──────────────────────────────────────────────────
273
+
274
+ export interface ValidateJudgeInput {
275
+ criterionId: string;
276
+ /** the PINNED judge model these numbers belong to (required — C-PIN). */
277
+ judgeModel: string;
278
+ /** human labels (with split tags). */
279
+ humanLabels: HumanLabel[];
280
+ /** judge predictions on the labeled set (read back from verdict files). */
281
+ judgeVerdicts: JudgePred[];
282
+ /** judge predictions on UNLABELED production traces (for p_obs). */
283
+ unlabeledVerdicts?: JudgePred[];
284
+ /** has the test split already been measured? (test-once guard). */
285
+ testAlreadyMeasured?: boolean;
286
+ /** override the min-labels gate (default MIN_LABELS). */
287
+ minLabels?: number;
288
+ }
289
+
290
+ /**
291
+ * Validate ONE judge against human labels → a `ValidationResult`. Picks the
292
+ * final-measurement split (test if present — enforcing test-once — else dev,
293
+ * else all labeled), computes TPR/TNR, the Rogan-Gladen corrected rate from the
294
+ * unlabeled p_obs, and a bootstrap CI. DEGRADES GRACEFULLY: < minLabels labels or
295
+ * sub-target TPR/TNR → `unvalidated` (reported bias-corrected, never blocking).
296
+ * THROWS only on a contract breach (missing pinned model, split overlap,
297
+ * test-reuse). PURE.
298
+ */
299
+ export function validateJudge(input: ValidateJudgeInput): ValidationResult {
300
+ if (input.judgeModel.length === 0) {
301
+ throw new Error("validateJudge: judgeModel is required (C-PIN — the numbers are model-specific).");
302
+ }
303
+ assertSplitsDisjoint(input.humanLabels);
304
+ const minLabels = input.minLabels ?? MIN_LABELS;
305
+
306
+ // choose the final-measurement split: test (once) > dev > all.
307
+ const hasTest = input.humanLabels.some((l) => l.split === "test");
308
+ const hasDev = input.humanLabels.some((l) => l.split === "dev");
309
+ let split: "dev" | "test" | undefined;
310
+ if (hasTest) {
311
+ assertTestUsedOnce(input.testAlreadyMeasured ?? false);
312
+ split = "test";
313
+ } else if (hasDev) {
314
+ split = "dev";
315
+ } else {
316
+ split = undefined; // no split tags → use all labeled
317
+ }
318
+
319
+ const pairs = pairLabels(input.humanLabels, input.judgeVerdicts, split);
320
+ const cm = confusionMatrix(pairs);
321
+ const tpr = tprOf(cm);
322
+ const tnr = tnrOf(cm);
323
+ const labelCount = pairs.length;
324
+
325
+ const pObs = observedPassRate(input.unlabeledVerdicts ?? []);
326
+ const rg =
327
+ tpr !== null && tnr !== null && pObs !== null
328
+ ? roganGladen(pObs, tpr, tnr)
329
+ : { corrected: null, valid: false };
330
+ const ci =
331
+ pObs !== null && rg.valid ? bootstrapCorrectedCI(pairs, pObs) : undefined;
332
+
333
+ // status + note (graceful degradation).
334
+ const reasons: string[] = [];
335
+ if (labelCount < minLabels) reasons.push(`only ${labelCount} labels (< ${minLabels})`);
336
+ if (tpr === null) reasons.push("no human-Pass examples (TPR undefined)");
337
+ else if (tpr < TARGET_TPR) reasons.push(`TPR ${tpr.toFixed(2)} < ${TARGET_TPR}`);
338
+ if (tnr === null) reasons.push("no human-Fail examples (TNR undefined)");
339
+ else if (tnr < TARGET_TNR) reasons.push(`TNR ${tnr.toFixed(2)} < ${TARGET_TNR}`);
340
+ const status = reasons.length === 0 ? ValidationStatus.Validated : ValidationStatus.Unvalidated;
341
+
342
+ const result: ValidationResult = {
343
+ criterionId: input.criterionId,
344
+ judgeModel: input.judgeModel,
345
+ status,
346
+ labelCount,
347
+ tpr,
348
+ tnr,
349
+ observedPassRate: pObs,
350
+ correctedRate: rg.corrected,
351
+ correctionValid: rg.valid,
352
+ note:
353
+ status === ValidationStatus.Validated
354
+ ? `validated on ${labelCount} labels (split: ${split ?? "all"})`
355
+ : `unvalidated — ${reasons.join("; ")}. Reporting bias-corrected, not raw; loop not blocked.`,
356
+ };
357
+ return ci === undefined ? result : { ...result, ci };
358
+ }