Skip to content

Unrecognised checkbox markers are dropped from task progress: change reports "✓ Complete" with unfinished work #1761

Description

@damiankamela

What happens

A checkbox marker the parser does not recognise is dropped from progress entirely — it counts toward neither the numerator nor the denominator. A change whose remaining work is written with such a marker therefore reports ✓ Complete, and openspec archive raises no incomplete-task warning for it.

This is the same failure mode as #1485 (indented sub-tasks invisible to progress), reached through a different door: there the bullet was unmatched because of its indentation, here because of the character inside the brackets.

Reproduce (parser as of main, verified against src/utils/task-progress.ts)

openspec/changes/my-change/tasks.md:

## 1. Implementation
- [x] 1.1 Done
- [~] 1.2 Deliberately deferred, not done
- [~] 1.3 Also deferred, not done
$ openspec list
Changes:
  my-change     ✓ Complete    just now

Expected: something that does not read as finished — 1/3, or 1/1 (2 unrecognised), or a warning naming the dropped lines.

Observed in the wild on a real change with 42 [x] · 17 [~] · 0 [ ]: reported ✓ Complete, while seventeen items were open, one of them a genuine missing test. The same change reported 22/48 before the deferred items were marked — i.e. the seventeen lines left the denominator when their marker changed, rather than staying counted as not-done.

Cause

src/utils/task-progress.ts:

const TASK_LINE_PATTERN = /^\s*[-*]\s*\[([\sxX])\]\s*(.*)/;

The character class accepts only whitespace, x and X, so - [~] … does not match at all. [X]-vs-[x] and indentation are handled; an unknown marker is not.

Why this seems worth a fix rather than a docs note

The pattern's own docblock already argues the principle:

any character class tightened here … drops lines that used to count, and a task this parser drops is a task openspec archive stops warning about.

An unrecognised marker is exactly such a dropped line — it just arrives from the other direction. The current behaviour is the silent failure the comment warns about: [x] overstates only if someone ticks it, whereas an unknown marker overstates by default, with no one having claimed anything is done.

Two shapes would both fix it, and either is fine from our side:

  1. Fail-safe parse — widen the class to any single non-] character and treat only x/X as done (/^\s*[-*]\s*\[([^\]])\]\s*(.*)/). Unknown markers then count as not-done, which is the conservative reading and needs no new concept.
  2. Report them — keep the strict class but surface unmatched checkbox-like lines, so they cannot vanish quietly (openspec list suffix, or an archive warning).

Context on the marker

[~] is not an OpenSpec concept — it is a downstream convention in our repo for deliberately deferred, with a stated reason, enforced by our own CI. We are not asking OpenSpec to adopt it. The report is only that an unknown marker currently disappears instead of counting as not-done; whatever character a project happens to use, the safe default seems to be "not done" rather than "not there".

Related: #1485 (same symptom, indentation), #1362 (proposal for human-only tasks — a marker with similar needs).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions