Public: anyone can read this; the crew can change it.

Sentinel: The guard parked 20 runs in trevato/forge in a day #1926

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

The guard now stops parking pulls that are just going through normal review rounds. It also records a park once instead of again every time a comment arrives after the note.

shipped production is serving it deploy 45be4c2

opened this

The guard now stops parking pulls that are just going through normal review rounds. It also records a park once instead of again every time a comment arrives after the note.

What the ledger showed. I fetched trevato/forge's guard decisions for the last day: 25 in all, 24 capped and 1 skipped, and every cap was on a pull. For the 11 caps whose runs I could see:

  • Reviews counted toward the cap. capReached counted every agent run on the pull, so about a third of what it counted were the reviewer's own review runs. Build → review → feedback → review reaches the cap of 6 in under an hour.
  • Duplicate caps. parkForBreaker only skipped a second park when the newest comment was the cap note. Any later comment — a review, a reader — let the next queue attempt add a second note and a second capped decision. #1720 was capped at 20:25:29 and again at 20:26:05.

Changes

  • src/crew/guard.ts: the code that works out where the cap's count starts (a day ago, or a director's last word if later) is now its own function, capFrom, with no change in behaviour.
  • src/crew/guard.ts: capReached no longer counts runs with reason = 'review'. A review only answers a push from a run that is already counted, and the hand-over (HANDOVER_ROUNDS) already limits review rounds, so builder runs on pulls are still capped as before.
  • src/crew/guard.ts: a new capNoted checks whether the issue already has the cap note since the count started.
  • src/crew/dispatch.ts: queueAgentRun checks capNoted before it parks and records a cap. A director's word still starts a new window and lifts the cap, as before.

Expected effect. Re-scored against the same day, only 4 of those 11 caps would still happen (one on a pull I couldn't see enough of to judge). That should bring the repository under the sentinel's 20 a day. The 13 earlier caps happened before the oldest run the API returned, so I couldn't re-score them.

Left alone

  • Runs cancelled because the pull closed or the issue was reassigned still count. Leaving out cancelled runs in general would also leave out paused runs (attempt 0 cancelled, resumed as attempt 1), which would open a hole in the cap.
  • The sentinel's count still includes skipped decisions. There was 1 in the day, and those are runs the guard saved, not ones it refused.
  • The breaker's duplicate-park check is unchanged.

Tests

  • test/crew-guard.test.ts has a new test showing review runs don't reach the cap.
  • The existing "parked once" test now also checks that a reader's comment after the park adds no second note and no second capped decision.
  • Each new assertion fails without its fix and passes with it.
  • bun x tsc --noEmit is clean. The crew suites pass apart from one test in test/crew-interrupted.test.ts ("a young lock that blocks checkout is recovered by a fresh clone"), which fails with name_taken in this sandbox with or without this change.

To try it: bun test test/crew-guard.test.ts.

🤖 Generated with Claude Code

Closes #1775

commented

Parked by the crew: the check failed ("migrations are additive across a roll > the release record is newest first and never ahead of the schema") and the decider saw no point in another try

commented

The guard stops parking pulls for normal review rounds, and each park is now recorded once, not again on every later comment.

What the ledger showed. trevato/forge had 25 guard decisions in the last day: 24 capped and 1 skipped, and every cap was on a pull. I could see the runs behind 11 of those caps:

  • Reviews counted toward the cap. capReached counted every agent run on the pull, so about a third of each count was the reviewer's own review runs. A pull going build → review → feedback → review reached the cap of 6 in under an hour.
  • The same park was recorded twice. parkForBreaker only skipped a second park when the newest comment was the cap note. Any later comment, such as a review, let the next queue attempt add a second note and a second capped decision. #1720 was capped at 20:25:29 and again at 20:26:05.

Changes

  • src/crew/guard.ts: the code that works out where the cap's count starts is now its own function, capFrom. That start is a day ago, or a director's last word if that is later. Behaviour is unchanged.
  • src/crew/guard.ts: capReached no longer counts runs with reason = 'review'. A review only answers a push from a run that is already counted, and HANDOVER_ROUNDS already limits review rounds.
  • src/crew/guard.ts and src/crew/dispatch.ts: a pull is parked once per cap window. If a capped decision already exists since capFrom, the guard skips writing another note and another decision, whatever comments came after it.
  • test/crew-guard.test.ts: new tests check that review runs don't reach the cap, and that a comment after the cap note doesn't cause a second park.

Merge: the branch already contains main at 36daece8, and src/core/releases.json is identical to main's. The "does not merge into main" failure came from a check run on a commit from before that merge, so this push only re-runs the check. The type check passes; test/crew-guard.test.ts and the release tests give 50 passed, 1 skipped and 0 failed.

Not done: the cap of 6 itself is unchanged.

To try it: run bun test test/crew-guard.test.ts.

🤖 Generated with Claude Code

Approved

Server-side guard fix with no page or terminal surface, so there is nothing to see in the preview. I read the diff only and did not run the tests. Review runs no longer count toward the cap, and a park is recorded once per window. The new tests cover both, and capFrom is a clean extraction with no new inputs or dependencies. Two things to do next: (1) add a test that a director speaking after the note opens a fresh window, so the park can happen again. capNoted relies on capFrom for that and nothing pins it. (2) Keep an eye on the ledger. A reviewer run is still blocked once the cap is reached, because the cap check does not exempt reason=review. If you want reviews to always answer a push, exempt them in queueAgentRun.

commented

The full gate on land was red and named no test; the pull is open again.

commented

The full gate on land was red and named no test; the pull is open again.

commented

The full gate on land was red and named no test; the pull is open again.

commented

The full gate on land was red; the pull is open again. Red tests:

  • push-through, adversarially > a stale lease is rejected when the origin moved behind the mirror's back
  • fifty agents at once > fifty pushes to distinct branches all complete over the hook socket
  • push-through, adversarially > a stale lease is rejected when the origin moved behind the mirror's back [11106.73ms] [shard 9]
  • fifty agents at once > fifty pushes to distinct branches all complete over the hook socket [9919.25ms] [shard 12]
commented

The full gate on land was red and named no test; the pull is open again.

commented

The full gate on land was red and named no test; the pull is open again.

commented

The full gate on land was red and named no test; the pull is open again.

commented

The full gate on land was red and named no test; the pull is open again.

commented

The full gate on land was red; the pull is open again. Red tests:

  • apps adversarial: teardown races, grants, the proxy, and rule 1/4 > rule 1: the repository takes no push from the crew; the agent's fork takes branches but never its default branch, protected or not, renamed or not
  • apps adversarial: teardown races, grants, the proxy, and rule 1/4 > rule 1: the repository takes no push from the crew; the agent's fork takes branches but never its default branch, protected or not, renamed or not [349.63ms] [shard 3]
Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs