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

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 (605) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +15 -1
  3. package/assets/manifest.json +2 -1
  4. package/assets/skills/comet/SKILL.md +54 -28
  5. package/assets/skills/comet/reference/auto-transition.md +1 -1
  6. package/assets/skills/comet/reference/comet-yaml-fields.md +11 -6
  7. package/assets/skills/comet/reference/context-recovery.md +12 -2
  8. package/assets/skills/comet/reference/decision-point.md +11 -0
  9. package/assets/skills/comet/reference/scripts.md +47 -15
  10. package/assets/skills/comet/reference/subagent-dispatch.md +6 -5
  11. package/assets/skills/comet/rules/comet-phase-guard.en.md +31 -28
  12. package/assets/skills/comet/rules/comet-phase-guard.md +31 -29
  13. package/assets/skills/comet/scripts/comet-resume-probe.mjs +3 -0
  14. package/assets/skills/comet/scripts/comet-runtime.mjs +1568 -476
  15. package/assets/skills/comet-any/SKILL.md +1 -1
  16. package/assets/skills/comet-any/reference/authored-zone-example.md +10 -5
  17. package/assets/skills/comet-any/reference/subagents/pause-points-author.md +14 -11
  18. package/assets/skills/comet-any/reference/subagents/skill-reviewer.md +2 -0
  19. package/assets/skills/comet-any/reference/subagents/workflow-entry-author.md +5 -4
  20. package/assets/skills/comet-archive/SKILL.md +52 -18
  21. package/assets/skills/comet-build/SKILL.md +64 -45
  22. package/assets/skills/comet-design/SKILL.md +24 -22
  23. package/assets/skills/comet-hotfix/SKILL.md +37 -34
  24. package/assets/skills/comet-open/SKILL.md +106 -57
  25. package/assets/skills/comet-tweak/SKILL.md +23 -18
  26. package/assets/skills/comet-verify/SKILL.md +57 -72
  27. package/assets/skills-zh/comet/SKILL.md +54 -28
  28. package/assets/skills-zh/comet/reference/auto-transition.md +1 -1
  29. package/assets/skills-zh/comet/reference/comet-yaml-fields.md +11 -6
  30. package/assets/skills-zh/comet/reference/context-recovery.md +12 -2
  31. package/assets/skills-zh/comet/reference/decision-point.md +11 -0
  32. package/assets/skills-zh/comet/reference/scripts.md +47 -15
  33. package/assets/skills-zh/comet/reference/subagent-dispatch.md +6 -5
  34. package/assets/skills-zh/comet-any/SKILL.md +1 -1
  35. package/assets/skills-zh/comet-any/reference/authored-zone-example.md +10 -5
  36. package/assets/skills-zh/comet-any/reference/subagents/pause-points-author.md +14 -12
  37. package/assets/skills-zh/comet-any/reference/subagents/skill-reviewer.md +2 -0
  38. package/assets/skills-zh/comet-any/reference/subagents/workflow-entry-author.md +5 -4
  39. package/assets/skills-zh/comet-archive/SKILL.md +52 -18
  40. package/assets/skills-zh/comet-build/SKILL.md +64 -45
  41. package/assets/skills-zh/comet-design/SKILL.md +24 -22
  42. package/assets/skills-zh/comet-hotfix/SKILL.md +36 -33
  43. package/assets/skills-zh/comet-open/SKILL.md +105 -56
  44. package/assets/skills-zh/comet-tweak/SKILL.md +22 -17
  45. package/assets/skills-zh/comet-verify/SKILL.md +57 -72
  46. package/dist/app/cli/comet-banner.d.ts +25 -0
  47. package/dist/app/cli/comet-banner.d.ts.map +1 -0
  48. package/dist/app/cli/comet-banner.js +265 -0
  49. package/dist/app/cli/comet-banner.js.map +1 -0
  50. package/dist/app/cli/index.js +36 -2
  51. package/dist/app/cli/index.js.map +1 -1
  52. package/dist/app/commands/classic.d.ts +4 -0
  53. package/dist/app/commands/classic.d.ts.map +1 -0
  54. package/dist/app/commands/classic.js +11 -0
  55. package/dist/app/commands/classic.js.map +1 -0
  56. package/dist/app/commands/doctor.d.ts.map +1 -1
  57. package/dist/app/commands/doctor.js +99 -37
  58. package/dist/app/commands/doctor.js.map +1 -1
  59. package/dist/app/commands/eval.d.ts.map +1 -1
  60. package/dist/app/commands/eval.js +57 -20
  61. package/dist/app/commands/eval.js.map +1 -1
  62. package/dist/app/commands/i18n.d.ts +1 -1
  63. package/dist/app/commands/i18n.d.ts.map +1 -1
  64. package/dist/app/commands/i18n.js +12 -4
  65. package/dist/app/commands/i18n.js.map +1 -1
  66. package/dist/app/commands/init.d.ts +1 -1
  67. package/dist/app/commands/init.d.ts.map +1 -1
  68. package/dist/app/commands/init.js +72 -25
  69. package/dist/app/commands/init.js.map +1 -1
  70. package/dist/app/commands/project-scope-selection.d.ts +13 -0
  71. package/dist/app/commands/project-scope-selection.d.ts.map +1 -0
  72. package/dist/app/commands/project-scope-selection.js +33 -0
  73. package/dist/app/commands/project-scope-selection.js.map +1 -0
  74. package/dist/app/commands/resume-probe.d.ts +11 -0
  75. package/dist/app/commands/resume-probe.d.ts.map +1 -0
  76. package/dist/app/commands/resume-probe.js +63 -0
  77. package/dist/app/commands/resume-probe.js.map +1 -0
  78. package/dist/app/commands/status.d.ts +31 -0
  79. package/dist/app/commands/status.d.ts.map +1 -1
  80. package/dist/app/commands/status.js +109 -20
  81. package/dist/app/commands/status.js.map +1 -1
  82. package/dist/app/commands/uninstall.d.ts +5 -0
  83. package/dist/app/commands/uninstall.d.ts.map +1 -1
  84. package/dist/app/commands/uninstall.js +264 -53
  85. package/dist/app/commands/uninstall.js.map +1 -1
  86. package/dist/app/commands/update.d.ts +6 -0
  87. package/dist/app/commands/update.d.ts.map +1 -1
  88. package/dist/app/commands/update.js +558 -86
  89. package/dist/app/commands/update.js.map +1 -1
  90. package/dist/config/repository-layout.json +4 -2
  91. package/dist/domains/bundle/bundle-platform.d.ts +1 -0
  92. package/dist/domains/bundle/bundle-platform.d.ts.map +1 -1
  93. package/dist/domains/bundle/bundle-platform.js +9 -3
  94. package/dist/domains/bundle/bundle-platform.js.map +1 -1
  95. package/dist/domains/bundle/eval-manifest-runtime.d.ts +6 -0
  96. package/dist/domains/bundle/eval-manifest-runtime.d.ts.map +1 -0
  97. package/dist/domains/bundle/eval-manifest-runtime.js +58 -0
  98. package/dist/domains/bundle/eval-manifest-runtime.js.map +1 -0
  99. package/dist/domains/bundle/types.d.ts +1 -1
  100. package/dist/domains/bundle/types.d.ts.map +1 -1
  101. package/dist/domains/comet-classic/classic-archive.d.ts +1 -0
  102. package/dist/domains/comet-classic/classic-archive.d.ts.map +1 -1
  103. package/dist/domains/comet-classic/classic-archive.js +35 -38
  104. package/dist/domains/comet-classic/classic-archive.js.map +1 -1
  105. package/dist/domains/comet-classic/classic-cli.d.ts +1 -1
  106. package/dist/domains/comet-classic/classic-cli.d.ts.map +1 -1
  107. package/dist/domains/comet-classic/classic-cli.js +3 -0
  108. package/dist/domains/comet-classic/classic-cli.js.map +1 -1
  109. package/dist/domains/comet-classic/classic-command-checks.d.ts +20 -0
  110. package/dist/domains/comet-classic/classic-command-checks.d.ts.map +1 -0
  111. package/dist/domains/comet-classic/classic-command-checks.js +97 -0
  112. package/dist/domains/comet-classic/classic-command-checks.js.map +1 -0
  113. package/dist/domains/comet-classic/classic-current-change.d.ts +19 -0
  114. package/dist/domains/comet-classic/classic-current-change.d.ts.map +1 -0
  115. package/dist/domains/comet-classic/classic-current-change.js +132 -0
  116. package/dist/domains/comet-classic/classic-current-change.js.map +1 -0
  117. package/dist/domains/comet-classic/classic-diagnostics.d.ts +2 -1
  118. package/dist/domains/comet-classic/classic-diagnostics.d.ts.map +1 -1
  119. package/dist/domains/comet-classic/classic-diagnostics.js +54 -1
  120. package/dist/domains/comet-classic/classic-diagnostics.js.map +1 -1
  121. package/dist/domains/comet-classic/classic-evidence.d.ts.map +1 -1
  122. package/dist/domains/comet-classic/classic-evidence.js +4 -0
  123. package/dist/domains/comet-classic/classic-evidence.js.map +1 -1
  124. package/dist/domains/comet-classic/classic-guard.d.ts.map +1 -1
  125. package/dist/domains/comet-classic/classic-guard.js +83 -80
  126. package/dist/domains/comet-classic/classic-guard.js.map +1 -1
  127. package/dist/domains/comet-classic/classic-hook-guard.d.ts.map +1 -1
  128. package/dist/domains/comet-classic/classic-hook-guard.js +179 -42
  129. package/dist/domains/comet-classic/classic-hook-guard.js.map +1 -1
  130. package/dist/domains/comet-classic/classic-project-config.d.ts +16 -0
  131. package/dist/domains/comet-classic/classic-project-config.d.ts.map +1 -0
  132. package/dist/domains/comet-classic/classic-project-config.js +40 -0
  133. package/dist/domains/comet-classic/classic-project-config.js.map +1 -0
  134. package/dist/domains/comet-classic/classic-resolver.d.ts.map +1 -1
  135. package/dist/domains/comet-classic/classic-resolver.js +4 -4
  136. package/dist/domains/comet-classic/classic-resolver.js.map +1 -1
  137. package/dist/domains/comet-classic/classic-resume-probe-command.d.ts +3 -0
  138. package/dist/domains/comet-classic/classic-resume-probe-command.d.ts.map +1 -0
  139. package/dist/domains/comet-classic/classic-resume-probe-command.js +58 -0
  140. package/dist/domains/comet-classic/classic-resume-probe-command.js.map +1 -0
  141. package/dist/domains/comet-classic/classic-resume-probe-entry.d.ts +2 -0
  142. package/dist/domains/comet-classic/classic-resume-probe-entry.d.ts.map +1 -0
  143. package/dist/domains/comet-classic/classic-resume-probe-entry.js +4 -0
  144. package/dist/domains/comet-classic/classic-resume-probe-entry.js.map +1 -0
  145. package/dist/domains/comet-classic/classic-resume-probe.d.ts +29 -0
  146. package/dist/domains/comet-classic/classic-resume-probe.d.ts.map +1 -0
  147. package/dist/domains/comet-classic/classic-resume-probe.js +386 -0
  148. package/dist/domains/comet-classic/classic-resume-probe.js.map +1 -0
  149. package/dist/domains/comet-classic/classic-runtime-run.d.ts +2 -1
  150. package/dist/domains/comet-classic/classic-runtime-run.d.ts.map +1 -1
  151. package/dist/domains/comet-classic/classic-runtime-run.js +38 -0
  152. package/dist/domains/comet-classic/classic-runtime-run.js.map +1 -1
  153. package/dist/domains/comet-classic/classic-state-command.d.ts.map +1 -1
  154. package/dist/domains/comet-classic/classic-state-command.js +150 -25
  155. package/dist/domains/comet-classic/classic-state-command.js.map +1 -1
  156. package/dist/domains/comet-classic/classic-state.d.ts +5 -2
  157. package/dist/domains/comet-classic/classic-state.d.ts.map +1 -1
  158. package/dist/domains/comet-classic/classic-state.js +17 -1
  159. package/dist/domains/comet-classic/classic-state.js.map +1 -1
  160. package/dist/domains/comet-classic/classic-store.d.ts +4 -1
  161. package/dist/domains/comet-classic/classic-store.d.ts.map +1 -1
  162. package/dist/domains/comet-classic/classic-store.js +4 -3
  163. package/dist/domains/comet-classic/classic-store.js.map +1 -1
  164. package/dist/domains/comet-classic/classic-transitions.d.ts +1 -1
  165. package/dist/domains/comet-classic/classic-transitions.d.ts.map +1 -1
  166. package/dist/domains/comet-classic/classic-transitions.js +36 -3
  167. package/dist/domains/comet-classic/classic-transitions.js.map +1 -1
  168. package/dist/domains/comet-classic/classic-validate-command.d.ts.map +1 -1
  169. package/dist/domains/comet-classic/classic-validate-command.js +8 -1
  170. package/dist/domains/comet-classic/classic-validate-command.js.map +1 -1
  171. package/dist/domains/comet-classic/index.d.ts +3 -0
  172. package/dist/domains/comet-classic/index.d.ts.map +1 -1
  173. package/dist/domains/comet-classic/index.js +3 -0
  174. package/dist/domains/comet-classic/index.js.map +1 -1
  175. package/dist/domains/dashboard/collector.js +10 -2
  176. package/dist/domains/dashboard/collector.js.map +1 -1
  177. package/dist/domains/dashboard/web/assets/_commonjsHelpers-CqkleIqs.js +1 -0
  178. package/dist/domains/dashboard/web/assets/arc-TGVUG2WN.js +1 -0
  179. package/dist/domains/dashboard/web/assets/architectureDiagram-3BPJPVTR-ASHmiHoP.js +36 -0
  180. package/dist/domains/dashboard/web/assets/blockDiagram-GPEHLZMM-CwASxBKe.js +132 -0
  181. package/dist/domains/dashboard/web/assets/c4Diagram-AAUBKEIU-BU8z_WNk.js +10 -0
  182. package/dist/domains/dashboard/web/assets/channel-kp6Ng2JJ.js +1 -0
  183. package/dist/domains/dashboard/web/assets/chunk-2J33WTMH-CBGlUx4_.js +1 -0
  184. package/dist/domains/dashboard/web/assets/chunk-4BX2VUAB-CS-iGcFz.js +1 -0
  185. package/dist/domains/dashboard/web/assets/chunk-55IACEB6-BUtCVJat.js +1 -0
  186. package/dist/domains/dashboard/web/assets/chunk-727SXJPM-C94tj_pf.js +206 -0
  187. package/dist/domains/dashboard/web/assets/chunk-AQP2D5EJ-BFOKcpdG.js +231 -0
  188. package/dist/domains/dashboard/web/assets/chunk-FMBD7UC4-Dmx8B-st.js +15 -0
  189. package/dist/domains/dashboard/web/assets/chunk-ND2GUHAM-DYV00CNn.js +1 -0
  190. package/dist/domains/dashboard/web/assets/chunk-QZHKN3VN-DMJJyQnw.js +1 -0
  191. package/dist/domains/dashboard/web/assets/classDiagram-4FO5ZUOK-yBDjgMY_.js +1 -0
  192. package/dist/domains/dashboard/web/assets/classDiagram-v2-Q7XG4LA2-yBDjgMY_.js +1 -0
  193. package/dist/domains/dashboard/web/assets/cose-bilkent-S5V4N54A-P4nE2rea.js +1 -0
  194. package/dist/domains/dashboard/web/assets/cynefin-VYW2F7L2-C-R1HXDv.js +166 -0
  195. package/dist/domains/dashboard/web/assets/cytoscape.esm-D3_iZ_3b.js +321 -0
  196. package/dist/domains/dashboard/web/assets/dagre-BM42HDAG-BH8d-C9z.js +4 -0
  197. package/dist/domains/dashboard/web/assets/defaultLocale-DX6XiGOO.js +1 -0
  198. package/dist/domains/dashboard/web/assets/diagram-2AECGRRQ-DpXTgQIH.js +43 -0
  199. package/dist/domains/dashboard/web/assets/diagram-5GNKFQAL-DSiFJzSw.js +10 -0
  200. package/dist/domains/dashboard/web/assets/diagram-KO2AKTUF-DULMkben.js +3 -0
  201. package/dist/domains/dashboard/web/assets/diagram-LMA3HP47-Pi8m_NO9.js +24 -0
  202. package/dist/domains/dashboard/web/assets/diagram-OG6HWLK6-BSe6bCWm.js +24 -0
  203. package/dist/domains/dashboard/web/assets/erDiagram-TEJ5UH35-zb-FEcbq.js +85 -0
  204. package/dist/domains/dashboard/web/assets/flowDiagram-I6XJVG4X-Dr-Gk0z2.js +162 -0
  205. package/dist/domains/dashboard/web/assets/ganttDiagram-6RSMTGT7-qs6Zb2A6.js +292 -0
  206. package/dist/domains/dashboard/web/assets/gitGraphDiagram-PVQCEYII-BQ314orT.js +106 -0
  207. package/dist/domains/dashboard/web/assets/graph--OzhPTMs.js +1 -0
  208. package/dist/domains/dashboard/web/assets/index-BLAfkNTu.css +1 -0
  209. package/dist/domains/dashboard/web/assets/index-DlSYK56b.js +139 -0
  210. package/dist/domains/dashboard/web/assets/index-DtLUOcAW.js +24 -0
  211. package/dist/domains/dashboard/web/assets/index-QO0z6F4w.js +10 -0
  212. package/dist/domains/dashboard/web/assets/infoDiagram-5YYISTIA-O0bQp98A.js +2 -0
  213. package/dist/domains/dashboard/web/assets/init-Gi6I4Gst.js +1 -0
  214. package/dist/domains/dashboard/web/assets/ishikawaDiagram-YF4QCWOH-BPC7wbKh.js +70 -0
  215. package/dist/domains/dashboard/web/assets/journeyDiagram-JHISSGLW-ohViOd4b.js +139 -0
  216. package/dist/domains/dashboard/web/assets/kanban-definition-UN3LZRKU-CHleNdbG.js +89 -0
  217. package/dist/domains/dashboard/web/assets/katex-HP8lGamR.js +257 -0
  218. package/dist/domains/dashboard/web/assets/layout-SsrduOYp.js +1 -0
  219. package/dist/domains/dashboard/web/assets/linear-CyqiW--Q.js +1 -0
  220. package/dist/domains/dashboard/web/assets/marked.esm-DECB3bxB.js +64 -0
  221. package/dist/domains/dashboard/web/assets/mermaid.core-qS9XvtaK.js +301 -0
  222. package/dist/domains/dashboard/web/assets/mindmap-definition-RKZ34NQL-oaGkqO9l.js +96 -0
  223. package/dist/domains/dashboard/web/assets/ordinal-Cboi1Yqb.js +1 -0
  224. package/dist/domains/dashboard/web/assets/pieDiagram-4H26LBE5-CPcB-AFh.js +30 -0
  225. package/dist/domains/dashboard/web/assets/purify.es-VaSPOPhr.js +3 -0
  226. package/dist/domains/dashboard/web/assets/quadrantDiagram-W4KKPZXB-LFy52Qtj.js +7 -0
  227. package/dist/domains/dashboard/web/assets/requirementDiagram-4Y6WPE33-BdjeaYP_.js +84 -0
  228. package/dist/domains/dashboard/web/assets/sankeyDiagram-5OEKKPKP-DDJ4styL.js +40 -0
  229. package/dist/domains/dashboard/web/assets/sequenceDiagram-3UESZ5HK-BL5bFNoz.js +162 -0
  230. package/dist/domains/dashboard/web/assets/stateDiagram-AJRCARHV-BNUfikui.js +1 -0
  231. package/dist/domains/dashboard/web/assets/stateDiagram-v2-BHNVJYJU-DGrsmWts.js +1 -0
  232. package/dist/domains/dashboard/web/assets/timeline-definition-PNZ67QCA--ps2uu6L.js +120 -0
  233. package/dist/domains/dashboard/web/assets/vennDiagram-CIIHVFJN-C2q8q26c.js +34 -0
  234. package/dist/domains/dashboard/web/assets/wardleyDiagram-YWT4CUSO-BUH9gXqd.js +78 -0
  235. package/dist/domains/dashboard/web/assets/xychartDiagram-2RQKCTM6-B-DielEy.js +7 -0
  236. package/dist/domains/dashboard/web/index.html +16 -16
  237. package/dist/domains/engine/types.d.ts +1 -1
  238. package/dist/domains/engine/types.d.ts.map +1 -1
  239. package/dist/domains/factory/package.d.ts.map +1 -1
  240. package/dist/domains/factory/package.js +20 -6
  241. package/dist/domains/factory/package.js.map +1 -1
  242. package/dist/domains/integrations/openspec.d.ts +4 -1
  243. package/dist/domains/integrations/openspec.d.ts.map +1 -1
  244. package/dist/domains/integrations/openspec.js +62 -10
  245. package/dist/domains/integrations/openspec.js.map +1 -1
  246. package/dist/domains/skill/find.d.ts.map +1 -1
  247. package/dist/domains/skill/find.js +1 -6
  248. package/dist/domains/skill/find.js.map +1 -1
  249. package/dist/domains/skill/json-object.d.ts +13 -0
  250. package/dist/domains/skill/json-object.d.ts.map +1 -0
  251. package/dist/domains/skill/json-object.js +24 -0
  252. package/dist/domains/skill/json-object.js.map +1 -0
  253. package/dist/domains/skill/managed-markdown.d.ts +14 -0
  254. package/dist/domains/skill/managed-markdown.d.ts.map +1 -0
  255. package/dist/domains/skill/managed-markdown.js +126 -0
  256. package/dist/domains/skill/managed-markdown.js.map +1 -0
  257. package/dist/domains/skill/platform-inspect.d.ts +9 -0
  258. package/dist/domains/skill/platform-inspect.d.ts.map +1 -0
  259. package/dist/domains/skill/platform-inspect.js +149 -0
  260. package/dist/domains/skill/platform-inspect.js.map +1 -0
  261. package/dist/domains/skill/platform-install.d.ts +20 -9
  262. package/dist/domains/skill/platform-install.d.ts.map +1 -1
  263. package/dist/domains/skill/platform-install.js +356 -153
  264. package/dist/domains/skill/platform-install.js.map +1 -1
  265. package/dist/domains/skill/project-instructions.d.ts +22 -0
  266. package/dist/domains/skill/project-instructions.d.ts.map +1 -0
  267. package/dist/domains/skill/project-instructions.js +61 -0
  268. package/dist/domains/skill/project-instructions.js.map +1 -0
  269. package/dist/domains/skill/uninstall.d.ts +3 -1
  270. package/dist/domains/skill/uninstall.d.ts.map +1 -1
  271. package/dist/domains/skill/uninstall.js +259 -149
  272. package/dist/domains/skill/uninstall.js.map +1 -1
  273. package/dist/platform/fs/file-system.d.ts +3 -3
  274. package/dist/platform/fs/file-system.d.ts.map +1 -1
  275. package/dist/platform/fs/file-system.js +21 -11
  276. package/dist/platform/fs/file-system.js.map +1 -1
  277. package/dist/platform/install/detect.d.ts +2 -1
  278. package/dist/platform/install/detect.d.ts.map +1 -1
  279. package/dist/platform/install/detect.js +10 -1
  280. package/dist/platform/install/detect.js.map +1 -1
  281. package/dist/platform/install/platforms.d.ts +9 -1
  282. package/dist/platform/install/platforms.d.ts.map +1 -1
  283. package/dist/platform/install/platforms.js +23 -4
  284. package/dist/platform/install/platforms.js.map +1 -1
  285. package/dist/platform/install/project-registry.d.ts +38 -0
  286. package/dist/platform/install/project-registry.d.ts.map +1 -0
  287. package/dist/platform/install/project-registry.js +213 -0
  288. package/dist/platform/install/project-registry.js.map +1 -0
  289. package/dist/platform/install/skill-root-owner.d.ts +15 -0
  290. package/dist/platform/install/skill-root-owner.d.ts.map +1 -0
  291. package/dist/platform/install/skill-root-owner.js +68 -0
  292. package/dist/platform/install/skill-root-owner.js.map +1 -0
  293. package/eval/.env.example +52 -0
  294. package/eval/CLAUDE.md +43 -0
  295. package/eval/README.md +538 -0
  296. package/eval/langsmith/.env.example +16 -0
  297. package/eval/langsmith/README.md +93 -0
  298. package/eval/langsmith/skills/README.md +5 -0
  299. package/eval/langsmith/tasks/README.md +5 -0
  300. package/eval/langsmith/tests/conftest.py +187 -0
  301. package/eval/langsmith/tests/tasks/test_tasks.py +287 -0
  302. package/eval/langsmith/treatments/README.md +5 -0
  303. package/eval/local/README.md +80 -0
  304. package/eval/local/regression_baseline.json +13 -0
  305. package/eval/local/report-style-demo-assets/quality_cost.en.svg +41 -0
  306. package/eval/local/report-style-demo-assets/quality_cost.zh.svg +41 -0
  307. package/eval/local/report-style-demo-assets/rubric_delta.en.svg +56 -0
  308. package/eval/local/report-style-demo-assets/rubric_delta.zh.svg +56 -0
  309. package/eval/local/report-style-demo-assets/task_outcomes.en.svg +46 -0
  310. package/eval/local/report-style-demo-assets/task_outcomes.zh.svg +46 -0
  311. package/eval/local/report-style-demo.html +867 -0
  312. package/eval/local/scripts/compare_baselines.py +1018 -0
  313. package/eval/local/scripts/generate_report_style_demo_charts.py +322 -0
  314. package/eval/local/scripts/regression_check.py +171 -0
  315. package/eval/local/scripts/render_readme_benchmark_figures.py +416 -0
  316. package/eval/local/scripts/rescore_rubric.py +120 -0
  317. package/eval/local/skills/benchmarks/039-release/comet-classic-039/SKILL.md +282 -0
  318. package/eval/local/skills/benchmarks/039-release/comet-classic-039/reference/auto-transition.md +27 -0
  319. package/eval/local/skills/benchmarks/039-release/comet-classic-039/reference/comet-yaml-fields.md +68 -0
  320. package/eval/local/skills/benchmarks/039-release/comet-classic-039/reference/context-recovery.md +35 -0
  321. package/eval/local/skills/benchmarks/039-release/comet-classic-039/reference/debug-gate.md +17 -0
  322. package/eval/local/skills/benchmarks/039-release/comet-classic-039/reference/decision-point.md +20 -0
  323. package/eval/local/skills/benchmarks/039-release/comet-classic-039/reference/dirty-worktree.md +59 -0
  324. package/eval/local/skills/benchmarks/039-release/comet-classic-039/reference/file-structure.md +28 -0
  325. package/eval/local/skills/benchmarks/039-release/comet-classic-039/reference/subagent-dispatch.md +113 -0
  326. package/eval/local/skills/benchmarks/039-release/comet-classic-039/rules/comet-phase-guard.md +125 -0
  327. package/eval/local/skills/benchmarks/039-release/comet-classic-039/scripts/comet-archive.sh +311 -0
  328. package/eval/local/skills/benchmarks/039-release/comet-classic-039/scripts/comet-env.sh +110 -0
  329. package/eval/local/skills/benchmarks/039-release/comet-classic-039/scripts/comet-guard.sh +778 -0
  330. package/eval/local/skills/benchmarks/039-release/comet-classic-039/scripts/comet-handoff.sh +390 -0
  331. package/eval/local/skills/benchmarks/039-release/comet-classic-039/scripts/comet-hook-guard.sh +336 -0
  332. package/eval/local/skills/benchmarks/039-release/comet-classic-039/scripts/comet-state.sh +1338 -0
  333. package/eval/local/skills/benchmarks/039-release/comet-classic-039/scripts/comet-yaml-validate.sh +225 -0
  334. package/eval/local/skills/benchmarks/039-release/comet-classic-039-archive/SKILL.md +100 -0
  335. package/eval/local/skills/benchmarks/039-release/comet-classic-039-build/SKILL.md +304 -0
  336. package/eval/local/skills/benchmarks/039-release/comet-classic-039-design/SKILL.md +263 -0
  337. package/eval/local/skills/benchmarks/039-release/comet-classic-039-hotfix/SKILL.md +204 -0
  338. package/eval/local/skills/benchmarks/039-release/comet-classic-039-open/SKILL.md +220 -0
  339. package/eval/local/skills/benchmarks/039-release/comet-classic-039-tweak/SKILL.md +180 -0
  340. package/eval/local/skills/benchmarks/039-release/comet-classic-039-verify/SKILL.md +234 -0
  341. package/eval/local/skills/benchmarks/040-beta/comet/SKILL.md +261 -0
  342. package/eval/local/skills/benchmarks/040-beta/comet/reference/auto-transition.md +27 -0
  343. package/eval/local/skills/benchmarks/040-beta/comet/reference/comet-yaml-fields.md +73 -0
  344. package/eval/local/skills/benchmarks/040-beta/comet/reference/context-recovery.md +45 -0
  345. package/eval/local/skills/benchmarks/040-beta/comet/reference/debug-gate.md +33 -0
  346. package/eval/local/skills/benchmarks/040-beta/comet/reference/decision-point.md +31 -0
  347. package/eval/local/skills/benchmarks/040-beta/comet/reference/dirty-worktree.md +59 -0
  348. package/eval/local/skills/benchmarks/040-beta/comet/reference/file-structure.md +28 -0
  349. package/eval/local/skills/benchmarks/040-beta/comet/reference/intent-frame.md +74 -0
  350. package/eval/local/skills/benchmarks/040-beta/comet/reference/scripts.md +69 -0
  351. package/eval/local/skills/benchmarks/040-beta/comet/reference/subagent-dispatch.md +169 -0
  352. package/eval/local/skills/benchmarks/040-beta/comet/rules/comet-phase-guard.md +130 -0
  353. package/eval/local/skills/benchmarks/040-beta/comet/runtime/classic/checks.yaml +6 -0
  354. package/eval/local/skills/benchmarks/040-beta/comet/runtime/classic/guardrails.yaml +13 -0
  355. package/eval/local/skills/benchmarks/040-beta/comet/runtime/classic/skill.yaml +122 -0
  356. package/eval/local/skills/benchmarks/040-beta/comet/scripts/comet-archive.mjs +9515 -0
  357. package/eval/local/skills/benchmarks/040-beta/comet/scripts/comet-env.mjs +15 -0
  358. package/eval/local/skills/benchmarks/040-beta/comet/scripts/comet-guard.mjs +10173 -0
  359. package/eval/local/skills/benchmarks/040-beta/comet/scripts/comet-handoff.mjs +9491 -0
  360. package/eval/local/skills/benchmarks/040-beta/comet/scripts/comet-hook-guard.mjs +9175 -0
  361. package/eval/local/skills/benchmarks/040-beta/comet/scripts/comet-intent.mjs +404 -0
  362. package/eval/local/skills/benchmarks/040-beta/comet/scripts/comet-state.mjs +9273 -0
  363. package/eval/local/skills/benchmarks/040-beta/comet/scripts/comet-yaml-validate.mjs +7627 -0
  364. package/eval/local/skills/benchmarks/040-beta/comet-archive/SKILL.md +110 -0
  365. package/eval/local/skills/benchmarks/040-beta/comet-build/SKILL.md +315 -0
  366. package/eval/local/skills/benchmarks/040-beta/comet-design/SKILL.md +260 -0
  367. package/eval/local/skills/benchmarks/040-beta/comet-hotfix/SKILL.md +190 -0
  368. package/eval/local/skills/benchmarks/040-beta/comet-open/SKILL.md +210 -0
  369. package/eval/local/skills/benchmarks/040-beta/comet-tweak/SKILL.md +183 -0
  370. package/eval/local/skills/benchmarks/040-beta/comet-verify/SKILL.md +230 -0
  371. package/eval/local/skills/benchmarks/dependency/claude-md/comet-workflow/CLAUDE.md +12 -0
  372. package/eval/local/skills/benchmarks/dependency/openspec/openspec-apply-change/SKILL.md +156 -0
  373. package/eval/local/skills/benchmarks/dependency/openspec/openspec-archive-change/SKILL.md +114 -0
  374. package/eval/local/skills/benchmarks/dependency/openspec/openspec-bulk-archive-change/SKILL.md +246 -0
  375. package/eval/local/skills/benchmarks/dependency/openspec/openspec-continue-change/SKILL.md +118 -0
  376. package/eval/local/skills/benchmarks/dependency/openspec/openspec-explore/SKILL.md +288 -0
  377. package/eval/local/skills/benchmarks/dependency/openspec/openspec-ff-change/SKILL.md +101 -0
  378. package/eval/local/skills/benchmarks/dependency/openspec/openspec-new-change/SKILL.md +74 -0
  379. package/eval/local/skills/benchmarks/dependency/openspec/openspec-onboard/SKILL.md +554 -0
  380. package/eval/local/skills/benchmarks/dependency/openspec/openspec-propose/SKILL.md +110 -0
  381. package/eval/local/skills/benchmarks/dependency/openspec/openspec-sync-specs/SKILL.md +138 -0
  382. package/eval/local/skills/benchmarks/dependency/openspec/openspec-verify-change/SKILL.md +168 -0
  383. package/eval/local/skills/benchmarks/dependency/superpowers/brainstorming/SKILL.md +159 -0
  384. package/eval/local/skills/benchmarks/dependency/superpowers/brainstorming/scripts/frame-template.html +213 -0
  385. package/eval/local/skills/benchmarks/dependency/superpowers/brainstorming/scripts/helper.js +167 -0
  386. package/eval/local/skills/benchmarks/dependency/superpowers/brainstorming/scripts/server.cjs +723 -0
  387. package/eval/local/skills/benchmarks/dependency/superpowers/brainstorming/scripts/start-server.sh +209 -0
  388. package/eval/local/skills/benchmarks/dependency/superpowers/brainstorming/scripts/stop-server.sh +120 -0
  389. package/eval/local/skills/benchmarks/dependency/superpowers/brainstorming/spec-document-reviewer-prompt.md +49 -0
  390. package/eval/local/skills/benchmarks/dependency/superpowers/brainstorming/visual-companion.md +291 -0
  391. package/eval/local/skills/benchmarks/dependency/superpowers/dispatching-parallel-agents/SKILL.md +185 -0
  392. package/eval/local/skills/benchmarks/dependency/superpowers/executing-plans/SKILL.md +70 -0
  393. package/eval/local/skills/benchmarks/dependency/superpowers/finishing-a-development-branch/SKILL.md +241 -0
  394. package/eval/local/skills/benchmarks/dependency/superpowers/receiving-code-review/SKILL.md +213 -0
  395. package/eval/local/skills/benchmarks/dependency/superpowers/requesting-code-review/SKILL.md +103 -0
  396. package/eval/local/skills/benchmarks/dependency/superpowers/requesting-code-review/code-reviewer.md +172 -0
  397. package/eval/local/skills/benchmarks/dependency/superpowers/subagent-driven-development/SKILL.md +418 -0
  398. package/eval/local/skills/benchmarks/dependency/superpowers/subagent-driven-development/implementer-prompt.md +139 -0
  399. package/eval/local/skills/benchmarks/dependency/superpowers/subagent-driven-development/scripts/review-package +44 -0
  400. package/eval/local/skills/benchmarks/dependency/superpowers/subagent-driven-development/scripts/sdd-workspace +22 -0
  401. package/eval/local/skills/benchmarks/dependency/superpowers/subagent-driven-development/scripts/task-brief +40 -0
  402. package/eval/local/skills/benchmarks/dependency/superpowers/subagent-driven-development/task-reviewer-prompt.md +188 -0
  403. package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/CREATION-LOG.md +119 -0
  404. package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/SKILL.md +296 -0
  405. package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/condition-based-waiting-example.ts +158 -0
  406. package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/condition-based-waiting.md +115 -0
  407. package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/defense-in-depth.md +122 -0
  408. package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/find-polluter.sh +63 -0
  409. package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/root-cause-tracing.md +169 -0
  410. package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/test-academic.md +14 -0
  411. package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/test-pressure-1.md +58 -0
  412. package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/test-pressure-2.md +68 -0
  413. package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/test-pressure-3.md +69 -0
  414. package/eval/local/skills/benchmarks/dependency/superpowers/test-driven-development/SKILL.md +371 -0
  415. package/eval/local/skills/benchmarks/dependency/superpowers/test-driven-development/testing-anti-patterns.md +299 -0
  416. package/eval/local/skills/benchmarks/dependency/superpowers/using-git-worktrees/SKILL.md +202 -0
  417. package/eval/local/skills/benchmarks/dependency/superpowers/verification-before-completion/SKILL.md +139 -0
  418. package/eval/local/skills/benchmarks/dependency/superpowers/writing-plans/SKILL.md +174 -0
  419. package/eval/local/skills/benchmarks/dependency/superpowers/writing-plans/plan-document-reviewer-prompt.md +49 -0
  420. package/eval/local/skills/benchmarks/dependency/superpowers/writing-skills/SKILL.md +689 -0
  421. package/eval/local/skills/benchmarks/dependency/superpowers/writing-skills/anthropic-best-practices.md +1150 -0
  422. package/eval/local/skills/benchmarks/dependency/superpowers/writing-skills/examples/CLAUDE_MD_TESTING.md +189 -0
  423. package/eval/local/skills/benchmarks/dependency/superpowers/writing-skills/graphviz-conventions.dot +172 -0
  424. package/eval/local/skills/benchmarks/dependency/superpowers/writing-skills/persuasion-principles.md +187 -0
  425. package/eval/local/skills/benchmarks/dependency/superpowers/writing-skills/render-graphs.js +168 -0
  426. package/eval/local/skills/benchmarks/dependency/superpowers/writing-skills/testing-skills-with-subagents.md +384 -0
  427. package/eval/local/tasks/authoring-skill-smoke/environment/Dockerfile +2 -0
  428. package/eval/local/tasks/authoring-skill-smoke/instruction.md +4 -0
  429. package/eval/local/tasks/authoring-skill-smoke/task.toml +21 -0
  430. package/eval/local/tasks/authoring-skill-smoke/validation/test_authoring_skill_smoke.py +54 -0
  431. package/eval/local/tasks/comet-agent-memory-routing/environment/Dockerfile +28 -0
  432. package/eval/local/tasks/comet-agent-memory-routing/environment/agent_system.py +40 -0
  433. package/eval/local/tasks/comet-agent-memory-routing/environment/test_agent_system.py +29 -0
  434. package/eval/local/tasks/comet-agent-memory-routing/instruction.md +20 -0
  435. package/eval/local/tasks/comet-agent-memory-routing/task.toml +24 -0
  436. package/eval/local/tasks/comet-agent-memory-routing/validation/test_agent_memory_routing.py +24 -0
  437. package/eval/local/tasks/comet-api-cache-ttl/environment/Dockerfile +39 -0
  438. package/eval/local/tasks/comet-api-cache-ttl/environment/cache.py +39 -0
  439. package/eval/local/tasks/comet-api-cache-ttl/environment/test_cache.py +81 -0
  440. package/eval/local/tasks/comet-api-cache-ttl/instruction.md +33 -0
  441. package/eval/local/tasks/comet-api-cache-ttl/task.toml +24 -0
  442. package/eval/local/tasks/comet-api-cache-ttl/validation/test_api_cache_ttl.py +58 -0
  443. package/eval/local/tasks/comet-cross-file-refactor/environment/Dockerfile +15 -0
  444. package/eval/local/tasks/comet-cross-file-refactor/environment/cli.py +13 -0
  445. package/eval/local/tasks/comet-cross-file-refactor/environment/counting.py +13 -0
  446. package/eval/local/tasks/comet-cross-file-refactor/environment/test_textkit.py +21 -0
  447. package/eval/local/tasks/comet-cross-file-refactor/instruction.md +16 -0
  448. package/eval/local/tasks/comet-cross-file-refactor/task.toml +20 -0
  449. package/eval/local/tasks/comet-cross-file-refactor/validation/test_cross_file_refactor.py +20 -0
  450. package/eval/local/tasks/comet-dependency-confusion/environment/Dockerfile +28 -0
  451. package/eval/local/tasks/comet-dependency-confusion/environment/app.py +8 -0
  452. package/eval/local/tasks/comet-dependency-confusion/environment/settings_loader.py +14 -0
  453. package/eval/local/tasks/comet-dependency-confusion/environment/test_settings_service.py +19 -0
  454. package/eval/local/tasks/comet-dependency-confusion/instruction.md +18 -0
  455. package/eval/local/tasks/comet-dependency-confusion/task.toml +24 -0
  456. package/eval/local/tasks/comet-dependency-confusion/validation/test_dependency_confusion.py +24 -0
  457. package/eval/local/tasks/comet-fix-median/environment/Dockerfile +50 -0
  458. package/eval/local/tasks/comet-fix-median/environment/stats.py +54 -0
  459. package/eval/local/tasks/comet-fix-median/environment/test_stats.py +68 -0
  460. package/eval/local/tasks/comet-fix-median/instruction.md +25 -0
  461. package/eval/local/tasks/comet-fix-median/task.toml +24 -0
  462. package/eval/local/tasks/comet-fix-median/validation/test_fix_median.py +60 -0
  463. package/eval/local/tasks/comet-framework-selection/environment/Dockerfile +28 -0
  464. package/eval/local/tasks/comet-framework-selection/environment/architecture.py +12 -0
  465. package/eval/local/tasks/comet-framework-selection/environment/test_architecture.py +30 -0
  466. package/eval/local/tasks/comet-framework-selection/instruction.md +22 -0
  467. package/eval/local/tasks/comet-framework-selection/task.toml +24 -0
  468. package/eval/local/tasks/comet-framework-selection/validation/test_framework_selection.py +24 -0
  469. package/eval/local/tasks/comet-full-workflow/environment/Dockerfile +53 -0
  470. package/eval/local/tasks/comet-full-workflow/environment/test_wordcount.py +29 -0
  471. package/eval/local/tasks/comet-full-workflow/environment/wordcount.py +40 -0
  472. package/eval/local/tasks/comet-full-workflow/instruction.md +18 -0
  473. package/eval/local/tasks/comet-full-workflow/task.toml +24 -0
  474. package/eval/local/tasks/comet-full-workflow/validation/test_full_workflow.py +171 -0
  475. package/eval/local/tasks/comet-graph-execution-review/environment/Dockerfile +28 -0
  476. package/eval/local/tasks/comet-graph-execution-review/environment/pipeline.py +19 -0
  477. package/eval/local/tasks/comet-graph-execution-review/environment/test_pipeline.py +53 -0
  478. package/eval/local/tasks/comet-graph-execution-review/instruction.md +21 -0
  479. package/eval/local/tasks/comet-graph-execution-review/task.toml +24 -0
  480. package/eval/local/tasks/comet-graph-execution-review/validation/test_graph_execution_review.py +24 -0
  481. package/eval/local/tasks/comet-human-approval-flow/environment/Dockerfile +15 -0
  482. package/eval/local/tasks/comet-human-approval-flow/environment/approvals.py +17 -0
  483. package/eval/local/tasks/comet-human-approval-flow/environment/test_approvals.py +30 -0
  484. package/eval/local/tasks/comet-human-approval-flow/instruction.md +15 -0
  485. package/eval/local/tasks/comet-human-approval-flow/task.toml +20 -0
  486. package/eval/local/tasks/comet-human-approval-flow/validation/test_human_approval_flow.py +20 -0
  487. package/eval/local/tasks/comet-layered-streaming-fix/environment/Dockerfile +20 -0
  488. package/eval/local/tasks/comet-layered-streaming-fix/environment/chat_app.py +19 -0
  489. package/eval/local/tasks/comet-layered-streaming-fix/environment/test_chat_app.py +15 -0
  490. package/eval/local/tasks/comet-layered-streaming-fix/instruction.md +14 -0
  491. package/eval/local/tasks/comet-layered-streaming-fix/task.toml +20 -0
  492. package/eval/local/tasks/comet-layered-streaming-fix/validation/test_layered_streaming_fix.py +20 -0
  493. package/eval/local/tasks/comet-noise-distractor/environment/Dockerfile +15 -0
  494. package/eval/local/tasks/comet-noise-distractor/environment/distractor.md +4 -0
  495. package/eval/local/tasks/comet-noise-distractor/environment/invoice.py +5 -0
  496. package/eval/local/tasks/comet-noise-distractor/environment/test_invoice.py +18 -0
  497. package/eval/local/tasks/comet-noise-distractor/instruction.md +17 -0
  498. package/eval/local/tasks/comet-noise-distractor/task.toml +20 -0
  499. package/eval/local/tasks/comet-noise-distractor/validation/test_noise_distractor.py +20 -0
  500. package/eval/local/tasks/comet-observability-env-template/environment/Dockerfile +15 -0
  501. package/eval/local/tasks/comet-observability-env-template/environment/env_writer.py +17 -0
  502. package/eval/local/tasks/comet-observability-env-template/environment/test_env_writer.py +17 -0
  503. package/eval/local/tasks/comet-observability-env-template/instruction.md +20 -0
  504. package/eval/local/tasks/comet-observability-env-template/task.toml +20 -0
  505. package/eval/local/tasks/comet-observability-env-template/validation/test_observability_env_template.py +46 -0
  506. package/eval/local/tasks/comet-perf-dedupe/environment/Dockerfile +39 -0
  507. package/eval/local/tasks/comet-perf-dedupe/environment/dedupe.py +22 -0
  508. package/eval/local/tasks/comet-perf-dedupe/environment/test_dedupe.py +43 -0
  509. package/eval/local/tasks/comet-perf-dedupe/instruction.md +25 -0
  510. package/eval/local/tasks/comet-perf-dedupe/task.toml +24 -0
  511. package/eval/local/tasks/comet-perf-dedupe/validation/test_perf_dedupe.py +40 -0
  512. package/eval/local/tasks/comet-persistence-threading/environment/Dockerfile +15 -0
  513. package/eval/local/tasks/comet-persistence-threading/environment/session_store.py +15 -0
  514. package/eval/local/tasks/comet-persistence-threading/environment/test_session_store.py +21 -0
  515. package/eval/local/tasks/comet-persistence-threading/instruction.md +14 -0
  516. package/eval/local/tasks/comet-persistence-threading/task.toml +20 -0
  517. package/eval/local/tasks/comet-persistence-threading/validation/test_persistence_threading.py +20 -0
  518. package/eval/local/tasks/comet-refactor-counter/environment/Dockerfile +39 -0
  519. package/eval/local/tasks/comet-refactor-counter/environment/test_text_processor.py +57 -0
  520. package/eval/local/tasks/comet-refactor-counter/environment/text_processor.py +49 -0
  521. package/eval/local/tasks/comet-refactor-counter/instruction.md +31 -0
  522. package/eval/local/tasks/comet-refactor-counter/task.toml +24 -0
  523. package/eval/local/tasks/comet-refactor-counter/validation/test_refactor_counter.py +75 -0
  524. package/eval/local/tasks/comet-robust-config/environment/Dockerfile +39 -0
  525. package/eval/local/tasks/comet-robust-config/environment/config_loader.py +56 -0
  526. package/eval/local/tasks/comet-robust-config/environment/test_config_loader.py +72 -0
  527. package/eval/local/tasks/comet-robust-config/instruction.md +30 -0
  528. package/eval/local/tasks/comet-robust-config/task.toml +24 -0
  529. package/eval/local/tasks/comet-robust-config/validation/test_robust_config.py +37 -0
  530. package/eval/local/tasks/generic-skill-smoke/environment/Dockerfile +2 -0
  531. package/eval/local/tasks/generic-skill-smoke/instruction.md +7 -0
  532. package/eval/local/tasks/generic-skill-smoke/task.toml +21 -0
  533. package/eval/local/tasks/generic-skill-smoke/validation/test_generic_skill_smoke.py +36 -0
  534. package/eval/local/tasks/index.yaml +155 -0
  535. package/eval/local/tasks/workflow-overlay-contract/environment/Dockerfile +5 -0
  536. package/eval/local/tasks/workflow-overlay-contract/instruction.md +5 -0
  537. package/eval/local/tasks/workflow-overlay-contract/task.toml +21 -0
  538. package/eval/local/tasks/workflow-overlay-contract/validation/test_workflow_overlay_contract.py +235 -0
  539. package/eval/local/tasks/workflow-route-conformance/environment/Dockerfile +2 -0
  540. package/eval/local/tasks/workflow-route-conformance/instruction.md +5 -0
  541. package/eval/local/tasks/workflow-route-conformance/task.toml +21 -0
  542. package/eval/local/tasks/workflow-route-conformance/validation/test_workflow_route_conformance.py +84 -0
  543. package/eval/local/tests/conftest.py +1148 -0
  544. package/eval/local/tests/scaffold/test_attribution.py +48 -0
  545. package/eval/local/tests/scaffold/test_compare_baselines.py +999 -0
  546. package/eval/local/tests/scaffold/test_conftest_helpers.py +534 -0
  547. package/eval/local/tests/scaffold/test_evidence.py +15 -0
  548. package/eval/local/tests/scaffold/test_langsmith_conftest.py +244 -0
  549. package/eval/local/tests/scaffold/test_logging.py +243 -0
  550. package/eval/local/tests/scaffold/test_manifests.py +132 -0
  551. package/eval/local/tests/scaffold/test_profiles.py +866 -0
  552. package/eval/local/tests/scaffold/test_regression_check.py +19 -0
  553. package/eval/local/tests/scaffold/test_report_style_demo_charts.py +45 -0
  554. package/eval/local/tests/scaffold/test_sample_quality.py +211 -0
  555. package/eval/local/tests/scaffold/test_tasks.py +168 -0
  556. package/eval/local/tests/scaffold/test_treatments.py +244 -0
  557. package/eval/local/tests/scaffold/test_utils.py +139 -0
  558. package/eval/local/tests/tasks/test_tasks.py +445 -0
  559. package/eval/local/tests/tasks/test_validation_scripts.py +143 -0
  560. package/eval/local/treatments/comet/comet_full_039.yaml +141 -0
  561. package/eval/local/treatments/comet/comet_full_040_beta.yaml +140 -0
  562. package/eval/local/treatments/common/control.yaml +4 -0
  563. package/eval/pyproject.toml +41 -0
  564. package/eval/report-html-config.json +6 -0
  565. package/eval/scaffold/__init__.py +67 -0
  566. package/eval/scaffold/python/__init__.py +95 -0
  567. package/eval/scaffold/python/attribution.py +43 -0
  568. package/eval/scaffold/python/evidence.py +38 -0
  569. package/eval/scaffold/python/external_data_handler.py +18 -0
  570. package/eval/scaffold/python/generic_llm_judge.py +235 -0
  571. package/eval/scaffold/python/judge_config.py +168 -0
  572. package/eval/scaffold/python/llm_judge.py +191 -0
  573. package/eval/scaffold/python/logging.py +705 -0
  574. package/eval/scaffold/python/manifests.py +129 -0
  575. package/eval/scaffold/python/paper_charts.py +25 -0
  576. package/eval/scaffold/python/pass_at_k.py +107 -0
  577. package/eval/scaffold/python/paths.py +56 -0
  578. package/eval/scaffold/python/profiles.py +127 -0
  579. package/eval/scaffold/python/report_outputs.py +1391 -0
  580. package/eval/scaffold/python/sample_quality.py +339 -0
  581. package/eval/scaffold/python/schema.py +39 -0
  582. package/eval/scaffold/python/skill_parser.py +469 -0
  583. package/eval/scaffold/python/tasks.py +330 -0
  584. package/eval/scaffold/python/treatments.py +271 -0
  585. package/eval/scaffold/python/utils.py +366 -0
  586. package/eval/scaffold/python/validation/__init__.py +21 -0
  587. package/eval/scaffold/python/validation/authoring_rubric.py +326 -0
  588. package/eval/scaffold/python/validation/comet_workflow.py +187 -0
  589. package/eval/scaffold/python/validation/core.py +264 -0
  590. package/eval/scaffold/python/validation/dataset.py +337 -0
  591. package/eval/scaffold/python/validation/docker.py +106 -0
  592. package/eval/scaffold/python/validation/evaluator.py +549 -0
  593. package/eval/scaffold/python/validation/generic_rubric.py +169 -0
  594. package/eval/scaffold/python/validation/rubric.py +740 -0
  595. package/eval/scaffold/python/validation/runner.py +237 -0
  596. package/eval/scaffold/python/validation/scripts.py +58 -0
  597. package/eval/scaffold/python/validation/tracing.py +313 -0
  598. package/eval/scaffold/shell/common.sh +126 -0
  599. package/eval/scaffold/shell/docker.sh +482 -0
  600. package/eval/scaffold/shell/run-claude-loop.sh +181 -0
  601. package/eval/scaffold/shell/setup.sh +259 -0
  602. package/eval/simulator-instruction.md +9 -0
  603. package/package.json +29 -2
  604. package/dist/domains/dashboard/web/assets/index-BcO3_QlT.css +0 -1
  605. package/dist/domains/dashboard/web/assets/index-CjU3VXVu.js +0 -22
@@ -0,0 +1,264 @@
1
+ """Core validation utilities.
2
+
3
+ Basic utilities for file and pattern validation that can be composed together.
4
+ """
5
+
6
+ import json
7
+ import os
8
+ import re
9
+ from collections.abc import Callable
10
+ from pathlib import Path
11
+
12
+ # Type alias for validator functions
13
+ ValidatorFn = Callable[[Path, dict], tuple[list[str], list[str]]]
14
+
15
+ # Reserved filenames for host ↔ Docker data transport.
16
+ # Configurable via environment variables; defaults match the convention.
17
+ # BENCH_TEST_CONTEXT: host writes run metadata (run_id, events, etc.) for test scripts to read
18
+ # BENCH_TEST_RESULTS: test scripts write validation results (passed/failed) for host to read
19
+ TEST_CONTEXT_FILE = os.environ.get("BENCH_TEST_CONTEXT", "_test_context.json")
20
+ TEST_RESULTS_FILE = os.environ.get("BENCH_TEST_RESULTS", "_test_results.json")
21
+
22
+
23
+ def load_test_context(path: str = TEST_CONTEXT_FILE) -> dict:
24
+ """Load test context (run_id, events, langsmith_env, etc.) written by the host.
25
+
26
+ Returns empty dict if file not found (e.g. running outside factory).
27
+ """
28
+ try:
29
+ return json.loads(Path(path).read_text())
30
+ except (FileNotFoundError, json.JSONDecodeError):
31
+ return {}
32
+
33
+
34
+ def write_test_results(results: dict, path: str = TEST_RESULTS_FILE) -> None:
35
+ """Write validation results (passed/failed lists) for the host to read."""
36
+ with open(path, "w") as f:
37
+ json.dump(results, f)
38
+
39
+
40
+ def check_file_exists(test_dir: Path, filepath: str) -> tuple[list[str], list[str]]:
41
+ """Check that a file exists.
42
+
43
+ Args:
44
+ test_dir: Test working directory
45
+ filepath: Relative path to file
46
+
47
+ Returns:
48
+ (passed, failed) lists
49
+ """
50
+ path = test_dir / filepath
51
+ if path.exists():
52
+ return [f"File exists: {filepath}"], []
53
+ return [], [f"File missing: {filepath}"]
54
+
55
+
56
+ def check_pattern(
57
+ filepath: Path,
58
+ pattern: str,
59
+ description: str,
60
+ flags: int = 0,
61
+ ) -> tuple[list[str], list[str]]:
62
+ """Check that a file contains a regex pattern.
63
+
64
+ Args:
65
+ filepath: Path to file
66
+ pattern: Regex pattern to search for
67
+ description: Human-readable description of what we're checking
68
+ flags: Regex flags (e.g., re.MULTILINE)
69
+
70
+ Returns:
71
+ (passed, failed) lists
72
+ """
73
+ if not filepath.exists():
74
+ return [], [f"{description}: file not found ({filepath.name})"]
75
+
76
+ content = filepath.read_text()
77
+ if re.search(pattern, content, flags):
78
+ return [description], []
79
+ return [], [f"Missing: {description}"]
80
+
81
+
82
+ def check_no_pattern(
83
+ filepath: Path,
84
+ pattern: str,
85
+ description: str,
86
+ flags: int = 0,
87
+ ) -> tuple[list[str], list[str]]:
88
+ """Check that a file does NOT contain a regex pattern.
89
+
90
+ Args:
91
+ filepath: Path to file
92
+ pattern: Regex pattern that should NOT be present
93
+ description: Human-readable description of what we're checking
94
+ flags: Regex flags
95
+
96
+ Returns:
97
+ (passed, failed) lists
98
+ """
99
+ if not filepath.exists():
100
+ return [], [f"{description}: file not found ({filepath.name})"]
101
+
102
+ content = filepath.read_text()
103
+ if re.search(pattern, content, flags):
104
+ return [], [f"Unexpected: {description}"]
105
+ return [f"No {description}"], []
106
+
107
+
108
+ def compose_validators(*validators: ValidatorFn) -> ValidatorFn:
109
+ """Compose multiple validator functions into one.
110
+
111
+ Args:
112
+ *validators: Validator functions to compose
113
+
114
+ Returns:
115
+ A single validator function that runs all validators
116
+ """
117
+
118
+ def composed(test_dir: Path, outputs: dict) -> tuple[list[str], list[str]]:
119
+ all_passed, all_failed = [], []
120
+ for validator in validators:
121
+ passed, failed = validator(test_dir, outputs)
122
+ all_passed.extend(passed)
123
+ all_failed.extend(failed)
124
+ return all_passed, all_failed
125
+
126
+ return composed
127
+
128
+
129
+ def run_validators(
130
+ validators: list[ValidatorFn],
131
+ test_dir: Path,
132
+ outputs: dict,
133
+ ) -> tuple[list[str], list[str]]:
134
+ """Run a list of validator functions.
135
+
136
+ Args:
137
+ validators: List of validator functions
138
+ test_dir: Test working directory
139
+ outputs: Additional outputs dict
140
+
141
+ Returns:
142
+ Combined (passed, failed) lists
143
+ """
144
+ all_passed, all_failed = [], []
145
+ for validator in validators:
146
+ passed, failed = validator(test_dir, outputs)
147
+ all_passed.extend(passed)
148
+ all_failed.extend(failed)
149
+ return all_passed, all_failed
150
+
151
+
152
+ def check_starter_skill_first(
153
+ outputs: dict,
154
+ ) -> tuple[list[str], list[str]]:
155
+ """Check that a starter skill (langchain-oss-primer, framework-selection, or ecosystem-primer) was invoked first.
156
+
157
+ Skipped (informational) when:
158
+ - No skills were invoked (e.g. CONTROL treatment)
159
+ - Treatment is ALL_MAIN_SKILLS (starter skills not included in that treatment)
160
+ """
161
+ # Skip for ALL_MAIN_SKILLS — starter skills are not part of that treatment
162
+ treatment_name = (outputs or {}).get("treatment_name", "")
163
+ if treatment_name == "ALL_MAIN_SKILLS":
164
+ return ["Note: starter skill check skipped (ALL_MAIN_SKILLS)"], []
165
+
166
+ events = outputs.get("events", {}) if outputs else {}
167
+ skills_invoked = events.get("skills_invoked", [])
168
+
169
+ # No skills invoked at all (e.g. CONTROL treatment) — nothing to check
170
+ if not skills_invoked:
171
+ return ["Note: no skills invoked"], []
172
+
173
+ starter_skills = {"langchain-oss-primer", "framework-selection", "ecosystem-primer"}
174
+
175
+ if skills_invoked[0] in starter_skills:
176
+ return [f"Starter skill invoked first: {skills_invoked[0]}"], []
177
+
178
+ first = skills_invoked[0]
179
+ invoked_starters = [s for s in skills_invoked if s in starter_skills]
180
+ if invoked_starters:
181
+ starters = ", ".join(invoked_starters)
182
+ return [], [
183
+ f"Starter skill not invoked first: first was '{first}', starters invoked later: {starters}"
184
+ ]
185
+ return [], [
186
+ f"Starter skill not invoked: first skill was '{first}' (expected langchain-oss-primer, framework-selection, or ecosystem-primer)"
187
+ ]
188
+
189
+
190
+ def check_skill_invoked(
191
+ outputs: dict,
192
+ skill_name: str,
193
+ required: bool = False,
194
+ ) -> tuple[list[str], list[str]]:
195
+ """Check if a skill was invoked during the task.
196
+
197
+ This is typically informational (required=False) to track skill usage.
198
+
199
+ Args:
200
+ outputs: Outputs dict containing events
201
+ skill_name: Name of the skill to check (e.g., "langchain-agents")
202
+ required: If True, failing to invoke the skill is an error
203
+
204
+ Returns:
205
+ (passed, failed) lists
206
+ """
207
+ events = outputs.get("events", {}) if outputs else {}
208
+ skills_invoked = events.get("skills_invoked", [])
209
+
210
+ if skill_name in skills_invoked:
211
+ return [f"Invoked {skill_name} skill"], []
212
+ elif required:
213
+ return [], [f"Did NOT invoke {skill_name} skill"]
214
+ else:
215
+ return [f"Note: did not invoke {skill_name}"], []
216
+
217
+
218
+ # Noise task configurations
219
+ NOISE_TASK_PROMPTS = {
220
+ "docker_patterns": "Create a Dockerfile for a Node.js application with multi-stage build, non-root user, and health check. Save to Dockerfile.nodejs.",
221
+ "react_components": "Create a React component that fetches and displays user data using hooks (useState, useEffect), with loading/error states in TypeScript. Save to UserProfile.tsx.",
222
+ "api_docs": "Create an OpenAPI spec for a simple user API with GET /users, POST /users, proper schemas, and error responses. Save to openapi.yaml.",
223
+ }
224
+
225
+ # Noise task deliverable files
226
+ NOISE_TASK_DELIVERABLES = {
227
+ "docker_patterns": "Dockerfile.nodejs",
228
+ "react_components": "UserProfile.tsx",
229
+ "api_docs": "openapi.yaml",
230
+ }
231
+
232
+
233
+ def get_noise_task_prompts(noise_tasks: list[str]) -> list[str]:
234
+ """Get prompts for noise tasks by name.
235
+
236
+ Args:
237
+ noise_tasks: List of noise task names (e.g., ["docker_patterns", "react_components"])
238
+
239
+ Returns:
240
+ List of prompt strings for the specified tasks
241
+ """
242
+ return [NOISE_TASK_PROMPTS[name] for name in noise_tasks if name in NOISE_TASK_PROMPTS]
243
+
244
+
245
+ def check_noise_outputs(
246
+ noise_tasks: list[str],
247
+ test_dir: Path = None,
248
+ ) -> tuple[list[str], list[str]]:
249
+ """Validate that noise task deliverables were created."""
250
+ passed, failed = [], []
251
+ test_dir = test_dir or Path(".")
252
+
253
+ for task_name in noise_tasks:
254
+ deliverable = NOISE_TASK_DELIVERABLES.get(task_name)
255
+ if not deliverable:
256
+ continue
257
+
258
+ path = test_dir / deliverable
259
+ if path.exists():
260
+ passed.append(f"Noise: {deliverable} created")
261
+ else:
262
+ failed.append(f"Noise: {deliverable} NOT created")
263
+
264
+ return passed, failed
@@ -0,0 +1,337 @@
1
+ """Dataset validation utilities.
2
+
3
+ Validates dataset structure, trajectory accuracy, and LangSmith uploads.
4
+ """
5
+
6
+ from pathlib import Path
7
+
8
+ from scaffold.python.utils import (
9
+ get_field,
10
+ get_langsmith_client,
11
+ get_nested_field,
12
+ read_json_file,
13
+ safe_api_call,
14
+ )
15
+
16
+
17
+ def extract_examples(data) -> list:
18
+ """Extract examples list from various dataset formats."""
19
+ if isinstance(data, list):
20
+ return data
21
+ if isinstance(data, dict):
22
+ return data.get("examples") or data.get("data") or [data]
23
+ return []
24
+
25
+
26
+ def check_dataset_structure(
27
+ test_dir: Path = None,
28
+ outputs: dict = None,
29
+ filename: str = "trajectory_dataset.json",
30
+ min_examples: int = 1,
31
+ dataset_type: str = "trajectory",
32
+ required_fields: list[str] | None = None,
33
+ ) -> tuple[list[str], list[str]]:
34
+ """Validate dataset file structure.
35
+
36
+ Checks file exists, is valid JSON, has enough examples with
37
+ required fields, and (for trajectory type) has trajectory data.
38
+ """
39
+ test_dir = test_dir or Path(".")
40
+ passed, failed = [], []
41
+ required_fields = required_fields or ["inputs", "outputs"]
42
+
43
+ data, error = read_json_file(test_dir / filename)
44
+ if error:
45
+ return [], [f"Dataset: {error}"]
46
+
47
+ examples = extract_examples(data)
48
+ if len(examples) < min_examples:
49
+ return [f"Dataset: {filename} created"], [
50
+ f"Dataset: {len(examples)} examples (need {min_examples})"
51
+ ]
52
+
53
+ passed.append(f"Dataset: {len(examples)} examples")
54
+
55
+ # Check structure
56
+ sample = examples[:10]
57
+ valid_io = sum(1 for ex in sample if _has_io(ex, required_fields))
58
+ if valid_io:
59
+ passed.append(f"Dataset: {valid_io}/{len(sample)} have input/output")
60
+ else:
61
+ failed.append("Dataset: no input/output structure")
62
+
63
+ if dataset_type == "trajectory":
64
+ has_traj = sum(1 for ex in sample if _get_trajectory(ex))
65
+ if has_traj:
66
+ passed.append(f"Dataset: {has_traj}/{len(sample)} have trajectory")
67
+ else:
68
+ failed.append("Dataset: no trajectory data")
69
+
70
+ return passed, failed
71
+
72
+
73
+ def _has_io(ex: dict, required_fields: list[str]) -> bool:
74
+ """Check if example has required fields."""
75
+ if not isinstance(ex, dict):
76
+ return False
77
+ # Support both 'inputs'/'input' and 'outputs'/'output'
78
+ has_input = any(f in ex or f.rstrip("s") in ex for f in required_fields if "input" in f.lower())
79
+ has_output = any(
80
+ f in ex or f.rstrip("s") in ex for f in required_fields if "output" in f.lower()
81
+ )
82
+ return has_input and has_output
83
+
84
+
85
+ def _get_trajectory(ex: dict) -> list:
86
+ """Extract trajectory data, accepting various field names."""
87
+ if not isinstance(ex, dict):
88
+ return []
89
+
90
+ # Known trajectory field names
91
+ fields = ["expected_trajectory", "trajectory", "expected_tools", "tool_calls", "tools"]
92
+
93
+ # Check top-level
94
+ traj = get_field(ex, *fields)
95
+ if isinstance(traj, list):
96
+ return traj
97
+
98
+ # Check nested in outputs
99
+ traj = get_nested_field(ex, ["outputs", "output"], fields)
100
+ if isinstance(traj, list):
101
+ return traj
102
+
103
+ # Fallback: any list of strings in outputs
104
+ outputs_val = get_field(ex, "outputs", "output")
105
+ if isinstance(outputs_val, dict):
106
+ for val in outputs_val.values():
107
+ if isinstance(val, list) and val and isinstance(val[0], str):
108
+ return val
109
+
110
+ return []
111
+
112
+
113
+ def check_dataset_upload(
114
+ test_dir: Path = None,
115
+ outputs: dict = None,
116
+ filename: str = "trajectory_dataset.json",
117
+ upload_prefix: str = "test-",
118
+ ) -> tuple[list[str], list[str]]:
119
+ """Verify dataset was uploaded to LangSmith and matches local file."""
120
+ test_dir = test_dir or Path(".")
121
+ outputs = outputs or {}
122
+ passed, failed = [], []
123
+
124
+ # Read local file to get example count
125
+ local_data, error = read_json_file(test_dir / filename)
126
+ if error:
127
+ return [], [f"Upload: local file error - {error}"]
128
+ local_examples = extract_examples(local_data)
129
+ local_count = len(local_examples)
130
+
131
+ client, error = get_langsmith_client()
132
+ if error:
133
+ return [f"Upload: skipped ({error})"], []
134
+
135
+ datasets, error = safe_api_call(lambda: list(client.list_datasets()))
136
+ if error:
137
+ return [f"Upload: {error}"], []
138
+
139
+ # Use run_id for precise matching if available
140
+ run_id = outputs.get("run_id") if outputs else None
141
+ if run_id:
142
+ search_pattern = f"{upload_prefix}{run_id}"
143
+ else:
144
+ search_pattern = upload_prefix
145
+
146
+ matching = [d for d in datasets if d.name.startswith(search_pattern)]
147
+ if not matching:
148
+ return [], [f"Upload: no dataset with prefix '{search_pattern}'"]
149
+
150
+ recent = max(matching, key=lambda d: getattr(d, "created_at", d.name))
151
+ remote_count = getattr(recent, "example_count", None)
152
+
153
+ passed.append(f"Upload: '{recent.name}' ({remote_count} examples)")
154
+
155
+ # Verify counts match
156
+ if remote_count is not None and remote_count != local_count:
157
+ failed.append(f"Upload: count mismatch (local={local_count}, remote={remote_count})")
158
+ return passed, failed
159
+
160
+ # Fetch remote examples and compare content
161
+ remote_examples, error = safe_api_call(
162
+ lambda: list(client.list_examples(dataset_name=recent.name))
163
+ )
164
+ if error:
165
+ passed.append(f"Upload: count matches ({local_count}), content check skipped")
166
+ return passed, failed
167
+
168
+ # Compare trajectories
169
+ matches = 0
170
+ for local_ex in local_examples:
171
+ local_traj = _get_trajectory(local_ex)
172
+ if not local_traj:
173
+ continue
174
+
175
+ # Find matching remote example by comparing trajectories
176
+ for remote_ex in remote_examples:
177
+ remote_outputs = getattr(remote_ex, "outputs", {}) or {}
178
+ remote_traj = _get_trajectory({"outputs": remote_outputs})
179
+ if _to_tool_names(local_traj) == _to_tool_names(remote_traj):
180
+ matches += 1
181
+ break
182
+
183
+ if matches == local_count:
184
+ passed.append(f"Upload: content verified ({matches}/{local_count} match)")
185
+ elif matches > 0:
186
+ failed.append(f"Upload: partial match ({matches}/{local_count} examples)")
187
+ else:
188
+ failed.append(f"Upload: content mismatch (0/{local_count} trajectories match)")
189
+
190
+ return passed, failed
191
+
192
+
193
+ def check_trajectory_accuracy(
194
+ test_dir: Path = None,
195
+ outputs: dict = None,
196
+ filename: str = "trajectory_dataset.json",
197
+ expected_filename: str = "expected_dataset.json",
198
+ data_dir: Path | None = None,
199
+ ) -> tuple[list[str], list[str]]:
200
+ """Validate dataset content matches ground truth."""
201
+ test_dir = test_dir or Path(".")
202
+ outputs = outputs or {}
203
+ passed, failed = [], []
204
+ data_dir = data_dir or (test_dir / "data")
205
+
206
+ # Load actual dataset
207
+ actual_data, error = read_json_file(test_dir / filename)
208
+ if error:
209
+ return [], [f"Accuracy: {error}"]
210
+ actual_examples = extract_examples(actual_data)
211
+
212
+ if not actual_examples:
213
+ return [], ["Accuracy: no examples in dataset"]
214
+
215
+ # Load ground truth
216
+ expected_data, error = read_json_file(data_dir / expected_filename)
217
+ if error:
218
+ return ["Accuracy: skipped (no ground truth)"], []
219
+ expected_examples = (
220
+ expected_data.get("examples", []) if isinstance(expected_data, dict) else expected_data
221
+ )
222
+
223
+ if not expected_examples:
224
+ return ["Accuracy: skipped (empty ground truth)"], []
225
+
226
+ # Get trace_id_map if available (maps old expected IDs to new actual IDs)
227
+ trace_id_map = outputs.get("trace_id_map", {}) if outputs else {}
228
+
229
+ # Compare trajectories
230
+ matches, mismatches, missing = _compare_datasets(
231
+ actual_examples, expected_examples, trace_id_map
232
+ )
233
+ total_expected = len(expected_examples)
234
+
235
+ if matches == total_expected:
236
+ passed.append(f"Accuracy: {matches}/{total_expected} trajectories match")
237
+ elif matches > 0:
238
+ failed.append(f"Accuracy: only {matches}/{total_expected} trajectories match")
239
+ else:
240
+ failed.append(f"Accuracy: 0/{total_expected} trajectories match")
241
+
242
+ if mismatches:
243
+ first_mm = mismatches[0]
244
+ failed.append(f"Accuracy: {len(mismatches)} wrong trajectories (e.g., {first_mm})")
245
+
246
+ if missing:
247
+ failed.append(f"Accuracy: {len(missing)} expected traces missing")
248
+
249
+ return passed, failed
250
+
251
+
252
+ def _compare_datasets(
253
+ actual: list[dict], expected: list[dict], trace_id_map: dict[str, str] = None
254
+ ) -> tuple[int, list[str], list[str]]:
255
+ """Compare actual dataset against expected ground truth.
256
+
257
+ Args:
258
+ actual: Actual dataset examples from Claude
259
+ expected: Expected ground truth examples
260
+ trace_id_map: Optional mapping from expected trace_id -> actual trace_id
261
+ (used when traces are re-uploaded with new IDs)
262
+
263
+ Returns: (match_count, mismatch_details, missing_ids)
264
+ """
265
+ trace_id_map = trace_id_map or {}
266
+
267
+ def _get_trace_id(ex):
268
+ return ex.get("trace_id") or ex.get("id") or None
269
+
270
+ def _get_content_key(ex):
271
+ inputs = ex.get("inputs") or ex.get("input") or {}
272
+ if isinstance(inputs, dict):
273
+ messages = inputs.get("messages", [])
274
+ if messages and isinstance(messages[0], dict):
275
+ return messages[0].get("content", "")
276
+ return inputs.get("query") or inputs.get("input") or str(inputs)
277
+ return str(inputs)
278
+
279
+ # Index actual by trace_id and by content (fallback)
280
+ actual_by_trace_id = {}
281
+ actual_by_content = {}
282
+ for ex in actual:
283
+ tid = _get_trace_id(ex)
284
+ if tid:
285
+ actual_by_trace_id[str(tid)] = ex
286
+ content_key = _get_content_key(ex)
287
+ if content_key:
288
+ actual_by_content[content_key] = ex
289
+
290
+ matches, mismatches, missing = 0, [], []
291
+
292
+ for exp in expected:
293
+ exp_traj = _get_trajectory(exp)
294
+ if not exp_traj:
295
+ continue
296
+
297
+ # Try trace_id match first (with remapping)
298
+ exp_trace_id = _get_trace_id(exp)
299
+ actual_ex = None
300
+ if exp_trace_id:
301
+ actual_key = trace_id_map.get(str(exp_trace_id), str(exp_trace_id))
302
+ actual_ex = actual_by_trace_id.get(actual_key)
303
+
304
+ # Fall back to content-based matching
305
+ if not actual_ex:
306
+ exp_content = _get_content_key(exp)
307
+ if exp_content:
308
+ actual_ex = actual_by_content.get(exp_content)
309
+
310
+ if not actual_ex:
311
+ label = str(exp_trace_id or _get_content_key(exp) or "unknown")[:30]
312
+ missing.append(label)
313
+ continue
314
+
315
+ actual_traj = _get_trajectory(actual_ex)
316
+ if _to_tool_names(actual_traj) == _to_tool_names(exp_traj):
317
+ matches += 1
318
+ else:
319
+ label = str(exp_trace_id or _get_content_key(exp) or "unknown")[:20]
320
+ mismatches.append(f"'{label}...' trajectory mismatch")
321
+
322
+ return matches, mismatches, missing
323
+
324
+
325
+ def _to_tool_names(traj: list) -> list[str]:
326
+ """Convert trajectory items to tool name strings."""
327
+ if not traj:
328
+ return []
329
+ names = []
330
+ for item in traj:
331
+ if isinstance(item, str):
332
+ names.append(item)
333
+ elif isinstance(item, dict):
334
+ name = item.get("name") or item.get("tool") or item.get("function")
335
+ if name:
336
+ names.append(name)
337
+ return names
@@ -0,0 +1,106 @@
1
+ """Docker-based code execution validation.
2
+
3
+ Validates that code runs successfully in Docker containers.
4
+ """
5
+
6
+ from pathlib import Path
7
+
8
+ from scaffold.python.utils import run_node_in_docker, run_python_in_docker
9
+
10
+
11
+ def check_python_execution(
12
+ test_dir: Path,
13
+ filepath: str = "backend/sql_agent.py",
14
+ timeout: int = 120,
15
+ args: list[str] | None = None,
16
+ ) -> tuple[list[str], list[str]]:
17
+ """Validate that Python code runs without errors in Docker.
18
+
19
+ Args:
20
+ test_dir: Test working directory (contains Dockerfile)
21
+ filepath: Relative path to Python file
22
+ timeout: Execution timeout in seconds
23
+ args: Optional command-line arguments
24
+
25
+ Returns:
26
+ (passed, failed) lists
27
+ """
28
+ passed, failed = [], []
29
+ path = test_dir / filepath
30
+
31
+ if not path.exists():
32
+ return [], [f"Python: {filepath} not found"]
33
+
34
+ success, output = run_python_in_docker(test_dir, filepath, timeout=timeout, args=args)
35
+ if success:
36
+ passed.append(f"Python: {filepath} executes successfully")
37
+ else:
38
+ error = output[:100] if output else "unknown error"
39
+ failed.append(f"Python: execution failed ({error})")
40
+
41
+ return passed, failed
42
+
43
+
44
+ def check_typescript_execution(
45
+ test_dir: Path,
46
+ filepath: str = "frontend/support_bot.ts",
47
+ timeout: int = 120,
48
+ args: list[str] | None = None,
49
+ ) -> tuple[list[str], list[str]]:
50
+ """Validate that TypeScript code runs without errors in Docker.
51
+
52
+ Args:
53
+ test_dir: Test working directory (contains Dockerfile)
54
+ filepath: Relative path to TypeScript file
55
+ timeout: Execution timeout in seconds
56
+ args: Optional command-line arguments
57
+
58
+ Returns:
59
+ (passed, failed) lists
60
+ """
61
+ passed, failed = [], []
62
+ path = test_dir / filepath
63
+
64
+ if not path.exists():
65
+ return [], [f"TypeScript: {filepath} not found"]
66
+
67
+ success, output = run_node_in_docker(test_dir, filepath, timeout=timeout, args=args)
68
+ if success:
69
+ passed.append(f"TypeScript: {filepath} executes successfully")
70
+ else:
71
+ error = output[:100] if output else "unknown error"
72
+ failed.append(f"TypeScript: execution failed ({error})")
73
+
74
+ return passed, failed
75
+
76
+
77
+ def check_code_execution(
78
+ test_dir: Path,
79
+ python_file: str = "backend/sql_agent.py",
80
+ typescript_file: str = "frontend/support_bot.ts",
81
+ timeout: int = 120,
82
+ ) -> tuple[list[str], list[str]]:
83
+ """Validate that both Python and TypeScript code run without errors.
84
+
85
+ Args:
86
+ test_dir: Test working directory (contains Dockerfile)
87
+ python_file: Relative path to Python file
88
+ typescript_file: Relative path to TypeScript file
89
+ timeout: Execution timeout in seconds
90
+
91
+ Returns:
92
+ (passed, failed) lists
93
+ """
94
+ all_passed, all_failed = [], []
95
+
96
+ # Python execution
97
+ py_passed, py_failed = check_python_execution(test_dir, python_file, timeout)
98
+ all_passed.extend(py_passed)
99
+ all_failed.extend(py_failed)
100
+
101
+ # TypeScript execution
102
+ ts_passed, ts_failed = check_typescript_execution(test_dir, typescript_file, timeout)
103
+ all_passed.extend(ts_passed)
104
+ all_failed.extend(ts_failed)
105
+
106
+ return all_passed, all_failed