@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,330 @@
1
+ """Task loader for self-contained benchmark tasks.
2
+
3
+ Each task is a directory containing:
4
+ - instruction.md: Task prompt with {variable} placeholders
5
+ - task.toml: Task metadata, validation config (test_scripts, target_artifacts)
6
+ - environment/: Docker context (Dockerfile, source code)
7
+ - validation/: Validator implementations
8
+ - data/: Test data and ground truth (optional)
9
+
10
+ Usage:
11
+ from scaffold.python.tasks import load_task, list_tasks
12
+
13
+ task = load_task("ls-evaluator")
14
+ prompt = task.render_prompt(py_dataset="ds-py", ts_dataset="ds-ts", run_id="abc123")
15
+ validators = task.load_validators()
16
+ """
17
+
18
+ from dataclasses import dataclass, field
19
+ from pathlib import Path
20
+ from typing import Any
21
+
22
+ try:
23
+ import tomllib
24
+ except ImportError:
25
+ import tomli as tomllib # Python < 3.11
26
+
27
+
28
+ from scaffold.python.paths import get_tasks_dir
29
+
30
+
31
+ COMET_WORKFLOW_INVOCATION_CONTRACT = """\
32
+ ## Eval harness requirement
33
+
34
+ You must begin by invoking the `/comet` Skill/slash command with this task request.
35
+ Do not simulate the Comet workflow in plain prose. The run is invalid unless the
36
+ Comet Skill is invoked and leaves real OpenSpec/Comet workflow artifacts.
37
+ """
38
+
39
+
40
+ @dataclass
41
+ class DataHandler:
42
+ """A data handler triggered by file pattern match."""
43
+
44
+ pattern: str # Glob pattern relative to task data dir (e.g., "trace_*.jsonl")
45
+ handler: str # Handler name (e.g., "upload_traces")
46
+ args: dict = field(default_factory=dict) # Handler-specific arguments
47
+
48
+
49
+ @dataclass
50
+ class SetupConfig:
51
+ """Setup configuration for a task.
52
+
53
+ Defines data handlers and template variables that are computed at test time.
54
+ """
55
+
56
+ # Data handlers triggered by pattern matches
57
+ data_handlers: list[DataHandler] = field(default_factory=list)
58
+
59
+ # Template variables with format strings (can use {run_id})
60
+ template_vars: dict[str, str] = field(default_factory=dict)
61
+
62
+
63
+ @dataclass
64
+ class ValidationConfig:
65
+ """Validation configuration from [validation] in task.toml.
66
+
67
+ Defines what to check and how. The framework auto-builds a validator
68
+ from this config — no validators.py needed for most tasks.
69
+ """
70
+
71
+ # Test script(s) to run in Docker (e.g., "test_agent.py")
72
+ test_scripts: str | list[str] = ""
73
+
74
+ # File(s) or dir(s) Claude should produce — existence is checked before
75
+ # running test scripts. Names are available via runner.artifacts.
76
+ target_artifacts: str | list[str] = field(default_factory=list)
77
+
78
+ # Docker execution timeout in seconds
79
+ timeout: int = 120
80
+
81
+
82
+ @dataclass
83
+ class EvaluationConfig:
84
+ """Skill-agnostic evaluation contract for a task."""
85
+
86
+ profile: str | None = None
87
+ required_skills: list[str] = field(default_factory=list)
88
+ expected_artifacts: list[str] = field(default_factory=list)
89
+ require_skill_invocation: bool = False
90
+ rubric_criteria: list[str] = field(default_factory=list)
91
+
92
+
93
+ @dataclass
94
+ class InteractionConfig:
95
+ """Controls whether the runner should simulate user replies."""
96
+
97
+ mode: str = "none"
98
+ max_turns: int = 12
99
+ simulator_prompt: str | None = None
100
+ decision_patterns: list[str] = field(default_factory=list)
101
+ continue_prompt: str = "Please continue with the next phase of the workflow."
102
+
103
+
104
+ @dataclass
105
+ class TaskConfig:
106
+ """Configuration loaded from task.toml."""
107
+
108
+ name: str
109
+ description: str
110
+ difficulty: str = "medium"
111
+ category: str = ""
112
+ tags: list[str] = field(default_factory=list)
113
+
114
+ # Description of what Claude has access to in this task environment
115
+ environment_description: str = ""
116
+
117
+ # Default treatments to test with this task
118
+ default_treatments: list[str] = field(default_factory=list)
119
+
120
+ # Template variables required for instruction.md
121
+ template_required: list[str] = field(default_factory=list)
122
+
123
+ # Environment settings
124
+ dockerfile: str = "Dockerfile"
125
+ timeout_sec: int = 900
126
+
127
+ # Validation configuration
128
+ validation: ValidationConfig = field(default_factory=ValidationConfig)
129
+
130
+ # Setup configuration
131
+ setup: SetupConfig = field(default_factory=SetupConfig)
132
+
133
+ # Skill-agnostic evaluation contract
134
+ evaluation: EvaluationConfig = field(default_factory=EvaluationConfig)
135
+
136
+ # Interaction / user-simulator configuration
137
+ interaction: InteractionConfig = field(default_factory=InteractionConfig)
138
+
139
+
140
+ @dataclass
141
+ class Task:
142
+ """A self-contained benchmark task."""
143
+
144
+ path: Path
145
+ config: TaskConfig
146
+ instruction_template: str
147
+
148
+ @property
149
+ def name(self) -> str:
150
+ return self.config.name
151
+
152
+ @property
153
+ def environment_dir(self) -> Path:
154
+ return self.path / "environment"
155
+
156
+ @property
157
+ def validation_dir(self) -> Path:
158
+ return self.path / "validation"
159
+
160
+ @property
161
+ def data_dir(self) -> Path:
162
+ return self.path / "data"
163
+
164
+ @property
165
+ def default_treatments(self) -> list[str]:
166
+ return self.config.default_treatments
167
+
168
+ def render_prompt(self, **kwargs: Any) -> str:
169
+ """Render the instruction template with provided variables.
170
+
171
+ Args:
172
+ **kwargs: Template variables (e.g., run_id, py_dataset, ts_dataset)
173
+
174
+ Returns:
175
+ Rendered prompt string
176
+
177
+ Raises:
178
+ KeyError: If a required template variable is missing
179
+ """
180
+ missing = set(self.config.template_required) - set(kwargs.keys())
181
+ if missing:
182
+ raise KeyError(f"Missing required template variables: {missing}")
183
+ prompt = self.instruction_template.format(**kwargs)
184
+ if self.config.evaluation.profile == "comet-workflow":
185
+ return f"{COMET_WORKFLOW_INVOCATION_CONTRACT}\n\n{prompt}"
186
+ return prompt
187
+
188
+ def load_validators(self) -> list:
189
+ """Build validator from task.toml [validation] config.
190
+
191
+ The config specifies test_scripts and target_artifacts. The framework
192
+ auto-builds an execution validator that runs the scripts in Docker.
193
+ """
194
+ vc = self.config.validation
195
+ if vc.test_scripts:
196
+ from scaffold.python.utils import make_execution_validator
197
+
198
+ return [
199
+ make_execution_validator(
200
+ validation_dir=self.validation_dir,
201
+ test_scripts=vc.test_scripts,
202
+ target_artifacts=vc.target_artifacts,
203
+ timeout=vc.timeout,
204
+ data_dir=self.data_dir if self.data_dir.exists() else None,
205
+ )
206
+ ]
207
+
208
+ return []
209
+
210
+
211
+ def load_task(name: str, tasks_dir: Path | None = None) -> Task:
212
+ """Load a task by name.
213
+
214
+ Args:
215
+ name: Task directory name (e.g., "ls-evaluator")
216
+ tasks_dir: Optional custom tasks directory
217
+
218
+ Returns:
219
+ Task object with config and instruction template
220
+ """
221
+ tasks_dir = tasks_dir or get_tasks_dir()
222
+ task_path = tasks_dir / name
223
+
224
+ if not task_path.exists():
225
+ raise FileNotFoundError(f"Task not found: {name} (looked in {tasks_dir})")
226
+
227
+ # Load task.toml
228
+ toml_path = task_path / "task.toml"
229
+ if not toml_path.exists():
230
+ raise FileNotFoundError(f"task.toml not found in {task_path}")
231
+
232
+ with open(toml_path, "rb") as f:
233
+ toml_data = tomllib.load(f)
234
+
235
+ metadata = toml_data.get("metadata", {})
236
+ template = toml_data.get("template", {})
237
+ environment = toml_data.get("environment", {})
238
+ validation = toml_data.get("validation", {})
239
+ evaluation = toml_data.get("evaluation", {})
240
+ interaction = toml_data.get("interaction", {})
241
+ setup_data = toml_data.get("setup", {})
242
+
243
+ # Parse setup config
244
+ data_handlers = [
245
+ DataHandler(pattern=d["pattern"], handler=d["handler"], args=d.get("args", {}))
246
+ for d in setup_data.get("data", [])
247
+ ]
248
+ setup = SetupConfig(
249
+ data_handlers=data_handlers,
250
+ template_vars=setup_data.get("template_vars", {}),
251
+ )
252
+
253
+ validation_config = ValidationConfig(
254
+ test_scripts=validation.get("test_scripts", ""),
255
+ target_artifacts=validation.get("target_artifacts", []),
256
+ timeout=validation.get("timeout", 120),
257
+ )
258
+
259
+ task_name = metadata.get("name", name)
260
+ inferred_profile = evaluation.get("profile")
261
+ if not inferred_profile and (
262
+ metadata.get("category") == "comet" or str(task_name).startswith("comet-")
263
+ ):
264
+ inferred_profile = "comet-workflow"
265
+
266
+ evaluation_config = EvaluationConfig(
267
+ profile=inferred_profile,
268
+ required_skills=evaluation.get("required_skills", []),
269
+ expected_artifacts=evaluation.get("expected_artifacts", []),
270
+ require_skill_invocation=bool(evaluation.get("require_skill_invocation", False)),
271
+ rubric_criteria=evaluation.get("rubric_criteria", []),
272
+ )
273
+
274
+ default_interaction_mode = "auto_user" if inferred_profile == "comet-workflow" else "none"
275
+ interaction_config = InteractionConfig(
276
+ mode=interaction.get("mode", default_interaction_mode),
277
+ max_turns=int(interaction.get("max_turns", 12)),
278
+ simulator_prompt=interaction.get("simulator_prompt"),
279
+ decision_patterns=interaction.get("decision_patterns", []),
280
+ continue_prompt=interaction.get(
281
+ "continue_prompt",
282
+ "Please continue with the next phase of the workflow.",
283
+ ),
284
+ )
285
+
286
+ config = TaskConfig(
287
+ name=task_name,
288
+ description=metadata.get("description", ""),
289
+ difficulty=metadata.get("difficulty", "medium"),
290
+ category=metadata.get("category", ""),
291
+ tags=metadata.get("tags", []),
292
+ environment_description=environment.get("description", ""),
293
+ default_treatments=metadata.get("default_treatments", []),
294
+ template_required=template.get("required", []),
295
+ dockerfile=environment.get("dockerfile", "Dockerfile"),
296
+ timeout_sec=environment.get("timeout_sec", 900),
297
+ validation=validation_config,
298
+ setup=setup,
299
+ evaluation=evaluation_config,
300
+ interaction=interaction_config,
301
+ )
302
+
303
+ # Load instruction.md
304
+ instruction_path = task_path / "instruction.md"
305
+ if not instruction_path.exists():
306
+ raise FileNotFoundError(f"instruction.md not found in {task_path}")
307
+
308
+ instruction_template = instruction_path.read_text(encoding="utf-8")
309
+
310
+ return Task(path=task_path, config=config, instruction_template=instruction_template)
311
+
312
+
313
+ def list_tasks(tasks_dir: Path | None = None) -> list[str]:
314
+ """List available task names.
315
+
316
+ Args:
317
+ tasks_dir: Optional custom tasks directory
318
+
319
+ Returns:
320
+ List of task directory names
321
+ """
322
+ tasks_dir = tasks_dir or get_tasks_dir()
323
+ if not tasks_dir.exists():
324
+ return []
325
+
326
+ return sorted(
327
+ d.name
328
+ for d in tasks_dir.iterdir()
329
+ if d.is_dir() and (d / "task.toml").exists() and (d / "instruction.md").exists()
330
+ )
@@ -0,0 +1,271 @@
1
+ """Treatment loader for comet skill benchmark experiments."""
2
+
3
+ import hashlib
4
+ import re
5
+ from dataclasses import dataclass, field
6
+ from pathlib import Path
7
+ from typing import Any
8
+
9
+ import yaml
10
+
11
+ from scaffold.python.skill_parser import load_skill_variant, skill_config
12
+ from scaffold.python.paths import EVAL_ROOT, get_skills_dir, get_treatments_dir
13
+
14
+ # Only comet-relevant categories
15
+ TREATMENT_CATEGORIES = {
16
+ "common",
17
+ "comet",
18
+ }
19
+
20
+
21
+ @dataclass
22
+ class TreatmentConfig:
23
+ name: str
24
+ description: str
25
+ claude_md: str = ""
26
+ skills: list[dict[str, Any]] = field(default_factory=list)
27
+ noise_tasks: list[str] = field(default_factory=list)
28
+
29
+
30
+ @dataclass
31
+ class SkillSource:
32
+ name: str
33
+ source_type: str
34
+ path: str | None = None
35
+ hash: str = ""
36
+ metadata: dict[str, Any] = field(default_factory=dict)
37
+
38
+
39
+ def _add_language_suffix(content: str, lang: str) -> str:
40
+ suffix = "(Python)" if lang == "py" else "(TypeScript)"
41
+ return re.sub(
42
+ r'^(description: "?)(.+?)("?)$',
43
+ rf"\1\2 {suffix}\3",
44
+ content,
45
+ count=1,
46
+ flags=re.MULTILINE,
47
+ )
48
+
49
+
50
+ def _filter_related_skills(sections: list[str]) -> list[str]:
51
+ return [s for s in sections if s and "<related_skills>" not in s]
52
+
53
+
54
+ def _find_skill_md(path: Path) -> Path:
55
+ if path.is_file():
56
+ if path.name != "SKILL.md":
57
+ raise FileNotFoundError(f"Expected SKILL.md file, got: {path}")
58
+ return path
59
+ skill_md = path / "SKILL.md"
60
+ if not skill_md.exists():
61
+ raise FileNotFoundError(f"SKILL.md not found in {path}")
62
+ return skill_md
63
+
64
+
65
+ def _hash_skill_dir(skill_path: Path) -> str:
66
+ if skill_path.is_file():
67
+ data = skill_path.read_bytes()
68
+ return "sha256:" + hashlib.sha256(data).hexdigest()
69
+ digest = hashlib.sha256()
70
+ for item in sorted(skill_path.rglob("*")):
71
+ if item.is_file():
72
+ digest.update(str(item.relative_to(skill_path)).replace("\\", "/").encode())
73
+ digest.update(item.read_bytes())
74
+ return "sha256:" + digest.hexdigest()
75
+
76
+
77
+ def _build_path_skill_config(name: str, path_value: str) -> dict:
78
+ raw_path = Path(path_value).expanduser()
79
+ source_path = raw_path.resolve()
80
+ if not source_path.exists() and not raw_path.is_absolute():
81
+ source_path = (EVAL_ROOT / raw_path).resolve()
82
+ skill_md = _find_skill_md(source_path)
83
+ skill_dir = skill_md.parent
84
+ scripts_dir = skill_dir / "scripts"
85
+ content = skill_md.read_text(encoding="utf-8")
86
+ cfg = skill_config([content], scripts_dir if scripts_dir.exists() else None, None)
87
+ cfg["source_dir"] = skill_dir
88
+ cfg["source"] = {
89
+ "name": name,
90
+ "source_type": "path",
91
+ "path": str(source_path),
92
+ "hash": _hash_skill_dir(skill_dir),
93
+ }
94
+ return cfg
95
+
96
+
97
+ def _build_skill_config(
98
+ skill_dir: str,
99
+ variant: str = "all",
100
+ suffix: bool = False,
101
+ include_related: bool = False,
102
+ noise: bool = False,
103
+ base: str = "benchmarks",
104
+ included_sections: list[str] | None = None,
105
+ extra_sections: list[str] | None = None,
106
+ section_overrides: dict[str, str] | None = None,
107
+ ) -> dict:
108
+ if base == "main":
109
+ skill_path = get_skills_dir() / "main" / skill_dir
110
+ else:
111
+ skill_path = get_skills_dir() / "benchmarks" / skill_dir
112
+
113
+ if noise:
114
+ noise_path = get_skills_dir() / "noise" / skill_dir
115
+ for filename in ["SKILL.md", "skill.md"]:
116
+ skill_md = noise_path / filename
117
+ if skill_md.exists():
118
+ return skill_config([skill_md.read_text(encoding="utf-8")], None, None)
119
+ return None
120
+
121
+ variant_path = skill_path / f"skill_{variant}.md" if variant else skill_path / "skill.md"
122
+ if variant and not variant_path.exists():
123
+ resolved_md_path = None
124
+ for filename in ["SKILL.md", "skill.md"]:
125
+ if (skill_path / filename).exists():
126
+ resolved_md_path = skill_path / filename
127
+ break
128
+ if resolved_md_path is None:
129
+ raise FileNotFoundError(f"No skill file found in {skill_path}")
130
+ from scaffold.python.skill_parser import get_section_list, parse_skill_md
131
+ sections = parse_skill_md(resolved_md_path)
132
+ all_sections = get_section_list(resolved_md_path)
133
+ scripts_dir = skill_path / "scripts"
134
+ skill = {
135
+ "sections": sections,
136
+ "all": all_sections,
137
+ "scripts_dir": scripts_dir if scripts_dir.exists() else None,
138
+ "script_filter": None,
139
+ }
140
+ else:
141
+ resolved_md_path = variant_path
142
+ skill = load_skill_variant(skill_path, variant)
143
+
144
+ if included_sections:
145
+ sections = []
146
+ for section_name in included_sections:
147
+ if section_overrides and section_name in section_overrides:
148
+ sections.append(section_overrides[section_name])
149
+ elif section_name in skill["sections"]:
150
+ sections.append(skill["sections"][section_name])
151
+ if not include_related:
152
+ sections = _filter_related_skills(sections)
153
+ if extra_sections:
154
+ sections = sections + extra_sections
155
+ content = "\n\n".join(sections)
156
+ elif section_overrides:
157
+ sections = []
158
+ for section_name, content in skill["sections"].items():
159
+ if section_name in section_overrides:
160
+ sections.append(section_overrides[section_name])
161
+ else:
162
+ sections.append(content)
163
+ if not include_related:
164
+ sections = _filter_related_skills(sections)
165
+ if extra_sections:
166
+ sections = sections + extra_sections
167
+ content = "\n\n".join(sections)
168
+ else:
169
+ content = resolved_md_path.read_text(encoding="utf-8")
170
+ if not include_related:
171
+ content = re.sub(
172
+ r"<related_skills>.*?</related_skills>\s*",
173
+ "",
174
+ content,
175
+ flags=re.DOTALL,
176
+ )
177
+ if extra_sections:
178
+ content = content + "\n\n" + "\n\n".join(extra_sections)
179
+
180
+ if suffix and variant in ("py", "ts"):
181
+ content = _add_language_suffix(content, variant)
182
+
183
+ cfg = skill_config([content], skill["scripts_dir"], skill.get("script_filter"))
184
+ cfg["source_dir"] = skill_path
185
+ return cfg
186
+
187
+
188
+ def build_treatment_skills(skill_configs: list[dict[str, Any]]) -> dict[str, dict]:
189
+ skills = {}
190
+ for cfg in skill_configs:
191
+ name = cfg.get("name")
192
+ skill_dir = cfg.get("skill")
193
+ if not name and skill_dir:
194
+ name = skill_dir.replace("_", "-")
195
+ if cfg.get("source") == "path":
196
+ skills[name] = _build_path_skill_config(name, cfg["path"])
197
+ continue
198
+ if "content" in cfg:
199
+ skills[name] = skill_config([cfg["content"]], None, None)
200
+ continue
201
+ variant = cfg.get("variant", "all")
202
+ suffix = cfg.get("suffix", False)
203
+ include_related = cfg.get("include_related", False)
204
+ noise = cfg.get("noise", False)
205
+ base = cfg.get("base", "benchmarks")
206
+ included_sections = cfg.get("included_sections")
207
+ extra_sections = cfg.get("extra_sections")
208
+ section_overrides = cfg.get("section_overrides")
209
+ skill_cfg = _build_skill_config(
210
+ skill_dir=skill_dir, variant=variant, suffix=suffix,
211
+ include_related=include_related, noise=noise, base=base,
212
+ included_sections=included_sections, extra_sections=extra_sections,
213
+ section_overrides=section_overrides,
214
+ )
215
+ if skill_cfg:
216
+ skills[name] = skill_cfg
217
+ return skills
218
+
219
+
220
+ def load_treatments_yaml(path: Path) -> dict[str, TreatmentConfig]:
221
+ if not path.exists():
222
+ raise FileNotFoundError(f"Treatments file not found: {path}")
223
+ with open(path, encoding="utf-8") as f:
224
+ data = yaml.safe_load(f)
225
+ treatments = {}
226
+ for name, cfg in data.items():
227
+ if name.startswith("_"):
228
+ continue
229
+ treatments[name] = TreatmentConfig(
230
+ name=name,
231
+ description=cfg.get("description", ""),
232
+ claude_md=cfg.get("claude_md", ""),
233
+ skills=cfg.get("skills", []),
234
+ noise_tasks=cfg.get("noise_tasks", []),
235
+ )
236
+ return treatments
237
+
238
+
239
+ def load_treatments() -> dict[str, TreatmentConfig]:
240
+ treatments_folder = get_treatments_dir()
241
+ if not treatments_folder.exists():
242
+ return {}
243
+ treatments = {}
244
+ for category in sorted(treatments_folder.iterdir()):
245
+ if not category.is_dir():
246
+ continue
247
+ if category.name not in TREATMENT_CATEGORIES:
248
+ continue
249
+ for yaml_file in sorted(category.glob("*.yaml")):
250
+ category_treatments = load_treatments_yaml(yaml_file)
251
+ treatments.update(category_treatments)
252
+ return treatments
253
+
254
+
255
+ def load_treatment(name: str):
256
+ from scaffold import Treatment
257
+ configs = load_treatments()
258
+ if name not in configs:
259
+ raise KeyError(f"Treatment not found: {name}. Available: {list(configs.keys())}")
260
+ cfg = configs[name]
261
+ skills = build_treatment_skills(cfg.skills) if cfg.skills else {}
262
+ return Treatment(
263
+ description=cfg.description,
264
+ skills=skills,
265
+ claude_md=cfg.claude_md if cfg.claude_md else None,
266
+ validators=[],
267
+ )
268
+
269
+
270
+ def list_treatments() -> list[str]:
271
+ return sorted(load_treatments().keys())