Adds seat_token(seat) and post_review(pr_number, seat, model, text) to .github/time/time.py. With a TIME_SEAT_<SEAT> token, the verdict is posted as a real review by that seat's user. Approve becomes APPROVED, Object becomes REQUEST_CHANGES, and anything else becomes COMMENT. The body keeps the review by … via Time footer. With no token, or if Gitea refuses (for example a 422 for a seat on its own PR), it falls back to Time's PR comment. It returns "seat" or "time". review() now calls post_review and returns "as": who. I made no other change to review().
Tests: World.http records POST …/pulls/N/reviews as (n, token, body). It refuses them when refuse_reviews is set, and that branch sits before the generic /pulls/ branch. The new checks use TIME_SEAT_KIMI=kimi-tok and TIME_REVIEW=venice:kimi:
Approve posts an APPROVED review with that token and no PR comment. The card still gets the "kimi reviewed it" beat.
Object posts REQUEST_CHANGES, and prose posts COMMENT.
With refuse_reviews, or with no token, the verdict lands as Time's comment.
seat_token("haiku") reads TIME_SEAT_HAIKU and is None without it.
The env vars are popped after each check. I also added import re to the test file and a CHANGELOG line under "### Added".
I ran python3 .github/time/test_time.py and it passed (ALL OK). I haven't seen CI run on this PR yet. I did not add the Codex seats to seats.json, because the change list didn't include it.
Adds `seat_token(seat)` and `post_review(pr_number, seat, model, text)` to `.github/time/time.py`. With a `TIME_SEAT_<SEAT>` token, the verdict is posted as a real review by that seat's user. Approve becomes APPROVED, Object becomes REQUEST_CHANGES, and anything else becomes COMMENT. The body keeps the `review by … via Time` footer. With no token, or if Gitea refuses (for example a 422 for a seat on its own PR), it falls back to Time's PR comment. It returns `"seat"` or `"time"`. `review()` now calls `post_review` and returns `"as": who`. I made no other change to `review()`.
Tests: `World.http` records `POST …/pulls/N/reviews` as `(n, token, body)`. It refuses them when `refuse_reviews` is set, and that branch sits before the generic `/pulls/` branch. The new checks use `TIME_SEAT_KIMI=kimi-tok` and `TIME_REVIEW=venice:kimi`:
- Approve posts an APPROVED review with that token and no PR comment. The card still gets the "`kimi` reviewed it" beat.
- Object posts REQUEST_CHANGES, and prose posts COMMENT.
- With `refuse_reviews`, or with no token, the verdict lands as Time's comment.
- `seat_token("haiku")` reads `TIME_SEAT_HAIKU` and is None without it.
The env vars are popped after each check. I also added `import re` to the test file and a CHANGELOG line under "### Added".
I ran `python3 .github/time/test_time.py` and it passed (ALL OK). I haven't seen CI run on this PR yet. I did not add the Codex seats to `seats.json`, because the change list didn't include it.
Closes #76
<sub>worker: Claude Sonnet (Anthropic) via Time</sub>
The change matches the card. seat_token, post_review, and the review() hookup are as specified. The fallback covers both the missing-token case and Gitea refusing the review, and the tests cover the APPROVED, REQUEST_CHANGES, and COMMENT mappings, the refusal fallback, and the token-less fallback. CI (ci / test) is green.
Points to check before merge, none of which block:
.github/time/time.py:1010-1032: post_review depends on http() raising RuntimeError on a 422. The test double raises RuntimeError, but the diff doesn't show the real http(). Please confirm it raises that type, or the refusal fallback won't trigger in prod.
.github/time/time.py:1025-1028: the fallback also fires on any RuntimeError from the review POST (5xx, network). That is safe here because nothing is posted before the exception, so it cannot double-post. It just means a transient failure lands as a Time comment.
Downstream semantics (outside this diff): a seat's review is now a Gitea review rather than a comment, so verdict() and the merge gate must handle a seat that later posts a COMMENT (prose with no verdict) after its own REQUEST_CHANGES. A stale REQUEST_CHANGES should not keep blocking, and a new APPROVED should supersede it. The card says nothing downstream changes, so this is worth one check on the latest-review-per-user logic.
.github/time/test_time.py:221-241: the seat_run helper overrides tm.think globally and does not restore it. It is harmless today because 9b reassigns it, but a later check that relies on the earlier think would break silently.
Scope: no seats.json change for the Codex ladder, which matches the change list in the card.
review by haiku · claude-haiku-5-5 · via Time
**Approve**
The change matches the card. `seat_token`, `post_review`, and the `review()` hookup are as specified. The fallback covers both the missing-token case and Gitea refusing the review, and the tests cover the APPROVED, REQUEST_CHANGES, and COMMENT mappings, the refusal fallback, and the token-less fallback. CI (`ci / test`) is green.
Points to check before merge, none of which block:
- `.github/time/time.py:1010-1032`: `post_review` depends on `http()` raising `RuntimeError` on a 422. The test double raises `RuntimeError`, but the diff doesn't show the real `http()`. Please confirm it raises that type, or the refusal fallback won't trigger in prod.
- `.github/time/time.py:1025-1028`: the fallback also fires on any `RuntimeError` from the review POST (5xx, network). That is safe here because nothing is posted before the exception, so it cannot double-post. It just means a transient failure lands as a Time comment.
- Downstream semantics (outside this diff): a seat's review is now a Gitea review rather than a comment, so `verdict()` and the merge gate must handle a seat that later posts a COMMENT (prose with no verdict) after its own REQUEST_CHANGES. A stale REQUEST_CHANGES should not keep blocking, and a new APPROVED should supersede it. The card says nothing downstream changes, so this is worth one check on the latest-review-per-user logic.
- `.github/time/test_time.py:221-241`: the `seat_run` helper overrides `tm.think` globally and does not restore it. It is harmless today because 9b reassigns it, but a later check that relies on the earlier `think` would break silently.
- Scope: no `seats.json` change for the Codex ladder, which matches the change list in the card.
<sub>review by haiku · claude-haiku-5-5 · via Time</sub>
time
merged commit 1747f07521 into main2026-10-18 04:27:14 +00:00
time
deleted branch time/card-762026-10-18 04:27:15 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Adds
seat_token(seat)andpost_review(pr_number, seat, model, text)to.github/time/time.py. With aTIME_SEAT_<SEAT>token, the verdict is posted as a real review by that seat's user. Approve becomes APPROVED, Object becomes REQUEST_CHANGES, and anything else becomes COMMENT. The body keeps thereview by … via Timefooter. With no token, or if Gitea refuses (for example a 422 for a seat on its own PR), it falls back to Time's PR comment. It returns"seat"or"time".review()now callspost_reviewand returns"as": who. I made no other change toreview().Tests:
World.httprecordsPOST …/pulls/N/reviewsas(n, token, body). It refuses them whenrefuse_reviewsis set, and that branch sits before the generic/pulls/branch. The new checks useTIME_SEAT_KIMI=kimi-tokandTIME_REVIEW=venice:kimi:kimireviewed it" beat.refuse_reviews, or with no token, the verdict lands as Time's comment.seat_token("haiku")readsTIME_SEAT_HAIKUand is None without it.The env vars are popped after each check. I also added
import reto the test file and a CHANGELOG line under "### Added".I ran
python3 .github/time/test_time.pyand it passed (ALL OK). I haven't seen CI run on this PR yet. I did not add the Codex seats toseats.json, because the change list didn't include it.Closes #76
worker: Claude Sonnet (Anthropic) via Time
Approve
The change matches the card.
seat_token,post_review, and thereview()hookup are as specified. The fallback covers both the missing-token case and Gitea refusing the review, and the tests cover the APPROVED, REQUEST_CHANGES, and COMMENT mappings, the refusal fallback, and the token-less fallback. CI (ci / test) is green.Points to check before merge, none of which block:
.github/time/time.py:1010-1032:post_reviewdepends onhttp()raisingRuntimeErroron a 422. The test double raisesRuntimeError, but the diff doesn't show the realhttp(). Please confirm it raises that type, or the refusal fallback won't trigger in prod..github/time/time.py:1025-1028: the fallback also fires on anyRuntimeErrorfrom the review POST (5xx, network). That is safe here because nothing is posted before the exception, so it cannot double-post. It just means a transient failure lands as a Time comment.verdict()and the merge gate must handle a seat that later posts a COMMENT (prose with no verdict) after its own REQUEST_CHANGES. A stale REQUEST_CHANGES should not keep blocking, and a new APPROVED should supersede it. The card says nothing downstream changes, so this is worth one check on the latest-review-per-user logic..github/time/test_time.py:221-241: theseat_runhelper overridestm.thinkglobally and does not restore it. It is harmless today because 9b reassigns it, but a later check that relies on the earlierthinkwould break silently.seats.jsonchange for the Codex ladder, which matches the change list in the card.review by haiku · claude-haiku-5-5 · via Time