@rpamis/comet 0.4.0-beta.3 → 0.4.0-beta.4

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 (508) hide show
  1. package/README.md +10 -0
  2. package/assets/manifest.json +2 -1
  3. package/assets/skills/comet/SKILL.md +25 -1
  4. package/assets/skills/comet/reference/comet-yaml-fields.md +5 -2
  5. package/assets/skills/comet/reference/context-recovery.md +10 -0
  6. package/assets/skills/comet/reference/scripts.md +47 -15
  7. package/assets/skills/comet/rules/comet-phase-guard.en.md +8 -0
  8. package/assets/skills/comet/rules/comet-phase-guard.md +9 -1
  9. package/assets/skills/comet/scripts/comet-resume-probe.mjs +3 -0
  10. package/assets/skills/comet/scripts/comet-runtime.mjs +1387 -424
  11. package/assets/skills/comet-archive/SKILL.md +24 -11
  12. package/assets/skills/comet-build/SKILL.md +42 -25
  13. package/assets/skills/comet-design/SKILL.md +1 -0
  14. package/assets/skills/comet-hotfix/SKILL.md +3 -1
  15. package/assets/skills/comet-open/SKILL.md +11 -1
  16. package/assets/skills/comet-tweak/SKILL.md +3 -1
  17. package/assets/skills/comet-verify/SKILL.md +29 -20
  18. package/assets/skills-zh/comet/SKILL.md +25 -1
  19. package/assets/skills-zh/comet/reference/comet-yaml-fields.md +5 -2
  20. package/assets/skills-zh/comet/reference/context-recovery.md +10 -0
  21. package/assets/skills-zh/comet/reference/scripts.md +47 -15
  22. package/assets/skills-zh/comet-archive/SKILL.md +24 -11
  23. package/assets/skills-zh/comet-build/SKILL.md +42 -25
  24. package/assets/skills-zh/comet-design/SKILL.md +1 -0
  25. package/assets/skills-zh/comet-hotfix/SKILL.md +3 -1
  26. package/assets/skills-zh/comet-open/SKILL.md +11 -1
  27. package/assets/skills-zh/comet-tweak/SKILL.md +3 -1
  28. package/assets/skills-zh/comet-verify/SKILL.md +30 -21
  29. package/dist/app/cli/comet-banner.d.ts +25 -0
  30. package/dist/app/cli/comet-banner.d.ts.map +1 -0
  31. package/dist/app/cli/comet-banner.js +265 -0
  32. package/dist/app/cli/comet-banner.js.map +1 -0
  33. package/dist/app/cli/index.js +36 -2
  34. package/dist/app/cli/index.js.map +1 -1
  35. package/dist/app/commands/classic.d.ts +4 -0
  36. package/dist/app/commands/classic.d.ts.map +1 -0
  37. package/dist/app/commands/classic.js +11 -0
  38. package/dist/app/commands/classic.js.map +1 -0
  39. package/dist/app/commands/doctor.d.ts.map +1 -1
  40. package/dist/app/commands/doctor.js +39 -24
  41. package/dist/app/commands/doctor.js.map +1 -1
  42. package/dist/app/commands/eval.d.ts.map +1 -1
  43. package/dist/app/commands/eval.js +57 -20
  44. package/dist/app/commands/eval.js.map +1 -1
  45. package/dist/app/commands/i18n.d.ts +1 -1
  46. package/dist/app/commands/i18n.d.ts.map +1 -1
  47. package/dist/app/commands/i18n.js +12 -4
  48. package/dist/app/commands/i18n.js.map +1 -1
  49. package/dist/app/commands/init.d.ts.map +1 -1
  50. package/dist/app/commands/init.js +16 -13
  51. package/dist/app/commands/init.js.map +1 -1
  52. package/dist/app/commands/project-scope-selection.d.ts +13 -0
  53. package/dist/app/commands/project-scope-selection.d.ts.map +1 -0
  54. package/dist/app/commands/project-scope-selection.js +33 -0
  55. package/dist/app/commands/project-scope-selection.js.map +1 -0
  56. package/dist/app/commands/resume-probe.d.ts +11 -0
  57. package/dist/app/commands/resume-probe.d.ts.map +1 -0
  58. package/dist/app/commands/resume-probe.js +63 -0
  59. package/dist/app/commands/resume-probe.js.map +1 -0
  60. package/dist/app/commands/status.d.ts +31 -0
  61. package/dist/app/commands/status.d.ts.map +1 -1
  62. package/dist/app/commands/status.js +109 -20
  63. package/dist/app/commands/status.js.map +1 -1
  64. package/dist/app/commands/uninstall.d.ts +2 -0
  65. package/dist/app/commands/uninstall.d.ts.map +1 -1
  66. package/dist/app/commands/uninstall.js +217 -40
  67. package/dist/app/commands/uninstall.js.map +1 -1
  68. package/dist/app/commands/update.d.ts +6 -0
  69. package/dist/app/commands/update.d.ts.map +1 -1
  70. package/dist/app/commands/update.js +361 -68
  71. package/dist/app/commands/update.js.map +1 -1
  72. package/dist/config/repository-layout.json +4 -2
  73. package/dist/domains/bundle/bundle-platform.d.ts.map +1 -1
  74. package/dist/domains/bundle/bundle-platform.js +3 -1
  75. package/dist/domains/bundle/bundle-platform.js.map +1 -1
  76. package/dist/domains/bundle/eval-manifest-runtime.d.ts +6 -0
  77. package/dist/domains/bundle/eval-manifest-runtime.d.ts.map +1 -0
  78. package/dist/domains/bundle/eval-manifest-runtime.js +58 -0
  79. package/dist/domains/bundle/eval-manifest-runtime.js.map +1 -0
  80. package/dist/domains/bundle/types.d.ts +1 -1
  81. package/dist/domains/bundle/types.d.ts.map +1 -1
  82. package/dist/domains/comet-classic/classic-archive.d.ts +1 -0
  83. package/dist/domains/comet-classic/classic-archive.d.ts.map +1 -1
  84. package/dist/domains/comet-classic/classic-archive.js +35 -38
  85. package/dist/domains/comet-classic/classic-archive.js.map +1 -1
  86. package/dist/domains/comet-classic/classic-cli.d.ts +1 -1
  87. package/dist/domains/comet-classic/classic-cli.d.ts.map +1 -1
  88. package/dist/domains/comet-classic/classic-cli.js +3 -0
  89. package/dist/domains/comet-classic/classic-cli.js.map +1 -1
  90. package/dist/domains/comet-classic/classic-command-checks.d.ts +20 -0
  91. package/dist/domains/comet-classic/classic-command-checks.d.ts.map +1 -0
  92. package/dist/domains/comet-classic/classic-command-checks.js +97 -0
  93. package/dist/domains/comet-classic/classic-command-checks.js.map +1 -0
  94. package/dist/domains/comet-classic/classic-current-change.d.ts +19 -0
  95. package/dist/domains/comet-classic/classic-current-change.d.ts.map +1 -0
  96. package/dist/domains/comet-classic/classic-current-change.js +132 -0
  97. package/dist/domains/comet-classic/classic-current-change.js.map +1 -0
  98. package/dist/domains/comet-classic/classic-diagnostics.d.ts +2 -1
  99. package/dist/domains/comet-classic/classic-diagnostics.d.ts.map +1 -1
  100. package/dist/domains/comet-classic/classic-diagnostics.js +54 -1
  101. package/dist/domains/comet-classic/classic-diagnostics.js.map +1 -1
  102. package/dist/domains/comet-classic/classic-evidence.d.ts.map +1 -1
  103. package/dist/domains/comet-classic/classic-evidence.js +4 -0
  104. package/dist/domains/comet-classic/classic-evidence.js.map +1 -1
  105. package/dist/domains/comet-classic/classic-guard.d.ts.map +1 -1
  106. package/dist/domains/comet-classic/classic-guard.js +68 -69
  107. package/dist/domains/comet-classic/classic-guard.js.map +1 -1
  108. package/dist/domains/comet-classic/classic-hook-guard.d.ts.map +1 -1
  109. package/dist/domains/comet-classic/classic-hook-guard.js +66 -23
  110. package/dist/domains/comet-classic/classic-hook-guard.js.map +1 -1
  111. package/dist/domains/comet-classic/classic-project-config.d.ts +16 -0
  112. package/dist/domains/comet-classic/classic-project-config.d.ts.map +1 -0
  113. package/dist/domains/comet-classic/classic-project-config.js +40 -0
  114. package/dist/domains/comet-classic/classic-project-config.js.map +1 -0
  115. package/dist/domains/comet-classic/classic-resolver.d.ts.map +1 -1
  116. package/dist/domains/comet-classic/classic-resolver.js +3 -3
  117. package/dist/domains/comet-classic/classic-resolver.js.map +1 -1
  118. package/dist/domains/comet-classic/classic-resume-probe-command.d.ts +3 -0
  119. package/dist/domains/comet-classic/classic-resume-probe-command.d.ts.map +1 -0
  120. package/dist/domains/comet-classic/classic-resume-probe-command.js +58 -0
  121. package/dist/domains/comet-classic/classic-resume-probe-command.js.map +1 -0
  122. package/dist/domains/comet-classic/classic-resume-probe-entry.d.ts +2 -0
  123. package/dist/domains/comet-classic/classic-resume-probe-entry.d.ts.map +1 -0
  124. package/dist/domains/comet-classic/classic-resume-probe-entry.js +4 -0
  125. package/dist/domains/comet-classic/classic-resume-probe-entry.js.map +1 -0
  126. package/dist/domains/comet-classic/classic-resume-probe.d.ts +29 -0
  127. package/dist/domains/comet-classic/classic-resume-probe.d.ts.map +1 -0
  128. package/dist/domains/comet-classic/classic-resume-probe.js +386 -0
  129. package/dist/domains/comet-classic/classic-resume-probe.js.map +1 -0
  130. package/dist/domains/comet-classic/classic-runtime-run.d.ts +2 -1
  131. package/dist/domains/comet-classic/classic-runtime-run.d.ts.map +1 -1
  132. package/dist/domains/comet-classic/classic-runtime-run.js +38 -0
  133. package/dist/domains/comet-classic/classic-runtime-run.js.map +1 -1
  134. package/dist/domains/comet-classic/classic-state-command.d.ts.map +1 -1
  135. package/dist/domains/comet-classic/classic-state-command.js +128 -12
  136. package/dist/domains/comet-classic/classic-state-command.js.map +1 -1
  137. package/dist/domains/comet-classic/classic-state.d.ts +3 -1
  138. package/dist/domains/comet-classic/classic-state.d.ts.map +1 -1
  139. package/dist/domains/comet-classic/classic-state.js +4 -0
  140. package/dist/domains/comet-classic/classic-state.js.map +1 -1
  141. package/dist/domains/comet-classic/classic-store.d.ts +4 -1
  142. package/dist/domains/comet-classic/classic-store.d.ts.map +1 -1
  143. package/dist/domains/comet-classic/classic-store.js +4 -3
  144. package/dist/domains/comet-classic/classic-store.js.map +1 -1
  145. package/dist/domains/comet-classic/classic-transitions.d.ts +1 -1
  146. package/dist/domains/comet-classic/classic-transitions.d.ts.map +1 -1
  147. package/dist/domains/comet-classic/classic-transitions.js +20 -1
  148. package/dist/domains/comet-classic/classic-transitions.js.map +1 -1
  149. package/dist/domains/comet-classic/classic-validate-command.d.ts.map +1 -1
  150. package/dist/domains/comet-classic/classic-validate-command.js +1 -0
  151. package/dist/domains/comet-classic/classic-validate-command.js.map +1 -1
  152. package/dist/domains/comet-classic/index.d.ts +3 -0
  153. package/dist/domains/comet-classic/index.d.ts.map +1 -1
  154. package/dist/domains/comet-classic/index.js +3 -0
  155. package/dist/domains/comet-classic/index.js.map +1 -1
  156. package/dist/domains/dashboard/collector.js +10 -2
  157. package/dist/domains/dashboard/collector.js.map +1 -1
  158. package/dist/domains/dashboard/web/assets/{index-CjU3VXVu.js → index-CIvN-PL8.js} +11 -11
  159. package/dist/domains/dashboard/web/assets/{index-BcO3_QlT.css → index-DcyRPBnT.css} +1 -1
  160. package/dist/domains/dashboard/web/index.html +2 -2
  161. package/dist/domains/engine/types.d.ts +1 -1
  162. package/dist/domains/engine/types.d.ts.map +1 -1
  163. package/dist/domains/integrations/openspec.d.ts.map +1 -1
  164. package/dist/domains/integrations/openspec.js +6 -6
  165. package/dist/domains/integrations/openspec.js.map +1 -1
  166. package/dist/domains/skill/find.d.ts.map +1 -1
  167. package/dist/domains/skill/find.js +1 -6
  168. package/dist/domains/skill/find.js.map +1 -1
  169. package/dist/domains/skill/managed-markdown.d.ts +14 -0
  170. package/dist/domains/skill/managed-markdown.d.ts.map +1 -0
  171. package/dist/domains/skill/managed-markdown.js +126 -0
  172. package/dist/domains/skill/managed-markdown.js.map +1 -0
  173. package/dist/domains/skill/platform-install.d.ts +4 -3
  174. package/dist/domains/skill/platform-install.d.ts.map +1 -1
  175. package/dist/domains/skill/platform-install.js +96 -26
  176. package/dist/domains/skill/platform-install.js.map +1 -1
  177. package/dist/domains/skill/project-instructions.d.ts +22 -0
  178. package/dist/domains/skill/project-instructions.d.ts.map +1 -0
  179. package/dist/domains/skill/project-instructions.js +61 -0
  180. package/dist/domains/skill/project-instructions.js.map +1 -0
  181. package/dist/domains/skill/uninstall.d.ts +3 -1
  182. package/dist/domains/skill/uninstall.d.ts.map +1 -1
  183. package/dist/domains/skill/uninstall.js +86 -39
  184. package/dist/domains/skill/uninstall.js.map +1 -1
  185. package/dist/platform/install/detect.d.ts +2 -1
  186. package/dist/platform/install/detect.d.ts.map +1 -1
  187. package/dist/platform/install/detect.js +10 -1
  188. package/dist/platform/install/detect.js.map +1 -1
  189. package/dist/platform/install/platforms.d.ts +5 -1
  190. package/dist/platform/install/platforms.d.ts.map +1 -1
  191. package/dist/platform/install/platforms.js +21 -4
  192. package/dist/platform/install/platforms.js.map +1 -1
  193. package/dist/platform/install/project-registry.d.ts +37 -0
  194. package/dist/platform/install/project-registry.d.ts.map +1 -0
  195. package/dist/platform/install/project-registry.js +205 -0
  196. package/dist/platform/install/project-registry.js.map +1 -0
  197. package/eval/.env +28 -0
  198. package/eval/.env.example +52 -0
  199. package/eval/CLAUDE.md +43 -0
  200. package/eval/README.md +538 -0
  201. package/eval/langsmith/.env.example +16 -0
  202. package/eval/langsmith/README.md +93 -0
  203. package/eval/langsmith/skills/README.md +5 -0
  204. package/eval/langsmith/tasks/README.md +5 -0
  205. package/eval/langsmith/tests/conftest.py +187 -0
  206. package/eval/langsmith/tests/tasks/test_tasks.py +287 -0
  207. package/eval/langsmith/treatments/README.md +5 -0
  208. package/eval/local/README.md +80 -0
  209. package/eval/local/regression_baseline.json +13 -0
  210. package/eval/local/report-style-demo-assets/quality_cost.en.svg +41 -0
  211. package/eval/local/report-style-demo-assets/quality_cost.zh.svg +41 -0
  212. package/eval/local/report-style-demo-assets/rubric_delta.en.svg +56 -0
  213. package/eval/local/report-style-demo-assets/rubric_delta.zh.svg +56 -0
  214. package/eval/local/report-style-demo-assets/task_outcomes.en.svg +46 -0
  215. package/eval/local/report-style-demo-assets/task_outcomes.zh.svg +46 -0
  216. package/eval/local/report-style-demo.html +867 -0
  217. package/eval/local/scripts/compare_baselines.py +1018 -0
  218. package/eval/local/scripts/generate_report_style_demo_charts.py +322 -0
  219. package/eval/local/scripts/regression_check.py +171 -0
  220. package/eval/local/scripts/render_readme_benchmark_figures.py +416 -0
  221. package/eval/local/scripts/rescore_rubric.py +120 -0
  222. package/eval/local/skills/benchmarks/039-release/comet-classic-039/SKILL.md +282 -0
  223. package/eval/local/skills/benchmarks/039-release/comet-classic-039/reference/auto-transition.md +27 -0
  224. package/eval/local/skills/benchmarks/039-release/comet-classic-039/reference/comet-yaml-fields.md +68 -0
  225. package/eval/local/skills/benchmarks/039-release/comet-classic-039/reference/context-recovery.md +35 -0
  226. package/eval/local/skills/benchmarks/039-release/comet-classic-039/reference/debug-gate.md +17 -0
  227. package/eval/local/skills/benchmarks/039-release/comet-classic-039/reference/decision-point.md +20 -0
  228. package/eval/local/skills/benchmarks/039-release/comet-classic-039/reference/dirty-worktree.md +59 -0
  229. package/eval/local/skills/benchmarks/039-release/comet-classic-039/reference/file-structure.md +28 -0
  230. package/eval/local/skills/benchmarks/039-release/comet-classic-039/reference/subagent-dispatch.md +113 -0
  231. package/eval/local/skills/benchmarks/039-release/comet-classic-039/rules/comet-phase-guard.md +125 -0
  232. package/eval/local/skills/benchmarks/039-release/comet-classic-039/scripts/comet-archive.sh +311 -0
  233. package/eval/local/skills/benchmarks/039-release/comet-classic-039/scripts/comet-env.sh +110 -0
  234. package/eval/local/skills/benchmarks/039-release/comet-classic-039/scripts/comet-guard.sh +778 -0
  235. package/eval/local/skills/benchmarks/039-release/comet-classic-039/scripts/comet-handoff.sh +390 -0
  236. package/eval/local/skills/benchmarks/039-release/comet-classic-039/scripts/comet-hook-guard.sh +336 -0
  237. package/eval/local/skills/benchmarks/039-release/comet-classic-039/scripts/comet-state.sh +1338 -0
  238. package/eval/local/skills/benchmarks/039-release/comet-classic-039/scripts/comet-yaml-validate.sh +225 -0
  239. package/eval/local/skills/benchmarks/039-release/comet-classic-039-archive/SKILL.md +100 -0
  240. package/eval/local/skills/benchmarks/039-release/comet-classic-039-build/SKILL.md +304 -0
  241. package/eval/local/skills/benchmarks/039-release/comet-classic-039-design/SKILL.md +263 -0
  242. package/eval/local/skills/benchmarks/039-release/comet-classic-039-hotfix/SKILL.md +204 -0
  243. package/eval/local/skills/benchmarks/039-release/comet-classic-039-open/SKILL.md +220 -0
  244. package/eval/local/skills/benchmarks/039-release/comet-classic-039-tweak/SKILL.md +180 -0
  245. package/eval/local/skills/benchmarks/039-release/comet-classic-039-verify/SKILL.md +234 -0
  246. package/eval/local/skills/benchmarks/040-beta/comet/SKILL.md +261 -0
  247. package/eval/local/skills/benchmarks/040-beta/comet/reference/auto-transition.md +27 -0
  248. package/eval/local/skills/benchmarks/040-beta/comet/reference/comet-yaml-fields.md +73 -0
  249. package/eval/local/skills/benchmarks/040-beta/comet/reference/context-recovery.md +45 -0
  250. package/eval/local/skills/benchmarks/040-beta/comet/reference/debug-gate.md +33 -0
  251. package/eval/local/skills/benchmarks/040-beta/comet/reference/decision-point.md +31 -0
  252. package/eval/local/skills/benchmarks/040-beta/comet/reference/dirty-worktree.md +59 -0
  253. package/eval/local/skills/benchmarks/040-beta/comet/reference/file-structure.md +28 -0
  254. package/eval/local/skills/benchmarks/040-beta/comet/reference/intent-frame.md +74 -0
  255. package/eval/local/skills/benchmarks/040-beta/comet/reference/scripts.md +69 -0
  256. package/eval/local/skills/benchmarks/040-beta/comet/reference/subagent-dispatch.md +169 -0
  257. package/eval/local/skills/benchmarks/040-beta/comet/rules/comet-phase-guard.md +130 -0
  258. package/eval/local/skills/benchmarks/040-beta/comet/runtime/classic/checks.yaml +6 -0
  259. package/eval/local/skills/benchmarks/040-beta/comet/runtime/classic/guardrails.yaml +13 -0
  260. package/eval/local/skills/benchmarks/040-beta/comet/runtime/classic/skill.yaml +122 -0
  261. package/eval/local/skills/benchmarks/040-beta/comet/scripts/comet-archive.mjs +9515 -0
  262. package/eval/local/skills/benchmarks/040-beta/comet/scripts/comet-env.mjs +15 -0
  263. package/eval/local/skills/benchmarks/040-beta/comet/scripts/comet-guard.mjs +10173 -0
  264. package/eval/local/skills/benchmarks/040-beta/comet/scripts/comet-handoff.mjs +9491 -0
  265. package/eval/local/skills/benchmarks/040-beta/comet/scripts/comet-hook-guard.mjs +9175 -0
  266. package/eval/local/skills/benchmarks/040-beta/comet/scripts/comet-intent.mjs +404 -0
  267. package/eval/local/skills/benchmarks/040-beta/comet/scripts/comet-state.mjs +9273 -0
  268. package/eval/local/skills/benchmarks/040-beta/comet/scripts/comet-yaml-validate.mjs +7627 -0
  269. package/eval/local/skills/benchmarks/040-beta/comet-archive/SKILL.md +110 -0
  270. package/eval/local/skills/benchmarks/040-beta/comet-build/SKILL.md +315 -0
  271. package/eval/local/skills/benchmarks/040-beta/comet-design/SKILL.md +260 -0
  272. package/eval/local/skills/benchmarks/040-beta/comet-hotfix/SKILL.md +190 -0
  273. package/eval/local/skills/benchmarks/040-beta/comet-open/SKILL.md +210 -0
  274. package/eval/local/skills/benchmarks/040-beta/comet-tweak/SKILL.md +183 -0
  275. package/eval/local/skills/benchmarks/040-beta/comet-verify/SKILL.md +230 -0
  276. package/eval/local/skills/benchmarks/dependency/claude-md/comet-workflow/CLAUDE.md +12 -0
  277. package/eval/local/skills/benchmarks/dependency/openspec/openspec-apply-change/SKILL.md +156 -0
  278. package/eval/local/skills/benchmarks/dependency/openspec/openspec-archive-change/SKILL.md +114 -0
  279. package/eval/local/skills/benchmarks/dependency/openspec/openspec-bulk-archive-change/SKILL.md +246 -0
  280. package/eval/local/skills/benchmarks/dependency/openspec/openspec-continue-change/SKILL.md +118 -0
  281. package/eval/local/skills/benchmarks/dependency/openspec/openspec-explore/SKILL.md +288 -0
  282. package/eval/local/skills/benchmarks/dependency/openspec/openspec-ff-change/SKILL.md +101 -0
  283. package/eval/local/skills/benchmarks/dependency/openspec/openspec-new-change/SKILL.md +74 -0
  284. package/eval/local/skills/benchmarks/dependency/openspec/openspec-onboard/SKILL.md +554 -0
  285. package/eval/local/skills/benchmarks/dependency/openspec/openspec-propose/SKILL.md +110 -0
  286. package/eval/local/skills/benchmarks/dependency/openspec/openspec-sync-specs/SKILL.md +138 -0
  287. package/eval/local/skills/benchmarks/dependency/openspec/openspec-verify-change/SKILL.md +168 -0
  288. package/eval/local/skills/benchmarks/dependency/superpowers/brainstorming/SKILL.md +159 -0
  289. package/eval/local/skills/benchmarks/dependency/superpowers/brainstorming/scripts/frame-template.html +213 -0
  290. package/eval/local/skills/benchmarks/dependency/superpowers/brainstorming/scripts/helper.js +167 -0
  291. package/eval/local/skills/benchmarks/dependency/superpowers/brainstorming/scripts/server.cjs +723 -0
  292. package/eval/local/skills/benchmarks/dependency/superpowers/brainstorming/scripts/start-server.sh +209 -0
  293. package/eval/local/skills/benchmarks/dependency/superpowers/brainstorming/scripts/stop-server.sh +120 -0
  294. package/eval/local/skills/benchmarks/dependency/superpowers/brainstorming/spec-document-reviewer-prompt.md +49 -0
  295. package/eval/local/skills/benchmarks/dependency/superpowers/brainstorming/visual-companion.md +291 -0
  296. package/eval/local/skills/benchmarks/dependency/superpowers/dispatching-parallel-agents/SKILL.md +185 -0
  297. package/eval/local/skills/benchmarks/dependency/superpowers/executing-plans/SKILL.md +70 -0
  298. package/eval/local/skills/benchmarks/dependency/superpowers/finishing-a-development-branch/SKILL.md +241 -0
  299. package/eval/local/skills/benchmarks/dependency/superpowers/receiving-code-review/SKILL.md +213 -0
  300. package/eval/local/skills/benchmarks/dependency/superpowers/requesting-code-review/SKILL.md +103 -0
  301. package/eval/local/skills/benchmarks/dependency/superpowers/requesting-code-review/code-reviewer.md +172 -0
  302. package/eval/local/skills/benchmarks/dependency/superpowers/subagent-driven-development/SKILL.md +418 -0
  303. package/eval/local/skills/benchmarks/dependency/superpowers/subagent-driven-development/implementer-prompt.md +139 -0
  304. package/eval/local/skills/benchmarks/dependency/superpowers/subagent-driven-development/scripts/review-package +44 -0
  305. package/eval/local/skills/benchmarks/dependency/superpowers/subagent-driven-development/scripts/sdd-workspace +22 -0
  306. package/eval/local/skills/benchmarks/dependency/superpowers/subagent-driven-development/scripts/task-brief +40 -0
  307. package/eval/local/skills/benchmarks/dependency/superpowers/subagent-driven-development/task-reviewer-prompt.md +188 -0
  308. package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/CREATION-LOG.md +119 -0
  309. package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/SKILL.md +296 -0
  310. package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/condition-based-waiting-example.ts +158 -0
  311. package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/condition-based-waiting.md +115 -0
  312. package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/defense-in-depth.md +122 -0
  313. package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/find-polluter.sh +63 -0
  314. package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/root-cause-tracing.md +169 -0
  315. package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/test-academic.md +14 -0
  316. package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/test-pressure-1.md +58 -0
  317. package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/test-pressure-2.md +68 -0
  318. package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/test-pressure-3.md +69 -0
  319. package/eval/local/skills/benchmarks/dependency/superpowers/test-driven-development/SKILL.md +371 -0
  320. package/eval/local/skills/benchmarks/dependency/superpowers/test-driven-development/testing-anti-patterns.md +299 -0
  321. package/eval/local/skills/benchmarks/dependency/superpowers/using-git-worktrees/SKILL.md +202 -0
  322. package/eval/local/skills/benchmarks/dependency/superpowers/verification-before-completion/SKILL.md +139 -0
  323. package/eval/local/skills/benchmarks/dependency/superpowers/writing-plans/SKILL.md +174 -0
  324. package/eval/local/skills/benchmarks/dependency/superpowers/writing-plans/plan-document-reviewer-prompt.md +49 -0
  325. package/eval/local/skills/benchmarks/dependency/superpowers/writing-skills/SKILL.md +689 -0
  326. package/eval/local/skills/benchmarks/dependency/superpowers/writing-skills/anthropic-best-practices.md +1150 -0
  327. package/eval/local/skills/benchmarks/dependency/superpowers/writing-skills/examples/CLAUDE_MD_TESTING.md +189 -0
  328. package/eval/local/skills/benchmarks/dependency/superpowers/writing-skills/graphviz-conventions.dot +172 -0
  329. package/eval/local/skills/benchmarks/dependency/superpowers/writing-skills/persuasion-principles.md +187 -0
  330. package/eval/local/skills/benchmarks/dependency/superpowers/writing-skills/render-graphs.js +168 -0
  331. package/eval/local/skills/benchmarks/dependency/superpowers/writing-skills/testing-skills-with-subagents.md +384 -0
  332. package/eval/local/tasks/authoring-skill-smoke/environment/Dockerfile +2 -0
  333. package/eval/local/tasks/authoring-skill-smoke/instruction.md +4 -0
  334. package/eval/local/tasks/authoring-skill-smoke/task.toml +21 -0
  335. package/eval/local/tasks/authoring-skill-smoke/validation/test_authoring_skill_smoke.py +54 -0
  336. package/eval/local/tasks/comet-agent-memory-routing/environment/Dockerfile +28 -0
  337. package/eval/local/tasks/comet-agent-memory-routing/environment/agent_system.py +40 -0
  338. package/eval/local/tasks/comet-agent-memory-routing/environment/test_agent_system.py +29 -0
  339. package/eval/local/tasks/comet-agent-memory-routing/instruction.md +20 -0
  340. package/eval/local/tasks/comet-agent-memory-routing/task.toml +24 -0
  341. package/eval/local/tasks/comet-agent-memory-routing/validation/test_agent_memory_routing.py +24 -0
  342. package/eval/local/tasks/comet-api-cache-ttl/environment/Dockerfile +39 -0
  343. package/eval/local/tasks/comet-api-cache-ttl/environment/cache.py +39 -0
  344. package/eval/local/tasks/comet-api-cache-ttl/environment/test_cache.py +81 -0
  345. package/eval/local/tasks/comet-api-cache-ttl/instruction.md +33 -0
  346. package/eval/local/tasks/comet-api-cache-ttl/task.toml +24 -0
  347. package/eval/local/tasks/comet-api-cache-ttl/validation/test_api_cache_ttl.py +58 -0
  348. package/eval/local/tasks/comet-cross-file-refactor/environment/Dockerfile +15 -0
  349. package/eval/local/tasks/comet-cross-file-refactor/environment/cli.py +13 -0
  350. package/eval/local/tasks/comet-cross-file-refactor/environment/counting.py +13 -0
  351. package/eval/local/tasks/comet-cross-file-refactor/environment/test_textkit.py +21 -0
  352. package/eval/local/tasks/comet-cross-file-refactor/instruction.md +16 -0
  353. package/eval/local/tasks/comet-cross-file-refactor/task.toml +20 -0
  354. package/eval/local/tasks/comet-cross-file-refactor/validation/test_cross_file_refactor.py +20 -0
  355. package/eval/local/tasks/comet-dependency-confusion/environment/Dockerfile +28 -0
  356. package/eval/local/tasks/comet-dependency-confusion/environment/app.py +8 -0
  357. package/eval/local/tasks/comet-dependency-confusion/environment/settings_loader.py +14 -0
  358. package/eval/local/tasks/comet-dependency-confusion/environment/test_settings_service.py +19 -0
  359. package/eval/local/tasks/comet-dependency-confusion/instruction.md +18 -0
  360. package/eval/local/tasks/comet-dependency-confusion/task.toml +24 -0
  361. package/eval/local/tasks/comet-dependency-confusion/validation/test_dependency_confusion.py +24 -0
  362. package/eval/local/tasks/comet-fix-median/environment/Dockerfile +50 -0
  363. package/eval/local/tasks/comet-fix-median/environment/stats.py +54 -0
  364. package/eval/local/tasks/comet-fix-median/environment/test_stats.py +68 -0
  365. package/eval/local/tasks/comet-fix-median/instruction.md +25 -0
  366. package/eval/local/tasks/comet-fix-median/task.toml +24 -0
  367. package/eval/local/tasks/comet-fix-median/validation/test_fix_median.py +60 -0
  368. package/eval/local/tasks/comet-framework-selection/environment/Dockerfile +28 -0
  369. package/eval/local/tasks/comet-framework-selection/environment/architecture.py +12 -0
  370. package/eval/local/tasks/comet-framework-selection/environment/test_architecture.py +30 -0
  371. package/eval/local/tasks/comet-framework-selection/instruction.md +22 -0
  372. package/eval/local/tasks/comet-framework-selection/task.toml +24 -0
  373. package/eval/local/tasks/comet-framework-selection/validation/test_framework_selection.py +24 -0
  374. package/eval/local/tasks/comet-full-workflow/environment/Dockerfile +53 -0
  375. package/eval/local/tasks/comet-full-workflow/environment/test_wordcount.py +29 -0
  376. package/eval/local/tasks/comet-full-workflow/environment/wordcount.py +40 -0
  377. package/eval/local/tasks/comet-full-workflow/instruction.md +18 -0
  378. package/eval/local/tasks/comet-full-workflow/task.toml +24 -0
  379. package/eval/local/tasks/comet-full-workflow/validation/test_full_workflow.py +171 -0
  380. package/eval/local/tasks/comet-graph-execution-review/environment/Dockerfile +28 -0
  381. package/eval/local/tasks/comet-graph-execution-review/environment/pipeline.py +19 -0
  382. package/eval/local/tasks/comet-graph-execution-review/environment/test_pipeline.py +53 -0
  383. package/eval/local/tasks/comet-graph-execution-review/instruction.md +21 -0
  384. package/eval/local/tasks/comet-graph-execution-review/task.toml +24 -0
  385. package/eval/local/tasks/comet-graph-execution-review/validation/test_graph_execution_review.py +24 -0
  386. package/eval/local/tasks/comet-human-approval-flow/environment/Dockerfile +15 -0
  387. package/eval/local/tasks/comet-human-approval-flow/environment/approvals.py +17 -0
  388. package/eval/local/tasks/comet-human-approval-flow/environment/test_approvals.py +30 -0
  389. package/eval/local/tasks/comet-human-approval-flow/instruction.md +15 -0
  390. package/eval/local/tasks/comet-human-approval-flow/task.toml +20 -0
  391. package/eval/local/tasks/comet-human-approval-flow/validation/test_human_approval_flow.py +20 -0
  392. package/eval/local/tasks/comet-layered-streaming-fix/environment/Dockerfile +20 -0
  393. package/eval/local/tasks/comet-layered-streaming-fix/environment/chat_app.py +19 -0
  394. package/eval/local/tasks/comet-layered-streaming-fix/environment/test_chat_app.py +15 -0
  395. package/eval/local/tasks/comet-layered-streaming-fix/instruction.md +14 -0
  396. package/eval/local/tasks/comet-layered-streaming-fix/task.toml +20 -0
  397. package/eval/local/tasks/comet-layered-streaming-fix/validation/test_layered_streaming_fix.py +20 -0
  398. package/eval/local/tasks/comet-noise-distractor/environment/Dockerfile +15 -0
  399. package/eval/local/tasks/comet-noise-distractor/environment/distractor.md +4 -0
  400. package/eval/local/tasks/comet-noise-distractor/environment/invoice.py +5 -0
  401. package/eval/local/tasks/comet-noise-distractor/environment/test_invoice.py +18 -0
  402. package/eval/local/tasks/comet-noise-distractor/instruction.md +17 -0
  403. package/eval/local/tasks/comet-noise-distractor/task.toml +20 -0
  404. package/eval/local/tasks/comet-noise-distractor/validation/test_noise_distractor.py +20 -0
  405. package/eval/local/tasks/comet-observability-env-template/environment/Dockerfile +15 -0
  406. package/eval/local/tasks/comet-observability-env-template/environment/env_writer.py +17 -0
  407. package/eval/local/tasks/comet-observability-env-template/environment/test_env_writer.py +17 -0
  408. package/eval/local/tasks/comet-observability-env-template/instruction.md +20 -0
  409. package/eval/local/tasks/comet-observability-env-template/task.toml +20 -0
  410. package/eval/local/tasks/comet-observability-env-template/validation/test_observability_env_template.py +46 -0
  411. package/eval/local/tasks/comet-perf-dedupe/environment/Dockerfile +39 -0
  412. package/eval/local/tasks/comet-perf-dedupe/environment/dedupe.py +22 -0
  413. package/eval/local/tasks/comet-perf-dedupe/environment/test_dedupe.py +43 -0
  414. package/eval/local/tasks/comet-perf-dedupe/instruction.md +25 -0
  415. package/eval/local/tasks/comet-perf-dedupe/task.toml +24 -0
  416. package/eval/local/tasks/comet-perf-dedupe/validation/test_perf_dedupe.py +40 -0
  417. package/eval/local/tasks/comet-persistence-threading/environment/Dockerfile +15 -0
  418. package/eval/local/tasks/comet-persistence-threading/environment/session_store.py +15 -0
  419. package/eval/local/tasks/comet-persistence-threading/environment/test_session_store.py +21 -0
  420. package/eval/local/tasks/comet-persistence-threading/instruction.md +14 -0
  421. package/eval/local/tasks/comet-persistence-threading/task.toml +20 -0
  422. package/eval/local/tasks/comet-persistence-threading/validation/test_persistence_threading.py +20 -0
  423. package/eval/local/tasks/comet-refactor-counter/environment/Dockerfile +39 -0
  424. package/eval/local/tasks/comet-refactor-counter/environment/test_text_processor.py +57 -0
  425. package/eval/local/tasks/comet-refactor-counter/environment/text_processor.py +49 -0
  426. package/eval/local/tasks/comet-refactor-counter/instruction.md +31 -0
  427. package/eval/local/tasks/comet-refactor-counter/task.toml +24 -0
  428. package/eval/local/tasks/comet-refactor-counter/validation/test_refactor_counter.py +75 -0
  429. package/eval/local/tasks/comet-robust-config/environment/Dockerfile +39 -0
  430. package/eval/local/tasks/comet-robust-config/environment/config_loader.py +56 -0
  431. package/eval/local/tasks/comet-robust-config/environment/test_config_loader.py +72 -0
  432. package/eval/local/tasks/comet-robust-config/instruction.md +30 -0
  433. package/eval/local/tasks/comet-robust-config/task.toml +24 -0
  434. package/eval/local/tasks/comet-robust-config/validation/test_robust_config.py +37 -0
  435. package/eval/local/tasks/generic-skill-smoke/environment/Dockerfile +2 -0
  436. package/eval/local/tasks/generic-skill-smoke/instruction.md +7 -0
  437. package/eval/local/tasks/generic-skill-smoke/task.toml +21 -0
  438. package/eval/local/tasks/generic-skill-smoke/validation/test_generic_skill_smoke.py +36 -0
  439. package/eval/local/tasks/index.yaml +155 -0
  440. package/eval/local/tasks/workflow-overlay-contract/environment/Dockerfile +5 -0
  441. package/eval/local/tasks/workflow-overlay-contract/instruction.md +5 -0
  442. package/eval/local/tasks/workflow-overlay-contract/task.toml +21 -0
  443. package/eval/local/tasks/workflow-overlay-contract/validation/test_workflow_overlay_contract.py +235 -0
  444. package/eval/local/tasks/workflow-route-conformance/environment/Dockerfile +2 -0
  445. package/eval/local/tasks/workflow-route-conformance/instruction.md +5 -0
  446. package/eval/local/tasks/workflow-route-conformance/task.toml +21 -0
  447. package/eval/local/tasks/workflow-route-conformance/validation/test_workflow_route_conformance.py +84 -0
  448. package/eval/local/tests/conftest.py +1148 -0
  449. package/eval/local/tests/scaffold/test_attribution.py +48 -0
  450. package/eval/local/tests/scaffold/test_compare_baselines.py +999 -0
  451. package/eval/local/tests/scaffold/test_conftest_helpers.py +534 -0
  452. package/eval/local/tests/scaffold/test_evidence.py +15 -0
  453. package/eval/local/tests/scaffold/test_langsmith_conftest.py +244 -0
  454. package/eval/local/tests/scaffold/test_logging.py +243 -0
  455. package/eval/local/tests/scaffold/test_manifests.py +132 -0
  456. package/eval/local/tests/scaffold/test_profiles.py +866 -0
  457. package/eval/local/tests/scaffold/test_regression_check.py +19 -0
  458. package/eval/local/tests/scaffold/test_report_style_demo_charts.py +45 -0
  459. package/eval/local/tests/scaffold/test_sample_quality.py +211 -0
  460. package/eval/local/tests/scaffold/test_tasks.py +168 -0
  461. package/eval/local/tests/scaffold/test_treatments.py +244 -0
  462. package/eval/local/tests/scaffold/test_utils.py +139 -0
  463. package/eval/local/tests/tasks/test_tasks.py +445 -0
  464. package/eval/local/tests/tasks/test_validation_scripts.py +143 -0
  465. package/eval/local/treatments/comet/comet_full_039.yaml +141 -0
  466. package/eval/local/treatments/comet/comet_full_040_beta.yaml +140 -0
  467. package/eval/local/treatments/common/control.yaml +4 -0
  468. package/eval/pyproject.toml +41 -0
  469. package/eval/report-html-config.json +6 -0
  470. package/eval/scaffold/__init__.py +67 -0
  471. package/eval/scaffold/python/__init__.py +95 -0
  472. package/eval/scaffold/python/attribution.py +43 -0
  473. package/eval/scaffold/python/evidence.py +38 -0
  474. package/eval/scaffold/python/external_data_handler.py +18 -0
  475. package/eval/scaffold/python/generic_llm_judge.py +235 -0
  476. package/eval/scaffold/python/judge_config.py +168 -0
  477. package/eval/scaffold/python/llm_judge.py +191 -0
  478. package/eval/scaffold/python/logging.py +705 -0
  479. package/eval/scaffold/python/manifests.py +129 -0
  480. package/eval/scaffold/python/paper_charts.py +25 -0
  481. package/eval/scaffold/python/pass_at_k.py +107 -0
  482. package/eval/scaffold/python/paths.py +56 -0
  483. package/eval/scaffold/python/profiles.py +127 -0
  484. package/eval/scaffold/python/report_outputs.py +1391 -0
  485. package/eval/scaffold/python/sample_quality.py +339 -0
  486. package/eval/scaffold/python/schema.py +39 -0
  487. package/eval/scaffold/python/skill_parser.py +469 -0
  488. package/eval/scaffold/python/tasks.py +330 -0
  489. package/eval/scaffold/python/treatments.py +271 -0
  490. package/eval/scaffold/python/utils.py +366 -0
  491. package/eval/scaffold/python/validation/__init__.py +21 -0
  492. package/eval/scaffold/python/validation/authoring_rubric.py +326 -0
  493. package/eval/scaffold/python/validation/comet_workflow.py +187 -0
  494. package/eval/scaffold/python/validation/core.py +264 -0
  495. package/eval/scaffold/python/validation/dataset.py +337 -0
  496. package/eval/scaffold/python/validation/docker.py +106 -0
  497. package/eval/scaffold/python/validation/evaluator.py +549 -0
  498. package/eval/scaffold/python/validation/generic_rubric.py +169 -0
  499. package/eval/scaffold/python/validation/rubric.py +740 -0
  500. package/eval/scaffold/python/validation/runner.py +237 -0
  501. package/eval/scaffold/python/validation/scripts.py +58 -0
  502. package/eval/scaffold/python/validation/tracing.py +313 -0
  503. package/eval/scaffold/shell/common.sh +126 -0
  504. package/eval/scaffold/shell/docker.sh +482 -0
  505. package/eval/scaffold/shell/run-claude-loop.sh +181 -0
  506. package/eval/scaffold/shell/setup.sh +259 -0
  507. package/eval/simulator-instruction.md +9 -0
  508. package/package.json +24 -2
@@ -0,0 +1,38 @@
1
+ """Evidence references for eval reports."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+ from pathlib import Path
7
+
8
+ TREATMENT_NAME_ALIASES = {
9
+ "COMET-FULL": "COMET_FULL_040_BETA",
10
+ }
11
+
12
+
13
+ @dataclass(frozen=True)
14
+ class EvalArtifactReference:
15
+ kind: str
16
+ path: str
17
+
18
+
19
+ def stable_treatment_name(treatment_name: str) -> str:
20
+ alias = TREATMENT_NAME_ALIASES.get(treatment_name)
21
+ if alias:
22
+ return alias
23
+ return treatment_name.replace("-", "_")
24
+
25
+
26
+ def build_eval_artifact_references(
27
+ base_dir: Path,
28
+ treatment_name: str,
29
+ rep: int,
30
+ ) -> dict[str, str]:
31
+ name = stable_treatment_name(treatment_name)
32
+ return {
33
+ "events": str(base_dir / "events" / f"{name}_rep{rep}.json"),
34
+ "raw_stdout": str(base_dir / "raw" / f"{name}_rep{rep}_stdout.json"),
35
+ "raw_stderr": str(base_dir / "raw" / f"{name}_rep{rep}_stderr.txt"),
36
+ "report": str(base_dir / "reports" / f"{name}_rep{rep}_report.json"),
37
+ "artifacts": str(base_dir / "artifacts" / f"{name}_rep{rep}"),
38
+ }
@@ -0,0 +1,18 @@
1
+ """External data handler - stub for comet skill benchmarks.
2
+
3
+ The original project uses this for LangSmith trace uploads and dataset management.
4
+ For comet-skill-eval, we keep the interface but remove LangSmith dependencies.
5
+ """
6
+
7
+ from pathlib import Path
8
+ from typing import Any
9
+
10
+
11
+ def run_handler(handler_name: str, **kwargs) -> Any:
12
+ """Run a named handler. No-op for comet benchmarks."""
13
+ return None
14
+
15
+
16
+ def run_task_handlers(handlers: list, data_dir: Path, langsmith_env: str, run_id: str) -> dict:
17
+ """Run task data handlers. Returns empty trace map for comet benchmarks."""
18
+ return {}
@@ -0,0 +1,235 @@
1
+ """LLM-as-judge scoring for generic Skill eval targets.
2
+
3
+ The rule-based generic rubric (``generic_rubric.py``) catches structural signals
4
+ (file presence, command execution) but misses qualitative depth: did the agent
5
+ produce meaningful output, or just a stub? This module asks a judge LLM to read
6
+ workspace artifacts and score three generic quality dimensions on a 0.00-1.00
7
+ scale with a cited reason.
8
+
9
+ Runs on the host (not in Docker) via the same Claude CLI + proxy used for the
10
+ subject agent, so it adds no new dependency. Scores are emitted in the same
11
+ ``[RUBRIC-JUDGE] dim: score - reason`` format the logging layer understands.
12
+
13
+ Usage::
14
+
15
+ from scaffold.python.generic_llm_judge import judge_generic_messages
16
+ results = judge_generic_messages(test_dir, outputs)
17
+ """
18
+
19
+ from __future__ import annotations
20
+
21
+ import os
22
+ import re
23
+ from pathlib import Path
24
+ from typing import Any
25
+
26
+ from scaffold.python.judge_config import build_judge_invocation, run_judge_prompt
27
+
28
+ try:
29
+ from dotenv import load_dotenv
30
+
31
+ load_dotenv(Path(__file__).resolve().parents[3] / ".env")
32
+ except Exception:
33
+ pass
34
+
35
+ GENERIC_JUDGE_DIMENSIONS = ("task_completion", "output_quality", "instruction_adherence")
36
+
37
+ _JUDGE_RE = re.compile(r"\[RUBRIC-JUDGE\]\s+(\S+):\s*([0-9.]+)\s*-\s*(.+)")
38
+
39
+ # Directories to skip when collecting workspace artifacts.
40
+ _SKIP_DIRS = {
41
+ ".git",
42
+ "node_modules",
43
+ "__pycache__",
44
+ ".comet",
45
+ ".pytest_cache",
46
+ "venv",
47
+ ".venv",
48
+ "env",
49
+ }
50
+
51
+ # Max chars per file, total budget across all files.
52
+ _PER_FILE_LIMIT = 3000
53
+ _TOTAL_BUDGET = 20_000
54
+
55
+
56
+ def _read_file(path: Path, limit: int = _PER_FILE_LIMIT) -> str:
57
+ """Read up to *limit* chars of a file, gracefully handling missing files."""
58
+ try:
59
+ text = path.read_text(errors="ignore")
60
+ return text[:limit] if len(text) > limit else text
61
+ except Exception:
62
+ return f"(missing: {path.name})"
63
+
64
+
65
+ def _collect_workspace_artifacts(test_dir: Path) -> str:
66
+ """Walk *test_dir* and return a concatenated dump of workspace files.
67
+
68
+ Skips hidden directories, common vendor dirs, and binary-looking files.
69
+ Total output is capped at ``_TOTAL_BUDGET`` chars.
70
+ """
71
+ parts: list[str] = []
72
+ total = 0
73
+
74
+ for path in sorted(test_dir.rglob("*")):
75
+ if not path.is_file():
76
+ continue
77
+ # Skip hidden paths.
78
+ if any(part.startswith(".") for part in path.relative_to(test_dir).parts):
79
+ continue
80
+ # Skip known vendor / cache dirs.
81
+ if any(part in _SKIP_DIRS for part in path.relative_to(test_dir).parts):
82
+ continue
83
+ # Skip large or binary-looking files.
84
+ try:
85
+ if path.stat().st_size > 50_000:
86
+ continue
87
+ except OSError:
88
+ continue
89
+
90
+ rel = path.relative_to(test_dir)
91
+ text = _read_file(path, _PER_FILE_LIMIT)
92
+ chunk = f"\n=== {rel} ===\n{text}\n"
93
+
94
+ if total + len(chunk) > _TOTAL_BUDGET:
95
+ remaining = _TOTAL_BUDGET - total
96
+ if remaining > 200:
97
+ parts.append(chunk[:remaining])
98
+ break
99
+ parts.append(chunk)
100
+ total += len(chunk)
101
+
102
+ return "".join(parts) if parts else "(no workspace files found)"
103
+
104
+
105
+ def _build_generic_judge_prompt(
106
+ test_dir: Path,
107
+ outputs: dict[str, Any],
108
+ ) -> str:
109
+ """Assemble workspace artifacts and the judging rubric into one prompt."""
110
+ artifacts = _collect_workspace_artifacts(test_dir)
111
+
112
+ # Include completion results summary if available.
113
+ completion = outputs.get("completion") or {}
114
+ passed_checks = completion.get("passed", [])
115
+ failed_checks = completion.get("failed", [])
116
+ completion_summary = (
117
+ f"Passed: {len(passed_checks)}, Failed: {len(failed_checks)}\n"
118
+ if passed_checks or failed_checks
119
+ else "(no baseline checks)\n"
120
+ )
121
+ if failed_checks:
122
+ completion_summary += "Failed checks:\n" + "\n".join(
123
+ f" - {item}" for item in failed_checks[:10]
124
+ )
125
+
126
+ # Custom rubric criteria from task.toml.
127
+ custom_criteria = outputs.get("rubric_criteria") or []
128
+ custom_section = ""
129
+ if custom_criteria:
130
+ lines = "\n".join(f"- {c}" for c in custom_criteria)
131
+ custom_section = f"\nAdditional task-specific criteria:\n{lines}\n"
132
+
133
+ # Build the list of dimensions the judge should output.
134
+ all_dims = list(GENERIC_JUDGE_DIMENSIONS)
135
+ dim_lines = [
136
+ f"[RUBRIC-JUDGE] {dim}: <score> - <reason>" for dim in all_dims
137
+ ]
138
+ extra_dim_lines = [
139
+ f"[RUBRIC-JUDGE] custom_{i}: <score> - <reason>"
140
+ for i in range(len(custom_criteria))
141
+ ]
142
+ all_output_lines = "\n".join(dim_lines + extra_dim_lines)
143
+
144
+ # Dimension count for the instruction.
145
+ total_dims = len(all_dims) + len(custom_criteria)
146
+
147
+ return f"""You are an impartial judge scoring an AI agent's task execution. Read the workspace artifacts below and score {total_dims} dimensions on a 0.00-1.00 scale. Output EXACTLY {total_dims} lines, each in this format (no other text):
148
+
149
+ {all_output_lines}
150
+
151
+ Scoring criteria:
152
+
153
+ task_completion (0.00-1.00):
154
+ - 1.0: all task requirements met, output artifacts present and correct, baseline checks pass
155
+ - 0.5: partial completion, some requirements met but others missing or incorrect
156
+ - 0.0: task not completed, key output missing or empty
157
+
158
+ output_quality (0.00-1.00):
159
+ - 1.0: output is well-structured, complete, non-trivial; shows evidence of thoughtful work
160
+ - 0.5: output present but shallow, minimal, or barely adequate
161
+ - 0.0: output missing, empty, or clearly a stub
162
+
163
+ instruction_adherence (0.00-1.00):
164
+ - 1.0: agent followed all instructions and constraints, no forbidden patterns, appropriate tool usage
165
+ - 0.5: minor deviations from instructions, but core intent respected
166
+ - 0.0: significant instruction violations, dangerous commands, or constraint failures
167
+ {custom_section}
168
+ Cite specific content from the artifacts in your reason (<=25 words each).
169
+
170
+ Baseline validation results:
171
+ {completion_summary}
172
+
173
+ === Workspace artifacts ===
174
+ {artifacts}
175
+ """
176
+
177
+
178
+ def _run_judge(prompt: str, timeout: int = 120) -> str:
179
+ """Call the judge LLM through the configured judge provider."""
180
+ return run_judge_prompt(prompt, timeout=timeout)
181
+
182
+
183
+ def judge_generic_artifacts(
184
+ test_dir: Path,
185
+ outputs: dict[str, Any],
186
+ timeout: int = 120,
187
+ ) -> dict[str, tuple[float, str]]:
188
+ """Score qualitative dimensions via an LLM judge for generic skills.
189
+
190
+ Returns ``{dim: (score, reason)}``. On any failure (model error, no
191
+ parseable output) the dimension is omitted so the caller falls back to
192
+ rule-based scores.
193
+ """
194
+ prompt = _build_generic_judge_prompt(test_dir, outputs)
195
+ raw = _run_judge(prompt, timeout=timeout)
196
+
197
+ # Collect all valid dimension names (standard + custom).
198
+ custom_criteria = outputs.get("rubric_criteria") or []
199
+ valid_dims = set(GENERIC_JUDGE_DIMENSIONS)
200
+ for i in range(len(custom_criteria)):
201
+ valid_dims.add(f"custom_{i}")
202
+
203
+ scores: dict[str, tuple[float, str]] = {}
204
+ for line in raw.splitlines():
205
+ m = _JUDGE_RE.search(line)
206
+ if not m:
207
+ continue
208
+ dim = m.group(1)
209
+ try:
210
+ score = float(m.group(2))
211
+ except ValueError:
212
+ continue
213
+ reason = m.group(3).strip()
214
+ if dim in valid_dims:
215
+ scores[dim] = (max(0.0, min(1.0, score)), reason)
216
+ return scores
217
+
218
+
219
+ def judge_generic_messages(
220
+ test_dir: Path,
221
+ outputs: dict[str, Any],
222
+ timeout: int = 120,
223
+ ) -> list[str]:
224
+ """Convenience wrapper returning ``[RUBRIC-JUDGE]`` check messages."""
225
+ out: list[str] = []
226
+ try:
227
+ build_judge_invocation()
228
+ except ValueError as e:
229
+ return [f"[RUBRIC-JUDGE] status: skipped - {e}"]
230
+
231
+ for dim, (score, reason) in judge_generic_artifacts(
232
+ test_dir, outputs, timeout=timeout
233
+ ).items():
234
+ out.append(f"[RUBRIC-JUDGE] {dim}: {score:.2f} - {reason}")
235
+ return out
@@ -0,0 +1,168 @@
1
+ """Dedicated LLM judge provider configuration."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import os
6
+ import json
7
+ import subprocess
8
+ import urllib.error
9
+ import urllib.request
10
+ from dataclasses import dataclass
11
+ from typing import Mapping
12
+
13
+
14
+ _ANTHROPIC_PROVIDER_KEYS = (
15
+ "ANTHROPIC_API_KEY",
16
+ "ANTHROPIC_AUTH_TOKEN",
17
+ "ANTHROPIC_BASE_URL",
18
+ "ANTHROPIC_MODEL",
19
+ "ANTHROPIC_DEFAULT_HAIKU_MODEL",
20
+ "ANTHROPIC_DEFAULT_SONNET_MODEL",
21
+ "ANTHROPIC_DEFAULT_OPUS_MODEL",
22
+ "ANTHROPIC_DEFAULT_OPUS_MODEL_NAME",
23
+ "ANTHROPIC_DEFAULT_SONNET_MODEL_NAME",
24
+ )
25
+
26
+
27
+ @dataclass(frozen=True)
28
+ class JudgeInvocation:
29
+ env: dict[str, str]
30
+ model_flag: list[str]
31
+ model: str
32
+ api_key: str
33
+ auth_token: str
34
+ base_url: str
35
+
36
+
37
+ def build_judge_invocation(
38
+ source_env: Mapping[str, str] | None = None,
39
+ ) -> JudgeInvocation:
40
+ """Build an isolated Claude CLI invocation environment for LLM-as-judge.
41
+
42
+ Judge configuration is intentionally separate from the subject agent's
43
+ ANTHROPIC_* provider settings. This prevents accidentally judging a run
44
+ with the same model or endpoint under test.
45
+ """
46
+ source = source_env if source_env is not None else os.environ
47
+ model = (source.get("BENCH_JUDGE_MODEL") or "").strip()
48
+ if not model:
49
+ raise ValueError("BENCH_JUDGE_MODEL is required when BENCH_LLM_JUDGE=1")
50
+
51
+ env = dict(source)
52
+ for key in _ANTHROPIC_PROVIDER_KEYS:
53
+ env.pop(key, None)
54
+
55
+ env["ANTHROPIC_MODEL"] = model
56
+
57
+ api_key = (source.get("BENCH_JUDGE_API_KEY") or "").strip()
58
+ auth_token = (source.get("BENCH_JUDGE_AUTH_TOKEN") or "").strip()
59
+ base_url = (source.get("BENCH_JUDGE_BASE_URL") or "").strip()
60
+
61
+ if api_key:
62
+ env["ANTHROPIC_API_KEY"] = api_key
63
+ if auth_token:
64
+ env["ANTHROPIC_AUTH_TOKEN"] = auth_token
65
+ env.pop("ANTHROPIC_API_KEY", None)
66
+ if base_url:
67
+ env["ANTHROPIC_BASE_URL"] = base_url
68
+
69
+ return JudgeInvocation(
70
+ env=env,
71
+ model_flag=["--model", model],
72
+ model=model,
73
+ api_key=api_key,
74
+ auth_token=auth_token,
75
+ base_url=base_url,
76
+ )
77
+
78
+
79
+ def run_judge_prompt(prompt: str, timeout: int = 120) -> str:
80
+ """Run the judge prompt through a dedicated provider configuration.
81
+
82
+ Anthropic-compatible HTTP is preferred when a judge base URL and credential
83
+ are configured. This avoids Claude CLI request-shape incompatibilities with
84
+ stricter proxy providers. Without a dedicated judge endpoint, fall back to
85
+ the local Claude CLI for existing host-authenticated setups.
86
+ """
87
+ try:
88
+ invocation = build_judge_invocation()
89
+ except ValueError as e:
90
+ return f"[RUBRIC-JUDGE] status: skipped - {e}"
91
+
92
+ if invocation.base_url and (invocation.auth_token or invocation.api_key):
93
+ return _run_judge_http(prompt, invocation, timeout=timeout)
94
+
95
+ return _run_judge_claude_cli(prompt, invocation, timeout=timeout)
96
+
97
+
98
+ def _messages_url(base_url: str) -> str:
99
+ base = base_url.rstrip("/")
100
+ if base.endswith("/messages"):
101
+ return base
102
+ if base.endswith("/v1"):
103
+ return f"{base}/messages"
104
+ return f"{base}/v1/messages"
105
+
106
+
107
+ def _run_judge_http(prompt: str, invocation: JudgeInvocation, timeout: int = 120) -> str:
108
+ body = json.dumps(
109
+ {
110
+ "model": invocation.model,
111
+ "max_tokens": 2048,
112
+ "messages": [{"role": "user", "content": prompt}],
113
+ }
114
+ ).encode("utf-8")
115
+ headers = {
116
+ "anthropic-version": "2023-06-01",
117
+ "content-type": "application/json",
118
+ }
119
+ if invocation.auth_token:
120
+ headers["authorization"] = f"Bearer {invocation.auth_token}"
121
+ else:
122
+ headers["x-api-key"] = invocation.api_key
123
+
124
+ request = urllib.request.Request(
125
+ _messages_url(invocation.base_url),
126
+ data=body,
127
+ headers=headers,
128
+ method="POST",
129
+ )
130
+ try:
131
+ with urllib.request.urlopen(request, timeout=timeout) as response:
132
+ payload = json.loads(response.read().decode("utf-8", errors="replace"))
133
+ except urllib.error.HTTPError as e:
134
+ detail = e.read().decode("utf-8", errors="replace").strip()
135
+ return f"(judge error: HTTP {e.code} {detail})"
136
+ except (urllib.error.URLError, TimeoutError, json.JSONDecodeError) as e:
137
+ return f"(judge error: {e})"
138
+
139
+ content = payload.get("content") or []
140
+ text_parts = [
141
+ item.get("text", "")
142
+ for item in content
143
+ if isinstance(item, dict) and item.get("type") == "text"
144
+ ]
145
+ return "\n".join(part for part in text_parts if part).strip()
146
+
147
+
148
+ def _run_judge_claude_cli(
149
+ prompt: str,
150
+ invocation: JudgeInvocation,
151
+ timeout: int = 120,
152
+ ) -> str:
153
+ import shutil
154
+
155
+ claude_bin = shutil.which("claude") or "claude"
156
+ try:
157
+ result = subprocess.run(
158
+ [claude_bin, "-p", "", "--dangerously-skip-permissions", *invocation.model_flag],
159
+ input=prompt,
160
+ capture_output=True,
161
+ timeout=timeout,
162
+ env=invocation.env,
163
+ encoding="utf-8",
164
+ errors="replace",
165
+ )
166
+ return result.stdout or ""
167
+ except (subprocess.TimeoutExpired, FileNotFoundError) as e:
168
+ return f"(judge error: {e})"
@@ -0,0 +1,191 @@
1
+ """LLM-as-judge scoring for qualitative rubric dimensions.
2
+
3
+ The rule-based rubric (``rubric.py``) catches structural signals (file
4
+ presence, keyword counts) but misses qualitative depth: did the design doc
5
+ genuinely explore alternatives, or did it just happen to contain the word
6
+ "risk"? This module asks a judge LLM to read the actual artifacts and score
7
+ three dimensions on a 0.00–1.00 scale with a cited reason.
8
+
9
+ Runs on the host (not in Docker) via the same Claude CLI + proxy used for the
10
+ subject agent, so it adds no new dependency. Scores are emitted in the same
11
+ ``[RUBRIC-JUDGE] dim: score - reason`` format the logging layer understands.
12
+
13
+ Usage from the rubric validator or rescore tool::
14
+
15
+ from scaffold.python.llm_judge import judge_artifacts
16
+ scores = judge_artifacts(test_dir) # {dim: (score, reason)}
17
+ """
18
+
19
+ from __future__ import annotations
20
+
21
+ import json
22
+ import os
23
+ import re
24
+ from pathlib import Path
25
+ from typing import Any
26
+
27
+ from scaffold.python.judge_config import build_judge_invocation, run_judge_prompt
28
+
29
+ # Ensure proxy credentials (ANTHROPIC_AUTH_TOKEN etc.) are available when this
30
+ # module is imported outside pytest (e.g. by the rescore tool).
31
+ try:
32
+ from dotenv import load_dotenv
33
+ load_dotenv(Path(__file__).resolve().parents[3] / ".env")
34
+ except Exception:
35
+ pass
36
+
37
+ # Dimensions the judge evaluates (subset of the rubric where rules are weak).
38
+ JUDGE_DIMENSIONS = ("artifact_quality", "spec_drift", "main_flow")
39
+
40
+ _JUDGE_RE = re.compile(r"\[RUBRIC-JUDGE\]\s+(\S+):\s*([0-9.]+)\s*-\s*(.+)")
41
+
42
+
43
+ def _read_file(path: Path, limit: int = 4000) -> str:
44
+ """Read up to `limit` chars of a file, gracefully handling missing files."""
45
+ try:
46
+ text = path.read_text(errors="ignore")
47
+ return text[:limit] if len(text) > limit else text
48
+ except Exception:
49
+ return f"(missing: {path.name})"
50
+
51
+
52
+ def _find_change_dir(test_dir: Path) -> Path | None:
53
+ """Locate the comet change dir, handling both active and archived layouts."""
54
+ changes_root = test_dir / "openspec" / "changes"
55
+ if not changes_root.exists():
56
+ return None
57
+ for d in changes_root.iterdir():
58
+ if not d.is_dir():
59
+ continue
60
+ if d.name == "archive":
61
+ for sub in d.iterdir():
62
+ if sub.is_dir() and (sub / "proposal.md").exists():
63
+ return sub
64
+ elif (d / "proposal.md").exists():
65
+ return d
66
+ # Fallback: any subdir of archive/
67
+ archive = changes_root / "archive"
68
+ if archive.exists():
69
+ for sub in archive.iterdir():
70
+ if sub.is_dir():
71
+ return sub
72
+ return None
73
+
74
+
75
+ def _build_judge_prompt(test_dir: Path) -> str:
76
+ """Assemble the artifacts and the judging rubric into one prompt."""
77
+ change = _find_change_dir(test_dir)
78
+ proposal = _read_file(change / "proposal.md") if change else "(no change dir)"
79
+ design = _read_file(change / "design.md") if change else "(no design.md)"
80
+ tasks = _read_file(change / "tasks.md") if change else "(no tasks.md)"
81
+
82
+ # Design doc may live under docs/superpowers/specs/ instead.
83
+ if design.startswith("(missing"):
84
+ specs_dir = test_dir / "docs" / "superpowers" / "specs"
85
+ if specs_dir.exists():
86
+ spec_files = sorted(specs_dir.glob("*.md"))
87
+ if spec_files:
88
+ design = _read_file(spec_files[0])
89
+
90
+ # Verify report (phase 4)
91
+ verify_report = "(none)"
92
+ reports_dir = test_dir / "docs" / "superpowers" / "reports"
93
+ if reports_dir.exists():
94
+ rep_files = sorted(reports_dir.glob("*.md"))
95
+ if rep_files:
96
+ verify_report = _read_file(rep_files[0], 2000)
97
+
98
+ # Delta spec (phase drift signal)
99
+ delta_spec = "(none)"
100
+ if change:
101
+ specs = list(change.rglob("spec.md"))
102
+ if specs:
103
+ delta_spec = _read_file(specs[0], 2000)
104
+
105
+ return f"""You are an impartial judge scoring a software-development workflow run. Read the artifacts below and score THREE dimensions on a 0.00–1.00 scale. Output EXACTLY three lines, each in this format (no other text):
106
+
107
+ [RUBRIC-JUDGE] artifact_quality: <score> - <reason>
108
+ [RUBRIC-JUDGE] spec_drift: <score> - <reason>
109
+ [RUBRIC-JUDGE] main_flow: <score> - <reason>
110
+
111
+ Scoring criteria:
112
+
113
+ artifact_quality (0.00–1.00):
114
+ - 1.0: proposal states real problem/goals/scope/non-goals; design explores >=2 alternatives with explicit tradeoffs and risks; tasks are actionable checkboxes; tests have real assertions
115
+ - 0.5: artifacts present but shallow (stub proposal, design lists one approach without alternatives, tasks vague)
116
+ - 0.0: key artifacts missing or empty
117
+
118
+ spec_drift (0.00–1.00):
119
+ - 1.0: if a delta spec was written, it was reconciled (synced to main spec or archived cleanly); if none needed, 0.9
120
+ - 0.5: delta spec written but not reconciled, or minor inconsistency
121
+ - 0.0: delta spec contradicts implementation, or implementation drifted from spec with no delta
122
+
123
+ main_flow (0.00–1.00):
124
+ - 1.0: evidence of all 5 phases (open proposal → design doc → build plan/code → verify report → archive)
125
+ - 0.5: 2-3 phases evidenced
126
+ - 0.0: <2 phases
127
+
128
+ Cite specific content from the artifacts in your reason (<=25 words each).
129
+
130
+ === proposal.md ===
131
+ {proposal}
132
+
133
+ === design.md ===
134
+ {design}
135
+
136
+ === tasks.md ===
137
+ {tasks}
138
+
139
+ === verify report ===
140
+ {verify_report}
141
+
142
+ === delta spec ===
143
+ {delta_spec}
144
+ """
145
+
146
+
147
+ def _run_judge(prompt: str, timeout: int = 120) -> str:
148
+ """Call the judge LLM through the configured judge provider."""
149
+ return run_judge_prompt(prompt, timeout=timeout)
150
+
151
+
152
+ def judge_artifacts(test_dir: Path, timeout: int = 120) -> dict[str, tuple[float, str]]:
153
+ """Score the three qualitative dimensions via an LLM judge.
154
+
155
+ Returns ``{dim: (score, reason)}``. On any failure (model error, no
156
+ parseable output) the dimension is omitted so the caller falls back to the
157
+ rule-based score.
158
+ """
159
+ if not _find_change_dir(test_dir):
160
+ return {}
161
+
162
+ prompt = _build_judge_prompt(test_dir)
163
+ raw = _run_judge(prompt, timeout=timeout)
164
+
165
+ scores: dict[str, tuple[float, str]] = {}
166
+ for line in raw.splitlines():
167
+ m = _JUDGE_RE.search(line)
168
+ if not m:
169
+ continue
170
+ dim = m.group(1)
171
+ try:
172
+ score = float(m.group(2))
173
+ except ValueError:
174
+ continue
175
+ reason = m.group(3).strip()
176
+ if dim in JUDGE_DIMENSIONS:
177
+ scores[dim] = (max(0.0, min(1.0, score)), reason)
178
+ return scores
179
+
180
+
181
+ def judge_messages(test_dir: Path, timeout: int = 120) -> list[str]:
182
+ """Convenience wrapper returning ``[RUBRIC-JUDGE]`` check messages."""
183
+ out: list[str] = []
184
+ try:
185
+ build_judge_invocation()
186
+ except ValueError as e:
187
+ return [f"[RUBRIC-JUDGE] status: skipped - {e}"]
188
+
189
+ for dim, (score, reason) in judge_artifacts(test_dir, timeout=timeout).items():
190
+ out.append(f"[RUBRIC-JUDGE] {dim}: {score:.2f} - {reason}")
191
+ return out