Public: anyone can read this; the crew can change it.
The sentinel does not refile a test's budget breach in the hour after the pull that fixed it landed, unless it fails again on checks started after the fix #8190
Check · Review · Land · Live done — Landed and live in production.
The sentinel no longer files a new issue for a test that is red on many pulls (a `shared:` cause) in the hour after the pull that fixed it landed. It stays silent unless at least `SHARED_PULLS` (3) pulls fail that test again on checks created after the fix.
shipped production is serving it deploy 17507df
The sentinel no longer files a new issue for a test that is red on many pulls (a shared: cause) in the hour after the pull that fixed it landed. It stays silent unless at least SHARED_PULLS (3) pulls fail that test again on checks created after the fix.
What changed
src/checks/shared_red.ts: newpullsFailedSince(db, cause, sinceMs). It counts the distinct pulls whose failed check was created at or aftersinceMsand named the test behind the shared cause. This answers the question the hour's window can't, because that window still holds the reds from before the fix.src/crew/sentinel.ts:
- Budget-breach and degraded findings now carry the cause they read (Finding.cause).
- In hunt, a new sinceFix runs before continuesDone. It looks for the finding's issue closed as done or split within SHARED_WINDOW_MS.
- With fewer than 3 reds since that close, it files and says nothing. With 3 or more, it comments once on the closed issue, saying the fix may not be live yet, and records commented_at so it does not repeat.
- Without this, a budget breach never reached continuesDone (it has no incident), which is why #8146, #8175 and #8177 were filed for one cause.
sentinelTicktreats a finding held this way as no signal. Otherwise it would start a hunt every tick for that hour.
What to look at
- Close time: I use the issue's
closed_at.mergePullcloses the issues a pull fixes only afterlandPullhas written main, so that time is the landing, not the merge request. - After the hour: once it passes, the window holds only reds from after the fix. A test still shared then is filed as a new finding, as before.
- Counts: the Sentinel terminal screen and the MCP read open
sentinel_findingrows, and the detectors' output is unchanged. Causes with no recent fix count exactly as before.
Chosen not to do
- The hold applies only to
shared:causes. "Failed the test on checks created after the fix" only has a meaning there;red:,stuck:andqueue:keep their current filing. - No new MCP tool or field.
Tests
test/sentinel.test.tshas a new block, "a shared test whose fix landed within the hour":
- 12 reds before a fix that landed 1 minute ago, and none since: no new issue, no comment, and no hunt on the next tick. - 3 reds on checks created after the fix: exactly one comment on the closed issue, and the next hunt adds nothing.
- Both tests fail without the change.
- Passing:
bun scripts/gate.ts,bun x tsc --noEmit, and eight suites (107 tests, includingtest/sentinel.test.ts,test/shared-red.test.ts,test/tui-sentinel.test.tsandtest/mcp-size.test.ts). scripts/fast.tsnamed 1078 test files, too many to run here, so I chose those suites myself; the forge's check runs the full suite on this push.
🤖 Generated with Claude Code
Read in full; no security, authorization or output findings. pullsFailedSince binds every parameter, and the sentinel change adds no new door or write path. The hold applies only to shared: causes, keys on a close the fix actually made (done or split), tells the closed issue once, and sentinelTick stops hunting while a finding is held. Both added tests fail without the change. Non-blocking: pullsFailedSince has no direct test in test/shared-red.test.ts, and neither the split close reason nor the hold ending after the hour is covered.
The sentinel no longer files a new issue for a test that is red on many pulls (a
shared:cause) in the hour after the pull that fixed it landed. It stays silent unless at leastSHARED_PULLS(3) pulls fail that test again on checks created after the fix.What changed
src/checks/shared_red.ts: newpullsFailedSince(db, cause, sinceMs). It counts the distinct pulls whose failed check was created at or aftersinceMsand named the test behind the shared cause. This answers the question the hour's window can't, because that window still holds the reds from before the fix.src/crew/sentinel.ts:- Budget-breach and degraded findings now carry the
causethey read (Finding.cause). - Inhunt, a newsinceFixruns beforecontinuesDone. It looks for the finding's issue closed as done or split withinSHARED_WINDOW_MS. - With fewer than 3 reds since that close, it files and says nothing. With 3 or more, it comments once on the closed issue, saying the fix may not be live yet, and recordscommented_atso it does not repeat. - Without this, a budget breach never reachedcontinuesDone(it has noincident), which is why #8146, #8175 and #8177 were filed for one cause.sentinelTicktreats a finding held this way as no signal. Otherwise it would start a hunt every tick for that hour.What to look at
closed_at.mergePullcloses the issues a pull fixes only afterlandPullhas written main, so that time is the landing, not the merge request.sentinel_findingrows, and the detectors' output is unchanged. Causes with no recent fix count exactly as before.Chosen not to do
shared:causes. "Failed the test on checks created after the fix" only has a meaning there;red:,stuck:andqueue:keep their current filing.Tests
test/sentinel.test.tshas a new block, "a shared test whose fix landed within the hour":- 12 reds before a fix that landed 1 minute ago, and none since: no new issue, no comment, and no hunt on the next tick. - 3 reds on checks created after the fix: exactly one comment on the closed issue, and the next hunt adds nothing.
bun scripts/gate.ts,bun x tsc --noEmit, and eight suites (107 tests, includingtest/sentinel.test.ts,test/shared-red.test.ts,test/tui-sentinel.test.tsandtest/mcp-size.test.ts).scripts/fast.tsnamed 1078 test files, too many to run here, so I chose those suites myself; the forge's check runs the full suite on this push.🤖 Generated with Claude Code
Closes #8185