cmpnd 0.78.0__tar.gz → 0.80.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 (405) hide show
  1. {cmpnd-0.78.0 → cmpnd-0.80.0}/PKG-INFO +1 -1
  2. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/cli/commands/admin.py +67 -3
  3. {cmpnd-0.78.0 → cmpnd-0.80.0}/docs/cli.md +17 -0
  4. {cmpnd-0.78.0 → cmpnd-0.80.0}/pyproject.toml +1 -1
  5. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_cli/test_admin.py +118 -5
  6. {cmpnd-0.78.0 → cmpnd-0.80.0}/uv.lock +1 -1
  7. {cmpnd-0.78.0 → cmpnd-0.80.0}/.gitignore +0 -0
  8. {cmpnd-0.78.0 → cmpnd-0.80.0}/AGENTS.md +0 -0
  9. {cmpnd-0.78.0 → cmpnd-0.80.0}/CLAUDE.md +0 -0
  10. {cmpnd-0.78.0 → cmpnd-0.80.0}/README.md +0 -0
  11. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/__init__.py +0 -0
  12. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/_assessments.py +0 -0
  13. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/_authored_import.py +0 -0
  14. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/_deployments.py +0 -0
  15. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/_exporter_pool.py +0 -0
  16. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/_gepa_patch.py +0 -0
  17. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/_http.py +0 -0
  18. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/_program_patch.py +0 -0
  19. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/_rlm_patch.py +0 -0
  20. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/_runtime_tools.py +0 -0
  21. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/_timespec.py +0 -0
  22. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/_traces.py +0 -0
  23. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/_valsets.py +0 -0
  24. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/authored.py +0 -0
  25. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/callback.py +0 -0
  26. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/cli/__init__.py +0 -0
  27. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/cli/api_client.py +0 -0
  28. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/cli/commands/__init__.py +0 -0
  29. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/cli/commands/assessments.py +0 -0
  30. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/cli/commands/auth.py +0 -0
  31. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/cli/commands/datasets.py +0 -0
  32. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/cli/commands/deployments.py +0 -0
  33. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/cli/commands/evals.py +0 -0
  34. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/cli/commands/login.py +0 -0
  35. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/cli/commands/optimizations.py +0 -0
  36. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/cli/commands/org.py +0 -0
  37. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/cli/commands/programs.py +0 -0
  38. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/cli/commands/provider_credentials.py +0 -0
  39. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/cli/commands/tool_servers.py +0 -0
  40. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/cli/commands/top.py +0 -0
  41. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/cli/commands/traces.py +0 -0
  42. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/cli/commands/valsets.py +0 -0
  43. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/cli/credentials.py +0 -0
  44. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/cli/deprecation.py +0 -0
  45. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/cli/pagination.py +0 -0
  46. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/cli/shell.py +0 -0
  47. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/cli/trace_render.py +0 -0
  48. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/cli/tree_help.py +0 -0
  49. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/cli/verbs.py +0 -0
  50. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/cli/views.py +0 -0
  51. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/client.py +0 -0
  52. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/configuration.py +0 -0
  53. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/context.py +0 -0
  54. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/credentials.py +0 -0
  55. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/dataset_sync.py +0 -0
  56. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/datasets.py +0 -0
  57. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/decorators.py +0 -0
  58. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/deployment.py +0 -0
  59. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/deployment_metadata.py +0 -0
  60. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/deployment_runs.py +0 -0
  61. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/eval_handler.py +0 -0
  62. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/execution.py +0 -0
  63. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/exporter.py +0 -0
  64. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/exporter_http.py +0 -0
  65. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/helpers.py +0 -0
  66. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/identity.py +0 -0
  67. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/imaging.py +0 -0
  68. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/ir/__init__.py +0 -0
  69. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/ir/decode.py +0 -0
  70. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/ir/encode.py +0 -0
  71. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/ir/hash.py +0 -0
  72. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/ir/program.py +0 -0
  73. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/ir/reflection.py +0 -0
  74. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/ir/types.py +0 -0
  75. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/ir/xxh64.py +0 -0
  76. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/lm_configuration.py +0 -0
  77. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/mcp_servers.py +0 -0
  78. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/models.py +0 -0
  79. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/named_programs.py +0 -0
  80. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/optimization.py +0 -0
  81. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/optimizers/__init__.py +0 -0
  82. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/optimizers/gepa.py +0 -0
  83. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/optimizers/gepa_callback.py +0 -0
  84. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/optimizers/resume.py +0 -0
  85. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/optimizers/tracker.py +0 -0
  86. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/packaging.py +0 -0
  87. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/program_naming.py +0 -0
  88. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/programs.py +0 -0
  89. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/references.py +0 -0
  90. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/retry.py +0 -0
  91. {cmpnd-0.78.0 → cmpnd-0.80.0}/cmpnd/traces.py +0 -0
  92. {cmpnd-0.78.0 → cmpnd-0.80.0}/docs/2026-04-02-code-review.md +0 -0
  93. {cmpnd-0.78.0 → cmpnd-0.80.0}/docs/client.md +0 -0
  94. {cmpnd-0.78.0 → cmpnd-0.80.0}/docs/custom-proposer.md +0 -0
  95. {cmpnd-0.78.0 → cmpnd-0.80.0}/docs/plans/2026-04-05-train-val-dataset-capture-design.md +0 -0
  96. {cmpnd-0.78.0 → cmpnd-0.80.0}/docs/plans/2026-04-05-train-val-dataset-capture.md +0 -0
  97. {cmpnd-0.78.0 → cmpnd-0.80.0}/docs/reading-traces.md +0 -0
  98. {cmpnd-0.78.0 → cmpnd-0.80.0}/docs/sdk-instrumentation.md +0 -0
  99. {cmpnd-0.78.0 → cmpnd-0.80.0}/examples/generalizing_proposer.py +0 -0
  100. {cmpnd-0.78.0 → cmpnd-0.80.0}/examples/local_ollama.py +0 -0
  101. {cmpnd-0.78.0 → cmpnd-0.80.0}/ingest/LINEAGE.md +0 -0
  102. {cmpnd-0.78.0 → cmpnd-0.80.0}/ingest/README.md +0 -0
  103. {cmpnd-0.78.0 → cmpnd-0.80.0}/ingest/cmpnd_ingest/__init__.py +0 -0
  104. {cmpnd-0.78.0 → cmpnd-0.80.0}/ingest/cmpnd_ingest/bodies.py +0 -0
  105. {cmpnd-0.78.0 → cmpnd-0.80.0}/ingest/cmpnd_ingest/client_floor.py +0 -0
  106. {cmpnd-0.78.0 → cmpnd-0.80.0}/ingest/cmpnd_ingest/exporter_http.py +0 -0
  107. {cmpnd-0.78.0 → cmpnd-0.80.0}/ingest/cmpnd_ingest/program_names.py +0 -0
  108. {cmpnd-0.78.0 → cmpnd-0.80.0}/ingest/cmpnd_ingest/protocols.py +0 -0
  109. {cmpnd-0.78.0 → cmpnd-0.80.0}/ingest/cmpnd_ingest/py.typed +0 -0
  110. {cmpnd-0.78.0 → cmpnd-0.80.0}/ingest/cmpnd_ingest/request_log.py +0 -0
  111. {cmpnd-0.78.0 → cmpnd-0.80.0}/ingest/cmpnd_ingest/retry.py +0 -0
  112. {cmpnd-0.78.0 → cmpnd-0.80.0}/ingest/cmpnd_ingest/trace_facts.py +0 -0
  113. {cmpnd-0.78.0 → cmpnd-0.80.0}/ingest/pyproject.toml +0 -0
  114. {cmpnd-0.78.0 → cmpnd-0.80.0}/scripts/audit-sdist.sh +0 -0
  115. {cmpnd-0.78.0 → cmpnd-0.80.0}/scripts/capture_review_run.py +0 -0
  116. {cmpnd-0.78.0 → cmpnd-0.80.0}/scripts/check-pip-install.sh +0 -0
  117. {cmpnd-0.78.0 → cmpnd-0.80.0}/scripts/check_release_artifacts.py +0 -0
  118. {cmpnd-0.78.0 → cmpnd-0.80.0}/scripts/fixtures/review_run.json.gz +0 -0
  119. {cmpnd-0.78.0 → cmpnd-0.80.0}/scripts/gepa_resume_bug.py +0 -0
  120. {cmpnd-0.78.0 → cmpnd-0.80.0}/scripts/install-test-env.sh +0 -0
  121. {cmpnd-0.78.0 → cmpnd-0.80.0}/scripts/release-gate.sh +0 -0
  122. {cmpnd-0.78.0 → cmpnd-0.80.0}/scripts/release-real-models.sh +0 -0
  123. {cmpnd-0.78.0 → cmpnd-0.80.0}/scripts/require_version_bump.py +0 -0
  124. {cmpnd-0.78.0 → cmpnd-0.80.0}/scripts/seed_review_run.py +0 -0
  125. {cmpnd-0.78.0 → cmpnd-0.80.0}/scripts/selfhost_compat.py +0 -0
  126. {cmpnd-0.78.0 → cmpnd-0.80.0}/scripts/test-in-linux.sh +0 -0
  127. {cmpnd-0.78.0 → cmpnd-0.80.0}/stubs/dspy/__init__.pyi +0 -0
  128. {cmpnd-0.78.0 → cmpnd-0.80.0}/stubs/dspy/primitives/__init__.pyi +0 -0
  129. {cmpnd-0.78.0 → cmpnd-0.80.0}/stubs/dspy/primitives/prediction.pyi +0 -0
  130. {cmpnd-0.78.0 → cmpnd-0.80.0}/stubs/dspy/utils/__init__.pyi +0 -0
  131. {cmpnd-0.78.0 → cmpnd-0.80.0}/stubs/dspy/utils/callback.pyi +0 -0
  132. {cmpnd-0.78.0 → cmpnd-0.80.0}/stubs/dspy/utils/dummies.pyi +0 -0
  133. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/__init__.py +0 -0
  134. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/_credential_route.py +0 -0
  135. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/_deployment_signature_helpers.py +0 -0
  136. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/_exporter_helpers.py +0 -0
  137. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/_fake_clock.py +0 -0
  138. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/_identity_helpers.py +0 -0
  139. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/_resolve_refs.py +0 -0
  140. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/_traced_run.py +0 -0
  141. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/conftest.py +0 -0
  142. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/e2e/__init__.py +0 -0
  143. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/e2e/committee_task.py +0 -0
  144. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/e2e/conftest.py +0 -0
  145. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/e2e/continuation_task.py +0 -0
  146. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/e2e/data/committee_train.ndjson.gz +0 -0
  147. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/e2e/data/committee_val.ndjson.gz +0 -0
  148. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/e2e/fake_lm.py +0 -0
  149. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/e2e/helpers.py +0 -0
  150. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/e2e/target_capabilities.py +0 -0
  151. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/e2e/test_assessments_cli.py +0 -0
  152. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/e2e/test_capture_prompts.py +0 -0
  153. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/e2e/test_composite_module.py +0 -0
  154. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/e2e/test_dataset_auto_creation.py +0 -0
  155. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/e2e/test_deploy_execute.py +0 -0
  156. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/e2e/test_deploy_pandas.py +0 -0
  157. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/e2e/test_deploy_programs.py +0 -0
  158. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/e2e/test_edge_cases.py +0 -0
  159. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/e2e/test_example_hash.py +0 -0
  160. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/e2e/test_gepa_optimization.py +0 -0
  161. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/e2e/test_interpreter_spans.py +0 -0
  162. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/e2e/test_lm_accuracy.py +0 -0
  163. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/e2e/test_module_tracing.py +0 -0
  164. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/e2e/test_optimization_lineage.py +0 -0
  165. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/e2e/test_optimization_metric_identity.py +0 -0
  166. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/e2e/test_optimize_authored_metric.py +0 -0
  167. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/e2e/test_optimize_continuation.py +0 -0
  168. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/e2e/test_optimize_custom_proposer.py +0 -0
  169. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/e2e/test_optimize_failures.py +0 -0
  170. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/e2e/test_optimize_loop.py +0 -0
  171. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/e2e/test_optimize_review_committee.py +0 -0
  172. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/e2e/test_optimize_server_owned_completion.py +0 -0
  173. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/e2e/test_parallel_export.py +0 -0
  174. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/e2e/test_project_attribution.py +0 -0
  175. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/e2e/test_react_tool_spans.py +0 -0
  176. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/e2e/test_save_load.py +0 -0
  177. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/e2e/test_trace_structure.py +0 -0
  178. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/e2e/test_traces_read.py +0 -0
  179. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/e2e/test_user_attribution.py +0 -0
  180. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/e2e/test_valsets_cli.py +0 -0
  181. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/identity_vectors/01_predict_qa.json +0 -0
  182. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/identity_vectors/02_predict_renamed_field.json +0 -0
  183. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/identity_vectors/03_chain_of_thought_qa.json +0 -0
  184. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/identity_vectors/04_predict_richer_types.json +0 -0
  185. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/identity_vectors/05_composite_two_predicts.json +0 -0
  186. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/identity_vectors/06_multichaincomparison.json +0 -0
  187. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/identity_vectors/07_program_of_thought.json +0 -0
  188. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/identity_vectors/08_opaque_module.json +0 -0
  189. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/identity_vectors/09_predict_pydantic_field.json +0 -0
  190. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/identity_vectors/10_react.json +0 -0
  191. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/identity_vectors/11_refine.json +0 -0
  192. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/identity_vectors/12_retrieve.json +0 -0
  193. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/identity_vectors/13_knn.json +0 -0
  194. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/identity_vectors/14_parallel.json +0 -0
  195. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/identity_vectors/README.md +0 -0
  196. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/ingest_conformance.py +0 -0
  197. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/integration/__init__.py +0 -0
  198. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/integration/authored_optimize/judge.py +0 -0
  199. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/integration/authored_optimize/optimize_hosted.py +0 -0
  200. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/integration/conftest.py +0 -0
  201. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/integration/hosted_mcp_tool_optimize_probe.py +0 -0
  202. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/integration/hosted_optimize_probe.py +0 -0
  203. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/integration/optimization_run_probe.py +0 -0
  204. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/integration/test_cli_deploy_smoketest.py +0 -0
  205. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/integration/test_logs_renders_traces.py +0 -0
  206. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/integration/test_optimization_run.py +0 -0
  207. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/integration/test_optimizing_progress.py +0 -0
  208. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/integration/test_unhappy_path.py +0 -0
  209. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/load/__init__.py +0 -0
  210. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/load/__main__.py +0 -0
  211. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/load/drain.py +0 -0
  212. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/load/ingest.py +0 -0
  213. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/load/latency_transport.py +0 -0
  214. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/load/rlm_shape.py +0 -0
  215. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/load/rlm_size_report.py +0 -0
  216. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/load/sweep.py +0 -0
  217. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/load/test_rlm_shape.py +0 -0
  218. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/load/test_rlm_size_report.py +0 -0
  219. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/parity/__init__.py +0 -0
  220. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/parity/conftest.py +0 -0
  221. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/parity/seed_parity.py +0 -0
  222. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/parity/test_auth.py +0 -0
  223. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/parity/test_datasets.py +0 -0
  224. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/parity/test_deployments.py +0 -0
  225. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/parity/test_evals.py +0 -0
  226. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/parity/test_health.py +0 -0
  227. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/parity/test_modules.py +0 -0
  228. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/parity/test_optimizations.py +0 -0
  229. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/parity/test_programs.py +0 -0
  230. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/parity/test_signatures.py +0 -0
  231. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/parity/test_trace_streaming.py +0 -0
  232. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/parity/test_traces.py +0 -0
  233. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/real_models/__init__.py +0 -0
  234. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/real_models/_provider.py +0 -0
  235. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/real_models/_readiness.py +0 -0
  236. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/real_models/_reliability.py +0 -0
  237. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/real_models/_result.py +0 -0
  238. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/real_models/mint_bedrock_token.py +0 -0
  239. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/real_models/test_bedrock_converse.py +0 -0
  240. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/real_models/test_deploy_programs.py +0 -0
  241. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/real_models/test_multi_client_stress.py +0 -0
  242. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/real_models/test_optimize_client_committee.py +0 -0
  243. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/real_models/test_optimize_continuation.py +0 -0
  244. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/real_models/test_optimize_loop.py +0 -0
  245. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/real_models/test_optimize_loop_wasm.py +0 -0
  246. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/real_models/test_optimize_stress.py +0 -0
  247. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/real_models/test_provider_roles.py +0 -0
  248. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/real_models/test_readiness.py +0 -0
  249. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/real_models/test_real_provider_twins.py +0 -0
  250. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/real_models/test_reliability.py +0 -0
  251. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/real_models/test_reliability_classify.py +0 -0
  252. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/real_models/test_rlm_wasm.py +0 -0
  253. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/real_models/test_trace_search.py +0 -0
  254. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/span_reference_fixture.py +0 -0
  255. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_adapter_reentrancy.py +0 -0
  256. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_assessments_api.py +0 -0
  257. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_authored.py +0 -0
  258. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_authored_binding_credentials.py +0 -0
  259. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_authored_bundle_collisions.py +0 -0
  260. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_authored_metric_contract.py +0 -0
  261. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_authored_named_models.py +0 -0
  262. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_authored_optimize.py +0 -0
  263. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_callback.py +0 -0
  264. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_candidate_lineage.py +0 -0
  265. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_cli/__init__.py +0 -0
  266. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_cli/conftest.py +0 -0
  267. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_cli/test_api_client.py +0 -0
  268. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_cli/test_assessments.py +0 -0
  269. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_cli/test_auth.py +0 -0
  270. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_cli/test_credentials.py +0 -0
  271. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_cli/test_datasets.py +0 -0
  272. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_cli/test_deployment_runs.py +0 -0
  273. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_cli/test_deployments.py +0 -0
  274. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_cli/test_evals.py +0 -0
  275. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_cli/test_login.py +0 -0
  276. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_cli/test_main.py +0 -0
  277. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_cli/test_optimizations.py +0 -0
  278. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_cli/test_org.py +0 -0
  279. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_cli/test_pagination.py +0 -0
  280. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_cli/test_parity.py +0 -0
  281. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_cli/test_programs.py +0 -0
  282. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_cli/test_provider_credentials.py +0 -0
  283. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_cli/test_schema_sample.py +0 -0
  284. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_cli/test_shell.py +0 -0
  285. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_cli/test_tool_servers.py +0 -0
  286. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_cli/test_top.py +0 -0
  287. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_cli/test_traces.py +0 -0
  288. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_cli/test_traces_program_and_module.py +0 -0
  289. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_cli/test_traces_search_wire.py +0 -0
  290. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_cli/test_tree_help.py +0 -0
  291. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_cli/test_valsets.py +0 -0
  292. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_client.py +0 -0
  293. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_client_floor.py +0 -0
  294. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_client_program_names.py +0 -0
  295. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_clustering/__init__.py +0 -0
  296. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_clustering/conftest.py +0 -0
  297. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_clustering/test_edge_cases.py +0 -0
  298. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_clustering/test_hash_consistency.py +0 -0
  299. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_clustering/test_type_conversion.py +0 -0
  300. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_cmp551_grouping_identity.py +0 -0
  301. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_configuration.py +0 -0
  302. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_context.py +0 -0
  303. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_context_propagation.py +0 -0
  304. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_credential_kwargs.py +0 -0
  305. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_credential_selection.py +0 -0
  306. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_credential_values.py +0 -0
  307. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_dataset_polling.py +0 -0
  308. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_dataset_sync.py +0 -0
  309. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_datasets.py +0 -0
  310. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_decision_client_spans.py +0 -0
  311. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_decorators.py +0 -0
  312. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_deploy.py +0 -0
  313. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_deploy_mcp_tool_references.py +0 -0
  314. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_deploy_program_id.py +0 -0
  315. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_deployment_metadata.py +0 -0
  316. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_deployment_runs.py +0 -0
  317. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_deployments_read.py +0 -0
  318. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_eval.py +0 -0
  319. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_eval_example_attribution.py +0 -0
  320. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_eval_program_id.py +0 -0
  321. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_eval_start.py +0 -0
  322. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_eval_trace_grouping.py +0 -0
  323. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_exception_paths.py +0 -0
  324. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_execute.py +0 -0
  325. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_execute_run_identity.py +0 -0
  326. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_exporter.py +0 -0
  327. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_exporter_program_names.py +0 -0
  328. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_exporter_queue.py +0 -0
  329. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_exporter_real.py +0 -0
  330. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_fake_lm.py +0 -0
  331. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_gepa_callback.py +0 -0
  332. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_gepa_integration.py +0 -0
  333. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_gepa_output_normalization.py +0 -0
  334. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_gepa_resume.py +0 -0
  335. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_identity.py +0 -0
  336. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_imaging.py +0 -0
  337. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_import_weight.py +0 -0
  338. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_ingest_conformance.py +0 -0
  339. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_ingest_second_producer.py +0 -0
  340. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_integration.py +0 -0
  341. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_interpreter_callback.py +0 -0
  342. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_ir_encoder_properties.py +0 -0
  343. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_ir_golden_vectors.py +0 -0
  344. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_ir_roundtrip.py +0 -0
  345. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_lm15_native_calls.py +0 -0
  346. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_lm_configuration.py +0 -0
  347. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_lm_usage_shapes.py +0 -0
  348. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_mcp_tools.py +0 -0
  349. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_models.py +0 -0
  350. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_multi_client_stress_readiness.py +0 -0
  351. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_no_signature_hash_on_the_wire.py +0 -0
  352. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_optimization_phase_callback.py +0 -0
  353. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_optimization_program_names.py +0 -0
  354. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_optimization_progress.py +0 -0
  355. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_optimization_start.py +0 -0
  356. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_optimize.py +0 -0
  357. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_optimize_budget.py +0 -0
  358. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_optimize_lift.py +0 -0
  359. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_optimize_lms.py +0 -0
  360. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_optimize_proposer.py +0 -0
  361. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_optimize_reflection_lm.py +0 -0
  362. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_optimize_terminal_failure.py +0 -0
  363. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_packaging.py +0 -0
  364. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_packaging_callable_source.py +0 -0
  365. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_packaging_mcp_tools.py +0 -0
  366. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_packaging_program_source.py +0 -0
  367. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_poll_until.py +0 -0
  368. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_program_id_deprecation.py +0 -0
  369. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_program_identity.py +0 -0
  370. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_program_lineage_persist.py +0 -0
  371. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_program_names_in_deploy.py +0 -0
  372. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_program_naming.py +0 -0
  373. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_programs_create.py +0 -0
  374. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_project_payload.py +0 -0
  375. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_real_provider_twins_readiness.py +0 -0
  376. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_reflector_properties.py +0 -0
  377. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_reflector_smoke.py +0 -0
  378. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_release_gate_script.py +0 -0
  379. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_release_real_models_script.py +0 -0
  380. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_replaced_names.py +0 -0
  381. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_repro_reactv2_bugs.py +0 -0
  382. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_require_version_bump.py +0 -0
  383. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_retry.py +0 -0
  384. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_reversible_failures.py +0 -0
  385. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_rlm_patch.py +0 -0
  386. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_run_attribution_paths.py +0 -0
  387. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_runtime_tools.py +0 -0
  388. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_schemas.py +0 -0
  389. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_seal_lm_credential.py +0 -0
  390. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_seed_review_run.py +0 -0
  391. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_signature_inputs.py +0 -0
  392. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_span_references.py +0 -0
  393. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_span_sent_once.py +0 -0
  394. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_system_one.py +0 -0
  395. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_trace_context_concurrency.py +0 -0
  396. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_trace_fact_wire_contract.py +0 -0
  397. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_trace_facts.py +0 -0
  398. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_trace_render.py +0 -0
  399. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_traces_read.py +0 -0
  400. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_tracked_gepa.py +0 -0
  401. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_tracker_enrich.py +0 -0
  402. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_truncation.py +0 -0
  403. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_upload_auth_headers.py +0 -0
  404. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_valsets_api.py +0 -0
  405. {cmpnd-0.78.0 → cmpnd-0.80.0}/tests/test_xxh64.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: cmpnd
3
- Version: 0.78.0
3
+ Version: 0.80.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>
@@ -9,7 +9,8 @@ queue. `cmpnd admin user …` is the operator's user-lifecycle surface (list,
9
9
  inspect, create, approve/reject the pending-signup queue, promote/demote admin,
10
10
  disable/enable, reset a password, and manage a user's API-key scopes). `cmpnd
11
11
  admin org plan …` and `cmpnd admin org overrides …` move an org between plans
12
- and override one of its limits, `cmpnd admin plans …` edits each plan's
12
+ and override one of its limits, `cmpnd admin org flags …` pins a feature flag
13
+ for one org, `cmpnd admin plans …` edits each plan's
13
14
  default limits and feature flags, and `cmpnd admin signup …` sets who may sign up
14
15
  and the plan a new account's org lands on. `cmpnd admin feature-flags …` reads and
15
16
  toggles the server's runtime flags. These hit
@@ -153,6 +154,25 @@ def _register_org(sub: _SubParsersAction[ArgumentParser]) -> None:
153
154
  override_delete.add_argument("name", help="Limit name")
154
155
  override_delete.set_defaults(func=handle_org_overrides_delete)
155
156
 
157
+ flags = osub.add_parser("flags", help="An org's own feature flags")
158
+ fsub = flags.add_subparsers(dest="org_flags_action")
159
+ flags_list = fsub.add_parser(
160
+ "list", help="List every flag with the org's, its plan's and the global value, and what serve resolves"
161
+ )
162
+ _org_id_arg(flags_list)
163
+ flags_list.set_defaults(func=handle_org_flags_list)
164
+ flag_update = fsub.add_parser("update", help="Pin a feature flag on (or, with --disabled, off) for the org")
165
+ _org_id_arg(flag_update)
166
+ flag_update.add_argument("name", help="Flag name; the flag must already exist")
167
+ flag_update.add_argument("--disabled", action="store_true", help="Pin the flag off (default is on)")
168
+ flag_update.set_defaults(func=handle_org_flags_update)
169
+ flag_delete = fsub.add_parser(
170
+ "delete", help="Delete the org's row for a flag so it follows its plan and the global value"
171
+ )
172
+ _org_id_arg(flag_delete)
173
+ flag_delete.add_argument("name", help="Flag name")
174
+ flag_delete.set_defaults(func=handle_org_flags_delete)
175
+
156
176
 
157
177
  def _register_user(sub: _SubParsersAction[ArgumentParser]) -> None:
158
178
  user = sub.add_parser("user", help="User lifecycle management")
@@ -182,8 +202,14 @@ def _register_user(sub: _SubParsersAction[ArgumentParser]) -> None:
182
202
  create.add_argument("--admin", dest="admin", action="store_true", help="Grant platform-admin")
183
203
  create.set_defaults(func=handle_user_create)
184
204
 
185
- approve = usub.add_parser("approve", help="Approve a pending signup")
205
+ approve = usub.add_parser("approve", help="Approve a pending membership")
186
206
  approve.add_argument("id", help="User id")
207
+ approve.add_argument(
208
+ "--org-id",
209
+ dest="org_id",
210
+ default="",
211
+ help="Org whose membership to approve (default: the user's active org)",
212
+ )
187
213
  approve.set_defaults(func=handle_user_approve)
188
214
 
189
215
  promote = usub.add_parser("promote", help="Grant platform-admin")
@@ -382,6 +408,21 @@ def handle_org_overrides_delete(client: api_client.ApiClient, args: Any) -> Any:
382
408
  return client.delete(f"/api/v1/admin/organizations/{args.org_id}/limits/{args.name}")
383
409
 
384
410
 
411
+ def handle_org_flags_list(client: api_client.ApiClient, args: Any) -> Any:
412
+ return client.get(f"/api/v1/admin/organizations/{args.org_id}/feature-flags")
413
+
414
+
415
+ def handle_org_flags_update(client: api_client.ApiClient, args: Any) -> Any:
416
+ return client.put(
417
+ f"/api/v1/admin/organizations/{args.org_id}/feature-flags/{args.name}",
418
+ json={"enabled": not args.disabled},
419
+ )
420
+
421
+
422
+ def handle_org_flags_delete(client: api_client.ApiClient, args: Any) -> Any:
423
+ return client.delete(f"/api/v1/admin/organizations/{args.org_id}/feature-flags/{args.name}")
424
+
425
+
385
426
  # --- plan handlers --------------------------------------------------------
386
427
 
387
428
 
@@ -457,7 +498,30 @@ def handle_user_create(client: api_client.ApiClient, args: Any) -> Any:
457
498
 
458
499
 
459
500
  def handle_user_approve(client: api_client.ApiClient, args: Any) -> Any:
460
- return client.patch(f"/api/v1/admin/users/{args.id}", json={"is_approved": True})
501
+ user_path = f"/api/v1/admin/users/{args.id}"
502
+ org_id = args.org_id or client.get(user_path)["org_id"]
503
+ try:
504
+ return client.post(f"{user_path}/approve", json={"org_id": org_id})
505
+ except api_client.CliError as err:
506
+ if not _route_unmounted(err):
507
+ raise
508
+ # A server older than the approve route approves only the active org,
509
+ # through PATCH.
510
+ if args.org_id:
511
+ raise api_client.CliError(
512
+ "This server cannot approve a membership in a named org. Upgrade it, or omit --org-id "
513
+ "to approve the membership in the user's active org."
514
+ ) from err
515
+ return client.patch(user_path, json={"is_approved": True})
516
+
517
+
518
+ def _route_unmounted(err: api_client.CliError) -> bool:
519
+ """Whether a 404 came from a server that has no such route.
520
+
521
+ Go's ServeMux answers an unmounted route with plain text. A mounted route's
522
+ own 404 is JSON, such as an approval for a membership that does not exist.
523
+ """
524
+ return err.status_code == 404 and "404 page not found" in str(err)
461
525
 
462
526
 
463
527
  def handle_user_promote(client: api_client.ApiClient, args: Any) -> Any:
@@ -494,6 +494,8 @@ stores one key per org per endpoint in `~/.config/cmpnd/credentials.json`, or
494
494
  `$CMPND_CONFIG_DIR/credentials.json` when that variable is set. The file has
495
495
  mode 0600. An active pointer names the org whose key commands use.
496
496
  `cmpnd login` stores a new key beside the others and makes its org active.
497
+ When you belong to more than one org, the approval page asks which org the
498
+ key is for and starts on your active org in the web app.
497
499
 
498
500
  - `cmpnd login --org <slug-or-id>` mints a key for that org instead of the
499
501
  active one. The approval page names the org, and serve refuses an org where
@@ -891,6 +893,14 @@ EMAIL` withdraws the open owner invites sent to that address, and the links
891
893
  stop working. `cmpnd admin org show` lists pending addresses under
892
894
  `seed.pending_owner_emails`.
893
895
 
896
+ `cmpnd admin user approve USER_ID --org-id ORG_ID` approves the user's pending
897
+ membership in that org, which need not be their active org. Without
898
+ `--org-id` it approves the membership in their active org, and a server
899
+ older than the approve route approves it the way older releases did. Serve applies the
900
+ operator queue's rules. A member waiting to join an org that has its own owner
901
+ belongs to that owner's queue, so serve refuses it with 400. `cmpnd admin user
902
+ reject USER_ID --org-id ORG_ID` declines a pending membership.
903
+
894
904
  ### Plans, limits and signups
895
905
 
896
906
  Every org has a plan, `free`, `pro` or `enterprise`, and each plan sets
@@ -927,6 +937,13 @@ PLAN NAME [--disabled]` pins a flag for the plan, and `flags delete` hands the
927
937
  plan back to the global default. A plan's flag must already exist, so create
928
938
  it first with `cmpnd admin feature-flags set`.
929
939
 
940
+ `cmpnd admin org flags list ORG_ID` shows every flag with the org's own row,
941
+ its plan's row and the global row, each `null` when absent, and `enabled`, the
942
+ value serve resolves for the org. `cmpnd admin org flags update ORG_ID NAME
943
+ [--disabled]` pins a flag for that org alone, which beats its plan and the
944
+ global value. `flags delete ORG_ID NAME` hands the org back to its plan and the
945
+ global value. The operator org page writes the same rows.
946
+
930
947
  `cmpnd admin signup show` reports who may sign up and the plan a new account's
931
948
  org lands on. `cmpnd admin signup update --mode closed|invite|open` overrides
932
949
  the installation's `CMPND_SERVE_SIGNUP_MODE`, and `--mode installation` follows
@@ -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.78.0"
8
+ version = "0.80.0"
9
9
  description = "DSPy observability and deployment SDK for cmpnd"
10
10
  readme = "README.md"
11
11
  requires-python = ">=3.11"
@@ -2,8 +2,15 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import json
5
6
  from argparse import Namespace
7
+ from collections.abc import Callable
8
+ from unittest import mock
6
9
 
10
+ import httpx
11
+ import pytest
12
+
13
+ from cmpnd.cli import api_client
7
14
  from cmpnd.cli.commands import admin
8
15
 
9
16
 
@@ -183,11 +190,15 @@ class TestAdminUser:
183
190
  },
184
191
  )
185
192
 
186
- def test_approve_patches_is_approved(self, mock_client):
187
- mock_client.patch.return_value = {"id": "u_1", "is_approved": True}
188
- result = admin.handle_user_approve(mock_client, Namespace(id="u_1"))
189
- mock_client.patch.assert_called_once_with("/api/v1/admin/users/u_1", json={"is_approved": True})
190
- assert result["is_approved"] is True
193
+ def test_approve_parser_takes_an_optional_org(self):
194
+ from argparse import ArgumentParser
195
+
196
+ parser = ArgumentParser()
197
+ admin.register(parser.add_subparsers())
198
+ args = parser.parse_args(["admin", "user", "approve", "u_1", "--org-id", "o_2"])
199
+ assert args.org_id == "o_2"
200
+ assert args.func is admin.handle_user_approve
201
+ assert parser.parse_args(["admin", "user", "approve", "u_1"]).org_id == ""
191
202
 
192
203
  def test_promote_patches_is_admin_true(self, mock_client):
193
204
  mock_client.patch.return_value = {"id": "u_1", "is_admin": True}
@@ -413,3 +424,105 @@ class TestAdminSignup:
413
424
  with pytest.raises(SystemExit):
414
425
  args.func(mock_client, args)
415
426
  mock_client.patch.assert_not_called()
427
+
428
+
429
+ def _serve(answer: Callable[[httpx.Request], httpx.Response]):
430
+ """A real ApiClient over a captured transport: `sent` collects each request."""
431
+ sent: list[httpx.Request] = []
432
+
433
+ def handle(request: httpx.Request) -> httpx.Response:
434
+ sent.append(request)
435
+ return answer(request)
436
+
437
+ real = httpx.Client
438
+ patch = mock.patch("httpx.Client", lambda **kwargs: real(**kwargs, transport=httpx.MockTransport(handle)))
439
+ return api_client.ApiClient("k", "http://serve.test"), sent, patch
440
+
441
+
442
+ def _wire(sent: list[httpx.Request]) -> list[tuple[str, str, object]]:
443
+ return [(r.method, r.url.path, json.loads(r.content) if r.content else None) for r in sent]
444
+
445
+
446
+ # Go's ServeMux answers an unmounted route with this plain-text 404.
447
+ _UNMOUNTED = httpx.Response(404, text="404 page not found\n")
448
+
449
+
450
+ class TestAdminUserApproveWire:
451
+ def test_approve_posts_the_named_org(self):
452
+ client, sent, patch = _serve(lambda _r: httpx.Response(200, json={"newly_approved": True}))
453
+ with patch:
454
+ result = admin.handle_user_approve(client, _parse("user", "approve", "u_1", "--org-id", "o_2"))
455
+ assert _wire(sent) == [("POST", "/api/v1/admin/users/u_1/approve", {"org_id": "o_2"})]
456
+ assert result["newly_approved"] is True
457
+
458
+ def test_approve_without_org_approves_the_active_org(self):
459
+ def answer(request: httpx.Request) -> httpx.Response:
460
+ if request.method == "GET":
461
+ return httpx.Response(200, json={"id": "u_1", "org_id": "o_1"})
462
+ return httpx.Response(200, json={"newly_approved": True})
463
+
464
+ client, sent, patch = _serve(answer)
465
+ with patch:
466
+ admin.handle_user_approve(client, _parse("user", "approve", "u_1"))
467
+ assert _wire(sent) == [
468
+ ("GET", "/api/v1/admin/users/u_1", None),
469
+ ("POST", "/api/v1/admin/users/u_1/approve", {"org_id": "o_1"}),
470
+ ]
471
+
472
+ def test_approve_without_org_falls_back_to_patch_on_a_server_without_the_route(self):
473
+ def answer(request: httpx.Request) -> httpx.Response:
474
+ if request.method == "GET":
475
+ return httpx.Response(200, json={"id": "u_1", "org_id": "o_1"})
476
+ if request.method == "POST":
477
+ return _UNMOUNTED
478
+ return httpx.Response(200, json={"id": "u_1", "is_approved": True})
479
+
480
+ client, sent, patch = _serve(answer)
481
+ with patch:
482
+ result = admin.handle_user_approve(client, _parse("user", "approve", "u_1"))
483
+ assert _wire(sent)[-1] == ("PATCH", "/api/v1/admin/users/u_1", {"is_approved": True})
484
+ assert result["is_approved"] is True
485
+
486
+ def test_approve_with_org_on_a_server_without_the_route_says_so(self):
487
+ client, sent, patch = _serve(lambda _r: _UNMOUNTED)
488
+ with patch, pytest.raises(api_client.CliError, match="--org-id"):
489
+ admin.handle_user_approve(client, _parse("user", "approve", "u_1", "--org-id", "o_2"))
490
+ assert [r.method for r in sent] == ["POST"]
491
+
492
+ def test_a_missing_membership_is_not_mistaken_for_an_old_server(self):
493
+ def answer(request: httpx.Request) -> httpx.Response:
494
+ if request.method == "GET":
495
+ return httpx.Response(200, json={"id": "u_1", "org_id": "o_1"})
496
+ return httpx.Response(404, json={"error": "no membership for that user in that org"})
497
+
498
+ client, sent, patch = _serve(answer)
499
+ with patch, pytest.raises(api_client.CliError, match="no membership"):
500
+ admin.handle_user_approve(client, _parse("user", "approve", "u_1"))
501
+ assert [r.method for r in sent] == ["GET", "POST"]
502
+
503
+
504
+ class TestAdminOrgFlagsWire:
505
+ def _run(self, *argv: str) -> list[tuple[str, str, object]]:
506
+ client, sent, patch = _serve(lambda _r: httpx.Response(200, json={"org_id": "o_1", "flags": []}))
507
+ args = _parse("org", "flags", *argv)
508
+ with patch:
509
+ args.func(client, args)
510
+ return _wire(sent)
511
+
512
+ def test_list_reads_every_flag_as_it_resolves_for_the_org(self):
513
+ assert self._run("list", "o_1") == [("GET", "/api/v1/admin/organizations/o_1/feature-flags", None)]
514
+
515
+ def test_update_pins_the_flag_on_by_default(self):
516
+ assert self._run("update", "o_1", "beta") == [
517
+ ("PUT", "/api/v1/admin/organizations/o_1/feature-flags/beta", {"enabled": True})
518
+ ]
519
+
520
+ def test_update_disabled_pins_the_flag_off(self):
521
+ assert self._run("update", "o_1", "beta", "--disabled") == [
522
+ ("PUT", "/api/v1/admin/organizations/o_1/feature-flags/beta", {"enabled": False})
523
+ ]
524
+
525
+ def test_delete_removes_the_orgs_row(self):
526
+ assert self._run("delete", "o_1", "beta") == [
527
+ ("DELETE", "/api/v1/admin/organizations/o_1/feature-flags/beta", None)
528
+ ]
@@ -505,7 +505,7 @@ wheels = [
505
505
 
506
506
  [[package]]
507
507
  name = "cmpnd"
508
- version = "0.78.0"
508
+ version = "0.80.0"
509
509
  source = { editable = "." }
510
510
  default-groups = ["dspy-3-4-1"]
511
511
  dependencies = [
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes