cmpnd 0.68.0__tar.gz → 0.70.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.68.0 → cmpnd-0.70.0}/PKG-INFO +1 -1
  2. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/_authored_import.py +0 -1
  3. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/authored.py +0 -5
  4. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/cli/commands/evals.py +13 -1
  5. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/dataset_sync.py +8 -5
  6. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/deployment.py +1 -4
  7. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/eval_handler.py +35 -9
  8. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/models.py +13 -3
  9. {cmpnd-0.68.0 → cmpnd-0.70.0}/docs/cli.md +12 -0
  10. {cmpnd-0.68.0 → cmpnd-0.70.0}/docs/sdk-instrumentation.md +5 -1
  11. {cmpnd-0.68.0 → cmpnd-0.70.0}/pyproject.toml +1 -1
  12. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/e2e/test_deploy_programs.py +0 -1
  13. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/e2e/test_optimize_loop.py +7 -11
  14. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_authored.py +2 -1
  15. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_cli/test_evals.py +16 -2
  16. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_deploy.py +3 -4
  17. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_deploy_program_id.py +1 -1
  18. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_eval.py +1 -1
  19. cmpnd-0.70.0/tests/test_eval_program_id.py +192 -0
  20. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_eval_start.py +2 -2
  21. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_ingest_conformance.py +2 -1
  22. {cmpnd-0.68.0 → cmpnd-0.70.0}/uv.lock +1 -1
  23. {cmpnd-0.68.0 → cmpnd-0.70.0}/.gitignore +0 -0
  24. {cmpnd-0.68.0 → cmpnd-0.70.0}/AGENTS.md +0 -0
  25. {cmpnd-0.68.0 → cmpnd-0.70.0}/CLAUDE.md +0 -0
  26. {cmpnd-0.68.0 → cmpnd-0.70.0}/README.md +0 -0
  27. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/__init__.py +0 -0
  28. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/_assessments.py +0 -0
  29. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/_deployments.py +0 -0
  30. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/_exporter_pool.py +0 -0
  31. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/_gepa_patch.py +0 -0
  32. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/_http.py +0 -0
  33. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/_program_patch.py +0 -0
  34. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/_rlm_patch.py +0 -0
  35. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/_runtime_tools.py +0 -0
  36. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/_timespec.py +0 -0
  37. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/_traces.py +0 -0
  38. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/_valsets.py +0 -0
  39. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/callback.py +0 -0
  40. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/cli/__init__.py +0 -0
  41. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/cli/api_client.py +0 -0
  42. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/cli/commands/__init__.py +0 -0
  43. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/cli/commands/admin.py +0 -0
  44. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/cli/commands/assessments.py +0 -0
  45. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/cli/commands/auth.py +0 -0
  46. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/cli/commands/datasets.py +0 -0
  47. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/cli/commands/deployments.py +0 -0
  48. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/cli/commands/login.py +0 -0
  49. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/cli/commands/optimizations.py +0 -0
  50. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/cli/commands/org.py +0 -0
  51. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/cli/commands/programs.py +0 -0
  52. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/cli/commands/provider_credentials.py +0 -0
  53. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/cli/commands/tool_servers.py +0 -0
  54. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/cli/commands/top.py +0 -0
  55. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/cli/commands/traces.py +0 -0
  56. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/cli/commands/valsets.py +0 -0
  57. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/cli/credentials.py +0 -0
  58. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/cli/deprecation.py +0 -0
  59. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/cli/pagination.py +0 -0
  60. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/cli/shell.py +0 -0
  61. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/cli/trace_render.py +0 -0
  62. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/cli/tree_help.py +0 -0
  63. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/cli/verbs.py +0 -0
  64. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/cli/views.py +0 -0
  65. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/client.py +0 -0
  66. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/configuration.py +0 -0
  67. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/context.py +0 -0
  68. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/credentials.py +0 -0
  69. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/datasets.py +0 -0
  70. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/decorators.py +0 -0
  71. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/deployment_metadata.py +0 -0
  72. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/deployment_runs.py +0 -0
  73. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/execution.py +0 -0
  74. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/exporter.py +0 -0
  75. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/exporter_http.py +0 -0
  76. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/helpers.py +0 -0
  77. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/identity.py +0 -0
  78. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/imaging.py +0 -0
  79. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/ir/__init__.py +0 -0
  80. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/ir/decode.py +0 -0
  81. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/ir/encode.py +0 -0
  82. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/ir/hash.py +0 -0
  83. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/ir/program.py +0 -0
  84. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/ir/reflection.py +0 -0
  85. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/ir/types.py +0 -0
  86. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/ir/xxh64.py +0 -0
  87. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/lm_configuration.py +0 -0
  88. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/mcp_servers.py +0 -0
  89. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/named_programs.py +0 -0
  90. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/optimization.py +0 -0
  91. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/optimizers/__init__.py +0 -0
  92. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/optimizers/gepa.py +0 -0
  93. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/optimizers/gepa_callback.py +0 -0
  94. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/optimizers/resume.py +0 -0
  95. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/optimizers/tracker.py +0 -0
  96. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/packaging.py +0 -0
  97. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/programs.py +0 -0
  98. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/references.py +0 -0
  99. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/retry.py +0 -0
  100. {cmpnd-0.68.0 → cmpnd-0.70.0}/cmpnd/traces.py +0 -0
  101. {cmpnd-0.68.0 → cmpnd-0.70.0}/docs/2026-04-02-code-review.md +0 -0
  102. {cmpnd-0.68.0 → cmpnd-0.70.0}/docs/client.md +0 -0
  103. {cmpnd-0.68.0 → cmpnd-0.70.0}/docs/custom-proposer.md +0 -0
  104. {cmpnd-0.68.0 → cmpnd-0.70.0}/docs/plans/2026-04-05-train-val-dataset-capture-design.md +0 -0
  105. {cmpnd-0.68.0 → cmpnd-0.70.0}/docs/plans/2026-04-05-train-val-dataset-capture.md +0 -0
  106. {cmpnd-0.68.0 → cmpnd-0.70.0}/docs/reading-traces.md +0 -0
  107. {cmpnd-0.68.0 → cmpnd-0.70.0}/examples/generalizing_proposer.py +0 -0
  108. {cmpnd-0.68.0 → cmpnd-0.70.0}/examples/local_ollama.py +0 -0
  109. {cmpnd-0.68.0 → cmpnd-0.70.0}/ingest/LINEAGE.md +0 -0
  110. {cmpnd-0.68.0 → cmpnd-0.70.0}/ingest/README.md +0 -0
  111. {cmpnd-0.68.0 → cmpnd-0.70.0}/ingest/cmpnd_ingest/__init__.py +0 -0
  112. {cmpnd-0.68.0 → cmpnd-0.70.0}/ingest/cmpnd_ingest/bodies.py +0 -0
  113. {cmpnd-0.68.0 → cmpnd-0.70.0}/ingest/cmpnd_ingest/client_floor.py +0 -0
  114. {cmpnd-0.68.0 → cmpnd-0.70.0}/ingest/cmpnd_ingest/exporter_http.py +0 -0
  115. {cmpnd-0.68.0 → cmpnd-0.70.0}/ingest/cmpnd_ingest/program_names.py +0 -0
  116. {cmpnd-0.68.0 → cmpnd-0.70.0}/ingest/cmpnd_ingest/protocols.py +0 -0
  117. {cmpnd-0.68.0 → cmpnd-0.70.0}/ingest/cmpnd_ingest/py.typed +0 -0
  118. {cmpnd-0.68.0 → cmpnd-0.70.0}/ingest/cmpnd_ingest/request_log.py +0 -0
  119. {cmpnd-0.68.0 → cmpnd-0.70.0}/ingest/cmpnd_ingest/retry.py +0 -0
  120. {cmpnd-0.68.0 → cmpnd-0.70.0}/ingest/cmpnd_ingest/trace_facts.py +0 -0
  121. {cmpnd-0.68.0 → cmpnd-0.70.0}/ingest/pyproject.toml +0 -0
  122. {cmpnd-0.68.0 → cmpnd-0.70.0}/scripts/audit-sdist.sh +0 -0
  123. {cmpnd-0.68.0 → cmpnd-0.70.0}/scripts/capture_review_run.py +0 -0
  124. {cmpnd-0.68.0 → cmpnd-0.70.0}/scripts/check-pip-install.sh +0 -0
  125. {cmpnd-0.68.0 → cmpnd-0.70.0}/scripts/check_release_artifacts.py +0 -0
  126. {cmpnd-0.68.0 → cmpnd-0.70.0}/scripts/fixtures/review_run.json.gz +0 -0
  127. {cmpnd-0.68.0 → cmpnd-0.70.0}/scripts/gepa_resume_bug.py +0 -0
  128. {cmpnd-0.68.0 → cmpnd-0.70.0}/scripts/install-test-env.sh +0 -0
  129. {cmpnd-0.68.0 → cmpnd-0.70.0}/scripts/release-gate.sh +0 -0
  130. {cmpnd-0.68.0 → cmpnd-0.70.0}/scripts/release-real-models.sh +0 -0
  131. {cmpnd-0.68.0 → cmpnd-0.70.0}/scripts/require_version_bump.py +0 -0
  132. {cmpnd-0.68.0 → cmpnd-0.70.0}/scripts/seed_review_run.py +0 -0
  133. {cmpnd-0.68.0 → cmpnd-0.70.0}/scripts/selfhost_compat.py +0 -0
  134. {cmpnd-0.68.0 → cmpnd-0.70.0}/scripts/test-in-linux.sh +0 -0
  135. {cmpnd-0.68.0 → cmpnd-0.70.0}/stubs/dspy/__init__.pyi +0 -0
  136. {cmpnd-0.68.0 → cmpnd-0.70.0}/stubs/dspy/primitives/__init__.pyi +0 -0
  137. {cmpnd-0.68.0 → cmpnd-0.70.0}/stubs/dspy/primitives/prediction.pyi +0 -0
  138. {cmpnd-0.68.0 → cmpnd-0.70.0}/stubs/dspy/utils/__init__.pyi +0 -0
  139. {cmpnd-0.68.0 → cmpnd-0.70.0}/stubs/dspy/utils/callback.pyi +0 -0
  140. {cmpnd-0.68.0 → cmpnd-0.70.0}/stubs/dspy/utils/dummies.pyi +0 -0
  141. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/__init__.py +0 -0
  142. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/_credential_route.py +0 -0
  143. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/_deployment_signature_helpers.py +0 -0
  144. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/_exporter_helpers.py +0 -0
  145. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/_fake_clock.py +0 -0
  146. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/_identity_helpers.py +0 -0
  147. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/_resolve_refs.py +0 -0
  148. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/_traced_run.py +0 -0
  149. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/conftest.py +0 -0
  150. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/e2e/__init__.py +0 -0
  151. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/e2e/committee_task.py +0 -0
  152. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/e2e/conftest.py +0 -0
  153. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/e2e/continuation_task.py +0 -0
  154. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/e2e/data/committee_train.ndjson.gz +0 -0
  155. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/e2e/data/committee_val.ndjson.gz +0 -0
  156. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/e2e/fake_lm.py +0 -0
  157. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/e2e/helpers.py +0 -0
  158. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/e2e/target_capabilities.py +0 -0
  159. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/e2e/test_assessments_cli.py +0 -0
  160. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/e2e/test_capture_prompts.py +0 -0
  161. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/e2e/test_composite_module.py +0 -0
  162. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/e2e/test_dataset_auto_creation.py +0 -0
  163. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/e2e/test_deploy_execute.py +0 -0
  164. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/e2e/test_deploy_pandas.py +0 -0
  165. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/e2e/test_edge_cases.py +0 -0
  166. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/e2e/test_example_hash.py +0 -0
  167. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/e2e/test_gepa_optimization.py +0 -0
  168. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/e2e/test_interpreter_spans.py +0 -0
  169. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/e2e/test_lm_accuracy.py +0 -0
  170. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/e2e/test_module_tracing.py +0 -0
  171. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/e2e/test_optimization_lineage.py +0 -0
  172. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/e2e/test_optimization_metric_identity.py +0 -0
  173. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/e2e/test_optimize_authored_metric.py +0 -0
  174. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/e2e/test_optimize_continuation.py +0 -0
  175. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/e2e/test_optimize_custom_proposer.py +0 -0
  176. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/e2e/test_optimize_failures.py +0 -0
  177. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/e2e/test_optimize_review_committee.py +0 -0
  178. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/e2e/test_optimize_server_owned_completion.py +0 -0
  179. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/e2e/test_parallel_export.py +0 -0
  180. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/e2e/test_project_attribution.py +0 -0
  181. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/e2e/test_react_tool_spans.py +0 -0
  182. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/e2e/test_save_load.py +0 -0
  183. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/e2e/test_trace_structure.py +0 -0
  184. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/e2e/test_traces_read.py +0 -0
  185. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/e2e/test_user_attribution.py +0 -0
  186. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/e2e/test_valsets_cli.py +0 -0
  187. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/identity_vectors/01_predict_qa.json +0 -0
  188. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/identity_vectors/02_predict_renamed_field.json +0 -0
  189. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/identity_vectors/03_chain_of_thought_qa.json +0 -0
  190. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/identity_vectors/04_predict_richer_types.json +0 -0
  191. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/identity_vectors/05_composite_two_predicts.json +0 -0
  192. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/identity_vectors/06_multichaincomparison.json +0 -0
  193. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/identity_vectors/07_program_of_thought.json +0 -0
  194. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/identity_vectors/08_opaque_module.json +0 -0
  195. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/identity_vectors/09_predict_pydantic_field.json +0 -0
  196. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/identity_vectors/10_react.json +0 -0
  197. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/identity_vectors/11_refine.json +0 -0
  198. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/identity_vectors/12_retrieve.json +0 -0
  199. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/identity_vectors/13_knn.json +0 -0
  200. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/identity_vectors/14_parallel.json +0 -0
  201. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/identity_vectors/README.md +0 -0
  202. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/ingest_conformance.py +0 -0
  203. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/integration/__init__.py +0 -0
  204. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/integration/authored_optimize/judge.py +0 -0
  205. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/integration/authored_optimize/optimize_hosted.py +0 -0
  206. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/integration/conftest.py +0 -0
  207. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/integration/hosted_mcp_tool_optimize_probe.py +0 -0
  208. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/integration/hosted_optimize_probe.py +0 -0
  209. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/integration/optimization_run_probe.py +0 -0
  210. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/integration/test_cli_deploy_smoketest.py +0 -0
  211. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/integration/test_logs_renders_traces.py +0 -0
  212. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/integration/test_optimization_run.py +0 -0
  213. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/integration/test_optimizing_progress.py +0 -0
  214. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/integration/test_unhappy_path.py +0 -0
  215. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/load/__init__.py +0 -0
  216. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/load/__main__.py +0 -0
  217. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/load/drain.py +0 -0
  218. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/load/ingest.py +0 -0
  219. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/load/latency_transport.py +0 -0
  220. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/load/rlm_shape.py +0 -0
  221. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/load/rlm_size_report.py +0 -0
  222. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/load/sweep.py +0 -0
  223. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/load/test_rlm_shape.py +0 -0
  224. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/load/test_rlm_size_report.py +0 -0
  225. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/parity/__init__.py +0 -0
  226. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/parity/conftest.py +0 -0
  227. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/parity/seed_parity.py +0 -0
  228. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/parity/test_auth.py +0 -0
  229. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/parity/test_datasets.py +0 -0
  230. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/parity/test_deployments.py +0 -0
  231. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/parity/test_evals.py +0 -0
  232. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/parity/test_health.py +0 -0
  233. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/parity/test_modules.py +0 -0
  234. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/parity/test_optimizations.py +0 -0
  235. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/parity/test_programs.py +0 -0
  236. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/parity/test_signatures.py +0 -0
  237. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/parity/test_trace_streaming.py +0 -0
  238. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/parity/test_traces.py +0 -0
  239. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/real_models/__init__.py +0 -0
  240. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/real_models/_provider.py +0 -0
  241. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/real_models/_readiness.py +0 -0
  242. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/real_models/_reliability.py +0 -0
  243. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/real_models/_result.py +0 -0
  244. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/real_models/mint_bedrock_token.py +0 -0
  245. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/real_models/test_bedrock_converse.py +0 -0
  246. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/real_models/test_deploy_programs.py +0 -0
  247. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/real_models/test_multi_client_stress.py +0 -0
  248. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/real_models/test_optimize_client_committee.py +0 -0
  249. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/real_models/test_optimize_continuation.py +0 -0
  250. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/real_models/test_optimize_loop.py +0 -0
  251. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/real_models/test_optimize_loop_wasm.py +0 -0
  252. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/real_models/test_optimize_stress.py +0 -0
  253. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/real_models/test_provider_roles.py +0 -0
  254. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/real_models/test_readiness.py +0 -0
  255. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/real_models/test_real_provider_twins.py +0 -0
  256. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/real_models/test_reliability.py +0 -0
  257. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/real_models/test_reliability_classify.py +0 -0
  258. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/real_models/test_rlm_wasm.py +0 -0
  259. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/real_models/test_trace_search.py +0 -0
  260. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/span_reference_fixture.py +0 -0
  261. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_adapter_reentrancy.py +0 -0
  262. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_assessments_api.py +0 -0
  263. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_authored_binding_credentials.py +0 -0
  264. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_authored_bundle_collisions.py +0 -0
  265. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_authored_metric_contract.py +0 -0
  266. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_authored_named_models.py +0 -0
  267. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_authored_optimize.py +0 -0
  268. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_callback.py +0 -0
  269. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_candidate_lineage.py +0 -0
  270. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_cli/__init__.py +0 -0
  271. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_cli/conftest.py +0 -0
  272. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_cli/test_admin.py +0 -0
  273. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_cli/test_api_client.py +0 -0
  274. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_cli/test_assessments.py +0 -0
  275. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_cli/test_auth.py +0 -0
  276. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_cli/test_credentials.py +0 -0
  277. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_cli/test_datasets.py +0 -0
  278. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_cli/test_deployment_runs.py +0 -0
  279. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_cli/test_deployments.py +0 -0
  280. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_cli/test_login.py +0 -0
  281. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_cli/test_main.py +0 -0
  282. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_cli/test_optimizations.py +0 -0
  283. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_cli/test_org.py +0 -0
  284. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_cli/test_pagination.py +0 -0
  285. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_cli/test_parity.py +0 -0
  286. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_cli/test_programs.py +0 -0
  287. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_cli/test_provider_credentials.py +0 -0
  288. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_cli/test_schema_sample.py +0 -0
  289. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_cli/test_shell.py +0 -0
  290. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_cli/test_tool_servers.py +0 -0
  291. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_cli/test_top.py +0 -0
  292. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_cli/test_traces.py +0 -0
  293. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_cli/test_traces_program_and_module.py +0 -0
  294. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_cli/test_traces_search_wire.py +0 -0
  295. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_cli/test_tree_help.py +0 -0
  296. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_cli/test_valsets.py +0 -0
  297. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_client.py +0 -0
  298. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_client_floor.py +0 -0
  299. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_client_program_names.py +0 -0
  300. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_clustering/__init__.py +0 -0
  301. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_clustering/conftest.py +0 -0
  302. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_clustering/test_edge_cases.py +0 -0
  303. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_clustering/test_hash_consistency.py +0 -0
  304. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_clustering/test_type_conversion.py +0 -0
  305. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_cmp551_grouping_identity.py +0 -0
  306. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_configuration.py +0 -0
  307. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_context.py +0 -0
  308. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_context_propagation.py +0 -0
  309. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_credential_kwargs.py +0 -0
  310. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_credential_selection.py +0 -0
  311. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_credential_values.py +0 -0
  312. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_dataset_polling.py +0 -0
  313. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_dataset_sync.py +0 -0
  314. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_datasets.py +0 -0
  315. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_decision_client_spans.py +0 -0
  316. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_decorators.py +0 -0
  317. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_deploy_mcp_tool_references.py +0 -0
  318. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_deployment_metadata.py +0 -0
  319. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_deployment_runs.py +0 -0
  320. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_deployments_read.py +0 -0
  321. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_eval_example_attribution.py +0 -0
  322. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_eval_trace_grouping.py +0 -0
  323. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_exception_paths.py +0 -0
  324. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_execute.py +0 -0
  325. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_execute_run_identity.py +0 -0
  326. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_exporter.py +0 -0
  327. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_exporter_program_names.py +0 -0
  328. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_exporter_queue.py +0 -0
  329. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_exporter_real.py +0 -0
  330. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_fake_lm.py +0 -0
  331. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_gepa_callback.py +0 -0
  332. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_gepa_integration.py +0 -0
  333. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_gepa_output_normalization.py +0 -0
  334. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_gepa_resume.py +0 -0
  335. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_identity.py +0 -0
  336. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_imaging.py +0 -0
  337. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_import_weight.py +0 -0
  338. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_ingest_second_producer.py +0 -0
  339. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_integration.py +0 -0
  340. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_interpreter_callback.py +0 -0
  341. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_ir_encoder_properties.py +0 -0
  342. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_ir_golden_vectors.py +0 -0
  343. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_ir_roundtrip.py +0 -0
  344. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_lm15_native_calls.py +0 -0
  345. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_lm_configuration.py +0 -0
  346. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_lm_usage_shapes.py +0 -0
  347. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_mcp_tools.py +0 -0
  348. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_models.py +0 -0
  349. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_multi_client_stress_readiness.py +0 -0
  350. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_optimization_progress.py +0 -0
  351. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_optimization_start.py +0 -0
  352. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_optimize.py +0 -0
  353. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_optimize_budget.py +0 -0
  354. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_optimize_lift.py +0 -0
  355. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_optimize_lms.py +0 -0
  356. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_optimize_proposer.py +0 -0
  357. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_optimize_reflection_lm.py +0 -0
  358. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_optimize_terminal_failure.py +0 -0
  359. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_packaging.py +0 -0
  360. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_packaging_callable_source.py +0 -0
  361. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_packaging_mcp_tools.py +0 -0
  362. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_packaging_program_source.py +0 -0
  363. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_poll_until.py +0 -0
  364. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_program_id_deprecation.py +0 -0
  365. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_program_identity.py +0 -0
  366. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_program_lineage_persist.py +0 -0
  367. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_program_names_in_deploy.py +0 -0
  368. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_programs_create.py +0 -0
  369. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_project_payload.py +0 -0
  370. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_real_provider_twins_readiness.py +0 -0
  371. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_reflector_properties.py +0 -0
  372. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_reflector_smoke.py +0 -0
  373. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_release_gate_script.py +0 -0
  374. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_release_real_models_script.py +0 -0
  375. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_replaced_names.py +0 -0
  376. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_repro_reactv2_bugs.py +0 -0
  377. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_require_version_bump.py +0 -0
  378. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_retry.py +0 -0
  379. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_reversible_failures.py +0 -0
  380. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_rlm_patch.py +0 -0
  381. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_run_attribution_paths.py +0 -0
  382. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_runtime_tools.py +0 -0
  383. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_schemas.py +0 -0
  384. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_seal_lm_credential.py +0 -0
  385. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_seed_review_run.py +0 -0
  386. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_signature_inputs.py +0 -0
  387. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_span_references.py +0 -0
  388. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_span_sent_once.py +0 -0
  389. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_system_one.py +0 -0
  390. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_trace_context_concurrency.py +0 -0
  391. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_trace_fact_wire_contract.py +0 -0
  392. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_trace_facts.py +0 -0
  393. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_trace_render.py +0 -0
  394. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_traces_read.py +0 -0
  395. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_tracked_gepa.py +0 -0
  396. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_tracker_enrich.py +0 -0
  397. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_truncation.py +0 -0
  398. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_upload_auth_headers.py +0 -0
  399. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_valsets_api.py +0 -0
  400. {cmpnd-0.68.0 → cmpnd-0.70.0}/tests/test_xxh64.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: cmpnd
3
- Version: 0.68.0
3
+ Version: 0.70.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>
@@ -263,7 +263,6 @@ def _program_facts(
263
263
  lm = packaging._extract_lm_object(program)
264
264
  lm_kwargs = getattr(lm, "kwargs", {}) if lm is not None else {}
265
265
  facts = ProgramFacts(
266
- program_signature_hash=identity.compute_program_hash(program),
267
266
  entrypoint_kind=kind,
268
267
  module_class=type(program).__name__,
269
268
  litellm_model=getattr(lm, "model", None),
@@ -43,7 +43,6 @@ class SourceCheckError(ValueError):
43
43
  class ProgramFacts:
44
44
  """Facts derived by importing the staged program without calling forward."""
45
45
 
46
- program_signature_hash: int | None = None
47
46
  entrypoint_kind: str = "instance"
48
47
  module_class: str | None = None
49
48
  signature_name: str | None = None
@@ -72,11 +71,7 @@ class ProgramFacts:
72
71
 
73
72
  def deploy_body(self) -> dict[str, Any]:
74
73
  """Return fields the deployment create route accepts."""
75
- from . import identity
76
-
77
74
  body: dict[str, Any] = {}
78
- if self.program_signature_hash is not None:
79
- body["program_signature_hash"] = identity.format_signature_hash(self.program_signature_hash)
80
75
  for name in (
81
76
  "module_class",
82
77
  "signature_name",
@@ -9,7 +9,18 @@ from .. import api_client, deprecation, pagination
9
9
 
10
10
 
11
11
  def _add_list_args(p: ArgumentParser) -> None:
12
- p.add_argument("--program", dest="program_name", help="Filter by program name")
12
+ p.add_argument(
13
+ "--program",
14
+ dest="program_name",
15
+ metavar="NAME",
16
+ help="Only the runs of the program with this name, current or retired",
17
+ )
18
+ p.add_argument(
19
+ "--module",
20
+ dest="module_class",
21
+ metavar="CLASS",
22
+ help="Only the runs that evaluated this module class, matched exactly (e.g. ReAct)",
23
+ )
13
24
  p.add_argument("--metric", dest="metric_name", help="Filter by metric name")
14
25
  p.add_argument("--status", help="Filter by status (running, completed, failed, cancelled)")
15
26
  pagination.add_args(p, with_page_aliases=True, default_limit=50)
@@ -63,6 +74,7 @@ def handle_list(client: api_client.ApiClient, args: Any) -> Any:
63
74
  body: dict[str, Any] = pagination.wire(args, "page_size")
64
75
  for attr, key in [
65
76
  ("program_name", "program_name"),
77
+ ("module_class", "module_class"),
66
78
  ("metric_name", "metric"),
67
79
  ("status", "status"),
68
80
  ]:
@@ -15,7 +15,7 @@ from . import _http, configuration, identity, models
15
15
  logger = logging.getLogger(__name__)
16
16
 
17
17
 
18
- def check_dataset_exists(dataset_hash: str) -> bool:
18
+ def check_dataset_exists(dataset_hash: str, config: configuration.Config | None = None) -> bool:
19
19
  """Check if a dataset with this hash already exists on the backend.
20
20
 
21
21
  Makes a GET request to /api/v1/datasets/check/{dataset_hash}.
@@ -23,14 +23,17 @@ def check_dataset_exists(dataset_hash: str) -> bool:
23
23
 
24
24
  Args:
25
25
  dataset_hash: The SHA256[:16] hash of the dataset.
26
+ config: The account to ask, which must be the account the run publishes
27
+ to. None asks the process-global account.
26
28
 
27
29
  Returns:
28
30
  True if the dataset exists, False otherwise (including on errors).
29
31
  """
30
- try:
31
- config = configuration.require_config()
32
- except RuntimeError:
33
- return False
32
+ if config is None:
33
+ try:
34
+ config = configuration.require_config()
35
+ except RuntimeError:
36
+ return False
34
37
 
35
38
  url = f"{config.endpoint}/api/v1/datasets/check/{dataset_hash}"
36
39
 
@@ -527,13 +527,10 @@ def deploy_module_under(
527
527
  # Package the module
528
528
  zip_bytes = packaging.generate_source_zip(module, metric, mcp_tools=pinned_mcp_tools)
529
529
 
530
- # Compute program identity via the IR reflector on the live module (class
531
- # tag included); the signature is kept around only for display metadata.
530
+ # The deployment names its program by id alone; the signature only describes it.
532
531
  sig = packaging._get_module_signature(module)
533
- program_signature_hash = identity.compute_program_hash(module) or 0
534
532
 
535
533
  deploy_body: dict[str, Any] = {
536
- "program_signature_hash": identity.format_signature_hash(program_signature_hash),
537
534
  # Declare the ZIP's exact length so the server can reject an oversized
538
535
  # deploy before the upload.
539
536
  "declared_content_length": len(zip_bytes),
@@ -10,7 +10,7 @@ import logging
10
10
  from datetime import datetime, timezone
11
11
  from typing import Any
12
12
 
13
- from . import context, exporter, helpers, identity, models
13
+ from . import context, helpers, identity, models
14
14
 
15
15
  logger = logging.getLogger(__name__)
16
16
 
@@ -85,7 +85,7 @@ class EvalHandler:
85
85
  logger.debug(f"Extracted program: {program}, type: {type(program) if program else None}")
86
86
 
87
87
  if program:
88
- eval_run.program_name = program.__class__.__name__
88
+ eval_run.module_class = program.__class__.__name__
89
89
 
90
90
  # Hash via the IR reflector on the live module so the class tag
91
91
  # discriminates correctly; signature_summary is still derived from
@@ -165,16 +165,23 @@ class EvalHandler:
165
165
  if not input_fields and devset and hasattr(devset[0], "_input_keys"):
166
166
  input_fields = set(devset[0]._input_keys)
167
167
  eval_run._input_fields = input_fields
168
- # Fire pre-flight check (synchronous, short timeout)
168
+ # Fire pre-flight check (synchronous, short timeout). It asks the
169
+ # account the run publishes to: a client's own, else the global one.
169
170
  from . import dataset_sync
170
171
 
171
172
  try:
172
- eval_run._dataset_exists = dataset_sync.check_dataset_exists(eval_run.dataset_hash)
173
+ eval_run._dataset_exists = dataset_sync.check_dataset_exists(
174
+ eval_run.dataset_hash, self._callback._own_config
175
+ )
173
176
  except Exception:
174
177
  eval_run._dataset_exists = None # Will include examples as fallback
175
178
 
179
+ exp = self._callback._current_exporter()
180
+ eval_run.program_id = self._program_id(exp)
181
+
176
182
  logger.info(
177
- f"EvalRun created: program_name={eval_run.program_name}, "
183
+ f"EvalRun created: program_id={eval_run.program_id}, "
184
+ f"module_class={eval_run.module_class}, "
178
185
  f"metric_name={eval_run.metric_name}, "
179
186
  f"dataset_hash={eval_run.dataset_hash}, "
180
187
  f"dataset_size={eval_run.dataset_size}"
@@ -184,7 +191,6 @@ class EvalHandler:
184
191
  # the exporter (serve/observe, or deploy in-Lambda) assigns it. Obtain
185
192
  # it synchronously now, before any eval trace ships, since every
186
193
  # in-flight trace and the dict keys / span below are stamped with it.
187
- exp = exporter.get_exporter()
188
194
  if exp:
189
195
  eval_run.eval_run_id = exp.export_eval_start(eval_run)
190
196
 
@@ -201,13 +207,33 @@ class EvalHandler:
201
207
 
202
208
  # Capture evaluation config in span attributes
203
209
  span.attributes["eval.run_id"] = str(eval_run.eval_run_id)
204
- span.attributes["eval.program_name"] = eval_run.program_name or ""
210
+ span.attributes["eval.module_class"] = eval_run.module_class or ""
205
211
  span.attributes["eval.metric_name"] = eval_run.metric_name or ""
206
212
  span.attributes["eval.dataset_size"] = str(eval_run.dataset_size)
207
213
 
208
214
  self._callback._call_id_to_span[call_id] = span
209
215
  context.push_span(span)
210
216
 
217
+ def _program_id(self, exp: Any) -> str | None:
218
+ """The program id the eval run carries, resolved the way a trace's is.
219
+
220
+ A program name the call declares wins over the callback's program id. The
221
+ exporter resolves the name now, on the caller's thread, because the run's
222
+ start is sent synchronously and must carry the id. The exporter keeps the
223
+ answer for the process, so a name its traces already resolved costs no
224
+ request. A name the exporter cannot resolve leaves the run without an id.
225
+ """
226
+ from . import callback
227
+
228
+ name = callback._declared_program_name()
229
+ if name is None:
230
+ return self._callback._resolve_program_id()
231
+ # Read with getattr because the member is optional: an in-memory collector
232
+ # that resolves no names has none.
233
+ resolve = getattr(exp, "resolve_program_name", None)
234
+ program_id = resolve(name) if callable(resolve) else None
235
+ return program_id if isinstance(program_id, str) else None
236
+
211
237
  def on_evaluate_end(
212
238
  self,
213
239
  call_id: str,
@@ -228,7 +254,7 @@ class EvalHandler:
228
254
  span.status = models.TraceStatus.OK
229
255
  context.pop_span()
230
256
  if self._callback._should_stream_span(span):
231
- exp = exporter.get_exporter()
257
+ exp = self._callback._current_exporter()
232
258
  if exp:
233
259
  exp.export_span(span)
234
260
 
@@ -373,7 +399,7 @@ class EvalHandler:
373
399
  span.attributes["eval.score"] = str(overall_score)
374
400
 
375
401
  # Export the eval run
376
- exp = exporter.get_exporter()
402
+ exp = self._callback._current_exporter()
377
403
  if exp:
378
404
  exp.export_eval_run(eval_run)
379
405
 
@@ -1274,7 +1274,11 @@ class EvalRunBuilder:
1274
1274
  start_time: datetime | None = None
1275
1275
 
1276
1276
  # Eval Identity (defines comparability)
1277
- program_name: str | None = None
1277
+ # The program the run evaluates: the id serve gave the program name the call
1278
+ # declared, or the client's program id. None when the run names no program.
1279
+ program_id: str | None = None
1280
+ # The evaluated module's class, such as "ReAct".
1281
+ module_class: str | None = None
1278
1282
  metric_name: str | None = None
1279
1283
  dataset_hash: str | None = None
1280
1284
  dataset_size: int = 0
@@ -1393,7 +1397,10 @@ class EvalRunBuilder:
1393
1397
  return {
1394
1398
  "eval_run_id": "new",
1395
1399
  "status": EvalRunStatus.RUNNING.value,
1396
- "program_name": self.program_name or "",
1400
+ "program_id": self.program_id,
1401
+ "module_class": self.module_class or "",
1402
+ # Also under the key a serve from before module_class reads.
1403
+ "program_name": self.module_class or "",
1397
1404
  "metric_name": self.metric_name or "",
1398
1405
  "dataset_hash": self.dataset_hash or "",
1399
1406
  "dataset_size": self.dataset_size,
@@ -1411,7 +1418,10 @@ class EvalRunBuilder:
1411
1418
  """Convert to API-compatible dictionary."""
1412
1419
  d = {
1413
1420
  "eval_run_id": str(self.eval_run_id) if self.eval_run_id else None,
1414
- "program_name": self.program_name or "",
1421
+ "program_id": self.program_id,
1422
+ "module_class": self.module_class or "",
1423
+ # Also under the key a serve from before module_class reads.
1424
+ "program_name": self.module_class or "",
1415
1425
  "metric_name": self.metric_name or "",
1416
1426
  "dataset_hash": self.dataset_hash or "",
1417
1427
  "dataset_size": self.dataset_size,
@@ -458,6 +458,18 @@ program signature hash. `cmpnd programs optimized` commands and
458
458
  optimization result, not a program. Each group's `--help` names the column its
459
459
  IDs come from.
460
460
 
461
+ `cmpnd evals list [--program NAME] [--module CLASS] [--metric] [--status]`
462
+ lists eval runs, newest first. `--program` takes the program's name, current
463
+ or retired, and a name no program answers to is an error that names it.
464
+ `--module` takes the evaluated module's class, such as `ReAct`, and matches it
465
+ exactly. The CLI sends them as `program_name` and `module_class`. Each eval
466
+ run in `evals list`, `evals show` and `programs evals` names what it evaluated
467
+ in three fields, as a trace does. `program_name` is the program's name, empty
468
+ when the program has none or the run names no program. `program_id` is the
469
+ program's `p_` id, and `module_class` is the evaluated module's class. A server
470
+ that predates `module_class` sends the class in `program_name` and filters
471
+ `--program` by class.
472
+
461
473
  `cmpnd deployments openapi <id>` prints the OpenAPI document a deployment
462
474
  serves, which an agent reads before it calls the deployment.
463
475
 
@@ -727,6 +727,8 @@ What it captures beyond the normal span flow:
727
727
  - An `EvalRunBuilder` (constructed at `eval_handler.py:79`) that groups all per-example traces under one eval ID.
728
728
  - The metric name (via `get_metric_name` from `python-sdk/cmpnd/helpers.py`) and inferred provider.
729
729
  - Links to the enclosing optimization run when one exists (`eval_handler.py:85`), so eval runs triggered inside `GEPA.compile` roll up under the optimization in the UI.
730
+ - The program the run evaluates, as `program_id`. A program name the call declares wins: the exporter resolves it with `resolve_program_name`, the same once-per-process answer its traces use, on the caller's thread because the eval start is sent synchronously. Without a declared name, the run takes the callback's program id. A name serve refuses leaves the run without an id. The evaluated module's class goes as `module_class`, and again under `program_name`, the key a serve from before `module_class` reads.
731
+ - The exporter it publishes through: the callback's own (`_current_exporter`), so a client's eval runs go to the client's account.
730
732
  - The dataset — on `on_evaluate_start` it triggers the `dataset_sync` pre-flight described above.
731
733
 
732
734
  Per-example results (scores, statuses, example hashes) are collected in `on_evaluate_end` and shipped as part of the `EvalRunBuilder`'s `to_api_dict()`, which the exporter routes to `/api/v1/eval_runs`.
@@ -803,7 +805,9 @@ name form. A program name wins over the config's id. `configure()`
803
805
  checks the id's shape and raises `ValueError` on a bad one, and a `Config` built directly
804
806
  is checked the same way.
805
807
 
806
- The id rides every body that can declare a program, beside `program_signature_hash`:
808
+ The id rides every body that can declare a program. A deployment create names its program
809
+ by the id alone and sends no `program_signature_hash`. The other bodies still carry the
810
+ hash beside the id:
807
811
 
808
812
  | Body | Where | Built by |
809
813
  |---|---|---|
@@ -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.68.0"
8
+ version = "0.70.0"
9
9
  description = "DSPy observability and deployment SDK for cmpnd"
10
10
  readme = "README.md"
11
11
  requires-python = ">=3.11"
@@ -219,7 +219,6 @@ class TestDeployBadImportRejected:
219
219
  create_resp = client.post(
220
220
  f"{config.endpoint}/api/v1/deployments",
221
221
  json={
222
- "program_signature_hash": 0,
223
222
  "declared_content_length": len(zip_bytes),
224
223
  "program_id": program_id_for(f"test_deploy_programs-{uuid.uuid4().hex[:8]}"),
225
224
  # A worker that spends egress tokens needs the model a token names, so
@@ -32,7 +32,6 @@ import dspy
32
32
  import pytest
33
33
 
34
34
  import cmpnd
35
- from tests import _identity_helpers
36
35
  from tests.e2e import committee_task, fake_lm
37
36
  from tests.e2e.helpers import named_program, platform_client, poll_until, program_id_for
38
37
  from tests.e2e.target_capabilities import needs_an_optimizer
@@ -190,7 +189,6 @@ class TestOptimizeGepaDeployDetail:
190
189
 
191
190
  def test_gepa_deploy_run_stamps_traces_and_lands_detail(self, deployed_source, program_id, server_client):
192
191
  program, trainset, valset, deployed = deployed_source
193
- sig_hash = _identity_helpers.program_hash_for_sig(program.signature)
194
192
  before = time.time()
195
193
 
196
194
  platform_client().optimize_deployment(
@@ -210,10 +208,10 @@ class TestOptimizeGepaDeployDetail:
210
208
 
211
209
  # Correlate to THIS run through the optimization index, not by scanning
212
210
  # the trace stream: `deployed_source` is module-scoped, so every other test
213
- # in this file emits traces under the SAME program_signature_hash. This run
214
- # is the only one of this optimizer + signature started after `before`.
215
- # (The optimization search is not filtered by program_signature_hash, so
216
- # match it on the returned row, which surfaces it.)
211
+ # in this file emits traces under the SAME program. This run is the only
212
+ # one of this optimizer + program started after `before`. A run serve
213
+ # starts names its deployment's program_id. The optimization search does
214
+ # not filter by program, so match it on the returned row, which carries it.
217
215
  #
218
216
  # Poll, don't sleep-once: on serve the deploy run's detail + traces land
219
217
  # via a background completion watcher (5s poll cadence) AFTER optimize_deployment()
@@ -228,11 +226,11 @@ class TestOptimizeGepaDeployDetail:
228
226
  order_direction="desc",
229
227
  per_page=50,
230
228
  ).get("optimization_runs", [])
231
- return [r for r in runs if str(r.get("program_signature_hash")) == str(sig_hash)]
229
+ return [r for r in runs if r.get("program_id") == program_id]
232
230
 
233
231
  mine = poll_until(_find_run, timeout=60.0, interval=3.0)
234
232
  assert mine, (
235
- f"no GEPA optimization run for program_signature_hash={sig_hash} after {start_from} "
233
+ f"no GEPA optimization run for program_id={program_id} after {start_from} "
236
234
  "(serve completion watcher didn't land it within 60s)"
237
235
  )
238
236
  run_id = mine[0]["run_id"]
@@ -254,9 +252,7 @@ class TestOptimizeGepaDeployDetail:
254
252
  assert candidates, f"GEPA deploy run {run_id} landed a header but no candidate detail (CMP-323)"
255
253
 
256
254
  # The worker's tracker stamps the run id onto the run's traces (the collector
257
- # stamps only deployment_id), and serve carries the int64
258
- # program_signature_hash through the poll without float-rounding it, so the
259
- # run row matches this signature. Its traces land under the deployment's program.
255
+ # stamps only deployment_id), and the traces land under the deployment's program.
260
256
  # Page wide (page_size=500, the API max) so this run's few traces aren't crowded
261
257
  # out of the default window by the other tests' runs — module-scoped
262
258
  # `deployed_source` means they all share this program —
@@ -142,8 +142,9 @@ def test_bundle_pins_tools_without_importing_the_program_twice(monkeypatch):
142
142
  check.assert_called_once()
143
143
 
144
144
 
145
- def test_deploy_body_omits_unknown_hash_and_trace_limits():
145
+ def test_deploy_body_omits_trace_limits_and_sends_no_hash():
146
146
  assert authored.ProgramFacts.minimal().deploy_body() == {}
147
+ assert "program_signature_hash" not in authored.ProgramFacts(module_class="Predict").deploy_body()
147
148
 
148
149
 
149
150
  def test_deploy_body_preserves_empty_signature_field_lists():
@@ -86,20 +86,34 @@ class TestEvalsList:
86
86
  # own spelling passes while the filter does nothing.
87
87
  def test_minimal_list(self, mock_client):
88
88
  mock_client.post.return_value = {"eval_runs": []}
89
- args = argparse.Namespace(program_name=None, metric_name=None, status=None, limit=50, offset=0)
89
+ args = argparse.Namespace(
90
+ program_name=None, module_class=None, metric_name=None, status=None, limit=50, offset=0
91
+ )
90
92
  handle_list(mock_client, args)
91
93
  body = mock_client.post.call_args[1]["json"]
92
94
  assert body == {"page": 1, "page_size": 50}
93
95
 
94
96
  def test_with_filters(self, mock_client):
95
97
  mock_client.post.return_value = {"eval_runs": []}
96
- args = argparse.Namespace(program_name="RAG", metric_name="accuracy", status="completed", limit=50, offset=0)
98
+ args = argparse.Namespace(
99
+ program_name="RAG", module_class=None, metric_name="accuracy", status="completed", limit=50, offset=0
100
+ )
97
101
  handle_list(mock_client, args)
98
102
  body = mock_client.post.call_args[1]["json"]
99
103
  assert body["program_name"] == "RAG"
100
104
  assert body["metric"] == "accuracy"
101
105
  assert body["status"] == "completed"
102
106
 
107
+ def test_program_names_the_program_and_module_names_the_class(self, mock_client):
108
+ # --program is the program's name; --module is the evaluated module's
109
+ # class, which the server matches exactly under module_class.
110
+ mock_client.post.return_value = {"eval_runs": []}
111
+ args = _build_parser().parse_args(["evals", "list", "--program", "capital-qa", "--module", "ReAct"])
112
+ handle_list(mock_client, args)
113
+ body = mock_client.post.call_args[1]["json"]
114
+ assert body["program_name"] == "capital-qa"
115
+ assert body["module_class"] == "ReAct"
116
+
103
117
  def test_deprecated_search_verb_dispatches_and_is_marked(self, mock_client):
104
118
  # The warning is the dispatcher's job (see test_main.py); the wiring is this one's.
105
119
  parser = _build_parser()
@@ -414,7 +414,8 @@ class TestDeploy:
414
414
  create_call = client.post.call_args_list[0]
415
415
  assert "ct_test_key" in str(create_call)
416
416
 
417
- def test_sends_program_signature_hash(self, mock_httpx):
417
+ def test_sends_no_program_signature_hash(self, mock_httpx):
418
+ # A deployment names its program by id alone.
418
419
  client = self._setup_mocks(mock_httpx)
419
420
 
420
421
  with mock.patch.object(deployment, "time") as mock_time:
@@ -425,9 +426,7 @@ class TestDeploy:
425
426
 
426
427
  create_call = client.post.call_args_list[0]
427
428
  body = create_call.kwargs.get("json", {})
428
- assert "program_signature_hash" in body
429
- # CMP-331: carried as a quoted decimal string on the wire, not a number.
430
- assert isinstance(body["program_signature_hash"], str)
429
+ assert "program_signature_hash" not in body
431
430
 
432
431
  def test_sends_the_programs_signature(self, mock_httpx):
433
432
  # A program's signature is known the moment the module is packaged, and the
@@ -108,7 +108,7 @@ class TestDeployBody:
108
108
  lambda: deployment.deploy_module_under(dspy.Predict("question -> answer"), None, 300, None, None, config)
109
109
  )
110
110
  assert "program_id" not in body
111
- assert "program_signature_hash" in body
111
+ assert "program_signature_hash" not in body
112
112
 
113
113
  def test_an_undeclared_bundle_deploy_omits_the_key(self):
114
114
  _configure()
@@ -199,7 +199,7 @@ class TestEvalLifecycle:
199
199
  eval_run = exporter.eval_runs[0]
200
200
 
201
201
  # Program metadata
202
- assert eval_run.program_name == "TestProgram"
202
+ assert eval_run.module_class == "TestProgram"
203
203
  assert eval_run.metric_name == "exact_match"
204
204
  assert eval_run.dataset_size == 3
205
205