From 6e95c3542cf6cbbf4ca0f63fb80235992b4aed36 Mon Sep 17 00:00:00 2001 From: Mikael Hugo Date: Wed, 13 May 2026 22:59:13 +0200 Subject: [PATCH] fix(bootstrap): always dispatch self-feedback triage on session_start MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The session_start hook only invoked dispatchSelfFeedbackInlineFixIfNeeded when triage.stillBlocked contained at least one high/critical entry. After the previous commit rewired the worker as a triage queue that returns every open forge-local entry (not just high/critical), this gate stranded medium/low backlog forever at startup — the unit was never given a chance to triage them. The dispatcher's own selectInlineFixCandidates is now the source of truth for eligibility; the call site should call unconditionally. Keep the high/critical-specific notify (still useful operator signal when the loud ones are present) but stop using it to gate the dispatch. The turn_end hook at the bottom of register-hooks.js already calls the dispatcher unconditionally, so this change aligns the two paths. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../extensions/sf/bootstrap/register-hooks.js | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/resources/extensions/sf/bootstrap/register-hooks.js b/src/resources/extensions/sf/bootstrap/register-hooks.js index 053c87277..1831de204 100644 --- a/src/resources/extensions/sf/bootstrap/register-hooks.js +++ b/src/resources/extensions/sf/bootstrap/register-hooks.js @@ -410,9 +410,13 @@ export function registerHooks(pi, ecosystemHandlers = []) { { noticeKind: NOTICE_KIND.SYSTEM_NOTICE }, ); } - // Forge-only: high/critical entries are queued as hidden follow-up repair - // work on startup, even outside /autonomous. The drain helper owns claim TTL - // and delivery failure retry, so this is safe to call opportunistically. + // Forge-only: queue the triage unit as hidden follow-up work on + // startup, even outside /autonomous. The dispatcher's own selector + // (selectInlineFixCandidates) decides eligibility — every open + // forge-local entry should reach a fix/promote/close decision per + // session, not just the high/critical ones. The drain helper owns + // claim TTL and delivery failure retry so this is safe to call + // opportunistically. const highBlocked = triage.stillBlocked.filter( (e) => e.severity === "high" || e.severity === "critical", ); @@ -423,11 +427,11 @@ export function registerHooks(pi, ecosystemHandlers = []) { "warning", { noticeKind: NOTICE_KIND.SYSTEM_NOTICE }, ); - const { dispatchSelfFeedbackInlineFixIfNeeded } = await import( - "../self-feedback-drain.js" - ); - dispatchSelfFeedbackInlineFixIfNeeded(process.cwd(), ctx, pi); } + const { dispatchSelfFeedbackInlineFixIfNeeded } = await import( + "../self-feedback-drain.js" + ); + dispatchSelfFeedbackInlineFixIfNeeded(process.cwd(), ctx, pi); } catch { /* non-fatal — self-feedback drain must never block session start */ }