freeharness 0.4.1

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 (375) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +108 -0
  3. package/README.md +134 -0
  4. package/canonical/HARVEST.yaml +858 -0
  5. package/canonical/PROVENANCE.yaml +740 -0
  6. package/canonical/agents/README.md +95 -0
  7. package/canonical/agents/agentic-architect.md +18 -0
  8. package/canonical/agents/database-reviewer.md +41 -0
  9. package/canonical/agents/explorer-ai-engineer-analyst.md +65 -0
  10. package/canonical/agents/pr-reviewer.md +96 -0
  11. package/canonical/agents/python-reviewer.md +55 -0
  12. package/canonical/agents/report-formatter.md +19 -0
  13. package/canonical/agents/security-reviewer.md +53 -0
  14. package/canonical/agents/test-writer.md +34 -0
  15. package/canonical/commands/fh-context.md +37 -0
  16. package/canonical/evals/promptfoo.redteam.yaml +108 -0
  17. package/canonical/hooks/cost-prices.json +14 -0
  18. package/canonical/hooks/freeharness-auto-memory.mjs +158 -0
  19. package/canonical/hooks/freeharness-config-guard.mjs +162 -0
  20. package/canonical/hooks/freeharness-context-monitor.mjs +198 -0
  21. package/canonical/hooks/freeharness-converge.mjs +227 -0
  22. package/canonical/hooks/freeharness-cost-tracker.mjs +1027 -0
  23. package/canonical/hooks/freeharness-memory-guard.mjs +57 -0
  24. package/canonical/hooks/freeharness-output-pruner.mjs +333 -0
  25. package/canonical/hooks/freeharness-precompact.mjs +323 -0
  26. package/canonical/hooks/freeharness-repeat-tool.mjs +208 -0
  27. package/canonical/hooks/freeharness-security-guidance.mjs +164 -0
  28. package/canonical/hooks/freeharness-session-start +583 -0
  29. package/canonical/hooks/hooks.auto-memory.claude-code.json +16 -0
  30. package/canonical/hooks/hooks.claude-code.json +17 -0
  31. package/canonical/hooks/hooks.config-guard.claude-code.json +16 -0
  32. package/canonical/hooks/hooks.context-monitor.claude-code.json +15 -0
  33. package/canonical/hooks/hooks.converge.claude-code.json +15 -0
  34. package/canonical/hooks/hooks.cost-tracker.claude-code.json +37 -0
  35. package/canonical/hooks/hooks.memory-guard.claude-code.json +16 -0
  36. package/canonical/hooks/hooks.output-pruner.claude-code.json +16 -0
  37. package/canonical/hooks/hooks.precompact.claude-code.json +15 -0
  38. package/canonical/hooks/hooks.repeat-tool.claude-code.json +25 -0
  39. package/canonical/hooks/hooks.security-guidance.claude-code.json +16 -0
  40. package/canonical/mcp/servers.json +20 -0
  41. package/canonical/openspec/config.base.yaml +89 -0
  42. package/canonical/openspec/schema.spec-driven.yaml +277 -0
  43. package/canonical/openspec/templates/data-contract.md +36 -0
  44. package/canonical/openspec/templates/design.md +84 -0
  45. package/canonical/openspec/templates/eval-plan.md +33 -0
  46. package/canonical/openspec/templates/follow-ups.md +2 -0
  47. package/canonical/openspec/templates/proposal.md +45 -0
  48. package/canonical/openspec/templates/spec.md +42 -0
  49. package/canonical/openspec/templates/tasks.md +38 -0
  50. package/canonical/profiles/local-llamacpp.LOCAL-MODELS.md +47 -0
  51. package/canonical/profiles/local-llamacpp.json +27 -0
  52. package/canonical/profiles/local-ollama.json +20 -0
  53. package/canonical/profiles/mcp.json +91 -0
  54. package/canonical/rules/CLAUDE.md +78 -0
  55. package/canonical/rules/project-CLAUDE.template.md +62 -0
  56. package/canonical/rules/routing.md +20 -0
  57. package/canonical/rules/safety.md +41 -0
  58. package/canonical/settings/settings.cache-hygiene.claude-code.json +5 -0
  59. package/canonical/skills/agent-evaluation/SKILL.md +102 -0
  60. package/canonical/skills/agent-evaluation/assets/evaluation_report_template.md +206 -0
  61. package/canonical/skills/agent-evaluation/evals/cases.yaml +106 -0
  62. package/canonical/skills/agent-evaluation/references/dataset-preparation.md +351 -0
  63. package/canonical/skills/agent-evaluation/references/scorers-constraints.md +165 -0
  64. package/canonical/skills/agent-evaluation/references/scorers.md +431 -0
  65. package/canonical/skills/agent-evaluation/references/setup-guide.md +252 -0
  66. package/canonical/skills/agent-evaluation/references/tracing-integration.md +164 -0
  67. package/canonical/skills/agent-evaluation/references/troubleshooting.md +514 -0
  68. package/canonical/skills/agent-evaluation/scripts/analyze_results.py +462 -0
  69. package/canonical/skills/agent-evaluation/scripts/create_dataset_template.py +382 -0
  70. package/canonical/skills/agent-evaluation/scripts/list_datasets.py +273 -0
  71. package/canonical/skills/agent-evaluation/scripts/run_evaluation_template.py +309 -0
  72. package/canonical/skills/agent-evaluation/scripts/setup_mlflow.py +353 -0
  73. package/canonical/skills/agent-evaluation/scripts/utils/__init__.py +27 -0
  74. package/canonical/skills/agent-evaluation/scripts/utils/env_validation.py +123 -0
  75. package/canonical/skills/agent-evaluation/scripts/utils/tracing_utils.py +108 -0
  76. package/canonical/skills/agent-evaluation/scripts/validate_agent_tracing.py +148 -0
  77. package/canonical/skills/agent-evaluation/scripts/validate_auth.py +240 -0
  78. package/canonical/skills/agent-evaluation/scripts/validate_environment.py +185 -0
  79. package/canonical/skills/agent-evaluation/scripts/validate_tracing_runtime.py +318 -0
  80. package/canonical/skills/agentic-architecture/SKILL.md +41 -0
  81. package/canonical/skills/agentic-architecture/evals/cases.yaml +94 -0
  82. package/canonical/skills/agentic-architecture/reference/context-engineering.md +75 -0
  83. package/canonical/skills/agentic-architecture/reference/patterns.md +76 -0
  84. package/canonical/skills/agentic-architecture/reference/reliability-observability.md +94 -0
  85. package/canonical/skills/agentic-architecture/reference/review-framework.md +59 -0
  86. package/canonical/skills/code-review/SKILL.md +52 -0
  87. package/canonical/skills/code-review/evals/cases.yaml +197 -0
  88. package/canonical/skills/git-workflow/SKILL.md +41 -0
  89. package/canonical/skills/git-workflow/evals/cases.yaml +92 -0
  90. package/canonical/skills/local-code/SKILL.md +24 -0
  91. package/canonical/skills/local-code/evals/cases.yaml +85 -0
  92. package/canonical/skills/local-code/scripts/query_llama.py +68 -0
  93. package/canonical/skills/report-formatting/SKILL.md +62 -0
  94. package/canonical/skills/report-formatting/evals/cases.yaml +83 -0
  95. package/canonical/skills/report-formatting/reference/ARCHITECTURE.md +135 -0
  96. package/canonical/skills/report-formatting/reference/HELPERS.md +120 -0
  97. package/canonical/skills/report-formatting/reference/PPTX.md +136 -0
  98. package/canonical/skills/report-formatting/reference/RELEASE.md +99 -0
  99. package/canonical/skills/report-formatting/reference/TEMPLATES.md +48 -0
  100. package/canonical/skills/report-formatting/reference/authoring.md +66 -0
  101. package/canonical/skills/report-formatting/scripts/architecture-template.md +271 -0
  102. package/canonical/skills/report-formatting/scripts/assets/claro-logo.png +0 -0
  103. package/canonical/skills/report-formatting/scripts/assets/claro-wordmark.svg +1 -0
  104. package/canonical/skills/report-formatting/scripts/build-architecture.js +57 -0
  105. package/canonical/skills/report-formatting/scripts/build-md-claro.js +224 -0
  106. package/canonical/skills/report-formatting/scripts/build-release.js +51 -0
  107. package/canonical/skills/report-formatting/scripts/check-env.js +58 -0
  108. package/canonical/skills/report-formatting/scripts/docmodel.js +283 -0
  109. package/canonical/skills/report-formatting/scripts/example-build.js +119 -0
  110. package/canonical/skills/report-formatting/scripts/example_build_ArchitectureReview_docx.js +195 -0
  111. package/canonical/skills/report-formatting/scripts/example_build_ExecutiveReport_docx.js +114 -0
  112. package/canonical/skills/report-formatting/scripts/package.json +17 -0
  113. package/canonical/skills/report-formatting/scripts/pptx/example_build_StatusReport_pptx.py +223 -0
  114. package/canonical/skills/report-formatting/scripts/pptx/example_build_WeeklyStatus_pptx.py +245 -0
  115. package/canonical/skills/report-formatting/scripts/pptx/pptx_office.py +144 -0
  116. package/canonical/skills/report-formatting/scripts/pptx/requirements.txt +7 -0
  117. package/canonical/skills/report-formatting/scripts/pptx/status_report_blocks.py +193 -0
  118. package/canonical/skills/report-formatting/scripts/pptx/theme_claro_pptx.py +473 -0
  119. package/canonical/skills/report-formatting/scripts/release-template.md +80 -0
  120. package/canonical/skills/report-formatting/scripts/render-mermaid.js +105 -0
  121. package/canonical/skills/report-formatting/scripts/theme-claro.js +403 -0
  122. package/canonical/skills/subagent-driven-development/SKILL.md +60 -0
  123. package/canonical/skills/subagent-driven-development/evals/cases.yaml +208 -0
  124. package/canonical/skills/subagent-driven-development/reference/brief.md +91 -0
  125. package/canonical/skills/subagent-driven-development/reference/handoff.md +118 -0
  126. package/canonical/skills/subagent-driven-development/scripts/validate-handoff.mjs +850 -0
  127. package/canonical/skills/systematic-debugging/SKILL.md +44 -0
  128. package/canonical/skills/systematic-debugging/evals/cases.yaml +90 -0
  129. package/canonical/skills/test-driven-development/SKILL.md +42 -0
  130. package/canonical/skills/test-driven-development/evals/cases.yaml +86 -0
  131. package/canonical/skills/test-driven-development/reference/writing-good-tests.md +52 -0
  132. package/canonical/skills/verification-before-completion/SKILL.md +53 -0
  133. package/canonical/skills/verification-before-completion/evals/cases.yaml +107 -0
  134. package/dist/adapters/content/language-lint.d.ts +46 -0
  135. package/dist/adapters/content/language-lint.js +191 -0
  136. package/dist/adapters/harness/claude-code.d.ts +57 -0
  137. package/dist/adapters/harness/claude-code.js +385 -0
  138. package/dist/adapters/harness/index.d.ts +3 -0
  139. package/dist/adapters/harness/index.js +17 -0
  140. package/dist/adapters/harness/opencode.d.ts +7 -0
  141. package/dist/adapters/harness/opencode.js +166 -0
  142. package/dist/adapters/harness/plugin.d.ts +22 -0
  143. package/dist/adapters/harness/plugin.js +257 -0
  144. package/dist/adapters/memory/doctor.d.ts +480 -0
  145. package/dist/adapters/memory/doctor.js +1217 -0
  146. package/dist/adapters/memory/vendored.d.ts +150 -0
  147. package/dist/adapters/memory/vendored.js +487 -0
  148. package/dist/adapters/package/node.d.ts +9 -0
  149. package/dist/adapters/package/node.js +20 -0
  150. package/dist/adapters/prompt/readline.d.ts +19 -0
  151. package/dist/adapters/prompt/readline.js +53 -0
  152. package/dist/adapters/sync/diff.d.ts +43 -0
  153. package/dist/adapters/sync/diff.js +380 -0
  154. package/dist/cli/cleanup.d.ts +86 -0
  155. package/dist/cli/cleanup.js +382 -0
  156. package/dist/cli/cost.d.ts +304 -0
  157. package/dist/cli/cost.js +501 -0
  158. package/dist/cli/doctor.d.ts +205 -0
  159. package/dist/cli/doctor.js +654 -0
  160. package/dist/cli/executor.d.ts +5 -0
  161. package/dist/cli/executor.js +48 -0
  162. package/dist/cli/plugin-validate.d.ts +37 -0
  163. package/dist/cli/plugin-validate.js +256 -0
  164. package/dist/cli/prefix.d.ts +68 -0
  165. package/dist/cli/prefix.js +218 -0
  166. package/dist/cli/profile.d.ts +170 -0
  167. package/dist/cli/profile.js +285 -0
  168. package/dist/cli/runner.d.ts +10 -0
  169. package/dist/cli/runner.js +27 -0
  170. package/dist/cli/uninstall.d.ts +65 -0
  171. package/dist/cli/uninstall.js +147 -0
  172. package/dist/index.d.ts +8 -0
  173. package/dist/index.js +989 -0
  174. package/dist/infra/dogfood.d.ts +31 -0
  175. package/dist/infra/dogfood.js +51 -0
  176. package/dist/infra/fsutil.d.ts +40 -0
  177. package/dist/infra/fsutil.js +143 -0
  178. package/dist/infra/manifest.d.ts +76 -0
  179. package/dist/infra/manifest.js +92 -0
  180. package/dist/infra/paths.d.ts +19 -0
  181. package/dist/infra/paths.js +74 -0
  182. package/dist/infra/routing.d.ts +4 -0
  183. package/dist/infra/routing.js +7 -0
  184. package/node_modules/@freeharness/core/dist/context.d.ts +30 -0
  185. package/node_modules/@freeharness/core/dist/context.js +1 -0
  186. package/node_modules/@freeharness/core/dist/index.d.ts +5 -0
  187. package/node_modules/@freeharness/core/dist/index.js +6 -0
  188. package/node_modules/@freeharness/core/dist/planner.d.ts +13 -0
  189. package/node_modules/@freeharness/core/dist/planner.js +18 -0
  190. package/node_modules/@freeharness/core/dist/ports.d.ts +90 -0
  191. package/node_modules/@freeharness/core/dist/ports.js +1 -0
  192. package/node_modules/@freeharness/core/dist/registry.d.ts +41 -0
  193. package/node_modules/@freeharness/core/dist/registry.js +124 -0
  194. package/node_modules/@freeharness/core/dist/tiers.d.ts +30 -0
  195. package/node_modules/@freeharness/core/dist/tiers.js +99 -0
  196. package/node_modules/@freeharness/core/package.json +34 -0
  197. package/node_modules/@freeharness/sdd/PROVENANCE.yaml +175 -0
  198. package/node_modules/@freeharness/sdd/dist/src/bin/openspec.d.ts +2 -0
  199. package/node_modules/@freeharness/sdd/dist/src/bin/openspec.js +166 -0
  200. package/node_modules/@freeharness/sdd/dist/src/index.d.ts +14 -0
  201. package/node_modules/@freeharness/sdd/dist/src/index.js +11 -0
  202. package/node_modules/@freeharness/sdd/dist/src/init.d.ts +39 -0
  203. package/node_modules/@freeharness/sdd/dist/src/init.js +190 -0
  204. package/node_modules/@freeharness/sdd/dist/src/root-resolver.d.ts +8 -0
  205. package/node_modules/@freeharness/sdd/dist/src/root-resolver.js +32 -0
  206. package/node_modules/@freeharness/sdd/dist/src/shim/archive.d.ts +81 -0
  207. package/node_modules/@freeharness/sdd/dist/src/shim/archive.js +483 -0
  208. package/node_modules/@freeharness/sdd/dist/src/shim/context.d.ts +4 -0
  209. package/node_modules/@freeharness/sdd/dist/src/shim/context.js +48 -0
  210. package/node_modules/@freeharness/sdd/dist/src/shim/follow-up.d.ts +57 -0
  211. package/node_modules/@freeharness/sdd/dist/src/shim/follow-up.js +279 -0
  212. package/node_modules/@freeharness/sdd/dist/src/shim/instructions.d.ts +67 -0
  213. package/node_modules/@freeharness/sdd/dist/src/shim/instructions.js +460 -0
  214. package/node_modules/@freeharness/sdd/dist/src/shim/list.d.ts +5 -0
  215. package/node_modules/@freeharness/sdd/dist/src/shim/list.js +95 -0
  216. package/node_modules/@freeharness/sdd/dist/src/shim/new-change.d.ts +6 -0
  217. package/node_modules/@freeharness/sdd/dist/src/shim/new-change.js +150 -0
  218. package/node_modules/@freeharness/sdd/dist/src/shim/schemas.d.ts +4 -0
  219. package/node_modules/@freeharness/sdd/dist/src/shim/schemas.js +23 -0
  220. package/node_modules/@freeharness/sdd/dist/src/shim/shared.d.ts +56 -0
  221. package/node_modules/@freeharness/sdd/dist/src/shim/shared.js +140 -0
  222. package/node_modules/@freeharness/sdd/dist/src/shim/status.d.ts +8 -0
  223. package/node_modules/@freeharness/sdd/dist/src/shim/status.js +85 -0
  224. package/node_modules/@freeharness/sdd/dist/src/shim/validate.d.ts +6 -0
  225. package/node_modules/@freeharness/sdd/dist/src/shim/validate.js +229 -0
  226. package/node_modules/@freeharness/sdd/dist/src/validate-change.d.ts +40 -0
  227. package/node_modules/@freeharness/sdd/dist/src/validate-change.js +114 -0
  228. package/node_modules/@freeharness/sdd/dist/src/validate.d.ts +24 -0
  229. package/node_modules/@freeharness/sdd/dist/src/validate.js +72 -0
  230. package/node_modules/@freeharness/sdd/dist/vendor/openspec/apply/specs-apply.d.ts +130 -0
  231. package/node_modules/@freeharness/sdd/dist/vendor/openspec/apply/specs-apply.js +981 -0
  232. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/change-metadata.d.ts +46 -0
  233. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/change-metadata.js +128 -0
  234. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/change-status-policy.d.ts +26 -0
  235. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/change-status-policy.js +32 -0
  236. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/file-system.d.ts +50 -0
  237. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/file-system.js +394 -0
  238. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/global-config.d.ts +15 -0
  239. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/global-config.js +49 -0
  240. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/graph.d.ts +71 -0
  241. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/graph.js +164 -0
  242. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/index.d.ts +11 -0
  243. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/index.js +21 -0
  244. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/instruction-loader.d.ts +102 -0
  245. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/instruction-loader.js +230 -0
  246. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/outputs.d.ts +18 -0
  247. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/outputs.js +138 -0
  248. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/resolver.d.ts +82 -0
  249. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/resolver.js +333 -0
  250. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/schema.d.ts +12 -0
  251. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/schema.js +110 -0
  252. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/state.d.ts +11 -0
  253. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/state.js +32 -0
  254. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/task-progress.d.ts +33 -0
  255. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/task-progress.js +149 -0
  256. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/types.d.ts +39 -0
  257. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/types.js +49 -0
  258. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/adapters/claude.d.ts +12 -0
  259. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/adapters/claude.js +31 -0
  260. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/adapters/index.d.ts +10 -0
  261. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/adapters/index.js +10 -0
  262. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/adapters/opencode.d.ts +12 -0
  263. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/adapters/opencode.js +26 -0
  264. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/generator.d.ts +28 -0
  265. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/generator.js +41 -0
  266. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/index.d.ts +23 -0
  267. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/index.js +25 -0
  268. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/invocation.d.ts +72 -0
  269. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/invocation.js +76 -0
  270. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/registry.d.ts +39 -0
  271. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/registry.js +53 -0
  272. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/types.d.ts +62 -0
  273. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/types.js +7 -0
  274. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/yaml.d.ts +35 -0
  275. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/yaml.js +47 -0
  276. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-references.d.ts +33 -0
  277. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-references.js +55 -0
  278. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/shared/allowed-tools.d.ts +11 -0
  279. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/shared/allowed-tools.js +11 -0
  280. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/shared/skill-generation.d.ts +48 -0
  281. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/shared/skill-generation.js +99 -0
  282. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/skill-templates.d.ts +19 -0
  283. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/skill-templates.js +18 -0
  284. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/types.d.ts +18 -0
  285. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/types.js +4 -0
  286. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/apply-change.d.ts +19 -0
  287. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/apply-change.js +207 -0
  288. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/archive-change.d.ts +12 -0
  289. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/archive-change.js +409 -0
  290. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/bulk-archive-change.d.ts +9 -0
  291. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/bulk-archive-change.js +673 -0
  292. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/continue-change.d.ts +9 -0
  293. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/continue-change.js +230 -0
  294. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/explore.d.ts +12 -0
  295. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/explore.js +550 -0
  296. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/feedback.d.ts +8 -0
  297. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/feedback.js +107 -0
  298. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/ff-change.d.ts +12 -0
  299. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/ff-change.js +228 -0
  300. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/new-change.d.ts +9 -0
  301. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/new-change.js +147 -0
  302. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/onboard.d.ts +9 -0
  303. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/onboard.js +571 -0
  304. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/propose.d.ts +12 -0
  305. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/propose.js +322 -0
  306. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/store-selection.d.ts +7 -0
  307. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/store-selection.js +7 -0
  308. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/sync-specs.d.ts +9 -0
  309. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/sync-specs.js +518 -0
  310. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/update-change.d.ts +9 -0
  311. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/update-change.js +176 -0
  312. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/verify-change.d.ts +9 -0
  313. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/verify-change.js +344 -0
  314. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/constants.d.ts +39 -0
  315. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/constants.js +54 -0
  316. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/delta-resolution.d.ts +35 -0
  317. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/delta-resolution.js +171 -0
  318. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/change-parser.d.ts +27 -0
  319. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/change-parser.js +210 -0
  320. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/code-fence.d.ts +14 -0
  321. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/code-fence.js +48 -0
  322. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/markdown-parser.d.ts +22 -0
  323. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/markdown-parser.js +186 -0
  324. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/requirement-blocks.d.ts +65 -0
  325. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/requirement-blocks.js +409 -0
  326. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/requirement-text.d.ts +55 -0
  327. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/requirement-text.js +98 -0
  328. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/spec-structure.d.ts +8 -0
  329. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/spec-structure.js +77 -0
  330. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/purpose-placeholder.d.ts +44 -0
  331. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/purpose-placeholder.js +116 -0
  332. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/base.schema.d.ts +12 -0
  333. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/base.schema.js +17 -0
  334. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/change.schema.d.ts +72 -0
  335. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/change.schema.js +30 -0
  336. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/index.d.ts +3 -0
  337. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/index.js +3 -0
  338. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/spec.schema.d.ts +17 -0
  339. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/spec.schema.js +14 -0
  340. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/spec-discovery.d.ts +39 -0
  341. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/spec-discovery.js +114 -0
  342. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/task-lines.d.ts +45 -0
  343. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/task-lines.js +105 -0
  344. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/task-numbering.d.ts +15 -0
  345. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/task-numbering.js +56 -0
  346. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/types.d.ts +17 -0
  347. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/types.js +1 -0
  348. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/validator.d.ts +94 -0
  349. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/validator.js +756 -0
  350. package/node_modules/@freeharness/sdd/package.json +57 -0
  351. package/node_modules/@freeharness/sdd/vendor/openspec/LICENSE.upstream +22 -0
  352. package/node_modules/@freeharness/sdd/vendor/openspec/assets/schema.upstream.yaml +232 -0
  353. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/README.md +19 -0
  354. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-apply-change/SKILL.md +187 -0
  355. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-archive-change/SKILL.md +181 -0
  356. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-bulk-archive-change/SKILL.md +338 -0
  357. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-continue-change/SKILL.md +117 -0
  358. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-explore/SKILL.md +342 -0
  359. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-ff-change/SKILL.md +116 -0
  360. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-new-change/SKILL.md +76 -0
  361. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-onboard/SKILL.md +560 -0
  362. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-propose/SKILL.md +162 -0
  363. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-sync-specs/SKILL.md +261 -0
  364. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-update-change/SKILL.md +90 -0
  365. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-verify-change/SKILL.md +174 -0
  366. package/package.json +70 -0
  367. package/provenance/canonical.PROVENANCE.yaml +740 -0
  368. package/provenance/claude-mem.LICENSE.upstream +202 -0
  369. package/provenance/memory.PROVENANCE.yaml +399 -0
  370. package/provenance/sdd.PROVENANCE.yaml +175 -0
  371. package/vendor-licenses/caveman.LICENSE +27 -0
  372. package/vendor-licenses/deepseek-harness.LICENSE +21 -0
  373. package/vendor-licenses/ecc.LICENSE +21 -0
  374. package/vendor-licenses/pi.LICENSE +21 -0
  375. package/vendor-licenses/superpowers.LICENSE +21 -0
@@ -0,0 +1,462 @@
1
+ """
2
+ Analyze MLflow evaluation results and generate actionable insights.
3
+
4
+ This script parses the JSON output from `mlflow traces evaluate` and generates:
5
+ - Pass rate analysis per scorer
6
+ - Failure pattern detection (multi-failure queries)
7
+ - Actionable recommendations
8
+ - Markdown evaluation report (NOT HTML)
9
+
10
+ Usage:
11
+ python scripts/analyze_results.py evaluation_results.json
12
+
13
+ # Or with custom output file
14
+ python scripts/analyze_results.py evaluation_results.json --output report.md
15
+ """
16
+
17
+ import json
18
+ import re
19
+ import sys
20
+ from collections import defaultdict
21
+ from datetime import datetime
22
+ from typing import Any
23
+
24
+
25
+ def strip_ansi_codes(text: str) -> str:
26
+ """Remove ANSI escape sequences from text.
27
+
28
+ This handles color codes, cursor movement, and other terminal control sequences
29
+ that may appear in mlflow traces evaluate output.
30
+
31
+ Args:
32
+ text: Text that may contain ANSI escape sequences
33
+
34
+ Returns:
35
+ Text with all ANSI escape sequences removed
36
+ """
37
+ # Standard ANSI escape sequence pattern
38
+ # Matches: ESC [ <parameters> <command>
39
+ ansi_escape = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])')
40
+ return ansi_escape.sub('', text)
41
+
42
+
43
+ def load_evaluation_results(json_file: str) -> list[dict[str, Any]]:
44
+ """Load evaluation results from JSON file, skipping console output.
45
+
46
+ Handles mlflow traces evaluate output which contains:
47
+ - Lines 1-N: Console output (progress bars, warnings, logging)
48
+ - Line N+1: Start of JSON array '['
49
+ """
50
+ try:
51
+ with open(json_file) as f:
52
+ content = f.read()
53
+
54
+ # Strip ANSI codes before processing
55
+ content = strip_ansi_codes(content)
56
+
57
+ # Find the start of JSON array (skip console output)
58
+ json_start = content.find("[")
59
+ if json_start == -1:
60
+ print("✗ No JSON array found in file")
61
+ sys.exit(1)
62
+
63
+ json_content = content[json_start:]
64
+ data = json.loads(json_content)
65
+
66
+ if not isinstance(data, list):
67
+ print(f"✗ Expected JSON array, got {type(data).__name__}")
68
+ sys.exit(1)
69
+
70
+ return data
71
+
72
+ except FileNotFoundError:
73
+ print(f"✗ File not found: {json_file}")
74
+ sys.exit(1)
75
+ except json.JSONDecodeError as e:
76
+ print(f"✗ Invalid JSON starting at position {json_start}: {e}")
77
+ print(f" First 100 chars: {json_content[:100]}")
78
+ sys.exit(1)
79
+
80
+
81
+ def extract_scorer_results(data: list[dict[str, Any]]) -> dict[str, list[dict]]:
82
+ """Extract scorer results from assessments array structure.
83
+
84
+ Parses the actual mlflow traces evaluate structure:
85
+ [{
86
+ "trace_id": "tr-...",
87
+ "assessments": [
88
+ {"name": "scorer", "result": "yes/no/pass/fail", "rationale": "...", "error": null}
89
+ ]
90
+ }]
91
+
92
+ Returns:
93
+ Dictionary mapping scorer names to list of result dictionaries.
94
+ Each result dict contains: {query, trace_id, passed, rationale}
95
+ """
96
+ scorer_results = defaultdict(list)
97
+
98
+ for trace_result in data:
99
+ trace_id = trace_result.get("trace_id", "unknown")
100
+
101
+ # Extract query from inputs if available
102
+ inputs = trace_result.get("inputs", {})
103
+ query = inputs.get("query", inputs.get("question", "unknown"))
104
+
105
+ # Parse assessments array
106
+ assessments = trace_result.get("assessments", [])
107
+
108
+ for assessment in assessments:
109
+ scorer_name = assessment.get("name", "unknown")
110
+ result = assessment.get("result", "fail")
111
+ result_str = result.lower() if result else "fail"
112
+ rationale = assessment.get("rationale", "")
113
+ error = assessment.get("error")
114
+
115
+ # Map string results to boolean
116
+ # "yes" / "pass" → True
117
+ # "no" / "fail" → False
118
+ passed = result_str in ["yes", "pass"]
119
+
120
+ # Skip if there was an error
121
+ if error:
122
+ print(f" ⚠ Warning: Scorer {scorer_name} had error for trace {trace_id}: {error}")
123
+ continue
124
+
125
+ scorer_results[scorer_name].append(
126
+ {"query": query, "trace_id": trace_id, "passed": passed, "rationale": rationale}
127
+ )
128
+
129
+ return scorer_results
130
+
131
+
132
+ def calculate_pass_rates(scorer_results: dict[str, list[dict]]) -> dict[str, dict]:
133
+ """Calculate pass rates for each scorer.
134
+
135
+ Returns:
136
+ Dictionary mapping scorer names to {pass_rate, passed, total, grade}
137
+ """
138
+ pass_rates = {}
139
+
140
+ for scorer_name, results in scorer_results.items():
141
+ total = len(results)
142
+ passed = sum(1 for r in results if r["passed"])
143
+ pass_rate = (passed / total * 100) if total > 0 else 0
144
+
145
+ # Assign grade
146
+ if pass_rate >= 90:
147
+ grade = "A"
148
+ emoji = "✓✓"
149
+ elif pass_rate >= 80:
150
+ grade = "B"
151
+ emoji = "✓"
152
+ elif pass_rate >= 70:
153
+ grade = "C"
154
+ emoji = "⚠"
155
+ elif pass_rate >= 60:
156
+ grade = "D"
157
+ emoji = "⚠⚠"
158
+ else:
159
+ grade = "F"
160
+ emoji = "✗"
161
+
162
+ pass_rates[scorer_name] = {
163
+ "pass_rate": pass_rate,
164
+ "passed": passed,
165
+ "total": total,
166
+ "grade": grade,
167
+ "emoji": emoji,
168
+ }
169
+
170
+ return pass_rates
171
+
172
+
173
+ def detect_failure_patterns(scorer_results: dict[str, list[dict]]) -> list[dict]:
174
+ """Detect patterns in failed queries.
175
+
176
+ Returns:
177
+ List of pattern dictionaries with {name, queries, scorers, description}
178
+ """
179
+ patterns = []
180
+
181
+ # Collect all failures
182
+ failures_by_query = defaultdict(list)
183
+
184
+ for scorer_name, results in scorer_results.items():
185
+ for result in results:
186
+ if not result["passed"]:
187
+ failures_by_query[result["query"]].append(
188
+ {
189
+ "scorer": scorer_name,
190
+ "rationale": result["rationale"],
191
+ "trace_id": result["trace_id"],
192
+ }
193
+ )
194
+
195
+ # Pattern: Multi-failure queries (queries failing 3+ scorers)
196
+ multi_failures = []
197
+ for query, failures in failures_by_query.items():
198
+ if len(failures) >= 3:
199
+ multi_failures.append(
200
+ {"query": query, "scorers": [f["scorer"] for f in failures], "count": len(failures)}
201
+ )
202
+
203
+ if multi_failures:
204
+ patterns.append(
205
+ {
206
+ "name": "Multi-Failure Queries",
207
+ "description": "Queries failing 3 or more scorers - need comprehensive fixes",
208
+ "queries": multi_failures,
209
+ "priority": "CRITICAL",
210
+ }
211
+ )
212
+
213
+ return patterns
214
+
215
+
216
+ def generate_recommendations(pass_rates: dict[str, dict], patterns: list[dict]) -> list[dict]:
217
+ """Generate actionable recommendations based on analysis.
218
+
219
+ Returns:
220
+ List of recommendation dictionaries with {title, issue, impact, effort, priority}
221
+ """
222
+ recommendations = []
223
+
224
+ # Recommendations from low-performing scorers
225
+ for scorer_name, metrics in pass_rates.items():
226
+ if metrics["pass_rate"] < 80:
227
+ recommendations.append(
228
+ {
229
+ "title": f"Improve {scorer_name} performance",
230
+ "issue": f"Only {metrics['pass_rate']:.1f}% pass rate ({metrics['passed']}/{metrics['total']})",
231
+ "impact": "Will improve overall evaluation quality",
232
+ "effort": "Medium",
233
+ "priority": "HIGH" if metrics["pass_rate"] < 70 else "MEDIUM",
234
+ }
235
+ )
236
+
237
+ # Recommendations from patterns
238
+ for pattern in patterns:
239
+ if pattern["priority"] == "CRITICAL":
240
+ recommendations.append(
241
+ {
242
+ "title": f"Fix {pattern['name'].lower()}",
243
+ "issue": f"{len(pattern['queries'])} queries failing multiple scorers",
244
+ "impact": "Critical for baseline quality",
245
+ "effort": "High",
246
+ "priority": "CRITICAL",
247
+ }
248
+ )
249
+ elif len(pattern["queries"]) >= 3:
250
+ recommendations.append(
251
+ {
252
+ "title": f"Address {pattern['name'].lower()}",
253
+ "issue": pattern["description"],
254
+ "impact": f"Affects {len(pattern['queries'])} queries",
255
+ "effort": "Medium",
256
+ "priority": "HIGH",
257
+ }
258
+ )
259
+
260
+ # Sort by priority
261
+ priority_order = {"CRITICAL": 0, "HIGH": 1, "MEDIUM": 2, "LOW": 3}
262
+ recommendations.sort(key=lambda x: priority_order.get(x["priority"], 99))
263
+
264
+ return recommendations
265
+
266
+
267
+ def generate_report(
268
+ scorer_results: dict[str, list[dict]],
269
+ pass_rates: dict[str, dict],
270
+ patterns: list[dict],
271
+ recommendations: list[dict],
272
+ output_file: str,
273
+ ) -> None:
274
+ """Generate markdown evaluation report."""
275
+
276
+ total_queries = len(next(iter(scorer_results.values()))) if scorer_results else 0
277
+ timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
278
+
279
+ report_lines = [
280
+ "# Agent Evaluation Results Analysis",
281
+ "",
282
+ f"**Generated**: {timestamp}",
283
+ f"**Dataset**: {total_queries} queries evaluated",
284
+ f"**Scorers**: {len(scorer_results)} ({', '.join(scorer_results.keys())})",
285
+ "",
286
+ "## Overall Pass Rates",
287
+ "",
288
+ ]
289
+
290
+ # Pass rates table
291
+ for scorer_name, metrics in pass_rates.items():
292
+ emoji = metrics["emoji"]
293
+ report_lines.append(
294
+ f" {scorer_name:30} {metrics['pass_rate']:5.1f}% ({metrics['passed']}/{metrics['total']}) {emoji}"
295
+ )
296
+
297
+ report_lines.extend(["", ""])
298
+
299
+ # Average pass rate
300
+ avg_pass_rate = (
301
+ sum(m["pass_rate"] for m in pass_rates.values()) / len(pass_rates) if pass_rates else 0
302
+ )
303
+ report_lines.append(f"**Average Pass Rate**: {avg_pass_rate:.1f}%")
304
+ report_lines.extend(["", ""])
305
+
306
+ # Failure patterns
307
+ if patterns:
308
+ report_lines.extend(["## Failure Patterns Detected", ""])
309
+
310
+ for i, pattern in enumerate(patterns, 1):
311
+ report_lines.extend(
312
+ [
313
+ f"### {i}. {pattern['name']} [{pattern['priority']}]",
314
+ "",
315
+ f"**Description**: {pattern['description']}",
316
+ "",
317
+ f"**Affected Queries**: {len(pattern['queries'])}",
318
+ "",
319
+ ]
320
+ )
321
+
322
+ for query_info in pattern["queries"][:5]: # Show first 5
323
+ report_lines.append(
324
+ f'- **Query**: "{query_info["query"][:100]}{"..." if len(query_info["query"]) > 100 else ""}"'
325
+ )
326
+ report_lines.append(f" - Failed scorers: {', '.join(query_info['scorers'])}")
327
+ report_lines.append("")
328
+
329
+ if len(pattern["queries"]) > 5:
330
+ report_lines.append(f" _(+{len(pattern['queries']) - 5} more queries)_")
331
+ report_lines.append("")
332
+
333
+ report_lines.append("")
334
+
335
+ # Recommendations
336
+ if recommendations:
337
+ report_lines.extend(["## Recommendations", ""])
338
+
339
+ for i, rec in enumerate(recommendations, 1):
340
+ report_lines.extend(
341
+ [
342
+ f"### {i}. {rec['title']} [{rec['priority']}]",
343
+ "",
344
+ f"- **Issue**: {rec['issue']}",
345
+ f"- **Expected Impact**: {rec['impact']}",
346
+ f"- **Effort**: {rec['effort']}",
347
+ "",
348
+ ]
349
+ )
350
+
351
+ # Next steps
352
+ report_lines.extend(
353
+ [
354
+ "## Next Steps",
355
+ "",
356
+ "1. Address CRITICAL and HIGH priority recommendations first",
357
+ "2. Re-run evaluation after implementing fixes",
358
+ "3. Compare results to measure improvement",
359
+ "4. Consider expanding dataset to cover identified gaps",
360
+ "",
361
+ "---",
362
+ "",
363
+ f"**Report Generated**: {timestamp}",
364
+ "**Evaluation Framework**: MLflow Agent Evaluation",
365
+ "",
366
+ ]
367
+ )
368
+
369
+ # Write report
370
+ with open(output_file, "w") as f:
371
+ f.write("\n".join(report_lines))
372
+
373
+ print(f"\n✓ Report saved to: {output_file}")
374
+
375
+
376
+ def main():
377
+ """Main analysis workflow."""
378
+ print("=" * 60)
379
+ print("MLflow Evaluation Results Analysis")
380
+ print("=" * 60)
381
+ print()
382
+
383
+ # Parse arguments
384
+ if len(sys.argv) < 2:
385
+ print(
386
+ "Usage: python scripts/analyze_results.py <evaluation_results.json> [--output report.md]"
387
+ )
388
+ sys.exit(1)
389
+
390
+ json_file = sys.argv[1]
391
+ output_file = "evaluation_report.md"
392
+
393
+ if "--output" in sys.argv:
394
+ idx = sys.argv.index("--output")
395
+ if idx + 1 < len(sys.argv):
396
+ output_file = sys.argv[idx + 1]
397
+
398
+ # Load results
399
+ print(f"Loading evaluation results from: {json_file}")
400
+ data = load_evaluation_results(json_file)
401
+ print("✓ Results loaded")
402
+ print()
403
+
404
+ # Extract scorer results
405
+ print("Extracting scorer results...")
406
+ scorer_results = extract_scorer_results(data)
407
+
408
+ if not scorer_results:
409
+ print("✗ No scorer results found in JSON")
410
+ print(" Check that the JSON file contains evaluation results")
411
+ sys.exit(1)
412
+
413
+ print(f"✓ Found {len(scorer_results)} scorer(s)")
414
+ print()
415
+
416
+ # Calculate pass rates
417
+ print("Calculating pass rates...")
418
+ pass_rates = calculate_pass_rates(scorer_results)
419
+
420
+ print("\nOverall Pass Rates:")
421
+ for scorer_name, metrics in pass_rates.items():
422
+ emoji = metrics["emoji"]
423
+ print(
424
+ f" {scorer_name:30} {metrics['pass_rate']:5.1f}% ({metrics['passed']}/{metrics['total']}) {emoji}"
425
+ )
426
+ print()
427
+
428
+ # Detect patterns
429
+ print("Detecting failure patterns...")
430
+ patterns = detect_failure_patterns(scorer_results)
431
+
432
+ if patterns:
433
+ print(f"✓ Found {len(patterns)} pattern(s)")
434
+ for pattern in patterns:
435
+ print(
436
+ f" - {pattern['name']}: {len(pattern['queries'])} queries [{pattern['priority']}]"
437
+ )
438
+ else:
439
+ print(" No significant patterns detected")
440
+ print()
441
+
442
+ # Generate recommendations
443
+ print("Generating recommendations...")
444
+ recommendations = generate_recommendations(pass_rates, patterns)
445
+ print(f"✓ Generated {len(recommendations)} recommendation(s)")
446
+ print()
447
+
448
+ # Generate report
449
+ print("Generating markdown report...")
450
+ generate_report(scorer_results, pass_rates, patterns, recommendations, output_file)
451
+ print()
452
+
453
+ print("=" * 60)
454
+ print("Analysis Complete")
455
+ print("=" * 60)
456
+ print()
457
+ print(f"Review the report at: {output_file}")
458
+ print()
459
+
460
+
461
+ if __name__ == "__main__":
462
+ main()