review-state CLI: flag parsing and update semantics defects #436
Labels
No labels
agent-ready
bug
contract
documentation
duplicate
enhancement
good first issue
help wanted
invalid
needs-human
needs-input
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
iterative-works/iw-cli#436
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Five defects in the
review-stateCLI surfaced while running the waterfall workflow for IW-423. They share a component and a root cause shape: a flag whose parsing does not match what every caller writes, with no validation to make a wrong invocation fail loudly.1.
--needs-attention falsesets the flag totrue--needs-attentionis a presence flag, not a value flag:So
./iw review-state update --needs-attention falsesetsneeds_attentiontotrueand leavesfalseas an ignored stray argument — the exact opposite of the caller's intent, silently. Clearing needs--clear-needs-attention(:223).The
wf-create-taskscommand's Step 8 script tells the caller to run--needs-attention false. Following it verbatim leaves every waterfall issue flagged as needing attention attasks_ready, polluting the dashboard's pending-act count.Fix: reject
--needs-attention <value>rather than ignoring the value.2.
--append-actiondoes not de-duplicate by idwf-create-analysisStep 9 writes--action "implement:Start Implementation:wf-implement".wf-create-tasksStep 8 then runs--append-actionwith the same action, soavailable_actionsends up holding two identicalimplemententries. Nothing validates against duplicate action ids.Fix: de-duplicate on append by
id.3.
--checkpointtakesphase:sha, notphase:context_sha=shaReviewStateCliParser.parseCheckpoint(core/model/ReviewStateCliParser.scala:75-79) splits on the first:and returns(phase, sha).ReviewStateUpdater(:198,:207) then writes thecontext_shakey itself:The
wf-implementStep 6a script says--checkpoint "${PHASE_NUM}:context_sha=${CONTEXT_SHA}". Following it verbatim writes"context_sha": "context_sha=ed7d788…".ReviewStateValidatoronly checks thatcontext_shais present and is a string, so it passes, and the resume path compares a non-SHA against git history.Fix: validate the checkpoint value as a SHA in
parseCheckpoint.4.
--checkpointreplaces the whole checkpoint map, wiping earlier phases--checkpointdefaults to replace mode.ReviewStateUpdater(core/model/ReviewStateUpdater.scala:194-201) builds a freshujson.Objand assigns it overphase_checkpoints:So
--checkpoint "2:${SHA}"dropped phase 1's checkpoint. Nothing in the state file records what was lost. Passing both--checkpointand--append-checkpointin one call does not help either: replace mode wins and the appended value is dropped silently.Fix: make append the default for
--checkpoint. A checkpoint map is an accumulating record of phases; no caller wants phase N's checkpoint to delete phase N-1's. Replace would then need an explicit--clear-checkpoints.5.
review-state updatedoes not refreshgit_shaReviewStateUpdaterdocumentsgit_shaas "preserved unless explicitly provided in update" (core/model/ReviewStateUpdater.scala:78,130). Only thewritepath fills it fromenv.git.getHeadSha(core/commands/ReviewState.scala:135).Every
wf-*command block claims the CLI "auto-populates required fields (version,issue_id,git_sha,last_updated)". That is true ofwriteand false ofupdate. For IW-423git_shastayed at the analysis commit through two later commits, and confirmed again on the Phase 2 transition. Step 1 ofwf-implementuses the state SHA as a resume sanity check ("state SHA is HEAD or ancestor"), which a stale value passes vacuously.Fix: refresh
git_shaonupdatefrom HEAD. It is a record of the state, not user input.Recorded during IW-423; see
project-management/issues/IW-423/LESSONS.mdentries 1, 2, 4, 5, 13, 14.The paired command-text corrections in dev-docs are filed separately as a kanon note.
Defects 3 and 4 hit again in IW-437, at all three phases, from the same unchanged caller snippet. Evidence that the loss in defect 4 is real rather than theoretical:
{1: ...}at phase 1, then{2: ...}alone at phase 2 (f294ed1), then{3: ...}alone at phase 3 (349a04a). Two checkpoints were destroyed before anyone looked.0f64de40) and phase 2 (b66e166e) were read back out of the card's own history, verified to resolve to their "Phase N: context ready" commits, and re-appended alongside phase 3 (ceb86105).This supports defect 4's proposed fix (append as the default, explicit
--clear-checkpointsfor replace) over any caller-side-only correction: the caller snippet was already recorded as wrong after IW-423 (dev-docs note #183) and was still producing corrupt cards three phases later in IW-437.Two duplicates filed on this ground have been closed in favour of this issue: #464 (from IW-437) and #446 (from MEDECA-430, which proposed the inverse fix — stripping a
context_sha=prefix — on a mistaken reading of the intended syntax).Caller-side fix tracked at dev-docs#187.