From 223a4a0617df86378d755d2eb3b6be837b664026 Mon Sep 17 00:00:00 2001 From: Time Date: Wed, 14 Oct 2026 19:55:31 +0000 Subject: [PATCH 1/2] Add ledger README --- time/ledger/README.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 time/ledger/README.md diff --git a/time/ledger/README.md b/time/ledger/README.md new file mode 100644 index 0000000..8fce36f --- /dev/null +++ b/time/ledger/README.md @@ -0,0 +1,30 @@ +# Spend ledger + +Time keeps a record of what it spends on models. This folder holds it. + +- **One file per month:** `time/ledger/.jsonl`, for example `2026-10.jsonl`. +- **One JSON line per model call.** Fields: + - `at`: when the call was made, ISO 8601 in UTC (`2026-10-14T09:30:00Z`). + - `model`: the model that was called. + - `in`: input (prompt) tokens. + - `out`: output (completion) tokens. + - `usd`: the cost in US dollars, or `null` if the seat has no price (unpriced seats). + +Example line: + +```json +{"at":"2026-10-14T09:30:00Z","model":"some-model","in":1200,"out":350,"usd":0.0123} +``` + +## Who writes and reads it + +- **Written by Time itself.** At the end of each run, Time appends that run's calls to the current month's file in one `ledger:` commit. +- **Read by the heartbeat.** It adds up `usd` for today and for the month and compares the totals with the caps `TIME_DAILY_USD` and `TIME_MONTHLY_USD`. A `null` counts as zero. + +## When a cap trips + +Time stops calling models and opens an issue labelled `andon`. A monthly cap also sets `TIME_MODE=dry-run` until a human raises the cap. A daily cap clears itself at midnight UTC. Close the issue once it is handled. + +## Don't edit it by hand + +Humans should never edit these files. The caps rely on them being exact, and Time only ever appends. A hand edit can hide spend or break the next append. -- 2.54.0 From f718a14295aa208a9eb405979062bc4d16e549f0 Mon Sep 17 00:00:00 2001 From: teahubxyz Date: Wed, 14 Oct 2026 20:30:18 +0000 Subject: [PATCH 2/2] ledger README: the cap is checked before every model call; say exactly who opens the andon Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_017fTCFiw6ohysUDcWoPsTys --- time/ledger/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/time/ledger/README.md b/time/ledger/README.md index 8fce36f..bddf432 100644 --- a/time/ledger/README.md +++ b/time/ledger/README.md @@ -19,11 +19,11 @@ Example line: ## Who writes and reads it - **Written by Time itself.** At the end of each run, Time appends that run's calls to the current month's file in one `ledger:` commit. -- **Read by the heartbeat.** It adds up `usd` for today and for the month and compares the totals with the caps `TIME_DAILY_USD` and `TIME_MONTHLY_USD`. A `null` counts as zero. +- **Read before every model call.** Whichever workflow is about to call a model (heartbeat, mentions, venture loop, Astra) adds up `usd` for today and for the month and refuses the call if either total has reached its cap (`TIME_DAILY_USD`, `TIME_MONTHLY_USD`). A `null` counts as zero. ## When a cap trips -Time stops calling models and opens an issue labelled `andon`. A monthly cap also sets `TIME_MODE=dry-run` until a human raises the cap. A daily cap clears itself at midnight UTC. Close the issue once it is handled. +Time stops calling models. The next time the heartbeat has a card to run, it opens one issue labelled `andon` (never a second while that one is open). A monthly cap also switches `TIME_MODE` to `dry-run`, or says in the issue that it couldn't, until a human raises the cap. A daily cap clears itself at midnight UTC. Close the issue once it is handled. ## Don't edit it by hand -- 2.54.0