Ledger README: explain time/ledger/<YYYY-MM>.jsonl #50

Merged
teahubxyz merged 2 commits from time/card-49 into main 2026-10-14 20:53:05 +00:00
Collaborator

Adds time/ledger/README.md, a short plain description of the spend ledger. It was already on the branch (commit "Add ledger README"), so I made no further edits.

It covers:

  • One file per month, with one JSON line per model call: at (ISO UTC), model, in, out, and usd (null for unpriced seats).
  • Time writes it itself at the end of each run, in a ledger: commit.
  • The heartbeat reads it to enforce TIME_DAILY_USD and TIME_MONTHLY_USD.
  • An andon issue is opened when a cap trips.
  • Humans should never edit it by hand.

Checks: I compared the README with .github/time/time.py (ledger_path, record/flush_ledger, spend, budget, andon) and it is accurate.

Tests: python3 .github/time/test_time.py ends with ALL OK (53, 35, 36, 41; venture tests skipped by default). That is only true with the TIME_* variables unset. This worker's environment sets TIME_WORKER=claude:sonnet, TIME_MODE=live and others. With them set, the test at line 158 fails because it assumes a clean environment. That is an environment artefact, not a problem with this change, and CI runs with a clean environment.

Closes #49

worker: Claude Sonnet (Anthropic) via Time

Adds `time/ledger/README.md`, a short plain description of the spend ledger. It was already on the branch (commit "Add ledger README"), so I made no further edits. It covers: - One file per month, with one JSON line per model call: `at` (ISO UTC), `model`, `in`, `out`, and `usd` (null for unpriced seats). - Time writes it itself at the end of each run, in a `ledger:` commit. - The heartbeat reads it to enforce `TIME_DAILY_USD` and `TIME_MONTHLY_USD`. - An `andon` issue is opened when a cap trips. - Humans should never edit it by hand. Checks: I compared the README with `.github/time/time.py` (`ledger_path`, `record`/`flush_ledger`, `spend`, `budget`, `andon`) and it is accurate. Tests: `python3 .github/time/test_time.py` ends with ALL OK (53, 35, 36, 41; venture tests skipped by default). That is only true with the `TIME_*` variables unset. This worker's environment sets `TIME_WORKER=claude:sonnet`, `TIME_MODE=live` and others. With them set, the test at line 158 fails because it assumes a clean environment. That is an environment artefact, not a problem with this change, and CI runs with a clean environment. Closes #49 <sub>worker: Claude Sonnet (Anthropic) via Time</sub>
time added 1 commit 2026-10-14 20:24:31 +00:00
Add ledger README
ci / test (pull_request) Successful in 35s
time/worker-run env | grep -E '^TIME_(WORKER|MODE|PLANNER|REVIEW)=' ; env -u TIME_WORKER -u TIME_MODE -u TIME_PLANNE
223a4a0617

Object

The README is short and in scope, and the ledger fields match the card. I'm blocking on two things: the finish line isn't demonstrated, and some behaviour in the README isn't in the card.

  • Tests (PR body, not a file): The finish line is "tests green". The author ran the suite only with TIME_* variables unset, and says a test at test_time.py:158 fails in its own environment. "CI runs clean" is asserted, not shown. Please attach a clean-environment run of python3 .github/time/test_time.py or a green CI link for this commit.
  • time/ledger/README.md:26: "A monthly cap also sets TIME_MODE=dry-run until a human raises the cap. A daily cap clears itself at midnight UTC. … Time stops calling models" is not in the card. The author says it checked against time.py, but the PR gives no line references. Please point to the code that does each of these, or cut the claims.
  • time/ledger/README.md:22: "A null counts as zero" is the same kind of claim. Confirm it in the spend code, or cite where it is handled.
  • time/ledger/README.md:26: The andon issue claim is in the card, so it stays. Just make sure the wording matches what andon actually opens.

Once the test evidence is posted and the behavioural claims are either verified with references or removed, this is a clean approve.

review by haiku · claude-haiku-5-5 · via Time

**Object** The README is short and in scope, and the ledger fields match the card. I'm blocking on two things: the finish line isn't demonstrated, and some behaviour in the README isn't in the card. - **Tests (PR body, not a file):** The finish line is "tests green". The author ran the suite only with `TIME_*` variables unset, and says a test at `test_time.py:158` fails in its own environment. "CI runs clean" is asserted, not shown. Please attach a clean-environment run of `python3 .github/time/test_time.py` or a green CI link for this commit. - **`time/ledger/README.md:26`:** "A monthly cap also sets `TIME_MODE=dry-run` until a human raises the cap. A daily cap clears itself at midnight UTC. … Time stops calling models" is not in the card. The author says it checked against `time.py`, but the PR gives no line references. Please point to the code that does each of these, or cut the claims. - **`time/ledger/README.md:22`:** "A `null` counts as zero" is the same kind of claim. Confirm it in the `spend` code, or cite where it is handled. - **`time/ledger/README.md:26`:** The `andon` issue claim is in the card, so it stays. Just make sure the wording matches what `andon` actually opens. Once the test evidence is posted and the behavioural claims are either verified with references or removed, this is a clean approve. <sub>review by haiku · claude-haiku-5-5 · via Time</sub>
teahubxyz added 1 commit 2026-10-14 20:30:20 +00:00
Owner

Evidence for the review above (no verdict from me: I pushed f718a14 to this branch, so the verdict should come from someone else).

  • Tests. CI ran the suite in a clean job and is green on both commits: ci / test (pull_request) passed on 223a4a0 and again on f718a14. The failure the worker saw came from its own shell inheriting the job's TIME_* variables. That's a real test-isolation bug, now card #51.
  • Monthly cap → dry-run, daily cap clears at midnight, Time stops calling models (README.md:26): budget_check() in .github/time/time.py raises Budget before any request once budget() reaches a cap. The day and month are UTC date prefixes, so the daily total resets at 00:00 UTC. On a monthly breach, andon() switches TIME_MODE to dry-run, or says in the issue that it couldn't.
  • null counts as zero (README.md:22): spend() sums r.get("usd") or 0.
  • andon wording: andon() opens one "Spend cap reached…" issue and never a second while it's open; the heartbeat's tick() is what calls it. f718a14 says exactly that, and that the cap is checked before every model call from any workflow, not only by the heartbeat.

This review exposed two gaps, now cards: the reviewer isn't shown check statuses (#52), and an objection can't go back to the worker (#53).

Evidence for the review above (no verdict from me: I pushed f718a14 to this branch, so the verdict should come from someone else). - **Tests.** CI ran the suite in a clean job and is green on both commits: `ci / test (pull_request)` passed on 223a4a0 and again on f718a14. The failure the worker saw came from its own shell inheriting the job's `TIME_*` variables. That's a real test-isolation bug, now card #51. - **Monthly cap → dry-run, daily cap clears at midnight, Time stops calling models** (`README.md:26`): `budget_check()` in `.github/time/time.py` raises `Budget` before any request once `budget()` reaches a cap. The day and month are UTC date prefixes, so the daily total resets at 00:00 UTC. On a monthly breach, `andon()` switches `TIME_MODE` to `dry-run`, or says in the issue that it couldn't. - **`null` counts as zero** (`README.md:22`): `spend()` sums `r.get("usd") or 0`. - **andon wording**: `andon()` opens one "Spend cap reached…" issue and never a second while it's open; the heartbeat's `tick()` is what calls it. f718a14 says exactly that, and that the cap is checked before every model call from any workflow, not only by the heartbeat. This review exposed two gaps, now cards: the reviewer isn't shown check statuses (#52), and an objection can't go back to the worker (#53).
teahubxyz merged commit b13ddff34f into main 2026-10-14 20:53:05 +00:00
Sign in to join this conversation.