Reproduced in this repository, just now
$ openspec validate --archived
✗ change/2026-08-25-conductor-tells-the-truth
✗ 1 incomplete task (114/115 completed)
pm reports the same file as 114/114 · 1 lifecycle, outstandingWork: 0, and the archive gate passes. The epic is archived · delivered.
Both are right about the checkboxes and disagree about what they mean.
The collision
pm ships a <!-- pm:lifecycle --> marker for a task that is bookkeeping about a change's own lifecycle — above all the task that archives the change itself, which is unticked at archive time by construction: it cannot be ticked before the thing that ticks it. outstandingWork()'s own docstring names this exactly — "a guard counting raw checkboxes would refuse every correctly finished change."
openspec validate --archivedis that guard. It counts raw checkboxes and has no knowledge of the marker. That file carries 8 lifecycle-marked tasks.
Why this is a live hazard rather than a curiosity
openspec validate --archived's own help text describes it as "for pre-commit linting." So any pm-managed repository that follows that advice gets a pre-commit hook which fails on every correctly-archived change — permanently, with no action that clears it, because ticking the archive task would be a false record and removing the marker would break pm's own gate.
That is not hypothetical: this repository would hit it today if it wired that command in, and the archive workflow pm documents produces the offending shape every time.
Found while
Investigating #123 (adopt the OpenSpec CLI surface for progress). That investigation concluded the CLI should not be adopted as a progress source, and this is the sharpest single reason: the two tools compute different quantities from the same file, and pm's is the one that makes its archive gate correct.
Options, none obviously right
- Upstream: OpenSpec could ignore a task line carrying an HTML comment marker, or expose an exclusion mechanism. That is the clean fix and it is not ours to make.
- pm side: document the incompatibility so nobody wires that command into a pm-managed repo expecting it to pass. Cheap, honest, and does not pretend to fix someone else's lint.
- Neither: accept that the two disagree and say so where the marker is documented.
Recommend the pm-side documentation now and an upstream report separately — this issue exists so the collision is on the record either way, since the failure mode is confusing precisely when it appears (a green repo suddenly failing a lint on a change that shipped correctly).
Note on the counts
The count arrives only as prose inside a human-readable message ("1 incomplete task (114/115 completed)"), so it cannot be consumed programmatically without parsing English — which is why #123 also could not use it as a progress source even setting the semantics aside.
Reproduced in this repository, just now
pm reports the same file as
114/114 · 1 lifecycle,outstandingWork: 0, and the archive gate passes. The epic isarchived · delivered.Both are right about the checkboxes and disagree about what they mean.
The collision
pm ships a
<!-- pm:lifecycle -->marker for a task that is bookkeeping about a change's own lifecycle — above all the task that archives the change itself, which is unticked at archive time by construction: it cannot be ticked before the thing that ticks it.outstandingWork()'s own docstring names this exactly — "a guard counting raw checkboxes would refuse every correctly finished change."openspec validate --archivedis that guard. It counts raw checkboxes and has no knowledge of the marker. That file carries 8 lifecycle-marked tasks.Why this is a live hazard rather than a curiosity
openspec validate --archived's own help text describes it as "for pre-commit linting." So any pm-managed repository that follows that advice gets a pre-commit hook which fails on every correctly-archived change — permanently, with no action that clears it, because ticking the archive task would be a false record and removing the marker would break pm's own gate.That is not hypothetical: this repository would hit it today if it wired that command in, and the archive workflow pm documents produces the offending shape every time.
Found while
Investigating #123 (adopt the OpenSpec CLI surface for progress). That investigation concluded the CLI should not be adopted as a progress source, and this is the sharpest single reason: the two tools compute different quantities from the same file, and pm's is the one that makes its archive gate correct.
Options, none obviously right
Recommend the pm-side documentation now and an upstream report separately — this issue exists so the collision is on the record either way, since the failure mode is confusing precisely when it appears (a green repo suddenly failing a lint on a change that shipped correctly).
Note on the counts
The count arrives only as prose inside a human-readable message (
"1 incomplete task (114/115 completed)"), so it cannot be consumed programmatically without parsing English — which is why #123 also could not use it as a progress source even setting the semantics aside.