solwyn-cli 0.2.0__tar.gz → 0.2.0rc1__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.
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/CONTRIBUTING.md +0 -6
- solwyn_cli-0.2.0rc1/PKG-INFO +287 -0
- solwyn_cli-0.2.0rc1/README.md +268 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/docs/mcp-quickstart.md +3 -4
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/docs/mcp-release.md +3 -3
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/docs/registry/server.draft.json +2 -2
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/examples/mcp/typescript/client.test.ts +1 -37
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/examples/mcp/typescript/client.ts +5 -9
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/pyproject.toml +1 -1
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/scripts/mcp_wheel_smoke.py +2 -6
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/fixtures/mcp_installed_legacy.py +1 -1
- solwyn_cli-0.2.0rc1/tests/golden/doctor-mcp-key.json +1 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/mcp_legacy_probe.py +1 -1
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_ci_packaging_smoke.py +1 -1
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_client.py +3 -3
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_mcp_wheel_runner.py +3 -10
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_smoke.py +1 -1
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/uv.lock +6 -6
- solwyn_cli-0.2.0/Makefile +0 -8
- solwyn_cli-0.2.0/PKG-INFO +0 -151
- solwyn_cli-0.2.0/README.md +0 -132
- solwyn_cli-0.2.0/docs/caller-owned-spend.md +0 -133
- solwyn_cli-0.2.0/docs/staging-smoke.md +0 -136
- solwyn_cli-0.2.0/scripts/budget-plane-cli-smoke.py +0 -8
- solwyn_cli-0.2.0/scripts/budget-plane-mcp-smoke.py +0 -441
- solwyn_cli-0.2.0/scripts/budget_plane_smoke.py +0 -828
- solwyn_cli-0.2.0/tests/golden/doctor-mcp-key.json +0 -1
- solwyn_cli-0.2.0/tests/test_budget_cli_smoke.py +0 -296
- solwyn_cli-0.2.0/tests/test_budget_mcp_smoke.py +0 -109
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/.github/workflows/ci.yml +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/.github/workflows/publish.yml +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/.gitignore +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/LICENSE +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/SECURITY.md +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/docs/commands/alerts.mdx +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/docs/commands/attest.mdx +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/docs/commands/costs.mdx +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/docs/commands/forecast.mdx +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/docs/commands/overview.mdx +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/docs/commands/status.mdx +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/docs/core-followups.md +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/docs/mcp-bounded-work.md +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/docs/mcp-diagnostics.md +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/docs/mcp-profiles.md +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/docs/media-confirmation.md +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/docs/registry/server.schema.2025-12-11.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/docs/registry/server.schema.2025-12-11.sha256 +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/docs/scripting.mdx +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/examples/mcp/python/client.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/examples/mcp/python/pyproject.toml +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/examples/mcp/python/uv.lock +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/examples/mcp/typescript/.gitignore +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/examples/mcp/typescript/package-lock.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/examples/mcp/typescript/package.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/examples/mcp/typescript/tsconfig.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/scripts/generate_contract.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/scripts/inspect_wheel.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/scripts/locks/mcp-legacy.in +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/scripts/locks/mcp-legacy.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/scripts/sync_spec.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/scripts/validate_mcp_registry.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/__init__.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/_mcp_doctor_helper.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/_mcp_doctor_ipc.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/_mcp_doctor_pipe.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/_mcp_doctor_process.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/_mcp_launch.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/_mcp_operation.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/_vendor/__init__.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/_vendor/batch.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/_vendor/notification_wire.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/_vendor/validation.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/_vendor/wire.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/artifacts/__init__.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/artifacts/_atomic.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/auth.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/client.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/commands/__init__.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/commands/_cost_advice_models.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/commands/_cost_filters.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/commands/_cost_models.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/commands/_entitlement.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/commands/_notifications_common.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/commands/_record.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/commands/_shared.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/commands/_tags.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/commands/account.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/commands/agent_context.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/commands/alerts.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/commands/attest.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/commands/audit.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/commands/budget.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/commands/budget_rules.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/commands/channels.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/commands/config.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/commands/cost_analysis.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/commands/cost_pricing.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/commands/costs.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/commands/doctor.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/commands/forecast.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/commands/init.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/commands/keys.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/commands/login.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/commands/mcp.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/commands/mcp_config.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/commands/mcp_doctor.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/commands/notifications.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/commands/overview.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/commands/plan.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/commands/projects.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/commands/providers.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/commands/record.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/commands/runs.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/commands/status.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/commands/tags.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/commands/webhooks.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/commands/whoami.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/config.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/errors.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/exit_codes.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/help.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/main.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/mcp/__init__.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/mcp/declarations.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/mcp/parameters.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/mcp/server.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/output.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/runtime.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/spec/__init__.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/src/solwyn_cli/spec/openapi_snapshot.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/contract/__init__.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/contract/account_cost_query_parameters.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/contract/alert_query_parameters.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/contract/builder.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/contract/cli_contract.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/contract/cost_query_parameters.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/fixtures/mcp_doctor_server.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/fixtures/mcp_doctor_telemetry.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/fixtures/mcp_doctor_wheel_smoke.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/__init__.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/account-alert-email-clear-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/account-alert-email-clear-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/account-alert-email-set-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/account-alert-email-set-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/account-alert-email-show-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/account-alert-email-show-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/agent-context.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/alerts-account-delete-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/alerts-account-delete-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/alerts-account-preview-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/alerts-account-preview-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/alerts-account-set-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/alerts-account-set-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/alerts-account-show-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/alerts-account-show-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/alerts-account-snooze-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/alerts-account-snooze-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/alerts-account-unsnooze-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/alerts-account-unsnooze-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/alerts-list-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/alerts-list-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/alerts-show-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/alerts-show-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/attest-account-csv.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/attest-project-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/audit-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/audit-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-check-allow-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-check-allow-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-check-batch-allowed.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-check-batch-allowed.table +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-check-batch-denied.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-check-batch-denied.table +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-check-batch-mixed.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-check-batch-mixed.table +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-check-batch-partial.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-check-batch-partial.table +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-check-batch-stopped.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-check-batch-stopped.table +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-check-batch-unknown.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-check-batch-unknown.table +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-check-deny-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-check-deny-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-check-fail-open-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-check-fail-open-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-check-read-only-key-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-check-read-only-key-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-check-run-stopped-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-check-run-stopped-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-check-tag-deny-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-check-tag-deny-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-confirm-expired-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-confirm-expired-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-confirm-missing-reservation-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-confirm-missing-reservation-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-confirm-success-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-confirm-success-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-restore-defaults-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-restore-defaults-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-rule-add-budget_threshold-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-rule-add-budget_threshold-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-rule-add-daily_anomaly-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-rule-add-daily_anomaly-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-rule-add-forecast_overrun-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-rule-add-forecast_overrun-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-rule-add-runaway_run-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-rule-add-runaway_run-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-rule-add-scoped_budget-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-rule-add-scoped_budget-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-rule-add-unit_cost_anomaly-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-rule-add-unit_cost_anomaly-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-rule-pause-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-rule-pause-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-rule-preview-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-rule-preview-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-rule-remove-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-rule-remove-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-rule-resume-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-rule-resume-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-rule-snooze-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-rule-snooze-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-rule-unsnooze-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-rule-unsnooze-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-rules-list-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-rules-list-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-set-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-set-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-status-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-status-rules-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-status-rules-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-status-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-threshold-snooze-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-threshold-snooze-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-threshold-unsnooze-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/budget-threshold-unsnooze-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/channels-create-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/channels-create-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/channels-delete-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/channels-delete-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/channels-list-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/channels-list-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/channels-show-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/channels-show-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/channels-test-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/channels-test-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/channels-update-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/channels-update-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/costs-account-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/costs-account-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/costs-account-withheld-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/costs-account-withheld-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/costs-agent_run-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/costs-agent_run-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/costs-baseline-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/costs-baseline-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/costs-day-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/costs-day-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/costs-drift-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/costs-drift-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/costs-events-continuation-stderr.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/costs-events-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/costs-events-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/costs-failover_reason-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/costs-failover_reason-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/costs-model-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/costs-model-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/costs-priced-models-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/costs-priced-models-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/costs-provider-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/costs-provider-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/costs-provider_region-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/costs-provider_region-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/costs-service_tier-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/costs-service_tier-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/costs-simulation-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/costs-simulation-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/costs-status-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/costs-status-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/costs-tag-customer-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/costs-tag-customer-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/costs-total-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/costs-total-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/costs-truncated-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/costs-truncated-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/costs-unit-economics-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/costs-unit-economics-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/doctor-degraded-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/doctor-jwt.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/email-not-verified.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/error.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/forecast-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/forecast.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/harness.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/human-error.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/init-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/init-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/keys-environment-key-refusal-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/keys-environment-key-refusal-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/keys-keyring-key-refusal-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/keys-keyring-key-refusal-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/keys-not-found-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/keys-not-found-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/keys-revoke-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/keys-revoke-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/keys-rotate-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/keys-rotate-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/keys-show-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/keys-show-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/login-jwt-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/login-jwt.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/login-key-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/login-key.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/logout-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/logout.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/mcp-config.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/mcp-tools.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/notifications-set-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/notifications-set-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/notifications-show-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/notifications-show-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/notifications-test-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/notifications-test-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/overview-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/overview-paid-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/overview-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/plan-team-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/plan-team.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/projects-create-display-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/projects-create-display-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/projects-create-stored-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/projects-create-stored-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/projects-delete-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/projects-delete-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/projects-list-environment-key-refusal-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/projects-list-environment-key-refusal-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/projects-list-jwt-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/projects-list-jwt-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/projects-list-keyring-key-refusal-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/projects-list-keyring-key-refusal-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/projects-rename-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/projects-rename-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/projects-show-jwt-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/projects-show-jwt-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/projects-show-key-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/projects-show-key-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/providers-failovers-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/providers-failovers.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/providers-untracked-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/providers-untracked.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/record-batch-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/record-batch-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/record-dedup-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/record-dedup-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/record-legacy-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/record-legacy-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/record-rejection-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/record-rejection-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/record-single-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/record-single-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/runs-list-jwt-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/runs-list-key-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/runs-show-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/runs-show-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/runs-stop-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/runs-stop-key-refusal-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/runs-stop-key-refusal-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/runs-stop-not-stoppable-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/runs-stop-not-stoppable-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/runs-stop-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/status-flags-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/status-flags.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/status-jwt-savings-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/status-jwt-savings-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/status-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/status.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/success.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/table-no-color.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/table-non-tty.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/table-tty.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/tags-list-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/tags-list-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/tags-retire-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/tags-retire-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/tags-values-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/tags-values-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/webhooks-create-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/webhooks-create-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/webhooks-delete-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/webhooks-delete-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/webhooks-list-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/webhooks-list-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/webhooks-rotate-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/webhooks-rotate-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/whoami-jwt-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/whoami-jwt.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/whoami-key-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/whoami-key.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/whoami-production-json.json +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/golden/whoami-production-table.txt +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/mcp_batch_fixtures.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_agent_artifacts.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_alert_query_contract.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_alerts_command.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_atomic_rename.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_attest_command.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_attest_contract.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_attest_models.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_attribution_commands.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_audit_command.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_auth.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_auth_commands.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_batch_journal_contract.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_budget_batch.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_budget_check_command.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_budget_command.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_budget_confirm_command.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_budget_rules_command.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_budget_set_command.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_config.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_config_command.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_contract_snapshot.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_cost_advice_command.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_cost_advice_contract.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_cost_advice_registration.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_cost_filters.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_cost_query_contract.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_cost_stream.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_costs_command.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_doctor_command.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_entitlement.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_errors.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_exit_codes.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_forecast_command.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_foundation.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_help_snapshots.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_init_command.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_keys_command.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_mcp_adoption.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_mcp_batch_recovery.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_mcp_boundary.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_mcp_bounded_results.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_mcp_cancellation_stdio.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_mcp_catalog.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_mcp_conformance.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_mcp_diagnostics.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_mcp_doctor_pipe.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_mcp_doctor_process.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_mcp_operation.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_mcp_pagination.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_mcp_protocol_privacy.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_mcp_registry.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_mcp_sdk_migration.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_mcp_server.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_mcp_transport_lifecycle.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_media_confirmation.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_notifications_commands.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_notifications_review_regressions.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_output.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_output_discipline.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_overview_command.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_plan_command.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_projects_command.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_providers_command.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_record_helpers.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_request_drift.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_response_subset.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_run_attribution_integration.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_runs_command.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_runtime.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_shared_command_auth.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_snapshot_age.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_status_command.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_tags_commands.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_vendor_sync.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_vendor_validation.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_vendor_wire.py +0 -0
- {solwyn_cli-0.2.0 → solwyn_cli-0.2.0rc1}/tests/test_webhooks_command.py +0 -0
|
@@ -10,12 +10,6 @@ uv run ruff format --check .
|
|
|
10
10
|
uv run pytest
|
|
11
11
|
```
|
|
12
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
13
|
## Command and output contracts
|
|
20
14
|
|
|
21
15
|
Treat command names, flags, help text, exit codes, stdout/stderr behavior, and JSON schemas as
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: solwyn-cli
|
|
3
|
+
Version: 0.2.0rc1
|
|
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` inspects the repository, writes local configuration, and renders SDK snippets for the providers it detects; add `--agents` to also write guidance files for Claude, Cursor, and `AGENTS.md`.
|
|
46
|
+
|
|
47
|
+
## Commands
|
|
48
|
+
|
|
49
|
+
| Command | What it does |
|
|
50
|
+
| --- | --- |
|
|
51
|
+
| `login` / `logout` / `whoami` | Manage credentials and show the current identity and project context. |
|
|
52
|
+
| `init` | Configure Solwyn safely for the current repository. |
|
|
53
|
+
| `status` | Show project budget and provider health. |
|
|
54
|
+
| `costs` | Show project costs across server-advertised dimensions, including agent runs and tags. |
|
|
55
|
+
| `record` | Attribute one completed call, or a JSON batch, without a reservation. |
|
|
56
|
+
| `tags list`, `tags values` | Discover account-scoped keys and values (Team+). |
|
|
57
|
+
| `tags retire` | Retire a registered account tag key (JWT admin/owner). |
|
|
58
|
+
| `budget status` | Read current budget status without authorizing spend. |
|
|
59
|
+
| `budget check` / `budget confirm` | Pre-flight guardrail loop for un-instrumented provider calls (below). |
|
|
60
|
+
| `budget set` | Update selected budget settings while preserving all other configuration. |
|
|
61
|
+
| `runs list` / `show` / `stop` | Inspect agent runs and stop their future checks and lease renewals. |
|
|
62
|
+
| `projects create` / `list` / `show` | Manage projects; `create --scope` mints the first key with an explicit scope. |
|
|
63
|
+
| `keys show` / `rotate` / `revoke` | Inspect key metadata (including its scope), rotate with `--scope` to change it, or hard-revoke. |
|
|
64
|
+
| `mcp` | Serve Solwyn tools to agents over local MCP stdio. |
|
|
65
|
+
| `mcp-config` | Generate an offline command/args descriptor; defaults to the read profile. |
|
|
66
|
+
| `doctor --mcp` | Check MCP discovery, selected project/key context and an authenticated read when supported. |
|
|
67
|
+
| `agent-context` | Print safe Solwyn budget guidance for coding agents. |
|
|
68
|
+
| `config` | Inspect and update local configuration. |
|
|
69
|
+
|
|
70
|
+
Every command's `--help` states its exit codes, authentication requirements, and JSON output schema.
|
|
71
|
+
|
|
72
|
+
## Budget guardrails for un-instrumented calls
|
|
73
|
+
|
|
74
|
+
Calls made through the Solwyn SDK are enforced and attributed automatically. For everything else — a `curl`, another language, a one-off script — the CLI provides an explicit two-step loop that covers enforcement and attribution:
|
|
75
|
+
|
|
76
|
+
```console
|
|
77
|
+
# 1. Reserve budget immediately before the call. A denied check exits with
|
|
78
|
+
# code 4, so scripts and CI can gate on it directly.
|
|
79
|
+
solwyn budget check --provider openai --model gpt-4.1 --estimated-input-tokens 1200
|
|
80
|
+
|
|
81
|
+
# 2. Make the provider call yourself.
|
|
82
|
+
|
|
83
|
+
# 3. Settle the reservation with what the call actually used.
|
|
84
|
+
solwyn budget confirm --call-id 12345678-1234-1234-1234-123456789abc --provider openai --model gpt-4.1 \
|
|
85
|
+
--reservation-id "$RESERVATION" --input-tokens 1180 --output-tokens 640
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
The CLI's caller-owned workflow maintains parity with Solwyn Python SDK 0.6.0 semantics and covers enforcement and attribution. Confirmation records attribution after settlement by default, using the same canonical call ID; add `--no-record` only when attribution is intentionally handled elsewhere.
|
|
89
|
+
|
|
90
|
+
The loop covers more than text tokens:
|
|
91
|
+
|
|
92
|
+
- **Media calls** — pass the billed quantities to `budget check` (`--image-count`, `--video-seconds`, `--audio-seconds`, `--input-characters`, `--generation-count`, `--resolution`, `--quality`) so unit-priced image, video, audio, and speech calls are priced and deniable before they run.
|
|
93
|
+
- **Image-token models** — `budget confirm` accepts `--image-input-tokens` and `--image-output-tokens` so image-rate spend settles at its real cost.
|
|
94
|
+
- **Fallbacks** — declare failover intent with repeated `--fallback-provider` / `--fallback-model` pairs.
|
|
95
|
+
- **Per-run caps** — scope enforcement to a single agent run with `--agent-run-id`.
|
|
96
|
+
|
|
97
|
+
Use `budget status` to poll; `check` is for the moment immediately before spend.
|
|
98
|
+
|
|
99
|
+
## For coding agents
|
|
100
|
+
|
|
101
|
+
Start with the [MCP quickstart](docs/mcp-quickstart.md): install the local wheel,
|
|
102
|
+
generate a read-first descriptor, diagnose credentials, and run the tested
|
|
103
|
+
Python or TypeScript client. The [release checklist](docs/mcp-release.md) and
|
|
104
|
+
Registry metadata are unpublished preparation.
|
|
105
|
+
|
|
106
|
+
`solwyn mcp` serves read, guardrail, and attribution tools over 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.
|
|
107
|
+
|
|
108
|
+
Use `solwyn --project proj_0123456789abcdef01234567 mcp --profile read` for the 13 read tools
|
|
109
|
+
(replace the synthetic ID with your project);
|
|
110
|
+
the default `guardrails` profile keeps all 17. Profiles are fixed at launch and
|
|
111
|
+
never grant permissions. See [MCP profiles and tool contracts](docs/mcp-profiles.md)
|
|
112
|
+
for authentication, discovery caching, and operation-specific replay rules.
|
|
113
|
+
|
|
114
|
+
## Scripting
|
|
115
|
+
|
|
116
|
+
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.
|
|
117
|
+
|
|
118
|
+
## Development
|
|
119
|
+
|
|
120
|
+
The project uses [uv](https://docs.astral.sh/uv/) for dependency and environment management.
|
|
121
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for the full local workflow and contract-update rules.
|
|
122
|
+
|
|
123
|
+
```console
|
|
124
|
+
uv sync --locked --all-groups
|
|
125
|
+
uv run solwyn --version
|
|
126
|
+
uv run ruff check .
|
|
127
|
+
uv run ruff format --check .
|
|
128
|
+
uv run pytest
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Two test-suite properties worth knowing before contributing:
|
|
132
|
+
|
|
133
|
+
- 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.
|
|
134
|
+
- 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.
|
|
135
|
+
|
|
136
|
+
The vendored snapshot has two independent safeguards: public CLI CI checks its age and the
|
|
137
|
+
checked-in request/response contracts, while a proposed private monitor compares its content
|
|
138
|
+
with Core. The private monitor, ownership, and verified Core follow-ups are documented in
|
|
139
|
+
[Core contract follow-ups](docs/core-followups.md) and tracked in
|
|
140
|
+
[Core issue #403](https://github.com/solwyn-ai/core/issues/403).
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
## Recording caller-owned spend
|
|
144
|
+
|
|
145
|
+
`budget confirm` records attribution after successful settlement by default.
|
|
146
|
+
`--no-record` skips attribution; a recording failure warns without undoing settlement.
|
|
147
|
+
Use `record` for completed calls that have no reservation, including local providers:
|
|
148
|
+
|
|
149
|
+
```sh
|
|
150
|
+
export SOLWYN_AGENT_RUN_ID="job-42"
|
|
151
|
+
export SOLWYN_TAGS="environment=prod,team=ops"
|
|
152
|
+
solwyn record --provider ollama --model llama3 --input-tokens 120 --output-tokens 30
|
|
153
|
+
solwyn record --batch events.json --json
|
|
154
|
+
solwyn --project YOUR_PROJECT_ID tags list
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Reuse the same canonical lowercase `--call-id` UUID for retries of one logical event
|
|
158
|
+
(generate one with `uuidgen | tr A-F a-f`). `record --batch FILE|-` takes a nonempty
|
|
159
|
+
JSON array of event inputs and chunks it into at most 1000 events per request. Each
|
|
160
|
+
invocation uses a fresh `sdk_instance_id` across all its chunks. Never send `cost_usd`
|
|
161
|
+
or `lease_id`; Core computes prices. Inspect `rejected` and `duplicates`: call-ID
|
|
162
|
+
replays succeed, while rejections and legacy timestamp collisions exit 1. On an uncertain
|
|
163
|
+
or partial write, retain the returned `call_ids` in input order before retrying; the
|
|
164
|
+
result has `status=failed` and preserves the dispositions already received.
|
|
165
|
+
|
|
166
|
+
Repeat `--tag key=value` to override environment tags. Keys and values preserve
|
|
167
|
+
whitespace and case; empty values and equals signs in values are legal, commas in
|
|
168
|
+
flag values are not. Tags allow at most 10 keys, keys of 1–64 characters, and values
|
|
169
|
+
up to 256 characters, with no NUL. Reusing `SOLWYN_AGENT_RUN_ID` groups a job's calls;
|
|
170
|
+
otherwise Core creates automatic runs from each invocation's ID.
|
|
171
|
+
|
|
172
|
+
Denied budget checks also record receipts unless `--no-record` is set. Supply
|
|
173
|
+
`--estimated-output-tokens` to attribute the upper savings bound. Tag submission
|
|
174
|
+
and enforcement work on every tier; discovery is account-scoped and requires Team.
|
|
175
|
+
`tags values KEY --prefix Q` pages through values; retiring a key frees an active
|
|
176
|
+
key slot, and later successful ingest may reactivate it.
|
|
177
|
+
|
|
178
|
+
## Batch budget checks
|
|
179
|
+
|
|
180
|
+
`solwyn budget check --batch checks.json --json` reads a nonempty JSON array of
|
|
181
|
+
check bodies; use `--batch -` for stdin. For example:
|
|
182
|
+
|
|
183
|
+
```json
|
|
184
|
+
[{"model":"gpt-4o","provider":"openai","estimated_input_tokens":1200,"agent_run_id":"job-42","tags":{"environment":"prod"}}]
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
All bodies validate before submission. Requests contain at most 32 checks, preserve
|
|
188
|
+
input order, and count every item against `checks_per_minute`. Each allowed item
|
|
189
|
+
normally holds its own reservation: confirm it after its provider call. A fail-open
|
|
190
|
+
item has a null reservation and must not be confirmed. Do not poll or repeat checks
|
|
191
|
+
to refresh reservations. Denied items record one receipt each unless `--no-record`
|
|
192
|
+
is set, sharing a fresh invocation ID. `--estimated-output-tokens` applies the same
|
|
193
|
+
savings upper bound to every denial. Put all other per-check options in the JSON;
|
|
194
|
+
missing tags and run IDs inherit `SOLWYN_TAGS` and `SOLWYN_AGENT_RUN_ID`. Explicit
|
|
195
|
+
nulls suppress these defaults. A run ID opts into termination directives.
|
|
196
|
+
|
|
197
|
+
The `solwyn.budget.check.batch.v1` payload has index-aligned `results`: each contains
|
|
198
|
+
either a nullable `result`, or `error_code` and `error_message`. Unknown models are
|
|
199
|
+
per-item errors. All allowed exits 0, any denial exits 4, and errors without a denial
|
|
200
|
+
exit 1. A request-level 404 or 503 fails the chunk. If an earlier chunk completed,
|
|
201
|
+
its results and reservation IDs remain in output, alongside `failed_chunk_start`
|
|
202
|
+
and `total_checks`; later chunks were not submitted. Reservation state inside a
|
|
203
|
+
503-failed chunk is unknown. Do not replay completed checks or assume rollback.
|
|
204
|
+
The MCP `budget_check_batch` tool submits at most 32 checks to Core’s durable
|
|
205
|
+
journal with a caller-retained UUIDv7. Recovery uses GET only; explicit denial
|
|
206
|
+
attribution retry preserves its exact event. See [bounded MCP work and recovery](docs/mcp-bounded-work.md)
|
|
207
|
+
for limits, required Core rollout, indexed outcomes and recording uncertainty.
|
|
208
|
+
|
|
209
|
+
## Trust posture
|
|
210
|
+
|
|
211
|
+
Solwyn CLI:
|
|
212
|
+
|
|
213
|
+
- sends only your own spend events; `sdk_instance_id` is an invocation ID (the retained operation UUID for recoverable MCP batches); no telemetry;
|
|
214
|
+
|
|
215
|
+
- never captures, logs, or transmits prompts or responses;
|
|
216
|
+
- never collects, stores, or proxies provider API keys;
|
|
217
|
+
- has no telemetry, update checks, or phone-home behavior; and
|
|
218
|
+
- stores Solwyn credentials only in the operating system keychain, never in configuration files, command-line arguments, or output.
|
|
219
|
+
|
|
220
|
+
## Security
|
|
221
|
+
|
|
222
|
+
Please report security issues privately as described in [SECURITY.md](SECURITY.md).
|
|
223
|
+
|
|
224
|
+
## License
|
|
225
|
+
|
|
226
|
+
Licensed under the Apache License 2.0. See [LICENSE](LICENSE).
|
|
227
|
+
|
|
228
|
+
### Budget rules and per-run caps
|
|
229
|
+
|
|
230
|
+
List rule conditions, routing, and separate pause/snooze state:
|
|
231
|
+
|
|
232
|
+
```sh
|
|
233
|
+
solwyn --project proj_example budget rules list
|
|
234
|
+
solwyn --json --project proj_example budget rules list
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
Rule mutations require a user login with owner/admin permissions. Each rule may
|
|
238
|
+
reference notification channels with repeatable `--channel ID` options:
|
|
239
|
+
|
|
240
|
+
```sh
|
|
241
|
+
solwyn budget rule add --type budget_threshold --percent 80
|
|
242
|
+
solwyn budget rule add --type runaway_run --spend 5 --mode hard_deny
|
|
243
|
+
solwyn budget rule add --type scoped_budget --scope tag --match env --value prod --limit 25 --mode hard_deny
|
|
244
|
+
solwyn budget rule add --type forecast_overrun --spend 200
|
|
245
|
+
solwyn budget rule add --type daily_anomaly --multiplier 2 --lookback 7
|
|
246
|
+
solwyn budget rule add --type unit_cost_anomaly --multiplier 3
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
Runaway `--calls N` and `--window MIN` must be supplied together. Scoped caps also
|
|
250
|
+
accept `--scope model|provider|agent_run`; `--value` is valid only for tag scope.
|
|
251
|
+
The rule count limit includes all six types. Adding a rule preserves the complete
|
|
252
|
+
budget configuration and re-reads it before writing. Core has no concurrency token,
|
|
253
|
+
so this detects changes before the final write but cannot eliminate the remaining
|
|
254
|
+
race. A 503 after a write triggers a read to confirm the complete configuration;
|
|
255
|
+
an unconfirmed outcome requires reviewing the budget before retrying.
|
|
256
|
+
|
|
257
|
+
```sh
|
|
258
|
+
solwyn budget rule pause RULE_KEY
|
|
259
|
+
solwyn budget rule resume RULE_KEY
|
|
260
|
+
solwyn budget rule snooze RULE_KEY --until +2h
|
|
261
|
+
solwyn budget rule unsnooze RULE_KEY
|
|
262
|
+
solwyn budget rule remove RULE_KEY
|
|
263
|
+
solwyn budget threshold snooze 80 --until 2026-12-01T12:00:00Z
|
|
264
|
+
solwyn budget threshold unsnooze 80
|
|
265
|
+
solwyn budget restore-defaults
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Snooze accepts timezone-aware ISO datetimes or `+30m`, `+2h`, and `+1d` durations,
|
|
269
|
+
which the CLI converts to absolute timestamps. **A snoozed hard-deny rule still
|
|
270
|
+
denies; pause releases enforcement.** Rule keys are content-addressed: editing
|
|
271
|
+
keyed condition fields changes the key. Restore-defaults preserves non-threshold
|
|
272
|
+
rules, and the CLI re-reads and prints the full rule state afterward.
|
|
273
|
+
|
|
274
|
+
Preview routing with a project key or user login, including an unsaved condition:
|
|
275
|
+
|
|
276
|
+
```sh
|
|
277
|
+
solwyn budget rule preview
|
|
278
|
+
solwyn budget rule preview RULE_KEY --channel CHANNEL_ID
|
|
279
|
+
solwyn budget rule preview --type runaway_run --spend 5 --mode hard_deny
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
During interactive project creation, `solwyn init --run-cap 5` adds a wildcard
|
|
283
|
+
`runaway_run` rule with `hard_deny` immediately after creation. It caps every run at
|
|
284
|
+
`min(caps)` when run identity is supplied; scoped run caps and wildcard caps share
|
|
285
|
+
the strictest limit. For an existing project, use `budget rule add` instead.
|
|
286
|
+
The default MCP surface includes the pure-read `list_budget_rules` tool; rule
|
|
287
|
+
mutations remain CLI operations.
|
|
@@ -0,0 +1,268 @@
|
|
|
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` inspects the repository, writes local configuration, and renders SDK snippets for the providers it detects; add `--agents` to also write guidance files for Claude, Cursor, and `AGENTS.md`.
|
|
27
|
+
|
|
28
|
+
## Commands
|
|
29
|
+
|
|
30
|
+
| Command | What it does |
|
|
31
|
+
| --- | --- |
|
|
32
|
+
| `login` / `logout` / `whoami` | Manage credentials and show the current identity and project context. |
|
|
33
|
+
| `init` | Configure Solwyn safely for the current repository. |
|
|
34
|
+
| `status` | Show project budget and provider health. |
|
|
35
|
+
| `costs` | Show project costs across server-advertised dimensions, including agent runs and tags. |
|
|
36
|
+
| `record` | Attribute one completed call, or a JSON batch, without a reservation. |
|
|
37
|
+
| `tags list`, `tags values` | Discover account-scoped keys and values (Team+). |
|
|
38
|
+
| `tags retire` | Retire a registered account tag key (JWT admin/owner). |
|
|
39
|
+
| `budget status` | Read current budget status without authorizing spend. |
|
|
40
|
+
| `budget check` / `budget confirm` | Pre-flight guardrail loop for un-instrumented provider calls (below). |
|
|
41
|
+
| `budget set` | Update selected budget settings while preserving all other configuration. |
|
|
42
|
+
| `runs list` / `show` / `stop` | Inspect agent runs and stop their future checks and lease renewals. |
|
|
43
|
+
| `projects create` / `list` / `show` | Manage projects; `create --scope` mints the first key with an explicit scope. |
|
|
44
|
+
| `keys show` / `rotate` / `revoke` | Inspect key metadata (including its scope), rotate with `--scope` to change it, or hard-revoke. |
|
|
45
|
+
| `mcp` | Serve Solwyn tools to agents over local MCP stdio. |
|
|
46
|
+
| `mcp-config` | Generate an offline command/args descriptor; defaults to the read profile. |
|
|
47
|
+
| `doctor --mcp` | Check MCP discovery, selected project/key context and an authenticated read when supported. |
|
|
48
|
+
| `agent-context` | Print safe Solwyn budget guidance for coding agents. |
|
|
49
|
+
| `config` | Inspect and update local configuration. |
|
|
50
|
+
|
|
51
|
+
Every command's `--help` states its exit codes, authentication requirements, and JSON output schema.
|
|
52
|
+
|
|
53
|
+
## Budget guardrails for un-instrumented calls
|
|
54
|
+
|
|
55
|
+
Calls made through the Solwyn SDK are enforced and attributed automatically. For everything else — a `curl`, another language, a one-off script — the CLI provides an explicit two-step loop that covers enforcement and attribution:
|
|
56
|
+
|
|
57
|
+
```console
|
|
58
|
+
# 1. Reserve budget immediately before the call. A denied check exits with
|
|
59
|
+
# code 4, so scripts and CI can gate on it directly.
|
|
60
|
+
solwyn budget check --provider openai --model gpt-4.1 --estimated-input-tokens 1200
|
|
61
|
+
|
|
62
|
+
# 2. Make the provider call yourself.
|
|
63
|
+
|
|
64
|
+
# 3. Settle the reservation with what the call actually used.
|
|
65
|
+
solwyn budget confirm --call-id 12345678-1234-1234-1234-123456789abc --provider openai --model gpt-4.1 \
|
|
66
|
+
--reservation-id "$RESERVATION" --input-tokens 1180 --output-tokens 640
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
The CLI's caller-owned workflow maintains parity with Solwyn Python SDK 0.6.0 semantics and covers enforcement and attribution. Confirmation records attribution after settlement by default, using the same canonical call ID; add `--no-record` only when attribution is intentionally handled elsewhere.
|
|
70
|
+
|
|
71
|
+
The loop covers more than text tokens:
|
|
72
|
+
|
|
73
|
+
- **Media calls** — pass the billed quantities to `budget check` (`--image-count`, `--video-seconds`, `--audio-seconds`, `--input-characters`, `--generation-count`, `--resolution`, `--quality`) so unit-priced image, video, audio, and speech calls are priced and deniable before they run.
|
|
74
|
+
- **Image-token models** — `budget confirm` accepts `--image-input-tokens` and `--image-output-tokens` so image-rate spend settles at its real cost.
|
|
75
|
+
- **Fallbacks** — declare failover intent with repeated `--fallback-provider` / `--fallback-model` pairs.
|
|
76
|
+
- **Per-run caps** — scope enforcement to a single agent run with `--agent-run-id`.
|
|
77
|
+
|
|
78
|
+
Use `budget status` to poll; `check` is for the moment immediately before spend.
|
|
79
|
+
|
|
80
|
+
## For coding agents
|
|
81
|
+
|
|
82
|
+
Start with the [MCP quickstart](docs/mcp-quickstart.md): install the local wheel,
|
|
83
|
+
generate a read-first descriptor, diagnose credentials, and run the tested
|
|
84
|
+
Python or TypeScript client. The [release checklist](docs/mcp-release.md) and
|
|
85
|
+
Registry metadata are unpublished preparation.
|
|
86
|
+
|
|
87
|
+
`solwyn mcp` serves read, guardrail, and attribution tools over 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.
|
|
88
|
+
|
|
89
|
+
Use `solwyn --project proj_0123456789abcdef01234567 mcp --profile read` for the 13 read tools
|
|
90
|
+
(replace the synthetic ID with your project);
|
|
91
|
+
the default `guardrails` profile keeps all 17. Profiles are fixed at launch and
|
|
92
|
+
never grant permissions. See [MCP profiles and tool contracts](docs/mcp-profiles.md)
|
|
93
|
+
for authentication, discovery caching, and operation-specific replay rules.
|
|
94
|
+
|
|
95
|
+
## Scripting
|
|
96
|
+
|
|
97
|
+
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.
|
|
98
|
+
|
|
99
|
+
## Development
|
|
100
|
+
|
|
101
|
+
The project uses [uv](https://docs.astral.sh/uv/) for dependency and environment management.
|
|
102
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for the full local workflow and contract-update rules.
|
|
103
|
+
|
|
104
|
+
```console
|
|
105
|
+
uv sync --locked --all-groups
|
|
106
|
+
uv run solwyn --version
|
|
107
|
+
uv run ruff check .
|
|
108
|
+
uv run ruff format --check .
|
|
109
|
+
uv run pytest
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Two test-suite properties worth knowing before contributing:
|
|
113
|
+
|
|
114
|
+
- 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.
|
|
115
|
+
- 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.
|
|
116
|
+
|
|
117
|
+
The vendored snapshot has two independent safeguards: public CLI CI checks its age and the
|
|
118
|
+
checked-in request/response contracts, while a proposed private monitor compares its content
|
|
119
|
+
with Core. The private monitor, ownership, and verified Core follow-ups are documented in
|
|
120
|
+
[Core contract follow-ups](docs/core-followups.md) and tracked in
|
|
121
|
+
[Core issue #403](https://github.com/solwyn-ai/core/issues/403).
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
## Recording caller-owned spend
|
|
125
|
+
|
|
126
|
+
`budget confirm` records attribution after successful settlement by default.
|
|
127
|
+
`--no-record` skips attribution; a recording failure warns without undoing settlement.
|
|
128
|
+
Use `record` for completed calls that have no reservation, including local providers:
|
|
129
|
+
|
|
130
|
+
```sh
|
|
131
|
+
export SOLWYN_AGENT_RUN_ID="job-42"
|
|
132
|
+
export SOLWYN_TAGS="environment=prod,team=ops"
|
|
133
|
+
solwyn record --provider ollama --model llama3 --input-tokens 120 --output-tokens 30
|
|
134
|
+
solwyn record --batch events.json --json
|
|
135
|
+
solwyn --project YOUR_PROJECT_ID tags list
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Reuse the same canonical lowercase `--call-id` UUID for retries of one logical event
|
|
139
|
+
(generate one with `uuidgen | tr A-F a-f`). `record --batch FILE|-` takes a nonempty
|
|
140
|
+
JSON array of event inputs and chunks it into at most 1000 events per request. Each
|
|
141
|
+
invocation uses a fresh `sdk_instance_id` across all its chunks. Never send `cost_usd`
|
|
142
|
+
or `lease_id`; Core computes prices. Inspect `rejected` and `duplicates`: call-ID
|
|
143
|
+
replays succeed, while rejections and legacy timestamp collisions exit 1. On an uncertain
|
|
144
|
+
or partial write, retain the returned `call_ids` in input order before retrying; the
|
|
145
|
+
result has `status=failed` and preserves the dispositions already received.
|
|
146
|
+
|
|
147
|
+
Repeat `--tag key=value` to override environment tags. Keys and values preserve
|
|
148
|
+
whitespace and case; empty values and equals signs in values are legal, commas in
|
|
149
|
+
flag values are not. Tags allow at most 10 keys, keys of 1–64 characters, and values
|
|
150
|
+
up to 256 characters, with no NUL. Reusing `SOLWYN_AGENT_RUN_ID` groups a job's calls;
|
|
151
|
+
otherwise Core creates automatic runs from each invocation's ID.
|
|
152
|
+
|
|
153
|
+
Denied budget checks also record receipts unless `--no-record` is set. Supply
|
|
154
|
+
`--estimated-output-tokens` to attribute the upper savings bound. Tag submission
|
|
155
|
+
and enforcement work on every tier; discovery is account-scoped and requires Team.
|
|
156
|
+
`tags values KEY --prefix Q` pages through values; retiring a key frees an active
|
|
157
|
+
key slot, and later successful ingest may reactivate it.
|
|
158
|
+
|
|
159
|
+
## Batch budget checks
|
|
160
|
+
|
|
161
|
+
`solwyn budget check --batch checks.json --json` reads a nonempty JSON array of
|
|
162
|
+
check bodies; use `--batch -` for stdin. For example:
|
|
163
|
+
|
|
164
|
+
```json
|
|
165
|
+
[{"model":"gpt-4o","provider":"openai","estimated_input_tokens":1200,"agent_run_id":"job-42","tags":{"environment":"prod"}}]
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
All bodies validate before submission. Requests contain at most 32 checks, preserve
|
|
169
|
+
input order, and count every item against `checks_per_minute`. Each allowed item
|
|
170
|
+
normally holds its own reservation: confirm it after its provider call. A fail-open
|
|
171
|
+
item has a null reservation and must not be confirmed. Do not poll or repeat checks
|
|
172
|
+
to refresh reservations. Denied items record one receipt each unless `--no-record`
|
|
173
|
+
is set, sharing a fresh invocation ID. `--estimated-output-tokens` applies the same
|
|
174
|
+
savings upper bound to every denial. Put all other per-check options in the JSON;
|
|
175
|
+
missing tags and run IDs inherit `SOLWYN_TAGS` and `SOLWYN_AGENT_RUN_ID`. Explicit
|
|
176
|
+
nulls suppress these defaults. A run ID opts into termination directives.
|
|
177
|
+
|
|
178
|
+
The `solwyn.budget.check.batch.v1` payload has index-aligned `results`: each contains
|
|
179
|
+
either a nullable `result`, or `error_code` and `error_message`. Unknown models are
|
|
180
|
+
per-item errors. All allowed exits 0, any denial exits 4, and errors without a denial
|
|
181
|
+
exit 1. A request-level 404 or 503 fails the chunk. If an earlier chunk completed,
|
|
182
|
+
its results and reservation IDs remain in output, alongside `failed_chunk_start`
|
|
183
|
+
and `total_checks`; later chunks were not submitted. Reservation state inside a
|
|
184
|
+
503-failed chunk is unknown. Do not replay completed checks or assume rollback.
|
|
185
|
+
The MCP `budget_check_batch` tool submits at most 32 checks to Core’s durable
|
|
186
|
+
journal with a caller-retained UUIDv7. Recovery uses GET only; explicit denial
|
|
187
|
+
attribution retry preserves its exact event. See [bounded MCP work and recovery](docs/mcp-bounded-work.md)
|
|
188
|
+
for limits, required Core rollout, indexed outcomes and recording uncertainty.
|
|
189
|
+
|
|
190
|
+
## Trust posture
|
|
191
|
+
|
|
192
|
+
Solwyn CLI:
|
|
193
|
+
|
|
194
|
+
- sends only your own spend events; `sdk_instance_id` is an invocation ID (the retained operation UUID for recoverable MCP batches); no telemetry;
|
|
195
|
+
|
|
196
|
+
- never captures, logs, or transmits prompts or responses;
|
|
197
|
+
- never collects, stores, or proxies provider API keys;
|
|
198
|
+
- has no telemetry, update checks, or phone-home behavior; and
|
|
199
|
+
- stores Solwyn credentials only in the operating system keychain, never in configuration files, command-line arguments, or output.
|
|
200
|
+
|
|
201
|
+
## Security
|
|
202
|
+
|
|
203
|
+
Please report security issues privately as described in [SECURITY.md](SECURITY.md).
|
|
204
|
+
|
|
205
|
+
## License
|
|
206
|
+
|
|
207
|
+
Licensed under the Apache License 2.0. See [LICENSE](LICENSE).
|
|
208
|
+
|
|
209
|
+
### Budget rules and per-run caps
|
|
210
|
+
|
|
211
|
+
List rule conditions, routing, and separate pause/snooze state:
|
|
212
|
+
|
|
213
|
+
```sh
|
|
214
|
+
solwyn --project proj_example budget rules list
|
|
215
|
+
solwyn --json --project proj_example budget rules list
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Rule mutations require a user login with owner/admin permissions. Each rule may
|
|
219
|
+
reference notification channels with repeatable `--channel ID` options:
|
|
220
|
+
|
|
221
|
+
```sh
|
|
222
|
+
solwyn budget rule add --type budget_threshold --percent 80
|
|
223
|
+
solwyn budget rule add --type runaway_run --spend 5 --mode hard_deny
|
|
224
|
+
solwyn budget rule add --type scoped_budget --scope tag --match env --value prod --limit 25 --mode hard_deny
|
|
225
|
+
solwyn budget rule add --type forecast_overrun --spend 200
|
|
226
|
+
solwyn budget rule add --type daily_anomaly --multiplier 2 --lookback 7
|
|
227
|
+
solwyn budget rule add --type unit_cost_anomaly --multiplier 3
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
Runaway `--calls N` and `--window MIN` must be supplied together. Scoped caps also
|
|
231
|
+
accept `--scope model|provider|agent_run`; `--value` is valid only for tag scope.
|
|
232
|
+
The rule count limit includes all six types. Adding a rule preserves the complete
|
|
233
|
+
budget configuration and re-reads it before writing. Core has no concurrency token,
|
|
234
|
+
so this detects changes before the final write but cannot eliminate the remaining
|
|
235
|
+
race. A 503 after a write triggers a read to confirm the complete configuration;
|
|
236
|
+
an unconfirmed outcome requires reviewing the budget before retrying.
|
|
237
|
+
|
|
238
|
+
```sh
|
|
239
|
+
solwyn budget rule pause RULE_KEY
|
|
240
|
+
solwyn budget rule resume RULE_KEY
|
|
241
|
+
solwyn budget rule snooze RULE_KEY --until +2h
|
|
242
|
+
solwyn budget rule unsnooze RULE_KEY
|
|
243
|
+
solwyn budget rule remove RULE_KEY
|
|
244
|
+
solwyn budget threshold snooze 80 --until 2026-12-01T12:00:00Z
|
|
245
|
+
solwyn budget threshold unsnooze 80
|
|
246
|
+
solwyn budget restore-defaults
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
Snooze accepts timezone-aware ISO datetimes or `+30m`, `+2h`, and `+1d` durations,
|
|
250
|
+
which the CLI converts to absolute timestamps. **A snoozed hard-deny rule still
|
|
251
|
+
denies; pause releases enforcement.** Rule keys are content-addressed: editing
|
|
252
|
+
keyed condition fields changes the key. Restore-defaults preserves non-threshold
|
|
253
|
+
rules, and the CLI re-reads and prints the full rule state afterward.
|
|
254
|
+
|
|
255
|
+
Preview routing with a project key or user login, including an unsaved condition:
|
|
256
|
+
|
|
257
|
+
```sh
|
|
258
|
+
solwyn budget rule preview
|
|
259
|
+
solwyn budget rule preview RULE_KEY --channel CHANNEL_ID
|
|
260
|
+
solwyn budget rule preview --type runaway_run --spend 5 --mode hard_deny
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
During interactive project creation, `solwyn init --run-cap 5` adds a wildcard
|
|
264
|
+
`runaway_run` rule with `hard_deny` immediately after creation. It caps every run at
|
|
265
|
+
`min(caps)` when run identity is supplied; scoped run caps and wildcard caps share
|
|
266
|
+
the strictest limit. For an existing project, use `budget rule add` instead.
|
|
267
|
+
The default MCP surface includes the pure-read `list_budget_rules` tool; rule
|
|
268
|
+
mutations remain CLI operations.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Connect a harness to Solwyn MCP
|
|
2
2
|
|
|
3
|
-
Solwyn 0.2.
|
|
3
|
+
Solwyn 0.2.0rc1 is **pre-release, private and not published to PyPI**. Start from an
|
|
4
4
|
authorized source checkout or a wheel built from it. This guide uses local stdio;
|
|
5
5
|
there is no hosted MCP endpoint. Account/project access is a separate prerequisite.
|
|
6
6
|
|
|
@@ -11,7 +11,7 @@ From the authorized CLI checkout:
|
|
|
11
11
|
```sh
|
|
12
12
|
uv sync --locked --all-groups
|
|
13
13
|
uv build --wheel
|
|
14
|
-
uv tool install --python 3.11 dist/solwyn_cli-0.2.
|
|
14
|
+
uv tool install --python 3.11 dist/solwyn_cli-0.2.0rc1-py3-none-any.whl
|
|
15
15
|
uv tool dir --bin
|
|
16
16
|
solwyn --version
|
|
17
17
|
solwyn login --with-key
|
|
@@ -145,8 +145,7 @@ proxy credentials and OTel configuration. The SDK adds its OS baseline even when
|
|
|
145
145
|
external clients/hosts remain separate from Solwyn's no-telemetry policy.
|
|
146
146
|
|
|
147
147
|
`--timeout` bounds client useful work (10 seconds by default, configurable from
|
|
148
|
-
0.1 to 30)
|
|
149
|
-
startup on Windows. Timeout/cancellation unwinds the transport explicitly. SDK cleanup
|
|
148
|
+
0.1 to 30); timeout/cancellation unwinds the transport explicitly. SDK cleanup
|
|
150
149
|
is additional: Python's inspected waits total up to 6.5 seconds plus scheduling;
|
|
151
150
|
TypeScript closes stdin, waits up to 2 seconds, then allows up to 2 seconds after
|
|
152
151
|
termination before killing, and the example observes direct-child exit for up
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# MCP release preparation
|
|
2
2
|
|
|
3
|
-
**Unpublished draft.** Package metadata currently says `solwyn-cli` 0.2.
|
|
3
|
+
**Unpublished draft.** Package metadata currently says `solwyn-cli` 0.2.0rc1; the
|
|
4
4
|
source repository is private and no PyPI publication is established. The
|
|
5
5
|
[Registry draft](registry/server.draft.json) proposes `ai.solwyn/solwyn`;
|
|
6
6
|
namespace ownership is **unverified**. Neither local validation nor MCP
|
|
@@ -33,7 +33,7 @@ resolution remains separate; this is not a claim of byte-identical wheel builds.
|
|
|
33
33
|
Inspect the final distribution before uploading; for the current version:
|
|
34
34
|
|
|
35
35
|
```sh
|
|
36
|
-
uv run --no-sync python scripts/inspect_wheel.py dist/solwyn_cli-0.2.
|
|
36
|
+
uv run --no-sync python scripts/inspect_wheel.py dist/solwyn_cli-0.2.0rc1-py3-none-any.whl
|
|
37
37
|
```
|
|
38
38
|
|
|
39
39
|
Protected checks keep their existing names: `Quality`, `Tests (Python 3.11)`,
|
|
@@ -75,7 +75,7 @@ artifacts and the Registry publisher's `mcp-publisher publish` from the director
|
|
|
75
75
|
containing the final `server.json`. Obtain credentials through the release
|
|
76
76
|
system, and follow the publisher's current authentication/namespace verification
|
|
77
77
|
instructions. Do not run these commands for `server.draft.json` or infer that
|
|
78
|
-
0.2.
|
|
78
|
+
0.2.0rc1 is already installable from an index.
|
|
79
79
|
|
|
80
80
|
## Registry schema and ownership marker
|
|
81
81
|
|
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
"name": "ai.solwyn/solwyn",
|
|
4
4
|
"title": "Solwyn",
|
|
5
5
|
"description": "Inspect Solwyn budgets and attribute model spend through local MCP tools.",
|
|
6
|
-
"version": "0.2.
|
|
6
|
+
"version": "0.2.0rc1",
|
|
7
7
|
"packages": [
|
|
8
8
|
{
|
|
9
9
|
"registryType": "pypi",
|
|
10
10
|
"registryBaseUrl": "https://pypi.org",
|
|
11
11
|
"identifier": "solwyn-cli",
|
|
12
|
-
"version": "0.2.
|
|
12
|
+
"version": "0.2.0rc1",
|
|
13
13
|
"runtimeHint": "uvx",
|
|
14
14
|
"transport": {"type": "stdio"},
|
|
15
15
|
"packageArguments": [
|