Quest CLI 0.9.0
Ships the 0.8.0 section below along with everything here: 0.8.0 was frozen and
tagged but never published, so its content reaches consumers for the first
time under this number.
Why the published number skips 0.8.0. 0.8.0 was frozen, tagged at
9d91fc35 and never published; 15 further commits then landed on dev,
including the Added entry below and four fixes. Re-pointing the tag was
refused rather than weighed: quest-web runs a live link gate against this
repository's tags, and opum-marketplace re-resolves tag to commit to tree
against a recorded baseline, so a moved tag falsifies every record citing it.
The precedent for a tagged-but-unpublished version is 0.6.1 to 0.6.2 -- ship
the content under the next unclaimed number. This is breaking-plus-feature
relative to published 0.7.1, so the next unclaimed number is a minor one.
This section exists because QCLI-286 came true. That task -- open, and
filed as a warning -- predicted that a rolled-forward version section can
silently swallow later fixes. It did: five consumer-observable changes sat on
dev with an empty Unreleased heading above a frozen ## 0.8.0, and
nothing caught it. It was found by walking git log v0.8.0..dev during
release preparation, which is exactly the manual step QCLI-286 asks to be
replaced by a check.
Added
unresolvedAtCompletionis persisted on the task record and queryable
across completed tasks (QCLI-336). QCLI-252 made it a response-only
signal, so the fact that a task closed with unchecked acceptance criteria
survived only in the output of the command that closed it.task complete
now computes it in the domain and writes it into the record, the zod schema
validates it, andtask view/task list --jsonsurface it.TaskInput
excludes it from creation: it is a fact a completion establishes, never one
a caller asserts.
Fixed
-
overviewcounted only.quest/tasks/, so completing a task removed it
from the totals instead of moving it (QCLI-339). It now counts every
retention location, and carries an additivebyLocationnaming how the
total divides, so a total that looks wrong can be read rather than guessed
at. -
overviewmilestone counts silently excluded archived milestones
(QCLI-340), the same unlisted-population shape as the entry above. Archived
is now reported alongside open and closed. QCLI-140 is preserved rather than
reopened: a retired milestone still counts as neither open nor closed work,
but the population it belongs to is now visible in the output instead of
only in a code comment. -
The
overviewguide documented an envelope the CLI does not emit
(QCLI-342). It described{schemaVersion, kind, data, principal}, omitting
contractVersion-- the key at index 1 -- and did not say that the record
lives underdata. An agent following it and projecting top-level fields
got all-null with exit 0 and empty stderr. The guide now names the envelope
exactly as emitted, separates success from error, states the additive-key
rule, and is pinned by a test that compares it against real CLI output
rather than against a copy of the prose. -
task create --id <taken>reported a write conflict and told the caller
to retry, against a condition no retry can resolve (QCLI-346). The id was
held by an existing record -- in the reported case an ARCHIVED one, which
task listdoes not show and which leftdoctorreporting healthy, so
every signal a caller could reach said the workspace was fine. It is now
validationon exit 6, names the id, and names the path holding it.task_already_existscovers two cases with opposite remedies and both were
mapped to the retryable one. An auto-allocated id losing a race to a
concurrent writer is a genuine conflict and retrying recomputes a fresh id;
an id supplied with--idis fixed, so the same retry loops forever. Only
the explicit case changed -- the auto-allocated path keepsconflictand
its retry hint. Reported by opum-cli-e2e, who followed the old hint three
times before finding the cause by listing.quest/archive/on a hunch. -
task editrejected--implementation-notes, the nametask create
uses for the same field (QCLI-344). It is now accepted as an alias of
--notes. Passing both is a usage error rather than a silent preference for
one, and a rejected flag now states that the rest of the command was not
applied -- previously a caller could not tell from the message whether a
multi-flag edit had partially landed.