@rpamis/comet 0.4.0-beta.2 → 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.
- package/README.md +27 -18
- package/assets/manifest.json +2 -1
- package/assets/skills/comet/SKILL.md +25 -1
- package/assets/skills/comet/reference/comet-yaml-fields.md +6 -4
- package/assets/skills/comet/reference/context-recovery.md +10 -0
- package/assets/skills/comet/reference/scripts.md +47 -15
- package/assets/skills/comet/rules/comet-phase-guard.en.md +8 -0
- package/assets/skills/comet/rules/comet-phase-guard.md +9 -1
- package/assets/skills/comet/scripts/comet-resume-probe.mjs +3 -0
- package/assets/skills/comet/scripts/comet-runtime.mjs +1664 -512
- package/assets/skills/comet-archive/SKILL.md +24 -11
- package/assets/skills/comet-build/SKILL.md +40 -31
- package/assets/skills/comet-design/SKILL.md +1 -0
- package/assets/skills/comet-hotfix/SKILL.md +3 -1
- package/assets/skills/comet-open/SKILL.md +11 -1
- package/assets/skills/comet-tweak/SKILL.md +3 -1
- package/assets/skills/comet-verify/SKILL.md +29 -20
- package/assets/skills-zh/comet/SKILL.md +25 -1
- package/assets/skills-zh/comet/reference/comet-yaml-fields.md +5 -4
- package/assets/skills-zh/comet/reference/context-recovery.md +10 -0
- package/assets/skills-zh/comet/reference/scripts.md +47 -15
- package/assets/skills-zh/comet-archive/SKILL.md +24 -11
- package/assets/skills-zh/comet-build/SKILL.md +40 -31
- package/assets/skills-zh/comet-design/SKILL.md +1 -0
- package/assets/skills-zh/comet-hotfix/SKILL.md +3 -1
- package/assets/skills-zh/comet-open/SKILL.md +11 -1
- package/assets/skills-zh/comet-tweak/SKILL.md +3 -1
- package/assets/skills-zh/comet-verify/SKILL.md +30 -21
- package/dist/app/cli/comet-banner.d.ts +25 -0
- package/dist/app/cli/comet-banner.d.ts.map +1 -0
- package/dist/app/cli/comet-banner.js +265 -0
- package/dist/app/cli/comet-banner.js.map +1 -0
- package/dist/app/cli/index.js +37 -3
- package/dist/app/cli/index.js.map +1 -1
- package/dist/app/commands/classic.d.ts +4 -0
- package/dist/app/commands/classic.d.ts.map +1 -0
- package/dist/app/commands/classic.js +11 -0
- package/dist/app/commands/classic.js.map +1 -0
- package/dist/app/commands/doctor.d.ts +1 -0
- package/dist/app/commands/doctor.d.ts.map +1 -1
- package/dist/app/commands/doctor.js +100 -35
- package/dist/app/commands/doctor.js.map +1 -1
- package/dist/app/commands/eval.d.ts.map +1 -1
- package/dist/app/commands/eval.js +57 -20
- package/dist/app/commands/eval.js.map +1 -1
- package/dist/app/commands/i18n.d.ts +1 -1
- package/dist/app/commands/i18n.d.ts.map +1 -1
- package/dist/app/commands/i18n.js +12 -4
- package/dist/app/commands/i18n.js.map +1 -1
- package/dist/app/commands/init.d.ts.map +1 -1
- package/dist/app/commands/init.js +16 -13
- package/dist/app/commands/init.js.map +1 -1
- package/dist/app/commands/project-scope-selection.d.ts +13 -0
- package/dist/app/commands/project-scope-selection.d.ts.map +1 -0
- package/dist/app/commands/project-scope-selection.js +33 -0
- package/dist/app/commands/project-scope-selection.js.map +1 -0
- package/dist/app/commands/resume-probe.d.ts +11 -0
- package/dist/app/commands/resume-probe.d.ts.map +1 -0
- package/dist/app/commands/resume-probe.js +63 -0
- package/dist/app/commands/resume-probe.js.map +1 -0
- package/dist/app/commands/status.d.ts +31 -0
- package/dist/app/commands/status.d.ts.map +1 -1
- package/dist/app/commands/status.js +109 -20
- package/dist/app/commands/status.js.map +1 -1
- package/dist/app/commands/uninstall.d.ts +2 -0
- package/dist/app/commands/uninstall.d.ts.map +1 -1
- package/dist/app/commands/uninstall.js +217 -40
- package/dist/app/commands/uninstall.js.map +1 -1
- package/dist/app/commands/update.d.ts +6 -0
- package/dist/app/commands/update.d.ts.map +1 -1
- package/dist/app/commands/update.js +361 -68
- package/dist/app/commands/update.js.map +1 -1
- package/dist/config/repository-layout.json +4 -2
- package/dist/domains/bundle/bundle-platform.d.ts.map +1 -1
- package/dist/domains/bundle/bundle-platform.js +3 -1
- package/dist/domains/bundle/bundle-platform.js.map +1 -1
- package/dist/domains/bundle/eval-manifest-runtime.d.ts +6 -0
- package/dist/domains/bundle/eval-manifest-runtime.d.ts.map +1 -0
- package/dist/domains/bundle/eval-manifest-runtime.js +58 -0
- package/dist/domains/bundle/eval-manifest-runtime.js.map +1 -0
- package/dist/domains/bundle/types.d.ts +1 -1
- package/dist/domains/bundle/types.d.ts.map +1 -1
- package/dist/domains/comet-classic/classic-archive.d.ts +1 -0
- package/dist/domains/comet-classic/classic-archive.d.ts.map +1 -1
- package/dist/domains/comet-classic/classic-archive.js +35 -38
- package/dist/domains/comet-classic/classic-archive.js.map +1 -1
- package/dist/domains/comet-classic/classic-cli.d.ts +1 -1
- package/dist/domains/comet-classic/classic-cli.d.ts.map +1 -1
- package/dist/domains/comet-classic/classic-cli.js +3 -0
- package/dist/domains/comet-classic/classic-cli.js.map +1 -1
- package/dist/domains/comet-classic/classic-command-checks.d.ts +20 -0
- package/dist/domains/comet-classic/classic-command-checks.d.ts.map +1 -0
- package/dist/domains/comet-classic/classic-command-checks.js +97 -0
- package/dist/domains/comet-classic/classic-command-checks.js.map +1 -0
- package/dist/domains/comet-classic/classic-current-change.d.ts +19 -0
- package/dist/domains/comet-classic/classic-current-change.d.ts.map +1 -0
- package/dist/domains/comet-classic/classic-current-change.js +132 -0
- package/dist/domains/comet-classic/classic-current-change.js.map +1 -0
- package/dist/domains/comet-classic/classic-diagnostics.d.ts +2 -1
- package/dist/domains/comet-classic/classic-diagnostics.d.ts.map +1 -1
- package/dist/domains/comet-classic/classic-diagnostics.js +54 -1
- package/dist/domains/comet-classic/classic-diagnostics.js.map +1 -1
- package/dist/domains/comet-classic/classic-evidence.d.ts.map +1 -1
- package/dist/domains/comet-classic/classic-evidence.js +4 -0
- package/dist/domains/comet-classic/classic-evidence.js.map +1 -1
- package/dist/domains/comet-classic/classic-guard.d.ts.map +1 -1
- package/dist/domains/comet-classic/classic-guard.js +101 -141
- package/dist/domains/comet-classic/classic-guard.js.map +1 -1
- package/dist/domains/comet-classic/classic-hook-guard.d.ts.map +1 -1
- package/dist/domains/comet-classic/classic-hook-guard.js +67 -29
- package/dist/domains/comet-classic/classic-hook-guard.js.map +1 -1
- package/dist/domains/comet-classic/classic-project-config.d.ts +16 -0
- package/dist/domains/comet-classic/classic-project-config.d.ts.map +1 -0
- package/dist/domains/comet-classic/classic-project-config.js +40 -0
- package/dist/domains/comet-classic/classic-project-config.js.map +1 -0
- package/dist/domains/comet-classic/classic-resolver.d.ts.map +1 -1
- package/dist/domains/comet-classic/classic-resolver.js +3 -3
- package/dist/domains/comet-classic/classic-resolver.js.map +1 -1
- package/dist/domains/comet-classic/classic-resume-probe-command.d.ts +3 -0
- package/dist/domains/comet-classic/classic-resume-probe-command.d.ts.map +1 -0
- package/dist/domains/comet-classic/classic-resume-probe-command.js +58 -0
- package/dist/domains/comet-classic/classic-resume-probe-command.js.map +1 -0
- package/dist/domains/comet-classic/classic-resume-probe-entry.d.ts +2 -0
- package/dist/domains/comet-classic/classic-resume-probe-entry.d.ts.map +1 -0
- package/dist/domains/comet-classic/classic-resume-probe-entry.js +4 -0
- package/dist/domains/comet-classic/classic-resume-probe-entry.js.map +1 -0
- package/dist/domains/comet-classic/classic-resume-probe.d.ts +29 -0
- package/dist/domains/comet-classic/classic-resume-probe.d.ts.map +1 -0
- package/dist/domains/comet-classic/classic-resume-probe.js +386 -0
- package/dist/domains/comet-classic/classic-resume-probe.js.map +1 -0
- package/dist/domains/comet-classic/classic-runtime-run.d.ts +2 -1
- package/dist/domains/comet-classic/classic-runtime-run.d.ts.map +1 -1
- package/dist/domains/comet-classic/classic-runtime-run.js +269 -4
- package/dist/domains/comet-classic/classic-runtime-run.js.map +1 -1
- package/dist/domains/comet-classic/classic-state-command.d.ts.map +1 -1
- package/dist/domains/comet-classic/classic-state-command.js +129 -15
- package/dist/domains/comet-classic/classic-state-command.js.map +1 -1
- package/dist/domains/comet-classic/classic-state.d.ts +3 -3
- package/dist/domains/comet-classic/classic-state.d.ts.map +1 -1
- package/dist/domains/comet-classic/classic-state.js +4 -6
- package/dist/domains/comet-classic/classic-state.js.map +1 -1
- package/dist/domains/comet-classic/classic-store.d.ts +4 -1
- package/dist/domains/comet-classic/classic-store.d.ts.map +1 -1
- package/dist/domains/comet-classic/classic-store.js +27 -9
- package/dist/domains/comet-classic/classic-store.js.map +1 -1
- package/dist/domains/comet-classic/classic-transitions.d.ts +1 -1
- package/dist/domains/comet-classic/classic-transitions.d.ts.map +1 -1
- package/dist/domains/comet-classic/classic-transitions.js +20 -1
- package/dist/domains/comet-classic/classic-transitions.js.map +1 -1
- package/dist/domains/comet-classic/classic-validate-command.d.ts.map +1 -1
- package/dist/domains/comet-classic/classic-validate-command.js +1 -0
- package/dist/domains/comet-classic/classic-validate-command.js.map +1 -1
- package/dist/domains/comet-classic/index.d.ts +3 -0
- package/dist/domains/comet-classic/index.d.ts.map +1 -1
- package/dist/domains/comet-classic/index.js +3 -0
- package/dist/domains/comet-classic/index.js.map +1 -1
- package/dist/domains/dashboard/collector.js +10 -2
- package/dist/domains/dashboard/collector.js.map +1 -1
- package/dist/domains/dashboard/web/assets/{index-CjU3VXVu.js → index-CIvN-PL8.js} +11 -11
- package/dist/domains/dashboard/web/assets/{index-BcO3_QlT.css → index-DcyRPBnT.css} +1 -1
- package/dist/domains/dashboard/web/index.html +16 -16
- package/dist/domains/engine/types.d.ts +1 -1
- package/dist/domains/engine/types.d.ts.map +1 -1
- package/dist/domains/integrations/openspec.d.ts.map +1 -1
- package/dist/domains/integrations/openspec.js +6 -6
- package/dist/domains/integrations/openspec.js.map +1 -1
- package/dist/domains/skill/find.d.ts.map +1 -1
- package/dist/domains/skill/find.js +1 -6
- package/dist/domains/skill/find.js.map +1 -1
- package/dist/domains/skill/managed-markdown.d.ts +14 -0
- package/dist/domains/skill/managed-markdown.d.ts.map +1 -0
- package/dist/domains/skill/managed-markdown.js +126 -0
- package/dist/domains/skill/managed-markdown.js.map +1 -0
- package/dist/domains/skill/platform-install.d.ts +4 -3
- package/dist/domains/skill/platform-install.d.ts.map +1 -1
- package/dist/domains/skill/platform-install.js +96 -26
- package/dist/domains/skill/platform-install.js.map +1 -1
- package/dist/domains/skill/project-instructions.d.ts +22 -0
- package/dist/domains/skill/project-instructions.d.ts.map +1 -0
- package/dist/domains/skill/project-instructions.js +61 -0
- package/dist/domains/skill/project-instructions.js.map +1 -0
- package/dist/domains/skill/uninstall.d.ts +3 -1
- package/dist/domains/skill/uninstall.d.ts.map +1 -1
- package/dist/domains/skill/uninstall.js +86 -39
- package/dist/domains/skill/uninstall.js.map +1 -1
- package/dist/platform/install/detect.d.ts +2 -1
- package/dist/platform/install/detect.d.ts.map +1 -1
- package/dist/platform/install/detect.js +10 -1
- package/dist/platform/install/detect.js.map +1 -1
- package/dist/platform/install/platforms.d.ts +5 -1
- package/dist/platform/install/platforms.d.ts.map +1 -1
- package/dist/platform/install/platforms.js +21 -4
- package/dist/platform/install/platforms.js.map +1 -1
- package/dist/platform/install/project-registry.d.ts +37 -0
- package/dist/platform/install/project-registry.d.ts.map +1 -0
- package/dist/platform/install/project-registry.js +205 -0
- package/dist/platform/install/project-registry.js.map +1 -0
- package/eval/.env +28 -0
- package/eval/.env.example +52 -0
- package/eval/CLAUDE.md +43 -0
- package/eval/README.md +538 -0
- package/eval/langsmith/.env.example +16 -0
- package/eval/langsmith/README.md +93 -0
- package/eval/langsmith/skills/README.md +5 -0
- package/eval/langsmith/tasks/README.md +5 -0
- package/eval/langsmith/tests/conftest.py +187 -0
- package/eval/langsmith/tests/tasks/test_tasks.py +287 -0
- package/eval/langsmith/treatments/README.md +5 -0
- package/eval/local/README.md +80 -0
- package/eval/local/regression_baseline.json +13 -0
- package/eval/local/report-style-demo-assets/quality_cost.en.svg +41 -0
- package/eval/local/report-style-demo-assets/quality_cost.zh.svg +41 -0
- package/eval/local/report-style-demo-assets/rubric_delta.en.svg +56 -0
- package/eval/local/report-style-demo-assets/rubric_delta.zh.svg +56 -0
- package/eval/local/report-style-demo-assets/task_outcomes.en.svg +46 -0
- package/eval/local/report-style-demo-assets/task_outcomes.zh.svg +46 -0
- package/eval/local/report-style-demo.html +867 -0
- package/eval/local/scripts/compare_baselines.py +1018 -0
- package/eval/local/scripts/generate_report_style_demo_charts.py +322 -0
- package/eval/local/scripts/regression_check.py +171 -0
- package/eval/local/scripts/render_readme_benchmark_figures.py +416 -0
- package/eval/local/scripts/rescore_rubric.py +120 -0
- package/eval/local/skills/benchmarks/039-release/comet-classic-039/SKILL.md +282 -0
- package/eval/local/skills/benchmarks/039-release/comet-classic-039/reference/auto-transition.md +27 -0
- package/eval/local/skills/benchmarks/039-release/comet-classic-039/reference/comet-yaml-fields.md +68 -0
- package/eval/local/skills/benchmarks/039-release/comet-classic-039/reference/context-recovery.md +35 -0
- package/eval/local/skills/benchmarks/039-release/comet-classic-039/reference/debug-gate.md +17 -0
- package/eval/local/skills/benchmarks/039-release/comet-classic-039/reference/decision-point.md +20 -0
- package/eval/local/skills/benchmarks/039-release/comet-classic-039/reference/dirty-worktree.md +59 -0
- package/eval/local/skills/benchmarks/039-release/comet-classic-039/reference/file-structure.md +28 -0
- package/eval/local/skills/benchmarks/039-release/comet-classic-039/reference/subagent-dispatch.md +113 -0
- package/eval/local/skills/benchmarks/039-release/comet-classic-039/rules/comet-phase-guard.md +125 -0
- package/eval/local/skills/benchmarks/039-release/comet-classic-039/scripts/comet-archive.sh +311 -0
- package/eval/local/skills/benchmarks/039-release/comet-classic-039/scripts/comet-env.sh +110 -0
- package/eval/local/skills/benchmarks/039-release/comet-classic-039/scripts/comet-guard.sh +778 -0
- package/eval/local/skills/benchmarks/039-release/comet-classic-039/scripts/comet-handoff.sh +390 -0
- package/eval/local/skills/benchmarks/039-release/comet-classic-039/scripts/comet-hook-guard.sh +336 -0
- package/eval/local/skills/benchmarks/039-release/comet-classic-039/scripts/comet-state.sh +1338 -0
- package/eval/local/skills/benchmarks/039-release/comet-classic-039/scripts/comet-yaml-validate.sh +225 -0
- package/eval/local/skills/benchmarks/039-release/comet-classic-039-archive/SKILL.md +100 -0
- package/eval/local/skills/benchmarks/039-release/comet-classic-039-build/SKILL.md +304 -0
- package/eval/local/skills/benchmarks/039-release/comet-classic-039-design/SKILL.md +263 -0
- package/eval/local/skills/benchmarks/039-release/comet-classic-039-hotfix/SKILL.md +204 -0
- package/eval/local/skills/benchmarks/039-release/comet-classic-039-open/SKILL.md +220 -0
- package/eval/local/skills/benchmarks/039-release/comet-classic-039-tweak/SKILL.md +180 -0
- package/eval/local/skills/benchmarks/039-release/comet-classic-039-verify/SKILL.md +234 -0
- package/eval/local/skills/benchmarks/040-beta/comet/SKILL.md +261 -0
- package/eval/local/skills/benchmarks/040-beta/comet/reference/auto-transition.md +27 -0
- package/eval/local/skills/benchmarks/040-beta/comet/reference/comet-yaml-fields.md +73 -0
- package/eval/local/skills/benchmarks/040-beta/comet/reference/context-recovery.md +45 -0
- package/eval/local/skills/benchmarks/040-beta/comet/reference/debug-gate.md +33 -0
- package/eval/local/skills/benchmarks/040-beta/comet/reference/decision-point.md +31 -0
- package/eval/local/skills/benchmarks/040-beta/comet/reference/dirty-worktree.md +59 -0
- package/eval/local/skills/benchmarks/040-beta/comet/reference/file-structure.md +28 -0
- package/eval/local/skills/benchmarks/040-beta/comet/reference/intent-frame.md +74 -0
- package/eval/local/skills/benchmarks/040-beta/comet/reference/scripts.md +69 -0
- package/eval/local/skills/benchmarks/040-beta/comet/reference/subagent-dispatch.md +169 -0
- package/eval/local/skills/benchmarks/040-beta/comet/rules/comet-phase-guard.md +130 -0
- package/eval/local/skills/benchmarks/040-beta/comet/runtime/classic/checks.yaml +6 -0
- package/eval/local/skills/benchmarks/040-beta/comet/runtime/classic/guardrails.yaml +13 -0
- package/eval/local/skills/benchmarks/040-beta/comet/runtime/classic/skill.yaml +122 -0
- package/eval/local/skills/benchmarks/040-beta/comet/scripts/comet-archive.mjs +9515 -0
- package/eval/local/skills/benchmarks/040-beta/comet/scripts/comet-env.mjs +15 -0
- package/eval/local/skills/benchmarks/040-beta/comet/scripts/comet-guard.mjs +10173 -0
- package/eval/local/skills/benchmarks/040-beta/comet/scripts/comet-handoff.mjs +9491 -0
- package/eval/local/skills/benchmarks/040-beta/comet/scripts/comet-hook-guard.mjs +9175 -0
- package/eval/local/skills/benchmarks/040-beta/comet/scripts/comet-intent.mjs +404 -0
- package/eval/local/skills/benchmarks/040-beta/comet/scripts/comet-state.mjs +9273 -0
- package/eval/local/skills/benchmarks/040-beta/comet/scripts/comet-yaml-validate.mjs +7627 -0
- package/eval/local/skills/benchmarks/040-beta/comet-archive/SKILL.md +110 -0
- package/eval/local/skills/benchmarks/040-beta/comet-build/SKILL.md +315 -0
- package/eval/local/skills/benchmarks/040-beta/comet-design/SKILL.md +260 -0
- package/eval/local/skills/benchmarks/040-beta/comet-hotfix/SKILL.md +190 -0
- package/eval/local/skills/benchmarks/040-beta/comet-open/SKILL.md +210 -0
- package/eval/local/skills/benchmarks/040-beta/comet-tweak/SKILL.md +183 -0
- package/eval/local/skills/benchmarks/040-beta/comet-verify/SKILL.md +230 -0
- package/eval/local/skills/benchmarks/dependency/claude-md/comet-workflow/CLAUDE.md +12 -0
- package/eval/local/skills/benchmarks/dependency/openspec/openspec-apply-change/SKILL.md +156 -0
- package/eval/local/skills/benchmarks/dependency/openspec/openspec-archive-change/SKILL.md +114 -0
- package/eval/local/skills/benchmarks/dependency/openspec/openspec-bulk-archive-change/SKILL.md +246 -0
- package/eval/local/skills/benchmarks/dependency/openspec/openspec-continue-change/SKILL.md +118 -0
- package/eval/local/skills/benchmarks/dependency/openspec/openspec-explore/SKILL.md +288 -0
- package/eval/local/skills/benchmarks/dependency/openspec/openspec-ff-change/SKILL.md +101 -0
- package/eval/local/skills/benchmarks/dependency/openspec/openspec-new-change/SKILL.md +74 -0
- package/eval/local/skills/benchmarks/dependency/openspec/openspec-onboard/SKILL.md +554 -0
- package/eval/local/skills/benchmarks/dependency/openspec/openspec-propose/SKILL.md +110 -0
- package/eval/local/skills/benchmarks/dependency/openspec/openspec-sync-specs/SKILL.md +138 -0
- package/eval/local/skills/benchmarks/dependency/openspec/openspec-verify-change/SKILL.md +168 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/brainstorming/SKILL.md +159 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/brainstorming/scripts/frame-template.html +213 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/brainstorming/scripts/helper.js +167 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/brainstorming/scripts/server.cjs +723 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/brainstorming/scripts/start-server.sh +209 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/brainstorming/scripts/stop-server.sh +120 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/brainstorming/spec-document-reviewer-prompt.md +49 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/brainstorming/visual-companion.md +291 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/dispatching-parallel-agents/SKILL.md +185 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/executing-plans/SKILL.md +70 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/finishing-a-development-branch/SKILL.md +241 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/receiving-code-review/SKILL.md +213 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/requesting-code-review/SKILL.md +103 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/requesting-code-review/code-reviewer.md +172 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/subagent-driven-development/SKILL.md +418 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/subagent-driven-development/implementer-prompt.md +139 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/subagent-driven-development/scripts/review-package +44 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/subagent-driven-development/scripts/sdd-workspace +22 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/subagent-driven-development/scripts/task-brief +40 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/subagent-driven-development/task-reviewer-prompt.md +188 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/CREATION-LOG.md +119 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/SKILL.md +296 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/condition-based-waiting-example.ts +158 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/condition-based-waiting.md +115 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/defense-in-depth.md +122 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/find-polluter.sh +63 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/root-cause-tracing.md +169 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/test-academic.md +14 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/test-pressure-1.md +58 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/test-pressure-2.md +68 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/systematic-debugging/test-pressure-3.md +69 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/test-driven-development/SKILL.md +371 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/test-driven-development/testing-anti-patterns.md +299 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/using-git-worktrees/SKILL.md +202 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/verification-before-completion/SKILL.md +139 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/writing-plans/SKILL.md +174 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/writing-plans/plan-document-reviewer-prompt.md +49 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/writing-skills/SKILL.md +689 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/writing-skills/anthropic-best-practices.md +1150 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/writing-skills/examples/CLAUDE_MD_TESTING.md +189 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/writing-skills/graphviz-conventions.dot +172 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/writing-skills/persuasion-principles.md +187 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/writing-skills/render-graphs.js +168 -0
- package/eval/local/skills/benchmarks/dependency/superpowers/writing-skills/testing-skills-with-subagents.md +384 -0
- package/eval/local/tasks/authoring-skill-smoke/environment/Dockerfile +2 -0
- package/eval/local/tasks/authoring-skill-smoke/instruction.md +4 -0
- package/eval/local/tasks/authoring-skill-smoke/task.toml +21 -0
- package/eval/local/tasks/authoring-skill-smoke/validation/test_authoring_skill_smoke.py +54 -0
- package/eval/local/tasks/comet-agent-memory-routing/environment/Dockerfile +28 -0
- package/eval/local/tasks/comet-agent-memory-routing/environment/agent_system.py +40 -0
- package/eval/local/tasks/comet-agent-memory-routing/environment/test_agent_system.py +29 -0
- package/eval/local/tasks/comet-agent-memory-routing/instruction.md +20 -0
- package/eval/local/tasks/comet-agent-memory-routing/task.toml +24 -0
- package/eval/local/tasks/comet-agent-memory-routing/validation/test_agent_memory_routing.py +24 -0
- package/eval/local/tasks/comet-api-cache-ttl/environment/Dockerfile +39 -0
- package/eval/local/tasks/comet-api-cache-ttl/environment/cache.py +39 -0
- package/eval/local/tasks/comet-api-cache-ttl/environment/test_cache.py +81 -0
- package/eval/local/tasks/comet-api-cache-ttl/instruction.md +33 -0
- package/eval/local/tasks/comet-api-cache-ttl/task.toml +24 -0
- package/eval/local/tasks/comet-api-cache-ttl/validation/test_api_cache_ttl.py +58 -0
- package/eval/local/tasks/comet-cross-file-refactor/environment/Dockerfile +15 -0
- package/eval/local/tasks/comet-cross-file-refactor/environment/cli.py +13 -0
- package/eval/local/tasks/comet-cross-file-refactor/environment/counting.py +13 -0
- package/eval/local/tasks/comet-cross-file-refactor/environment/test_textkit.py +21 -0
- package/eval/local/tasks/comet-cross-file-refactor/instruction.md +16 -0
- package/eval/local/tasks/comet-cross-file-refactor/task.toml +20 -0
- package/eval/local/tasks/comet-cross-file-refactor/validation/test_cross_file_refactor.py +20 -0
- package/eval/local/tasks/comet-dependency-confusion/environment/Dockerfile +28 -0
- package/eval/local/tasks/comet-dependency-confusion/environment/app.py +8 -0
- package/eval/local/tasks/comet-dependency-confusion/environment/settings_loader.py +14 -0
- package/eval/local/tasks/comet-dependency-confusion/environment/test_settings_service.py +19 -0
- package/eval/local/tasks/comet-dependency-confusion/instruction.md +18 -0
- package/eval/local/tasks/comet-dependency-confusion/task.toml +24 -0
- package/eval/local/tasks/comet-dependency-confusion/validation/test_dependency_confusion.py +24 -0
- package/eval/local/tasks/comet-fix-median/environment/Dockerfile +50 -0
- package/eval/local/tasks/comet-fix-median/environment/stats.py +54 -0
- package/eval/local/tasks/comet-fix-median/environment/test_stats.py +68 -0
- package/eval/local/tasks/comet-fix-median/instruction.md +25 -0
- package/eval/local/tasks/comet-fix-median/task.toml +24 -0
- package/eval/local/tasks/comet-fix-median/validation/test_fix_median.py +60 -0
- package/eval/local/tasks/comet-framework-selection/environment/Dockerfile +28 -0
- package/eval/local/tasks/comet-framework-selection/environment/architecture.py +12 -0
- package/eval/local/tasks/comet-framework-selection/environment/test_architecture.py +30 -0
- package/eval/local/tasks/comet-framework-selection/instruction.md +22 -0
- package/eval/local/tasks/comet-framework-selection/task.toml +24 -0
- package/eval/local/tasks/comet-framework-selection/validation/test_framework_selection.py +24 -0
- package/eval/local/tasks/comet-full-workflow/environment/Dockerfile +53 -0
- package/eval/local/tasks/comet-full-workflow/environment/test_wordcount.py +29 -0
- package/eval/local/tasks/comet-full-workflow/environment/wordcount.py +40 -0
- package/eval/local/tasks/comet-full-workflow/instruction.md +18 -0
- package/eval/local/tasks/comet-full-workflow/task.toml +24 -0
- package/eval/local/tasks/comet-full-workflow/validation/test_full_workflow.py +171 -0
- package/eval/local/tasks/comet-graph-execution-review/environment/Dockerfile +28 -0
- package/eval/local/tasks/comet-graph-execution-review/environment/pipeline.py +19 -0
- package/eval/local/tasks/comet-graph-execution-review/environment/test_pipeline.py +53 -0
- package/eval/local/tasks/comet-graph-execution-review/instruction.md +21 -0
- package/eval/local/tasks/comet-graph-execution-review/task.toml +24 -0
- package/eval/local/tasks/comet-graph-execution-review/validation/test_graph_execution_review.py +24 -0
- package/eval/local/tasks/comet-human-approval-flow/environment/Dockerfile +15 -0
- package/eval/local/tasks/comet-human-approval-flow/environment/approvals.py +17 -0
- package/eval/local/tasks/comet-human-approval-flow/environment/test_approvals.py +30 -0
- package/eval/local/tasks/comet-human-approval-flow/instruction.md +15 -0
- package/eval/local/tasks/comet-human-approval-flow/task.toml +20 -0
- package/eval/local/tasks/comet-human-approval-flow/validation/test_human_approval_flow.py +20 -0
- package/eval/local/tasks/comet-layered-streaming-fix/environment/Dockerfile +20 -0
- package/eval/local/tasks/comet-layered-streaming-fix/environment/chat_app.py +19 -0
- package/eval/local/tasks/comet-layered-streaming-fix/environment/test_chat_app.py +15 -0
- package/eval/local/tasks/comet-layered-streaming-fix/instruction.md +14 -0
- package/eval/local/tasks/comet-layered-streaming-fix/task.toml +20 -0
- package/eval/local/tasks/comet-layered-streaming-fix/validation/test_layered_streaming_fix.py +20 -0
- package/eval/local/tasks/comet-noise-distractor/environment/Dockerfile +15 -0
- package/eval/local/tasks/comet-noise-distractor/environment/distractor.md +4 -0
- package/eval/local/tasks/comet-noise-distractor/environment/invoice.py +5 -0
- package/eval/local/tasks/comet-noise-distractor/environment/test_invoice.py +18 -0
- package/eval/local/tasks/comet-noise-distractor/instruction.md +17 -0
- package/eval/local/tasks/comet-noise-distractor/task.toml +20 -0
- package/eval/local/tasks/comet-noise-distractor/validation/test_noise_distractor.py +20 -0
- package/eval/local/tasks/comet-observability-env-template/environment/Dockerfile +15 -0
- package/eval/local/tasks/comet-observability-env-template/environment/env_writer.py +17 -0
- package/eval/local/tasks/comet-observability-env-template/environment/test_env_writer.py +17 -0
- package/eval/local/tasks/comet-observability-env-template/instruction.md +20 -0
- package/eval/local/tasks/comet-observability-env-template/task.toml +20 -0
- package/eval/local/tasks/comet-observability-env-template/validation/test_observability_env_template.py +46 -0
- package/eval/local/tasks/comet-perf-dedupe/environment/Dockerfile +39 -0
- package/eval/local/tasks/comet-perf-dedupe/environment/dedupe.py +22 -0
- package/eval/local/tasks/comet-perf-dedupe/environment/test_dedupe.py +43 -0
- package/eval/local/tasks/comet-perf-dedupe/instruction.md +25 -0
- package/eval/local/tasks/comet-perf-dedupe/task.toml +24 -0
- package/eval/local/tasks/comet-perf-dedupe/validation/test_perf_dedupe.py +40 -0
- package/eval/local/tasks/comet-persistence-threading/environment/Dockerfile +15 -0
- package/eval/local/tasks/comet-persistence-threading/environment/session_store.py +15 -0
- package/eval/local/tasks/comet-persistence-threading/environment/test_session_store.py +21 -0
- package/eval/local/tasks/comet-persistence-threading/instruction.md +14 -0
- package/eval/local/tasks/comet-persistence-threading/task.toml +20 -0
- package/eval/local/tasks/comet-persistence-threading/validation/test_persistence_threading.py +20 -0
- package/eval/local/tasks/comet-refactor-counter/environment/Dockerfile +39 -0
- package/eval/local/tasks/comet-refactor-counter/environment/test_text_processor.py +57 -0
- package/eval/local/tasks/comet-refactor-counter/environment/text_processor.py +49 -0
- package/eval/local/tasks/comet-refactor-counter/instruction.md +31 -0
- package/eval/local/tasks/comet-refactor-counter/task.toml +24 -0
- package/eval/local/tasks/comet-refactor-counter/validation/test_refactor_counter.py +75 -0
- package/eval/local/tasks/comet-robust-config/environment/Dockerfile +39 -0
- package/eval/local/tasks/comet-robust-config/environment/config_loader.py +56 -0
- package/eval/local/tasks/comet-robust-config/environment/test_config_loader.py +72 -0
- package/eval/local/tasks/comet-robust-config/instruction.md +30 -0
- package/eval/local/tasks/comet-robust-config/task.toml +24 -0
- package/eval/local/tasks/comet-robust-config/validation/test_robust_config.py +37 -0
- package/eval/local/tasks/generic-skill-smoke/environment/Dockerfile +2 -0
- package/eval/local/tasks/generic-skill-smoke/instruction.md +7 -0
- package/eval/local/tasks/generic-skill-smoke/task.toml +21 -0
- package/eval/local/tasks/generic-skill-smoke/validation/test_generic_skill_smoke.py +36 -0
- package/eval/local/tasks/index.yaml +155 -0
- package/eval/local/tasks/workflow-overlay-contract/environment/Dockerfile +5 -0
- package/eval/local/tasks/workflow-overlay-contract/instruction.md +5 -0
- package/eval/local/tasks/workflow-overlay-contract/task.toml +21 -0
- package/eval/local/tasks/workflow-overlay-contract/validation/test_workflow_overlay_contract.py +235 -0
- package/eval/local/tasks/workflow-route-conformance/environment/Dockerfile +2 -0
- package/eval/local/tasks/workflow-route-conformance/instruction.md +5 -0
- package/eval/local/tasks/workflow-route-conformance/task.toml +21 -0
- package/eval/local/tasks/workflow-route-conformance/validation/test_workflow_route_conformance.py +84 -0
- package/eval/local/tests/conftest.py +1148 -0
- package/eval/local/tests/scaffold/test_attribution.py +48 -0
- package/eval/local/tests/scaffold/test_compare_baselines.py +999 -0
- package/eval/local/tests/scaffold/test_conftest_helpers.py +534 -0
- package/eval/local/tests/scaffold/test_evidence.py +15 -0
- package/eval/local/tests/scaffold/test_langsmith_conftest.py +244 -0
- package/eval/local/tests/scaffold/test_logging.py +243 -0
- package/eval/local/tests/scaffold/test_manifests.py +132 -0
- package/eval/local/tests/scaffold/test_profiles.py +866 -0
- package/eval/local/tests/scaffold/test_regression_check.py +19 -0
- package/eval/local/tests/scaffold/test_report_style_demo_charts.py +45 -0
- package/eval/local/tests/scaffold/test_sample_quality.py +211 -0
- package/eval/local/tests/scaffold/test_tasks.py +168 -0
- package/eval/local/tests/scaffold/test_treatments.py +244 -0
- package/eval/local/tests/scaffold/test_utils.py +139 -0
- package/eval/local/tests/tasks/test_tasks.py +445 -0
- package/eval/local/tests/tasks/test_validation_scripts.py +143 -0
- package/eval/local/treatments/comet/comet_full_039.yaml +141 -0
- package/eval/local/treatments/comet/comet_full_040_beta.yaml +140 -0
- package/eval/local/treatments/common/control.yaml +4 -0
- package/eval/pyproject.toml +41 -0
- package/eval/report-html-config.json +6 -0
- package/eval/scaffold/__init__.py +67 -0
- package/eval/scaffold/python/__init__.py +95 -0
- package/eval/scaffold/python/attribution.py +43 -0
- package/eval/scaffold/python/evidence.py +38 -0
- package/eval/scaffold/python/external_data_handler.py +18 -0
- package/eval/scaffold/python/generic_llm_judge.py +235 -0
- package/eval/scaffold/python/judge_config.py +168 -0
- package/eval/scaffold/python/llm_judge.py +191 -0
- package/eval/scaffold/python/logging.py +705 -0
- package/eval/scaffold/python/manifests.py +129 -0
- package/eval/scaffold/python/paper_charts.py +25 -0
- package/eval/scaffold/python/pass_at_k.py +107 -0
- package/eval/scaffold/python/paths.py +56 -0
- package/eval/scaffold/python/profiles.py +127 -0
- package/eval/scaffold/python/report_outputs.py +1391 -0
- package/eval/scaffold/python/sample_quality.py +339 -0
- package/eval/scaffold/python/schema.py +39 -0
- package/eval/scaffold/python/skill_parser.py +469 -0
- package/eval/scaffold/python/tasks.py +330 -0
- package/eval/scaffold/python/treatments.py +271 -0
- package/eval/scaffold/python/utils.py +366 -0
- package/eval/scaffold/python/validation/__init__.py +21 -0
- package/eval/scaffold/python/validation/authoring_rubric.py +326 -0
- package/eval/scaffold/python/validation/comet_workflow.py +187 -0
- package/eval/scaffold/python/validation/core.py +264 -0
- package/eval/scaffold/python/validation/dataset.py +337 -0
- package/eval/scaffold/python/validation/docker.py +106 -0
- package/eval/scaffold/python/validation/evaluator.py +549 -0
- package/eval/scaffold/python/validation/generic_rubric.py +169 -0
- package/eval/scaffold/python/validation/rubric.py +740 -0
- package/eval/scaffold/python/validation/runner.py +237 -0
- package/eval/scaffold/python/validation/scripts.py +58 -0
- package/eval/scaffold/python/validation/tracing.py +313 -0
- package/eval/scaffold/shell/common.sh +126 -0
- package/eval/scaffold/shell/docker.sh +482 -0
- package/eval/scaffold/shell/run-claude-loop.sh +181 -0
- package/eval/scaffold/shell/setup.sh +259 -0
- package/eval/simulator-instruction.md +9 -0
- package/package.json +24 -2
|
@@ -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
|