Files
time/.agents/skills/housekeeping
Claude e69fbd32eb
ci / test (pull_request) Successful in 45s
heartbeat / tick (pull_request_review) Successful in 15s
Router: record each pick's outcome, so a learning policy has data
Part of #72, follows #168. The router's policy is still one function
(`router.score`); a restless bandit needs rewards, and nothing recorded
what a pick turned into. This card is the data, not the policy.

- `router.py`: the shape of an outcome and the arithmetic over the log.
  `picks()` reads every live pick out of Astra's beats (a card picked
  twice keeps its first pick; a dry run picked nothing), `outcome()`
  settles one pick into a line and returns None while its card is open,
  `read_outcomes()`/`summary()`/`outcome_lines()` are the read side.
- `housekeeping.py` step 4: one line per settled pick appended to
  `time/ledger/router-outcomes.jsonl` in one commit, dry-run writes
  nothing. A pick already in the file is never written twice.
- `astra.py`: one summary line per kind (picks, merged share, median
  days, median $) over the ranked table, so the owner sees what a kind
  returns before changing its weight.

Two notes on what the card asked for:

- Spend proxy: the card offered the card's worker beats' `usd` or the
  runs' time window. Beats carry no `usd` today, so this uses the runs'
  time window — each `dispatched` beat until the next beat on the card
  — which attributes a run's spend to the card that ran it instead of
  charging it the whole factory's spend over the days it was open.
  Review and planning calls on the card are not counted; two cards
  whose runs overlap are each charged their own window. Documented in
  `time/ledger/README.md`.
- The line carries `pr` as well as the shape the card listed: the card
  asks for the PR number and the line is the only place to keep it.
- The file lives under `time/ledger/`, as the card says, since that is
  the one path `ci.yml` ignores and the sweep appends to it daily. No
  workflow change is needed: `housekeeping.yml` already passes
  `GITHUB_TOKEN` (the push) and `TIME_VENTURE_MEASURE_DAYS` (day 7).

A venture pick waits until its venture's day 7 has passed and then
carries the signups counted at that day; with no registry entry for the
card the line goes in with no count rather than waiting forever.

Tests: `test_housekeeping.py` covers a merged pick, an unmerged pick, a
pick still in flight (no line), idempotence, the venture's day-7 count
and dry-run; `test_time.py` section 172 covers the pure functions, the
summary's arithmetic and the log's header. All three suites green.

Closes #172

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