fix: cap pm item reads at 64 MiB instead of Node's 1 MiB spawnSync default
Problem
buildCsvExport() — the CSV export itself spawns the pm CLI to read items but passes no maxBuffer, so Node's 1 MiB spawnSync default applies.
Measured with this package's exact argv against a real 443-item pm workspace: 1,054,002 bytes — over the cap, failing today.
Past the cap the child is killed and the result comes back as:
status: null signal: SIGTERM error.code: ENOBUFS stderr: ""
Because stderr is empty, the failure surfaced with nothing to diagnose. And at larger sizes stdout is genuinely truncated mid-document — verified by forcing a 100 KiB cap on the same workspace:
JSON.parse -> Unterminated string in JSON at position 130829
This is the package's primary function: exporting a mature tracker is exactly when it matters.
This was a straggler: pm-changelog, pm-context, pm-brief, pm-graph and pm-linear already cap their pm reads explicitly. A fleet-wide audit this session found 8 packages that did not.
Change
- cap the pm read at 64 MiB, matching the sibling packages
- report an
ENOBUFSoverrun explicitly — naming the limit and the remedy — instead of an unexplained failure
Verification
Same argv, same real 443-item workspace:
| read buffer | result |
|---|---|
| Node default (1 MiB) | status: null, ENOBUFS, empty stderr |
| 64 MiB (this PR) | status: 0, complete payload |
Typecheck and the full test suite pass; changelog:check green.
pm items
| item | status |
|---|---|
| pm-csv-m13h — pm item reads are capped at Node's 1 MiB spawnSync default, so a mature tracker fails with no diagnosis | closed |
Companion-tracked fleet sweep; the same fix landed in pm-github (unbraind/pm-github#13), where it additionally unblocked --atomic --dry-run.
🤖 Generated with Claude Code
Summary by cubic
Cap pm item reads to 16 MiB by default (overridable via PM_LIST_MAX_BUFFER) to avoid Node’s 1 MiB spawnSync limit and stop silent truncation. The cap now resolves per call, and overruns and real pm exits report clear errors.
- Bug Fixes
- Apply
maxBufferviapmListMaxBuffer()to allpm list-allcalls (CSV export, key index, applied-by-transaction); env override is read at runtime. - On
ENOBUFS, throw a message that names the effective limit and suggests narrowing the export or raisingPM_LIST_MAX_BUFFER; nonzeropmexits now surface stderr. - Reject malformed
PM_LIST_MAX_BUFFERvalues (e.g., "64MiB"); useNumber()with a positive safe-integer check and fall back to the default.
- Apply