cmpnd 0.51.0__tar.gz → 0.53.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 (383) hide show
  1. {cmpnd-0.51.0 → cmpnd-0.53.0}/PKG-INFO +196 -90
  2. {cmpnd-0.51.0 → cmpnd-0.53.0}/README.md +195 -89
  3. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/__init__.py +1 -1
  4. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/callback.py +14 -6
  5. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/cli/__init__.py +1 -2
  6. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/cli/commands/programs.py +21 -24
  7. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/cli/commands/top.py +39 -41
  8. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/cli/shell.py +10 -13
  9. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/client.py +63 -44
  10. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/configuration.py +34 -9
  11. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/deployment.py +50 -29
  12. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/identity.py +34 -4
  13. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/named_programs.py +25 -1
  14. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/optimization.py +34 -20
  15. cmpnd-0.53.0/cmpnd/programs.py +57 -0
  16. {cmpnd-0.51.0 → cmpnd-0.53.0}/docs/cli.md +4 -16
  17. {cmpnd-0.51.0 → cmpnd-0.53.0}/docs/client.md +27 -15
  18. {cmpnd-0.51.0 → cmpnd-0.53.0}/docs/sdk-instrumentation.md +33 -21
  19. {cmpnd-0.51.0 → cmpnd-0.53.0}/pyproject.toml +1 -1
  20. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/e2e/committee_task.py +3 -3
  21. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/e2e/helpers.py +41 -8
  22. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/e2e/test_deploy_execute.py +21 -13
  23. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/e2e/test_deploy_pandas.py +2 -2
  24. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/e2e/test_deploy_programs.py +7 -5
  25. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/e2e/test_optimize_failures.py +2 -4
  26. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/e2e/test_optimize_loop.py +16 -13
  27. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/e2e/test_optimize_server_owned_completion.py +6 -5
  28. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/e2e/test_user_attribution.py +4 -1
  29. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/e2e/test_valsets_cli.py +2 -1
  30. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/integration/hosted_mcp_tool_optimize_probe.py +6 -6
  31. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/integration/hosted_optimize_probe.py +4 -3
  32. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/stress/test_deploy_programs.py +2 -1
  33. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/stress/test_optimize_loop.py +2 -3
  34. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/stress/test_optimize_loop_wasm.py +4 -6
  35. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/stress/test_optimize_stress.py +10 -7
  36. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/stress/test_real_provider_twins.py +2 -3
  37. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/stress/test_rlm_wasm.py +3 -2
  38. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_authored_optimize.py +1 -1
  39. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_cli/test_shell.py +4 -4
  40. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_cli/test_top.py +37 -32
  41. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_client.py +46 -29
  42. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_client_program_names.py +98 -29
  43. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_deploy.py +2 -2
  44. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_deploy_mcp_tool_references.py +1 -1
  45. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_deploy_program_id.py +21 -21
  46. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_execute_run_identity.py +3 -2
  47. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_optimize.py +4 -2
  48. cmpnd-0.53.0/tests/test_program_id_deprecation.py +308 -0
  49. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_program_identity.py +25 -23
  50. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_program_names_in_deploy.py +35 -44
  51. cmpnd-0.53.0/tests/test_programs_create.py +95 -0
  52. {cmpnd-0.51.0 → cmpnd-0.53.0}/uv.lock +161 -120
  53. cmpnd-0.51.0/cmpnd/programs.py +0 -135
  54. cmpnd-0.51.0/tests/test_programs_create.py +0 -127
  55. {cmpnd-0.51.0 → cmpnd-0.53.0}/.gitignore +0 -0
  56. {cmpnd-0.51.0 → cmpnd-0.53.0}/AGENTS.md +0 -0
  57. {cmpnd-0.51.0 → cmpnd-0.53.0}/CLAUDE.md +0 -0
  58. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/_assessments.py +0 -0
  59. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/_authored_import.py +0 -0
  60. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/_deployments.py +0 -0
  61. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/_exporter_pool.py +0 -0
  62. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/_gepa_patch.py +0 -0
  63. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/_http.py +0 -0
  64. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/_program_patch.py +0 -0
  65. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/_rlm_patch.py +0 -0
  66. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/_runtime_tools.py +0 -0
  67. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/_timespec.py +0 -0
  68. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/_traces.py +0 -0
  69. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/_valsets.py +0 -0
  70. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/authored.py +0 -0
  71. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/cli/api_client.py +0 -0
  72. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/cli/commands/__init__.py +0 -0
  73. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/cli/commands/admin.py +0 -0
  74. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/cli/commands/assessments.py +0 -0
  75. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/cli/commands/auth.py +0 -0
  76. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/cli/commands/datasets.py +0 -0
  77. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/cli/commands/deployments.py +0 -0
  78. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/cli/commands/evals.py +0 -0
  79. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/cli/commands/login.py +0 -0
  80. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/cli/commands/optimizations.py +0 -0
  81. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/cli/commands/org.py +0 -0
  82. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/cli/commands/provider_credentials.py +0 -0
  83. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/cli/commands/signatures.py +0 -0
  84. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/cli/commands/tool_servers.py +0 -0
  85. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/cli/commands/traces.py +0 -0
  86. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/cli/commands/valsets.py +0 -0
  87. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/cli/credentials.py +0 -0
  88. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/cli/deprecation.py +0 -0
  89. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/cli/pagination.py +0 -0
  90. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/cli/trace_render.py +0 -0
  91. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/cli/tree_help.py +0 -0
  92. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/cli/verbs.py +0 -0
  93. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/context.py +0 -0
  94. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/dataset_sync.py +0 -0
  95. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/datasets.py +0 -0
  96. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/decorators.py +0 -0
  97. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/deployment_metadata.py +0 -0
  98. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/deployment_runs.py +0 -0
  99. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/eval_handler.py +0 -0
  100. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/execution.py +0 -0
  101. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/exporter.py +0 -0
  102. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/exporter_http.py +0 -0
  103. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/helpers.py +0 -0
  104. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/imaging.py +0 -0
  105. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/ir/__init__.py +0 -0
  106. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/ir/decode.py +0 -0
  107. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/ir/encode.py +0 -0
  108. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/ir/hash.py +0 -0
  109. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/ir/program.py +0 -0
  110. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/ir/reflection.py +0 -0
  111. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/ir/types.py +0 -0
  112. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/ir/xxh64.py +0 -0
  113. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/lm_configuration.py +0 -0
  114. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/mcp_servers.py +0 -0
  115. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/models.py +0 -0
  116. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/optimizers/__init__.py +0 -0
  117. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/optimizers/gepa.py +0 -0
  118. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/optimizers/gepa_callback.py +0 -0
  119. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/optimizers/resume.py +0 -0
  120. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/optimizers/tracker.py +0 -0
  121. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/packaging.py +0 -0
  122. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/references.py +0 -0
  123. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/retry.py +0 -0
  124. {cmpnd-0.51.0 → cmpnd-0.53.0}/cmpnd/traces.py +0 -0
  125. {cmpnd-0.51.0 → cmpnd-0.53.0}/docs/2026-04-02-code-review.md +0 -0
  126. {cmpnd-0.51.0 → cmpnd-0.53.0}/docs/custom-proposer.md +0 -0
  127. {cmpnd-0.51.0 → cmpnd-0.53.0}/docs/plans/2026-04-05-train-val-dataset-capture-design.md +0 -0
  128. {cmpnd-0.51.0 → cmpnd-0.53.0}/docs/plans/2026-04-05-train-val-dataset-capture.md +0 -0
  129. {cmpnd-0.51.0 → cmpnd-0.53.0}/docs/reading-traces.md +0 -0
  130. {cmpnd-0.51.0 → cmpnd-0.53.0}/examples/generalizing_proposer.py +0 -0
  131. {cmpnd-0.51.0 → cmpnd-0.53.0}/examples/local_ollama.py +0 -0
  132. {cmpnd-0.51.0 → cmpnd-0.53.0}/ingest/LINEAGE.md +0 -0
  133. {cmpnd-0.51.0 → cmpnd-0.53.0}/ingest/README.md +0 -0
  134. {cmpnd-0.51.0 → cmpnd-0.53.0}/ingest/cmpnd_ingest/__init__.py +0 -0
  135. {cmpnd-0.51.0 → cmpnd-0.53.0}/ingest/cmpnd_ingest/bodies.py +0 -0
  136. {cmpnd-0.51.0 → cmpnd-0.53.0}/ingest/cmpnd_ingest/client_floor.py +0 -0
  137. {cmpnd-0.51.0 → cmpnd-0.53.0}/ingest/cmpnd_ingest/exporter_http.py +0 -0
  138. {cmpnd-0.51.0 → cmpnd-0.53.0}/ingest/cmpnd_ingest/program_names.py +0 -0
  139. {cmpnd-0.51.0 → cmpnd-0.53.0}/ingest/cmpnd_ingest/protocols.py +0 -0
  140. {cmpnd-0.51.0 → cmpnd-0.53.0}/ingest/cmpnd_ingest/py.typed +0 -0
  141. {cmpnd-0.51.0 → cmpnd-0.53.0}/ingest/cmpnd_ingest/request_log.py +0 -0
  142. {cmpnd-0.51.0 → cmpnd-0.53.0}/ingest/cmpnd_ingest/retry.py +0 -0
  143. {cmpnd-0.51.0 → cmpnd-0.53.0}/ingest/cmpnd_ingest/trace_facts.py +0 -0
  144. {cmpnd-0.51.0 → cmpnd-0.53.0}/ingest/pyproject.toml +0 -0
  145. {cmpnd-0.51.0 → cmpnd-0.53.0}/scripts/audit-sdist.sh +0 -0
  146. {cmpnd-0.51.0 → cmpnd-0.53.0}/scripts/capture_review_run.py +0 -0
  147. {cmpnd-0.51.0 → cmpnd-0.53.0}/scripts/check-pip-install.sh +0 -0
  148. {cmpnd-0.51.0 → cmpnd-0.53.0}/scripts/check_release_artifacts.py +0 -0
  149. {cmpnd-0.51.0 → cmpnd-0.53.0}/scripts/fixtures/review_run.json.gz +0 -0
  150. {cmpnd-0.51.0 → cmpnd-0.53.0}/scripts/gepa_resume_bug.py +0 -0
  151. {cmpnd-0.51.0 → cmpnd-0.53.0}/scripts/release-stress.sh +0 -0
  152. {cmpnd-0.51.0 → cmpnd-0.53.0}/scripts/require_version_bump.py +0 -0
  153. {cmpnd-0.51.0 → cmpnd-0.53.0}/scripts/seed_review_run.py +0 -0
  154. {cmpnd-0.51.0 → cmpnd-0.53.0}/scripts/test-in-linux.sh +0 -0
  155. {cmpnd-0.51.0 → cmpnd-0.53.0}/stubs/dspy/__init__.pyi +0 -0
  156. {cmpnd-0.51.0 → cmpnd-0.53.0}/stubs/dspy/primitives/__init__.pyi +0 -0
  157. {cmpnd-0.51.0 → cmpnd-0.53.0}/stubs/dspy/primitives/prediction.pyi +0 -0
  158. {cmpnd-0.51.0 → cmpnd-0.53.0}/stubs/dspy/utils/__init__.pyi +0 -0
  159. {cmpnd-0.51.0 → cmpnd-0.53.0}/stubs/dspy/utils/callback.pyi +0 -0
  160. {cmpnd-0.51.0 → cmpnd-0.53.0}/stubs/dspy/utils/dummies.pyi +0 -0
  161. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/__init__.py +0 -0
  162. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/_deployment_signature_helpers.py +0 -0
  163. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/_exporter_helpers.py +0 -0
  164. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/_fake_clock.py +0 -0
  165. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/_identity_helpers.py +0 -0
  166. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/_resolve_refs.py +0 -0
  167. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/_traced_run.py +0 -0
  168. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/conftest.py +0 -0
  169. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/e2e/__init__.py +0 -0
  170. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/e2e/conftest.py +0 -0
  171. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/e2e/data/committee_train.ndjson.gz +0 -0
  172. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/e2e/data/committee_val.ndjson.gz +0 -0
  173. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/e2e/fake_lm.py +0 -0
  174. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/e2e/target_capabilities.py +0 -0
  175. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/e2e/test_assessments_cli.py +0 -0
  176. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/e2e/test_capture_prompts.py +0 -0
  177. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/e2e/test_composite_module.py +0 -0
  178. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/e2e/test_dataset_auto_creation.py +0 -0
  179. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/e2e/test_edge_cases.py +0 -0
  180. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/e2e/test_example_hash.py +0 -0
  181. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/e2e/test_gepa_optimization.py +0 -0
  182. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/e2e/test_interpreter_spans.py +0 -0
  183. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/e2e/test_lm_accuracy.py +0 -0
  184. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/e2e/test_module_tracing.py +0 -0
  185. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/e2e/test_optimization_lineage.py +0 -0
  186. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/e2e/test_optimization_metric_identity.py +0 -0
  187. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/e2e/test_optimize_review_committee.py +0 -0
  188. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/e2e/test_parallel_export.py +0 -0
  189. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/e2e/test_project_attribution.py +0 -0
  190. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/e2e/test_react_tool_spans.py +0 -0
  191. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/e2e/test_save_load.py +0 -0
  192. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/e2e/test_trace_structure.py +0 -0
  193. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/e2e/test_traces_read.py +0 -0
  194. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/identity_vectors/01_predict_qa.json +0 -0
  195. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/identity_vectors/02_predict_renamed_field.json +0 -0
  196. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/identity_vectors/03_chain_of_thought_qa.json +0 -0
  197. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/identity_vectors/04_predict_richer_types.json +0 -0
  198. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/identity_vectors/05_composite_two_predicts.json +0 -0
  199. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/identity_vectors/06_multichaincomparison.json +0 -0
  200. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/identity_vectors/07_program_of_thought.json +0 -0
  201. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/identity_vectors/08_opaque_module.json +0 -0
  202. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/identity_vectors/09_predict_pydantic_field.json +0 -0
  203. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/identity_vectors/10_react.json +0 -0
  204. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/identity_vectors/11_refine.json +0 -0
  205. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/identity_vectors/12_retrieve.json +0 -0
  206. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/identity_vectors/13_knn.json +0 -0
  207. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/identity_vectors/14_parallel.json +0 -0
  208. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/identity_vectors/README.md +0 -0
  209. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/ingest_conformance.py +0 -0
  210. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/integration/__init__.py +0 -0
  211. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/integration/authored_optimize/judge.py +0 -0
  212. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/integration/authored_optimize/optimize_hosted.py +0 -0
  213. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/integration/conftest.py +0 -0
  214. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/integration/optimization_run_probe.py +0 -0
  215. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/integration/test_cli_deploy_smoketest.py +0 -0
  216. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/integration/test_logs_renders_traces.py +0 -0
  217. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/integration/test_optimization_run.py +0 -0
  218. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/integration/test_optimizing_progress.py +0 -0
  219. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/integration/test_unhappy_path.py +0 -0
  220. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/load/__init__.py +0 -0
  221. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/load/__main__.py +0 -0
  222. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/load/drain.py +0 -0
  223. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/load/ingest.py +0 -0
  224. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/load/latency_transport.py +0 -0
  225. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/load/rlm_shape.py +0 -0
  226. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/load/rlm_size_report.py +0 -0
  227. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/load/sweep.py +0 -0
  228. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/load/test_rlm_shape.py +0 -0
  229. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/load/test_rlm_size_report.py +0 -0
  230. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/parity/__init__.py +0 -0
  231. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/parity/conftest.py +0 -0
  232. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/parity/seed_parity.py +0 -0
  233. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/parity/test_auth.py +0 -0
  234. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/parity/test_datasets.py +0 -0
  235. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/parity/test_deployments.py +0 -0
  236. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/parity/test_evals.py +0 -0
  237. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/parity/test_health.py +0 -0
  238. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/parity/test_modules.py +0 -0
  239. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/parity/test_optimizations.py +0 -0
  240. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/parity/test_programs.py +0 -0
  241. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/parity/test_signatures.py +0 -0
  242. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/parity/test_trace_streaming.py +0 -0
  243. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/parity/test_traces.py +0 -0
  244. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/span_reference_fixture.py +0 -0
  245. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/stress/__init__.py +0 -0
  246. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/stress/_provider.py +0 -0
  247. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/stress/_readiness.py +0 -0
  248. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/stress/_reliability.py +0 -0
  249. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/stress/_result.py +0 -0
  250. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/stress/mint_bedrock_token.py +0 -0
  251. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/stress/test_multi_client_stress.py +0 -0
  252. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/stress/test_optimize_client_committee.py +0 -0
  253. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/stress/test_provider_roles.py +0 -0
  254. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/stress/test_readiness.py +0 -0
  255. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/stress/test_reliability.py +0 -0
  256. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/stress/test_reliability_classify.py +0 -0
  257. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/stress/test_trace_search.py +0 -0
  258. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_adapter_reentrancy.py +0 -0
  259. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_assessments_api.py +0 -0
  260. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_authored.py +0 -0
  261. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_authored_bundle_collisions.py +0 -0
  262. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_authored_metric_contract.py +0 -0
  263. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_authored_named_models.py +0 -0
  264. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_callback.py +0 -0
  265. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_candidate_lineage.py +0 -0
  266. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_cli/__init__.py +0 -0
  267. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_cli/conftest.py +0 -0
  268. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_cli/test_admin.py +0 -0
  269. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_cli/test_api_client.py +0 -0
  270. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_cli/test_assessments.py +0 -0
  271. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_cli/test_auth.py +0 -0
  272. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_cli/test_credentials.py +0 -0
  273. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_cli/test_datasets.py +0 -0
  274. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_cli/test_deployment_runs.py +0 -0
  275. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_cli/test_deployments.py +0 -0
  276. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_cli/test_evals.py +0 -0
  277. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_cli/test_login.py +0 -0
  278. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_cli/test_main.py +0 -0
  279. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_cli/test_optimizations.py +0 -0
  280. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_cli/test_org.py +0 -0
  281. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_cli/test_pagination.py +0 -0
  282. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_cli/test_parity.py +0 -0
  283. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_cli/test_programs.py +0 -0
  284. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_cli/test_provider_credentials.py +0 -0
  285. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_cli/test_schema_sample.py +0 -0
  286. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_cli/test_signatures.py +0 -0
  287. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_cli/test_tool_servers.py +0 -0
  288. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_cli/test_traces.py +0 -0
  289. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_cli/test_traces_search_wire.py +0 -0
  290. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_cli/test_tree_help.py +0 -0
  291. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_cli/test_valsets.py +0 -0
  292. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_client_floor.py +0 -0
  293. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_clustering/__init__.py +0 -0
  294. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_clustering/conftest.py +0 -0
  295. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_clustering/test_edge_cases.py +0 -0
  296. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_clustering/test_hash_consistency.py +0 -0
  297. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_clustering/test_type_conversion.py +0 -0
  298. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_cmp551_grouping_identity.py +0 -0
  299. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_configuration.py +0 -0
  300. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_context.py +0 -0
  301. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_context_propagation.py +0 -0
  302. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_dataset_polling.py +0 -0
  303. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_dataset_sync.py +0 -0
  304. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_datasets.py +0 -0
  305. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_decision_client_spans.py +0 -0
  306. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_decorators.py +0 -0
  307. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_deployment_metadata.py +0 -0
  308. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_deployment_runs.py +0 -0
  309. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_deployments_read.py +0 -0
  310. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_eval.py +0 -0
  311. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_eval_example_attribution.py +0 -0
  312. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_eval_start.py +0 -0
  313. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_eval_trace_grouping.py +0 -0
  314. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_exception_paths.py +0 -0
  315. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_execute.py +0 -0
  316. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_exporter.py +0 -0
  317. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_exporter_program_names.py +0 -0
  318. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_exporter_queue.py +0 -0
  319. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_exporter_real.py +0 -0
  320. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_fake_lm.py +0 -0
  321. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_gepa_callback.py +0 -0
  322. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_gepa_integration.py +0 -0
  323. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_gepa_output_normalization.py +0 -0
  324. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_gepa_resume.py +0 -0
  325. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_identity.py +0 -0
  326. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_imaging.py +0 -0
  327. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_import_weight.py +0 -0
  328. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_ingest_conformance.py +0 -0
  329. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_ingest_second_producer.py +0 -0
  330. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_integration.py +0 -0
  331. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_interpreter_callback.py +0 -0
  332. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_ir_encoder_properties.py +0 -0
  333. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_ir_golden_vectors.py +0 -0
  334. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_ir_roundtrip.py +0 -0
  335. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_lm15_native_calls.py +0 -0
  336. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_lm_configuration.py +0 -0
  337. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_lm_usage_shapes.py +0 -0
  338. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_mcp_tools.py +0 -0
  339. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_models.py +0 -0
  340. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_multi_client_stress_readiness.py +0 -0
  341. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_optimization_progress.py +0 -0
  342. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_optimization_start.py +0 -0
  343. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_optimize_budget.py +0 -0
  344. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_optimize_lift.py +0 -0
  345. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_optimize_lms.py +0 -0
  346. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_optimize_proposer.py +0 -0
  347. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_optimize_reflection_lm.py +0 -0
  348. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_optimize_terminal_failure.py +0 -0
  349. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_packaging.py +0 -0
  350. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_packaging_callable_source.py +0 -0
  351. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_packaging_mcp_tools.py +0 -0
  352. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_packaging_program_source.py +0 -0
  353. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_poll_until.py +0 -0
  354. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_program_lineage_persist.py +0 -0
  355. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_project_payload.py +0 -0
  356. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_real_provider_twins_readiness.py +0 -0
  357. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_reflector_properties.py +0 -0
  358. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_reflector_smoke.py +0 -0
  359. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_release_stress_script.py +0 -0
  360. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_repro_reactv2_bugs.py +0 -0
  361. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_require_version_bump.py +0 -0
  362. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_retry.py +0 -0
  363. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_reversible_failures.py +0 -0
  364. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_rlm_patch.py +0 -0
  365. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_run_attribution_paths.py +0 -0
  366. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_runtime_tools.py +0 -0
  367. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_schemas.py +0 -0
  368. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_seed_review_run.py +0 -0
  369. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_signature_inputs.py +0 -0
  370. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_span_references.py +0 -0
  371. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_span_sent_once.py +0 -0
  372. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_system_one.py +0 -0
  373. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_trace_context_concurrency.py +0 -0
  374. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_trace_fact_wire_contract.py +0 -0
  375. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_trace_facts.py +0 -0
  376. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_trace_render.py +0 -0
  377. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_traces_read.py +0 -0
  378. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_tracked_gepa.py +0 -0
  379. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_tracker_enrich.py +0 -0
  380. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_truncation.py +0 -0
  381. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_upload_auth_headers.py +0 -0
  382. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_valsets_api.py +0 -0
  383. {cmpnd-0.51.0 → cmpnd-0.53.0}/tests/test_xxh64.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: cmpnd
3
- Version: 0.51.0
3
+ Version: 0.53.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>
@@ -60,8 +60,20 @@ cmpnd platform. One call turns on tracing, and one more deploys a program.
60
60
  uv add cmpnd # or: pip install cmpnd
61
61
  ```
62
62
 
63
+ ## Authentication
64
+
65
+ The `cmpnd` library works with the cmpnd service at
66
+ [platform.cmpnd.ai](https://platform.cmpnd.ai). Create an API key on the
67
+ platform under Settings → API keys, and pass it as `api_key=` to
68
+ `cmpnd.configure()` or `cmpnd.Client()`. For a self-hosted cmpnd install, also
69
+ pass the install's URL as `endpoint=`.
70
+
63
71
  ## Quick start
64
72
 
73
+ `cmpnd.auto_instrument()` records a trace of every DSPy call in the process.
74
+ Your code needs no other change. Use it to sketch a [DSPy program](https://dspy.ai/) and see what it
75
+ does.
76
+
65
77
  ```python
66
78
  import cmpnd
67
79
  import dspy
@@ -78,109 +90,137 @@ cmpnd.trace_id(result) # "a1b2c3d4-...", or None outside instrumentation
78
90
  ```
79
91
 
80
92
  `cmpnd.trace_id()` links a result to its platform trace, for example to attach
81
- feedback later.
93
+ feedback later. Traces recorded this way have no program name. The platform
94
+ groups them by the structure of the program's modules. The API reference
95
+ below lists the other options of `cmpnd.configure()`.
82
96
 
83
- ## Configuration
97
+ ## Program names
84
98
 
85
- `cmpnd.configure()` reads `CMPND_API_KEY` and `CMPND_ENDPOINT` when you pass
86
- no arguments. The endpoint defaults to `https://platform.cmpnd.ai`.
99
+ When you’re ready to name programs, evolve them, and share them with your team, switch
100
+ to `cmpnd.Client`. A client replaces `configure()` and `auto_instrument()` and offers
101
+ more features. A client records only the programs you run through it, and each of
102
+ those programs has a program name. A client takes most of the same arguments as `configure()`.
87
103
 
88
- ```bash
89
- export CMPND_API_KEY="ck_your_api_key"
90
- export CMPND_ENDPOINT="https://platform.cmpnd.ai" # optional
91
- export CMPND_PROGRAM_ID="p_0123456789Ab" # optional: the program these traces belong to
104
+ A program name is the name your organization gives a program, such as `question-answerer`.
105
+ Traces, deployments and optimization runs under one program name go to one
106
+ program. The platform makes the program the first time your organization uses
107
+ the program name.
108
+
109
+ `@cmpnd.program(name)` above a `dspy.Module` class gives the class a program
110
+ name. Building the class takes its own arguments and a required `lm=`. The
111
+ `lm=` argument is the `dspy.LM` that the program runs on:
112
+
113
+ ```python
114
+ import cmpnd
115
+ import dspy
116
+
117
+ class Answer(dspy.Signature):
118
+ """Answer the question in one short sentence."""
119
+ question: str = dspy.InputField()
120
+ answer: str = dspy.OutputField()
121
+
122
+ @cmpnd.program("question-answerer")
123
+ class QA(dspy.Predict):
124
+ def __init__(self):
125
+ super().__init__(Answer)
126
+
127
+ qa1 = QA(lm=dspy.LM("openai/gpt-6-luna"))
92
128
  ```
93
129
 
130
+ A client runs the program and records its trace under the program name:
131
+
94
132
  ```python
95
- cmpnd.configure(
96
- api_key="ck_xxx", # required, or CMPND_API_KEY
97
- endpoint="https://platform.cmpnd.ai", # optional, or CMPND_ENDPOINT
98
- project_tags="my-project", # optional: one tag or a list of tags
99
- program_id="p_0123456789Ab", # optional, or CMPND_PROGRAM_ID: the id `cmpnd programs create` prints
100
- batch_size=100, # optional: spans per export batch
101
- flush_interval_seconds=5.0, # optional: seconds between flushes
102
- capture_inputs=True, # optional: record span inputs
103
- capture_outputs=True, # optional: record span outputs
104
- default_tags={"env": "prod"}, # optional: tags on every trace
105
- )
133
+ gepa = dspy.GEPA(metric=metric, reflection_lm=dspy.LM("openai/gpt-6-luna"), auto="light")
134
+
135
+ with cmpnd.Client(api_key="ck_xxx", project_tags="my-project") as sdk:
136
+ # the trace will go to the program "question-answerer"
137
+ result = sdk.run_program(qa1, question="What is DSPy?")
138
+ qa2 = sdk.run_optimization(gepa, qa1, trainset=train, valset=val)
106
139
  ```
107
140
 
108
- `project` is a deprecated alias for `project_tags`. Passing both raises
109
- `ValueError`. `CMPND_MAX_INPUT_SIZE` and `CMPND_MAX_OUTPUT_SIZE` set the
110
- captured input and output size limits, 65,536 bytes each by default.
141
+ A client is active from construction. The `with` form flushes the client's
142
+ traces and closes it on exit. Without `with`, the client stays active until
143
+ you call `close()` or the process exits, and its traces go out at exit:
144
+
145
+ ```python
146
+ sdk = cmpnd.Client(api_key="ck_xxx", project_tags="my-project")
147
+ sdk.run_program(qa2, question="What is DSPy?")
111
148
 
112
- ## Deployment
149
+ # optional: flushes the traces now, so a later read sees them
150
+ sdk.close()
151
+ ```
113
152
 
114
- Every deployment belongs to a program, and the platform issues each program
115
- an id. Create a program first. The command prints its id:
153
+ The `cmpnd.Program` constructor gives a program name to a module you already
154
+ have, such as a `dspy.Predict`. It makes the same kind of
155
+ program as the decorator:
116
156
 
117
- ```bash
118
- cmpnd programs create --name qa
157
+ ```python
158
+ qa3 = cmpnd.Program(
159
+ "question-answerer", module=dspy.Predict("question -> answer"), lm=dspy.LM("openai/gpt-6-luna")
160
+ )
119
161
  ```
120
162
 
121
- Then deploy a DSPy module under that program for server-side execution:
163
+ - A program name starts with an ASCII letter or digit, then has letters,
164
+ digits, `.`, `_` or `-`, at most 64 characters. It does not start with `p_`.
165
+ A bad name raises `ValueError`. Declaring a program makes no network call.
166
+ - `run_optimization` returns a copy of the program that holds the optimized
167
+ module. The copy keeps the program name and the LM.
168
+ - Calling a `cmpnd.Program` directly while `auto_instrument()` is on raises a
169
+ `TypeError` that points to `cmpnd.Client`.
170
+
171
+ ## Deployed programs
172
+
173
+ Every deployment belongs to a program, and each program has a program name.
174
+ Give a DSPy module a program name with `cmpnd.Program`, then deploy it for
175
+ server-side execution:
122
176
 
123
177
  ```python
124
178
  import cmpnd
125
179
  import dspy
126
180
 
127
- cmpnd.configure(api_key="ck_xxx", program_id="p_0123456789Ab")
128
- dspy.configure(lm=dspy.LM("openai/gpt-6-luna"))
181
+ cmpnd.configure(api_key="ck_xxx")
129
182
 
130
- module = dspy.Predict("question -> answer")
131
- deployed = cmpnd.deploy(module)
183
+ qa4 = cmpnd.Program(
184
+ "question-answerer", module=dspy.Predict("question -> answer"), lm=dspy.LM("openai/gpt-6-luna")
185
+ )
186
+ deployed = cmpnd.deploy(qa4)
132
187
 
133
188
  result = deployed(question="What is DSPy?") # runs server-side
134
189
  print(result.answer)
135
190
  ```
136
191
 
137
- `deploy()` packages the module's source into a ZIP, uploads it and polls until
138
- the server-side parser finishes. It then reads the deployment's persisted
139
- interface and returns a `DeployedProgram`. Call the program to execute it
192
+ `deploy()` packages the module's source, sends it to the platform and waits
193
+ until the platform has read it. It then returns a `DeployedProgram`. Call the program to execute it
140
194
  server-side. `str(deployed)` and `deployed.deployment_id` return the
141
195
  deployment ID. `deployed.artifact_metadata` holds the typed artifact record
142
196
  when the platform has inspected it. An unknown interface leaves `input_fields`
143
197
  and `output_fields` as `None`. A known interface with no fields returns empty
144
198
  lists.
145
199
 
146
- `cmpnd.deploy(module, program_id="p_…")` names the program for one call.
147
- Without a configured or passed id, `deploy` raises `ValueError` before it
148
- packages or sends anything.
149
-
150
- To deploy a source file, run `cmpnd deploy program.py --program-id p_…`, or
151
- set `CMPND_PROGRAM_ID`. The CLI uploads the file's exact bytes and does not
152
- reconstruct the source from a live object. Use `--source-root` and repeated
153
- `--include` flags for sibling modules or data, and `cmpnd inspect <id>
154
- --source` to read the deployed entry file back. [`docs/cli.md`](docs/cli.md)
155
- covers the CLI.
200
+ The platform makes the program the first time your organization uses the
201
+ program name. Later deploys under the same program name go to the same
202
+ program, and so do the traces of a client that runs it.
156
203
 
157
204
  ### Options
158
205
 
159
206
  ```python
160
207
  cmpnd.deploy(
161
- module, # required: a DSPy module
208
+ program, # required: a cmpnd.Program
162
209
  metric=None, # optional: a metric callable, packaged for optimization
163
- timeout=300, # optional: seconds to wait for the parser after the upload
210
+ timeout=300, # optional: seconds to wait for the deployment to be ready
164
211
  metadata=None, # optional: a JSON-serializable dict, at most 64 KiB, stored with the deployment
165
- program_id="p_…", # the program the deployment belongs to; serve requires it after self-host 2026-001
166
212
  )
167
213
  ```
168
214
 
169
215
  ### How it works
170
216
 
171
- 1. The SDK generates source from the live module, including its LM
172
- configuration, signature and types.
173
- 2. `POST /api/v1/deployments` creates the deployment and returns an upload
174
- URL.
175
- 3. The SDK uploads the source ZIP to that URL. The bytes go to the worker.
176
- 4. The worker's parser extracts the program and its LM configuration.
177
- 5. The SDK polls until the status is `ready`, reads the artifact metadata and
178
- returns the `DeployedProgram`.
179
-
180
- The parser reads the model string, such as `openai/gpt-6-luna`, and its
181
- sampling settings from the source.
217
+ 1. The SDK packages the module's source, including its LM configuration,
218
+ signature and types.
219
+ 2. The platform reads the program, the model string and the sampling settings
220
+ from that source.
221
+ 3. `deploy()` returns the `DeployedProgram` when the deployment is ready.
182
222
 
183
- ## Optimization
223
+ ## Optimization on the platform
184
224
 
185
225
  `cmpnd.optimize()` optimizes a program through the platform. Like `deploy()`,
186
226
  it returns a `DeployedProgram` that you call directly, and the program's
@@ -190,16 +230,18 @@ it returns a `DeployedProgram` that you call directly, and the program's
190
230
  import cmpnd
191
231
  import dspy
192
232
 
193
- cmpnd.configure(api_key="ck_xxx", program_id="p_0123456789Ab") # from `cmpnd programs create`
194
- dspy.configure(lm=dspy.LM("openai/gpt-6-luna"))
233
+ cmpnd.configure(api_key="ck_xxx")
195
234
 
196
- program = dspy.ChainOfThought("topic -> haiku")
235
+ program = cmpnd.Program(
236
+ "haiku", module=dspy.ChainOfThought("topic -> haiku"), lm=dspy.LM("openai/gpt-6-luna")
237
+ )
197
238
 
198
239
  # GEPA needs a five-argument feedback metric that returns dspy.Prediction(score=, feedback=)
199
240
  def metric(example, pred, trace=None, pred_name=None, pred_trace=None):
200
241
  ok = example.season.lower() not in pred.haiku.lower()
201
- return dspy.Prediction(score=float(ok),
202
- feedback=None if ok else "Don't name the season.")
242
+ return dspy.Prediction(
243
+ score=float(ok), feedback=None if ok else "Don't name the season."
244
+ )
203
245
 
204
246
  best = cmpnd.optimize(
205
247
  program,
@@ -233,7 +275,7 @@ warning.
233
275
 
234
276
  `gepa` is the only optimizer the platform runs. `optimize()` raises
235
277
  `ValueError` for the retired `bootstrap_fewshot` and `random_search` before
236
- any network call, and serve answers them with a 404 that names gepa.
278
+ any network call, and the platform answers them with a 404 that names gepa.
237
279
 
238
280
  ### A metric with its own model
239
281
 
@@ -269,7 +311,7 @@ rules:
269
311
  names.
270
312
  - `"default-lm"` is reserved for the program's own model, which comes from the
271
313
  deployment. Declaring it raises an error that names it.
272
- - Serve refuses a model your org holds no credential for when it dispatches
314
+ - The platform refuses a model your org holds no credential for when it dispatches
273
315
  the run, before the run starts. These LMs, like `reflection_lm`, must not set
274
316
  `api_key`, `api_base` or `base_url`.
275
317
 
@@ -277,9 +319,6 @@ The `lms` parameter does not change the arity check. Five or more positional
277
319
  arguments make a feedback metric, and a metric without `lms` never receives
278
320
  it.
279
321
 
280
- A run can also bring its own instruction proposer through `proposer`.
281
- [`docs/custom-proposer.md`](docs/custom-proposer.md) describes it.
282
-
283
322
  ### Reusing a deployment
284
323
 
285
324
  Pass the `deployment_id` of a ready deployment to skip the initial deploy:
@@ -300,8 +339,7 @@ cmpnd.optimize(
300
339
  trainset=train, # required: training examples
301
340
  valset=val, # required: validation examples
302
341
  metric=metric, # required: the metric, arity-checked
303
- proposer=None, # optional: the run's own instruction proposer
304
- config=None, # optional: optimizer config, allow-listed by serve
342
+ config=None, # optional: optimizer config, allow-listed by the platform
305
343
  deployment_id=None, # optional: a ready deployment to start from
306
344
  reflection_lm=None, # required: a dspy.LM or a bare model name
307
345
  lms=None, # optional: name -> dspy.LM, the run's named models
@@ -311,7 +349,7 @@ cmpnd.optimize(
311
349
  max_steps=10, # optional: the most optimize steps
312
350
  patience=2, # optional: stop after this many steps without improvement
313
351
  seed=0, # optional: the starting seed, advanced each step
314
- poll_interval=3.0, # optional: seconds between status polls
352
+ poll_interval=3.0, # optional: seconds between status checks
315
353
  timeout=600.0, # optional: seconds to wait for each step
316
354
  )
317
355
  ```
@@ -320,20 +358,41 @@ Pass exactly one budget: `max_metric_calls`, `auto` or
320
358
  `config["max_full_evals"]`. The SDK raises before any network call when the
321
359
  budget is missing.
322
360
 
323
- `optimize()` raises `cmpnd.OptimizeError` when serve answers a step's
361
+ `optimize()` raises `cmpnd.OptimizeError` when the platform answers a step's
324
362
  initiation with a 4xx, such as a 409 for missing data or a metric mismatch. It
325
363
  raises `cmpnd.OptimizeFailed` when a step reaches `failed`.
326
364
 
327
- ### From the CLI
365
+ ## Command line
366
+
367
+ The package installs the `cmpnd` command. `cmpnd login` saves your API key for
368
+ the command line. `cmpnd -h` lists the commands, and `cmpnd COMMAND -h`
369
+ describes one:
370
+
371
+ ```
372
+ usage: cmpnd [-h] [--version] [--api-key API_KEY] [--endpoint ENDPOINT]
373
+ {auth,login,logout,org,credentials,tool-servers,optimizations,programs,signatures,traces,evals,datasets,deployments,ps,status,logs,inspect,schema,sample,run,deploy,optimize}
374
+ ...
375
+
376
+ CMPND platform CLI — deploy, invoke, and inspect DSPy programs.
377
+
378
+ options:
379
+ -h, --help show this help message and exit
380
+ --version show program's version number and exit
381
+ --api-key API_KEY API key (or set CMPND_API_KEY)
382
+ --endpoint ENDPOINT API endpoint (or set CMPND_ENDPOINT)
383
+ ```
384
+
385
+ Deploy a source file under a program name, or optimize the program a file
386
+ declares:
328
387
 
329
388
  ```bash
330
- cmpnd optimize gepa task.py --program-id p_0123456789Ab --reflection-model openai/gpt-6-luna --auto light
389
+ cmpnd deploy program.py question-answerer
390
+ cmpnd optimize gepa task.py haiku --reflection-model openai/gpt-6-luna --auto light
331
391
  ```
332
392
 
333
- The file, or `-` for stdin, binds `program`, `trainset`, `valset` and
334
- `metric`. The CLI prints the best deployment ID. The CLI deploys the file's
335
- program first, so it needs `--program-id` or `CMPND_PROGRAM_ID`. With
336
- `--deployment-id`, the program id is optional.
393
+ `cmpnd deploy` uploads the file as written. `cmpnd optimize` reads `program`,
394
+ `trainset`, `valset` and `metric` from the file, deploys the program under the
395
+ program name and prints the best deployment ID.
337
396
 
338
397
  ## Custom spans
339
398
 
@@ -383,11 +442,59 @@ def run_pipeline(query: str):
383
442
 
384
443
  ### `cmpnd.configure()`
385
444
 
386
- Sets the API key, endpoint and options.
445
+ Sets the global API key, endpoint and options that `auto_instrument()`,
446
+ `deploy()`, `optimize()` and `execute()` use:
447
+
448
+ ```python
449
+ cmpnd.configure(
450
+ api_key="ck_xxx", # required, or CMPND_API_KEY
451
+ endpoint="https://platform.cmpnd.ai", # optional, or CMPND_ENDPOINT
452
+ project_tags="my-project", # optional: one tag or a list of tags
453
+ batch_size=100, # optional: spans per export batch
454
+ flush_interval_seconds=5.0, # optional: seconds between flushes
455
+ capture_inputs=True, # optional: record span inputs
456
+ capture_outputs=True, # optional: record span outputs
457
+ default_tags={"env": "prod"}, # optional: tags on every trace
458
+ )
459
+ ```
460
+
461
+ `api_key` and `endpoint` fall back to the `CMPND_API_KEY` and
462
+ `CMPND_ENDPOINT` environment variables. `project` is a deprecated alias for
463
+ `project_tags`. Passing both raises `ValueError`. `CMPND_MAX_INPUT_SIZE` and `CMPND_MAX_OUTPUT_SIZE` set the
464
+ captured input and output size limits, 65,536 bytes each by default.
387
465
 
388
466
  ### `cmpnd.auto_instrument()`
389
467
 
390
- Registers the callback with DSPy.
468
+ Registers the callback with DSPy, so every DSPy call records a trace.
469
+
470
+ ### `cmpnd.Client()`
471
+
472
+ Takes most of the same arguments as `cmpnd.configure()` and keeps them apart from the
473
+ global config. Use it as a context manager or as a plain object.
474
+
475
+ - `run_program(program, **inputs)` runs a `cmpnd.Program` and records its trace
476
+ under the program name.
477
+ - `run_optimization(optimizer, program, trainset=..., valset=...)` compiles a
478
+ `cmpnd.Program` with a DSPy optimizer, records every rollout, and returns a
479
+ copy of the program that holds the optimized module. For `dspy.GEPA`, it
480
+ also records the optimization run.
481
+ - `list_traces(**filters)` and `get_trace(trace_id)` read traces with the
482
+ client's credentials. They flush the client's traces first.
483
+ - `close()` flushes the client's traces and closes the client. A closed
484
+ client raises `RuntimeError` on every method.
485
+
486
+ ### `cmpnd.program()`
487
+
488
+ `@cmpnd.program(name)` above a `dspy.Module` class returns a `cmpnd.Program`
489
+ class with the same class name. Building it takes the class's own arguments
490
+ and a required `lm=` keyword. The decorator refuses a class whose
491
+ constructor already takes `lm`. Give an instance of it to `cmpnd.Program` instead.
492
+
493
+ ### `cmpnd.Program()`
494
+
495
+ `cmpnd.Program(name, *, module, lm)` gives a DSPy module a program name and
496
+ the `dspy.LM` it runs on. `@cmpnd.program(name)` builds the same thing from a
497
+ `dspy.Module` class.
391
498
 
392
499
  ### `cmpnd.CmpndCallback`
393
500
 
@@ -403,8 +510,8 @@ dspy.configure(callbacks=[cmpnd.CmpndCallback()])
403
510
 
404
511
  ### `cmpnd.deploy()`
405
512
 
406
- Deploys a DSPy module under a program id and returns a callable
407
- `DeployedProgram`. It uses `program_id=`, else the configured id.
513
+ Deploys a `cmpnd.Program` under its program name and returns a callable
514
+ `DeployedProgram`.
408
515
 
409
516
  ### `cmpnd.optimize()`
410
517
 
@@ -416,14 +523,13 @@ Optimizes a program through the platform. It returns the best
416
523
 
417
524
  Submits one durable run by `deployment_id`, waits for the result within the
418
525
  local timeout and returns a `dspy.Prediction`. A `DeployedProgram` call goes
419
- through this function. The SDK sends `Prefer: wait=5`, shortened to fit the
420
- remaining budget, so a fast result arrives without polling. It never repeats
421
- the submission POST.
526
+ through this function. A fast result returns at once, and the SDK never
527
+ submits one run twice.
422
528
 
423
529
  `timeout` is the whole submit-and-wait budget in seconds, 30 by default, or
424
530
  `None` for no local limit. `program_name` and `lm` select a module and model
425
531
  and travel beside the inputs. `metadata` and `tags` take `dict[str, str]`
426
- values that serve applies to the run's root trace. Serve-owned names such as
532
+ values that the platform applies to the run's root trace. Names the platform sets, such as
427
533
  `deployment_run_id` raise `TypeError` before anything is sent. The errors:
428
534
 
429
535
  - A refused request raises `httpx.HTTPStatusError`.
@@ -432,7 +538,7 @@ values that serve applies to the run's root trace. Serve-owned names such as
432
538
  - An answer that expired before it was read raises `RunResultExpired`.
433
539
 
434
540
  `cmpnd.deployment_run_id(result)` returns the run ID of a result, or of an
435
- exception when serve had assigned a run.
541
+ exception when the platform had assigned a run.
436
542
 
437
543
  `cmpnd.submit_deployment_run(id, inputs)` returns the accepted handle without
438
544
  waiting. `cmpnd.list_deployment_runs()`, `get_deployment_run(id)`,