Skip to content

fix: close a Step only when it says - Status: done - #102

Merged
hkwuks merged 3 commits into
mainfrom
fix/close-step-status
Oct 27, 2026
Merged

hkwuks merged 3 commits into
mainfrom
fix/close-step-status

Conversation

@hkwuks

@hkwuks hkwuks commented Oct 27, 2026 •

Copy link
Copy Markdown
Owner

Summary

A Step counts as closed only when it says - Status: done. Every other value — completed, a misspelling, an empty value, a missing line — now counts as unfinished, because the check was a blacklist and everything it did not recognize read as finished.

Measured 2026-10-27 by driving hooks/completion-gate directly: completed, complted, skipped, wip, DONE, an empty value and a Step with no - Status: line each returned exit 0 and "finished". hooks/task progress has only ever accepted pending|in_progress|done|blocked, so none of those spellings could have been written by the tool — they are hand edits made precisely because the reader and the writer disagreed. This makes them agree.

The block is located by its ### Step <number> heading anywhere in the Plan, which is how task progress finds the block it edits. Scanning only ## Steps would have given the reader a different set of Steps than the writer changes.

TaskFlow traceability

  • Task: TaskFlowDocs/achieved/2026-10-27-close-step-status/
  • Scope: hooks/completion-gate (the Step condition and how a block is located), hooks/smoke-test (19 new assertions), skills/taskflow/SKILL.md, skills/taskflow/references/runtime.md, CHANGELOG.md. hooks/task progress is deliberately unchanged — it already accepts only done.
  • Base branch: main
  • Target repository: https://github.com/hkwuks/TaskFlow (origin; no fork remotes configured)

Verification

  • The Hooks workflow reports pass for this branch — run 40519266846 at f03b806, success, all seven jobs: changes, evals, release, todo-merge-audit, and smoke on ubuntu-latest (20s), windows-latest (39s), macos-latest (1m7s)
  • git diff --check
  • python3 <skill-creator>/scripts/quick_validate.py skills/taskflow — Skill is valid!
  • Results recorded in the TaskFlow Plan — ## Verification / Review in the archived Plan carries the CI run and the local runs

Local, before CI existed for this branch: bash hooks/smoke-test — ALL SMOKE PASSED. Five mutations were run against the new assertions, each reddening a named assertion:

Mutation Result
restore the old blacklist line FAIL completion-gate clean: rc 1 != 0
scope the reader to ## Steps FAIL completion-gate unfinished: rc 0 != 1, and the new fixture catches it independently
drop the END flush FAIL completion-gate unfinished: rc 0 != 1
tighten done to an exact line red only after two fixtures were added — see the limitations below
accept (done|completed) FAIL completion-gate closed-completed: rc 0 != 1

Review boundaries

  • No secrets or opaque remote payloads included
  • No unrelated task or user files changed — the TaskFlowDocs/todo.md diff is three entries recorded earlier the same day, from the same requests that produced this task
  • Remote/base assumptions are stated above
  • Known limitations and follow-ups are documented — see below

Known limitations

  • A Plan with no ### Step block at all is not refused. That is "must a Plan have Steps", a separate rule with its own arguments, and it is not smuggled in here. It is pinned by an assertion (no-step-blocks) so it stays a decision rather than an oversight.
  • Five archived Plans read as unfinished under the new rule and are not rewritten. achieved/ is read-only in place, so no task is affected. They are 2026-09-07-repository-standards-and-doc-root, 2026-10-11-gate-host-coverage, 2026-09-08-token-efficiency, 2026-09-14-personal-docs-git-boundary, and 2026-10-22-taskflow-drift-guard. Run over all 91 archived Plans, only two change verdict — the other three were already refused on main for unrelated reasons.
  • ### Step <number> reused as an ordinary subheading is now read as a Step. 2026-10-22-taskflow-drift-guard does exactly that under ## Verification / Review. This is not a new split: task progress already treats that block as a Step and edits it. Forbidding the reuse would be a separate rule.
  • The first version of the assertions did not pin the trailing-whitespace tolerance — an exact-line match passed the whole suite. Two fixtures generated with printf (a CRLF line ending, and trailing spaces) closed the gap. The mutation found the hole in the assertions, not in the code.

The gate read the field as a blacklist: `pending`, `in_progress` and
`blocked` were named, and everything else counted as finished. So
`completed` archived an unfinished Plan, and so did a misspelling, an empty
value, and a Step with no Status line at all. Measured 2026-10-27 by driving
the gate directly: `completed`, `complted`, `skipped`, `wip`, `DONE`, an
empty value and a missing line each returned exit 0.

`hooks/task progress` has only ever accepted `pending|in_progress|done|
blocked`, so none of those spellings could have been written by the tool.
They are hand edits made because the two sides disagreed, and reading
anything unknown as closed is that disagreement, not a fix for it. Closed is
now a whitelist of the one word the writer accepts.

The block is located by its `### Step <number>` heading anywhere in the
Plan, which is how `task progress` finds the block it edits; scanning only
`## Steps` would give the reader a different set of Steps than the writer
changes. Knowingly still open and pinned by an assertion: a Plan with no
`### Step` at all is not refused, because "must a Plan have Steps" is a
separate rule.

Five archived Plans read as unfinished under the new rule and are not
rewritten -- `achieved/` is read-only in place, and editing history to pass a
check that no longer applies to it would make the record untrue. Run over all
91, only two change verdict; the other three were already refused on main for
unrelated reasons.

smoke grew by 19 completion-gate assertions. Five mutations were run against
them, each reddening a named assertion; the fourth showed the first version
of the assertions did not pin the trailing-whitespace tolerance, so two
fixtures were generated with printf to cover `\r` and trailing spaces.
@hkwuks
hkwuks marked this pull request as ready for review October 27, 2026 14:28
@hkwuks
hkwuks merged commit 7739e56 into main Oct 27, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant