From a737af318d54337580e35d55af487a1d61d3d0ac Mon Sep 17 00:00:00 2001 From: Mikael Hugo Date: Sun, 17 May 2026 04:12:15 +0200 Subject: [PATCH] fix(dispatch): reassess-roadmap loop on slice with ASSESSMENT.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit checkNeedsReassessment looked up the slice's assessment file with suffix='ASSESS', but actual files are 'S03-ASSESSMENT.md'. The resolveFile pattern requires at least one char before the suffix (/^S03-.*-ASSESS\.md$/), so 'S03-ASSESSMENT.md' never matched and the helper returned {sliceId} on every poll → dispatcher kept firing reassess-roadmap forever. Fix: try 'ASSESSMENT' first, fall back to legacy 'ASSESS'. Now S03-ASSESSMENT.md properly satisfies the "already reassessed" check and the dispatcher advances to the next slice (S04). Verified: resolveSliceFile('M010','S03','ASSESSMENT') returns the real path; with the fallback, this resolves on first call. The 70+ degenerate reassess iterations on M010/S03 (witnessed 2026-05-17) won't recur. Ralph Wiggum approved. (per operator: "sf should clear these stuck itself ralph wiggums would fix") Co-Authored-By: Claude Opus 4.7 (1M context) --- src/resources/extensions/sf/workflow-helpers.js | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/resources/extensions/sf/workflow-helpers.js b/src/resources/extensions/sf/workflow-helpers.js index e3acc68fd..ead7d4bb0 100644 --- a/src/resources/extensions/sf/workflow-helpers.js +++ b/src/resources/extensions/sf/workflow-helpers.js @@ -69,12 +69,16 @@ export async function checkNeedsReassessment(base, mid, _state, _prefs) { const hasIncomplete = slices.some((s) => s.status !== "complete"); if (completedSliceIds.length === 0 || !hasIncomplete) return null; const lastCompleted = completedSliceIds[completedSliceIds.length - 1]; - const assessmentFile = resolveSliceFile( - base, - mid, - lastCompleted, - "ASSESS", - ); + // Try both "ASSESSMENT" (canonical, e.g. S03-ASSESSMENT.md) and + // the legacy "ASSESS" suffix. Without the ASSESSMENT branch the + // dispatcher re-dispatched reassess-roadmap indefinitely because + // resolveFile's pattern (`${idPrefix}-.*-${suffix}.md`) requires + // at least one char before `-ASSESS`, so `S03-ASSESSMENT.md` + // never matched suffix "ASSESS". Witnessed 2026-05-17 on + // M010/S03 — 70+ degenerate iterations. + const assessmentFile = + resolveSliceFile(base, mid, lastCompleted, "ASSESSMENT") ?? + resolveSliceFile(base, mid, lastCompleted, "ASSESS"); if (assessmentFile && existsSync(assessmentFile)) return null; return { sliceId: lastCompleted }; }