Files
time/.github
Claude cf38e08677
ci / test (pull_request) Successful in 45s
heartbeat / tick (pull_request_review) Successful in 22s
Router: optimization candidates from the ledger, CI and parked cards
The router only ranked work someone had written a card for, so optimization
showed up only when a human noticed it. It now reads three of the factory's own
records over the last seven days and proposes the rest itself, deterministically.

router.py, one synthetic candidate per finding (`opt:<source>:<id>`, kind
optimization, no card yet, a drafted title and body that carries its own key and
a `DONE:` line):

- `ledger_candidates`: the week's spend grouped by model and by entry point (a
  line's `entry` where it has one, else `pool`, the route it booked to). A group
  that took over half the bill is a candidate, where there is a second group in
  that dimension to compare it with; so is a model whose spend per call is double
  its own median, which is a few heavy calls behind a cheap average. Pennies
  (under $0.25 a week) are left alone and one group yields at most one candidate.
- `run_candidates`: Actions runs as `/actions/runs` gives them (the shape
  `tea_actions` reads: the list, or `workflow_runs`). A workflow with two or more
  failed or cancelled runs in the window is a candidate, with the failure count
  and the last run's id.
- `parked_candidates`: a card parked by an `error` or `stuck` beat older than a
  day, with no open PR and #78's automatic retries spent ("retry or split #N").
  One Time will still retry on its own is left to it.
- `named` / `opt_candidates`: a source an open card already names (`Router:
  opt:<source>:<id>` in the body) is not proposed again.

astra.py gathers the three sources (`ledger_week`, `action_runs`, `parked_cards`;
each is context, so unreadable means no candidates from it, never a failed run)
and the seat judges them like any other candidate. Live, a picked one is written
as a card, unqueued and a candidate from tomorrow, and is never worked on in
place; dry, the ranked table shows it as "would be written as a card". The log
line and the beat's `opt` say which source became which card.

Tests (test_time.py section 171): a ledger with one dominant route yields one
candidate, and so does the entry-point dimension, the median rule, pennies, a
single group and a stale window; two failed runs of one workflow yield one
candidate with its count and last run id; a parked card yields one unless it has
an open PR, retries left or was parked today; a source an open card names yields
none; Astra live writes the card unqueued while dry writes nothing.

Closes #171

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EzRXxLDJF4YDoZgzSsbW24
2026-10-19 17:03:18 +00:00
..