Summary
The profile budget scope is enforced and configurable via budget.yaml, but the /budget command surface only half-exposes it: /budget forecast accepts profile, while /budget set rejects it and the /budget status block never lists per-profile budgets. Today the only way to create or see a per-profile budget through the plugin is hand-editing budget.yaml.
Current behavior
/budget set profile <id> … → rejected with Unknown scope 'profile' (budget.py:637-638). The usage string lists only <global|cron_job|sender> (budget.py:702-703), and there is no per_profile write branch (budget.py:653-658).
/budget status omits profiles — it enumerates global, cron jobs and senders, but there is no profile section and no db.list_profile_ids() helper (budget.py:532-549).
/budget forecast <window> profile <id> → accepted (budget.py:695).
- Enforcement works:
evaluate_run checks the profile scope (budget.py:339-343) and _resolve_limits reads budgets.per_profile (budget.py:239-242).
- Manual config works:
budget.example.yaml documents the per_profile: block.
Impact
forecast advertises a profile scope that set cannot create, which is inconsistent. Anyone acting on the "per-profile budgets" capability naturally tries /budget set profile <name> daily 10 and hits Unknown scope, with no in-command way to configure or inspect the limit.
Proposed fix
_set_budget: accept profile and write to budgets.per_profile.default[<window>_usd], mirroring the cron_job/sender pattern. Update the scope guard and the Usage: string.
_status_block: add a "Profiles:" section, backed by a new db.list_profile_ids(since_iso) helper (mirroring list_cron_job_ids/list_sender_ids), excluding NULL profiles.
- Tests for both paths, plus an ONBOARDING/README refresh of the
/budget command docs.
Note: as with cron_job/sender, set would only write the default bucket; per-id overrides stay YAML-only (out of scope here). No schema change is needed — runs.profile already exists (v12).
Summary
The
profilebudget scope is enforced and configurable viabudget.yaml, but the/budgetcommand surface only half-exposes it:/budget forecastacceptsprofile, while/budget setrejects it and the/budgetstatus block never lists per-profile budgets. Today the only way to create or see a per-profile budget through the plugin is hand-editingbudget.yaml.Current behavior
/budget set profile <id> …→ rejected withUnknown scope 'profile'(budget.py:637-638). The usage string lists only<global|cron_job|sender>(budget.py:702-703), and there is noper_profilewrite branch (budget.py:653-658)./budgetstatus omits profiles — it enumerates global, cron jobs and senders, but there is no profile section and nodb.list_profile_ids()helper (budget.py:532-549)./budget forecast <window> profile <id>→ accepted (budget.py:695).evaluate_runchecks theprofilescope (budget.py:339-343) and_resolve_limitsreadsbudgets.per_profile(budget.py:239-242).budget.example.yamldocuments theper_profile:block.Impact
forecastadvertises aprofilescope thatsetcannot create, which is inconsistent. Anyone acting on the "per-profile budgets" capability naturally tries/budget set profile <name> daily 10and hitsUnknown scope, with no in-command way to configure or inspect the limit.Proposed fix
_set_budget: acceptprofileand write tobudgets.per_profile.default[<window>_usd], mirroring thecron_job/senderpattern. Update the scope guard and theUsage:string._status_block: add a "Profiles:" section, backed by a newdb.list_profile_ids(since_iso)helper (mirroringlist_cron_job_ids/list_sender_ids), excluding NULL profiles./budgetcommand docs.Note: as with
cron_job/sender,setwould only write thedefaultbucket; per-idoverridesstay YAML-only (out of scope here). No schema change is needed —runs.profilealready exists (v12).