cmpnd 0.70.0__tar.gz → 0.72.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.
Files changed (400) hide show
  1. {cmpnd-0.70.0 → cmpnd-0.72.0}/PKG-INFO +1 -1
  2. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/cli/__init__.py +2 -9
  3. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/cli/commands/admin.py +1 -2
  4. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/cli/commands/deployments.py +3 -0
  5. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/client.py +23 -23
  6. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/execution.py +22 -1
  7. {cmpnd-0.70.0 → cmpnd-0.72.0}/docs/cli.md +6 -7
  8. {cmpnd-0.70.0 → cmpnd-0.72.0}/docs/client.md +5 -8
  9. {cmpnd-0.70.0 → cmpnd-0.72.0}/docs/sdk-instrumentation.md +8 -1
  10. {cmpnd-0.70.0 → cmpnd-0.72.0}/pyproject.toml +1 -1
  11. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_cli/test_deployment_runs.py +34 -0
  12. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_cli/test_main.py +22 -0
  13. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_cli/test_parity.py +10 -5
  14. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_client.py +27 -16
  15. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_client_program_names.py +0 -2
  16. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_deployment_runs.py +68 -0
  17. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_program_id_deprecation.py +0 -1
  18. {cmpnd-0.70.0 → cmpnd-0.72.0}/uv.lock +1 -1
  19. {cmpnd-0.70.0 → cmpnd-0.72.0}/.gitignore +0 -0
  20. {cmpnd-0.70.0 → cmpnd-0.72.0}/AGENTS.md +0 -0
  21. {cmpnd-0.70.0 → cmpnd-0.72.0}/CLAUDE.md +0 -0
  22. {cmpnd-0.70.0 → cmpnd-0.72.0}/README.md +0 -0
  23. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/__init__.py +0 -0
  24. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/_assessments.py +0 -0
  25. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/_authored_import.py +0 -0
  26. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/_deployments.py +0 -0
  27. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/_exporter_pool.py +0 -0
  28. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/_gepa_patch.py +0 -0
  29. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/_http.py +0 -0
  30. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/_program_patch.py +0 -0
  31. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/_rlm_patch.py +0 -0
  32. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/_runtime_tools.py +0 -0
  33. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/_timespec.py +0 -0
  34. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/_traces.py +0 -0
  35. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/_valsets.py +0 -0
  36. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/authored.py +0 -0
  37. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/callback.py +0 -0
  38. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/cli/api_client.py +0 -0
  39. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/cli/commands/__init__.py +0 -0
  40. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/cli/commands/assessments.py +0 -0
  41. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/cli/commands/auth.py +0 -0
  42. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/cli/commands/datasets.py +0 -0
  43. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/cli/commands/evals.py +0 -0
  44. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/cli/commands/login.py +0 -0
  45. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/cli/commands/optimizations.py +0 -0
  46. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/cli/commands/org.py +0 -0
  47. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/cli/commands/programs.py +0 -0
  48. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/cli/commands/provider_credentials.py +0 -0
  49. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/cli/commands/tool_servers.py +0 -0
  50. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/cli/commands/top.py +0 -0
  51. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/cli/commands/traces.py +0 -0
  52. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/cli/commands/valsets.py +0 -0
  53. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/cli/credentials.py +0 -0
  54. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/cli/deprecation.py +0 -0
  55. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/cli/pagination.py +0 -0
  56. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/cli/shell.py +0 -0
  57. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/cli/trace_render.py +0 -0
  58. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/cli/tree_help.py +0 -0
  59. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/cli/verbs.py +0 -0
  60. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/cli/views.py +0 -0
  61. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/configuration.py +0 -0
  62. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/context.py +0 -0
  63. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/credentials.py +0 -0
  64. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/dataset_sync.py +0 -0
  65. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/datasets.py +0 -0
  66. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/decorators.py +0 -0
  67. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/deployment.py +0 -0
  68. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/deployment_metadata.py +0 -0
  69. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/deployment_runs.py +0 -0
  70. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/eval_handler.py +0 -0
  71. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/exporter.py +0 -0
  72. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/exporter_http.py +0 -0
  73. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/helpers.py +0 -0
  74. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/identity.py +0 -0
  75. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/imaging.py +0 -0
  76. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/ir/__init__.py +0 -0
  77. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/ir/decode.py +0 -0
  78. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/ir/encode.py +0 -0
  79. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/ir/hash.py +0 -0
  80. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/ir/program.py +0 -0
  81. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/ir/reflection.py +0 -0
  82. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/ir/types.py +0 -0
  83. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/ir/xxh64.py +0 -0
  84. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/lm_configuration.py +0 -0
  85. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/mcp_servers.py +0 -0
  86. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/models.py +0 -0
  87. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/named_programs.py +0 -0
  88. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/optimization.py +0 -0
  89. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/optimizers/__init__.py +0 -0
  90. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/optimizers/gepa.py +0 -0
  91. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/optimizers/gepa_callback.py +0 -0
  92. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/optimizers/resume.py +0 -0
  93. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/optimizers/tracker.py +0 -0
  94. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/packaging.py +0 -0
  95. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/programs.py +0 -0
  96. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/references.py +0 -0
  97. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/retry.py +0 -0
  98. {cmpnd-0.70.0 → cmpnd-0.72.0}/cmpnd/traces.py +0 -0
  99. {cmpnd-0.70.0 → cmpnd-0.72.0}/docs/2026-04-02-code-review.md +0 -0
  100. {cmpnd-0.70.0 → cmpnd-0.72.0}/docs/custom-proposer.md +0 -0
  101. {cmpnd-0.70.0 → cmpnd-0.72.0}/docs/plans/2026-04-05-train-val-dataset-capture-design.md +0 -0
  102. {cmpnd-0.70.0 → cmpnd-0.72.0}/docs/plans/2026-04-05-train-val-dataset-capture.md +0 -0
  103. {cmpnd-0.70.0 → cmpnd-0.72.0}/docs/reading-traces.md +0 -0
  104. {cmpnd-0.70.0 → cmpnd-0.72.0}/examples/generalizing_proposer.py +0 -0
  105. {cmpnd-0.70.0 → cmpnd-0.72.0}/examples/local_ollama.py +0 -0
  106. {cmpnd-0.70.0 → cmpnd-0.72.0}/ingest/LINEAGE.md +0 -0
  107. {cmpnd-0.70.0 → cmpnd-0.72.0}/ingest/README.md +0 -0
  108. {cmpnd-0.70.0 → cmpnd-0.72.0}/ingest/cmpnd_ingest/__init__.py +0 -0
  109. {cmpnd-0.70.0 → cmpnd-0.72.0}/ingest/cmpnd_ingest/bodies.py +0 -0
  110. {cmpnd-0.70.0 → cmpnd-0.72.0}/ingest/cmpnd_ingest/client_floor.py +0 -0
  111. {cmpnd-0.70.0 → cmpnd-0.72.0}/ingest/cmpnd_ingest/exporter_http.py +0 -0
  112. {cmpnd-0.70.0 → cmpnd-0.72.0}/ingest/cmpnd_ingest/program_names.py +0 -0
  113. {cmpnd-0.70.0 → cmpnd-0.72.0}/ingest/cmpnd_ingest/protocols.py +0 -0
  114. {cmpnd-0.70.0 → cmpnd-0.72.0}/ingest/cmpnd_ingest/py.typed +0 -0
  115. {cmpnd-0.70.0 → cmpnd-0.72.0}/ingest/cmpnd_ingest/request_log.py +0 -0
  116. {cmpnd-0.70.0 → cmpnd-0.72.0}/ingest/cmpnd_ingest/retry.py +0 -0
  117. {cmpnd-0.70.0 → cmpnd-0.72.0}/ingest/cmpnd_ingest/trace_facts.py +0 -0
  118. {cmpnd-0.70.0 → cmpnd-0.72.0}/ingest/pyproject.toml +0 -0
  119. {cmpnd-0.70.0 → cmpnd-0.72.0}/scripts/audit-sdist.sh +0 -0
  120. {cmpnd-0.70.0 → cmpnd-0.72.0}/scripts/capture_review_run.py +0 -0
  121. {cmpnd-0.70.0 → cmpnd-0.72.0}/scripts/check-pip-install.sh +0 -0
  122. {cmpnd-0.70.0 → cmpnd-0.72.0}/scripts/check_release_artifacts.py +0 -0
  123. {cmpnd-0.70.0 → cmpnd-0.72.0}/scripts/fixtures/review_run.json.gz +0 -0
  124. {cmpnd-0.70.0 → cmpnd-0.72.0}/scripts/gepa_resume_bug.py +0 -0
  125. {cmpnd-0.70.0 → cmpnd-0.72.0}/scripts/install-test-env.sh +0 -0
  126. {cmpnd-0.70.0 → cmpnd-0.72.0}/scripts/release-gate.sh +0 -0
  127. {cmpnd-0.70.0 → cmpnd-0.72.0}/scripts/release-real-models.sh +0 -0
  128. {cmpnd-0.70.0 → cmpnd-0.72.0}/scripts/require_version_bump.py +0 -0
  129. {cmpnd-0.70.0 → cmpnd-0.72.0}/scripts/seed_review_run.py +0 -0
  130. {cmpnd-0.70.0 → cmpnd-0.72.0}/scripts/selfhost_compat.py +0 -0
  131. {cmpnd-0.70.0 → cmpnd-0.72.0}/scripts/test-in-linux.sh +0 -0
  132. {cmpnd-0.70.0 → cmpnd-0.72.0}/stubs/dspy/__init__.pyi +0 -0
  133. {cmpnd-0.70.0 → cmpnd-0.72.0}/stubs/dspy/primitives/__init__.pyi +0 -0
  134. {cmpnd-0.70.0 → cmpnd-0.72.0}/stubs/dspy/primitives/prediction.pyi +0 -0
  135. {cmpnd-0.70.0 → cmpnd-0.72.0}/stubs/dspy/utils/__init__.pyi +0 -0
  136. {cmpnd-0.70.0 → cmpnd-0.72.0}/stubs/dspy/utils/callback.pyi +0 -0
  137. {cmpnd-0.70.0 → cmpnd-0.72.0}/stubs/dspy/utils/dummies.pyi +0 -0
  138. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/__init__.py +0 -0
  139. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/_credential_route.py +0 -0
  140. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/_deployment_signature_helpers.py +0 -0
  141. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/_exporter_helpers.py +0 -0
  142. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/_fake_clock.py +0 -0
  143. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/_identity_helpers.py +0 -0
  144. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/_resolve_refs.py +0 -0
  145. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/_traced_run.py +0 -0
  146. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/conftest.py +0 -0
  147. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/e2e/__init__.py +0 -0
  148. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/e2e/committee_task.py +0 -0
  149. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/e2e/conftest.py +0 -0
  150. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/e2e/continuation_task.py +0 -0
  151. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/e2e/data/committee_train.ndjson.gz +0 -0
  152. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/e2e/data/committee_val.ndjson.gz +0 -0
  153. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/e2e/fake_lm.py +0 -0
  154. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/e2e/helpers.py +0 -0
  155. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/e2e/target_capabilities.py +0 -0
  156. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/e2e/test_assessments_cli.py +0 -0
  157. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/e2e/test_capture_prompts.py +0 -0
  158. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/e2e/test_composite_module.py +0 -0
  159. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/e2e/test_dataset_auto_creation.py +0 -0
  160. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/e2e/test_deploy_execute.py +0 -0
  161. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/e2e/test_deploy_pandas.py +0 -0
  162. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/e2e/test_deploy_programs.py +0 -0
  163. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/e2e/test_edge_cases.py +0 -0
  164. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/e2e/test_example_hash.py +0 -0
  165. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/e2e/test_gepa_optimization.py +0 -0
  166. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/e2e/test_interpreter_spans.py +0 -0
  167. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/e2e/test_lm_accuracy.py +0 -0
  168. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/e2e/test_module_tracing.py +0 -0
  169. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/e2e/test_optimization_lineage.py +0 -0
  170. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/e2e/test_optimization_metric_identity.py +0 -0
  171. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/e2e/test_optimize_authored_metric.py +0 -0
  172. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/e2e/test_optimize_continuation.py +0 -0
  173. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/e2e/test_optimize_custom_proposer.py +0 -0
  174. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/e2e/test_optimize_failures.py +0 -0
  175. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/e2e/test_optimize_loop.py +0 -0
  176. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/e2e/test_optimize_review_committee.py +0 -0
  177. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/e2e/test_optimize_server_owned_completion.py +0 -0
  178. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/e2e/test_parallel_export.py +0 -0
  179. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/e2e/test_project_attribution.py +0 -0
  180. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/e2e/test_react_tool_spans.py +0 -0
  181. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/e2e/test_save_load.py +0 -0
  182. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/e2e/test_trace_structure.py +0 -0
  183. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/e2e/test_traces_read.py +0 -0
  184. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/e2e/test_user_attribution.py +0 -0
  185. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/e2e/test_valsets_cli.py +0 -0
  186. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/identity_vectors/01_predict_qa.json +0 -0
  187. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/identity_vectors/02_predict_renamed_field.json +0 -0
  188. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/identity_vectors/03_chain_of_thought_qa.json +0 -0
  189. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/identity_vectors/04_predict_richer_types.json +0 -0
  190. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/identity_vectors/05_composite_two_predicts.json +0 -0
  191. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/identity_vectors/06_multichaincomparison.json +0 -0
  192. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/identity_vectors/07_program_of_thought.json +0 -0
  193. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/identity_vectors/08_opaque_module.json +0 -0
  194. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/identity_vectors/09_predict_pydantic_field.json +0 -0
  195. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/identity_vectors/10_react.json +0 -0
  196. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/identity_vectors/11_refine.json +0 -0
  197. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/identity_vectors/12_retrieve.json +0 -0
  198. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/identity_vectors/13_knn.json +0 -0
  199. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/identity_vectors/14_parallel.json +0 -0
  200. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/identity_vectors/README.md +0 -0
  201. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/ingest_conformance.py +0 -0
  202. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/integration/__init__.py +0 -0
  203. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/integration/authored_optimize/judge.py +0 -0
  204. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/integration/authored_optimize/optimize_hosted.py +0 -0
  205. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/integration/conftest.py +0 -0
  206. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/integration/hosted_mcp_tool_optimize_probe.py +0 -0
  207. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/integration/hosted_optimize_probe.py +0 -0
  208. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/integration/optimization_run_probe.py +0 -0
  209. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/integration/test_cli_deploy_smoketest.py +0 -0
  210. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/integration/test_logs_renders_traces.py +0 -0
  211. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/integration/test_optimization_run.py +0 -0
  212. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/integration/test_optimizing_progress.py +0 -0
  213. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/integration/test_unhappy_path.py +0 -0
  214. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/load/__init__.py +0 -0
  215. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/load/__main__.py +0 -0
  216. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/load/drain.py +0 -0
  217. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/load/ingest.py +0 -0
  218. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/load/latency_transport.py +0 -0
  219. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/load/rlm_shape.py +0 -0
  220. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/load/rlm_size_report.py +0 -0
  221. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/load/sweep.py +0 -0
  222. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/load/test_rlm_shape.py +0 -0
  223. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/load/test_rlm_size_report.py +0 -0
  224. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/parity/__init__.py +0 -0
  225. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/parity/conftest.py +0 -0
  226. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/parity/seed_parity.py +0 -0
  227. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/parity/test_auth.py +0 -0
  228. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/parity/test_datasets.py +0 -0
  229. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/parity/test_deployments.py +0 -0
  230. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/parity/test_evals.py +0 -0
  231. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/parity/test_health.py +0 -0
  232. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/parity/test_modules.py +0 -0
  233. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/parity/test_optimizations.py +0 -0
  234. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/parity/test_programs.py +0 -0
  235. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/parity/test_signatures.py +0 -0
  236. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/parity/test_trace_streaming.py +0 -0
  237. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/parity/test_traces.py +0 -0
  238. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/real_models/__init__.py +0 -0
  239. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/real_models/_provider.py +0 -0
  240. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/real_models/_readiness.py +0 -0
  241. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/real_models/_reliability.py +0 -0
  242. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/real_models/_result.py +0 -0
  243. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/real_models/mint_bedrock_token.py +0 -0
  244. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/real_models/test_bedrock_converse.py +0 -0
  245. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/real_models/test_deploy_programs.py +0 -0
  246. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/real_models/test_multi_client_stress.py +0 -0
  247. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/real_models/test_optimize_client_committee.py +0 -0
  248. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/real_models/test_optimize_continuation.py +0 -0
  249. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/real_models/test_optimize_loop.py +0 -0
  250. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/real_models/test_optimize_loop_wasm.py +0 -0
  251. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/real_models/test_optimize_stress.py +0 -0
  252. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/real_models/test_provider_roles.py +0 -0
  253. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/real_models/test_readiness.py +0 -0
  254. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/real_models/test_real_provider_twins.py +0 -0
  255. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/real_models/test_reliability.py +0 -0
  256. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/real_models/test_reliability_classify.py +0 -0
  257. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/real_models/test_rlm_wasm.py +0 -0
  258. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/real_models/test_trace_search.py +0 -0
  259. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/span_reference_fixture.py +0 -0
  260. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_adapter_reentrancy.py +0 -0
  261. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_assessments_api.py +0 -0
  262. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_authored.py +0 -0
  263. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_authored_binding_credentials.py +0 -0
  264. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_authored_bundle_collisions.py +0 -0
  265. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_authored_metric_contract.py +0 -0
  266. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_authored_named_models.py +0 -0
  267. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_authored_optimize.py +0 -0
  268. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_callback.py +0 -0
  269. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_candidate_lineage.py +0 -0
  270. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_cli/__init__.py +0 -0
  271. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_cli/conftest.py +0 -0
  272. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_cli/test_admin.py +0 -0
  273. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_cli/test_api_client.py +0 -0
  274. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_cli/test_assessments.py +0 -0
  275. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_cli/test_auth.py +0 -0
  276. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_cli/test_credentials.py +0 -0
  277. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_cli/test_datasets.py +0 -0
  278. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_cli/test_deployments.py +0 -0
  279. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_cli/test_evals.py +0 -0
  280. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_cli/test_login.py +0 -0
  281. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_cli/test_optimizations.py +0 -0
  282. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_cli/test_org.py +0 -0
  283. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_cli/test_pagination.py +0 -0
  284. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_cli/test_programs.py +0 -0
  285. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_cli/test_provider_credentials.py +0 -0
  286. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_cli/test_schema_sample.py +0 -0
  287. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_cli/test_shell.py +0 -0
  288. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_cli/test_tool_servers.py +0 -0
  289. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_cli/test_top.py +0 -0
  290. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_cli/test_traces.py +0 -0
  291. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_cli/test_traces_program_and_module.py +0 -0
  292. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_cli/test_traces_search_wire.py +0 -0
  293. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_cli/test_tree_help.py +0 -0
  294. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_cli/test_valsets.py +0 -0
  295. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_client_floor.py +0 -0
  296. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_clustering/__init__.py +0 -0
  297. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_clustering/conftest.py +0 -0
  298. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_clustering/test_edge_cases.py +0 -0
  299. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_clustering/test_hash_consistency.py +0 -0
  300. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_clustering/test_type_conversion.py +0 -0
  301. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_cmp551_grouping_identity.py +0 -0
  302. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_configuration.py +0 -0
  303. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_context.py +0 -0
  304. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_context_propagation.py +0 -0
  305. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_credential_kwargs.py +0 -0
  306. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_credential_selection.py +0 -0
  307. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_credential_values.py +0 -0
  308. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_dataset_polling.py +0 -0
  309. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_dataset_sync.py +0 -0
  310. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_datasets.py +0 -0
  311. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_decision_client_spans.py +0 -0
  312. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_decorators.py +0 -0
  313. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_deploy.py +0 -0
  314. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_deploy_mcp_tool_references.py +0 -0
  315. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_deploy_program_id.py +0 -0
  316. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_deployment_metadata.py +0 -0
  317. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_deployments_read.py +0 -0
  318. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_eval.py +0 -0
  319. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_eval_example_attribution.py +0 -0
  320. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_eval_program_id.py +0 -0
  321. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_eval_start.py +0 -0
  322. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_eval_trace_grouping.py +0 -0
  323. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_exception_paths.py +0 -0
  324. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_execute.py +0 -0
  325. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_execute_run_identity.py +0 -0
  326. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_exporter.py +0 -0
  327. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_exporter_program_names.py +0 -0
  328. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_exporter_queue.py +0 -0
  329. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_exporter_real.py +0 -0
  330. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_fake_lm.py +0 -0
  331. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_gepa_callback.py +0 -0
  332. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_gepa_integration.py +0 -0
  333. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_gepa_output_normalization.py +0 -0
  334. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_gepa_resume.py +0 -0
  335. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_identity.py +0 -0
  336. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_imaging.py +0 -0
  337. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_import_weight.py +0 -0
  338. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_ingest_conformance.py +0 -0
  339. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_ingest_second_producer.py +0 -0
  340. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_integration.py +0 -0
  341. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_interpreter_callback.py +0 -0
  342. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_ir_encoder_properties.py +0 -0
  343. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_ir_golden_vectors.py +0 -0
  344. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_ir_roundtrip.py +0 -0
  345. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_lm15_native_calls.py +0 -0
  346. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_lm_configuration.py +0 -0
  347. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_lm_usage_shapes.py +0 -0
  348. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_mcp_tools.py +0 -0
  349. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_models.py +0 -0
  350. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_multi_client_stress_readiness.py +0 -0
  351. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_optimization_progress.py +0 -0
  352. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_optimization_start.py +0 -0
  353. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_optimize.py +0 -0
  354. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_optimize_budget.py +0 -0
  355. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_optimize_lift.py +0 -0
  356. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_optimize_lms.py +0 -0
  357. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_optimize_proposer.py +0 -0
  358. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_optimize_reflection_lm.py +0 -0
  359. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_optimize_terminal_failure.py +0 -0
  360. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_packaging.py +0 -0
  361. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_packaging_callable_source.py +0 -0
  362. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_packaging_mcp_tools.py +0 -0
  363. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_packaging_program_source.py +0 -0
  364. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_poll_until.py +0 -0
  365. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_program_identity.py +0 -0
  366. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_program_lineage_persist.py +0 -0
  367. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_program_names_in_deploy.py +0 -0
  368. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_programs_create.py +0 -0
  369. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_project_payload.py +0 -0
  370. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_real_provider_twins_readiness.py +0 -0
  371. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_reflector_properties.py +0 -0
  372. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_reflector_smoke.py +0 -0
  373. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_release_gate_script.py +0 -0
  374. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_release_real_models_script.py +0 -0
  375. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_replaced_names.py +0 -0
  376. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_repro_reactv2_bugs.py +0 -0
  377. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_require_version_bump.py +0 -0
  378. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_retry.py +0 -0
  379. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_reversible_failures.py +0 -0
  380. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_rlm_patch.py +0 -0
  381. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_run_attribution_paths.py +0 -0
  382. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_runtime_tools.py +0 -0
  383. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_schemas.py +0 -0
  384. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_seal_lm_credential.py +0 -0
  385. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_seed_review_run.py +0 -0
  386. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_signature_inputs.py +0 -0
  387. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_span_references.py +0 -0
  388. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_span_sent_once.py +0 -0
  389. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_system_one.py +0 -0
  390. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_trace_context_concurrency.py +0 -0
  391. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_trace_fact_wire_contract.py +0 -0
  392. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_trace_facts.py +0 -0
  393. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_trace_render.py +0 -0
  394. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_traces_read.py +0 -0
  395. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_tracked_gepa.py +0 -0
  396. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_tracker_enrich.py +0 -0
  397. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_truncation.py +0 -0
  398. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_upload_auth_headers.py +0 -0
  399. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_valsets_api.py +0 -0
  400. {cmpnd-0.70.0 → cmpnd-0.72.0}/tests/test_xxh64.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: cmpnd
3
- Version: 0.70.0
3
+ Version: 0.72.0
4
4
  Summary: DSPy observability and deployment SDK for cmpnd
5
5
  Project-URL: Homepage, https://cmpnd.ai
6
6
  Author-email: cmpnd <hello@cmpnd.ai>
@@ -171,15 +171,8 @@ def main() -> None:
171
171
  evals.register(subparsers)
172
172
  datasets.register(subparsers)
173
173
  deployments.register(subparsers)
174
-
175
- # Assessments and valsets CLIs are still in development, hidden behind
176
- # CMPND_CLI_DEV=1 (mirroring the CMPND_CLI_ADMIN gate above). The env var
177
- # only hides the commands from customers; the server still gates each action
178
- # on the assessments:* / valsets:* scope, so this is discoverability, not
179
- # enforcement.
180
- if os.environ.get("CMPND_CLI_DEV") == "1":
181
- assessments.register(subparsers)
182
- valsets.register(subparsers)
174
+ assessments.register(subparsers)
175
+ valsets.register(subparsers)
183
176
 
184
177
  # Top-level Docker-style shortcuts (human-readable by default; --json opts in)
185
178
  top.register(subparsers)
@@ -14,8 +14,7 @@ default limits and feature flags, and `cmpnd admin signup …` sets who may sign
14
14
  and the plan a new account's org lands on. `cmpnd admin feature-flags …` reads and
15
15
  toggles the server's runtime flags. These hit
16
16
  /api/v1/admin/* and require an API key carrying the admin:* scopes — the server
17
- is the real authority. The CMPND_CLI_ADMIN env gate (mirroring CMPND_CLI_DEV)
18
- only keeps these out of customers' --help; it grants nothing.
17
+ is the real authority. The CMPND_CLI_ADMIN env gate only keeps these out of customers' --help; it grants nothing.
19
18
  """
20
19
 
21
20
  from __future__ import annotations
@@ -191,6 +191,9 @@ def submit_cli_run(
191
191
  raise
192
192
  except httpx.HTTPStatusError as exc:
193
193
  raise _http_refusal(exc) from exc
194
+ trace_id = settled.get("trace_id")
195
+ if isinstance(trace_id, str) and trace_id:
196
+ print(f"Trace: {trace_id}", file=sys.stderr)
194
197
  if settled["status"] == "failed":
195
198
  return settled, None
196
199
  result = settled.get("result")
@@ -17,10 +17,6 @@ and propagates to its own eval / parallel threads. It registers nothing global
17
17
  and holds no OS resource: exporters are pooled by credentials at module scope
18
18
  (:mod:`cmpnd._exporter_pool`), so a client may fall out of scope with nothing to
19
19
  release. ``close()`` is an optional alias for end-of-scope flushing.
20
-
21
- The assessment and valset calls are in development. Each raises unless
22
- ``CMPND_CLI_DEV=1`` is set, the switch that hides the in-development
23
- ``cmpnd assessments`` and ``cmpnd valsets`` CLI groups. Tracing needs no flag.
24
20
  """
25
21
 
26
22
  from __future__ import annotations
@@ -111,15 +107,6 @@ class Client:
111
107
  if not self._active:
112
108
  raise RuntimeError("client is closed; create a new cmpnd.Client")
113
109
 
114
- def _check_in_development(self, method: str) -> None:
115
- """Refuse an assessment or valset call unless ``CMPND_CLI_DEV=1`` is set."""
116
- if os.getenv("CMPND_CLI_DEV") != "1":
117
- raise RuntimeError(
118
- f"cmpnd.Client.{method}() is in development and not yet generally available. "
119
- "Set CMPND_CLI_DEV=1 to enable it."
120
- )
121
- self._check_active()
122
-
123
110
  def _scoped_callbacks(self) -> list[Any]:
124
111
  """This client's callback, plus the caller's own non-cmpnd callbacks.
125
112
 
@@ -403,6 +390,19 @@ class Client:
403
390
 
404
391
  return execution.deployment_run_id(result_or_error)
405
392
 
393
+ def get_trace_id(self, result_or_error: Any) -> str | None:
394
+ """The root trace id of a ``run_deployment`` prediction or exception.
395
+
396
+ It reads the id serve returned with the settled run and sends no
397
+ request. ``get_trace`` opens the trace.
398
+ The id lives outside the prediction's output fields. A run that stored no
399
+ trace, a server that names none, and a failure before serve accepted a run
400
+ all return ``None``.
401
+ """
402
+ from . import execution
403
+
404
+ return execution.get_trace_id(result_or_error)
405
+
406
406
  def submit_deployment_run(
407
407
  self,
408
408
  deployment_or_id: Any,
@@ -918,7 +918,7 @@ class Client:
918
918
  e.g. ``annotations=[("output", "/trends/2", "the third trend"),
919
919
  ("span", "a1b2c3", "wrong field")]``.
920
920
  """
921
- self._check_in_development("create_assessment")
921
+ self._check_active()
922
922
  _exporter_pool.flush(self._config) # the referenced trace must be durable first
923
923
  return _assessments.create(
924
924
  trace_id,
@@ -937,7 +937,7 @@ class Client:
937
937
  Pass exactly one of ``program`` (all of that program's assessments, named by
938
938
  its name or ``p_`` id) or ``trace_id`` (one trace's assessments).
939
939
  """
940
- self._check_in_development("list_assessments")
940
+ self._check_active()
941
941
  if program is not None and trace_id is not None:
942
942
  raise ValueError("pass exactly one of program or trace_id")
943
943
  page = _assessments.list(
@@ -952,24 +952,24 @@ class Client:
952
952
 
953
953
  def get_assessment(self, assessment_id: str) -> dict[str, Any]:
954
954
  """Fetch one assessment with its annotations."""
955
- self._check_in_development("get_assessment")
955
+ self._check_active()
956
956
  return _assessments.get(assessment_id, api_key=self._config.api_key, endpoint=self._config.endpoint)
957
957
 
958
958
  def delete_assessment(self, assessment_id: str) -> None:
959
959
  """Delete one assessment. Raises if it does not exist."""
960
- self._check_in_development("delete_assessment")
960
+ self._check_active()
961
961
  _assessments.delete(assessment_id, api_key=self._config.api_key, endpoint=self._config.endpoint)
962
962
 
963
963
  def create_valset(self, program: str, *, name: str | None = None) -> dict[str, Any]:
964
964
  """Create a valset owned by ``program``, a program name or ``p_`` id; name auto-assigned when omitted."""
965
- self._check_in_development("create_valset")
965
+ self._check_active()
966
966
  return _valsets.create(
967
967
  self._program_id(program), name=name, api_key=self._config.api_key, endpoint=self._config.endpoint
968
968
  )
969
969
 
970
970
  def list_valsets(self, program: str, *, limit: int = 50, offset: int = 0) -> list[dict[str, Any]]:
971
971
  """The valsets of ``program``, a program name or ``p_`` id, newest first (paged by limit/offset)."""
972
- self._check_in_development("list_valsets")
972
+ self._check_active()
973
973
  page = _valsets.list(
974
974
  self._program_id(program),
975
975
  limit=limit,
@@ -981,12 +981,12 @@ class Client:
981
981
 
982
982
  def get_valset(self, valset_id: str) -> dict[str, Any]:
983
983
  """Fetch one valset with its field shape and current version."""
984
- self._check_in_development("get_valset")
984
+ self._check_active()
985
985
  return _valsets.get(valset_id, api_key=self._config.api_key, endpoint=self._config.endpoint)
986
986
 
987
987
  def list_valset_entries(self, valset_id: str, *, limit: int = 50, offset: int = 0) -> list[dict[str, Any]]:
988
988
  """A valset's active entries (paged by limit/offset)."""
989
- self._check_in_development("list_valset_entries")
989
+ self._check_active()
990
990
  page = _valsets.list_entries(
991
991
  valset_id, limit=limit, offset=offset, api_key=self._config.api_key, endpoint=self._config.endpoint
992
992
  )
@@ -1002,7 +1002,7 @@ class Client:
1002
1002
  ) -> dict[str, Any]:
1003
1003
  """Add one entry. Pass exactly one of ``from_assessment`` (the server
1004
1004
  derives inputs from its trace) or ``inputs``."""
1005
- self._check_in_development("create_valset_entry")
1005
+ self._check_active()
1006
1006
  return _valsets.create_entry(
1007
1007
  valset_id,
1008
1008
  expected_outputs=expected_outputs,
@@ -1014,7 +1014,7 @@ class Client:
1014
1014
 
1015
1015
  def delete_valset_entry(self, entry_id: str) -> dict[str, Any]:
1016
1016
  """Retire an entry (versioned, not a hard delete)."""
1017
- self._check_in_development("delete_valset_entry")
1017
+ self._check_active()
1018
1018
  return _valsets.delete_entry(entry_id, api_key=self._config.api_key, endpoint=self._config.endpoint)
1019
1019
 
1020
1020
  def _run_gepa(
@@ -33,6 +33,21 @@ def deployment_run_id(result_or_error: Any) -> str | None:
33
33
  return getattr(result_or_error, "_cmpnd_deployment_run_id", None)
34
34
 
35
35
 
36
+ def get_trace_id(result_or_error: Any) -> str | None:
37
+ """Return the root trace id serve named for a run's prediction or exception.
38
+
39
+ The id lives outside the prediction's program output fields. A run that
40
+ stored no trace, a server that names none, and a failure before serve
41
+ accepted a run all return ``None``.
42
+ """
43
+ return getattr(result_or_error, "_cmpnd_deployment_trace_id", None)
44
+
45
+
46
+ def _settled_trace_id(settled: dict[str, Any]) -> str | None:
47
+ trace_id = settled.get("trace_id")
48
+ return trace_id if isinstance(trace_id, str) and trace_id else None
49
+
50
+
36
51
  def _with_run_id(error: Exception, run_id: str | None) -> Exception:
37
52
  error._cmpnd_deployment_run_id = run_id # pyright: ignore[reportAttributeAccessIssue]
38
53
  return error
@@ -247,14 +262,20 @@ def run_deployment(
247
262
  raise
248
263
 
249
264
  settled_id: str = settled["deployment_run_id"]
265
+ trace_id = _settled_trace_id(settled)
250
266
  result = settled["result"]
251
267
  if settled["status"] == "failed":
252
- _raise_stored_failure(settled_id, result, config.endpoint)
268
+ try:
269
+ _raise_stored_failure(settled_id, result, config.endpoint)
270
+ except Exception as error:
271
+ error._cmpnd_deployment_trace_id = trace_id # pyright: ignore[reportAttributeAccessIssue]
272
+ raise
253
273
  if not isinstance(result, dict) or "output" not in result:
254
274
  raise _with_run_id(RuntimeError("Deployment run result has no program output"), settled_id)
255
275
  output = result["output"]
256
276
  prediction = Prediction(**output) if isinstance(output, dict) else Prediction(**{"output": output})
257
277
  setattr(prediction, "_cmpnd_deployment_run_id", settled_id)
278
+ setattr(prediction, "_cmpnd_deployment_trace_id", trace_id)
258
279
  return prediction
259
280
 
260
281
 
@@ -228,6 +228,10 @@ seconds, unless `--timeout` sets the budget. The CLI prints the accepted run ID
228
228
  on stderr as soon as serve replies, which can take up to serve's five-second
229
229
  wait. A failed run exits nonzero. Human mode prints the stored error code,
230
230
  message and provider status. `--json` prints the whole settled run on stdout.
231
+ When a settled run names its root trace, the CLI prints `Trace: <id>` on
232
+ stderr, completed or failed. `cmpnd traces show <id>` opens that trace. The
233
+ run's `trace_id` field holds the same ID, and serve leaves it out when the run
234
+ stored no trace.
231
235
  The CLI retries status reads that time out or answer `408`, `429` or `5xx`
232
236
  within the budget.
233
237
 
@@ -418,10 +422,7 @@ down or neutral conclusion, an optional prose body and annotations. An
418
422
  annotation attaches a note to a span or to a piece of the output addressed by
419
423
  a JSON pointer.
420
424
 
421
- The group is in development. The CLI registers it only when
422
- `CMPND_CLI_DEV=1` is set, so it does not appear in `cmpnd --help`. The
423
- variable only hides the commands. Serve still checks each action against the
424
- `assessments:*` scopes.
425
+ Serve checks each action against the `assessments:*` scopes.
425
426
 
426
427
  - `cmpnd assessments create <trace-id> [--up|--down|--neutral] [-m "prose"]
427
428
  [--annotate KIND REF NOTE …]` records one judgement.
@@ -534,9 +535,7 @@ that lookup, so it creates a valset by the program's name. On a server from befo
534
535
  name fails with an error that says to upgrade the server. Entries live in an
535
536
  `entries` subgroup, the same shape as `cmpnd datasets examples`.
536
537
 
537
- The group is in development. The CLI registers it only when
538
- `CMPND_CLI_DEV=1` is set. Serve still checks each action against the
539
- `valsets:*` scopes.
538
+ Serve checks each action against the `valsets:*` scopes.
540
539
 
541
540
  - `cmpnd valsets create <program> [--name <name>]` creates a validation
542
541
  set for a program. The valset ID is its identity, and the name is a label
@@ -10,11 +10,6 @@ client methods too, and have no form outside a client. A client holds its own ta
10
10
  the global config that `auto_instrument()` reads, so both can run in one
11
11
  process.
12
12
 
13
- The client's assessment and valset calls are in development. Each one raises
14
- `RuntimeError` unless `CMPND_CLI_DEV=1` is set. The same variable reveals the
15
- in-development `cmpnd assessments` and `cmpnd valsets` CLI groups. Tracing
16
- through a client needs no flag.
17
-
18
13
  ## Entry point
19
14
 
20
15
  ```python
@@ -152,7 +147,9 @@ endpoint. None of these reads the global config:
152
147
  - `sdk.submit_deployment_run`, `list_deployment_runs`, `get_deployment_run`,
153
148
  `get_deployment_run_result` and `wait_deployment_run` submit, find and resume
154
149
  runs without waiting in one call. `sdk.deployment_run_id(result)` reads the run
155
- id of a prediction or an exception.
150
+ id of a prediction or an exception. `sdk.get_trace_id(result)` reads the
151
+ id of the run's root trace the same way, or returns `None` when serve named no
152
+ trace.
156
153
  - `sdk.optimize_deployment(deployment, optimizer="gepa", ...)` runs the
157
154
  platform's optimization on a deployment and returns the best
158
155
  `DeployedProgram`, with `.score`. It never deploys. The program's model comes
@@ -218,12 +215,12 @@ methods:
218
215
  file the deployment stores, or the archive-relative file `path` names.
219
216
  `sdk.get_deployment_signature(deployment_id)` returns the selected
220
217
  artifact's typed metadata. It reads no worker status or executions.
221
- - Assessments, in development behind `CMPND_CLI_DEV=1`:
218
+ - Assessments:
222
219
  `sdk.create_assessment(trace_id, conclusion=..., body=...,
223
220
  annotations=...)`, `sdk.list_assessments(program=... | trace_id=...,
224
221
  limit=..., offset=...)`, `sdk.get_assessment(assessment_id)` and
225
222
  `sdk.delete_assessment(assessment_id)`.
226
- - Valsets, in development behind `CMPND_CLI_DEV=1`:
223
+ - Valsets:
227
224
  `sdk.create_valset(program, name=...)`, `sdk.list_valsets(program,
228
225
  limit=..., offset=...)`, `sdk.get_valset(valset_id)`,
229
226
  `sdk.list_valset_entries(valset_id, limit=..., offset=...)`,
@@ -432,7 +432,12 @@ command, and re-raises.
432
432
  `client.deployment_run_id(result)` reads the ID from
433
433
  private prediction metadata, so a program can use `output` or
434
434
  `deployment_run_id` as an output field. The accessor also accepts a stored
435
- execution error, a refused read, `RunWaitTimeout` and `RunResultExpired`. A
435
+ execution error, a refused read, `RunWaitTimeout` and `RunResultExpired`.
436
+ `client.get_trace_id(result)` reads the id of the run's root trace from
437
+ the same metadata, for a completed run's prediction and a failed run's error.
438
+ `cmpnd traces show` opens that trace. It returns `None` when the run stored no
439
+ trace, when the server names none, and when the run failed before serve
440
+ accepted it. A
436
441
  retained provider failure keeps its structured `RetryableProviderError` type but
437
442
  does not start another run. Trace delivery can finish after the result is
438
443
  available.
@@ -454,8 +459,10 @@ header readable.
454
459
  try:
455
460
  result = client.run_deployment(deployed, question="What changed?")
456
461
  run_id = client.deployment_run_id(result)
462
+ trace_id = client.get_trace_id(result)
457
463
  except Exception as error:
458
464
  run_id = client.deployment_run_id(error)
465
+ trace_id = client.get_trace_id(error)
459
466
  raise
460
467
  ```
461
468
 
@@ -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.70.0"
8
+ version = "0.72.0"
9
9
  description = "DSPy observability and deployment SDK for cmpnd"
10
10
  readme = "README.md"
11
11
  requires-python = ">=3.11"
@@ -537,3 +537,37 @@ def test_json_run_commands_do_not_import_dspy(argv: list[str], replies: list):
537
537
  assert "JSON run command imported dspy" not in result.stderr
538
538
  out = json.loads(result.stdout)
539
539
  assert RUN_ID in result.stdout or "yes" in json.dumps(out)
540
+
541
+
542
+ TRACE_ID = "0b9c6f2e-4f1d-4c3a-9e2b-7a1d5c3e8f00"
543
+
544
+
545
+ def test_failed_run_names_its_trace_on_stderr(monkeypatch: pytest.MonkeyPatch, capsys):
546
+ failure = {"error": {"type": "ProgramError", "message": "bad input"}, "execution_status": 500}
547
+
548
+ def answer(req):
549
+ return httpx.Response(200, json={**_envelope("failed", failure), "trace_id": TRACE_ID}, request=req)
550
+
551
+ with pytest.raises(SystemExit):
552
+ _run_cli(monkeypatch, ["run", DEPLOYMENT_ID, "{}"], answer)
553
+ assert f"Trace: {TRACE_ID}" in capsys.readouterr().err
554
+
555
+
556
+ def test_completed_run_names_its_trace_on_stderr_and_keeps_stdout_the_output(monkeypatch: pytest.MonkeyPatch, capsys):
557
+ def answer(req):
558
+ return httpx.Response(
559
+ 200, json={**_envelope("completed", {"output": {"answer": "yes"}}), "trace_id": TRACE_ID}, request=req
560
+ )
561
+
562
+ _run_cli(monkeypatch, ["run", DEPLOYMENT_ID, "{}", "--json"], answer)
563
+ out = capsys.readouterr()
564
+ assert json.loads(out.out) == {"answer": "yes"}
565
+ assert f"Trace: {TRACE_ID}" in out.err
566
+
567
+
568
+ def test_run_without_a_trace_names_none(monkeypatch: pytest.MonkeyPatch, capsys):
569
+ def answer(req):
570
+ return httpx.Response(200, json=_envelope("completed", {"output": {"answer": "yes"}}), request=req)
571
+
572
+ _run_cli(monkeypatch, ["run", DEPLOYMENT_ID, "{}", "--json"], answer)
573
+ assert "Trace:" not in capsys.readouterr().err
@@ -169,6 +169,28 @@ class TestDevGate:
169
169
  output = json.loads(captured.out)
170
170
  assert "families" in output
171
171
 
172
+ def test_assessments_works_without_flag(self, capsys):
173
+ env = {k: v for k, v in os.environ.items() if k != "CMPND_CLI_DEV"}
174
+ env["CMPND_API_KEY"] = "test-key"
175
+ mock_response = {"assessments": [], "total": 0}
176
+ with mock.patch("sys.argv", ["cmpnd", "assessments", "list", "--trace", "t_1"]):
177
+ with mock.patch.dict(os.environ, env, clear=True):
178
+ with mock.patch("cmpnd.cli.api_client.ApiClient.get", autospec=True, return_value=mock_response) as get:
179
+ main()
180
+ assert get.call_args.args[1] == "/api/v1/assessments"
181
+ assert json.loads(capsys.readouterr().out) == mock_response
182
+
183
+ def test_valsets_works_without_flag(self, capsys):
184
+ env = {k: v for k, v in os.environ.items() if k != "CMPND_CLI_DEV"}
185
+ env["CMPND_API_KEY"] = "test-key"
186
+ mock_response = {"id": "v_1", "name": "valset-2026-11-02"}
187
+ with mock.patch("sys.argv", ["cmpnd", "valsets", "show", "v_1"]):
188
+ with mock.patch.dict(os.environ, env, clear=True):
189
+ with mock.patch("cmpnd.cli.api_client.ApiClient.get", autospec=True, return_value=mock_response) as get:
190
+ main()
191
+ assert get.call_args.args[1] == "/api/v1/valsets/v_1"
192
+ assert json.loads(capsys.readouterr().out) == mock_response
193
+
172
194
 
173
195
  class TestAdminGate:
174
196
  """CMP-126: `admin` commands gated behind CMPND_CLI_ADMIN=1; the
@@ -16,7 +16,6 @@ from __future__ import annotations
16
16
 
17
17
  import argparse
18
18
  import itertools
19
- import os
20
19
  import re
21
20
  from pathlib import Path
22
21
  from unittest import mock
@@ -26,6 +25,9 @@ from cmpnd.cli.api_client import ApiClient
26
25
  from cmpnd.cli.commands import (
27
26
  admin as _admin,
28
27
  )
28
+ from cmpnd.cli.commands import (
29
+ assessments as _assessments,
30
+ )
29
31
  from cmpnd.cli.commands import (
30
32
  auth as _auth,
31
33
  )
@@ -59,6 +61,9 @@ from cmpnd.cli.commands import (
59
61
  from cmpnd.cli.commands import (
60
62
  traces as _traces,
61
63
  )
64
+ from cmpnd.cli.commands import (
65
+ valsets as _valsets,
66
+ )
62
67
 
63
68
  #: Every module registering a resource-tier noun group. `login` is excluded
64
69
  #: deliberately: `login` / `logout` are task-tier top-level commands with no
@@ -75,6 +80,8 @@ _RESOURCE_MODULES = (
75
80
  _evals,
76
81
  _datasets,
77
82
  _deployments,
83
+ _assessments,
84
+ _valsets,
78
85
  )
79
86
 
80
87
 
@@ -281,10 +288,8 @@ class TestOptimizeBinding:
281
288
  partial revival (CLI but not REPL) is the failure worth catching."""
282
289
 
283
290
  def test_optimize_is_bound_on_both_surfaces(self):
284
- env = {k: v for k, v in os.environ.items() if k != "CMPND_CLI_DEV"}
285
- with mock.patch.dict(os.environ, env, clear=True):
286
- assert "optimize" in _argparse_subcommands()
287
- assert "optimize" in _shell_namespace()
291
+ assert "optimize" in _argparse_subcommands()
292
+ assert "optimize" in _shell_namespace()
288
293
 
289
294
 
290
295
  class TestResourceVocabulary:
@@ -327,11 +327,11 @@ class TestMisuseGuard:
327
327
  sdk5.run_program(a_program(), question="What is the capital of France?")
328
328
 
329
329
 
330
- class TestDevelopmentGate:
331
- """The client's tracing needs no flag. Its assessment and valset calls are in
332
- development, gated behind CMPND_CLI_DEV=1 as their CLI groups are."""
330
+ class TestAssessmentsAndValsetsNeedNoFlag:
331
+ """The client's assessment and valset calls need no environment flag. A closed
332
+ client still refuses each one, as it refuses every other call."""
333
333
 
334
- GATED = {
334
+ CALLS = {
335
335
  "create_assessment": ("t_1",),
336
336
  "list_assessments": ("p_0123456789Ab",),
337
337
  "get_assessment": ("a_1",),
@@ -344,23 +344,19 @@ class TestDevelopmentGate:
344
344
  "delete_valset_entry": ("e_1",),
345
345
  }
346
346
 
347
- def test_construction_needs_no_flag(self, monkeypatch: pytest.MonkeyPatch):
348
- monkeypatch.delenv("CMPND_CLI_DEV", raising=False)
349
- sdk = cmpnd.Client(project_tags=["context-Z"], api_key="k", endpoint="http://x")
350
- assert sdk._active
351
-
352
- @pytest.mark.parametrize("method", sorted(GATED))
353
- def test_an_assessment_or_valset_call_refuses_without_the_flag(self, method, monkeypatch: pytest.MonkeyPatch):
347
+ @pytest.mark.parametrize("method", sorted(CALLS))
348
+ def test_a_closed_client_refuses_an_assessment_or_valset_call(self, method, monkeypatch: pytest.MonkeyPatch):
354
349
  monkeypatch.delenv("CMPND_CLI_DEV", raising=False)
355
350
  sdk = cmpnd.Client(api_key="k", endpoint="http://x")
351
+ sdk.close()
356
352
  kwargs = {"expected_outputs": {}} if method == "create_valset_entry" else {}
357
- with pytest.raises(RuntimeError, match=r"CMPND_CLI_DEV=1"):
358
- getattr(sdk, method)(*self.GATED[method], **kwargs)
353
+ with pytest.raises(RuntimeError, match=r"client is closed"):
354
+ getattr(sdk, method)(*self.CALLS[method], **kwargs)
359
355
 
360
- def test_every_assessment_and_valset_method_is_gated(self):
356
+ def test_every_assessment_and_valset_method_is_listed(self):
361
357
  public = {name for name in dir(cmpnd.Client) if not name.startswith("_")}
362
358
  data = {name for name in public if "assessment" in name or "valset" in name}
363
- assert data == set(self.GATED)
359
+ assert data == set(self.CALLS)
364
360
 
365
361
 
366
362
  # --- Case 7: exceptions and cleanup --------------------------------------
@@ -794,7 +790,7 @@ class TestClientDataSurface:
794
790
  client's own credentials, list_* unwrap to lists, and client.traces warns."""
795
791
 
796
792
  def _client(self, monkeypatch):
797
- monkeypatch.setenv("CMPND_CLI_DEV", "1")
793
+ monkeypatch.delenv("CMPND_CLI_DEV", raising=False)
798
794
  monkeypatch.setattr(cmpnd.client._exporter_pool, "flush", lambda cfg: None)
799
795
  return cmpnd.Client(api_key="k", endpoint="http://x")
800
796
 
@@ -811,6 +807,21 @@ class TestClientDataSurface:
811
807
  assert seen["trace_id"] == "t-1" and seen["conclusion"] == "down"
812
808
  assert seen["api_key"] == "k" and seen["endpoint"] == "http://x"
813
809
 
810
+ @pytest.mark.parametrize(
811
+ ("method", "module", "function", "ref"),
812
+ [
813
+ ("get_assessment", "_assessments", "get", "as_1"),
814
+ ("get_valset", "_valsets", "get", "v_1"),
815
+ ("delete_valset_entry", "_valsets", "delete_entry", "e_1"),
816
+ ],
817
+ )
818
+ def test_a_one_id_call_delegates_with_client_creds(self, method, module, function, ref, monkeypatch):
819
+ fake = mock.create_autospec(getattr(getattr(cmpnd, module), function), return_value={"id": ref})
820
+ monkeypatch.setattr(getattr(cmpnd, module), function, fake)
821
+
822
+ assert getattr(self._client(monkeypatch), method)(ref) == {"id": ref}
823
+ fake.assert_called_once_with(ref, api_key="k", endpoint="http://x")
824
+
814
825
  def test_get_deployment_signature_delegates_with_client_creds(self, monkeypatch):
815
826
  seen: dict = {}
816
827
  answer = object()
@@ -126,7 +126,6 @@ def _provider():
126
126
 
127
127
  @pytest.fixture(autouse=True)
128
128
  def _clean_slate(monkeypatch: pytest.MonkeyPatch):
129
- monkeypatch.delenv("CMPND_CLI_DEV", raising=False) # a client traces with no dev flag
130
129
  monkeypatch.delenv("CMPND_PROGRAM_ID", raising=False)
131
130
  configuration._config = None
132
131
  saved_callbacks = list(dspy.settings.callbacks or [])
@@ -328,7 +327,6 @@ def minting_server(monkeypatch: pytest.MonkeyPatch):
328
327
  def _new_client(**kw: Any) -> httpx.Client:
329
328
  return real_new_client(transport=httpx.MockTransport(srv.handler), **kw)
330
329
 
331
- monkeypatch.setenv("CMPND_CLI_DEV", "1")
332
330
  with (
333
331
  mock.patch("cmpnd._http.new_client", autospec=True, side_effect=_new_client),
334
332
  mock.patch("cmpnd.exporter_http.BatchExporter", autospec=True, side_effect=_factory),
@@ -505,3 +505,71 @@ def test_failure_summary_names_code_message_and_provider_status():
505
505
  f"Deployment run {RUN_ID} failed: EgressFailed: provider failed (provider status 429)"
506
506
  )
507
507
  assert deployment_runs.failure_summary(_run("failed", {"error": "boom"})) == f"Deployment run {RUN_ID} failed: boom"
508
+
509
+
510
+ TRACE_ID = "0b9c6f2e-4f1d-4c3a-9e2b-7a1d5c3e8f00"
511
+
512
+
513
+ def test_a_completed_run_names_its_trace_beside_its_run_id(monkeypatch: pytest.MonkeyPatch):
514
+ def answer(req: httpx.Request) -> httpx.Response:
515
+ body = {**_run("completed", {"output": {"answer": "yes"}}, available=True), "trace_id": TRACE_ID}
516
+ return httpx.Response(200, json=body, request=req)
517
+
518
+ _transport(monkeypatch, answer)
519
+ prediction = _client().run_deployment(DEPLOYMENT_ID, question="hi")
520
+ assert prediction.answer == "yes"
521
+ assert _client().get_trace_id(prediction) == TRACE_ID
522
+ assert _client().deployment_run_id(prediction) == RUN_ID
523
+ assert "trace_id" not in prediction.keys()
524
+
525
+
526
+ def test_a_failed_run_names_its_trace_on_the_raised_error(monkeypatch: pytest.MonkeyPatch):
527
+ failure = {"error": {"type": "ProgramError", "message": "bad input"}, "execution_status": 500}
528
+
529
+ def answer(req: httpx.Request) -> httpx.Response:
530
+ return httpx.Response(200, json={**_run("failed", failure, available=True), "trace_id": TRACE_ID}, request=req)
531
+
532
+ _transport(monkeypatch, answer)
533
+ with pytest.raises(httpx.HTTPStatusError) as caught:
534
+ _client().run_deployment(DEPLOYMENT_ID)
535
+ assert _client().get_trace_id(caught.value) == TRACE_ID
536
+ assert _client().deployment_run_id(caught.value) == RUN_ID
537
+
538
+
539
+ def test_a_retryable_provider_failure_names_its_trace(monkeypatch: pytest.MonkeyPatch):
540
+ failure = {
541
+ "error": {"type": "EgressFailed", "message": "provider refused"},
542
+ "execution_status": 503,
543
+ "retryable": True,
544
+ "failure": {"domain": "provider", "upstream_status": 429, "attempts": 3},
545
+ }
546
+
547
+ def answer(req: httpx.Request) -> httpx.Response:
548
+ return httpx.Response(200, json={**_run("failed", failure, available=True), "trace_id": TRACE_ID}, request=req)
549
+
550
+ _transport(monkeypatch, answer)
551
+ with pytest.raises(cmpnd.RetryableProviderError) as caught:
552
+ _client().run_deployment(DEPLOYMENT_ID)
553
+ assert _client().get_trace_id(caught.value) == TRACE_ID
554
+
555
+
556
+ @pytest.mark.parametrize("trace_field", [{}, {"trace_id": None}, {"trace_id": ""}, {"trace_id": 7}])
557
+ def test_a_run_serve_names_no_trace_for_has_none(monkeypatch: pytest.MonkeyPatch, trace_field: dict):
558
+ def answer(req: httpx.Request) -> httpx.Response:
559
+ body = {**_run("completed", {"output": {"answer": "yes"}}, available=True), **trace_field}
560
+ return httpx.Response(200, json=body, request=req)
561
+
562
+ _transport(monkeypatch, answer)
563
+ prediction = _client().run_deployment(DEPLOYMENT_ID, question="hi")
564
+ assert _client().get_trace_id(prediction) is None
565
+
566
+
567
+ def test_a_failure_before_acceptance_has_no_trace(monkeypatch: pytest.MonkeyPatch):
568
+ def answer(req: httpx.Request) -> httpx.Response:
569
+ return httpx.Response(404, json={"error": "not found"}, request=req)
570
+
571
+ _transport(monkeypatch, answer)
572
+ with pytest.raises(httpx.HTTPStatusError) as caught:
573
+ _client().run_deployment(DEPLOYMENT_ID)
574
+ assert _client().get_trace_id(caught.value) is None
575
+ assert _client().get_trace_id(object()) is None
@@ -44,7 +44,6 @@ def _clean_configuration(monkeypatch):
44
44
  monkeypatch.delenv("CMPND_PROGRAM_ID", raising=False)
45
45
  monkeypatch.delenv("CMPND_API_KEY", raising=False)
46
46
  monkeypatch.delenv("CMPND_ENDPOINT", raising=False)
47
- monkeypatch.delenv("CMPND_CLI_DEV", raising=False) # a client traces with no dev flag
48
47
  dspy.settings.configure(lm=None)
49
48
  yield
50
49
  configuration._config = None
@@ -505,7 +505,7 @@ wheels = [
505
505
 
506
506
  [[package]]
507
507
  name = "cmpnd"
508
- version = "0.70.0"
508
+ version = "0.72.0"
509
509
  source = { editable = "." }
510
510
  default-groups = ["dspy-3-4-1"]
511
511
  dependencies = [
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes