Reginald's context is tiered so the model always sees what matters without ever
copying ticket data into the prompt:
- HOT (this module) — charter + active directives + the focus snapshot, packed
under a hard token budget (2k). Assembled fresh each turn as the prompt seed.
- WARM — the append-only directive/event ledger + digest, summarized on demand.
- COLD — gitea + sidecar via query_project. Ticket bodies/comments/detail live
here and are NEVER inlined; the model fetches them by number when needed.
- `assembleHotContext(inputs, budget=2000)`: focus (tiny, always kept) → most
recent active directives (each while they fit ~⅔) → charter fills the true
remainder, truncated on a line boundary. Measures the fixed tail exactly and
reserves for header/joiner/ellipsis so the total never exceeds budget.
- `estimateTokens` (tokenizer-free ~4 chars/token, slight over-estimate so a real
tokenizer stays under), `activeDirectives` (accepted/amended, most-recent-first).
Acceptance met: hot assembles under the 2k budget even with a ~34k-token charter;
nothing ticket-shaped is inlined (only numbers + titles for focus). +5 core tests;
full core suite + typecheck green.
Follow-up: wire assembleHotContext into the live system prompt in main (needs
charter + directives + focus at chat time) — the assembly + budget is the tested core.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>