Council verdict: TIME_REVIEW takes several seats, votes count per seat, and TIME_REVIEW_TIEBREAK names a seat called only on a tie #77

Closed
opened 2026-10-17 19:22:15 +00:00 by teahubxyz · 4 comments
Owner

Depends on #76

Why. One reviewer is one opinion. The operator wants seats that keep each other in check and a vote that settles instead of deadlocking 1 v 1.

Council design (decided 2026-10-17).

  • Votes count per seat (one Gitea identity each, #76). Models within a family are distinct voters — haiku and opus can both sit — while cross-family agreement is the stronger evidence, so the standing configuration mixes families.
  • TIME_REVIEW is a comma-separated list of seat specs; every listed seat reviews each PR and posts as itself. Standing pair for this repo: claude:haiku, codex (Codex reviews through a headless CLI run, #79; until that lands the pair is claude:haiku, claude:opus).
  • TIME_REVIEW_TIEBREAK names one seat that is called only when the standing seats split (equal approves and objects, or below quorum with no objection). For this repo: venice:kimi. Venice credits are spent on ties alone.
  • TIME_REVIEW_QUORUM (default 1): approvals needed, net of objections.
  • Codex's seat ladder, comparable to haiku → fable: luna, terra, sol, astra. Add them to seats.json with the CLI route, then they are valid in TIME_REVIEW like any seat. Note the name clash with the daily planning tick ("Astra", an opus seat): the tick keeps its role name in its log line; the astra login is the Codex seat.

Change (.github/time/time.py).

  • review(): parse the list; run each seat; each posts via post_review(); return the seats it ran.
  • verdict(pr, since): take each trusted identity's latest verdict since since (Time's own comments count as one identity, gitea-actions); approve when approves minus objects reaches the quorum, object when objects exceed approves, else None.
  • Tie path in land(): on None with every standing seat having voted, call the tie-break seat once (one review, posted as itself), then re-evaluate; if still None, one "the council is split N–N; over to a human" comment with a needs-human beat. With one standing seat and quorum 1, behaviour is exactly today's.

Tests. Two seats Approve/Approve → merge; Approve/Object → tie-break seat is called exactly once, its Approve merges, its Object yields the split message once; a seat that objected and later re-approves → its latest vote counts; quorum 2 with one Approve and no tie-break configured → waits; the single-seat path unchanged (checks 13 and 55 keep passing); the tie-break seat is never called when the standing seats agree.

CHANGELOG line under "### Added". The TIME_REVIEW / TIME_REVIEW_TIEBREAK variables on this repo are the CEO's to set once this lands.

DONE: PR open with the code above, python3 .github/time/test_time.py green including the new checks, CI green

Depends on #76 **Why.** One reviewer is one opinion. The operator wants seats that keep each other in check and a vote that settles instead of deadlocking 1 v 1. **Council design (decided 2026-10-17).** - Votes count per seat (one Gitea identity each, #76). Models within a family are distinct voters — `haiku` and `opus` can both sit — while cross-family agreement is the stronger evidence, so the standing configuration mixes families. - `TIME_REVIEW` is a comma-separated list of seat specs; every listed seat reviews each PR and posts as itself. Standing pair for this repo: `claude:haiku, codex` (Codex reviews through a headless CLI run, #79; until that lands the pair is `claude:haiku, claude:opus`). - `TIME_REVIEW_TIEBREAK` names one seat that is called **only when the standing seats split** (equal approves and objects, or below quorum with no objection). For this repo: `venice:kimi`. Venice credits are spent on ties alone. - `TIME_REVIEW_QUORUM` (default 1): approvals needed, net of objections. - Codex's seat ladder, comparable to haiku → fable: `luna`, `terra`, `sol`, `astra`. Add them to `seats.json` with the CLI route, then they are valid in `TIME_REVIEW` like any seat. Note the name clash with the daily planning tick ("Astra", an opus seat): the tick keeps its role name in its log line; the `astra` login is the Codex seat. **Change (`.github/time/time.py`).** - `review()`: parse the list; run each seat; each posts via `post_review()`; return the seats it ran. - `verdict(pr, since)`: take each trusted identity's **latest** verdict since `since` (Time's own comments count as one identity, `gitea-actions`); `approve` when approves minus objects reaches the quorum, `object` when objects exceed approves, else `None`. - Tie path in `land()`: on `None` with every standing seat having voted, call the tie-break seat once (one review, posted as itself), then re-evaluate; if still `None`, one "the council is split N–N; over to a human" comment with a `needs-human` beat. With one standing seat and quorum 1, behaviour is exactly today's. **Tests.** Two seats Approve/Approve → merge; Approve/Object → tie-break seat is called exactly once, its Approve merges, its Object yields the split message once; a seat that objected and later re-approves → its latest vote counts; quorum 2 with one Approve and no tie-break configured → waits; the single-seat path unchanged (checks 13 and 55 keep passing); the tie-break seat is never called when the standing seats agree. CHANGELOG line under "### Added". The `TIME_REVIEW` / `TIME_REVIEW_TIEBREAK` variables on this repo are the CEO's to set once this lands. DONE: PR open with the code above, `python3 .github/time/test_time.py` green including the new checks, CI green
teahubxyz changed title from Council verdict: TIME_REVIEW takes several seats and the PR lands on a majority of distinct identities to Council verdict: TIME_REVIEW takes several seats, votes count per seat, and TIME_REVIEW_TIEBREAK names a seat called only on a tie 2026-10-17 22:54:45 +00:00
teahubxyz added the queued label 2026-10-18 01:55:04 +00:00
time added ready and removed queued labels 2026-10-18 04:39:51 +00:00

⏱️ Time: Claude Sonnet (Anthropic) is working on this now, on branch time/card-77.

⏱️ Time: Claude Sonnet (Anthropic) is working on this now, on branch `time/card-77`. <!-- time {"beat":"dispatched","launched":true,"worker":"anthropic"} -->

⏱️ Time: sonnet opened PR #122 (23 steps, claude-sonnet-5-5). Review and landing follow on the next beat.

⏱️ Time: `sonnet` opened PR #122 (23 steps, claude-sonnet-5-5). Review and landing follow on the next beat. <!-- time {"beat":"dispatched","worker":"anthropic","pr":122,"steps":23,"seat":"sonnet","model":"claude-sonnet-5-5"} -->

⏱️ Time: PR #122 is up for this card. haiku reviewed it on the PR.

⏱️ Time: PR #122 is up for this card. `haiku` reviewed it on the PR. <!-- time {"beat":"pr","pr":122,"launched":false,"review":"venice","seat":"haiku","as":"seat"} -->
time closed this issue 2026-10-18 04:59:26 +00:00

⏱️ Time: approved and green, merged PR #122. Card done.

⏱️ Time: approved and green, merged PR #122. Card done. <!-- time {"beat":"merged","pr":122} -->
Sign in to join this conversation.
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: teahubxyz/time#77