Skip to content

feat(llc/budget): provision per-agent budget — hire-time auto-create + explicit endpoint (#9901) - #9981

Merged
mrveiss merged 4 commits into
Dev_new_guifrom
issue-9901
Jun 11, 2026
Merged

mrveiss merged 4 commits into
Dev_new_guifrom
issue-9901

Conversation

@mrveiss

@mrveiss mrveiss commented Jun 11, 2026

Copy link
Copy Markdown
Owner

Thinking Path

The LLC budget API could ingest, read, and update-limit an llc_agent_budgets row but nothing could create one — the e2e test had to seed the row directly. Per the issue's preference, provisioning happens at hire (where an agent gets created), inside the same transaction as the agent_org_nodes INSERT, plus an explicit endpoint for out-of-band provisioning. An independent review round hardened it: provision is race-safe (savepoint + IntegrityError → idempotent return), the default-limit env parse can no longer crash router import, and company_id is derived from agent_org_nodes server-side instead of trusted from the request body.

What Changed

  • llc/config/__init__.py: DEFAULT_BUDGET_LIMIT from LLC_DEFAULT_BUDGET_LIMIT (guarded Decimal parse — warn + 10.00 fallback on malformed value; never crashes import)
  • llc/services/budget.py: BudgetService.provision_budget() — idempotent, savepoint-wrapped insert catching IntegrityError (concurrent provision returns the existing row instead of 500ing, and can no longer fail a racing hire)
  • llc/api/budget.py: POST /budget/{agent_id} — 404 unknown agent, 409 already provisioned; budget_limit validated gt=0, lt=1e9 (fits Numeric(15,6)); company_id derived from the agent's org node; duplicated derived-status block extracted to _derive_status()
  • llc/api/agent_hires.py: hire_agent auto-provisions the budget row before commit — same transaction as the agent node
  • llc/tests/test_budget_provision.py: 11 tests — 201/409/404, custom limit, idempotency, ingest-after-provision, hire-wiring (AsyncMock assert), IntegrityError race path

Verification

  • 11/11 test_budget_provision.py; broader -k budget: 22 pre-existing passes unchanged (3 failures + 11 errors are pre-existing on base, unrelated fixture/cache issues)
  • Independent code-reviewer round (REQUEST_CHANGES → all 4 MEDIUM + 3 LOW findings fixed)
  • flake8 + py_compile clean on touched files
  • Not in scope (noted in issue): backfilling budget rows for pre-existing agents — org-chart still reports 0/0 for them

Model Used

Fable 5 (main session) + Sonnet sub-agents (implementation, review, fixes)

Fixes #9901

🤖 Generated with Claude Code

mrveiss and others added 2 commits June 11, 2026 17:00
…+ explicit endpoint (#9901)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…e, validation, derived company_id (#9901)

M1: wrap provision_budget insert in begin_nested/flush; catch IntegrityError, re-select and return (existing, False)
M2: replace bare Decimal(os.environ.get(...)) with _env_decimal() helper that logs warning and falls back on InvalidOperation
M3: budget_limit field gets gt=0, lt=1_000_000_000 validation in ProvisionRequest
M4: remove company_id from ProvisionRequest; derive it from agent_org_nodes in the same query that does the 404 check
L5: add test_hire_endpoint_calls_provision_budget (AsyncMock probe) and test_provision_budget_race_returns_existing (begin_nested patch)
L6: extract _derive_status(row) helper; replace 2x duplicated spend/limit/threshold blocks in provision_budget and get_budget endpoints
L7: fix ProvisionRequest docstring — company_id removed, accurate description of what the field does

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jun 11, 2026 •

Copy link
Copy Markdown
Contributor

✅ SSOT Configuration Compliance: Passing

🎉 No hardcoded values detected that have SSOT config equivalents!

github-actions Bot and others added 2 commits June 11, 2026 14:35
Applied Black, isort, and autoflake to match code-quality checks.
Triggered by workflow auto-fix-formatting.yml.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant