fix(gsd): tighten verifyExpectedArtifact to prevent rogue-write false positives
Three fixes to fail-closed when gsd_complete_task didn't actually run: 1. Legacy branch: require checked checkbox (- [x] **T01:) instead of accepting heading-style matches that only prove the task was planned 2. No plan file: return false instead of falling through 3. DB available but task row missing: return false instead of treating as verified — if the DB is up and the task isn't there, the completion tool never ran Closes #3607 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
b4c6229360
commit
8f2e120a29
1 changed files with 10 additions and 8 deletions
|
|
@ -286,7 +286,7 @@ export function verifyExpectedArtifact(
|
|||
if (!hasCheckboxTask && !hasHeadingTask) return false;
|
||||
}
|
||||
|
||||
// execute-task: DB status is authoritative. Fall back to heading-style plan
|
||||
// execute-task: DB status is authoritative. Fall back to checked-checkbox
|
||||
// detection when the DB is unavailable (unmigrated projects).
|
||||
if (unitType === "execute-task") {
|
||||
const { milestone: mid, slice: sid, task: tid } = parseUnitId(unitId);
|
||||
|
|
@ -297,20 +297,22 @@ export function verifyExpectedArtifact(
|
|||
if (dbTask.status !== "complete" && dbTask.status !== "done") return false;
|
||||
} else if (!isDbAvailable()) {
|
||||
// LEGACY: Pre-migration fallback for projects without DB.
|
||||
// Fall back to plan heading check (format detection, not reconciliation).
|
||||
// Heading-style entries (### T01 --) count as verified because the
|
||||
// summary file existence (checked above) is the real signal.
|
||||
// Require a CHECKED checkbox — a bare heading or unchecked checkbox
|
||||
// does not prove gsd_complete_task ran. Summary file on disk alone
|
||||
// is not sufficient evidence (could be a rogue write) (#3607).
|
||||
const planAbs = resolveSliceFile(base, mid, sid, "PLAN");
|
||||
if (planAbs && existsSync(planAbs)) {
|
||||
const planContent = readFileSync(planAbs, "utf-8");
|
||||
const escapedTid = tid.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
||||
const hdRe = new RegExp(`^#{2,4}\\s+${escapedTid}\\s*(?:--|—|:)`, "m");
|
||||
const cbRe = new RegExp(`^- \\[[xX]\\] \\*\\*${escapedTid}:`, "m");
|
||||
if (!hdRe.test(planContent) && !cbRe.test(planContent)) return false;
|
||||
if (!cbRe.test(planContent)) return false;
|
||||
} else {
|
||||
return false; // no plan file → cannot verify
|
||||
}
|
||||
} else {
|
||||
// DB available but task row not found — completion tool never ran (#3607)
|
||||
return false;
|
||||
}
|
||||
// else: DB available but task not found — summary file exists (checked above),
|
||||
// so treat as verified (task may not be imported yet)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue