fix(gsd): force re-validation when verdict is needs-remediation
When validation returns needs-remediation, remediation slices are added and executed. But the state machine treated any terminal verdict as ready for completing-milestone, while dispatch correctly blocked completion for needs-remediation — creating a permanent deadlock. Now all three derivation paths (deriveStateFromDb, _deriveStateImpl registry loop, and _deriveStateImpl completion check) treat needs-remediation as requiring re-validation, routing back to validating-milestone instead of completing-milestone. Closes #3596 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
b4c6229360
commit
3e5bce5dbd
1 changed files with 16 additions and 7 deletions
|
|
@ -636,12 +636,15 @@ export async function deriveStateFromDb(basePath: string): Promise<GSDState> {
|
|||
const validationFile = resolveMilestoneFile(basePath, activeMilestone.id, "VALIDATION");
|
||||
const validationContent = validationFile ? await loadFile(validationFile) : null;
|
||||
const validationTerminal = validationContent ? isValidationTerminal(validationContent) : false;
|
||||
const verdict = validationContent ? extractVerdict(validationContent) : undefined;
|
||||
const sliceProgress = {
|
||||
done: activeMilestoneSlices.length,
|
||||
total: activeMilestoneSlices.length,
|
||||
};
|
||||
|
||||
if (!validationTerminal) {
|
||||
// Force re-validation when verdict is needs-remediation — remediation slices
|
||||
// may have completed since the stale validation was written (#3596).
|
||||
if (!validationTerminal || verdict === 'needs-remediation') {
|
||||
return {
|
||||
activeMilestone, activeSlice: null, activeTask: null,
|
||||
phase: 'validating-milestone',
|
||||
|
|
@ -1099,22 +1102,25 @@ export async function _deriveStateImpl(basePath: string): Promise<GSDState> {
|
|||
const validationFile = resolveMilestoneFile(basePath, mid, "VALIDATION");
|
||||
const validationContent = validationFile ? await cachedLoadFile(validationFile) : null;
|
||||
const validationTerminal = validationContent ? isValidationTerminal(validationContent) : false;
|
||||
const verdict = validationContent ? extractVerdict(validationContent) : undefined;
|
||||
// needs-remediation is terminal but requires re-validation (#3596)
|
||||
const needsRevalidation = !validationTerminal || verdict === 'needs-remediation';
|
||||
|
||||
if (summaryFile) {
|
||||
// Summary exists → milestone is complete regardless of validation state.
|
||||
// The summary is the terminal artifact (#864).
|
||||
registry.push({ id: mid, title, status: 'complete' });
|
||||
} else if (!validationTerminal && !activeMilestoneFound) {
|
||||
// No summary and no terminal validation → validating-milestone
|
||||
} else if (needsRevalidation && !activeMilestoneFound) {
|
||||
// No summary and needs (re-)validation → validating-milestone
|
||||
activeMilestone = { id: mid, title };
|
||||
activeRoadmap = roadmap;
|
||||
activeMilestoneFound = true;
|
||||
registry.push({ id: mid, title, status: 'active' });
|
||||
} else if (!validationTerminal && activeMilestoneFound) {
|
||||
// No summary and no terminal validation, but another milestone is already active
|
||||
} else if (needsRevalidation && activeMilestoneFound) {
|
||||
// Needs (re-)validation, but another milestone is already active
|
||||
registry.push({ id: mid, title, status: 'pending' });
|
||||
} else if (!activeMilestoneFound) {
|
||||
// Terminal validation but no summary → completing-milestone
|
||||
// Terminal validation (pass/needs-attention) but no summary → completing-milestone
|
||||
activeMilestone = { id: mid, title };
|
||||
activeRoadmap = roadmap;
|
||||
activeMilestoneFound = true;
|
||||
|
|
@ -1299,12 +1305,15 @@ export async function _deriveStateImpl(basePath: string): Promise<GSDState> {
|
|||
const validationFile = resolveMilestoneFile(basePath, activeMilestone.id, "VALIDATION");
|
||||
const validationContent = validationFile ? await cachedLoadFile(validationFile) : null;
|
||||
const validationTerminal = validationContent ? isValidationTerminal(validationContent) : false;
|
||||
const verdict = validationContent ? extractVerdict(validationContent) : undefined;
|
||||
const sliceProgress = {
|
||||
done: activeRoadmap.slices.length,
|
||||
total: activeRoadmap.slices.length,
|
||||
};
|
||||
|
||||
if (!validationTerminal) {
|
||||
// Force re-validation when verdict is needs-remediation — remediation slices
|
||||
// may have completed since the stale validation was written (#3596).
|
||||
if (!validationTerminal || verdict === 'needs-remediation') {
|
||||
return {
|
||||
activeMilestone,
|
||||
activeSlice: null,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue