Follows up on jrusso1020's review in #320.
Exit code no longer gated on check health
---------------------------------------
`doctor --json` previously set exitCode=1 when any check failed. Two
problems:
- `checkVersion` returns ok:false whenever a newer npm version is
available, so any pipeline using `hyperframes doctor --json || fail`
would start failing the next time a new CLI version was published.
- Asymmetric with bare `doctor` which always exits 0.
Exit code now strictly reflects whether the command executed, not
whether the environment is healthy. Consumers who want to gate do:
hyperframes doctor --json | jq -e '.ok' > /dev/null || handle_failure
Documented that pattern in docs/packages/cli.mdx.
Schema locked with a snapshot test
----------------------------------
Extracted `buildDoctorReport()` as a pure function and added
`doctor.test.ts` covering:
- top-level key set (any accidental rename/addition fails the test)
- shape of each CheckOutcome entry
- ok flag true/false semantics
- check-order preservation
- hint field: omitted when absent, preserved when present
- redact option both on and off
Any future refactor that silently breaks the documented JSON contract
will now fail CI.
$HOME redaction for JSON mode
-----------------------------
JSON output is explicitly designed to be pasted into bug reports and
agent contexts. Added `redactHome()` so the user's home directory is
replaced with the literal `$HOME` in `detail`/`hint` when --json is
set. Human mode is unchanged (shows real paths).
Import grouping
---------------
Moved `node:os` + `_examples` imports up with the rest so `export const
examples` no longer sits between imports.
The "FFmpeg not found" hint was hardcoded to `sudo apt install ffmpeg`
for any non-macOS platform — Windows users would see an apt command that
doesn't exist on their system, and Red Hat / Arch users got the wrong
package manager too.
`getFFmpegInstallHint()` already exists in browser/ffmpeg.ts (and is
already used by render.ts) and handles darwin / linux / win32 correctly.
Use it here too.
Also rewrite checkFFprobe:
- it previously used `which ffprobe` which is not available on Windows
(cmd uses `where`), so on Windows the check always reported "Not
found" even when ffprobe was on PATH
- run `ffprobe -version` directly instead, which works cross-platform
whenever ffprobe is resolvable on PATH, and surfaces the version
string in the same style as the FFmpeg check
`doctor` is one of the first commands users and agents run when something
is off — remote bug reports (e.g. #294, #316, #317) typically include a
doctor screenshot, which is painful to parse programmatically.
Every other CLI command that reports state already supports `--json`
(info, lint, compositions, catalog, benchmark, validate, capture). This
brings `doctor` in line with that convention so:
- CI pipelines can gate on `hyperframes doctor --json` (exit 1 on
failure) without scraping terminal output
- AI agents consuming telemetry / diagnostic data get structured input
- Bug report tooling can attach machine-readable doctor output
Schema:
{
"ok": boolean,
"platform": "darwin" | "linux" | "win32",
"arch": "arm64" | "x64" | ...,
"checks": [
{ "name": "FFmpeg", "ok": true, "detail": "ffmpeg version 8.1 …" },
{ "name": "Docker", "ok": false, "detail": "Not found",
"hint": "https://docs.docker.com/get-docker/" }
],
"_meta": { "version", "latestVersion", "updateAvailable" }
}
Uses the existing `withMeta()` helper so the `_meta` envelope matches
other `--json` commands. Human output format is unchanged.