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

Sentinel: The guard parked 33 runs in trevato/forge in a day #2198

Merged opened this

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

Merged

mason/forge:mason/2197-sentinel-the-guard-parked-33-runs-in-tre → main 1 commit fork

  • Merged. mason/2197-sentinel-the-guard-parked-33-runs-in-tre was merged into main as d678625.

Review

Sign in to review this change.
2 files changed +32 −2
src/crew/guard.ts +6 −2
@@ -142,7 +142,11 @@ function capFrom(db: Database, repo: Repo, issue: Issue, now: Date): string {
142142 * who may direct the crew last spoke on it. A run a restart or the
143143 * provider cut short, a resumed run and a skipped one are not new starts;
144144 * nor is a reviewer's run on a pull, which only answers a push the counted
145 * runs made and is bounded by the hand-over (`HANDOVER_ROUNDS`).
145 * runs made and is bounded by the hand-over (`HANDOVER_ROUNDS`). Nor is a
146 * run bringing a pull up to a main that moved, or answering its red check:
147 * neither is the agent going round, and both already have their own bound
148 * (`CHECK_FAILED_LIMIT` over `automaticRunsSince`), which parks or releases
149 * the pull itself — counted here too, they parked pulls that were working.
146150 */
147151 export function capReached(
148152 db: Database,
@@ -156,7 +160,7 @@ export function capReached(
156160 `SELECT COUNT(*) AS n FROM run
157161 WHERE issue_id = ?1 AND kind = 'agent' AND created_at > ?2
158162 AND attempt = 0
159 AND reason != 'review'
163 AND reason NOT IN ('review', 'conflict', 'check_failed')
160164 AND summary NOT LIKE 'interrupted: %'
161165 AND summary NOT LIKE 'skipped: %'`,
162166 )
test/crew-guard.test.ts +26
@@ -342,6 +342,32 @@ describe("an issue cannot loop", () => {
342342 ).toBe("queued");
343343 });
344344
345 test("bringing a pull up to main and answering its red check are bounded on their own, not by the cap", () => {
346 const issue = held("Quieter toasts");
347 for (let n = 0; n < ISSUE_RUN_CAP - 1; n++) {
348 ran(issue, undefined, "ok", "feedback");
349 ran(issue, undefined, "ok", "conflict");
350 ran(issue, undefined, "ok", "check_failed");
351 }
352 const before = guards("capped");
353 expect(
354 queueAgentRun(app, fresh(), issue, bot, "assigned", alice.id)?.state,
355 ).toBe("queued");
356 expect(guards("capped")).toBe(before);
357 });
358
359 test("the agent's own starts still reach the cap", () => {
360 const issue = held("Louder toasts");
361 ran(issue);
362 for (let n = 1; n < ISSUE_RUN_CAP; n++) {
363 ran(issue, undefined, "ok", "feedback");
364 ran(issue, undefined, "ok", "conflict");
365 }
366 expect(
367 queueAgentRun(app, fresh(), issue, bot, "assigned", alice.id),
368 ).toBeUndefined();
369 });
370
345371 test("the cap is a setting", () => {
346372 const issue = held("Softer shadow");
347373 ran(issue);

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs