feat(ledgerr-cloud): GPU-training cloud budget reconciliation crate + MCP tool - #179
Open
elasticdotventures wants to merge 3 commits into
Open
feat(ledgerr-cloud): GPU-training cloud budget reconciliation crate + MCP tool#179elasticdotventures wants to merge 3 commits into
elasticdotventures wants to merge 3 commits into
Conversation
…n crate New net-new crate porting the _b00t_/cloud-budget.tomllmd bash datum's AWS/GCP/Azure/HuggingFace budget-check logic into typed, panic-free Rust. Each provider shells out to its already-installed CLI via tokio::process::Command (no cloud SDK deps) and parses real JSON/TSV output shapes with serde_json rather than grep-style matching. - BudgetProvider trait (check_auth/fetch_budget) implemented by AwsProvider, GcpProvider, AzureProvider, HfProvider - CloudBudgetConfig with CAKE_USD_RATE/CAKE_MONTHLY_CAP env overrides, documented datum defaults (usd_per_cake=10.00, hf a100_large=2.50, warn=0.75, gate=0.90) - ReconcileRunner::run() never propagates a single provider's error out of the run — each is caught into a Pass/Fail/Skip ProviderStatus - HF is structurally NoApi (no billing API); its declared, non- authoritative CAKE_MONTHLY_CAP cap round-trips through the report via ProviderStatus.authoritative 19 unit tests, JSON/TSV fixtures under tests/fixtures/. No unwrap() or unchecked indexing in the crate. Refs #111 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Registers a new ledgerr_budget MCP tool (single "reconcile" action) that calls ledgerr_cloud::ReconcileRunner::default_providers().run() and returns the ReconcileReport as structured JSON. Follows the exact existing contract.rs/mcp_adapter.rs pattern used by ledgerr_focus and ledgerr_manifest: tool name const, BudgetArgs action enum wired through tool_input_schema, PUBLISHED_TOOLS/TOOL_REGISTRY entries, a handler in mcp_adapter.rs, and a match arm in the stdio server binary. ReconcileRunner::run is async (each provider shells out via tokio::process::Command); the MCP dispatch loop is synchronous, so handle_budget_tool drives it on a scratch current-thread tokio runtime rather than making the whole server async for one tool. ReconcileReport/ProviderStatus/ReconcileStatus now derive Serialize/Deserialize so the report can round-trip through the MCP JSON envelope. Regenerated docs/mcp-capability-contract.md and docs/agent-mcp-runbook.md via `cargo run -p ledgerr-mcp --bin regen-docs` (both are generated from contract.rs and asserted equal to it by tests/contract_codegen.rs). Bumped the two hardcoded 12-tool-count assertions in tests/mcp_adapter_contract.rs and tests/mcp_stdio_e2e.rs to 13. New tests/budget_reconcile_tool.rs exercises handle_budget_tool end-to-end (well-formed 4-provider report shape, unknown-action rejection, PUBLISHED_TOOLS registration) with a 30s watchdog thread so an unusually slow CLI in some environment fails the test instead of hanging it; no cloud credentials required to pass. Refs #111 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds tests/reconcile_integration.rs (gh#111 Phase 4): runs ReconcileRunner::default_providers().run() for real, against whatever aws/gcloud/az/hf CLIs and credentials actually exist in this environment. Report-shape assertions (exactly 4 entries, no non-authoritative cap mislabeled) hold unconditionally per ReconcileRunner::run's own graceful-degradation contract; the HF-is-always-Skip assertion holds structurally regardless of environment. Provider-specific "Pass when authenticated" assertions are additionally guarded with an env-var check that SKIPs (eprintln! + return) rather than fails when that provider isn't configured, mirroring the existing live-test convention in crates/ledgerr-mcp/tests/mcp_provider_smoke.rs (live_openmetadata_provider_lists_prefixed_tools_when_configured). Full-green (all providers Pass) requires the human-only cloud auth steps tracked in the Phase 2 tracking issues — see #111. Refs #111 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Net-new code (not modifying/fixing existing logic). Builds the real GPU-training-budget-reconciliation subsystem that GitHub issues #107–#111 describe prospectively — a prior investigation confirmed nothing in the actual repo implemented it. This is that implementation, ported faithfully from the
_b00t_/cloud-budget.tomllmdbash datum's AWS/GCP/Azure/HuggingFace logic (that datum lives in a separate_b00t_repo and is not accessible from this build; only its documented behavior/defaults were ported).Phase 1 —
crates/ledgerr-cloud(new crate)BudgetProvidertrait (check_auth/fetch_budget) implemented byAwsProvider,GcpProvider,AzureProvider,HfProvider— each shells out to its already-installed CLI viatokio::process::Command(no cloud SDK deps), parsing real JSON/TSV output shapes withserde_jsonrather than grep-style matching.CloudBudgetConfig:usd_per_cake/monthly_cap_cake/hf_a100_large_rate/warn_threshold/gate_threshold, withCAKE_USD_RATE/CAKE_MONTHLY_CAPenv overrides and the datum's documented defaults (10.00 / 2.50 / 0.75 / 0.90).ReconcileRunner::run()never propagates a single provider's error out of the run — each provider is caught into aPass/Fail/SkipProviderStatus. HF is structurallyNoApi(no billing API); its declared, non-authoritativeCAKE_MONTHLY_CAPcap round-trips through the report viaProviderStatus.authoritative.tests/fixtures/. Nounwrap()or unchecked indexing in the crate.Phase 3 — wired into
crates/ledgerr-mcpledgerr_budgetMCP tool (singlereconcileaction), following the repo's realcontract.rs/mcp_adapter.rspattern exactly (tool-name const, action enum wired throughtool_input_schema,PUBLISHED_TOOLS/TOOL_REGISTRYentries, a handler inmcp_adapter.rs, a match arm in the stdio server binary) — same shape asledgerr_focus/ledgerr_manifest.ReconcileRunner::runis async; the MCP dispatch loop is synchronous, so the handler drives it on a scratch current-thread tokio runtime.docs/mcp-capability-contract.md/docs/agent-mcp-runbook.mdvia the repo's ownregen-docsbinary; bumped the two hardcoded 12-tool-count assertions to 13.tests/budget_reconcile_tool.rswith a 30s watchdog thread so a slow CLI call can't hang the suite; requires no cloud credentials to pass.Phase 4 — integration test skeleton
crates/ledgerr-cloud/tests/reconcile_integration.rsruns the realReconcileRunneragainst whatever CLIs/creds exist in-environment; report-shape assertions hold unconditionally, provider-specific "Pass when authenticated" assertions SKIP (not fail) via the same env-var-guard convention already used incrates/ledgerr-mcp/tests/mcp_provider_smoke.rs. Full-green requires the human-only auth steps tracked in the Phase 2 tracking issues — see feat: expose BudgetProvider reconcile via ledgerr-mcp MCP tool #111.Verification (PASS evidence, verbatim)
Refs #111