fix: cap pm item reads at 64 MiB instead of Node's 1 MiB spawnSync default
Problem
readPmItems() — the documented safe read pattern every demo reuses 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
Because this path is contractually never-throw (return [] on any failure), a read failure was indistinguishable from an empty workspace — every demo would show no items and look correct. The cap fix is paired with a stderr line so the cause is visible without breaking the contract.
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-starter-y8hb — 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
Capped pm item reads at 64 MiB with a per‑call PM_JSON_MAX_BUFFER override and clearer errors so large or failing workspaces don’t look empty. Malformed overrides now fall back to the default instead of imposing tiny caps.
- Bug Fixes
- Resolve
PM_JSON_MAX_BUFFERon everyreadPmItemscall; reject invalid/non‑positive values withNumber()+isSafeInteger; overrun message names the actual byte limit and points to the env var. Matches sibling packages and resolvespm-starter-y8hb. - Keep the never‑throw
[]contract but log ENOBUFS and non‑zero exits (exit code + stderr); restored the safe‑read JSDoc in the emittedd.ts. - Added smoke tests for a forced 64‑byte cap and malformed overrides; disabled jshint on generated
dist/in Hound to avoid ES5 lint noise.
- Resolve