v0.27.1
Planner dropped-step diagnostics: fix five defects in the v0.27.0 note-step guard.
-
TASK-MODE COVERAGE HOLE: v0.27.0 replaced the note-step guard with
hasTargetCoverageGap, which derives fromenhancedEditableTargetsand is therefore ALWAYS false in task mode. A task-mode plan shipped silently minus every step that was dropped, with no indication anything was discarded. The guard is now one pure exported decision (evaluatePlanGuard) that computestaskModeandhasTargetCoverageGapitself and applies a MODE GATE internally: story mode is governed by coverage, task mode by dropped work. Both guard sites are pure delegations. -
DROPPED-STEP SET: new exported
computeDroppedSteps— an identity-keyed set difference ({raw steps the LLM authored as executable} MINUS {classified.executable}). It never gates onrejectionReasons, which is a SUPERSET of the drops (the advisory "missing paired test/doc" loop pushes descriptors for steps that were KEPT, into the same array object, mutating it in place). Identity keying is required: a label-keyed difference computes {P} \ {P} = ∅ when a kept step and a dropped step share a path, losing the drop entirely. -
UNNAMEABLE REJECTIONS: the "No executable actions generated" description rendered rejections via
r.path, so a pathless step became the literal string "null: ". It now renders byr.label, which always falls back path → title → . -
SILENCED DIAGNOSTIC: steps hard-rejected as
_invalidvanished from the retry prompt, so the planner asked the LLM to fix something it never named. Dropped steps are now named — with action, path, title and reason — in both the retry guidance and therefinement_requiredpayload. -
DEBT: the exhausted-return payload's
noteStepsis nownoteLabels(the apologetic comment and the contorted inline expression are gone), and the source-text grep in planner-note-step-degeneracy.test.mjs that pinned that expression in place is de-mirrored into behavioral assertions against the real exported payload builder.
LLM-authored note steps are never treated as lost work — commentary must not cost a build.