cmpnd 0.6.2__tar.gz → 0.7.0__tar.gz
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.
- {cmpnd-0.6.2 → cmpnd-0.7.0}/PKG-INFO +1 -1
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/cli/__init__.py +9 -4
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/cli/commands/optimizations.py +40 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/pyproject.toml +1 -1
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_cli/test_main.py +13 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_cli/test_optimizations.py +41 -1
- {cmpnd-0.6.2 → cmpnd-0.7.0}/uv.lock +1 -1
- {cmpnd-0.6.2 → cmpnd-0.7.0}/.gitignore +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/CLAUDE.md +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/README.md +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/__init__.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/_gepa_patch.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/_program_patch.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/_rlm_patch.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/callback.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/cli/api_client.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/cli/commands/__init__.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/cli/commands/admin.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/cli/commands/auth.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/cli/commands/datasets.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/cli/commands/deployments.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/cli/commands/evals.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/cli/commands/login.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/cli/commands/org.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/cli/commands/programs.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/cli/commands/top.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/cli/commands/traces.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/cli/credentials.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/cli/shell.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/cli/trace_render.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/cli/verbs.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/configuration.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/context.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/dataset_sync.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/datasets.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/decorators.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/deployment.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/eval_handler.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/execution.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/exporter.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/exporter_http.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/helpers.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/identity.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/ir/__init__.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/ir/decode.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/ir/encode.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/ir/hash.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/ir/program.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/ir/reflection.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/ir/types.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/ir/xxh64.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/models.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/optimization.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/optimizers/__init__.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/optimizers/gepa.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/optimizers/gepa_callback.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/optimizers/resume.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/optimizers/tracker.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/cmpnd/packaging.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/docs/2026-04-02-code-review.md +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/docs/plans/2026-04-05-train-val-dataset-capture-design.md +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/docs/plans/2026-04-05-train-val-dataset-capture.md +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/docs/sdk-instrumentation.md +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/examples/local_ollama.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/scripts/capture_review_run.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/scripts/fixtures/review_run.json.gz +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/scripts/gepa_resume_bug.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/scripts/seed_review_run.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/stubs/dspy/__init__.pyi +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/stubs/dspy/primitives/__init__.pyi +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/stubs/dspy/primitives/prediction.pyi +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/stubs/dspy/utils/__init__.pyi +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/stubs/dspy/utils/callback.pyi +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/__init__.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/_exporter_helpers.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/_identity_helpers.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/e2e/__init__.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/e2e/committee_task.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/e2e/conftest.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/e2e/data/committee_train.ndjson.gz +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/e2e/data/committee_val.ndjson.gz +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/e2e/fake_lm.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/e2e/helpers.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/e2e/test_capture_prompts.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/e2e/test_composite_module.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/e2e/test_dataset_auto_creation.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/e2e/test_deploy_execute.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/e2e/test_deploy_programs.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/e2e/test_edge_cases.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/e2e/test_example_hash.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/e2e/test_gepa_optimization.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/e2e/test_lm_accuracy.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/e2e/test_module_tracing.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/e2e/test_optimization_lineage.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/e2e/test_optimization_metric_identity.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/e2e/test_optimize_failures.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/e2e/test_optimize_loop.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/e2e/test_optimize_review_committee.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/e2e/test_optimize_server_owned_completion.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/e2e/test_parallel_export.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/e2e/test_project_attribution.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/e2e/test_react_tool_spans.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/e2e/test_save_load.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/e2e/test_trace_structure.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/e2e/test_user_attribution.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/identity_vectors/01_predict_qa.json +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/identity_vectors/02_predict_renamed_field.json +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/identity_vectors/03_chain_of_thought_qa.json +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/identity_vectors/04_predict_richer_types.json +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/identity_vectors/05_composite_two_predicts.json +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/identity_vectors/06_multichaincomparison.json +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/identity_vectors/07_program_of_thought.json +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/identity_vectors/08_opaque_module.json +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/identity_vectors/09_predict_pydantic_field.json +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/identity_vectors/10_react.json +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/identity_vectors/11_refine.json +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/identity_vectors/12_retrieve.json +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/identity_vectors/13_knn.json +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/identity_vectors/14_parallel.json +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/identity_vectors/README.md +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/integration/__init__.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/integration/conftest.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/integration/test_cli_deploy_smoketest.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/integration/test_logs_renders_traces.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/integration/test_optimizing_progress.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/integration/test_unhappy_path.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/parity/__init__.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/parity/conftest.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/parity/seed_parity.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/parity/test_auth.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/parity/test_datasets.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/parity/test_deployments.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/parity/test_evals.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/parity/test_health.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/parity/test_modules.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/parity/test_optimizations.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/parity/test_programs.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/parity/test_signatures.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/parity/test_trace_streaming.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/parity/test_traces.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/stress/__init__.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/stress/_provider.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/stress/_reliability.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/stress/mint_bedrock_token.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/stress/test_deploy_programs.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/stress/test_multi_client_stress.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/stress/test_optimize_client_committee.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/stress/test_optimize_loop.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/stress/test_optimize_loop_wasm.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/stress/test_optimize_stress.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/stress/test_real_provider_twins.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/stress/test_reliability.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/stress/test_reliability_classify.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_callback.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_cli/__init__.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_cli/conftest.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_cli/test_admin.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_cli/test_api_client.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_cli/test_auth.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_cli/test_credentials.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_cli/test_datasets.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_cli/test_deployments.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_cli/test_evals.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_cli/test_login.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_cli/test_org.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_cli/test_parity.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_cli/test_programs.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_cli/test_shell.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_cli/test_top.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_cli/test_traces.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_clustering/__init__.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_clustering/conftest.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_clustering/test_edge_cases.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_clustering/test_hash_consistency.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_clustering/test_type_conversion.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_cmp551_grouping_identity.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_configuration.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_context.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_context_propagation.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_dataset_polling.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_dataset_sync.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_datasets.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_decorators.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_deploy.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_eval.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_eval_start.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_exception_paths.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_execute.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_exporter.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_exporter_real.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_fake_lm.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_gepa_callback.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_gepa_integration.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_gepa_resume.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_identity.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_import_weight.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_integration.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_ir_encoder_properties.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_ir_golden_vectors.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_ir_roundtrip.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_models.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_optimization_progress.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_optimization_start.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_optimize.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_optimize_lift.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_optimize_terminal_failure.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_packaging.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_packaging_callable_source.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_packaging_program_source.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_program_lineage_persist.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_project_payload.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_reflector_properties.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_reflector_smoke.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_repro_reactv2_bugs.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_rlm_patch.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_schemas.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_seed_review_run.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_stats_export.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_trace_render.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_tracked_gepa.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_tracker_enrich.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_truncation.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/tests/test_xxh64.py +0 -0
- {cmpnd-0.6.2 → cmpnd-0.7.0}/todo.md +0 -0
|
@@ -99,13 +99,18 @@ def main() -> None:
|
|
|
99
99
|
if os.environ.get("CMPND_CLI_ADMIN") == "1":
|
|
100
100
|
admin.register(subparsers)
|
|
101
101
|
|
|
102
|
-
#
|
|
103
|
-
#
|
|
104
|
-
#
|
|
102
|
+
# Optimizations is productized: the program-scoped failing-examples flow is
|
|
103
|
+
# a supported power-user path, so the group is always registered — the
|
|
104
|
+
# server gates each read on optimizations:read, so a caller without scope
|
|
105
|
+
# just gets a 403, not a hidden command.
|
|
106
|
+
optimizations.register(subparsers)
|
|
107
|
+
|
|
108
|
+
# The remaining resource subcommands are dev-only until productized. Set
|
|
109
|
+
# CMPND_CLI_DEV=1 to expose programs, traces, evals, datasets, and
|
|
110
|
+
# deployments in --help.
|
|
105
111
|
if os.environ.get("CMPND_CLI_DEV") == "1":
|
|
106
112
|
programs.register(subparsers)
|
|
107
113
|
traces.register(subparsers)
|
|
108
|
-
optimizations.register(subparsers)
|
|
109
114
|
evals.register(subparsers)
|
|
110
115
|
datasets.register(subparsers)
|
|
111
116
|
deployments.register(subparsers)
|
|
@@ -33,6 +33,33 @@ def register(subparsers: _SubParsersAction[ArgumentParser]) -> None:
|
|
|
33
33
|
cands.add_argument("id", help="Optimization run ID (UUID)")
|
|
34
34
|
cands.set_defaults(func=handle_candidates)
|
|
35
35
|
|
|
36
|
+
failing = sub.add_parser(
|
|
37
|
+
"failing-examples",
|
|
38
|
+
help="Datapoints that fail across a program's optimizations",
|
|
39
|
+
)
|
|
40
|
+
failing.add_argument("--program", dest="program", required=True, help="Program name")
|
|
41
|
+
failing.add_argument(
|
|
42
|
+
"--min-failures",
|
|
43
|
+
dest="min_failures",
|
|
44
|
+
type=int,
|
|
45
|
+
default=2,
|
|
46
|
+
help="Min distinct models that must fail an example (default 2)",
|
|
47
|
+
)
|
|
48
|
+
failing.add_argument(
|
|
49
|
+
"--all",
|
|
50
|
+
dest="all_models",
|
|
51
|
+
action="store_true",
|
|
52
|
+
help="Require failure under EVERY model in each family (overrides --min-failures)",
|
|
53
|
+
)
|
|
54
|
+
failing.set_defaults(func=handle_failing_examples)
|
|
55
|
+
|
|
56
|
+
analysis = sub.add_parser(
|
|
57
|
+
"dataset-analysis",
|
|
58
|
+
help="Per-run always-fail / inconsistent example classification",
|
|
59
|
+
)
|
|
60
|
+
analysis.add_argument("id", help="Optimization run ID (op_...)")
|
|
61
|
+
analysis.set_defaults(func=handle_dataset_analysis)
|
|
62
|
+
|
|
36
63
|
|
|
37
64
|
def handle_search(client: api_client.ApiClient, args: Any) -> Any:
|
|
38
65
|
body: dict[str, Any] = {"page": args.page, "per_page": args.per_page}
|
|
@@ -58,3 +85,16 @@ def handle_iterations(client: api_client.ApiClient, args: Any) -> Any:
|
|
|
58
85
|
|
|
59
86
|
def handle_candidates(client: api_client.ApiClient, args: Any) -> Any:
|
|
60
87
|
return client.get(f"/api/v1/optimizations/{args.id}/candidates")
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def handle_failing_examples(client: api_client.ApiClient, args: Any) -> Any:
|
|
91
|
+
params: dict[str, Any] = {"program": args.program}
|
|
92
|
+
if getattr(args, "all_models", False):
|
|
93
|
+
params["all"] = "true"
|
|
94
|
+
else:
|
|
95
|
+
params["min_failures"] = args.min_failures
|
|
96
|
+
return client.get("/api/v1/optimizations/failing-examples", params=params)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def handle_dataset_analysis(client: api_client.ApiClient, args: Any) -> Any:
|
|
100
|
+
return client.get(f"/api/v1/optimizations/{args.id}/dataset-analysis")
|
|
@@ -5,7 +5,7 @@ name = "cmpnd"
|
|
|
5
5
|
# it's new) — no git tags. Bump with `uv version --bump {minor,patch}` or by
|
|
6
6
|
# hand. Runtime `cmpnd.__version__` reads installed metadata, so it tracks
|
|
7
7
|
# this automatically. See docs/plans/2026-07-02-sdk-pypi-tag-free-publish.md.
|
|
8
|
-
version = "0.
|
|
8
|
+
version = "0.7.0"
|
|
9
9
|
description = "DSPy observability and deployment SDK for cmpnd"
|
|
10
10
|
readme = "README.md"
|
|
11
11
|
requires-python = ">=3.10"
|
|
@@ -90,6 +90,19 @@ class TestDevGate:
|
|
|
90
90
|
captured = capsys.readouterr()
|
|
91
91
|
assert "(no deployments)" in captured.out
|
|
92
92
|
|
|
93
|
+
def test_optimizations_works_without_flag(self, capsys):
|
|
94
|
+
# optimizations is productized — available without CMPND_CLI_DEV.
|
|
95
|
+
env = {k: v for k, v in os.environ.items() if k != "CMPND_CLI_DEV"}
|
|
96
|
+
env["CMPND_API_KEY"] = "test-key"
|
|
97
|
+
mock_response = {"families": [], "total": 0}
|
|
98
|
+
with mock.patch("sys.argv", ["cmpnd", "optimizations", "failing-examples", "--program", "RAG"]):
|
|
99
|
+
with mock.patch.dict(os.environ, env, clear=True):
|
|
100
|
+
with mock.patch("cmpnd.cli.api_client.ApiClient.get", return_value=mock_response):
|
|
101
|
+
main()
|
|
102
|
+
captured = capsys.readouterr()
|
|
103
|
+
output = json.loads(captured.out)
|
|
104
|
+
assert "families" in output
|
|
105
|
+
|
|
93
106
|
|
|
94
107
|
class TestAdminGate:
|
|
95
108
|
"""CMP-126: `admin` commands gated behind CMPND_CLI_ADMIN=1; the
|
|
@@ -4,7 +4,14 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import argparse
|
|
6
6
|
|
|
7
|
-
from cmpnd.cli.commands.optimizations import
|
|
7
|
+
from cmpnd.cli.commands.optimizations import (
|
|
8
|
+
handle_candidates,
|
|
9
|
+
handle_dataset_analysis,
|
|
10
|
+
handle_failing_examples,
|
|
11
|
+
handle_iterations,
|
|
12
|
+
handle_search,
|
|
13
|
+
handle_show,
|
|
14
|
+
)
|
|
8
15
|
|
|
9
16
|
|
|
10
17
|
class TestOptimizationsSearch:
|
|
@@ -50,3 +57,36 @@ class TestOptimizationsCandidates:
|
|
|
50
57
|
args = argparse.Namespace(id="abc")
|
|
51
58
|
handle_candidates(mock_client, args)
|
|
52
59
|
mock_client.get.assert_called_once_with("/api/v1/optimizations/abc/candidates")
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class TestOptimizationsFailingExamples:
|
|
63
|
+
def test_default_uses_min_failures(self, mock_client):
|
|
64
|
+
mock_client.get.return_value = {"families": [], "total": 0}
|
|
65
|
+
args = argparse.Namespace(program="RAG", min_failures=2, all_models=False)
|
|
66
|
+
handle_failing_examples(mock_client, args)
|
|
67
|
+
mock_client.get.assert_called_once_with(
|
|
68
|
+
"/api/v1/optimizations/failing-examples",
|
|
69
|
+
params={"program": "RAG", "min_failures": 2},
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
def test_custom_min_failures(self, mock_client):
|
|
73
|
+
mock_client.get.return_value = {"families": []}
|
|
74
|
+
args = argparse.Namespace(program="RAG", min_failures=3, all_models=False)
|
|
75
|
+
handle_failing_examples(mock_client, args)
|
|
76
|
+
assert mock_client.get.call_args[1]["params"]["min_failures"] == 3
|
|
77
|
+
|
|
78
|
+
def test_all_flag_overrides_min_failures(self, mock_client):
|
|
79
|
+
mock_client.get.return_value = {"families": []}
|
|
80
|
+
args = argparse.Namespace(program="RAG", min_failures=2, all_models=True)
|
|
81
|
+
handle_failing_examples(mock_client, args)
|
|
82
|
+
params = mock_client.get.call_args[1]["params"]
|
|
83
|
+
assert params == {"program": "RAG", "all": "true"}
|
|
84
|
+
assert "min_failures" not in params
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class TestOptimizationsDatasetAnalysis:
|
|
88
|
+
def test_calls_correct_endpoint(self, mock_client):
|
|
89
|
+
mock_client.get.return_value = {"total_examples": 0}
|
|
90
|
+
args = argparse.Namespace(id="op_abc")
|
|
91
|
+
handle_dataset_analysis(mock_client, args)
|
|
92
|
+
mock_client.get.assert_called_once_with("/api/v1/optimizations/op_abc/dataset-analysis")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|