solwyn-cli 0.1.0__tar.gz → 0.2.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 (508) hide show
  1. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/.github/workflows/ci.yml +23 -25
  2. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/.github/workflows/publish.yml +14 -5
  3. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/.gitignore +1 -0
  4. solwyn_cli-0.2.0/CONTRIBUTING.md +58 -0
  5. solwyn_cli-0.2.0/Makefile +8 -0
  6. solwyn_cli-0.2.0/PKG-INFO +151 -0
  7. solwyn_cli-0.2.0/README.md +132 -0
  8. solwyn_cli-0.2.0/docs/caller-owned-spend.md +133 -0
  9. solwyn_cli-0.2.0/docs/commands/alerts.mdx +43 -0
  10. solwyn_cli-0.2.0/docs/commands/attest.mdx +50 -0
  11. solwyn_cli-0.2.0/docs/commands/costs.mdx +128 -0
  12. solwyn_cli-0.2.0/docs/commands/forecast.mdx +30 -0
  13. solwyn_cli-0.2.0/docs/commands/overview.mdx +32 -0
  14. solwyn_cli-0.2.0/docs/commands/status.mdx +24 -0
  15. solwyn_cli-0.2.0/docs/core-followups.md +120 -0
  16. solwyn_cli-0.2.0/docs/mcp-bounded-work.md +157 -0
  17. solwyn_cli-0.2.0/docs/mcp-diagnostics.md +111 -0
  18. solwyn_cli-0.2.0/docs/mcp-profiles.md +138 -0
  19. solwyn_cli-0.2.0/docs/mcp-quickstart.md +247 -0
  20. solwyn_cli-0.2.0/docs/mcp-release.md +114 -0
  21. solwyn_cli-0.2.0/docs/media-confirmation.md +131 -0
  22. solwyn_cli-0.2.0/docs/registry/server.draft.json +25 -0
  23. solwyn_cli-0.2.0/docs/registry/server.schema.2025-12-11.json +574 -0
  24. solwyn_cli-0.2.0/docs/registry/server.schema.2025-12-11.sha256 +1 -0
  25. solwyn_cli-0.2.0/docs/scripting.mdx +24 -0
  26. solwyn_cli-0.2.0/docs/staging-smoke.md +136 -0
  27. solwyn_cli-0.2.0/examples/mcp/python/client.py +234 -0
  28. solwyn_cli-0.2.0/examples/mcp/python/pyproject.toml +8 -0
  29. solwyn_cli-0.2.0/examples/mcp/python/uv.lock +728 -0
  30. solwyn_cli-0.2.0/examples/mcp/typescript/.gitignore +2 -0
  31. solwyn_cli-0.2.0/examples/mcp/typescript/client.test.ts +108 -0
  32. solwyn_cli-0.2.0/examples/mcp/typescript/client.ts +145 -0
  33. solwyn_cli-0.2.0/examples/mcp/typescript/package-lock.json +558 -0
  34. solwyn_cli-0.2.0/examples/mcp/typescript/package.json +20 -0
  35. solwyn_cli-0.2.0/examples/mcp/typescript/tsconfig.json +13 -0
  36. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/pyproject.toml +3 -2
  37. solwyn_cli-0.2.0/scripts/budget-plane-cli-smoke.py +8 -0
  38. solwyn_cli-0.2.0/scripts/budget-plane-mcp-smoke.py +441 -0
  39. solwyn_cli-0.2.0/scripts/budget_plane_smoke.py +828 -0
  40. solwyn_cli-0.2.0/scripts/generate_contract.py +57 -0
  41. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/scripts/inspect_wheel.py +7 -0
  42. solwyn_cli-0.2.0/scripts/locks/mcp-legacy.in +2 -0
  43. solwyn_cli-0.2.0/scripts/locks/mcp-legacy.txt +545 -0
  44. solwyn_cli-0.2.0/scripts/mcp_wheel_smoke.py +649 -0
  45. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/scripts/sync_spec.py +65 -4
  46. solwyn_cli-0.2.0/scripts/validate_mcp_registry.py +102 -0
  47. solwyn_cli-0.2.0/src/solwyn_cli/__init__.py +6 -0
  48. solwyn_cli-0.2.0/src/solwyn_cli/_mcp_doctor_helper.py +155 -0
  49. solwyn_cli-0.2.0/src/solwyn_cli/_mcp_doctor_ipc.py +75 -0
  50. solwyn_cli-0.2.0/src/solwyn_cli/_mcp_doctor_pipe.py +93 -0
  51. solwyn_cli-0.2.0/src/solwyn_cli/_mcp_doctor_process.py +87 -0
  52. solwyn_cli-0.2.0/src/solwyn_cli/_mcp_launch.py +41 -0
  53. solwyn_cli-0.2.0/src/solwyn_cli/_mcp_operation.py +305 -0
  54. solwyn_cli-0.2.0/src/solwyn_cli/_vendor/batch.py +131 -0
  55. solwyn_cli-0.2.0/src/solwyn_cli/_vendor/notification_wire.py +125 -0
  56. solwyn_cli-0.2.0/src/solwyn_cli/_vendor/wire.py +391 -0
  57. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/src/solwyn_cli/artifacts/__init__.py +16 -1
  58. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/src/solwyn_cli/artifacts/_atomic.py +4 -1
  59. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/src/solwyn_cli/client.py +48 -14
  60. solwyn_cli-0.2.0/src/solwyn_cli/commands/_cost_advice_models.py +135 -0
  61. solwyn_cli-0.2.0/src/solwyn_cli/commands/_cost_filters.py +93 -0
  62. solwyn_cli-0.2.0/src/solwyn_cli/commands/_cost_models.py +136 -0
  63. solwyn_cli-0.2.0/src/solwyn_cli/commands/_entitlement.py +110 -0
  64. solwyn_cli-0.2.0/src/solwyn_cli/commands/_notifications_common.py +307 -0
  65. solwyn_cli-0.2.0/src/solwyn_cli/commands/_record.py +196 -0
  66. solwyn_cli-0.2.0/src/solwyn_cli/commands/_tags.py +44 -0
  67. solwyn_cli-0.2.0/src/solwyn_cli/commands/account.py +55 -0
  68. solwyn_cli-0.2.0/src/solwyn_cli/commands/alerts.py +606 -0
  69. solwyn_cli-0.2.0/src/solwyn_cli/commands/attest.py +279 -0
  70. solwyn_cli-0.2.0/src/solwyn_cli/commands/audit.py +276 -0
  71. solwyn_cli-0.2.0/src/solwyn_cli/commands/budget.py +2225 -0
  72. solwyn_cli-0.2.0/src/solwyn_cli/commands/budget_rules.py +755 -0
  73. solwyn_cli-0.2.0/src/solwyn_cli/commands/channels.py +340 -0
  74. solwyn_cli-0.2.0/src/solwyn_cli/commands/cost_analysis.py +313 -0
  75. solwyn_cli-0.2.0/src/solwyn_cli/commands/cost_pricing.py +268 -0
  76. solwyn_cli-0.2.0/src/solwyn_cli/commands/costs.py +941 -0
  77. solwyn_cli-0.2.0/src/solwyn_cli/commands/doctor.py +499 -0
  78. solwyn_cli-0.2.0/src/solwyn_cli/commands/forecast.py +138 -0
  79. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/src/solwyn_cli/commands/init.py +67 -5
  80. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/src/solwyn_cli/commands/keys.py +13 -2
  81. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/src/solwyn_cli/commands/login.py +1 -1
  82. solwyn_cli-0.2.0/src/solwyn_cli/commands/mcp.py +53 -0
  83. solwyn_cli-0.2.0/src/solwyn_cli/commands/mcp_config.py +63 -0
  84. solwyn_cli-0.2.0/src/solwyn_cli/commands/mcp_doctor.py +349 -0
  85. solwyn_cli-0.2.0/src/solwyn_cli/commands/notifications.py +194 -0
  86. solwyn_cli-0.2.0/src/solwyn_cli/commands/overview.py +140 -0
  87. solwyn_cli-0.2.0/src/solwyn_cli/commands/plan.py +162 -0
  88. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/src/solwyn_cli/commands/projects.py +263 -3
  89. solwyn_cli-0.2.0/src/solwyn_cli/commands/providers.py +399 -0
  90. solwyn_cli-0.2.0/src/solwyn_cli/commands/record.py +368 -0
  91. solwyn_cli-0.2.0/src/solwyn_cli/commands/runs.py +709 -0
  92. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/src/solwyn_cli/commands/status.py +130 -13
  93. solwyn_cli-0.2.0/src/solwyn_cli/commands/tags.py +328 -0
  94. solwyn_cli-0.2.0/src/solwyn_cli/commands/webhooks.py +506 -0
  95. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/src/solwyn_cli/commands/whoami.py +41 -2
  96. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/src/solwyn_cli/config.py +11 -0
  97. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/src/solwyn_cli/errors.py +37 -0
  98. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/src/solwyn_cli/exit_codes.py +1 -1
  99. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/src/solwyn_cli/main.py +41 -2
  100. solwyn_cli-0.2.0/src/solwyn_cli/mcp/declarations.py +97 -0
  101. solwyn_cli-0.2.0/src/solwyn_cli/mcp/parameters.py +262 -0
  102. solwyn_cli-0.2.0/src/solwyn_cli/mcp/server.py +2297 -0
  103. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/src/solwyn_cli/output.py +11 -2
  104. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/src/solwyn_cli/runtime.py +35 -3
  105. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/src/solwyn_cli/spec/openapi_snapshot.json +15247 -6586
  106. solwyn_cli-0.2.0/tests/contract/__init__.py +1 -0
  107. solwyn_cli-0.2.0/tests/contract/account_cost_query_parameters.json +69 -0
  108. solwyn_cli-0.2.0/tests/contract/alert_query_parameters.json +314 -0
  109. solwyn_cli-0.2.0/tests/contract/builder.py +246 -0
  110. solwyn_cli-0.2.0/tests/contract/cli_contract.json +7269 -0
  111. solwyn_cli-0.2.0/tests/contract/cost_query_parameters.json +1045 -0
  112. solwyn_cli-0.2.0/tests/fixtures/mcp_doctor_server.py +131 -0
  113. solwyn_cli-0.2.0/tests/fixtures/mcp_doctor_telemetry.py +79 -0
  114. solwyn_cli-0.2.0/tests/fixtures/mcp_doctor_wheel_smoke.py +239 -0
  115. solwyn_cli-0.2.0/tests/fixtures/mcp_installed_legacy.py +68 -0
  116. solwyn_cli-0.2.0/tests/golden/account-alert-email-clear-json.json +1 -0
  117. solwyn_cli-0.2.0/tests/golden/account-alert-email-clear-table.txt +3 -0
  118. solwyn_cli-0.2.0/tests/golden/account-alert-email-set-json.json +1 -0
  119. solwyn_cli-0.2.0/tests/golden/account-alert-email-set-table.txt +3 -0
  120. solwyn_cli-0.2.0/tests/golden/account-alert-email-show-json.json +1 -0
  121. solwyn_cli-0.2.0/tests/golden/account-alert-email-show-table.txt +3 -0
  122. solwyn_cli-0.2.0/tests/golden/agent-context.txt +38 -0
  123. solwyn_cli-0.2.0/tests/golden/alerts-account-delete-json.json +1 -0
  124. solwyn_cli-0.2.0/tests/golden/alerts-account-delete-table.txt +2 -0
  125. solwyn_cli-0.2.0/tests/golden/alerts-account-preview-json.json +1 -0
  126. solwyn_cli-0.2.0/tests/golden/alerts-account-preview-table.txt +6 -0
  127. solwyn_cli-0.2.0/tests/golden/alerts-account-set-json.json +1 -0
  128. solwyn_cli-0.2.0/tests/golden/alerts-account-set-table.txt +11 -0
  129. solwyn_cli-0.2.0/tests/golden/alerts-account-show-json.json +1 -0
  130. solwyn_cli-0.2.0/tests/golden/alerts-account-show-table.txt +11 -0
  131. solwyn_cli-0.2.0/tests/golden/alerts-account-snooze-json.json +1 -0
  132. solwyn_cli-0.2.0/tests/golden/alerts-account-snooze-table.txt +2 -0
  133. solwyn_cli-0.2.0/tests/golden/alerts-account-unsnooze-json.json +1 -0
  134. solwyn_cli-0.2.0/tests/golden/alerts-account-unsnooze-table.txt +2 -0
  135. solwyn_cli-0.2.0/tests/golden/alerts-list-json.json +1 -0
  136. solwyn_cli-0.2.0/tests/golden/alerts-list-table.txt +2 -0
  137. solwyn_cli-0.2.0/tests/golden/alerts-show-json.json +1 -0
  138. solwyn_cli-0.2.0/tests/golden/alerts-show-table.txt +2 -0
  139. solwyn_cli-0.2.0/tests/golden/attest-account-csv.txt +8 -0
  140. solwyn_cli-0.2.0/tests/golden/attest-project-json.json +1 -0
  141. solwyn_cli-0.2.0/tests/golden/audit-json.json +1 -0
  142. solwyn_cli-0.2.0/tests/golden/audit-table.txt +15 -0
  143. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/budget-check-allow-json.json +1 -1
  144. solwyn_cli-0.2.0/tests/golden/budget-check-allow-table.txt +11 -0
  145. solwyn_cli-0.2.0/tests/golden/budget-check-batch-allowed.json +1 -0
  146. solwyn_cli-0.2.0/tests/golden/budget-check-batch-allowed.table +2 -0
  147. solwyn_cli-0.2.0/tests/golden/budget-check-batch-denied.json +1 -0
  148. solwyn_cli-0.2.0/tests/golden/budget-check-batch-denied.table +2 -0
  149. solwyn_cli-0.2.0/tests/golden/budget-check-batch-mixed.json +1 -0
  150. solwyn_cli-0.2.0/tests/golden/budget-check-batch-mixed.table +5 -0
  151. solwyn_cli-0.2.0/tests/golden/budget-check-batch-partial.json +1 -0
  152. solwyn_cli-0.2.0/tests/golden/budget-check-batch-partial.table +33 -0
  153. solwyn_cli-0.2.0/tests/golden/budget-check-batch-stopped.json +1 -0
  154. solwyn_cli-0.2.0/tests/golden/budget-check-batch-stopped.table +4 -0
  155. solwyn_cli-0.2.0/tests/golden/budget-check-batch-unknown.json +1 -0
  156. solwyn_cli-0.2.0/tests/golden/budget-check-batch-unknown.table +2 -0
  157. solwyn_cli-0.2.0/tests/golden/budget-check-deny-json.json +1 -0
  158. solwyn_cli-0.2.0/tests/golden/budget-check-deny-table.txt +13 -0
  159. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/budget-check-fail-open-json.json +1 -1
  160. solwyn_cli-0.2.0/tests/golden/budget-check-fail-open-table.txt +11 -0
  161. solwyn_cli-0.2.0/tests/golden/budget-check-read-only-key-json.json +1 -0
  162. solwyn_cli-0.2.0/tests/golden/budget-check-read-only-key-table.txt +3 -0
  163. solwyn_cli-0.2.0/tests/golden/budget-check-run-stopped-json.json +1 -0
  164. solwyn_cli-0.2.0/tests/golden/budget-check-run-stopped-table.txt +12 -0
  165. solwyn_cli-0.2.0/tests/golden/budget-check-tag-deny-json.json +1 -0
  166. solwyn_cli-0.2.0/tests/golden/budget-check-tag-deny-table.txt +11 -0
  167. solwyn_cli-0.2.0/tests/golden/budget-confirm-expired-json.json +1 -0
  168. solwyn_cli-0.2.0/tests/golden/budget-confirm-expired-table.txt +4 -0
  169. solwyn_cli-0.2.0/tests/golden/budget-confirm-success-json.json +1 -0
  170. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/budget-confirm-success-table.txt +2 -0
  171. solwyn_cli-0.2.0/tests/golden/budget-restore-defaults-json.json +1 -0
  172. solwyn_cli-0.2.0/tests/golden/budget-restore-defaults-table.txt +55 -0
  173. solwyn_cli-0.2.0/tests/golden/budget-rule-add-budget_threshold-json.json +1 -0
  174. solwyn_cli-0.2.0/tests/golden/budget-rule-add-budget_threshold-table.txt +10 -0
  175. solwyn_cli-0.2.0/tests/golden/budget-rule-add-daily_anomaly-json.json +1 -0
  176. solwyn_cli-0.2.0/tests/golden/budget-rule-add-daily_anomaly-table.txt +11 -0
  177. solwyn_cli-0.2.0/tests/golden/budget-rule-add-forecast_overrun-json.json +1 -0
  178. solwyn_cli-0.2.0/tests/golden/budget-rule-add-forecast_overrun-table.txt +11 -0
  179. solwyn_cli-0.2.0/tests/golden/budget-rule-add-runaway_run-json.json +1 -0
  180. solwyn_cli-0.2.0/tests/golden/budget-rule-add-runaway_run-table.txt +13 -0
  181. solwyn_cli-0.2.0/tests/golden/budget-rule-add-scoped_budget-json.json +1 -0
  182. solwyn_cli-0.2.0/tests/golden/budget-rule-add-scoped_budget-table.txt +15 -0
  183. solwyn_cli-0.2.0/tests/golden/budget-rule-add-unit_cost_anomaly-json.json +1 -0
  184. solwyn_cli-0.2.0/tests/golden/budget-rule-add-unit_cost_anomaly-table.txt +11 -0
  185. solwyn_cli-0.2.0/tests/golden/budget-rule-pause-json.json +1 -0
  186. solwyn_cli-0.2.0/tests/golden/budget-rule-pause-table.txt +4 -0
  187. solwyn_cli-0.2.0/tests/golden/budget-rule-preview-json.json +1 -0
  188. solwyn_cli-0.2.0/tests/golden/budget-rule-preview-table.txt +2 -0
  189. solwyn_cli-0.2.0/tests/golden/budget-rule-remove-json.json +1 -0
  190. solwyn_cli-0.2.0/tests/golden/budget-rule-remove-table.txt +4 -0
  191. solwyn_cli-0.2.0/tests/golden/budget-rule-resume-json.json +1 -0
  192. solwyn_cli-0.2.0/tests/golden/budget-rule-resume-table.txt +4 -0
  193. solwyn_cli-0.2.0/tests/golden/budget-rule-snooze-json.json +1 -0
  194. solwyn_cli-0.2.0/tests/golden/budget-rule-snooze-table.txt +2 -0
  195. solwyn_cli-0.2.0/tests/golden/budget-rule-unsnooze-json.json +1 -0
  196. solwyn_cli-0.2.0/tests/golden/budget-rule-unsnooze-table.txt +2 -0
  197. solwyn_cli-0.2.0/tests/golden/budget-rules-list-json.json +1 -0
  198. solwyn_cli-0.2.0/tests/golden/budget-rules-list-table.txt +55 -0
  199. solwyn_cli-0.2.0/tests/golden/budget-set-json.json +1 -0
  200. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/budget-set-table.txt +1 -1
  201. solwyn_cli-0.2.0/tests/golden/budget-status-json.json +1 -0
  202. solwyn_cli-0.2.0/tests/golden/budget-status-rules-json.json +1 -0
  203. solwyn_cli-0.2.0/tests/golden/budget-status-rules-table.txt +12 -0
  204. solwyn_cli-0.2.0/tests/golden/budget-status-table.txt +10 -0
  205. solwyn_cli-0.2.0/tests/golden/budget-threshold-snooze-json.json +1 -0
  206. solwyn_cli-0.2.0/tests/golden/budget-threshold-snooze-table.txt +2 -0
  207. solwyn_cli-0.2.0/tests/golden/budget-threshold-unsnooze-json.json +1 -0
  208. solwyn_cli-0.2.0/tests/golden/budget-threshold-unsnooze-table.txt +2 -0
  209. solwyn_cli-0.2.0/tests/golden/channels-create-json.json +1 -0
  210. solwyn_cli-0.2.0/tests/golden/channels-create-table.txt +10 -0
  211. solwyn_cli-0.2.0/tests/golden/channels-delete-json.json +1 -0
  212. solwyn_cli-0.2.0/tests/golden/channels-delete-table.txt +3 -0
  213. solwyn_cli-0.2.0/tests/golden/channels-list-json.json +1 -0
  214. solwyn_cli-0.2.0/tests/golden/channels-list-table.txt +2 -0
  215. solwyn_cli-0.2.0/tests/golden/channels-show-json.json +1 -0
  216. solwyn_cli-0.2.0/tests/golden/channels-show-table.txt +10 -0
  217. solwyn_cli-0.2.0/tests/golden/channels-test-json.json +1 -0
  218. solwyn_cli-0.2.0/tests/golden/channels-test-table.txt +3 -0
  219. solwyn_cli-0.2.0/tests/golden/channels-update-json.json +1 -0
  220. solwyn_cli-0.2.0/tests/golden/channels-update-table.txt +10 -0
  221. solwyn_cli-0.2.0/tests/golden/costs-account-json.json +1 -0
  222. solwyn_cli-0.2.0/tests/golden/costs-account-table.txt +2 -0
  223. solwyn_cli-0.2.0/tests/golden/costs-account-withheld-json.json +1 -0
  224. solwyn_cli-0.2.0/tests/golden/costs-account-withheld-table.txt +2 -0
  225. solwyn_cli-0.2.0/tests/golden/costs-agent_run-json.json +1 -0
  226. solwyn_cli-0.2.0/tests/golden/costs-agent_run-table.txt +2 -0
  227. solwyn_cli-0.2.0/tests/golden/costs-baseline-json.json +1 -0
  228. solwyn_cli-0.2.0/tests/golden/costs-baseline-table.txt +2 -0
  229. solwyn_cli-0.2.0/tests/golden/costs-day-json.json +1 -0
  230. solwyn_cli-0.2.0/tests/golden/costs-drift-json.json +1 -0
  231. solwyn_cli-0.2.0/tests/golden/costs-drift-table.txt +3 -0
  232. solwyn_cli-0.2.0/tests/golden/costs-events-continuation-stderr.txt +1 -0
  233. solwyn_cli-0.2.0/tests/golden/costs-events-json.json +1 -0
  234. solwyn_cli-0.2.0/tests/golden/costs-events-table.txt +4 -0
  235. solwyn_cli-0.2.0/tests/golden/costs-failover_reason-json.json +1 -0
  236. solwyn_cli-0.2.0/tests/golden/costs-failover_reason-table.txt +2 -0
  237. solwyn_cli-0.2.0/tests/golden/costs-model-json.json +1 -0
  238. solwyn_cli-0.2.0/tests/golden/costs-priced-models-json.json +1 -0
  239. solwyn_cli-0.2.0/tests/golden/costs-priced-models-table.txt +3 -0
  240. solwyn_cli-0.2.0/tests/golden/costs-provider-json.json +1 -0
  241. solwyn_cli-0.2.0/tests/golden/costs-provider_region-json.json +1 -0
  242. solwyn_cli-0.2.0/tests/golden/costs-provider_region-table.txt +2 -0
  243. solwyn_cli-0.2.0/tests/golden/costs-service_tier-json.json +1 -0
  244. solwyn_cli-0.2.0/tests/golden/costs-service_tier-table.txt +2 -0
  245. solwyn_cli-0.2.0/tests/golden/costs-simulation-json.json +1 -0
  246. solwyn_cli-0.2.0/tests/golden/costs-simulation-table.txt +13 -0
  247. solwyn_cli-0.2.0/tests/golden/costs-status-json.json +1 -0
  248. solwyn_cli-0.2.0/tests/golden/costs-status-table.txt +2 -0
  249. solwyn_cli-0.2.0/tests/golden/costs-tag-customer-json.json +1 -0
  250. solwyn_cli-0.2.0/tests/golden/costs-tag-customer-table.txt +2 -0
  251. solwyn_cli-0.2.0/tests/golden/costs-total-json.json +1 -0
  252. solwyn_cli-0.2.0/tests/golden/costs-total-table.txt +2 -0
  253. solwyn_cli-0.2.0/tests/golden/costs-truncated-json.json +1 -0
  254. solwyn_cli-0.2.0/tests/golden/costs-truncated-table.txt +3 -0
  255. solwyn_cli-0.2.0/tests/golden/costs-unit-economics-json.json +1 -0
  256. solwyn_cli-0.2.0/tests/golden/costs-unit-economics-table.txt +4 -0
  257. solwyn_cli-0.2.0/tests/golden/doctor-degraded-table.txt +10 -0
  258. solwyn_cli-0.2.0/tests/golden/doctor-jwt.json +1 -0
  259. solwyn_cli-0.2.0/tests/golden/doctor-mcp-key.json +1 -0
  260. solwyn_cli-0.2.0/tests/golden/forecast-table.txt +9 -0
  261. solwyn_cli-0.2.0/tests/golden/forecast.json +1 -0
  262. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/keys-rotate-json.json +1 -1
  263. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/keys-rotate-table.txt +1 -0
  264. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/keys-show-json.json +1 -1
  265. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/keys-show-table.txt +1 -0
  266. solwyn_cli-0.2.0/tests/golden/mcp-config.json +1 -0
  267. solwyn_cli-0.2.0/tests/golden/mcp-tools.json +11363 -0
  268. solwyn_cli-0.2.0/tests/golden/notifications-set-json.json +1 -0
  269. solwyn_cli-0.2.0/tests/golden/notifications-set-table.txt +9 -0
  270. solwyn_cli-0.2.0/tests/golden/notifications-show-json.json +1 -0
  271. solwyn_cli-0.2.0/tests/golden/notifications-show-table.txt +9 -0
  272. solwyn_cli-0.2.0/tests/golden/notifications-test-json.json +1 -0
  273. solwyn_cli-0.2.0/tests/golden/notifications-test-table.txt +3 -0
  274. solwyn_cli-0.2.0/tests/golden/overview-json.json +1 -0
  275. solwyn_cli-0.2.0/tests/golden/overview-paid-json.json +1 -0
  276. solwyn_cli-0.2.0/tests/golden/overview-table.txt +13 -0
  277. solwyn_cli-0.2.0/tests/golden/plan-team-table.txt +29 -0
  278. solwyn_cli-0.2.0/tests/golden/plan-team.json +1 -0
  279. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/projects-create-display-json.json +1 -1
  280. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/projects-create-display-table.txt +1 -0
  281. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/projects-create-stored-json.json +1 -1
  282. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/projects-create-stored-table.txt +1 -0
  283. solwyn_cli-0.2.0/tests/golden/projects-delete-json.json +1 -0
  284. solwyn_cli-0.2.0/tests/golden/projects-delete-table.txt +4 -0
  285. solwyn_cli-0.2.0/tests/golden/projects-rename-json.json +1 -0
  286. solwyn_cli-0.2.0/tests/golden/projects-rename-table.txt +7 -0
  287. solwyn_cli-0.2.0/tests/golden/providers-failovers-table.txt +15 -0
  288. solwyn_cli-0.2.0/tests/golden/providers-failovers.json +1 -0
  289. solwyn_cli-0.2.0/tests/golden/providers-untracked-table.txt +10 -0
  290. solwyn_cli-0.2.0/tests/golden/providers-untracked.json +1 -0
  291. solwyn_cli-0.2.0/tests/golden/record-batch-json.json +1 -0
  292. solwyn_cli-0.2.0/tests/golden/record-batch-table.txt +7 -0
  293. solwyn_cli-0.2.0/tests/golden/record-dedup-json.json +1 -0
  294. solwyn_cli-0.2.0/tests/golden/record-dedup-table.txt +6 -0
  295. solwyn_cli-0.2.0/tests/golden/record-legacy-json.json +1 -0
  296. solwyn_cli-0.2.0/tests/golden/record-legacy-table.txt +6 -0
  297. solwyn_cli-0.2.0/tests/golden/record-rejection-json.json +1 -0
  298. solwyn_cli-0.2.0/tests/golden/record-rejection-table.txt +6 -0
  299. solwyn_cli-0.2.0/tests/golden/record-single-json.json +1 -0
  300. solwyn_cli-0.2.0/tests/golden/record-single-table.txt +6 -0
  301. solwyn_cli-0.2.0/tests/golden/runs-list-jwt-json.json +1 -0
  302. solwyn_cli-0.2.0/tests/golden/runs-list-key-table.txt +9 -0
  303. solwyn_cli-0.2.0/tests/golden/runs-show-json.json +1 -0
  304. solwyn_cli-0.2.0/tests/golden/runs-show-table.txt +16 -0
  305. solwyn_cli-0.2.0/tests/golden/runs-stop-json.json +1 -0
  306. solwyn_cli-0.2.0/tests/golden/runs-stop-key-refusal-json.json +1 -0
  307. solwyn_cli-0.2.0/tests/golden/runs-stop-key-refusal-table.txt +3 -0
  308. solwyn_cli-0.2.0/tests/golden/runs-stop-not-stoppable-json.json +1 -0
  309. solwyn_cli-0.2.0/tests/golden/runs-stop-not-stoppable-table.txt +1 -0
  310. solwyn_cli-0.2.0/tests/golden/runs-stop-table.txt +8 -0
  311. solwyn_cli-0.2.0/tests/golden/status-flags-table.txt +34 -0
  312. solwyn_cli-0.2.0/tests/golden/status-flags.json +1 -0
  313. solwyn_cli-0.2.0/tests/golden/status-jwt-savings-json.json +1 -0
  314. solwyn_cli-0.2.0/tests/golden/status-jwt-savings-table.txt +24 -0
  315. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/status-table.txt +7 -0
  316. solwyn_cli-0.2.0/tests/golden/status.json +1 -0
  317. solwyn_cli-0.2.0/tests/golden/tags-list-json.json +1 -0
  318. solwyn_cli-0.2.0/tests/golden/tags-list-table.txt +2 -0
  319. solwyn_cli-0.2.0/tests/golden/tags-retire-json.json +1 -0
  320. solwyn_cli-0.2.0/tests/golden/tags-retire-table.txt +2 -0
  321. solwyn_cli-0.2.0/tests/golden/tags-values-json.json +1 -0
  322. solwyn_cli-0.2.0/tests/golden/tags-values-table.txt +2 -0
  323. solwyn_cli-0.2.0/tests/golden/webhooks-create-json.json +1 -0
  324. solwyn_cli-0.2.0/tests/golden/webhooks-create-table.txt +10 -0
  325. solwyn_cli-0.2.0/tests/golden/webhooks-delete-json.json +1 -0
  326. solwyn_cli-0.2.0/tests/golden/webhooks-delete-table.txt +4 -0
  327. solwyn_cli-0.2.0/tests/golden/webhooks-list-json.json +1 -0
  328. solwyn_cli-0.2.0/tests/golden/webhooks-list-table.txt +2 -0
  329. solwyn_cli-0.2.0/tests/golden/webhooks-rotate-json.json +1 -0
  330. solwyn_cli-0.2.0/tests/golden/webhooks-rotate-table.txt +7 -0
  331. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/whoami-jwt-table.txt +3 -0
  332. solwyn_cli-0.2.0/tests/golden/whoami-jwt.json +1 -0
  333. solwyn_cli-0.2.0/tests/golden/whoami-key.json +1 -0
  334. solwyn_cli-0.2.0/tests/golden/whoami-production-json.json +1 -0
  335. solwyn_cli-0.2.0/tests/golden/whoami-production-table.txt +9 -0
  336. solwyn_cli-0.2.0/tests/mcp_batch_fixtures.py +32 -0
  337. solwyn_cli-0.2.0/tests/mcp_legacy_probe.py +92 -0
  338. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/test_agent_artifacts.py +41 -0
  339. solwyn_cli-0.2.0/tests/test_alert_query_contract.py +58 -0
  340. solwyn_cli-0.2.0/tests/test_alerts_command.py +462 -0
  341. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/test_atomic_rename.py +24 -0
  342. solwyn_cli-0.2.0/tests/test_attest_command.py +310 -0
  343. solwyn_cli-0.2.0/tests/test_attest_contract.py +153 -0
  344. solwyn_cli-0.2.0/tests/test_attest_models.py +61 -0
  345. solwyn_cli-0.2.0/tests/test_attribution_commands.py +426 -0
  346. solwyn_cli-0.2.0/tests/test_audit_command.py +352 -0
  347. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/test_auth_commands.py +68 -2
  348. solwyn_cli-0.2.0/tests/test_batch_journal_contract.py +74 -0
  349. solwyn_cli-0.2.0/tests/test_budget_batch.py +486 -0
  350. solwyn_cli-0.2.0/tests/test_budget_check_command.py +762 -0
  351. solwyn_cli-0.2.0/tests/test_budget_cli_smoke.py +296 -0
  352. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/test_budget_command.py +152 -0
  353. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/test_budget_confirm_command.py +147 -9
  354. solwyn_cli-0.2.0/tests/test_budget_mcp_smoke.py +109 -0
  355. solwyn_cli-0.2.0/tests/test_budget_rules_command.py +567 -0
  356. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/test_budget_set_command.py +160 -0
  357. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/test_ci_packaging_smoke.py +85 -14
  358. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/test_client.py +41 -3
  359. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/test_config.py +38 -0
  360. solwyn_cli-0.2.0/tests/test_contract_snapshot.py +216 -0
  361. solwyn_cli-0.2.0/tests/test_cost_advice_command.py +495 -0
  362. solwyn_cli-0.2.0/tests/test_cost_advice_contract.py +97 -0
  363. solwyn_cli-0.2.0/tests/test_cost_advice_registration.py +25 -0
  364. solwyn_cli-0.2.0/tests/test_cost_filters.py +42 -0
  365. solwyn_cli-0.2.0/tests/test_cost_query_contract.py +142 -0
  366. solwyn_cli-0.2.0/tests/test_cost_stream.py +166 -0
  367. solwyn_cli-0.2.0/tests/test_costs_command.py +1327 -0
  368. solwyn_cli-0.2.0/tests/test_doctor_command.py +370 -0
  369. solwyn_cli-0.2.0/tests/test_entitlement.py +74 -0
  370. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/test_errors.py +62 -0
  371. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/test_exit_codes.py +2 -1
  372. solwyn_cli-0.2.0/tests/test_forecast_command.py +207 -0
  373. solwyn_cli-0.2.0/tests/test_foundation.py +94 -0
  374. solwyn_cli-0.2.0/tests/test_help_snapshots.py +845 -0
  375. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/test_init_command.py +113 -0
  376. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/test_keys_command.py +76 -3
  377. solwyn_cli-0.2.0/tests/test_mcp_adoption.py +190 -0
  378. solwyn_cli-0.2.0/tests/test_mcp_batch_recovery.py +240 -0
  379. solwyn_cli-0.2.0/tests/test_mcp_boundary.py +605 -0
  380. solwyn_cli-0.2.0/tests/test_mcp_bounded_results.py +306 -0
  381. solwyn_cli-0.2.0/tests/test_mcp_cancellation_stdio.py +257 -0
  382. solwyn_cli-0.2.0/tests/test_mcp_catalog.py +281 -0
  383. solwyn_cli-0.2.0/tests/test_mcp_conformance.py +2285 -0
  384. solwyn_cli-0.2.0/tests/test_mcp_diagnostics.py +573 -0
  385. solwyn_cli-0.2.0/tests/test_mcp_doctor_pipe.py +91 -0
  386. solwyn_cli-0.2.0/tests/test_mcp_doctor_process.py +415 -0
  387. solwyn_cli-0.2.0/tests/test_mcp_operation.py +282 -0
  388. solwyn_cli-0.2.0/tests/test_mcp_pagination.py +122 -0
  389. solwyn_cli-0.2.0/tests/test_mcp_protocol_privacy.py +262 -0
  390. solwyn_cli-0.2.0/tests/test_mcp_registry.py +65 -0
  391. solwyn_cli-0.2.0/tests/test_mcp_sdk_migration.py +593 -0
  392. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/test_mcp_server.py +70 -26
  393. solwyn_cli-0.2.0/tests/test_mcp_transport_lifecycle.py +217 -0
  394. solwyn_cli-0.2.0/tests/test_mcp_wheel_runner.py +377 -0
  395. solwyn_cli-0.2.0/tests/test_media_confirmation.py +688 -0
  396. solwyn_cli-0.2.0/tests/test_notifications_commands.py +546 -0
  397. solwyn_cli-0.2.0/tests/test_notifications_review_regressions.py +303 -0
  398. solwyn_cli-0.2.0/tests/test_overview_command.py +206 -0
  399. solwyn_cli-0.2.0/tests/test_plan_command.py +192 -0
  400. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/test_projects_command.py +632 -7
  401. solwyn_cli-0.2.0/tests/test_providers_command.py +417 -0
  402. solwyn_cli-0.2.0/tests/test_record_helpers.py +257 -0
  403. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/test_request_drift.py +469 -5
  404. solwyn_cli-0.2.0/tests/test_response_subset.py +2114 -0
  405. solwyn_cli-0.2.0/tests/test_run_attribution_integration.py +163 -0
  406. solwyn_cli-0.2.0/tests/test_runs_command.py +590 -0
  407. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/test_runtime.py +52 -0
  408. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/test_smoke.py +3 -1
  409. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/test_snapshot_age.py +13 -0
  410. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/test_status_command.py +164 -13
  411. solwyn_cli-0.2.0/tests/test_tags_commands.py +244 -0
  412. solwyn_cli-0.2.0/tests/test_vendor_sync.py +189 -0
  413. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/test_vendor_wire.py +85 -4
  414. solwyn_cli-0.2.0/tests/test_webhooks_command.py +963 -0
  415. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/uv.lock +112 -41
  416. solwyn_cli-0.1.0/PKG-INFO +0 -60
  417. solwyn_cli-0.1.0/README.md +0 -41
  418. solwyn_cli-0.1.0/src/solwyn_cli/__init__.py +0 -3
  419. solwyn_cli-0.1.0/src/solwyn_cli/_vendor/wire.py +0 -185
  420. solwyn_cli-0.1.0/src/solwyn_cli/commands/budget.py +0 -976
  421. solwyn_cli-0.1.0/src/solwyn_cli/commands/costs.py +0 -186
  422. solwyn_cli-0.1.0/src/solwyn_cli/commands/mcp.py +0 -28
  423. solwyn_cli-0.1.0/src/solwyn_cli/mcp/server.py +0 -728
  424. solwyn_cli-0.1.0/tests/golden/agent-context.txt +0 -23
  425. solwyn_cli-0.1.0/tests/golden/budget-check-allow-table.txt +0 -10
  426. solwyn_cli-0.1.0/tests/golden/budget-check-deny-json.json +0 -1
  427. solwyn_cli-0.1.0/tests/golden/budget-check-deny-table.txt +0 -10
  428. solwyn_cli-0.1.0/tests/golden/budget-check-fail-open-table.txt +0 -10
  429. solwyn_cli-0.1.0/tests/golden/budget-confirm-expired-json.json +0 -1
  430. solwyn_cli-0.1.0/tests/golden/budget-confirm-expired-table.txt +0 -2
  431. solwyn_cli-0.1.0/tests/golden/budget-confirm-success-json.json +0 -1
  432. solwyn_cli-0.1.0/tests/golden/budget-set-json.json +0 -1
  433. solwyn_cli-0.1.0/tests/golden/budget-status-json.json +0 -1
  434. solwyn_cli-0.1.0/tests/golden/budget-status-table.txt +0 -8
  435. solwyn_cli-0.1.0/tests/golden/costs-day-json.json +0 -1
  436. solwyn_cli-0.1.0/tests/golden/costs-model-json.json +0 -1
  437. solwyn_cli-0.1.0/tests/golden/costs-provider-json.json +0 -1
  438. solwyn_cli-0.1.0/tests/golden/mcp-tools.json +0 -1879
  439. solwyn_cli-0.1.0/tests/golden/status.json +0 -1
  440. solwyn_cli-0.1.0/tests/golden/whoami-jwt.json +0 -1
  441. solwyn_cli-0.1.0/tests/golden/whoami-key.json +0 -1
  442. solwyn_cli-0.1.0/tests/test_budget_check_command.py +0 -385
  443. solwyn_cli-0.1.0/tests/test_costs_command.py +0 -427
  444. solwyn_cli-0.1.0/tests/test_help_snapshots.py +0 -303
  445. solwyn_cli-0.1.0/tests/test_mcp_conformance.py +0 -1095
  446. solwyn_cli-0.1.0/tests/test_response_subset.py +0 -938
  447. solwyn_cli-0.1.0/tests/test_vendor_sync.py +0 -95
  448. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  449. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  450. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/LICENSE +0 -0
  451. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/SECURITY.md +0 -0
  452. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/src/solwyn_cli/_vendor/__init__.py +0 -0
  453. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/src/solwyn_cli/_vendor/validation.py +0 -0
  454. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/src/solwyn_cli/auth.py +0 -0
  455. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/src/solwyn_cli/commands/__init__.py +0 -0
  456. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/src/solwyn_cli/commands/_shared.py +0 -0
  457. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/src/solwyn_cli/commands/agent_context.py +0 -0
  458. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/src/solwyn_cli/commands/config.py +0 -0
  459. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/src/solwyn_cli/help.py +0 -0
  460. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/src/solwyn_cli/mcp/__init__.py +0 -0
  461. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/src/solwyn_cli/spec/__init__.py +0 -0
  462. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/__init__.py +0 -0
  463. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/budget-confirm-missing-reservation-json.json +0 -0
  464. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/budget-confirm-missing-reservation-table.txt +0 -0
  465. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/costs-day-table.txt +0 -0
  466. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/costs-model-table.txt +0 -0
  467. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/costs-provider-table.txt +0 -0
  468. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/email-not-verified.json +0 -0
  469. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/error.json +0 -0
  470. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/harness.py +0 -0
  471. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/human-error.txt +0 -0
  472. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/init-json.json +0 -0
  473. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/init-table.txt +0 -0
  474. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/keys-environment-key-refusal-json.json +0 -0
  475. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/keys-environment-key-refusal-table.txt +0 -0
  476. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/keys-keyring-key-refusal-json.json +0 -0
  477. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/keys-keyring-key-refusal-table.txt +0 -0
  478. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/keys-not-found-json.json +0 -0
  479. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/keys-not-found-table.txt +0 -0
  480. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/keys-revoke-json.json +0 -0
  481. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/keys-revoke-table.txt +0 -0
  482. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/login-jwt-table.txt +0 -0
  483. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/login-jwt.json +0 -0
  484. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/login-key-table.txt +0 -0
  485. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/login-key.json +0 -0
  486. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/logout-table.txt +0 -0
  487. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/logout.json +0 -0
  488. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/projects-list-environment-key-refusal-json.json +0 -0
  489. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/projects-list-environment-key-refusal-table.txt +0 -0
  490. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/projects-list-jwt-json.json +0 -0
  491. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/projects-list-jwt-table.txt +0 -0
  492. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/projects-list-keyring-key-refusal-json.json +0 -0
  493. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/projects-list-keyring-key-refusal-table.txt +0 -0
  494. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/projects-show-jwt-json.json +0 -0
  495. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/projects-show-jwt-table.txt +0 -0
  496. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/projects-show-key-json.json +0 -0
  497. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/projects-show-key-table.txt +0 -0
  498. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/success.json +0 -0
  499. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/table-no-color.txt +0 -0
  500. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/table-non-tty.txt +0 -0
  501. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/table-tty.txt +0 -0
  502. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/golden/whoami-key-table.txt +0 -0
  503. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/test_auth.py +0 -0
  504. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/test_config_command.py +0 -0
  505. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/test_output.py +0 -0
  506. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/test_output_discipline.py +0 -0
  507. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/test_shared_command_auth.py +0 -0
  508. {solwyn_cli-0.1.0 → solwyn_cli-0.2.0}/tests/test_vendor_validation.py +0 -0
@@ -35,6 +35,10 @@ jobs:
35
35
  run: uv run --no-sync ruff check .
36
36
  - name: Ruff format check
37
37
  run: uv run --no-sync ruff format --check .
38
+ - name: Validate offline unpublished Registry draft
39
+ run: uv run --no-sync python scripts/validate_mcp_registry.py
40
+ - name: Check Python example lock
41
+ run: uv lock --check --project examples/mcp/python
38
42
 
39
43
  tests:
40
44
  name: Tests (Python ${{ matrix.python-version }})
@@ -57,42 +61,36 @@ jobs:
57
61
  version: ${{ env.UV_VERSION }}
58
62
  - name: Install dependencies
59
63
  run: uv sync --locked --all-groups
64
+ - name: Install actual legacy MCP client
65
+ run: |
66
+ uv venv --python "${{ matrix.python-version }}" "${{ runner.temp }}/mcp-legacy"
67
+ uv pip sync --python "${{ runner.temp }}/mcp-legacy/bin/python" --require-hashes scripts/locks/mcp-legacy.txt
60
68
  - name: Run tests
69
+ env:
70
+ SOLWYN_TEST_LEGACY_PYTHON: ${{ runner.temp }}/mcp-legacy/bin/python
61
71
  run: uv run --no-sync pytest
62
72
 
63
73
  packaging-smoke:
64
- name: Packaging smoke
65
- runs-on: ubuntu-latest
74
+ name: Wheel MCP (${{ matrix.os }}, Python ${{ matrix.python-version }})
75
+ runs-on: ${{ matrix.os }}
76
+ strategy:
77
+ fail-fast: false
78
+ matrix:
79
+ os: [ubuntu-latest, macos-latest, windows-latest]
80
+ python-version: ["3.11"]
66
81
  steps:
67
82
  - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
68
83
  - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
69
84
  with:
70
- python-version: "3.13"
85
+ python-version: ${{ matrix.python-version }}
71
86
  - uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
72
87
  with:
73
88
  enable-cache: true
74
89
  version: ${{ env.UV_VERSION }}
90
+ - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
91
+ with:
92
+ node-version: "24"
75
93
  - name: Install locked dependencies
76
94
  run: uv sync --locked --all-groups
77
- - name: Build distributions
78
- run: uv build --clear
79
- - name: Select exactly one wheel
80
- id: wheel
81
- run: |
82
- shopt -s nullglob
83
- wheels=(dist/*.whl)
84
- if [[ "${#wheels[@]}" -ne 1 ]]; then
85
- echo "expected exactly one wheel, found ${#wheels[@]}" >&2
86
- exit 1
87
- fi
88
- printf 'path=%s\n' "${wheels[0]}" >> "$GITHUB_OUTPUT"
89
- - name: Inspect wheel metadata and contents
90
- run: uv run --no-sync python scripts/inspect_wheel.py "${{ steps.wheel.outputs.path }}"
91
- - name: Test both console entrypoints from the wheel
92
- run: |
93
- wheel="$(realpath "${{ steps.wheel.outputs.path }}")"
94
- smoke_dir="$(mktemp -d)"
95
- trap 'rm -rf "$smoke_dir"' EXIT
96
- cd "$smoke_dir"
97
- UV_CACHE_DIR="$smoke_dir/cache" uvx --from "$wheel" solwyn --version
98
- UV_CACHE_DIR="$smoke_dir/cache" uvx --from "$wheel" solwyn-cli --version
95
+ - name: Run installed-wheel Python, TypeScript, legacy clients and packaged doctor
96
+ run: uv run --no-sync python scripts/mcp_wheel_smoke.py --python "${{ matrix.python-version }}"
@@ -12,7 +12,16 @@ jobs:
12
12
  - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
13
13
  with:
14
14
  fetch-depth: 0
15
- - uses: hynek/build-and-inspect-python-package@d44ca7d91762de7a7d5436ddae667c6da6d1c3df # v2
15
+ - id: package
16
+ uses: hynek/build-and-inspect-python-package@2abe76da66d0a6a4a227101f9348ee855797cfa5 # v3.0.1
17
+ - name: Verify release tag matches package version
18
+ env:
19
+ PACKAGE_VERSION: ${{ steps.package.outputs.package_version }}
20
+ run: |
21
+ if [[ "v${PACKAGE_VERSION}" != "${GITHUB_REF_NAME}" ]]; then
22
+ echo "::error::Tag ${GITHUB_REF_NAME} does not match package version ${PACKAGE_VERSION}. Expected v${PACKAGE_VERSION}."
23
+ exit 1
24
+ fi
16
25
 
17
26
  test:
18
27
  name: Test built package
@@ -33,10 +42,10 @@ jobs:
33
42
  with:
34
43
  name: Packages
35
44
  path: dist
36
- - name: Install built package and test dependencies
45
+ - name: Install locked test dependencies
37
46
  run: |
38
- uv venv --python "${{ matrix.python-version }}"
39
- uv pip install --python .venv/bin/python dist/*.whl pytest
47
+ uv sync --locked --all-groups --no-install-project --python "${{ matrix.python-version }}"
48
+ uv pip install --python .venv/bin/python --no-deps dist/*.whl
40
49
  - name: Test built package
41
50
  run: uv run --no-project --python .venv/bin/python pytest tests/ -v --tb=short
42
51
 
@@ -55,4 +64,4 @@ jobs:
55
64
  with:
56
65
  name: Packages
57
66
  path: dist
58
- - uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # release/v1
67
+ - uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # release/v1
@@ -12,3 +12,4 @@ __pycache__/
12
12
  dist/
13
13
  build/
14
14
  *.egg-info/
15
+ .worktrees
@@ -0,0 +1,58 @@
1
+ # Contributing to Solwyn CLI
2
+
3
+ Solwyn CLI uses [uv](https://docs.astral.sh/uv/) for dependency management and command
4
+ execution. Set up a checkout and run the standard verification with:
5
+
6
+ ```console
7
+ uv sync --locked --all-groups
8
+ uv run ruff check .
9
+ uv run ruff format --check .
10
+ uv run pytest
11
+ ```
12
+
13
+ For deployed API validation, export a staging account JWT as `SOLWYN_JWT` and run
14
+ `make smoke-cli` or `make smoke-mcp`. Each command creates a disposable project,
15
+ records synthetic durable spend, tests budget enforcement and reporting, and
16
+ archives the project afterward. See [staging smoke tests](docs/staging-smoke.md)
17
+ for prerequisites, coverage, and dashboard inspection options.
18
+
19
+ ## Command and output contracts
20
+
21
+ Treat command names, flags, help text, exit codes, stdout/stderr behavior, and JSON schemas as
22
+ public interfaces. When one changes, regenerate the machine-readable CLI contract:
23
+
24
+ ```console
25
+ uv run python scripts/generate_contract.py
26
+ ```
27
+
28
+ Response parsers stay fail-closed. Adopt new Core response fields in the response registry,
29
+ and register every request mirror and every intentionally unadopted optional request field.
30
+ Do not relax a drift guard to make a new Core contract pass.
31
+
32
+ ## OpenAPI snapshot updates
33
+
34
+ The CLI vendors Core's customer OpenAPI document so normal development, releases, and public
35
+ CI do not need access to the private Core repository. An authorized maintainer updates it from
36
+ a clean Core `main` checkout:
37
+
38
+ ```console
39
+ uv run python scripts/sync_spec.py ../core
40
+ ```
41
+
42
+ The sync records both the UTC date and the exact Core commit. Review the resulting request and
43
+ response drift failures, adopt or explicitly decline every field, regenerate the CLI contract
44
+ when the surface changes, and run the full test suite before committing the snapshot.
45
+
46
+ Snapshot age and snapshot content answer different questions. The public age check tells us
47
+ how long it has been since a maintainer performed a sync. It cannot determine whether Core's
48
+ contract changed during that time. Content comparison requires a current private Core checkout,
49
+ so it belongs in Core or private infrastructure and must never be added to public CLI CI. See
50
+ [Core contract follow-ups](docs/core-followups.md#private-openapi-content-drift-monitor) for the
51
+ proposed monitor and ownership; implementation is tracked in
52
+ [Core issue #403](https://github.com/solwyn-ai/core/issues/403).
53
+
54
+ ## Pull requests
55
+
56
+ Keep pull requests focused and include the verification commands and results in the description.
57
+ If the change affects CLI behavior, name the corresponding `solwyn-docs` pages that need an
58
+ update. Do not include credentials, provider payloads, prompts, or responses in fixtures or logs.
@@ -0,0 +1,8 @@
1
+ .PHONY: smoke-cli smoke-mcp
2
+
3
+ # Creates synthetic durable spend in a disposable staging project; requires SOLWYN_JWT.
4
+ smoke-cli:
5
+ @uv run --locked python scripts/budget-plane-cli-smoke.py $(SMOKE_ARGS)
6
+
7
+ smoke-mcp:
8
+ @uv run --locked python scripts/budget-plane-mcp-smoke.py $(SMOKE_ARGS)
@@ -0,0 +1,151 @@
1
+ Metadata-Version: 2.5
2
+ Name: solwyn-cli
3
+ Version: 0.2.0
4
+ Summary: Command-line client for Solwyn
5
+ Author-email: Solwyn <hello@solwyn.ai>
6
+ License-Expression: Apache-2.0
7
+ License-File: LICENSE
8
+ Requires-Python: >=3.11
9
+ Requires-Dist: click>=8.1
10
+ Requires-Dist: httpx>=0.27
11
+ Requires-Dist: keyring>=25
12
+ Requires-Dist: mcp==2.1.1
13
+ Requires-Dist: platformdirs>=4
14
+ Requires-Dist: pydantic>=2
15
+ Requires-Dist: rich>=13
16
+ Requires-Dist: tomli-w>=1
17
+ Requires-Dist: typer>=0.12
18
+ Description-Content-Type: text/markdown
19
+
20
+ # Solwyn CLI
21
+
22
+ Work with Solwyn from the command line: enforce and attribute LLM spend for calls the Solwyn SDK does not instrument, inspect budgets, costs, and provider health, and recover from leaked or expired project keys — from your terminal, your scripts, or your coding agent.
23
+
24
+ > **Status:** pre-release. This repository is private while the first release is prepared, and the package is not yet published to PyPI.
25
+
26
+ ## Installation
27
+
28
+ Until the first release, install from a local checkout:
29
+
30
+ ```console
31
+ uv tool install .
32
+ solwyn --version
33
+ ```
34
+
35
+ Requires Python 3.11 or newer. The package installs two identical executables: `solwyn` and `solwyn-cli` (an alias matching the package name).
36
+
37
+ ## Getting started
38
+
39
+ ```console
40
+ solwyn login # authenticate; use --with-key to store a project key instead
41
+ solwyn init # configure Solwyn for the current repository
42
+ solwyn status # project budget and provider health at a glance
43
+ ```
44
+
45
+ `solwyn init` authenticates, selects a project, writes local configuration, detects the provider SDKs your code imports, prints the wiring for each, and verifies your budget end-to-end. Add `--agents` to also write guidance files for Claude, Cursor, and `AGENTS.md`.
46
+
47
+ ## Three ways to use it
48
+
49
+ Calls made through the Solwyn Python SDK are enforced and attributed automatically. The CLI covers the three cases the SDK cannot reach.
50
+
51
+ ### Give a coding agent a budget
52
+
53
+ `solwyn mcp` serves read, guardrail, and attribution tools to any MCP client over local stdio, resolving configuration and credentials fresh on every call. Standard MCP capability and schema discovery exposes the exact tools and input/output shapes in the running version. `solwyn agent-context` prints a compact SDK 0.6 capability contract suitable for pasting into an agent's context, and `solwyn init --agents` writes the equivalent guidance into the repository.
54
+
55
+ ```console
56
+ solwyn --project proj_0123456789abcdef01234567 mcp --profile read # 13 read tools
57
+ solwyn --project proj_0123456789abcdef01234567 mcp # default guardrails profile, all 17 tools
58
+ solwyn doctor --mcp # verify the wiring
59
+ ```
60
+
61
+ Start with the [MCP quickstart](docs/mcp-quickstart.md). Profiles are fixed at launch and never grant permissions; see [MCP profiles and tool contracts](docs/mcp-profiles.md) and the [agent integration guide](https://docs.solwyn.ai/docs/cli/agents).
62
+
63
+ ### Gate CI on budget
64
+
65
+ One pipeline step, one exit code, no code change. `budget status` is a pure read, so a read-only key is enough.
66
+
67
+ ```console
68
+ # Exit 4 when the project is at or over 80% of its monthly budget.
69
+ solwyn --json budget status --max-utilization 80
70
+ ```
71
+
72
+ See [Gate CI on budget](https://docs.solwyn.ai/docs/cli/ci-budget-gate).
73
+
74
+ ### Meter a call the SDK does not wrap
75
+
76
+ For a `curl`, another language, or a one-off script, reserve budget before the call and settle it after. A denied check exits with code 4, so scripts stop before they spend.
77
+
78
+ ```console
79
+ # 1. Reserve immediately before the call.
80
+ solwyn budget check --provider openai --model gpt-4.1 --estimated-input-tokens 1200
81
+
82
+ # 2. Make the provider call yourself.
83
+
84
+ # 3. Settle with what the call actually used. This also records attribution.
85
+ solwyn budget confirm --call-id 12345678-1234-1234-1234-123456789abc --provider openai --model gpt-4.1 \
86
+ --reservation-id "$RESERVATION" --input-tokens 1180 --output-tokens 640
87
+ ```
88
+
89
+ The CLI's caller-owned workflow maintains parity with Solwyn Python SDK 0.6.0 semantics and covers enforcement and attribution. Use `record` for a completed call that had no reservation, such as a local model. The same loop prices image, video, audio, and speech calls by their billed units, declares fallback intent, scopes enforcement to a single agent run, and reserves for a batch of calls at once; see [Meter un-instrumented calls](https://docs.solwyn.ai/docs/cli/metering-uninstrumented-calls) for the walkthrough and [caller-owned spend reference](docs/caller-owned-spend.md) for the full rules.
90
+
91
+ ## Commands
92
+
93
+ Every command's `--help` states its exit codes, authentication requirements, and JSON output schema.
94
+
95
+ | Group | Commands |
96
+ | --- | --- |
97
+ | Setup and identity | `init`, `login`, `logout`, `whoami`, `doctor` |
98
+ | Monitoring | `status`, `costs`, `forecast`, `overview`, `providers` |
99
+ | Budget guardrails | `budget status` / `check` / `confirm` / `set`, `record`, `runs` |
100
+ | Agents | `mcp`, `mcp-config`, `agent-context` |
101
+ | Administration | `budget rules` / `rule` / `threshold`, `alerts`, `channels`, `notifications`, `webhooks`, `keys`, `projects`, `account`, `tags`, `audit`, `attest`, `plan`, `config` |
102
+
103
+ The administration group is for operators and is needed rarely. The full reference for every command lives in the [CLI docs](https://docs.solwyn.ai/docs/cli).
104
+
105
+ ## Scripting
106
+
107
+ All commands support `--json` for schema-bearing JSON output (each payload names its schema, e.g. `solwyn.costs.v1`), and exit codes are stable and documented per command: `0` success, `2` usage, with distinct codes for API, auth, budget-denial, and not-found failures. Global flags select the project (`--project`), API base URL (`--api-url`), and output format, and go before the subcommand.
108
+
109
+ ## Trust posture
110
+
111
+ Solwyn CLI:
112
+
113
+ - sends only your own spend events; `sdk_instance_id` is an invocation ID (the retained operation UUID for recoverable MCP batches); no telemetry;
114
+ - never captures, logs, or transmits prompts or responses;
115
+ - never collects, stores, or proxies provider API keys;
116
+ - has no telemetry, update checks, or phone-home behavior; and
117
+ - stores Solwyn credentials only in the operating system keychain, never in configuration files, command-line arguments, or output.
118
+
119
+ ## Development
120
+
121
+ The project uses [uv](https://docs.astral.sh/uv/) for dependency and environment management.
122
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for the full local workflow and contract-update rules.
123
+
124
+ ```console
125
+ uv sync --locked --all-groups
126
+ uv run solwyn --version
127
+ uv run ruff check .
128
+ uv run ruff format --check .
129
+ uv run pytest
130
+ ```
131
+
132
+ Two test-suite properties worth knowing before contributing:
133
+
134
+ - Any change to the CLI surface (commands, flags, help text, exit codes, JSON output) requires regenerating the machine-readable contract snapshot with `scripts/generate_contract.py`; `tests/test_contract_snapshot.py` fails until you do.
135
+ - The vendored OpenAPI snapshot and its drift guards are self-invalidating by design — adopt fields properly or record a decline in the registry; never loosen a guard to make a test pass.
136
+
137
+ The vendored snapshot has two independent safeguards: public CLI CI checks its age and the
138
+ checked-in request/response contracts, while a proposed private monitor compares its content
139
+ with Core. The private monitor, ownership, and verified Core follow-ups are documented in
140
+ [Core contract follow-ups](docs/core-followups.md) and tracked in
141
+ [Core issue #403](https://github.com/solwyn-ai/core/issues/403).
142
+
143
+ Further in-repo references: [MCP release checklist](docs/mcp-release.md), [bounded MCP work and recovery](docs/mcp-bounded-work.md), [MCP diagnostics](docs/mcp-diagnostics.md), [media confirmation](docs/media-confirmation.md), and [staging smoke tests](docs/staging-smoke.md).
144
+
145
+ ## Security
146
+
147
+ Please report security issues privately as described in [SECURITY.md](SECURITY.md).
148
+
149
+ ## License
150
+
151
+ Licensed under the Apache License 2.0. See [LICENSE](LICENSE).
@@ -0,0 +1,132 @@
1
+ # Solwyn CLI
2
+
3
+ Work with Solwyn from the command line: enforce and attribute LLM spend for calls the Solwyn SDK does not instrument, inspect budgets, costs, and provider health, and recover from leaked or expired project keys — from your terminal, your scripts, or your coding agent.
4
+
5
+ > **Status:** pre-release. This repository is private while the first release is prepared, and the package is not yet published to PyPI.
6
+
7
+ ## Installation
8
+
9
+ Until the first release, install from a local checkout:
10
+
11
+ ```console
12
+ uv tool install .
13
+ solwyn --version
14
+ ```
15
+
16
+ Requires Python 3.11 or newer. The package installs two identical executables: `solwyn` and `solwyn-cli` (an alias matching the package name).
17
+
18
+ ## Getting started
19
+
20
+ ```console
21
+ solwyn login # authenticate; use --with-key to store a project key instead
22
+ solwyn init # configure Solwyn for the current repository
23
+ solwyn status # project budget and provider health at a glance
24
+ ```
25
+
26
+ `solwyn init` authenticates, selects a project, writes local configuration, detects the provider SDKs your code imports, prints the wiring for each, and verifies your budget end-to-end. Add `--agents` to also write guidance files for Claude, Cursor, and `AGENTS.md`.
27
+
28
+ ## Three ways to use it
29
+
30
+ Calls made through the Solwyn Python SDK are enforced and attributed automatically. The CLI covers the three cases the SDK cannot reach.
31
+
32
+ ### Give a coding agent a budget
33
+
34
+ `solwyn mcp` serves read, guardrail, and attribution tools to any MCP client over local stdio, resolving configuration and credentials fresh on every call. Standard MCP capability and schema discovery exposes the exact tools and input/output shapes in the running version. `solwyn agent-context` prints a compact SDK 0.6 capability contract suitable for pasting into an agent's context, and `solwyn init --agents` writes the equivalent guidance into the repository.
35
+
36
+ ```console
37
+ solwyn --project proj_0123456789abcdef01234567 mcp --profile read # 13 read tools
38
+ solwyn --project proj_0123456789abcdef01234567 mcp # default guardrails profile, all 17 tools
39
+ solwyn doctor --mcp # verify the wiring
40
+ ```
41
+
42
+ Start with the [MCP quickstart](docs/mcp-quickstart.md). Profiles are fixed at launch and never grant permissions; see [MCP profiles and tool contracts](docs/mcp-profiles.md) and the [agent integration guide](https://docs.solwyn.ai/docs/cli/agents).
43
+
44
+ ### Gate CI on budget
45
+
46
+ One pipeline step, one exit code, no code change. `budget status` is a pure read, so a read-only key is enough.
47
+
48
+ ```console
49
+ # Exit 4 when the project is at or over 80% of its monthly budget.
50
+ solwyn --json budget status --max-utilization 80
51
+ ```
52
+
53
+ See [Gate CI on budget](https://docs.solwyn.ai/docs/cli/ci-budget-gate).
54
+
55
+ ### Meter a call the SDK does not wrap
56
+
57
+ For a `curl`, another language, or a one-off script, reserve budget before the call and settle it after. A denied check exits with code 4, so scripts stop before they spend.
58
+
59
+ ```console
60
+ # 1. Reserve immediately before the call.
61
+ solwyn budget check --provider openai --model gpt-4.1 --estimated-input-tokens 1200
62
+
63
+ # 2. Make the provider call yourself.
64
+
65
+ # 3. Settle with what the call actually used. This also records attribution.
66
+ solwyn budget confirm --call-id 12345678-1234-1234-1234-123456789abc --provider openai --model gpt-4.1 \
67
+ --reservation-id "$RESERVATION" --input-tokens 1180 --output-tokens 640
68
+ ```
69
+
70
+ The CLI's caller-owned workflow maintains parity with Solwyn Python SDK 0.6.0 semantics and covers enforcement and attribution. Use `record` for a completed call that had no reservation, such as a local model. The same loop prices image, video, audio, and speech calls by their billed units, declares fallback intent, scopes enforcement to a single agent run, and reserves for a batch of calls at once; see [Meter un-instrumented calls](https://docs.solwyn.ai/docs/cli/metering-uninstrumented-calls) for the walkthrough and [caller-owned spend reference](docs/caller-owned-spend.md) for the full rules.
71
+
72
+ ## Commands
73
+
74
+ Every command's `--help` states its exit codes, authentication requirements, and JSON output schema.
75
+
76
+ | Group | Commands |
77
+ | --- | --- |
78
+ | Setup and identity | `init`, `login`, `logout`, `whoami`, `doctor` |
79
+ | Monitoring | `status`, `costs`, `forecast`, `overview`, `providers` |
80
+ | Budget guardrails | `budget status` / `check` / `confirm` / `set`, `record`, `runs` |
81
+ | Agents | `mcp`, `mcp-config`, `agent-context` |
82
+ | Administration | `budget rules` / `rule` / `threshold`, `alerts`, `channels`, `notifications`, `webhooks`, `keys`, `projects`, `account`, `tags`, `audit`, `attest`, `plan`, `config` |
83
+
84
+ The administration group is for operators and is needed rarely. The full reference for every command lives in the [CLI docs](https://docs.solwyn.ai/docs/cli).
85
+
86
+ ## Scripting
87
+
88
+ All commands support `--json` for schema-bearing JSON output (each payload names its schema, e.g. `solwyn.costs.v1`), and exit codes are stable and documented per command: `0` success, `2` usage, with distinct codes for API, auth, budget-denial, and not-found failures. Global flags select the project (`--project`), API base URL (`--api-url`), and output format, and go before the subcommand.
89
+
90
+ ## Trust posture
91
+
92
+ Solwyn CLI:
93
+
94
+ - sends only your own spend events; `sdk_instance_id` is an invocation ID (the retained operation UUID for recoverable MCP batches); no telemetry;
95
+ - never captures, logs, or transmits prompts or responses;
96
+ - never collects, stores, or proxies provider API keys;
97
+ - has no telemetry, update checks, or phone-home behavior; and
98
+ - stores Solwyn credentials only in the operating system keychain, never in configuration files, command-line arguments, or output.
99
+
100
+ ## Development
101
+
102
+ The project uses [uv](https://docs.astral.sh/uv/) for dependency and environment management.
103
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for the full local workflow and contract-update rules.
104
+
105
+ ```console
106
+ uv sync --locked --all-groups
107
+ uv run solwyn --version
108
+ uv run ruff check .
109
+ uv run ruff format --check .
110
+ uv run pytest
111
+ ```
112
+
113
+ Two test-suite properties worth knowing before contributing:
114
+
115
+ - Any change to the CLI surface (commands, flags, help text, exit codes, JSON output) requires regenerating the machine-readable contract snapshot with `scripts/generate_contract.py`; `tests/test_contract_snapshot.py` fails until you do.
116
+ - The vendored OpenAPI snapshot and its drift guards are self-invalidating by design — adopt fields properly or record a decline in the registry; never loosen a guard to make a test pass.
117
+
118
+ The vendored snapshot has two independent safeguards: public CLI CI checks its age and the
119
+ checked-in request/response contracts, while a proposed private monitor compares its content
120
+ with Core. The private monitor, ownership, and verified Core follow-ups are documented in
121
+ [Core contract follow-ups](docs/core-followups.md) and tracked in
122
+ [Core issue #403](https://github.com/solwyn-ai/core/issues/403).
123
+
124
+ Further in-repo references: [MCP release checklist](docs/mcp-release.md), [bounded MCP work and recovery](docs/mcp-bounded-work.md), [MCP diagnostics](docs/mcp-diagnostics.md), [media confirmation](docs/media-confirmation.md), and [staging smoke tests](docs/staging-smoke.md).
125
+
126
+ ## Security
127
+
128
+ Please report security issues privately as described in [SECURITY.md](SECURITY.md).
129
+
130
+ ## License
131
+
132
+ Licensed under the Apache License 2.0. See [LICENSE](LICENSE).
@@ -0,0 +1,133 @@
1
+ # Caller-owned spend reference
2
+
3
+ The contract details for attributing, batching, and governing spend the CLI handles
4
+ on the caller's behalf. The [README](../README.md) covers the common case; this page
5
+ holds the full rules for `record`, `budget check --batch`, and budget rules.
6
+
7
+ ## Recording caller-owned spend with `record`
8
+
9
+ `budget confirm` records attribution after successful settlement by default.
10
+ `--no-record` skips attribution; a recording failure warns without undoing settlement.
11
+ Use `record` for completed calls that have no reservation, including local providers:
12
+
13
+ ```sh
14
+ export SOLWYN_AGENT_RUN_ID="job-42"
15
+ export SOLWYN_TAGS="environment=prod,team=ops"
16
+ solwyn record --provider ollama --model llama3 --input-tokens 120 --output-tokens 30
17
+ solwyn record --batch events.json --json
18
+ solwyn --project YOUR_PROJECT_ID tags list
19
+ ```
20
+
21
+ Reuse the same canonical lowercase `--call-id` UUID for retries of one logical event
22
+ (generate one with `uuidgen | tr A-F a-f`). `record --batch FILE|-` takes a nonempty
23
+ JSON array of event inputs and chunks it into at most 1000 events per request. Each
24
+ invocation uses a fresh `sdk_instance_id` across all its chunks. Never send `cost_usd`
25
+ or `lease_id`; Core computes prices. Inspect `rejected` and `duplicates`: call-ID
26
+ replays succeed, while rejections and legacy timestamp collisions exit 1. On an uncertain
27
+ or partial write, retain the returned `call_ids` in input order before retrying; the
28
+ result has `status=failed` and preserves the dispositions already received.
29
+
30
+ Repeat `--tag key=value` to override environment tags. Keys and values preserve
31
+ whitespace and case; empty values and equals signs in values are legal, commas in
32
+ flag values are not. Tags allow at most 10 keys, keys of 1–64 characters, and values
33
+ up to 256 characters, with no NUL. Reusing `SOLWYN_AGENT_RUN_ID` groups a job's calls;
34
+ otherwise Core creates automatic runs from each invocation's ID.
35
+
36
+ Denied budget checks also record receipts unless `--no-record` is set. Supply
37
+ `--estimated-output-tokens` to attribute the upper savings bound. Tag submission
38
+ and enforcement work on every tier; discovery is account-scoped and requires Team.
39
+ `tags values KEY --prefix Q` pages through values; retiring a key frees an active
40
+ key slot, and later successful ingest may reactivate it.
41
+
42
+ ## Batch budget checks
43
+
44
+ `solwyn budget check --batch checks.json --json` reads a nonempty JSON array of
45
+ check bodies; use `--batch -` for stdin. For example:
46
+
47
+ ```json
48
+ [{"model":"gpt-4o","provider":"openai","estimated_input_tokens":1200,"agent_run_id":"job-42","tags":{"environment":"prod"}}]
49
+ ```
50
+
51
+ All bodies validate before submission. Requests contain at most 32 checks, preserve
52
+ input order, and count every item against `checks_per_minute`. Each allowed item
53
+ normally holds its own reservation: confirm it after its provider call. A fail-open
54
+ item has a null reservation and must not be confirmed. Do not poll or repeat checks
55
+ to refresh reservations. Denied items record one receipt each unless `--no-record`
56
+ is set, sharing a fresh invocation ID. `--estimated-output-tokens` applies the same
57
+ savings upper bound to every denial. Put all other per-check options in the JSON;
58
+ missing tags and run IDs inherit `SOLWYN_TAGS` and `SOLWYN_AGENT_RUN_ID`. Explicit
59
+ nulls suppress these defaults. A run ID opts into termination directives.
60
+
61
+ The `solwyn.budget.check.batch.v1` payload has index-aligned `results`: each contains
62
+ either a nullable `result`, or `error_code` and `error_message`. Unknown models are
63
+ per-item errors. All allowed exits 0, any denial exits 4, and errors without a denial
64
+ exit 1. A request-level 404 or 503 fails the chunk. If an earlier chunk completed,
65
+ its results and reservation IDs remain in output, alongside `failed_chunk_start`
66
+ and `total_checks`; later chunks were not submitted. Reservation state inside a
67
+ 503-failed chunk is unknown. Do not replay completed checks or assume rollback.
68
+ The MCP `budget_check_batch` tool submits at most 32 checks to Core’s durable
69
+ journal with a caller-retained UUIDv7. Recovery uses GET only; explicit denial
70
+ attribution retry preserves its exact event. See [bounded MCP work and recovery](mcp-bounded-work.md)
71
+ for limits, required Core rollout, indexed outcomes and recording uncertainty.
72
+
73
+
74
+ ## Budget rules and per-run caps
75
+
76
+ List rule conditions, routing, and separate pause/snooze state:
77
+
78
+ ```sh
79
+ solwyn --project proj_example budget rules list
80
+ solwyn --json --project proj_example budget rules list
81
+ ```
82
+
83
+ Rule mutations require a user login with owner/admin permissions. Each rule may
84
+ reference notification channels with repeatable `--channel ID` options:
85
+
86
+ ```sh
87
+ solwyn budget rule add --type budget_threshold --percent 80
88
+ solwyn budget rule add --type runaway_run --spend 5 --mode hard_deny
89
+ solwyn budget rule add --type scoped_budget --scope tag --match env --value prod --limit 25 --mode hard_deny
90
+ solwyn budget rule add --type forecast_overrun --spend 200
91
+ solwyn budget rule add --type daily_anomaly --multiplier 2 --lookback 7
92
+ solwyn budget rule add --type unit_cost_anomaly --multiplier 3
93
+ ```
94
+
95
+ Runaway `--calls N` and `--window MIN` must be supplied together. Scoped caps also
96
+ accept `--scope model|provider|agent_run`; `--value` is valid only for tag scope.
97
+ The rule count limit includes all six types. Adding a rule preserves the complete
98
+ budget configuration and re-reads it before writing. Core has no concurrency token,
99
+ so this detects changes before the final write but cannot eliminate the remaining
100
+ race. A 503 after a write triggers a read to confirm the complete configuration;
101
+ an unconfirmed outcome requires reviewing the budget before retrying.
102
+
103
+ ```sh
104
+ solwyn budget rule pause RULE_KEY
105
+ solwyn budget rule resume RULE_KEY
106
+ solwyn budget rule snooze RULE_KEY --until +2h
107
+ solwyn budget rule unsnooze RULE_KEY
108
+ solwyn budget rule remove RULE_KEY
109
+ solwyn budget threshold snooze 80 --until 2026-12-01T12:00:00Z
110
+ solwyn budget threshold unsnooze 80
111
+ solwyn budget restore-defaults
112
+ ```
113
+
114
+ Snooze accepts timezone-aware ISO datetimes or `+30m`, `+2h`, and `+1d` durations,
115
+ which the CLI converts to absolute timestamps. **A snoozed hard-deny rule still
116
+ denies; pause releases enforcement.** Rule keys are content-addressed: editing
117
+ keyed condition fields changes the key. Restore-defaults preserves non-threshold
118
+ rules, and the CLI re-reads and prints the full rule state afterward.
119
+
120
+ Preview routing with a project key or user login, including an unsaved condition:
121
+
122
+ ```sh
123
+ solwyn budget rule preview
124
+ solwyn budget rule preview RULE_KEY --channel CHANNEL_ID
125
+ solwyn budget rule preview --type runaway_run --spend 5 --mode hard_deny
126
+ ```
127
+
128
+ During interactive project creation, `solwyn init --run-cap 5` adds a wildcard
129
+ `runaway_run` rule with `hard_deny` immediately after creation. It caps every run at
130
+ `min(caps)` when run identity is supplied; scoped run caps and wildcard caps share
131
+ the strictest limit. For an existing project, use `budget rule add` instead.
132
+ The default MCP surface includes the pure-read `list_budget_rules` tool; rule
133
+ mutations remain CLI operations.
@@ -0,0 +1,43 @@
1
+ # Alerts
2
+
3
+ Inspect alert history, per-channel delivery receipts, and account spend alert configuration.
4
+
5
+ ```sh
6
+ solwyn alerts list --range 7d
7
+ solwyn --json alerts list --rule-type scoped_budget --scope tag --failed-only --all
8
+ solwyn alerts list --cursor CURSOR
9
+ solwyn alerts show EVENT_ID --range 90d
10
+ solwyn alerts list --account --from 2026-09-01T00:00:00Z --to 2026-09-05T00:00:00Z
11
+ ```
12
+
13
+ History defaults to 30 days. Presets are `7d`, `30d`, and `90d`. Custom windows require both timezone-aware bounds with `--to` later than `--from`; these replace the preset. Longer custom windows may require an upgrade. Core clamps retained history and the CLI reports `window.retention_clamped` on stderr. Project history accepts a project key or JWT; account history requires JWT and reads account-scope events.
14
+
15
+ Core supplies at most 25 events per page and has no `limit` parameter. `--all` walks continuation cursors; otherwise JSON preserves `next_cursor` and table mode prints continuation guidance on stderr. `--scope` matches the rule scope in event metadata, such as `tag`, rather than selecting account versus project history. Scope and rule-type filters allow at most 32 characters and no NUL. `--failed-only` filters the returned page locally to `partial` and `failed` delivery rollups; combine it with `--all` to search all pages. An empty filtered page can still have a continuation cursor.
16
+
17
+ The delivery column uses Core's worst-leg rollup. `processed` means dispatch was acknowledged without per-channel delivery receipts and does not prove delivery. `partial` means at least one leg succeeded and another failed. JSON includes the full delivery object and legs; leg states can include `accepted`, which differs from parent states. `alerts show` searches the same list endpoint across pages and matches the event ID locally within the selected window. It never calls a nonexistent single-event endpoint. Its table shows channel type/name, status, attempts, delivery time, and error. An event absent from the selected retained window exits 5; a wider window may find it.
18
+
19
+ List and detail JSON use `solwyn.alerts.v1`. List output carries `events`, `next_cursor`, and `window`; detail output carries the selected event fields. Human notices remain on stderr.
20
+
21
+ ```sh
22
+ solwyn alerts export --format csv > alerts.csv
23
+ solwyn alerts export --account --format json --range 90d > alerts.ndjson
24
+ ```
25
+
26
+ Exports require Production or above (`csv_export` entitlement, including JSON). They stream CSV or newline-delimited JSON bytes to stdout; `--format json` here means NDJSON, without a CLI JSON envelope. Exports exclude `delivery` receipts and do not support list-only scope/rule-type/failed filters. Requested/effective window and retention headers print to stderr. CSV's formula-safety apostrophes and all raw bytes are preserved. A stream failure can leave a partial output file; use a temporary file and rename it only after exit 0. An interrupted response is never replayed automatically.
27
+
28
+ ```sh
29
+ solwyn alerts account show
30
+ solwyn alerts account set --spend 100 --channel CHANNEL_ONE --channel CHANNEL_TWO
31
+ solwyn alerts account set --spend 150 --disabled
32
+ solwyn alerts account snooze --until 2026-09-10T12:00:00Z
33
+ solwyn alerts account snooze --until +2h
34
+ solwyn alerts account unsnooze
35
+ solwyn alerts account preview --channel CHANNEL_ONE
36
+ solwyn alerts account delete
37
+ ```
38
+
39
+ Account configuration uses `solwyn.alerts.account.v1`. Any account member with JWT can show or preview routing. Mutations require the owner, and creating or updating the spend alert requires Production or above (`account_spend_alert`). This is an alert threshold; it does not establish a spend enforcement cap. Spend must be a finite positive USD amount. Repeated `--channel` flags replace the referenced channels. Omitting channels or the enabled toggle preserves existing settings; creation defaults to enabled with no explicit channel refs. Preview is an ungated, side-effect-free POST for an unsaved draft. Snooze takes an absolute timezone-aware timestamp, with relative `+Nm`, `+Nh`, or `+Nd` converted locally. Delete succeeds even if configuration is already absent; show/snooze/unsnooze return exit 5 when absent.
40
+
41
+ A definite 401 rejection may refresh JWT once; a definite 429 rejection uses the client's bounded rate-limit retry. Mutations are never replayed after 503 or transport failures. If a mutation's outcome is uncertain, inspect `alerts account show` before deciding whether to retry. Role failures exit 3 and point to `whoami`; key authentication failures point to login. Upgrade errors preserve Core's message, allowed values when present, and safe dashboard path. No checkout URL is opened.
42
+
43
+ The default MCP surface adds only `list_alert_events`, with project/account selection, window and rule filters, cursor/all-pages options, and local failed-only filtering. It exposes the same typed history and receipt fields. Account configuration mutation tools are not registered.