Skip to content

A non-ok doctor check states its conclusion without the observation that produced it #465

Description

@MongLong0214

A non-ok doctor check states its conclusion without the observation that produced it. The exit code a probe returned, the path that was actually executed, the counts a verdict rests on — all of it is either interpolated into the detail sentence or discarded. A machine consumer gets prose; a human pasting a bug report gets whatever the sentence happened to include.

Why this exists

The defect history of this command is a history of missing evidence:

PRD §1.3 makes evidence a rule; ADR-0032 §8.3 makes it an invariant: "No claim without evidence."

Scope

Populate evidence: Record<string, string> in every check path. Keys snake_case, values strings (PRD §1.3).

  • A bounded-excerpt helper for process output: first line, hard cap 200 characters, paired <stream>_truncated: "true" | "false" key (PRD §1.3 rule 2). The excerpt stays because hook-runtime and inject-runtime diagnose from stderr first lines — ADR-0032 explicitly rejected collapsing evidence to present/empty.
  • A home-relative path helper: no evidence value carries an absolute $HOME prefix; paths render ~/... (PRD §1.3 rule 3).
  • Minimum keys per check (more are allowed; these are the floor a reviewer checks):
check minimum evidence
cli-runtime entry (the resolved artifact probed — the #40 lesson), version on ok; exit_code, stderr_first_line, stderr_truncated on fail
notes-refspec remotes; missing / forced when non-empty; per-remote fetch exit_code on the could-not-verify path
notes-push remote, local_sha; remote_sha or ls_remote_stderr_first_line
commit-msg-hook hook_path, the recorded target fields (bin, node as recorded), commitlore_bin_override when set — the #49 surface
hook-runtime exit_code, stderr_first_line, stderr_truncated on non-ok
inject-runtime executable (what was actually spawned — the #149 surface), exit_code, stderr_first_line on non-ok
inject-version executable, theirs, mine — the #382 surface
mcp-lifecycle unfinished_count, last_pid, last_at on warn
pending-backlog stranded, staged_expired, oldest on warn
git-trailers git_version, parsed on fail
history-depth shallow: "true" on warn
index-health trailers, commits, last_indexed_sha, head_sha, fts
squash-conservation candidates, checked, uncheckable, lost_count on non-skip
  • Detail strings and text output stay byte-identical: evidence is a --json surface until the text ticket adds --verbose.

Acceptance criteria

  • Suite-wide invariant, exactly as PRD §1.3 rule 1 words it: "A status with empty evidence and a non-ok value fails the test suite" — asserted over every fixture report in the suite.
  • Every process-output evidence value is a first line, ≤ 200 characters, with its paired _truncated key.
  • No evidence value contains the absolute $HOME prefix (walk all fixture reports with HOME pointed at the fixture parent).
  • The minimum-keys table above is satisfied per check per status path.
  • Evidence values are strings — numbers stringified, the record flat, no nesting.
  • Text output byte-identical; --json gains only new keys; existing doctor tests pass without edits.

Tests that must exist

case what it catches
a hook printing 10KB of stderr yields a ≤200-char excerpt with stderr_truncated "true" unbounded evidence — the exact PRD §1.3.2 warning: "the bound exists so --json output size is independent of what a broken tool prints". This is the fails-if-wrong-the-way-the-PRD-warns case
inject-runtime failure names the executable it spawned the #149 regression: evidence must be the configured command actually executed, never a reconstructed path
commit-msg-hook surfaces the recorded target and any COMMITLORE_BIN override the #49 channel going quiet again
inject-version rows carry theirs and mine the #382 skew becoming prose-only again
paths under HOME render home-relative $HOME leaking into pasted bug reports (PRD §1.3.3)
non-ok with empty evidence fails the suite (the invariant itself, exercised by a deliberately-broken test-only row) any future check path that reaches a verdict without recording an observation — ADR-0032 §8.3

Depends on

Out of scope

  • --verbose rendering (text ticket), the envelope, changing any status decision or detail string, the squash-conservation truncation counters (branches_seen/branches_checked belong to the performance ticket, PRD §10.3).

Traceability: PRD §1.3; ADR-0032 §8.3 and the rejected "present/empty" collapse.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions