orizu 0.5.19 → 0.5.21
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 +23 -0
- package/dist/archive-artifacts-cli.d.ts +50 -0
- package/dist/archive-artifacts-cli.d.ts.map +1 -0
- package/dist/artifact-archive.d.ts +48 -0
- package/dist/artifact-archive.d.ts.map +1 -0
- package/dist/artifact-pull.d.ts +22 -0
- package/dist/artifact-pull.d.ts.map +1 -0
- package/dist/banner.d.ts +3 -0
- package/dist/banner.d.ts.map +1 -0
- package/dist/connectors-cli.d.ts +31 -0
- package/dist/connectors-cli.d.ts.map +1 -0
- package/dist/credentials.d.ts +46 -0
- package/dist/credentials.d.ts.map +1 -0
- package/dist/csv.d.ts +49 -0
- package/dist/csv.d.ts.map +1 -0
- package/dist/dataset-download.d.ts +6 -0
- package/dist/dataset-download.d.ts.map +1 -0
- package/dist/dataset-edit-rows.d.ts +10 -0
- package/dist/dataset-edit-rows.d.ts.map +1 -0
- package/dist/dataset-upload-snapshot.d.ts +13 -0
- package/dist/dataset-upload-snapshot.d.ts.map +1 -0
- package/dist/daytona-slice-rehearsal.d.ts +89 -0
- package/dist/daytona-slice-rehearsal.d.ts.map +1 -0
- package/dist/daytona-slice.d.ts +106 -0
- package/dist/daytona-slice.d.ts.map +1 -0
- package/dist/deploy-key-merge-core.d.ts +121 -0
- package/dist/deploy-key-merge-core.d.ts.map +1 -0
- package/dist/diff-comments-cli.d.ts +12 -0
- package/dist/diff-comments-cli.d.ts.map +1 -0
- package/dist/diff-comments-cli.js +21 -2
- package/dist/egress-allowlist-cli.d.ts +23 -0
- package/dist/egress-allowlist-cli.d.ts.map +1 -0
- package/dist/egress-policy.d.ts +108 -0
- package/dist/egress-policy.d.ts.map +1 -0
- package/dist/error-response.d.ts +9 -0
- package/dist/error-response.d.ts.map +1 -0
- package/dist/file-parser.d.ts +5 -0
- package/dist/file-parser.d.ts.map +1 -0
- package/dist/gepa-engine-dispatch.d.ts +9 -0
- package/dist/gepa-engine-dispatch.d.ts.map +1 -0
- package/dist/gepa-engine-dispatch.js +307 -0
- package/dist/gepa-python-command.d.ts +6 -0
- package/dist/gepa-python-command.d.ts.map +1 -0
- package/dist/gepa-python-command.js +26 -0
- package/dist/gepa-python-paths.d.ts +6 -0
- package/dist/gepa-python-paths.d.ts.map +1 -0
- package/dist/gepa-python-paths.js +42 -0
- package/dist/git-credential.d.ts +69 -0
- package/dist/git-credential.d.ts.map +1 -0
- package/dist/git-recovery-environment.d.ts +31 -0
- package/dist/git-recovery-environment.d.ts.map +1 -0
- package/dist/github-setup.d.ts +122 -0
- package/dist/github-setup.d.ts.map +1 -0
- package/dist/global-flags.d.ts +12 -0
- package/dist/global-flags.d.ts.map +1 -0
- package/dist/help.d.ts +46 -0
- package/dist/help.d.ts.map +1 -0
- package/dist/help.js +93 -25
- package/dist/hosted-boot.d.ts +273 -0
- package/dist/hosted-boot.d.ts.map +1 -0
- package/dist/hosted-bootstrap-rehearsal.d.ts +86 -0
- package/dist/hosted-bootstrap-rehearsal.d.ts.map +1 -0
- package/dist/hosted-bootstrap.d.ts +188 -0
- package/dist/hosted-bootstrap.d.ts.map +1 -0
- package/dist/hosted-broker-server.d.ts +50 -0
- package/dist/hosted-broker-server.d.ts.map +1 -0
- package/dist/hosted-git-http-server.d.ts +36 -0
- package/dist/hosted-git-http-server.d.ts.map +1 -0
- package/dist/hosted-harness-claude.d.ts +195 -0
- package/dist/hosted-harness-claude.d.ts.map +1 -0
- package/dist/hosted-harness-opencode.d.ts +227 -0
- package/dist/hosted-harness-opencode.d.ts.map +1 -0
- package/dist/hosted-harness.d.ts +118 -0
- package/dist/hosted-harness.d.ts.map +1 -0
- package/dist/hosted-harvest.d.ts +68 -0
- package/dist/hosted-harvest.d.ts.map +1 -0
- package/dist/hosted-headless.d.ts +72 -0
- package/dist/hosted-headless.d.ts.map +1 -0
- package/dist/hosted-loop-lifecycle.d.ts +206 -0
- package/dist/hosted-loop-lifecycle.d.ts.map +1 -0
- package/dist/hosted-loop.d.ts +170 -0
- package/dist/hosted-loop.d.ts.map +1 -0
- package/dist/hosted-run-event-sink.d.ts +222 -0
- package/dist/hosted-run-event-sink.d.ts.map +1 -0
- package/dist/hosted-runtime-assets.d.ts +186 -0
- package/dist/hosted-runtime-assets.d.ts.map +1 -0
- package/dist/hosted-session-cli.d.ts +258 -0
- package/dist/hosted-session-cli.d.ts.map +1 -0
- package/dist/hosted-skill-staging.d.ts +73 -0
- package/dist/hosted-skill-staging.d.ts.map +1 -0
- package/dist/http.d.ts +8 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +119 -129
- package/dist/instruction-set-gepa-launch.d.ts +3 -0
- package/dist/instruction-set-gepa-launch.d.ts.map +1 -0
- package/dist/instruction-set-gepa-launch.js +15 -0
- package/dist/instruction-set-loader.d.ts +6 -0
- package/dist/instruction-set-loader.d.ts.map +1 -0
- package/dist/instruction-set-loader.js +59 -0
- package/dist/instruction-set-manifest.d.ts +14 -0
- package/dist/instruction-set-manifest.d.ts.map +1 -0
- package/dist/instruction-set-manifest.js +162 -0
- package/dist/instruction-sets-cli.d.ts +40 -0
- package/dist/instruction-sets-cli.d.ts.map +1 -0
- package/dist/instruction-sets-cli.js +361 -0
- package/dist/json-response.d.ts +4 -0
- package/dist/json-response.d.ts.map +1 -0
- package/dist/jsonl-stream.d.ts +8 -0
- package/dist/jsonl-stream.d.ts.map +1 -0
- package/dist/kill-switch-cli.d.ts +30 -0
- package/dist/kill-switch-cli.d.ts.map +1 -0
- package/dist/loopback-serve.d.ts +25 -0
- package/dist/loopback-serve.d.ts.map +1 -0
- package/dist/manifests-cli.d.ts +22 -0
- package/dist/manifests-cli.d.ts.map +1 -0
- package/dist/markdown-report-input.d.ts +7 -0
- package/dist/markdown-report-input.d.ts.map +1 -0
- package/dist/markdown-report-input.js +15 -1
- package/dist/merge-job.d.ts +155 -0
- package/dist/merge-job.d.ts.map +1 -0
- package/dist/model-configs-cli.d.ts +19 -0
- package/dist/model-configs-cli.d.ts.map +1 -0
- package/dist/model-configs-cli.js +104 -0
- package/dist/optimization-export-cli.d.ts +19 -0
- package/dist/optimization-export-cli.d.ts.map +1 -0
- package/dist/optimizations-list-cli.d.ts +20 -0
- package/dist/optimizations-list-cli.d.ts.map +1 -0
- package/dist/optimizations-promote-cli.d.ts +8 -0
- package/dist/optimizations-promote-cli.d.ts.map +1 -0
- package/dist/optimizations-promote-cli.js +34 -0
- package/dist/option-validation.d.ts +15 -0
- package/dist/option-validation.d.ts.map +1 -0
- package/dist/preview-runtime.d.ts +63 -0
- package/dist/preview-runtime.d.ts.map +1 -0
- package/dist/prompt-draft-push.d.ts +60 -0
- package/dist/prompt-draft-push.d.ts.map +1 -0
- package/dist/prompt-label-cli.d.ts +11 -0
- package/dist/prompt-label-cli.d.ts.map +1 -0
- package/dist/prompt-label-cli.js +29 -0
- package/dist/prompt-length-wire.d.ts +28 -0
- package/dist/prompt-length-wire.d.ts.map +1 -0
- package/dist/prompt-length-wire.js +2 -2
- package/dist/prompt-report-cli.d.ts +10 -0
- package/dist/prompt-report-cli.d.ts.map +1 -0
- package/dist/prompt-report-cli.js +2 -2
- package/dist/prompt-summary-table.d.ts +15 -0
- package/dist/prompt-summary-table.d.ts.map +1 -0
- package/dist/prompt-summary-table.js +6 -0
- package/dist/registration-tag-warning.d.ts +32 -0
- package/dist/registration-tag-warning.d.ts.map +1 -0
- package/dist/report-comments-cli.d.ts +16 -0
- package/dist/report-comments-cli.d.ts.map +1 -0
- package/dist/report-markdown-blankness.d.ts +2 -0
- package/dist/report-markdown-blankness.d.ts.map +1 -0
- package/dist/report-markdown-blankness.js +6 -0
- package/dist/report-replacement-warning.d.ts +17 -0
- package/dist/report-replacement-warning.d.ts.map +1 -0
- package/dist/report-replacement-warning.js +31 -0
- package/dist/repository-backup-core.d.ts +225 -0
- package/dist/repository-backup-core.d.ts.map +1 -0
- package/dist/repository-recovery-manifest.d.ts +83 -0
- package/dist/repository-recovery-manifest.d.ts.map +1 -0
- package/dist/run-event-digest.d.ts +74 -0
- package/dist/run-event-digest.d.ts.map +1 -0
- package/dist/runner-dir-verify.d.ts +66 -0
- package/dist/runner-dir-verify.d.ts.map +1 -0
- package/dist/runner-instruction-set-contract.d.ts +24 -0
- package/dist/runner-instruction-set-contract.d.ts.map +1 -0
- package/dist/runner-instruction-set-contract.js +50 -0
- package/dist/sandbox-hygiene.d.ts +45 -0
- package/dist/sandbox-hygiene.d.ts.map +1 -0
- package/dist/sandbox-provider.d.ts +193 -0
- package/dist/sandbox-provider.d.ts.map +1 -0
- package/dist/scorer-draft-push.d.ts +50 -0
- package/dist/scorer-draft-push.d.ts.map +1 -0
- package/dist/scorers-cli.d.ts +20 -0
- package/dist/scorers-cli.d.ts.map +1 -0
- package/dist/scorers-cli.js +22 -0
- package/dist/scorers-verify-parity-bridge.d.ts +16 -0
- package/dist/scorers-verify-parity-bridge.d.ts.map +1 -0
- package/dist/scorers-verify-parity-bridge.js +90 -0
- package/dist/scorers-verify-parity.d.ts +81 -0
- package/dist/scorers-verify-parity.d.ts.map +1 -0
- package/dist/scorers-verify-parity.js +502 -0
- package/dist/scores-accept-cli.d.ts +21 -0
- package/dist/scores-accept-cli.d.ts.map +1 -0
- package/dist/secret-redaction.d.ts +47 -0
- package/dist/secret-redaction.d.ts.map +1 -0
- package/dist/session-timeline.d.ts +54 -0
- package/dist/session-timeline.d.ts.map +1 -0
- package/dist/setup-prompt.d.ts +5 -0
- package/dist/setup-prompt.d.ts.map +1 -0
- package/dist/skill-installer.d.ts +68 -0
- package/dist/skill-installer.d.ts.map +1 -0
- package/dist/skilled-proposer-launch.d.ts +7 -0
- package/dist/skilled-proposer-launch.d.ts.map +1 -0
- package/dist/skilled-proposer-launch.js +60 -0
- package/dist/smoke.d.ts +102 -0
- package/dist/smoke.d.ts.map +1 -0
- package/dist/start-intent.d.ts +12 -0
- package/dist/start-intent.d.ts.map +1 -0
- package/dist/task-assignment-manifest.d.ts +15 -0
- package/dist/task-assignment-manifest.d.ts.map +1 -0
- package/dist/task-create-error.d.ts +18 -0
- package/dist/task-create-error.d.ts.map +1 -0
- package/dist/team-connectors-cli.d.ts +29 -0
- package/dist/team-connectors-cli.d.ts.map +1 -0
- package/dist/types.d.ts +39 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/vercel-sandbox-provider.d.ts +156 -0
- package/dist/vercel-sandbox-provider.d.ts.map +1 -0
- package/dist/workbench-cli.d.ts +233 -0
- package/dist/workbench-cli.d.ts.map +1 -0
- package/dist/workspace-sync.d.ts +207 -0
- package/dist/workspace-sync.d.ts.map +1 -0
- package/dist/workspace.d.ts +92 -0
- package/dist/workspace.d.ts.map +1 -0
- package/dist/zip-draft-push.d.ts +55 -0
- package/dist/zip-draft-push.d.ts.map +1 -0
- package/package.json +15 -2
- package/requirements/README.md +138 -0
- package/requirements/skilled-proposer.in +66 -0
- package/requirements/skilled-proposer.lock +265 -0
- package/scripts/build-cli-dist.mjs +30 -0
- package/scripts/ensure-skilled-proposer-venv.mjs +5 -0
- package/scripts/orizu-source-checkout.d.mts +1 -0
- package/scripts/orizu-source-checkout.mjs +10 -0
- package/scripts/refresh-skilled-proposer-lock.mjs +256 -0
- package/scripts/vendor-gepa-python.mjs +187 -4
- package/src/diff-comments-cli.ts +41 -3
- package/src/gepa-engine-dispatch.ts +340 -0
- package/src/gepa-python-command.ts +31 -0
- package/src/gepa-python-paths.ts +56 -0
- package/src/help.ts +95 -25
- package/src/index.ts +131 -166
- package/src/instruction-set-gepa-launch.ts +28 -0
- package/src/instruction-set-loader.ts +37 -0
- package/src/instruction-set-manifest.ts +120 -0
- package/src/instruction-sets-cli.ts +306 -0
- package/src/markdown-report-input.ts +19 -1
- package/src/model-configs-cli.ts +119 -0
- package/src/optimizations-promote-cli.ts +41 -0
- package/src/prompt-label-cli.ts +55 -0
- package/src/prompt-length-wire.ts +1 -1
- package/src/prompt-report-cli.ts +2 -2
- package/src/prompt-summary-table.ts +12 -0
- package/src/report-markdown-blankness.ts +6 -0
- package/src/report-replacement-warning.ts +35 -0
- package/src/runner-instruction-set-contract.ts +64 -0
- package/src/scorers-cli.ts +40 -0
- package/src/scorers-verify-parity-bridge.ts +90 -0
- package/src/scorers-verify-parity.ts +564 -0
- package/src/skilled-proposer-launch.ts +89 -0
- package/src/skilled-proposer-venv-manager.mjs +757 -0
- package/tsconfig.json +2 -0
- package/vendor/gepa-python/LICENSE +7 -0
- package/vendor/gepa-python/manifest.json +107 -0
- package/vendor/gepa-python/src/gepa/__init__.py +22 -0
- package/vendor/gepa-python/src/gepa/adapters/__init__.py +0 -0
- package/vendor/gepa-python/src/gepa/adapters/anymaths_adapter/__init__.py +1 -0
- package/vendor/gepa-python/src/gepa/adapters/anymaths_adapter/anymaths_adapter.py +174 -0
- package/vendor/gepa-python/src/gepa/adapters/confidence_adapter/__init__.py +26 -0
- package/vendor/gepa-python/src/gepa/adapters/confidence_adapter/confidence_adapter.py +618 -0
- package/vendor/gepa-python/src/gepa/adapters/confidence_adapter/scoring.py +206 -0
- package/vendor/gepa-python/src/gepa/adapters/default_adapter/__init__.py +0 -0
- package/vendor/gepa-python/src/gepa/adapters/default_adapter/default_adapter.py +206 -0
- package/vendor/gepa-python/src/gepa/adapters/dspy_adapter/__init__.py +0 -0
- package/vendor/gepa-python/src/gepa/adapters/dspy_adapter/dspy_adapter.py +525 -0
- package/vendor/gepa-python/src/gepa/adapters/dspy_adapter/instruction_proposal.py +500 -0
- package/vendor/gepa-python/src/gepa/adapters/dspy_full_program_adapter/__init__.py +6 -0
- package/vendor/gepa-python/src/gepa/adapters/dspy_full_program_adapter/dspy_program_proposal_signature.py +137 -0
- package/vendor/gepa-python/src/gepa/adapters/dspy_full_program_adapter/full_program_adapter.py +269 -0
- package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/__init__.py +56 -0
- package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/evaluation_metrics.py +226 -0
- package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/generic_rag_adapter.py +496 -0
- package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/rag_pipeline.py +238 -0
- package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/vector_store_interface.py +212 -0
- package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/vector_stores/__init__.py +2 -0
- package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/vector_stores/chroma_store.py +196 -0
- package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/vector_stores/lancedb_store.py +422 -0
- package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/vector_stores/milvus_store.py +409 -0
- package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/vector_stores/qdrant_store.py +368 -0
- package/vendor/gepa-python/src/gepa/adapters/generic_rag_adapter/vector_stores/weaviate_store.py +418 -0
- package/vendor/gepa-python/src/gepa/adapters/langchain_adapter/__init__.py +11 -0
- package/vendor/gepa-python/src/gepa/adapters/langchain_adapter/langchain_adapter.py +261 -0
- package/vendor/gepa-python/src/gepa/adapters/mcp_adapter/__init__.py +37 -0
- package/vendor/gepa-python/src/gepa/adapters/mcp_adapter/mcp_adapter.py +693 -0
- package/vendor/gepa-python/src/gepa/adapters/mcp_adapter/mcp_client.py +364 -0
- package/vendor/gepa-python/src/gepa/adapters/optimize_anything_adapter/optimize_anything_adapter.py +879 -0
- package/vendor/gepa-python/src/gepa/adapters/terminal_bench_adapter/__init__.py +0 -0
- package/vendor/gepa-python/src/gepa/adapters/terminal_bench_adapter/terminal_bench_adapter.py +217 -0
- package/vendor/gepa-python/src/gepa/api.py +468 -0
- package/vendor/gepa-python/src/gepa/core/__init__.py +0 -0
- package/vendor/gepa-python/src/gepa/core/adapter.py +227 -0
- package/vendor/gepa-python/src/gepa/core/callbacks.py +551 -0
- package/vendor/gepa-python/src/gepa/core/data_loader.py +74 -0
- package/vendor/gepa-python/src/gepa/core/engine.py +1025 -0
- package/vendor/gepa-python/src/gepa/core/result.py +271 -0
- package/vendor/gepa-python/src/gepa/core/state.py +706 -0
- package/vendor/gepa-python/src/gepa/examples/__init__.py +0 -0
- package/vendor/gepa-python/src/gepa/examples/aime.py +24 -0
- package/vendor/gepa-python/src/gepa/examples/anymaths-bench/eval_default.py +111 -0
- package/vendor/gepa-python/src/gepa/examples/anymaths-bench/train_anymaths.py +177 -0
- package/vendor/gepa-python/src/gepa/examples/mcp_adapter/__init__.py +4 -0
- package/vendor/gepa-python/src/gepa/examples/mcp_adapter/mcp_optimization_example.py +456 -0
- package/vendor/gepa-python/src/gepa/examples/rag_adapter/__init__.py +9 -0
- package/vendor/gepa-python/src/gepa/examples/rag_adapter/rag_optimization.py +824 -0
- package/vendor/gepa-python/src/gepa/examples/terminal-bench/train_terminus.py +161 -0
- package/vendor/gepa-python/src/gepa/gepa_utils.py +117 -0
- package/vendor/gepa-python/src/gepa/gskill/__init__.py +1 -0
- package/vendor/gepa-python/src/gepa/gskill/gskill/__init__.py +0 -0
- package/vendor/gepa-python/src/gepa/gskill/gskill/cost_tracker.py +194 -0
- package/vendor/gepa-python/src/gepa/gskill/gskill/evaluate/__init__.py +0 -0
- package/vendor/gepa-python/src/gepa/gskill/gskill/evaluate/claude_code.py +1117 -0
- package/vendor/gepa-python/src/gepa/gskill/gskill/evaluate/claude_code_skills.py +613 -0
- package/vendor/gepa-python/src/gepa/gskill/gskill/evaluate/mini_swe_agent.py +440 -0
- package/vendor/gepa-python/src/gepa/gskill/gskill/experiment_logger.py +367 -0
- package/vendor/gepa-python/src/gepa/gskill/gskill/swe_fitness_fn.py +209 -0
- package/vendor/gepa-python/src/gepa/gskill/gskill/swe_harness.py +352 -0
- package/vendor/gepa-python/src/gepa/gskill/gskill/train_optimize_anything.py +830 -0
- package/vendor/gepa-python/src/gepa/image.py +104 -0
- package/vendor/gepa-python/src/gepa/lm.py +261 -0
- package/vendor/gepa-python/src/gepa/logging/__init__.py +0 -0
- package/vendor/gepa-python/src/gepa/logging/experiment_tracker.py +457 -0
- package/vendor/gepa-python/src/gepa/logging/logger.py +75 -0
- package/vendor/gepa-python/src/gepa/logging/utils.py +130 -0
- package/vendor/gepa-python/src/gepa/optimize_anything.py +1701 -0
- package/vendor/gepa-python/src/gepa/proposer/__init__.py +0 -0
- package/vendor/gepa-python/src/gepa/proposer/base.py +53 -0
- package/vendor/gepa-python/src/gepa/proposer/merge.py +403 -0
- package/vendor/gepa-python/src/gepa/proposer/reflective_mutation/__init__.py +0 -0
- package/vendor/gepa-python/src/gepa/proposer/reflective_mutation/base.py +64 -0
- package/vendor/gepa-python/src/gepa/proposer/reflective_mutation/reflection_lm.py +178 -0
- package/vendor/gepa-python/src/gepa/proposer/reflective_mutation/reflective_mutation.py +641 -0
- package/vendor/gepa-python/src/gepa/py.typed +0 -0
- package/vendor/gepa-python/src/gepa/strategies/__init__.py +0 -0
- package/vendor/gepa-python/src/gepa/strategies/acceptance.py +66 -0
- package/vendor/gepa-python/src/gepa/strategies/batch_sampler.py +103 -0
- package/vendor/gepa-python/src/gepa/strategies/candidate_selector.py +82 -0
- package/vendor/gepa-python/src/gepa/strategies/component_selector.py +36 -0
- package/vendor/gepa-python/src/gepa/strategies/eval_policy.py +64 -0
- package/vendor/gepa-python/src/gepa/strategies/instruction_proposal.py +153 -0
- package/vendor/gepa-python/src/gepa/strategies/proposal_sampling.py +128 -0
- package/vendor/gepa-python/src/gepa/strategies/proposal_selection.py +84 -0
- package/vendor/gepa-python/src/gepa/utils/__init__.py +63 -0
- package/vendor/gepa-python/src/gepa/utils/code_execution.py +626 -0
- package/vendor/gepa-python/src/gepa/utils/stdio_capture.py +145 -0
- package/vendor/gepa-python/src/gepa/utils/stop_condition.py +230 -0
- package/vendor/gepa-python/src/gepa/visualization.py +359 -0
- package/vendor/orizu-gepa/pyproject.toml +18 -0
- package/vendor/orizu-gepa/src/orizu_gepa_connector/__init__.py +9 -0
- package/vendor/orizu-gepa/src/orizu_gepa_connector/__main__.py +5 -0
- package/vendor/orizu-gepa/src/orizu_gepa_connector/adapter.py +138 -0
- package/vendor/orizu-gepa/src/orizu_gepa_connector/callbacks.py +666 -0
- package/vendor/orizu-gepa/src/orizu_gepa_connector/cli.py +7 -0
- package/vendor/orizu-gepa/src/orizu_gepa_connector/engine.py +269 -0
- package/vendor/orizu-gepa/src/orizu_gepa_connector/instruction_set_loader.py +52 -0
- package/vendor/orizu-gepa/src/orizu_gepa_connector/preflight.py +64 -0
- package/vendor/orizu-gepa/src/orizu_gepa_connector/reflection.py +186 -0
- package/vendor/orizu-gepa/src/orizu_gepa_connector/runtime.py +721 -0
- package/vendor/orizu-gepa/src/orizu_gepa_connector/skilled_proposer_bridge.py +381 -0
- package/vendor/orizu-gepa/src/orizu_gepa_connector/stop_conditions.py +55 -0
- package/vendor/orizu-gepa/src/orizu_gepa_connector/translator.py +203 -0
- package/vendor/orizu-gepa-python/pyproject.toml +1 -1
- package/vendor/orizu-gepa-python/src/orizu_gepa/cli.py +1 -0
- package/vendor/orizu-gepa-python/src/orizu_gepa/client.py +52 -7
- package/vendor/orizu-gepa-python/src/orizu_gepa/local_log.py +52 -0
- package/vendor/orizu-gepa-python/src/orizu_gepa/optimizer.py +10 -5
- package/vendor/orizu-gepa-python/src/orizu_gepa/reflection.py +323 -68
- package/vendor/orizu-gepa-python/src/orizu_gepa/runner.py +207 -13
- package/vendor/skills/orizu-cli/SKILL.md +3 -1
- package/vendor/skills/orizu-cli/references/cli-reference.md +85 -1
- package/vendor/skills/orizu-cli/references/migrate-existing-gepa-setup.md +303 -0
- package/vendor/skills/orizu-cli/references/optimization-reports.md +1 -1
- package/vendor/skills/orizu-cli/references/optimization-with-gepa.md +26 -1
- package/vendor/skills/orizu-cli/references/prompt-control-plane.md +113 -10
|
@@ -0,0 +1,613 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Evaluate testset with Claude Code using proper Claude Code Skills.
|
|
3
|
+
|
|
4
|
+
This is a variant of evaluate_claude_code.py that installs skills as proper
|
|
5
|
+
Claude Code skills (.claude/skills/<repo>/SKILL.md with YAML frontmatter)
|
|
6
|
+
instead of plain CLAUDE.md files.
|
|
7
|
+
|
|
8
|
+
See: https://code.claude.com/docs/en/skills
|
|
9
|
+
|
|
10
|
+
Usage is identical to evaluate_claude_code.py:
|
|
11
|
+
python -m src.evaluate.claude_code_skills --config gepa_results/logs/run_xxx/config.json --use-skills
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import argparse
|
|
15
|
+
import json
|
|
16
|
+
import os
|
|
17
|
+
import sys
|
|
18
|
+
import uuid
|
|
19
|
+
from concurrent.futures import ThreadPoolExecutor, as_completed
|
|
20
|
+
from datetime import datetime
|
|
21
|
+
from pathlib import Path
|
|
22
|
+
from typing import Any
|
|
23
|
+
|
|
24
|
+
import docker
|
|
25
|
+
|
|
26
|
+
# Import all shared utilities from the original evaluate_claude_code module.
|
|
27
|
+
# This avoids duplicating data loading, image management, verification, etc.
|
|
28
|
+
from gskill.evaluate.claude_code import (
|
|
29
|
+
# Result types
|
|
30
|
+
ClaudeCodeResult,
|
|
31
|
+
ensure_claude_code_image,
|
|
32
|
+
# Docker image management
|
|
33
|
+
get_base_image_name,
|
|
34
|
+
load_test_ids,
|
|
35
|
+
load_testset_by_ids,
|
|
36
|
+
load_testset_from_config,
|
|
37
|
+
save_test_ids,
|
|
38
|
+
# Verification
|
|
39
|
+
verify_patch_with_harness,
|
|
40
|
+
)
|
|
41
|
+
from gskill.evaluate.claude_code import (
|
|
42
|
+
# Original Claude Code runner (imported as private; we wrap it)
|
|
43
|
+
run_claude_code_in_container as _run_claude_code_in_container,
|
|
44
|
+
)
|
|
45
|
+
from swebench.harness.constants import (
|
|
46
|
+
DOCKER_USER,
|
|
47
|
+
DOCKER_WORKDIR,
|
|
48
|
+
KEY_INSTANCE_ID,
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
# ============================================================================
|
|
52
|
+
# Skill Installation (the key difference from evaluate_claude_code.py)
|
|
53
|
+
# ============================================================================
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def format_skill_md(skills_content: str, repo_name: str) -> str:
|
|
57
|
+
"""
|
|
58
|
+
Wrap raw skills text with proper SKILL.md YAML frontmatter.
|
|
59
|
+
|
|
60
|
+
The frontmatter follows the Claude Code skill spec:
|
|
61
|
+
https://code.claude.com/docs/en/skills
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
skills_content: Raw skills text (e.g. contents of best_skills.txt)
|
|
65
|
+
repo_name: Repository name (e.g. "blevesearch__bleve")
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
Complete SKILL.md content with frontmatter
|
|
69
|
+
"""
|
|
70
|
+
# Clean repo name for the `name` field (lowercase, hyphens only)
|
|
71
|
+
skill_name = repo_name.replace("__", "-").replace("_", "-").lower()
|
|
72
|
+
|
|
73
|
+
# Build an informative description so Claude knows when to apply the skill
|
|
74
|
+
human_repo = repo_name.replace("__", "/").replace("_", "-")
|
|
75
|
+
description = (
|
|
76
|
+
f"Expert bug-fixing skills optimized for the {human_repo} repository. "
|
|
77
|
+
f"Contains repo-specific patterns, diagnostic strategies, and "
|
|
78
|
+
f"step-by-step workflows for efficiently finding and resolving bugs "
|
|
79
|
+
f"in this codebase. Use when debugging issues, fixing failing tests, "
|
|
80
|
+
f"or resolving reported bugs."
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
return f"---\nname: {skill_name}-bugfix\ndescription: {description}\n---\n\n{skills_content}"
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def install_skill_in_container(
|
|
87
|
+
container,
|
|
88
|
+
skills_content: str,
|
|
89
|
+
repo_name: str,
|
|
90
|
+
) -> None:
|
|
91
|
+
"""
|
|
92
|
+
Install skills as a proper Claude Code skill inside the container.
|
|
93
|
+
|
|
94
|
+
Creates:
|
|
95
|
+
<workdir>/.claude/skills/<repo_name>/SKILL.md
|
|
96
|
+
|
|
97
|
+
with YAML frontmatter so Claude Code discovers and loads it automatically.
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
container: Running Docker container
|
|
101
|
+
skills_content: Raw skills text
|
|
102
|
+
repo_name: Repository name used as the skill directory name
|
|
103
|
+
"""
|
|
104
|
+
from swebench.harness.docker_utils import copy_to_container
|
|
105
|
+
|
|
106
|
+
skill_md = format_skill_md(skills_content, repo_name)
|
|
107
|
+
skill_dir = f"{DOCKER_WORKDIR}/.claude/skills/{repo_name}"
|
|
108
|
+
|
|
109
|
+
# Create the skill directory structure
|
|
110
|
+
container.exec_run(f"mkdir -p {skill_dir}", user="root")
|
|
111
|
+
|
|
112
|
+
# Write SKILL.md into the container
|
|
113
|
+
skill_file_local = Path(f"/tmp/skill_{uuid.uuid4().hex[:8]}.md")
|
|
114
|
+
skill_file_container = Path(f"{skill_dir}/SKILL.md")
|
|
115
|
+
try:
|
|
116
|
+
skill_file_local.write_text(skill_md)
|
|
117
|
+
copy_to_container(container, skill_file_local, skill_file_container)
|
|
118
|
+
container.exec_run("sync", user="root")
|
|
119
|
+
# Make the whole .claude tree readable
|
|
120
|
+
container.exec_run(f"chmod -R 755 {DOCKER_WORKDIR}/.claude", user="root")
|
|
121
|
+
print(f" Installed skill at .claude/skills/{repo_name}/SKILL.md ({len(skill_md)} chars)")
|
|
122
|
+
finally:
|
|
123
|
+
skill_file_local.unlink(missing_ok=True)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
# ============================================================================
|
|
127
|
+
# Wrapped Claude Code Runner
|
|
128
|
+
# ============================================================================
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def run_claude_code_in_container(
|
|
132
|
+
task: dict,
|
|
133
|
+
container,
|
|
134
|
+
timeout: int = 1800,
|
|
135
|
+
poll_interval: int = 10,
|
|
136
|
+
skills: str | None = None,
|
|
137
|
+
repo_name: str | None = None,
|
|
138
|
+
) -> ClaudeCodeResult:
|
|
139
|
+
"""
|
|
140
|
+
Run Claude Code with skills installed as a proper SKILL.md.
|
|
141
|
+
|
|
142
|
+
This wraps the original run_claude_code_in_container: if skills are
|
|
143
|
+
provided, they are first installed as .claude/skills/<repo>/SKILL.md,
|
|
144
|
+
then the original runner is called with skills=None (so it skips
|
|
145
|
+
CLAUDE.md creation).
|
|
146
|
+
|
|
147
|
+
Args:
|
|
148
|
+
task: Task instance dict
|
|
149
|
+
container: Running Docker container
|
|
150
|
+
timeout: Maximum time to wait (seconds)
|
|
151
|
+
poll_interval: How often to check for completion (seconds)
|
|
152
|
+
skills: Optional raw skills content
|
|
153
|
+
repo_name: Repository name for the skill directory
|
|
154
|
+
|
|
155
|
+
Returns:
|
|
156
|
+
ClaudeCodeResult with patch and status
|
|
157
|
+
"""
|
|
158
|
+
if skills:
|
|
159
|
+
effective_repo = repo_name or task.get("repo", "").split("/")[-1] or "default"
|
|
160
|
+
install_skill_in_container(container, skills, effective_repo)
|
|
161
|
+
|
|
162
|
+
# Delegate to original runner with skills=None (skill already installed)
|
|
163
|
+
return _run_claude_code_in_container(task, container, timeout=timeout, poll_interval=poll_interval, skills=None)
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
# ============================================================================
|
|
167
|
+
# Evaluation Functions (thin overrides that thread repo_name through)
|
|
168
|
+
# ============================================================================
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def evaluate_single_task(
|
|
172
|
+
task: dict,
|
|
173
|
+
claude_image: str,
|
|
174
|
+
timeout: int = 1800,
|
|
175
|
+
verify_timeout: int = 300,
|
|
176
|
+
skills: str | None = None,
|
|
177
|
+
repo_name: str | None = None,
|
|
178
|
+
) -> dict[str, Any]:
|
|
179
|
+
"""
|
|
180
|
+
Evaluate a single task with Claude Code (skill-aware version).
|
|
181
|
+
|
|
182
|
+
Identical to evaluate_claude_code.evaluate_single_task except that
|
|
183
|
+
skills are installed as .claude/skills/<repo>/SKILL.md.
|
|
184
|
+
"""
|
|
185
|
+
instance_id = task[KEY_INSTANCE_ID]
|
|
186
|
+
container = None
|
|
187
|
+
|
|
188
|
+
try:
|
|
189
|
+
client = docker.from_env()
|
|
190
|
+
client.ping()
|
|
191
|
+
except Exception as e:
|
|
192
|
+
return {
|
|
193
|
+
"instance_id": instance_id,
|
|
194
|
+
"claude_success": False,
|
|
195
|
+
"test_passed": False,
|
|
196
|
+
"patch": "",
|
|
197
|
+
"claude_output": "",
|
|
198
|
+
"test_output": "",
|
|
199
|
+
"duration_seconds": 0,
|
|
200
|
+
"error": f"Docker connection failed: {e!s}",
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
try:
|
|
204
|
+
container_name = f"claude-code-{instance_id}.{uuid.uuid4().hex[:8]}"
|
|
205
|
+
container = client.containers.create(
|
|
206
|
+
image=claude_image,
|
|
207
|
+
name=container_name,
|
|
208
|
+
user=DOCKER_USER,
|
|
209
|
+
detach=True,
|
|
210
|
+
command="tail -f /dev/null",
|
|
211
|
+
platform="linux/x86_64",
|
|
212
|
+
mem_limit="10g",
|
|
213
|
+
)
|
|
214
|
+
container.start()
|
|
215
|
+
|
|
216
|
+
val = container.exec_run(
|
|
217
|
+
f"git checkout {instance_id}",
|
|
218
|
+
workdir=DOCKER_WORKDIR,
|
|
219
|
+
user=DOCKER_USER,
|
|
220
|
+
)
|
|
221
|
+
if val.exit_code != 0:
|
|
222
|
+
raise RuntimeError(f"Failed to checkout {instance_id}: {val.output.decode()}")
|
|
223
|
+
|
|
224
|
+
# Uses our skill-aware run_claude_code_in_container
|
|
225
|
+
result = run_claude_code_in_container(task, container, timeout=timeout, skills=skills, repo_name=repo_name)
|
|
226
|
+
|
|
227
|
+
passed = False
|
|
228
|
+
test_output = ""
|
|
229
|
+
if result.patch.strip():
|
|
230
|
+
passed, test_output = verify_patch_with_harness(task, result.patch, timeout=verify_timeout)
|
|
231
|
+
else:
|
|
232
|
+
test_output = "No patch generated"
|
|
233
|
+
|
|
234
|
+
return {
|
|
235
|
+
"instance_id": instance_id,
|
|
236
|
+
"claude_success": result.success,
|
|
237
|
+
"test_passed": passed,
|
|
238
|
+
"patch": result.patch,
|
|
239
|
+
"claude_output": result.output[:5000],
|
|
240
|
+
"test_output": test_output[:5000],
|
|
241
|
+
"duration_seconds": result.duration_seconds,
|
|
242
|
+
"error": result.error,
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
except Exception as e:
|
|
246
|
+
import traceback
|
|
247
|
+
|
|
248
|
+
return {
|
|
249
|
+
"instance_id": instance_id,
|
|
250
|
+
"claude_success": False,
|
|
251
|
+
"test_passed": False,
|
|
252
|
+
"patch": "",
|
|
253
|
+
"claude_output": "",
|
|
254
|
+
"test_output": "",
|
|
255
|
+
"duration_seconds": 0,
|
|
256
|
+
"error": f"{e!s}\n{traceback.format_exc()}",
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
finally:
|
|
260
|
+
if container:
|
|
261
|
+
try:
|
|
262
|
+
container.stop()
|
|
263
|
+
container.remove()
|
|
264
|
+
except Exception:
|
|
265
|
+
pass
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
def evaluate_testset(
|
|
269
|
+
test_data: list[dict],
|
|
270
|
+
output_dir: Path,
|
|
271
|
+
n_workers: int = 4,
|
|
272
|
+
timeout: int = 1800,
|
|
273
|
+
verify_timeout: int = 300,
|
|
274
|
+
skills: str | None = None,
|
|
275
|
+
run_config: dict[str, Any] | None = None,
|
|
276
|
+
repo_name: str | None = None,
|
|
277
|
+
) -> dict[str, Any]:
|
|
278
|
+
"""
|
|
279
|
+
Evaluate all tasks in testset (skill-aware version).
|
|
280
|
+
|
|
281
|
+
Identical to evaluate_claude_code.evaluate_testset except that skills
|
|
282
|
+
are installed as proper Claude Code skills.
|
|
283
|
+
"""
|
|
284
|
+
output_dir.mkdir(parents=True, exist_ok=True)
|
|
285
|
+
|
|
286
|
+
# Ensure Claude Code images exist for all unique base images
|
|
287
|
+
print("\n" + "=" * 70)
|
|
288
|
+
print("Preparing Claude Code Docker images...")
|
|
289
|
+
print("=" * 70)
|
|
290
|
+
|
|
291
|
+
image_cache: dict[str, str] = {}
|
|
292
|
+
for task in test_data:
|
|
293
|
+
base_image = get_base_image_name(task)
|
|
294
|
+
if base_image not in image_cache:
|
|
295
|
+
claude_image = ensure_claude_code_image(task)
|
|
296
|
+
image_cache[base_image] = claude_image
|
|
297
|
+
|
|
298
|
+
print(f"Prepared {len(image_cache)} Claude Code image(s)")
|
|
299
|
+
|
|
300
|
+
# Evaluate tasks
|
|
301
|
+
print("\n" + "=" * 70)
|
|
302
|
+
print(f"Evaluating {len(test_data)} tasks with Claude Code...")
|
|
303
|
+
print(f"Workers: {n_workers}, Timeout: {timeout}s")
|
|
304
|
+
if skills:
|
|
305
|
+
print(f"Skills: installed as .claude/skills/{repo_name or '<auto>'}/SKILL.md")
|
|
306
|
+
print("=" * 70 + "\n")
|
|
307
|
+
|
|
308
|
+
results: list[dict[str, Any]] = []
|
|
309
|
+
|
|
310
|
+
def process_task(task):
|
|
311
|
+
base_image = get_base_image_name(task)
|
|
312
|
+
claude_image = image_cache[base_image]
|
|
313
|
+
return evaluate_single_task(
|
|
314
|
+
task,
|
|
315
|
+
claude_image,
|
|
316
|
+
timeout,
|
|
317
|
+
verify_timeout,
|
|
318
|
+
skills=skills,
|
|
319
|
+
repo_name=repo_name,
|
|
320
|
+
)
|
|
321
|
+
|
|
322
|
+
if n_workers <= 1:
|
|
323
|
+
for i, task in enumerate(test_data):
|
|
324
|
+
print(f"[{i + 1}/{len(test_data)}] {task[KEY_INSTANCE_ID][:50]}...")
|
|
325
|
+
result = process_task(task)
|
|
326
|
+
results.append(result)
|
|
327
|
+
|
|
328
|
+
status = "✓ PASS" if result["test_passed"] else "✗ FAIL"
|
|
329
|
+
print(f" {status} ({result['duration_seconds']:.1f}s)")
|
|
330
|
+
|
|
331
|
+
with open(output_dir / "results.jsonl", "a") as f:
|
|
332
|
+
f.write(json.dumps(result) + "\n")
|
|
333
|
+
else:
|
|
334
|
+
with ThreadPoolExecutor(max_workers=n_workers) as executor:
|
|
335
|
+
futures = {executor.submit(process_task, task): task for task in test_data}
|
|
336
|
+
|
|
337
|
+
for i, future in enumerate(as_completed(futures)):
|
|
338
|
+
task = futures[future]
|
|
339
|
+
try:
|
|
340
|
+
result = future.result()
|
|
341
|
+
except Exception as e:
|
|
342
|
+
result = {
|
|
343
|
+
"instance_id": task[KEY_INSTANCE_ID],
|
|
344
|
+
"claude_success": False,
|
|
345
|
+
"test_passed": False,
|
|
346
|
+
"error": str(e),
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
results.append(result)
|
|
350
|
+
|
|
351
|
+
status = "✓ PASS" if result.get("test_passed") else "✗ FAIL"
|
|
352
|
+
print(f"[{i + 1}/{len(test_data)}] {result['instance_id'][:50]}: {status}")
|
|
353
|
+
|
|
354
|
+
with open(output_dir / "results.jsonl", "a") as f:
|
|
355
|
+
f.write(json.dumps(result) + "\n")
|
|
356
|
+
|
|
357
|
+
# Compute summary
|
|
358
|
+
passed = sum(1 for r in results if r.get("test_passed"))
|
|
359
|
+
claude_success = sum(1 for r in results if r.get("claude_success"))
|
|
360
|
+
total = len(results)
|
|
361
|
+
|
|
362
|
+
summary = {
|
|
363
|
+
"run_config": run_config or {},
|
|
364
|
+
"total": total,
|
|
365
|
+
"passed": passed,
|
|
366
|
+
"pass_rate": passed / total if total > 0 else 0,
|
|
367
|
+
"claude_generated_patches": claude_success,
|
|
368
|
+
"claude_patch_rate": claude_success / total if total > 0 else 0,
|
|
369
|
+
"avg_duration": (sum(r.get("duration_seconds", 0) for r in results) / total if total > 0 else 0),
|
|
370
|
+
"results": results,
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
with open(output_dir / "summary.json", "w") as f:
|
|
374
|
+
json.dump(summary, f, indent=2)
|
|
375
|
+
|
|
376
|
+
print("\n" + "=" * 70)
|
|
377
|
+
print("EVALUATION COMPLETE")
|
|
378
|
+
print("=" * 70)
|
|
379
|
+
print(f"Total tasks: {total}")
|
|
380
|
+
print(f"Claude generated patches: {claude_success}/{total} ({summary['claude_patch_rate']:.1%})")
|
|
381
|
+
print(f"Tests passed: {passed}/{total} ({summary['pass_rate']:.1%})")
|
|
382
|
+
print(f"Average duration: {summary['avg_duration']:.1f}s")
|
|
383
|
+
print(f"Results saved to: {output_dir}")
|
|
384
|
+
|
|
385
|
+
return summary
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
# ============================================================================
|
|
389
|
+
# CLI (same arguments as evaluate_claude_code.py)
|
|
390
|
+
# ============================================================================
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
def main():
|
|
394
|
+
parser = argparse.ArgumentParser(
|
|
395
|
+
description="Evaluate testset with Claude Code (proper Skills variant)",
|
|
396
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
397
|
+
epilog="""
|
|
398
|
+
This script is identical to evaluate_claude_code.py except that --use-skills
|
|
399
|
+
installs skills as .claude/skills/<repo>/SKILL.md (with YAML frontmatter)
|
|
400
|
+
instead of a plain CLAUDE.md file.
|
|
401
|
+
|
|
402
|
+
See: https://code.claude.com/docs/en/skills
|
|
403
|
+
|
|
404
|
+
Examples:
|
|
405
|
+
# Evaluate with proper Claude Code skills
|
|
406
|
+
python -m src.evaluate.claude_code_skills --config gepa_results/logs/run_xxx/config.json --use-skills
|
|
407
|
+
|
|
408
|
+
# Evaluate without skills (identical to evaluate_claude_code.py)
|
|
409
|
+
python -m src.evaluate.claude_code_skills --config gepa_results/logs/run_xxx/config.json
|
|
410
|
+
""",
|
|
411
|
+
)
|
|
412
|
+
|
|
413
|
+
parser.add_argument(
|
|
414
|
+
"--config",
|
|
415
|
+
type=str,
|
|
416
|
+
required=True,
|
|
417
|
+
help="Path to config.json from a GEPA run",
|
|
418
|
+
)
|
|
419
|
+
parser.add_argument(
|
|
420
|
+
"--extract-ids",
|
|
421
|
+
type=str,
|
|
422
|
+
default=None,
|
|
423
|
+
help="Extract test IDs to this file and exit",
|
|
424
|
+
)
|
|
425
|
+
parser.add_argument(
|
|
426
|
+
"--output",
|
|
427
|
+
type=str,
|
|
428
|
+
default=None,
|
|
429
|
+
help="Output directory for results (default: gepa_results/claude_code/<run_id>)",
|
|
430
|
+
)
|
|
431
|
+
parser.add_argument(
|
|
432
|
+
"--workers",
|
|
433
|
+
type=int,
|
|
434
|
+
default=4,
|
|
435
|
+
help="Number of parallel workers (default: 4)",
|
|
436
|
+
)
|
|
437
|
+
parser.add_argument(
|
|
438
|
+
"--timeout",
|
|
439
|
+
type=int,
|
|
440
|
+
default=1800,
|
|
441
|
+
help="Timeout for Claude Code in seconds (default: 1800)",
|
|
442
|
+
)
|
|
443
|
+
parser.add_argument(
|
|
444
|
+
"--verify-timeout",
|
|
445
|
+
type=int,
|
|
446
|
+
default=300,
|
|
447
|
+
help="Timeout for test verification in seconds (default: 300)",
|
|
448
|
+
)
|
|
449
|
+
parser.add_argument(
|
|
450
|
+
"--ids-file",
|
|
451
|
+
type=str,
|
|
452
|
+
default=None,
|
|
453
|
+
help="Load test IDs from file instead of reconstructing from config",
|
|
454
|
+
)
|
|
455
|
+
parser.add_argument(
|
|
456
|
+
"--dry-run",
|
|
457
|
+
action="store_true",
|
|
458
|
+
help="Only prepare images and show what would be run, don't execute",
|
|
459
|
+
)
|
|
460
|
+
parser.add_argument(
|
|
461
|
+
"--limit",
|
|
462
|
+
type=int,
|
|
463
|
+
default=None,
|
|
464
|
+
help="Limit number of tasks to evaluate (for testing)",
|
|
465
|
+
)
|
|
466
|
+
parser.add_argument(
|
|
467
|
+
"--model",
|
|
468
|
+
type=str,
|
|
469
|
+
default="sonnet",
|
|
470
|
+
choices=["sonnet", "opus", "haiku", "default"],
|
|
471
|
+
help="Claude Code model to use (default: sonnet = Claude Sonnet 4.5)",
|
|
472
|
+
)
|
|
473
|
+
parser.add_argument(
|
|
474
|
+
"--use-skills",
|
|
475
|
+
action="store_true",
|
|
476
|
+
help="Load best_skills.txt and install as .claude/skills/<repo>/SKILL.md in the repo",
|
|
477
|
+
)
|
|
478
|
+
|
|
479
|
+
args = parser.parse_args()
|
|
480
|
+
|
|
481
|
+
# Verify Docker connection
|
|
482
|
+
try:
|
|
483
|
+
client = docker.from_env()
|
|
484
|
+
client.ping()
|
|
485
|
+
print(f"Docker connection OK (DOCKER_HOST={os.environ.get('DOCKER_HOST', 'default')})")
|
|
486
|
+
except Exception as e:
|
|
487
|
+
print(f"ERROR: Cannot connect to Docker: {e}")
|
|
488
|
+
print("Please ensure Docker is running:")
|
|
489
|
+
print(" Rootless: systemctl --user start docker")
|
|
490
|
+
print(" Standard: sudo systemctl start docker")
|
|
491
|
+
sys.exit(1)
|
|
492
|
+
|
|
493
|
+
# Load config
|
|
494
|
+
with open(args.config) as f:
|
|
495
|
+
config = json.load(f)
|
|
496
|
+
|
|
497
|
+
run_id = config.get("run_id", Path(args.config).parent.name)
|
|
498
|
+
repo = config["repo"]
|
|
499
|
+
|
|
500
|
+
# Set model environment variable for Claude Code
|
|
501
|
+
os.environ["CLAUDE_CODE_MODEL"] = args.model
|
|
502
|
+
print(f"Using Claude Code model: {args.model}")
|
|
503
|
+
|
|
504
|
+
# Load testset
|
|
505
|
+
if args.ids_file:
|
|
506
|
+
print(f"Loading test IDs from {args.ids_file}")
|
|
507
|
+
test_ids = load_test_ids(args.ids_file)
|
|
508
|
+
test_data = load_testset_by_ids(test_ids, repo)
|
|
509
|
+
print(f"Loaded {len(test_data)} tasks from IDs file")
|
|
510
|
+
else:
|
|
511
|
+
test_data, _ = load_testset_from_config(args.config)
|
|
512
|
+
|
|
513
|
+
# Extract IDs mode
|
|
514
|
+
if args.extract_ids:
|
|
515
|
+
save_test_ids(test_data, args.extract_ids)
|
|
516
|
+
return
|
|
517
|
+
|
|
518
|
+
# Set output directory
|
|
519
|
+
if args.output:
|
|
520
|
+
output_dir = Path(args.output)
|
|
521
|
+
else:
|
|
522
|
+
output_dir = Path("gepa_results/claude_code") / f"{run_id}_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
|
|
523
|
+
|
|
524
|
+
# Apply limit
|
|
525
|
+
if args.limit and args.limit < len(test_data):
|
|
526
|
+
print(f"Limiting to first {args.limit} tasks (out of {len(test_data)})")
|
|
527
|
+
test_data = test_data[: args.limit]
|
|
528
|
+
|
|
529
|
+
# Save test IDs for reference
|
|
530
|
+
output_dir.mkdir(parents=True, exist_ok=True)
|
|
531
|
+
save_test_ids(test_data, str(output_dir / "test_ids.txt"))
|
|
532
|
+
|
|
533
|
+
# Save config copy
|
|
534
|
+
with open(output_dir / "source_config.json", "w") as f:
|
|
535
|
+
json.dump(config, f, indent=2)
|
|
536
|
+
|
|
537
|
+
# Load skills from config directory if requested
|
|
538
|
+
config_dir = Path(args.config).parent
|
|
539
|
+
skills = None
|
|
540
|
+
repo_name = repo # e.g. "blevesearch__bleve"
|
|
541
|
+
if args.use_skills:
|
|
542
|
+
skills_path = config_dir / "prompts" / "best_skills.txt"
|
|
543
|
+
if skills_path.exists():
|
|
544
|
+
skills = skills_path.read_text()
|
|
545
|
+
print(f"Loaded skills from {skills_path} ({len(skills)} chars)")
|
|
546
|
+
print(f"Will install as .claude/skills/{repo_name}/SKILL.md (proper Claude Code skill)")
|
|
547
|
+
# Save copy of raw skills
|
|
548
|
+
with open(output_dir / "skills_raw.txt", "w") as f:
|
|
549
|
+
f.write(skills)
|
|
550
|
+
# Also save the formatted SKILL.md for reference
|
|
551
|
+
with open(output_dir / "SKILL.md", "w") as f:
|
|
552
|
+
f.write(format_skill_md(skills, repo_name))
|
|
553
|
+
else:
|
|
554
|
+
print(f"WARNING: Skills file not found: {skills_path}")
|
|
555
|
+
|
|
556
|
+
# Dry run mode
|
|
557
|
+
if args.dry_run:
|
|
558
|
+
print("\n" + "=" * 70)
|
|
559
|
+
print("DRY RUN - Preparing images only")
|
|
560
|
+
print("=" * 70)
|
|
561
|
+
|
|
562
|
+
image_cache = {}
|
|
563
|
+
for task in test_data:
|
|
564
|
+
base_image = get_base_image_name(task)
|
|
565
|
+
if base_image not in image_cache:
|
|
566
|
+
claude_image = ensure_claude_code_image(task)
|
|
567
|
+
image_cache[base_image] = claude_image
|
|
568
|
+
|
|
569
|
+
print(f"\nPrepared {len(image_cache)} Claude Code image(s)")
|
|
570
|
+
print(f"Would evaluate {len(test_data)} tasks")
|
|
571
|
+
if skills:
|
|
572
|
+
print(f"Skills mode: .claude/skills/{repo_name}/SKILL.md")
|
|
573
|
+
print(f"Test IDs saved to: {output_dir / 'test_ids.txt'}")
|
|
574
|
+
|
|
575
|
+
return {
|
|
576
|
+
"dry_run": True,
|
|
577
|
+
"num_tasks": len(test_data),
|
|
578
|
+
"images": list(image_cache.values()),
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
# Build run configuration metadata
|
|
582
|
+
run_config = {
|
|
583
|
+
"model": args.model,
|
|
584
|
+
"use_skills": args.use_skills,
|
|
585
|
+
"skills_format": "claude_code_skill" if args.use_skills else None,
|
|
586
|
+
"skills_path": (str(config_dir / "prompts" / "best_skills.txt") if args.use_skills else None),
|
|
587
|
+
"config_path": str(Path(args.config).resolve()),
|
|
588
|
+
"source_run_id": run_id,
|
|
589
|
+
"repo": repo,
|
|
590
|
+
"workers": args.workers,
|
|
591
|
+
"timeout": args.timeout,
|
|
592
|
+
"verify_timeout": args.verify_timeout,
|
|
593
|
+
"num_tasks": len(test_data),
|
|
594
|
+
"timestamp": datetime.now().isoformat(),
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
# Run evaluation
|
|
598
|
+
summary = evaluate_testset(
|
|
599
|
+
test_data=test_data,
|
|
600
|
+
output_dir=output_dir,
|
|
601
|
+
n_workers=args.workers,
|
|
602
|
+
timeout=args.timeout,
|
|
603
|
+
verify_timeout=args.verify_timeout,
|
|
604
|
+
skills=skills,
|
|
605
|
+
run_config=run_config,
|
|
606
|
+
repo_name=repo_name,
|
|
607
|
+
)
|
|
608
|
+
|
|
609
|
+
return summary
|
|
610
|
+
|
|
611
|
+
|
|
612
|
+
if __name__ == "__main__":
|
|
613
|
+
main()
|