Audit ref: AUDIT-2026-08.md item B44 · Priority P3 (score 39) · Evidence: cli.ts:803-804
Context
doctor is the command a user runs when something is wrong. It currently makes that harder in two ways (cli.ts:803-804):
- Streams are backwards. The JSON goes to stdout and the human-readable summary goes to stderr. So
structured-edit doctor shows JSON to a human, and structured-edit doctor 2>/dev/null hides the readable part. Both audiences get the wrong thing.
- It always exits 0, even when it reports an unhealthy installation. Nothing can gate on it — not CI, not the installer, not a setup script.
Required behavior
- Adopt the global
--format json|text rule: text to stdout on a TTY, JSON to stdout when piped. Diagnostics only on stderr. Never both payloads at once.
- Exit non-zero when unhealthy.
0 healthy, 1 warnings only, 2 one or more failures. Document it — this is what makes doctor usable as a CI gate and as the installer's final verification step.
- Make the output actionable: every failed check names the specific fix command, not just "missing". Since
doctor is where the audit's silent-AST-fallback problem becomes visible, it must explicitly report whether the tree-sitter bindings actually loaded, per language — getParser() swallows init errors and returns null, so a broken native build currently manifests only as mysteriously-worse edits.
- Report versions of everything relevant: HashPilot, Bun, each parser, LSP servers if present, config file locations actually in use.
Acceptance criteria
Context
doctoris the command a user runs when something is wrong. It currently makes that harder in two ways (cli.ts:803-804):structured-edit doctorshows JSON to a human, andstructured-edit doctor 2>/dev/nullhides the readable part. Both audiences get the wrong thing.Required behavior
--format json|textrule: text to stdout on a TTY, JSON to stdout when piped. Diagnostics only on stderr. Never both payloads at once.0healthy,1warnings only,2one or more failures. Document it — this is what makesdoctorusable as a CI gate and as the installer's final verification step.doctoris where the audit's silent-AST-fallback problem becomes visible, it must explicitly report whether the tree-sitter bindings actually loaded, per language —getParser()swallows init errors and returnsnull, so a broken native build currently manifests only as mysteriously-worse edits.Acceptance criteria
install.shrunsdoctorat the end and fails the install on exit 2.