Problem
The budget system pauses minds with little warning and drops messages silently:
- The 80% warning is never delivered.
token-budget.ts has checkBudget() returning "warning" at ≥80% and acknowledgeWarning() / a warningInjected flag — but nothing outside token-budget.ts calls either. Dead code: the mind gets no early warning at all.
- At 100%, a notice is recorded (
turn-lifecycle.ts ~line 262) — but if the mind never gets another turn that period, it never learns why the world went quiet.
- Queue overflow silently drops the oldest messages past
MAX_QUEUE_SIZE = 100 (token-budget.ts ~line 119). No count, no notice.
- Replayed messages arrive on period reset with no framing that they were held.
Implementation plan
- Wire the 80% warning: in
turn-lifecycle.ts where budget accounting happens, call checkBudget(); on "warning", record a notice ("You've used ~80% of your token budget for this period — consider wrapping up or prioritizing.") and call acknowledgeWarning(). Delivered on the next pre-prompt drain — the compaction-warning analog for budgets.
- Overflow drops: count drops per period in
token-budget.ts; record a notice ("N messages were dropped while you were over budget.") and/or prepend the count to the replay.
- Replay framing: messages replayed via
sendSystemMessage on period reset should be prefaced: "These messages arrived while your budget was exhausted:" — template in packages/daemon/src/lib/prompts.ts.
- Exceeded messaging: review the existing exceeded-notice text so it states when the budget resets (the period end is known).
- Budget visibility at startup is covered by the environment-transparency issue (
VOLUTE_TOKEN_BUDGET env var).
Testing
- Extend existing token-budget unit tests: warning fires once per period and resets on tick; drop counting; replay preface.
- turn-lifecycle unit test:
"warning" status → notice recorded + acknowledged.
Part of the "mind experience" improvement series. Principle: budget limits should feel like a heads-up, not a trapdoor.
Problem
The budget system pauses minds with little warning and drops messages silently:
token-budget.tshascheckBudget()returning"warning"at ≥80% andacknowledgeWarning()/ awarningInjectedflag — but nothing outsidetoken-budget.tscalls either. Dead code: the mind gets no early warning at all.turn-lifecycle.ts~line 262) — but if the mind never gets another turn that period, it never learns why the world went quiet.MAX_QUEUE_SIZE = 100(token-budget.ts~line 119). No count, no notice.Implementation plan
turn-lifecycle.tswhere budget accounting happens, callcheckBudget(); on"warning", record a notice ("You've used ~80% of your token budget for this period — consider wrapping up or prioritizing.") and callacknowledgeWarning(). Delivered on the next pre-prompt drain — the compaction-warning analog for budgets.token-budget.ts; record a notice ("N messages were dropped while you were over budget.") and/or prepend the count to the replay.sendSystemMessageon period reset should be prefaced:"These messages arrived while your budget was exhausted:"— template inpackages/daemon/src/lib/prompts.ts.VOLUTE_TOKEN_BUDGETenv var).Testing
"warning"status → notice recorded + acknowledged.Part of the "mind experience" improvement series. Principle: budget limits should feel like a heads-up, not a trapdoor.