Summary
When an item document fails to decode, pm list omits it from items[] and from count, reporting the loss only as a string in warnings[]. An agent consuming pm list --json therefore receives a well-formed, plausible, silently incomplete result set. Nothing in the shape of the response distinguishes "3 open items" from "3 open items, and 2 more I could not read".
For a tool whose premise is that project management is context management, silently narrowing an agent's view of the workspace is the most damaging possible failure mode: the agent does not know to distrust the answer.
Reproduction
Any unreadable item reproduces it. A drifted @toon-format/toon install (see #747) is one easy way:
$ pm list --json
{
"items": [ ... 2 items ... ],
"count": 2,
"total": 2,
"has_more": false,
"truncated": false,
"warnings": [
"item_list_item_read_failed:chores/pm-gantt-chart-xcqd.toon",
"item_list_item_read_failed:issues/pm-gantt-chart-76at.toon"
]
}
count, total, has_more: false and truncated: false all assert completeness. Two of the four items in the workspace are simply gone.
Why this cost real time
Diagnosing this took hours across a 20-workspace fleet, because every symptom pointed at data corruption rather than at the environment:
pm list looked successful — correct exit code, no error, a coherent item set.
pm get <id> failed with TOON item document is not valid TOON, which reads as "this document is malformed" and says nothing about the decoder.
pm validate did flag validate_storage_unreadable_items, which is good, but by then the natural conclusion was that committed items had been corrupted.
The actual cause was that @unbrained/pm-cli correctly declares "@toon-format/toon": "^2.3.1" while the resolved package on disk was 2.3.0 — a version whose decoder rejects bracketed segments inside quoted scalars. The lockfiles pinned 2.3.1; npm install reported up to date without reconciling the drift. 29 items across 13 workspaces were invisible, and every one was byte-identical to its committed version.
Requests
1. Never report a filtered result set as complete. When reads fail, either surface the loss structurally so a consumer must see it:
…or fail the command outright under a strict flag. A warnings[] string is easy for a programmatic consumer to ignore, and agents do ignore it. complete: false (or a non-zero unreadable_count) is not ignorable by an agent that checks its own result shape.
2. Name the decoder version in the decode error. TOON item document is not valid TOON attributes the fault to the document. When the installed @toon-format/toon does not satisfy pm's own declared range, say so:
TOON item document is not valid TOON
Why: the installed @toon-format/toon is 2.3.0, but this pm build requires >=2.3.1.
2.3.0 cannot decode bracketed segments inside quoted scalars.
Recovery: rm -rf node_modules/@toon-format/toon && npm install
That single line would have replaced the entire investigation.
3. Consider a startup guard. A cheap runtime check that the resolved decoder satisfies the declared range, failing loudly once at startup, converts a silent whole-workspace integrity failure into an unmissable one-line diagnosis.
Environment
@unbrained/pm-cli 2026.7.26
- resolved
@toon-format/toon 2.3.0 (declared ^2.3.1, lockfile pinned 2.3.1)
- Node 26.5.0, Linux
Related
Summary
When an item document fails to decode,
pm listomits it fromitems[]and fromcount, reporting the loss only as a string inwarnings[]. An agent consumingpm list --jsontherefore receives a well-formed, plausible, silently incomplete result set. Nothing in the shape of the response distinguishes "3 open items" from "3 open items, and 2 more I could not read".For a tool whose premise is that project management is context management, silently narrowing an agent's view of the workspace is the most damaging possible failure mode: the agent does not know to distrust the answer.
Reproduction
Any unreadable item reproduces it. A drifted
@toon-format/tooninstall (see #747) is one easy way:count,total,has_more: falseandtruncated: falseall assert completeness. Two of the four items in the workspace are simply gone.Why this cost real time
Diagnosing this took hours across a 20-workspace fleet, because every symptom pointed at data corruption rather than at the environment:
pm listlooked successful — correct exit code, no error, a coherent item set.pm get <id>failed withTOON item document is not valid TOON, which reads as "this document is malformed" and says nothing about the decoder.pm validatedid flagvalidate_storage_unreadable_items, which is good, but by then the natural conclusion was that committed items had been corrupted.The actual cause was that
@unbrained/pm-clicorrectly declares"@toon-format/toon": "^2.3.1"while the resolved package on disk was2.3.0— a version whose decoder rejects bracketed segments inside quoted scalars. The lockfiles pinned 2.3.1;npm installreportedup to datewithout reconciling the drift. 29 items across 13 workspaces were invisible, and every one was byte-identical to its committed version.Requests
1. Never report a filtered result set as complete. When reads fail, either surface the loss structurally so a consumer must see it:
{ "items": [...], "count": 2, "unreadable_count": 2, "unreadable": ["chores/pm-gantt-chart-xcqd.toon", "issues/pm-gantt-chart-76at.toon"], "complete": false }…or fail the command outright under a strict flag. A
warnings[]string is easy for a programmatic consumer to ignore, and agents do ignore it.complete: false(or a non-zerounreadable_count) is not ignorable by an agent that checks its own result shape.2. Name the decoder version in the decode error.
TOON item document is not valid TOONattributes the fault to the document. When the installed@toon-format/toondoes not satisfy pm's own declared range, say so:That single line would have replaced the entire investigation.
3. Consider a startup guard. A cheap runtime check that the resolved decoder satisfies the declared range, failing loudly once at startup, converts a silent whole-workspace integrity failure into an unmissable one-line diagnosis.
Environment
@unbrained/pm-cli2026.7.26@toon-format/toon2.3.0 (declared^2.3.1, lockfile pinned 2.3.1)Related
pm validatereportingok:true/checked_items:0for an unparseable item. Same family: an integrity gate that reads as success while excluding the thing it failed on.