@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,20 @@
|
|
|
1
|
+
[metadata]
|
|
2
|
+
name = "comet-noise-distractor"
|
|
3
|
+
description = "Fix invoice tax calculation while leaving an unrelated distracting file untouched"
|
|
4
|
+
difficulty = "medium"
|
|
5
|
+
category = "comet"
|
|
6
|
+
tags = ["comet", "workflow", "noise", "scope-control"]
|
|
7
|
+
default_treatments = ["CONTROL", "COMET_FULL_040_BETA", "COMET_FULL_039"]
|
|
8
|
+
|
|
9
|
+
[template]
|
|
10
|
+
required = []
|
|
11
|
+
|
|
12
|
+
[environment]
|
|
13
|
+
description = "Python invoice calculator plus a distracting unrelated file. Claude must keep scope tight."
|
|
14
|
+
dockerfile = "environment/Dockerfile"
|
|
15
|
+
timeout_sec = 900
|
|
16
|
+
|
|
17
|
+
[validation]
|
|
18
|
+
test_scripts = "test_noise_distractor.py"
|
|
19
|
+
target_artifacts = []
|
|
20
|
+
timeout = 120
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import subprocess
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
from comet_checks import run_comet_checks, write_results, _passed, _failed, WORKSPACE
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def check_invoice_scope() -> dict:
|
|
8
|
+
result = subprocess.run(
|
|
9
|
+
[sys.executable, "-m", "pytest", "test_invoice.py", "-q"],
|
|
10
|
+
capture_output=True,
|
|
11
|
+
text=True,
|
|
12
|
+
cwd=str(WORKSPACE),
|
|
13
|
+
)
|
|
14
|
+
if result.returncode != 0:
|
|
15
|
+
return _failed("invoice_fix_scope_control", (result.stdout + result.stderr)[-600:])
|
|
16
|
+
return _passed("invoice_fix_scope_control", "tax calculation fixed and distractor untouched")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
if __name__ == "__main__":
|
|
20
|
+
write_results([*run_comet_checks(), check_invoice_scope()])
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
FROM python:3.12-slim
|
|
2
|
+
|
|
3
|
+
WORKDIR /workspace
|
|
4
|
+
|
|
5
|
+
RUN apt-get update && apt-get install -y --no-install-recommends bash git curl jq ca-certificates nodejs npm && rm -rf /var/lib/apt/lists/*
|
|
6
|
+
RUN pip install --no-cache-dir pyyaml pytest
|
|
7
|
+
RUN npm config set registry https://registry.npmmirror.com && npm install -g @fission-ai/openspec@1.3.1 && npm install -g @anthropic-ai/claude-code@latest && npm config delete registry
|
|
8
|
+
COPY . /workspace/
|
|
9
|
+
RUN mkdir -p openspec/changes
|
|
10
|
+
RUN useradd --create-home --shell /bin/bash agent && chown -R agent:agent /workspace
|
|
11
|
+
USER agent
|
|
12
|
+
ENV HOME=/home/agent
|
|
13
|
+
ENV PYTHONPATH=/workspace
|
|
14
|
+
RUN git config --global user.email "agent@eval.local" && git config --global user.name "Comet Eval Agent" && git config --global init.defaultBranch master
|
|
15
|
+
CMD ["bash"]
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def write_env_example(path: str | Path = ".env.example") -> Path:
|
|
7
|
+
target = Path(path)
|
|
8
|
+
target.write_text(
|
|
9
|
+
"ANTHROPIC_API_KEY=\n"
|
|
10
|
+
"LANGSMITH_API_KEY=\n",
|
|
11
|
+
encoding="utf-8",
|
|
12
|
+
)
|
|
13
|
+
return target
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
if __name__ == "__main__":
|
|
17
|
+
write_env_example()
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import subprocess
|
|
4
|
+
import sys
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def test_env_example_contains_simplified_langsmith_config(tmp_path):
|
|
9
|
+
script = Path.cwd() / "env_writer.py"
|
|
10
|
+
result = subprocess.run([sys.executable, str(script)], cwd=tmp_path, capture_output=True, text=True)
|
|
11
|
+
assert result.returncode == 0
|
|
12
|
+
content = (tmp_path / ".env.example").read_text(encoding="utf-8")
|
|
13
|
+
assert "ANTHROPIC_API_KEY=" in content
|
|
14
|
+
assert "LANGSMITH_API_KEY=" in content
|
|
15
|
+
assert "LANGSMITH_PROJECT=agent-template" in content
|
|
16
|
+
assert "LANGSMITH_TRACING=true" in content
|
|
17
|
+
assert "TRACE_TO_LANGSMITH" not in content
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
You are working on a Python project called "agent-template".
|
|
2
|
+
|
|
3
|
+
Your task: Use the comet workflow to fix the `.env.example` generator for LangSmith observability.
|
|
4
|
+
|
|
5
|
+
This task is adapted from `skills-benchmarks/ls-lang-tracing`.
|
|
6
|
+
|
|
7
|
+
## Requirements
|
|
8
|
+
|
|
9
|
+
Running `python env_writer.py` should create `.env.example` with:
|
|
10
|
+
|
|
11
|
+
- `ANTHROPIC_API_KEY=`
|
|
12
|
+
- `LANGSMITH_API_KEY=`
|
|
13
|
+
- `LANGSMITH_PROJECT=agent-template`
|
|
14
|
+
- `LANGSMITH_TRACING=true`
|
|
15
|
+
|
|
16
|
+
Do not include `TRACE_TO_LANGSMITH` in the normal template; the harness derives Claude Code plugin variables from `LANGSMITH_*`.
|
|
17
|
+
|
|
18
|
+
Run `python -m pytest test_env_writer.py -q`, follow the comet workflow, and archive the completed change.
|
|
19
|
+
|
|
20
|
+
When the workflow asks for confirmation, assume "yes, proceed with the recommended option".
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
[metadata]
|
|
2
|
+
name = "comet-observability-env-template"
|
|
3
|
+
description = "Generate a LangSmith-ready .env.example with simplified LANGSMITH_* configuration"
|
|
4
|
+
difficulty = "medium"
|
|
5
|
+
category = "comet"
|
|
6
|
+
tags = ["comet", "workflow", "config", "observability"]
|
|
7
|
+
default_treatments = ["CONTROL", "COMET_FULL_040_BETA", "COMET_FULL_039"]
|
|
8
|
+
|
|
9
|
+
[template]
|
|
10
|
+
required = []
|
|
11
|
+
|
|
12
|
+
[environment]
|
|
13
|
+
description = "Python project with an incomplete env template generator."
|
|
14
|
+
dockerfile = "environment/Dockerfile"
|
|
15
|
+
timeout_sec = 900
|
|
16
|
+
|
|
17
|
+
[validation]
|
|
18
|
+
test_scripts = "test_observability_env_template.py"
|
|
19
|
+
target_artifacts = []
|
|
20
|
+
timeout = 120
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import subprocess
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
from comet_checks import WORKSPACE, _failed, _passed, run_comet_checks, write_results
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def check_langsmith_env_template() -> dict:
|
|
8
|
+
result = subprocess.run(
|
|
9
|
+
[sys.executable, "-m", "pytest", "test_env_writer.py", "-q"],
|
|
10
|
+
capture_output=True,
|
|
11
|
+
text=True,
|
|
12
|
+
cwd=str(WORKSPACE),
|
|
13
|
+
)
|
|
14
|
+
if result.returncode != 0:
|
|
15
|
+
return _failed("langsmith_env_template", (result.stdout + result.stderr)[-600:])
|
|
16
|
+
|
|
17
|
+
env_example = WORKSPACE / ".env.example"
|
|
18
|
+
if not env_example.exists():
|
|
19
|
+
run_result = subprocess.run(
|
|
20
|
+
[sys.executable, "env_writer.py"],
|
|
21
|
+
capture_output=True,
|
|
22
|
+
text=True,
|
|
23
|
+
cwd=str(WORKSPACE),
|
|
24
|
+
)
|
|
25
|
+
if run_result.returncode != 0:
|
|
26
|
+
return _failed(
|
|
27
|
+
"langsmith_env_template",
|
|
28
|
+
(run_result.stdout + run_result.stderr)[-600:],
|
|
29
|
+
)
|
|
30
|
+
content = env_example.read_text(encoding="utf-8")
|
|
31
|
+
expected = [
|
|
32
|
+
"ANTHROPIC_API_KEY=",
|
|
33
|
+
"LANGSMITH_API_KEY=",
|
|
34
|
+
"LANGSMITH_PROJECT=agent-template",
|
|
35
|
+
"LANGSMITH_TRACING=true",
|
|
36
|
+
]
|
|
37
|
+
missing = [item for item in expected if item not in content]
|
|
38
|
+
if missing:
|
|
39
|
+
return _failed("langsmith_env_template", f"missing entries: {missing}")
|
|
40
|
+
if "TRACE_TO_LANGSMITH" in content:
|
|
41
|
+
return _failed("langsmith_env_template", "TRACE_TO_LANGSMITH should not be emitted")
|
|
42
|
+
return _passed("langsmith_env_template", "LangSmith .env.example template is correct")
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
if __name__ == "__main__":
|
|
46
|
+
write_results([*run_comet_checks(), check_langsmith_env_template()])
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
FROM python:3.12-slim
|
|
2
|
+
|
|
3
|
+
WORKDIR /workspace
|
|
4
|
+
|
|
5
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
6
|
+
bash git curl jq ca-certificates \
|
|
7
|
+
nodejs npm && \
|
|
8
|
+
rm -rf /var/lib/apt/lists/*
|
|
9
|
+
|
|
10
|
+
RUN pip install --no-cache-dir pyyaml pytest
|
|
11
|
+
|
|
12
|
+
RUN npm config set registry https://registry.npmmirror.com && \
|
|
13
|
+
npm install -g @fission-ai/openspec@1.3.1 && \
|
|
14
|
+
npm config delete registry
|
|
15
|
+
|
|
16
|
+
ARG CLAUDE_CODE_VERSION=latest
|
|
17
|
+
RUN npm config set registry https://registry.npmmirror.com && \
|
|
18
|
+
npm install -g @anthropic-ai/claude-code@${CLAUDE_CODE_VERSION} && \
|
|
19
|
+
npm config delete registry
|
|
20
|
+
|
|
21
|
+
COPY dedupe.py /workspace/dedupe.py
|
|
22
|
+
COPY test_dedupe.py /workspace/test_dedupe.py
|
|
23
|
+
|
|
24
|
+
RUN mkdir -p wordcount-cli && \
|
|
25
|
+
echo '# Dedupe Tool' > wordcount-cli/README.md
|
|
26
|
+
RUN mkdir -p openspec/changes
|
|
27
|
+
|
|
28
|
+
RUN useradd --create-home --shell /bin/bash agent && \
|
|
29
|
+
chown -R agent:agent /workspace
|
|
30
|
+
USER agent
|
|
31
|
+
ENV HOME=/home/agent
|
|
32
|
+
# Validator scripts import scaffold.*; bake PYTHONPATH so it never crosses the
|
|
33
|
+
# MSYS path-conversion boundary on the docker run command line.
|
|
34
|
+
ENV PYTHONPATH=/workspace
|
|
35
|
+
RUN git config --global user.email "agent@eval.local" && \
|
|
36
|
+
git config --global user.name "Comet Eval Agent" && \
|
|
37
|
+
git config --global init.defaultBranch master
|
|
38
|
+
|
|
39
|
+
CMD ["bash"]
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""dedupe-tool: remove duplicates from a sequence while preserving order.
|
|
2
|
+
|
|
3
|
+
The current implementation is O(n²) — it scans the whole output list for each
|
|
4
|
+
element. This is correct but far too slow for large inputs (10k+ items).
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import Hashable, List, Sequence
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def dedupe(items: Sequence[Hashable]) -> List[Hashable]:
|
|
13
|
+
"""Remove duplicates, preserving first-occurrence order.
|
|
14
|
+
|
|
15
|
+
BUG (performance): O(n²) because `in result` is a linear scan. For a list
|
|
16
|
+
of 10,000 items this takes several seconds; it should be near-instant.
|
|
17
|
+
"""
|
|
18
|
+
result: List[Hashable] = []
|
|
19
|
+
for item in items:
|
|
20
|
+
if item not in result: # <-- O(n) scan, making the whole thing O(n²)
|
|
21
|
+
result.append(item)
|
|
22
|
+
return result
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""Tests for dedupe-tool. All pass currently; the issue is performance, not correctness."""
|
|
2
|
+
|
|
3
|
+
import time
|
|
4
|
+
|
|
5
|
+
import pytest
|
|
6
|
+
|
|
7
|
+
from dedupe import dedupe
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class TestCorrectness:
|
|
11
|
+
def test_basic(self):
|
|
12
|
+
assert dedupe([1, 2, 2, 3, 3, 3]) == [1, 2, 3]
|
|
13
|
+
|
|
14
|
+
def test_preserves_order(self):
|
|
15
|
+
assert dedupe([3, 1, 3, 2, 1]) == [3, 1, 2]
|
|
16
|
+
|
|
17
|
+
def test_empty(self):
|
|
18
|
+
assert dedupe([]) == []
|
|
19
|
+
|
|
20
|
+
def test_all_same(self):
|
|
21
|
+
assert dedupe([5, 5, 5, 5]) == [5]
|
|
22
|
+
|
|
23
|
+
def test_no_duplicates(self):
|
|
24
|
+
assert dedupe([1, 2, 3]) == [1, 2, 3]
|
|
25
|
+
|
|
26
|
+
def test_strings(self):
|
|
27
|
+
assert dedupe(["a", "b", "a", "c"]) == ["a", "b", "c"]
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class TestPerformance:
|
|
31
|
+
def test_large_input_is_fast(self):
|
|
32
|
+
"""A 30k-element list should dedupe in well under 1 second.
|
|
33
|
+
|
|
34
|
+
The current O(n^2) implementation takes ~2s on a fast machine and
|
|
35
|
+
longer in a Docker container; an O(n) implementation is near-instant.
|
|
36
|
+
"""
|
|
37
|
+
data = list(range(15000)) * 2 # 30k items, 15k unique
|
|
38
|
+
start = time.perf_counter()
|
|
39
|
+
result = dedupe(data)
|
|
40
|
+
elapsed = time.perf_counter() - start
|
|
41
|
+
|
|
42
|
+
assert result == list(range(15000)), "correctness broke"
|
|
43
|
+
assert elapsed < 1.0, f"too slow: {elapsed:.2f}s (O(n²)? expected O(n))"
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
You are working on a Python project called "dedupe-tool" - a utility for removing duplicates from sequences.
|
|
2
|
+
|
|
3
|
+
Your task: Use the comet workflow to **optimize** the `dedupe()` function from O(n²) to O(n).
|
|
4
|
+
|
|
5
|
+
## The problem
|
|
6
|
+
|
|
7
|
+
`dedupe()` in `dedupe.py` is correct but uses `if item not in result` where `result` is a list — a linear scan that makes the whole function O(n²). For a 10,000-element input this takes several seconds.
|
|
8
|
+
|
|
9
|
+
The performance test `TestPerformance::test_large_input_is_fast` currently FAILS because of this.
|
|
10
|
+
|
|
11
|
+
## Goal
|
|
12
|
+
|
|
13
|
+
Rewrite `dedupe()` to run in **O(n)** time while preserving:
|
|
14
|
+
1. **Correctness** — same output for all inputs (first-occurrence order preserved)
|
|
15
|
+
2. **The signature** — `dedupe(items: Sequence[Hashable]) -> List[Hashable]`
|
|
16
|
+
|
|
17
|
+
The standard approach is to track seen items in a `set` (O(1) lookup) alongside the result list. Consider whether `dict.fromkeys()` (which preserves insertion order in Python 3.7+) is appropriate, and document the tradeoff in your design.
|
|
18
|
+
|
|
19
|
+
## What to do
|
|
20
|
+
|
|
21
|
+
1. Run the tests to confirm the perf test fails: `python -m pytest test_dedupe.py -v`
|
|
22
|
+
2. Follow the comet workflow (Open → Design → Build → Verify → Archive).
|
|
23
|
+
3. After optimizing, confirm ALL tests pass including the performance test.
|
|
24
|
+
|
|
25
|
+
Start by detecting the current phase and following the comet workflow. When you reach a decision point that asks for confirmation, assume "yes, proceed with the recommended option".
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
[metadata]
|
|
2
|
+
name = "comet-perf-dedupe"
|
|
3
|
+
description = "Optimize an O(n^2) deduplication function to O(n) using a set/dict while preserving order"
|
|
4
|
+
difficulty = "medium"
|
|
5
|
+
category = "comet"
|
|
6
|
+
tags = ["comet", "workflow", "performance", "algorithm"]
|
|
7
|
+
default_treatments = [
|
|
8
|
+
"CONTROL",
|
|
9
|
+
"COMET_FULL_040_BETA",
|
|
10
|
+
"COMET_FULL_039",
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
[template]
|
|
14
|
+
required = []
|
|
15
|
+
|
|
16
|
+
[environment]
|
|
17
|
+
description = "Python dedupe tool with an O(n^2) implementation. Claude must optimize to O(n)."
|
|
18
|
+
dockerfile = "environment/Dockerfile"
|
|
19
|
+
timeout_sec = 900
|
|
20
|
+
|
|
21
|
+
[validation]
|
|
22
|
+
test_scripts = "test_perf_dedupe.py"
|
|
23
|
+
target_artifacts = []
|
|
24
|
+
timeout = 120
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"""Validation for the comet-perf-dedupe task.
|
|
2
|
+
|
|
3
|
+
Checks: comet workflow followed + all tests pass (correctness + performance).
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import subprocess
|
|
7
|
+
import sys
|
|
8
|
+
|
|
9
|
+
from comet_checks import (
|
|
10
|
+
run_comet_checks,
|
|
11
|
+
write_results,
|
|
12
|
+
_passed,
|
|
13
|
+
_failed,
|
|
14
|
+
WORKSPACE,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def check_dedupe_optimized() -> dict:
|
|
19
|
+
"""All dedupe tests pass, including the performance test."""
|
|
20
|
+
result = subprocess.run(
|
|
21
|
+
[sys.executable, "-m", "pytest", "test_dedupe.py", "-v", "-q"],
|
|
22
|
+
capture_output=True, text=True, cwd=str(WORKSPACE),
|
|
23
|
+
)
|
|
24
|
+
if result.returncode != 0:
|
|
25
|
+
# Distinguish perf failure from correctness failure.
|
|
26
|
+
out = result.stdout + result.stderr
|
|
27
|
+
if "too slow" in out or "O(n" in out:
|
|
28
|
+
return _failed("dedupe_optimized", f"still O(n²): {out[-300:]}")
|
|
29
|
+
return _failed("dedupe_optimized", f"tests failing:\n{out[-400:]}")
|
|
30
|
+
return _passed("dedupe_optimized", "correctness + performance tests pass")
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def run_all() -> list[dict]:
|
|
34
|
+
results = run_comet_checks()
|
|
35
|
+
results.append(check_dedupe_optimized())
|
|
36
|
+
return results
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
if __name__ == "__main__":
|
|
40
|
+
write_results(run_all())
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
FROM python:3.12-slim
|
|
2
|
+
|
|
3
|
+
WORKDIR /workspace
|
|
4
|
+
|
|
5
|
+
RUN apt-get update && apt-get install -y --no-install-recommends bash git curl jq ca-certificates nodejs npm && rm -rf /var/lib/apt/lists/*
|
|
6
|
+
RUN pip install --no-cache-dir pyyaml pytest
|
|
7
|
+
RUN npm config set registry https://registry.npmmirror.com && npm install -g @fission-ai/openspec@1.3.1 && npm install -g @anthropic-ai/claude-code@latest && npm config delete registry
|
|
8
|
+
COPY . /workspace/
|
|
9
|
+
RUN mkdir -p openspec/changes
|
|
10
|
+
RUN useradd --create-home --shell /bin/bash agent && chown -R agent:agent /workspace
|
|
11
|
+
USER agent
|
|
12
|
+
ENV HOME=/home/agent
|
|
13
|
+
ENV PYTHONPATH=/workspace
|
|
14
|
+
RUN git config --global user.email "agent@eval.local" && git config --global user.name "Comet Eval Agent" && git config --global init.defaultBranch master
|
|
15
|
+
CMD ["bash"]
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class SessionStore:
|
|
7
|
+
def __init__(self, path: str | Path):
|
|
8
|
+
self.path = Path(path)
|
|
9
|
+
self._state: dict[str, str] = {}
|
|
10
|
+
|
|
11
|
+
def save(self, thread_id: str, key: str, value: str) -> None:
|
|
12
|
+
self._state[key] = value
|
|
13
|
+
|
|
14
|
+
def load(self, thread_id: str, key: str, default: str | None = None) -> str | None:
|
|
15
|
+
return self._state.get(key, default)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from session_store import SessionStore
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def test_thread_ids_are_isolated(tmp_path):
|
|
7
|
+
store = SessionStore(tmp_path / "state.json")
|
|
8
|
+
store.save("thread-a", "status", "draft")
|
|
9
|
+
store.save("thread-b", "status", "approved")
|
|
10
|
+
|
|
11
|
+
assert store.load("thread-a", "status") == "draft"
|
|
12
|
+
assert store.load("thread-b", "status") == "approved"
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def test_state_persists_across_store_instances(tmp_path):
|
|
16
|
+
path = tmp_path / "state.json"
|
|
17
|
+
first = SessionStore(path)
|
|
18
|
+
first.save("thread-a", "checkpoint", "ready")
|
|
19
|
+
|
|
20
|
+
second = SessionStore(path)
|
|
21
|
+
assert second.load("thread-a", "checkpoint") == "ready"
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
You are working on a Python project called "session-store".
|
|
2
|
+
|
|
3
|
+
Your task: Use the comet workflow to fix state isolation and persistence.
|
|
4
|
+
|
|
5
|
+
This task is adapted from `skills-benchmarks/oss-fix-lg-persistence`.
|
|
6
|
+
|
|
7
|
+
## Bugs
|
|
8
|
+
|
|
9
|
+
- Values written for one `thread_id` leak into another thread.
|
|
10
|
+
- Creating a new `SessionStore` pointed at the same data file loses previously saved state.
|
|
11
|
+
|
|
12
|
+
Run `python -m pytest test_session_store.py -q`, follow the comet workflow, and keep the `SessionStore` API compatible.
|
|
13
|
+
|
|
14
|
+
When the workflow asks for confirmation, assume "yes, proceed with the recommended option".
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
[metadata]
|
|
2
|
+
name = "comet-persistence-threading"
|
|
3
|
+
description = "Make session state isolate by thread_id and persist across store instances"
|
|
4
|
+
difficulty = "hard"
|
|
5
|
+
category = "comet"
|
|
6
|
+
tags = ["comet", "workflow", "persistence", "threading"]
|
|
7
|
+
default_treatments = ["CONTROL", "COMET_FULL_040_BETA", "COMET_FULL_039"]
|
|
8
|
+
|
|
9
|
+
[template]
|
|
10
|
+
required = []
|
|
11
|
+
|
|
12
|
+
[environment]
|
|
13
|
+
description = "Python session store with thread isolation and persistence bugs."
|
|
14
|
+
dockerfile = "environment/Dockerfile"
|
|
15
|
+
timeout_sec = 900
|
|
16
|
+
|
|
17
|
+
[validation]
|
|
18
|
+
test_scripts = "test_persistence_threading.py"
|
|
19
|
+
target_artifacts = []
|
|
20
|
+
timeout = 120
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import subprocess
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
from comet_checks import run_comet_checks, write_results, _passed, _failed, WORKSPACE
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def check_persistence_threading() -> dict:
|
|
8
|
+
result = subprocess.run(
|
|
9
|
+
[sys.executable, "-m", "pytest", "test_session_store.py", "-q"],
|
|
10
|
+
capture_output=True,
|
|
11
|
+
text=True,
|
|
12
|
+
cwd=str(WORKSPACE),
|
|
13
|
+
)
|
|
14
|
+
if result.returncode != 0:
|
|
15
|
+
return _failed("persistence_threading", (result.stdout + result.stderr)[-600:])
|
|
16
|
+
return _passed("persistence_threading", "thread state is isolated and persisted")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
if __name__ == "__main__":
|
|
20
|
+
write_results([*run_comet_checks(), check_persistence_threading()])
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
FROM python:3.12-slim
|
|
2
|
+
|
|
3
|
+
WORKDIR /workspace
|
|
4
|
+
|
|
5
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
6
|
+
bash git curl jq ca-certificates \
|
|
7
|
+
nodejs npm && \
|
|
8
|
+
rm -rf /var/lib/apt/lists/*
|
|
9
|
+
|
|
10
|
+
RUN pip install --no-cache-dir pyyaml pytest
|
|
11
|
+
|
|
12
|
+
RUN npm config set registry https://registry.npmmirror.com && \
|
|
13
|
+
npm install -g @fission-ai/openspec@1.3.1 && \
|
|
14
|
+
npm config delete registry
|
|
15
|
+
|
|
16
|
+
ARG CLAUDE_CODE_VERSION=latest
|
|
17
|
+
RUN npm config set registry https://registry.npmmirror.com && \
|
|
18
|
+
npm install -g @anthropic-ai/claude-code@${CLAUDE_CODE_VERSION} && \
|
|
19
|
+
npm config delete registry
|
|
20
|
+
|
|
21
|
+
COPY text_processor.py /workspace/text_processor.py
|
|
22
|
+
COPY test_text_processor.py /workspace/test_text_processor.py
|
|
23
|
+
|
|
24
|
+
RUN mkdir -p wordcount-cli && \
|
|
25
|
+
echo '# Text Processor' > wordcount-cli/README.md
|
|
26
|
+
RUN mkdir -p openspec/changes
|
|
27
|
+
|
|
28
|
+
RUN useradd --create-home --shell /bin/bash agent && \
|
|
29
|
+
chown -R agent:agent /workspace
|
|
30
|
+
USER agent
|
|
31
|
+
ENV HOME=/home/agent
|
|
32
|
+
# Validator scripts import scaffold.*; bake PYTHONPATH so it never crosses the
|
|
33
|
+
# MSYS path-conversion boundary on the docker run command line.
|
|
34
|
+
ENV PYTHONPATH=/workspace
|
|
35
|
+
RUN git config --global user.email "agent@eval.local" && \
|
|
36
|
+
git config --global user.name "Comet Eval Agent" && \
|
|
37
|
+
git config --global init.defaultBranch master
|
|
38
|
+
|
|
39
|
+
CMD ["bash"]
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"""Tests for text-processor. All pass; refactoring must keep them passing."""
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from text_processor import count_words, count_lines, count_chars, analyze
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TestCountWords:
|
|
9
|
+
def test_basic(self):
|
|
10
|
+
assert count_words("hello world foo") == 3
|
|
11
|
+
|
|
12
|
+
def test_empty(self):
|
|
13
|
+
assert count_words("") == 0
|
|
14
|
+
|
|
15
|
+
def test_whitespace_only(self):
|
|
16
|
+
assert count_words(" \t ") == 0
|
|
17
|
+
|
|
18
|
+
def test_single(self):
|
|
19
|
+
assert count_words("hello") == 1
|
|
20
|
+
|
|
21
|
+
def test_multiple_spaces(self):
|
|
22
|
+
assert count_words("a b c") == 3
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class TestCountLines:
|
|
26
|
+
def test_basic(self):
|
|
27
|
+
assert count_lines("line1\nline2\nline3") == 3
|
|
28
|
+
|
|
29
|
+
def test_empty(self):
|
|
30
|
+
assert count_lines("") == 0
|
|
31
|
+
|
|
32
|
+
def test_single_no_newline(self):
|
|
33
|
+
assert count_lines("hello") == 1
|
|
34
|
+
|
|
35
|
+
def test_trailing_newline(self):
|
|
36
|
+
assert count_lines("a\nb\n") == 2
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class TestCountChars:
|
|
40
|
+
def test_basic(self):
|
|
41
|
+
assert count_chars("hello") == 5
|
|
42
|
+
|
|
43
|
+
def test_empty(self):
|
|
44
|
+
assert count_chars("") == 0
|
|
45
|
+
|
|
46
|
+
def test_with_spaces(self):
|
|
47
|
+
assert count_chars("a b c") == 5
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class TestAnalyze:
|
|
51
|
+
def test_combined(self):
|
|
52
|
+
text = "hello world\nfoo bar"
|
|
53
|
+
result = analyze(text)
|
|
54
|
+
assert result == {"words": 4, "lines": 2, "chars": 19}
|
|
55
|
+
|
|
56
|
+
def test_empty(self):
|
|
57
|
+
assert analyze("") == {"words": 0, "lines": 0, "chars": 0}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"""text-processor: text analysis utilities.
|
|
2
|
+
|
|
3
|
+
This module has three near-identical counting functions with duplicated logic.
|
|
4
|
+
They should be refactored into a single `count(text, unit)` dispatcher while
|
|
5
|
+
preserving the exact same behavior (and the public names as thin wrappers).
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def count_words(text: str) -> int:
|
|
12
|
+
"""Count words (whitespace-separated tokens)."""
|
|
13
|
+
if not text:
|
|
14
|
+
return 0
|
|
15
|
+
words = text.split()
|
|
16
|
+
count = 0
|
|
17
|
+
for word in words:
|
|
18
|
+
count += 1
|
|
19
|
+
return count
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def count_lines(text: str) -> int:
|
|
23
|
+
"""Count lines (newline-separated)."""
|
|
24
|
+
if not text:
|
|
25
|
+
return 0
|
|
26
|
+
lines = text.splitlines()
|
|
27
|
+
count = 0
|
|
28
|
+
for line in lines:
|
|
29
|
+
count += 1
|
|
30
|
+
return count
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def count_chars(text: str) -> int:
|
|
34
|
+
"""Count characters."""
|
|
35
|
+
if not text:
|
|
36
|
+
return 0
|
|
37
|
+
count = 0
|
|
38
|
+
for char in text:
|
|
39
|
+
count += 1
|
|
40
|
+
return count
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def analyze(text: str) -> dict:
|
|
44
|
+
"""Return a summary of all counts."""
|
|
45
|
+
return {
|
|
46
|
+
"words": count_words(text),
|
|
47
|
+
"lines": count_lines(text),
|
|
48
|
+
"chars": count_chars(text),
|
|
49
|
+
}
|