Files
OpenSpec/openspec
Clay GoodandClaude Opus 5 8b99c07bd0 fix(status): name the command that resumes a change (#1786)
* fix(status): name the command that resumes a change

`openspec status` printed the artifact checklist and stopped. The command
that moves the change forward was computed already and shipped in the JSON
`nextSteps` sentence, but the text surface never rendered it, so anyone
resuming a change had to know the next command by heart.

Extract `resolveNextStep` so the command and the published sentence come
from one place, and print it as a `Next:` line — matching the idiom
`openspec new change` already uses to hand off to `openspec status`.

The completion case matters most: "All planning artifacts complete!" reads
as "you are done" even while implementation tasks remain, and it is now
followed by the `openspec instructions apply` command that resumes the work.

Closes #906

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* style(status): keep the loadStatus comment on loadStatus

The store-flag note landed between the "single definition" comment and the
declaration it describes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* test(status): cover the next-step line, and record it in the spec

The behavior change shipped without the OpenSpec change this repo requires
of user-facing work, and without coverage for the paths a reviewer would
reasonably ask about.

Adds `add-status-next-step`, whose delta modifies `Next Artifact Discovery`
in `cli-artifact-workflow` - the requirement that already says status is how
you learn what comes next. It now also says status names the command.

Coverage added:
- Unit tests for `resolveNextStep`, pinning the published `nextSteps`
  sentences verbatim. Confirmed byte-identical to main's output, so the
  split into command + sentence provably did not reword the contract.
- Custom-schema case: the line is built from the resolved artifact id, so a
  project with neither proposal/specs/design/tasks still gets a usable
  command.
- Skipped artifacts are never named - they satisfy dependents but must not
  be created.
- `--json` stays parseable and carries no `Next:` line.
- `--all` gives every change its own line, and a failed entry none.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* test(status): assert the next-step line closes the output

The spec delta says the text output ends with the `Next:` line, but the
assertions used toContain, which a later line would still satisfy. Compare
the last non-empty line instead, across all four ready/complete cases and
the skipped one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* test(status): read the closing line CRLF-safely

Split on /\r?\n/ so a CRLF stream cannot leave a carriage return attached
to the line under comparison, and route the parity check through the same
helper instead of its own scan.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* docs: move the status Next: line to the canonical CLI page

docs-lab/README.md makes docs-lab/ canonical and the old docs/ tree legacy, so
the entry now lives under 'openspec status' in docs-lab/reference/cli.md and
docs/cli.md is back to its state on main.

Both documented outputs were captured from real runs rather than written by
hand: the blocked case in a change with proposal and specs, and the complete
case with all four artifacts.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* docs(status): drop em dashes from the changeset and proposal

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-09-16 15:47:08 +00:00
..