A "fail" verdict from runFeatureValidation is only trustworthy once the
linked task's code has actually landed (column done/archived). When the
task is still mid-pipeline — an in-review PR, an external merge train, a
deferred base sync — the validator judged a checkout that predates the
merge and reports the work as missing, minting a duplicate Fix feature
(and board task) for code that is about to land.
Route that case to handleValidationInconclusive (R21: no Fix feature,
run completed as blocked, distinguishable verification_inconclusive
event) so a later validation judges the merged code instead.
The guard fails open: a missing/unlinked task, an unreadable task store,
or an unknown column all keep the existing handleValidationFail path —
it can only ever defer a fail on affirmative evidence of an unmerged
column, never suppress one on missing data. The vanilla done-triggered
flow (scheduler fires processTaskOutcome on toColumn === "done") is
unaffected; the guard matters for recovery-path validations and for
deployments whose tasks merge through external pipelines.
Incident context: a mission validator racing an external merge train
failed four features while their tasks were in-review, and the four
generated Fix tasks' file-scope leases on hot shared files serialized
the entire board.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>