From e1a3c9235e642ffb422b2fc692f43ef7ae3fd429 Mon Sep 17 00:00:00 2001 From: MongLong0214 Date: Sat, 8 Aug 2026 15:26:46 +0900 Subject: [PATCH] Make a doctor row carry the observation its verdict rests on The defect history of this command is a history of values held and not recorded. #49 had the redirected hook target in hand and printed it into prose. #128 and #149 failed a working hook by probing a synthesized path, which a row naming what was actually executed would have exposed on first read. #382 printed the stale pin inside its own ok line. #63 had the fetch exit code. #335 and #458 were verdicts built on counting a different convention's vocabulary. Every row now carries an evidence map beside its sentence: what was executed, what it returned, and the counts a conclusion rests on. A non-ok row must carry at least one key, so a claim with nothing behind it does not typecheck as a complete row. Process output is kept as a bounded excerpt rather than collapsed to present-or-empty, because hook-runtime and inject-runtime diagnose from stderr first lines -- the reference implementation sanitises there and this one reads there. Paths render home-relative so a pasted bug report does not carry someone's directory layout. The text report is byte-identical. The pinned snapshot is what says so. Limit: evidence answers what was observed, not whether the observation was the right one to make -- #335's wrong count would now be visible in a field rather than prevented Ruled-out: collapsing stdout and stderr to present or empty, as the reference does | it sanitises against paths and tokens it cannot inspect, while these checks diagnose from the first line and would lose the diagnosis Ruled-out: leaving evidence optional on non-ok rows | a conclusion without its observation is the shape every defect above shares, and optional means absent in the row nobody looked at Warn: the 200-character cap is a judgement with no measurement behind it, and a diagnostic whose useful part sits past it will be silently cut with only the paired truncated flag to say so Blast: local Undo: easy Certainty: firm Verified: thirteen of thirteen rows carry evidence with zero empty maps, no value contains an absolute home path, the excerpt cap and its paired truncated flag hold in both directions, and the text and check-order snapshots are unchanged across the change Provenance: authored Record-Id: r-evidence465 --- dist/commands/doctor.d.ts | 5 +- dist/commands/doctor.js | 414 +++++++++++++++--- dist/commands/doctor.js.map | 2 +- dist/commitlore.mjs | 787 ++++++++++++++++++++++++++++++++--- src/commands/doctor.ts | 777 +++++++++++++++++++++++++++++++--- test/doctor-snapshot.test.ts | 178 +++++++- 6 files changed, 1977 insertions(+), 186 deletions(-) diff --git a/dist/commands/doctor.d.ts b/dist/commands/doctor.d.ts index ba2a351..5d9fc5c 100644 --- a/dist/commands/doctor.d.ts +++ b/dist/commands/doctor.d.ts @@ -67,9 +67,8 @@ export interface DoctorCheck { /** Derived from `status`; never passed in, never read by the exit code. */ severity: Severity; /** - * The observation behind the conclusion. Populated per check by a later - * ticket; `{}` until then, so an absent field never has to be told apart - * from an empty one. + * The observation behind the conclusion. A row without one cannot explain + * why its status is trustworthy, so construction rejects empty evidence. */ evidence: Record; /** No shipping check is optional at introduction (PRD §1.4). */ diff --git a/dist/commands/doctor.js b/dist/commands/doctor.js index 7b90af0..0cb191c 100644 --- a/dist/commands/doctor.js +++ b/dist/commands/doctor.js @@ -53,6 +53,34 @@ const EXACT_NOTES_REFSPEC_PATTERN = `^\\${EXACT_NOTES_REFSPEC}$`; */ const escapeConfigValuePattern = (value) => value.replace(/[\\.*+?[\]^$(){}|]/g, (character) => `\\${character}`); const gitOptions = (opts) => (opts.cwd === undefined ? {} : { cwd: opts.cwd }); +/** The bound keeps a broken child process from making a JSON report unbounded. */ +const boundedExcerpt = (output) => { + const [firstLine = ''] = (output ?? '').split(/\r?\n/, 1); + return { + firstLine: firstLine.slice(0, 200), + truncated: firstLine.length > 200 ? 'true' : 'false', + }; +}; +const streamEvidence = (stream, output) => { + const excerpt = boundedExcerpt(output); + return { + [`${stream}_first_line`]: excerpt.firstLine, + [`${stream}_truncated`]: excerpt.truncated, + }; +}; +/** Reports keep paths useful in bug reports without carrying a user's home directory. */ +const homeRelativePath = (value) => { + const home = process.env['HOME']; + if (home === undefined || home === '') + return value; + const escapedHome = home.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + return value.replace(new RegExp(`${escapedHome}(?=$|/)`, 'g'), '~'); +}; +const normaliseEvidence = (evidence) => Object.fromEntries(Object.entries(evidence).map(([key, value]) => [key, homeRelativePath(value)])); +const evidenceKey = (value) => value + .replace(/[^A-Za-z0-9]+/g, '_') + .replace(/^_+|_+$/g, '') + .toLowerCase() || 'remote'; /** * `severity` as a total function of `status` — the only place it is decided. * @@ -62,6 +90,10 @@ const gitOptions = (opts) => (opts.cwd === undefined ? {} : { cwd: opts.cwd }); */ const severityOf = (status) => status === 'fail' ? 'error' : status === 'warn' ? 'warning' : 'info'; function check(id, category, title, status, detail, fix = null, fixed = false, needsAttention = status === 'warn' || status === 'fail', extra = {}) { + const evidence = extra.evidence ?? {}; + if (Object.keys(evidence).length === 0) { + throw new Error(`doctor check ${id} has no evidence`); + } return { id, title, @@ -72,7 +104,7 @@ function check(id, category, title, status, detail, fix = null, fixed = false, n fixed, category, severity: severityOf(status), - evidence: extra.evidence ?? {}, + evidence: normaliseEvidence(evidence), optional: extra.optional ?? false, ...(extra.skipReason === undefined ? {} : { skipReason: extra.skipReason }), }; @@ -80,8 +112,9 @@ function check(id, category, title, status, detail, fix = null, fixed = false, n const checkRefspec = (opts) => { const title = 'notes fetch refspec'; const remotes = listRemotes(opts); + const remoteEvidence = { remotes: remotes.join(', ') || 'none' }; if (remotes.length === 0) { - return check('notes-refspec', 'transport', title, 'warn', 'no remote is configured, so records cannot be shared with anyone', 'add a remote, then rerun: commitlore doctor --fix', false, false); + return check('notes-refspec', 'transport', title, 'warn', 'no remote is configured, so records cannot be shared with anyone', 'add a remote, then rerun: commitlore doctor --fix', false, false, { evidence: remoteEvidence }); } let missing = remotes.filter((remote) => !fetchRefspecs(remote, opts).some(coversNotes)); let forced = remotes.filter((remote) => fetchRefspecs(remote, opts).some(forcesNotes)); @@ -115,10 +148,10 @@ const checkRefspec = (opts) => { return check('notes-refspec', 'transport', title, 'warn', `${forced.join(', ')} fetches ${NOTES_REF} with a forced refspec, so an ordinary git fetch ` + 'overwrites this clone\'s mirror — a record written here and not yet pushed is destroyed silently', forced .map((remote) => `git config --replace-all remote.${remote}.fetch '${NOTES_REFSPEC}' '^\\+refs/notes/'`) - .join('\n'), fixed); + .join('\n'), fixed, undefined, { evidence: { ...remoteEvidence, forced: forced.join(', ') } }); } if (missing.length > 0) { - return check('notes-refspec', 'transport', title, 'warn', `${missing.join(', ')} does not fetch ${NOTES_REF}, so records pushed by others stay invisible here`, missing.map((remote) => `git config --add remote.${remote}.fetch '${NOTES_REFSPEC}'`).join('\n')); + return check('notes-refspec', 'transport', title, 'warn', `${missing.join(', ')} does not fetch ${NOTES_REF}, so records pushed by others stay invisible here`, missing.map((remote) => `git config --add remote.${remote}.fetch '${NOTES_REFSPEC}'`).join('\n'), false, undefined, { evidence: { ...remoteEvidence, missing: missing.join(', ') } }); } const failed = remotes .map((remote) => ({ remote, result: execGit(['fetch', '--dry-run', remote], gitOptions(opts)) })) @@ -126,7 +159,15 @@ const checkRefspec = (opts) => { if (failed.length > 0) { return check('notes-refspec', 'transport', title, 'warn', `could not verify (${failed .map(({ remote, result }) => `${remote}: ${result.stderr.trim().split('\n')[0] ?? 'git fetch failed'}`) - .join('; ')})`, failed.map(({ remote }) => `git fetch ${remote}`).join('\n'), fixed); + .join('; ')})`, failed.map(({ remote }) => `git fetch ${remote}`).join('\n'), fixed, undefined, { + evidence: { + ...remoteEvidence, + ...Object.fromEntries(failed.map(({ remote, result }) => [ + `fetch_exit_code_${evidenceKey(remote)}`, + String(result.code), + ])), + }, + }); } // A refspec written by `--fix` has not been fetched through yet, and this // check is the last thing the operator reads before believing the mirror is @@ -135,7 +176,7 @@ const checkRefspec = (opts) => { // retrieved -- the configuration is right and the records are still missing. return check('notes-refspec', 'transport', title, 'ok', fixed ? `${NOTES_REF} is now covered for ${remotes.join(', ')} — nothing has been fetched through it yet` - : `git fetch succeeds for ${remotes.join(', ')} and covers ${NOTES_REF}`, fixed ? `git fetch ${remotes[0] ?? 'origin'}` : null, fixed); + : `git fetch succeeds for ${remotes.join(', ')} and covers ${NOTES_REF}`, fixed ? `git fetch ${remotes[0] ?? 'origin'}` : null, fixed, undefined, { evidence: remoteEvidence }); }; /** * Pushing is never automatic: `git push` writes to a ref other people read, @@ -147,17 +188,28 @@ const checkPush = (opts) => { const remote = remotes[0] ?? 'origin'; const command = `git push ${remote} ${NOTES_REF}`; const local = execGit(['rev-parse', '--verify', '--quiet', NOTES_REF], gitOptions(opts)); + const localEvidence = { + remote, + local_sha: local.code === 0 ? local.stdout.trim() || 'unknown' : 'none', + }; if (local.code !== 0) { - return check('notes-push', 'transport', title, 'ok', `no local mirror yet — nothing to push (${command}, once there is)`); + return check('notes-push', 'transport', title, 'ok', `no local mirror yet — nothing to push (${command}, once there is)`, null, false, undefined, { evidence: { ...localEvidence, remote_sha: 'not_queried' } }); } const advertised = execGit(['ls-remote', remote, NOTES_REF], gitOptions(opts)); if (advertised.code !== 0) { - return check('notes-push', 'transport', title, 'warn', `could not verify (${remote}: ${advertised.stderr.trim().split('\n')[0] ?? 'git ls-remote failed'})`, command); + return check('notes-push', 'transport', title, 'warn', `could not verify (${remote}: ${advertised.stderr.trim().split('\n')[0] ?? 'git ls-remote failed'})`, command, false, undefined, { + evidence: { + ...localEvidence, + ls_remote_exit_code: String(advertised.code), + ...streamEvidence('ls_remote_stderr', advertised.stderr), + }, + }); } - if (advertised.stdout.split(/\s/)[0] === local.stdout.trim()) { - return check('notes-push', 'transport', title, 'ok', `${remote} has the current ${NOTES_REF}`); + const remoteSha = advertised.stdout.split(/\s/)[0] ?? ''; + if (remoteSha === local.stdout.trim()) { + return check('notes-push', 'transport', title, 'ok', `${remote} has the current ${NOTES_REF}`, null, false, undefined, { evidence: { ...localEvidence, remote_sha: remoteSha || 'none' } }); } - return check('notes-push', 'transport', title, 'warn', `this clone has local records in ${NOTES_REF}; no command pushes them for you`, command); + return check('notes-push', 'transport', title, 'warn', `this clone has local records in ${NOTES_REF}; no command pushes them for you`, command, false, undefined, { evidence: { ...localEvidence, remote_sha: remoteSha || 'none' } }); }; /** * Installation belongs to `commitlore hooks install` (T-202). This reads. @@ -174,28 +226,34 @@ const checkHook = (opts, runtime) => { // somewhere else entirely. const located = execGit(['rev-parse', '--git-path', 'hooks/commit-msg'], gitOptions(opts)); if (located.code !== 0) { - return check(id, category, title, 'warn', 'not inside a git repository', install); + return check(id, category, title, 'warn', 'not inside a git repository', install, false, undefined, { evidence: { hook_path: 'unavailable', bin: 'not_recorded', node: 'not_recorded' } }); } const path = resolve(opts.cwd ?? process.cwd(), located.stdout.trim()); const target = readRecordedHookTarget(opts.cwd ?? process.cwd()); const override = process.env['COMMITLORE_BIN']; + const hookEvidence = { + hook_path: path, + bin: target.bin || '(unset)', + node: target.node || '(unset)', + ...(override === undefined || override === '' ? {} : { commitlore_bin_override: override }), + }; const targetDetail = [ ...describeRecordedHookTarget(target), ...(override === undefined || override === '' ? [] : [`COMMITLORE_BIN: ${override}`]), ].join('; '); if (!existsSync(path)) { - return check(id, category, title, 'warn', `no commit-msg hook at ${path}; ${targetDetail}`, install); + return check(id, category, title, 'warn', `no commit-msg hook at ${path}; ${targetDetail}`, install, false, undefined, { evidence: hookEvidence }); } const contents = readFileSync(path, 'utf8'); if (!contents.includes(HOOK_MARKER)) { - return check(id, category, title, 'warn', `a commit-msg hook exists at ${path} but does not invoke commitlore; ${targetDetail}`, install); + return check(id, category, title, 'warn', `a commit-msg hook exists at ${path} but does not invoke commitlore; ${targetDetail}`, install, false, undefined, { evidence: hookEvidence }); } // `hooks status` has always reported this; doctor did not, and doctor is what // people run to ask whether their installation is healthy. A stale stub is // exactly how a fixed resolution order fails to reach anyone who installed // before it landed. if (contents !== commitMsgStub()) { - return check(id, category, title, 'warn', `installed at ${path}, but the stub is out of date — it predates a change to how the hook finds the CLI; ${targetDetail}`, install); + return check(id, category, title, 'warn', `installed at ${path}, but the stub is out of date — it predates a change to how the hook finds the CLI; ${targetDetail}`, install, false, undefined, { evidence: hookEvidence }); } const problems = [ ...target.problems, @@ -217,13 +275,16 @@ const checkHook = (opts, runtime) => { // written out rather than cast away so that adding one cannot silently // produce a reasonless skip here. if (runtime.status === 'skipped') { - return check(id, category, title, 'skipped', inherited, install, false, false, { skipReason: runtime.skipReason ?? 'nothing_applicable' }); + return check(id, category, title, 'skipped', inherited, install, false, false, { + evidence: { ...hookEvidence, runtime_status: runtime.status }, + skipReason: runtime.skipReason ?? 'nothing_applicable', + }); } - return check(id, category, title, runtime.status, inherited, install); + return check(id, category, title, runtime.status, inherited, install, false, undefined, { evidence: { ...hookEvidence, runtime_status: runtime.status } }); } return problems.length === 0 - ? check(id, category, title, 'ok', `installed at ${path}; ${targetDetail}`) - : check(id, category, title, 'warn', `installed at ${path}; ${targetDetail}; ${problems.join('; ')}`, install); + ? check(id, category, title, 'ok', `installed at ${path}; ${targetDetail}`, null, false, undefined, { evidence: hookEvidence }) + : check(id, category, title, 'warn', `installed at ${path}; ${targetDetail}; ${problems.join('; ')}`, install, false, undefined, { evidence: hookEvidence }); }; /** * Runs the real parse path once. Trailer boundaries are git's to decide @@ -246,13 +307,13 @@ const checkGit = (opts) => { } catch (error) { const reason = error instanceof Error ? error.message : String(error); - return check(id, category, title, 'fail', `${version || 'git'} could not parse a probe: ${reason}`, upgrade); + return check(id, category, title, 'fail', `${version || 'git'} could not parse a probe: ${reason}`, upgrade, false, undefined, { evidence: { git_version: version || 'unavailable', parsed: 'unavailable' } }); } const parsed = trailers.map((trailer) => `${trailer.key}: ${trailer.value}`).join(', '); if (parsed !== 'Limit: probe, Blast: local') { - return check(id, category, title, 'fail', `${version} parsed the probe as [${parsed}]`, upgrade); + return check(id, category, title, 'fail', `${version} parsed the probe as [${parsed}]`, upgrade, false, undefined, { evidence: { git_version: version || 'unavailable', parsed } }); } - return check(id, category, title, 'ok', `${version} parses trailers as the spec expects`); + return check(id, category, title, 'ok', `${version} parses trailers as the spec expects`, null, false, undefined, { evidence: { git_version: version || 'unavailable', parsed } }); }; /** * Whether the CLI this installation actually uses runs. @@ -284,7 +345,13 @@ const checkRuntime = (opts) => { const candidates = ['dist/commitlore.mjs', 'dist/cli.js'].map((rel) => installedPath(rel)); const entry = candidates.find((path) => existsSync(path)); if (entry === undefined) { - return check(id, category, title, 'fail', `no built CLI at ${candidates.join(' or ')} — this checkout has not been built`, 'npm install && npm run build'); + return check(id, category, title, 'fail', `no built CLI at ${candidates.join(' or ')} — this checkout has not been built`, 'npm install && npm run build', false, undefined, { + evidence: { + entry: candidates.join(' or '), + exit_code: 'not_run', + ...streamEvidence('stderr', ''), + }, + }); } const run = spawnSync(process.execPath, [entry, '--version'], { shell: false, @@ -292,13 +359,32 @@ const checkRuntime = (opts) => { ...gitOptions(opts), }); if (run.error !== undefined) { - return check(id, category, title, 'fail', `could not run ${entry}: ${run.error.message}`, null); + return check(id, category, title, 'fail', `could not run ${entry}: ${run.error.message}`, null, false, undefined, { + evidence: { + entry, + exit_code: String(run.status ?? 'unavailable'), + error: run.error.message, + ...streamEvidence('stderr', run.stderr), + }, + }); } if (run.status !== 0) { const detail = `${run.stderr ?? ''}`.trim().split('\n')[0] ?? `exit ${String(run.status)}`; - return check(id, category, title, 'fail', `${entry} exits ${String(run.status)}: ${detail}`, 'npm install'); + return check(id, category, title, 'fail', `${entry} exits ${String(run.status)}: ${detail}`, 'npm install', false, undefined, { + evidence: { + entry, + exit_code: String(run.status), + ...streamEvidence('stderr', run.stderr), + }, + }); } - return check(id, category, title, 'ok', `${entry} runs (${run.stdout.trim()})`); + return check(id, category, title, 'ok', `${entry} runs (${run.stdout.trim()})`, null, false, undefined, { + evidence: { + entry, + version: boundedExcerpt(run.stdout).firstLine, + ...streamEvidence('stdout', run.stdout), + }, + }); }; /** * Whether the installed hook actually runs, in the environment git gives it. @@ -326,13 +412,21 @@ const checkHookRuntime = (opts) => { const fix = 'commitlore hooks install'; const cwd = opts.cwd ?? process.cwd(); const located = execGit(['rev-parse', '--git-path', 'hooks/commit-msg'], gitOptions(opts)); - if (located.code !== 0) - return check(id, category, title, 'warn', 'not inside a git repository', fix); + if (located.code !== 0) { + return check(id, category, title, 'warn', 'not inside a git repository', fix, false, undefined, { + evidence: { + hook_path: 'unavailable', + exit_code: String(located.code), + ...streamEvidence('stderr', located.stderr), + }, + }); + } const hook = resolve(cwd, located.stdout.trim()); // The hook's absence is `checkHook`'s finding; saying it twice teaches the // reader to skim both. - if (!existsSync(hook)) - return check(id, category, title, 'ok', 'no hook installed — nothing to run'); + if (!existsSync(hook)) { + return check(id, category, title, 'ok', 'no hook installed — nothing to run', null, false, undefined, { evidence: { hook_path: hook } }); + } const probe = join(tmpdirPath(), `commitlore-doctor-${String(process.pid)}.txt`); try { writeFileSync(probe, PROBE_MESSAGE); @@ -345,7 +439,14 @@ const checkHookRuntime = (opts) => { env: { PATH: '/usr/bin:/bin', HOME: process.env['HOME'] ?? '' }, }); if (run.error !== undefined) { - return check(id, category, title, 'fail', `could not run the hook: ${run.error.message}`, fix); + return check(id, category, title, 'fail', `could not run the hook: ${run.error.message}`, fix, false, undefined, { + evidence: { + hook_path: hook, + exit_code: String(run.status ?? 'unavailable'), + error: run.error.message, + ...streamEvidence('stderr', run.stderr), + }, + }); } if (run.status !== 0) { const said = `${run.stderr ?? ''}`.trim().split('\n')[0] ?? ''; @@ -362,12 +463,25 @@ const checkHookRuntime = (opts) => { else { detail = `the hook exited ${String(run.status)} under the restricted PATH — cause unclear: ${said || 'no output'}`; } - return check(id, category, title, 'fail', detail, fix); + return check(id, category, title, 'fail', detail, fix, false, undefined, { + evidence: { + hook_path: hook, + exit_code: String(run.status), + ...streamEvidence('stderr', run.stderr), + }, + }); } - return check(id, category, title, 'ok', 'the hook runs and validates without node on PATH'); + return check(id, category, title, 'ok', 'the hook runs and validates without node on PATH', null, false, undefined, { evidence: { hook_path: hook, exit_code: '0' } }); } catch (error) { - return check(id, category, title, 'warn', `could not probe the hook: ${error instanceof Error ? error.message : String(error)}`, fix); + return check(id, category, title, 'warn', `could not probe the hook: ${error instanceof Error ? error.message : String(error)}`, fix, false, undefined, { + evidence: { + hook_path: hook, + exit_code: 'unavailable', + error: error instanceof Error ? error.message : String(error), + ...streamEvidence('stderr', ''), + }, + }); } finally { rmSync(probe, { force: true }); @@ -404,21 +518,54 @@ const checkHookRuntime = (opts) => { */ export const evaluateInjectRun = (run, ctx) => { const { id, category, title, executable, path, fix, unavailableFix } = ctx; + const executionEvidence = { executable, path }; if (run.status === null || run.status === undefined) { if (run.error !== undefined && 'code' in run.error && run.error.code === 'ENOENT') { - return check(id, category, title, 'fail', `configured PreToolUse hook executable ${JSON.stringify(executable)} is not resolvable from PATH`, unavailableFix); + return check(id, category, title, 'fail', `configured PreToolUse hook executable ${JSON.stringify(executable)} is not resolvable from PATH`, unavailableFix, false, undefined, { + evidence: { + ...executionEvidence, + exit_code: 'unavailable', + ...streamEvidence('stderr', run.stderr), + }, + }); } - return check(id, category, title, 'fail', `could not run the PreToolUse hook: ${run.error?.message ?? 'no diagnosis'}`, fix); + return check(id, category, title, 'fail', `could not run the PreToolUse hook: ${run.error?.message ?? 'no diagnosis'}`, fix, false, undefined, { + evidence: { + ...executionEvidence, + exit_code: 'unavailable', + error: run.error?.message ?? 'no diagnosis', + ...streamEvidence('stderr', run.stderr), + }, + }); } if (run.status !== 0) { const said = `${run.stderr ?? ''}`.trim().split('\n')[0] ?? ''; - return check(id, category, title, 'fail', `the PreToolUse hook exits ${String(run.status)}: ${said || 'no diagnosis'}`, fix); + return check(id, category, title, 'fail', `the PreToolUse hook exits ${String(run.status)}: ${said || 'no diagnosis'}`, fix, false, undefined, { + evidence: { + ...executionEvidence, + exit_code: String(run.status), + ...streamEvidence('stderr', run.stderr), + }, + }); } if (`${run.stdout ?? ''}`.trim() === '') { const said = `${run.stderr ?? ''}`.trim().split('\n')[0] ?? ''; - return check(id, category, title, 'fail', `the PreToolUse hook returned no context for a known-good payload${said === '' ? '' : `: ${said}`}`, fix); + return check(id, category, title, 'fail', `the PreToolUse hook returned no context for a known-good payload${said === '' ? '' : `: ${said}`}`, fix, false, undefined, { + evidence: { + ...executionEvidence, + exit_code: '0', + ...streamEvidence('stdout', run.stdout), + ...streamEvidence('stderr', run.stderr), + }, + }); } - return check(id, category, title, 'ok', `the PreToolUse hook returned context for ${path}`); + return check(id, category, title, 'ok', `the PreToolUse hook returned context for ${path}`, null, false, undefined, { + evidence: { + ...executionEvidence, + exit_code: '0', + ...streamEvidence('stdout', run.stdout), + }, + }); }; const checkInjectRuntime = (opts) => { const title = 'PreToolUse hook runtime'; @@ -431,22 +578,61 @@ const checkInjectRuntime = (opts) => { if (settings.state !== 'installed') { const command = settings.commands[0]; if (settings.state === 'outdated' && command !== undefined) { - return check(id, category, title, 'skipped', `not checked: configured command ${JSON.stringify(command)} is not recognised; running it might have side effects`, null, false, false, { skipReason: 'command_unrecognized' }); + return check(id, category, title, 'skipped', `not checked: configured command ${JSON.stringify(command)} is not recognised; running it might have side effects`, null, false, false, { + evidence: { + settings_path: settings.settingsPath, + settings_state: settings.state, + configured_command: command, + executable: 'not_run', + exit_code: 'not_run', + ...streamEvidence('stderr', ''), + }, + skipReason: 'command_unrecognized', + }); } const detail = settings.state === 'absent' ? `not installed in ${settings.settingsPath}` : `${settings.state} in ${settings.settingsPath}${settings.problem === undefined ? '' : `: ${settings.problem}`}`; - return check(id, category, title, 'warn', detail, 'commitlore inject install-claude-hook'); + return check(id, category, title, 'warn', detail, 'commitlore inject install-claude-hook', false, undefined, { + evidence: { + settings_path: settings.settingsPath, + settings_state: settings.state, + executable: 'not_run', + exit_code: 'not_run', + ...streamEvidence('stderr', ''), + ...(settings.problem === undefined ? {} : { problem: settings.problem }), + }, + }); } const command = settings.commands[0]; if (command !== CLAUDE_HOOK_COMMAND) { - return check(id, category, title, 'skipped', 'not checked: the configured command is not recognised', null, false, false, { skipReason: 'command_unrecognized' }); + return check(id, category, title, 'skipped', 'not checked: the configured command is not recognised', null, false, false, { + evidence: { + settings_path: settings.settingsPath, + settings_state: settings.state, + configured_command: command ?? 'none', + executable: 'not_run', + exit_code: 'not_run', + ...streamEvidence('stderr', ''), + }, + skipReason: 'command_unrecognized', + }); } const path = runQuery({ cwd, noIndex: true }).records .flatMap((record) => record.paths) .find((candidate) => candidate !== '' && candidate !== '.'); if (path === undefined) { - return check(id, category, title, 'skipped', 'no recorded path is available for a runtime probe', null, false, false, { skipReason: 'probe_path_unavailable' }); + return check(id, category, title, 'skipped', 'no recorded path is available for a runtime probe', null, false, false, { + evidence: { + settings_path: settings.settingsPath, + settings_state: settings.state, + executable: 'not_run', + probe_path: 'unavailable', + exit_code: 'not_run', + ...streamEvidence('stderr', ''), + }, + skipReason: 'probe_path_unavailable', + }); } const payload = JSON.stringify({ session_id: 'commitlore-doctor', @@ -511,11 +697,22 @@ const checkInjectVersion = (opts) => { const mine = packageVersion(); const settings = readClaudeHookStatus(claudeSettingsPath(cwd)); if (settings.state !== 'installed') { - return check(id, category, title, 'skipped', `no installed hook to compare against ${mine}`, null, false, false, { skipReason: 'hook_not_installed' }); + return check(id, category, title, 'skipped', `no installed hook to compare against ${mine}`, null, false, false, { + evidence: { executable: 'not_run', theirs: 'not_run', mine }, + skipReason: 'hook_not_installed', + }); } const command = settings.commands[0]; if (command !== CLAUDE_HOOK_COMMAND) { - return check(id, category, title, 'skipped', 'not checked: the configured command is not recognised', null, false, false, { skipReason: 'command_unrecognized' }); + return check(id, category, title, 'skipped', 'not checked: the configured command is not recognised', null, false, false, { + evidence: { + executable: 'not_run', + theirs: 'not_run', + mine, + configured_command: command ?? 'none', + }, + skipReason: 'command_unrecognized', + }); } const configured = command.replace(` ${CLAUDE_HOOK_MARKER}`, ''); const executable = configured.slice(0, configured.indexOf(' ')); @@ -528,10 +725,18 @@ const checkInjectVersion = (opts) => { HOME: process.env['HOME'] ?? '', }, }); + const reported = typeof run.stdout === 'string' ? run.stdout : ''; + const versionEvidence = { + executable, + theirs: boundedExcerpt(reported).firstLine || 'unavailable', + mine, + exit_code: String(run.status ?? 'unavailable'), + ...streamEvidence('stdout', reported), + }; if (run.status !== 0 || typeof run.stdout !== 'string') { // `checkInjectRuntime` owns "the hook does not run at all" and reports it // with the remedy. Saying it twice would be noise. - return check(id, category, title, 'skipped', `${executable} did not report a version`, null, false, false, { skipReason: 'version_unreadable' }); + return check(id, category, title, 'skipped', `${executable} did not report a version`, null, false, false, { evidence: versionEvidence, skipReason: 'version_unreadable' }); } const theirs = run.stdout.trim(); // Exit 0 is not the same as an answer. A wrapper that ignores its arguments @@ -539,12 +744,12 @@ const checkInjectVersion = (opts) => { // version reports a mismatch against something that was never a version. // Two builds cannot be compared unless both sides actually said one. if (!SEMVER_ISH.test(theirs)) { - return check(id, category, title, 'skipped', `${executable} answered --version with something that is not a version`, null, false, false, { skipReason: 'version_unreadable' }); + return check(id, category, title, 'skipped', `${executable} answered --version with something that is not a version`, null, false, false, { evidence: versionEvidence, skipReason: 'version_unreadable' }); } if (theirs === mine) { - return check(id, category, title, 'ok', `the hook runs ${theirs}, the same build as this CLI`); + return check(id, category, title, 'ok', `the hook runs ${theirs}, the same build as this CLI`, null, false, undefined, { evidence: versionEvidence }); } - return check(id, category, title, 'warn', `the agent's hook runs ${theirs} but this CLI is ${mine} — every edit is graded by ${theirs}'s rules, not this one's`, 'update the installation the hook resolves to (for the plugin: /plugin marketplace update commitlore), then rerun: commitlore doctor'); + return check(id, category, title, 'warn', `the agent's hook runs ${theirs} but this CLI is ${mine} — every edit is graded by ${theirs}'s rules, not this one's`, 'update the installation the hook resolves to (for the plugin: /plugin marketplace update commitlore), then rerun: commitlore doctor', false, undefined, { evidence: versionEvidence }); }; /** * MCP servers that started here and never recorded an exit (#424). @@ -568,12 +773,18 @@ const checkMcpLifecycle = (opts) => { const cwd = opts.cwd ?? process.cwd(); const unfinished = unfinishedRuns(cwd); if (unfinished.length === 0) { - return check(id, category, title, 'ok', 'every recorded MCP session ended cleanly, or is still running'); + return check(id, category, title, 'ok', 'every recorded MCP session ended cleanly, or is still running', null, false, undefined, { evidence: { unfinished_count: '0', last_pid: 'none', last_at: 'none' } }); } const last = unfinished[unfinished.length - 1]; return check(id, category, title, 'warn', `${unfinished.length} MCP server session(s) started here and never recorded an exit — ` + `most recently pid ${String(last?.pid ?? 0)} at ${last?.at ?? 'unknown'}. ` + - 'A killed server loses its tool registration in the client, which reports the same as a tool that never existed (#424)', 'restart the client session; if this repeats, capture it with a client started under --debug'); + 'A killed server loses its tool registration in the client, which reports the same as a tool that never existed (#424)', 'restart the client session; if this repeats, capture it with a client started under --debug', false, undefined, { + evidence: { + unfinished_count: String(unfinished.length), + last_pid: String(last?.pid ?? 0), + last_at: last?.at ?? 'unknown', + }, + }); }; /** * #458: captures that were prepared and then never reached a commit. @@ -608,17 +819,31 @@ const checkPendingBacklog = (opts) => { listing = runPendingList({ cwd }); } catch { - return check(id, category, title, 'ok', 'no pending directory — nothing has been captured here yet'); + return check(id, category, title, 'ok', 'no pending directory — nothing has been captured here yet', null, false, undefined, { evidence: { stranded: '0', staged_expired: '0', oldest: 'none' } }); } if (listing.unreadable.length > 0) { - return check(id, category, title, 'warn', `${listing.unreadable.length} pending file(s) cannot be read as a transaction`, 'commitlore pending ls'); + return check(id, category, title, 'warn', `${listing.unreadable.length} pending file(s) cannot be read as a transaction`, 'commitlore pending ls', false, undefined, { + evidence: { + stranded: '0', + staged_expired: '0', + oldest: 'none', + unreadable: String(listing.unreadable.length), + }, + }); } // A stale transaction can no longer apply: its base_head is not HEAD, so the // commit it was prepared for either never happened or happened without it. const stranded = listing.transactions.filter((transaction) => transaction.stale); if (stranded.length === 0) { const held = listing.transactions.length; - return check(id, category, title, 'ok', held === 0 ? 'no captures are waiting' : `${String(held)} capture(s) waiting, all still able to apply`); + return check(id, category, title, 'ok', held === 0 ? 'no captures are waiting' : `${String(held)} capture(s) waiting, all still able to apply`, null, false, undefined, { + evidence: { + stranded: '0', + staged_expired: '0', + oldest: 'none', + waiting: String(held), + }, + }); } const lost = stranded.filter((transaction) => transaction.phase === 'staged'); const oldest = stranded @@ -635,7 +860,13 @@ const checkPendingBacklog = (opts) => { : `${String(stranded.length)} capture(s) can no longer apply — their base commit is no longer HEAD`; return check(id, category, title, 'warn', `${detail}; oldest from ${oldest ?? 'an unknown time'}. ` + 'A staged record binds to the tree it was prepared for and is skipped once that tree moves, ' + - 'so these decisions were never written to the history (#458)', 'commitlore pending ls'); + 'so these decisions were never written to the history (#458)', 'commitlore pending ls', false, undefined, { + evidence: { + stranded: String(stranded.length), + staged_expired: String(lost.length), + oldest: oldest ?? 'unknown', + }, + }); }; const checkIndex = (opts) => { const cwd = opts.cwd ?? process.cwd(); @@ -644,19 +875,42 @@ const checkIndex = (opts) => { handle = openIndex({ cwd, readonly: true }); } catch { - return check('index-health', 'index', 'index health', 'warn', 'no index yet — queries fall back to scanning the history', 'commitlore index --rebuild'); + return check('index-health', 'index', 'index health', 'warn', 'no index yet — queries fall back to scanning the history', 'commitlore index --rebuild', false, undefined, { + evidence: { + trailers: '0', + commits: '0', + last_indexed_sha: 'none', + head_sha: 'not_queried', + fts: 'unavailable', + }, + }); } try { const info = indexInfo(handle); const head = execGit(['rev-parse', 'HEAD'], gitOptions(opts)); const behind = head.code === 0 && info.lastIndexedSha !== head.stdout.trim(); const fts = info.fts ? 'FTS5' : 'no FTS5 (value search falls back to LIKE)'; + const indexEvidence = { + trailers: String(info.trailers), + commits: String(info.commits), + last_indexed_sha: info.lastIndexedSha || 'none', + head_sha: head.code === 0 ? head.stdout.trim() || 'none' : 'unavailable', + fts: info.fts ? 'true' : 'false', + }; return behind - ? check('index-health', 'index', 'index health', 'warn', `${info.trailers} trailers over ${info.commits} commits, behind HEAD — ${fts}`, 'commitlore index') - : check('index-health', 'index', 'index health', 'ok', `${info.trailers} trailers over ${info.commits} commits, current with HEAD — ${fts}`); + ? check('index-health', 'index', 'index health', 'warn', `${info.trailers} trailers over ${info.commits} commits, behind HEAD — ${fts}`, 'commitlore index', false, undefined, { evidence: indexEvidence }) + : check('index-health', 'index', 'index health', 'ok', `${info.trailers} trailers over ${info.commits} commits, current with HEAD — ${fts}`, null, false, undefined, { evidence: indexEvidence }); } catch (error) { - return check('index-health', 'index', 'index health', 'warn', `index unreadable (${error instanceof Error ? error.message : String(error)}) — queries still work without it`, 'commitlore index --rebuild'); + return check('index-health', 'index', 'index health', 'warn', `index unreadable (${error instanceof Error ? error.message : String(error)}) — queries still work without it`, 'commitlore index --rebuild', false, undefined, { + evidence: { + trailers: 'unavailable', + commits: 'unavailable', + last_indexed_sha: 'unavailable', + head_sha: 'unavailable', + fts: 'unavailable', + }, + }); } finally { try { @@ -668,8 +922,8 @@ const checkIndex = (opts) => { } }; const checkHistoryDepth = (opts) => hasShallowHistory(opts.cwd ?? process.cwd()) - ? check('history-depth', 'history', 'history depth', 'warn', 'this clone has shallow history, so queries may be missing records that exist upstream', 'git fetch --unshallow') - : check('history-depth', 'history', 'history depth', 'ok', 'full history is available'); + ? check('history-depth', 'history', 'history depth', 'warn', 'this clone has shallow history, so queries may be missing records that exist upstream', 'git fetch --unshallow', false, undefined, { evidence: { shallow: 'true' } }) + : check('history-depth', 'history', 'history depth', 'ok', 'full history is available', null, false, undefined, { evidence: { shallow: 'false' } }); /** Local branches this check will look at, past which a repository is skipped rather than walked exhaustively. */ const MAX_SQUASH_CANDIDATE_BRANCHES = 200; /** @@ -743,11 +997,17 @@ const checkSquashConservation = (opts) => { const cwd = opts.cwd ?? process.cwd(); const head = execGit(['rev-parse', '--verify', '--quiet', 'HEAD'], gitOptions(opts)); if (head.code !== 0) { - return check(id, category, title, 'skipped', 'no HEAD yet — nothing to compare against', null, false, false, { skipReason: 'unborn_head' }); + return check(id, category, title, 'skipped', 'no HEAD yet — nothing to compare against', null, false, false, { + evidence: { candidates: '0', checked: '0', uncheckable: '0', lost_count: '0' }, + skipReason: 'unborn_head', + }); } const candidates = squashCandidates(opts, head.stdout.trim()); if (candidates.length === 0) { - return check(id, category, title, 'skipped', 'no local branch looks like the source of a squash — nothing to check', null, false, false, { skipReason: 'nothing_applicable' }); + return check(id, category, title, 'skipped', 'no local branch looks like the source of a squash — nothing to check', null, false, false, { + evidence: { candidates: '0', checked: '0', uncheckable: '0', lost_count: '0' }, + skipReason: 'nothing_applicable', + }); } let known = null; const lost = []; @@ -785,7 +1045,15 @@ const checkSquashConservation = (opts) => { } } if (checked === 0) { - return check(id, category, title, 'skipped', `${candidates.length} branch(es) looked like a squash source, but recorded nothing checkable`, null, false, false, { skipReason: 'nothing_applicable' }); + return check(id, category, title, 'skipped', `${candidates.length} branch(es) looked like a squash source, but recorded nothing checkable`, null, false, false, { + evidence: { + candidates: String(candidates.length), + checked: '0', + uncheckable: String(uncheckable), + lost_count: '0', + }, + skipReason: 'nothing_applicable', + }); } if (lost.length > 0) { const named = lost @@ -794,13 +1062,27 @@ const checkSquashConservation = (opts) => { .join(', '); const more = lost.length > 5 ? `, and ${lost.length - 5} more` : ''; return check(id, category, title, 'warn', `${lost.length} record(s) declared on a branch not reachable from HEAD do not appear in HEAD's history: ${named}${more}`, 'commitlore squash-preserve .. --target , ' + - 'then commit or attach the result'); + 'then commit or attach the result', false, undefined, { + evidence: { + candidates: String(candidates.length), + checked: String(checked), + uncheckable: String(uncheckable), + lost_count: String(lost.length), + }, + }); } const detail = uncheckable > 0 ? `${checked} squash-shaped branch(es) checked, every declared Record-Id is reachable from HEAD ` + `(${uncheckable} branch(es) recorded nothing with an id and could not be checked this way)` : `${checked} squash-shaped branch(es) checked, every declared Record-Id is reachable from HEAD`; - return check(id, category, title, 'ok', detail); + return check(id, category, title, 'ok', detail, null, false, undefined, { + evidence: { + candidates: String(candidates.length), + checked: String(checked), + uncheckable: String(uncheckable), + lost_count: '0', + }, + }); }; /** Runs `hook-runtime` at most once per report, whichever row asks first. */ const hookRuntimeOf = (ctx) => { diff --git a/dist/commands/doctor.js.map b/dist/commands/doctor.js.map index f110b75..bb8bcc2 100644 --- a/dist/commands/doctor.js.map +++ b/dist/commands/doctor.js.map @@ -1 +1 @@ -{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/commitlore.mjs b/dist/commitlore.mjs index 0f92de1..78f42b8 100755 --- a/dist/commitlore.mjs +++ b/dist/commitlore.mjs @@ -17249,8 +17249,36 @@ var EXACT_NOTES_REFSPEC = `+${NOTES_REF}:${NOTES_REF}`; var EXACT_NOTES_REFSPEC_PATTERN = `^\\${EXACT_NOTES_REFSPEC}$`; var escapeConfigValuePattern = (value) => value.replace(/[\\.*+?[\]^$(){}|]/g, (character) => `\\${character}`); var gitOptions3 = (opts) => opts.cwd === void 0 ? {} : { cwd: opts.cwd }; +var boundedExcerpt = (output) => { + const [firstLine5 = ""] = (output ?? "").split(/\r?\n/, 1); + return { + firstLine: firstLine5.slice(0, 200), + truncated: firstLine5.length > 200 ? "true" : "false" + }; +}; +var streamEvidence = (stream, output) => { + const excerpt = boundedExcerpt(output); + return { + [`${stream}_first_line`]: excerpt.firstLine, + [`${stream}_truncated`]: excerpt.truncated + }; +}; +var homeRelativePath = (value) => { + const home = process.env["HOME"]; + if (home === void 0 || home === "") return value; + const escapedHome = home.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); + return value.replace(new RegExp(`${escapedHome}(?=$|/)`, "g"), "~"); +}; +var normaliseEvidence = (evidence) => Object.fromEntries( + Object.entries(evidence).map(([key, value]) => [key, homeRelativePath(value)]) +); +var evidenceKey = (value) => value.replace(/[^A-Za-z0-9]+/g, "_").replace(/^_+|_+$/g, "").toLowerCase() || "remote"; var severityOf = (status) => status === "fail" ? "error" : status === "warn" ? "warning" : "info"; function check(id, category, title, status, detail, fix = null, fixed = false, needsAttention = status === "warn" || status === "fail", extra = {}) { + const evidence = extra.evidence ?? {}; + if (Object.keys(evidence).length === 0) { + throw new Error(`doctor check ${id} has no evidence`); + } return { id, title, @@ -17261,7 +17289,7 @@ function check(id, category, title, status, detail, fix = null, fixed = false, n fixed, category, severity: severityOf(status), - evidence: extra.evidence ?? {}, + evidence: normaliseEvidence(evidence), optional: extra.optional ?? false, ...extra.skipReason === void 0 ? {} : { skipReason: extra.skipReason } }; @@ -17269,6 +17297,7 @@ function check(id, category, title, status, detail, fix = null, fixed = false, n var checkRefspec = (opts) => { const title = "notes fetch refspec"; const remotes = listRemotes(opts); + const remoteEvidence = { remotes: remotes.join(", ") || "none" }; if (remotes.length === 0) { return check( "notes-refspec", @@ -17278,7 +17307,8 @@ var checkRefspec = (opts) => { "no remote is configured, so records cannot be shared with anyone", "add a remote, then rerun: commitlore doctor --fix", false, - false + false, + { evidence: remoteEvidence } ); } let missing = remotes.filter((remote) => !fetchRefspecs(remote, opts).some(coversNotes)); @@ -17318,7 +17348,9 @@ var checkRefspec = (opts) => { "warn", `${forced.join(", ")} fetches ${NOTES_REF} with a forced refspec, so an ordinary git fetch overwrites this clone's mirror \u2014 a record written here and not yet pushed is destroyed silently`, forced.map((remote) => `git config --replace-all remote.${remote}.fetch '${NOTES_REFSPEC}' '^\\+refs/notes/'`).join("\n"), - fixed + fixed, + void 0, + { evidence: { ...remoteEvidence, forced: forced.join(", ") } } ); } if (missing.length > 0) { @@ -17328,7 +17360,10 @@ var checkRefspec = (opts) => { title, "warn", `${missing.join(", ")} does not fetch ${NOTES_REF}, so records pushed by others stay invisible here`, - missing.map((remote) => `git config --add remote.${remote}.fetch '${NOTES_REFSPEC}'`).join("\n") + missing.map((remote) => `git config --add remote.${remote}.fetch '${NOTES_REFSPEC}'`).join("\n"), + false, + void 0, + { evidence: { ...remoteEvidence, missing: missing.join(", ") } } ); } const failed = remotes.map((remote) => ({ remote, result: execGit(["fetch", "--dry-run", remote], gitOptions3(opts)) })).filter(({ result }) => result.code !== 0); @@ -17340,7 +17375,19 @@ var checkRefspec = (opts) => { "warn", `could not verify (${failed.map(({ remote, result }) => `${remote}: ${result.stderr.trim().split("\n")[0] ?? "git fetch failed"}`).join("; ")})`, failed.map(({ remote }) => `git fetch ${remote}`).join("\n"), - fixed + fixed, + void 0, + { + evidence: { + ...remoteEvidence, + ...Object.fromEntries( + failed.map(({ remote, result }) => [ + `fetch_exit_code_${evidenceKey(remote)}`, + String(result.code) + ]) + ) + } + } ); } return check( @@ -17350,7 +17397,9 @@ var checkRefspec = (opts) => { "ok", fixed ? `${NOTES_REF} is now covered for ${remotes.join(", ")} \u2014 nothing has been fetched through it yet` : `git fetch succeeds for ${remotes.join(", ")} and covers ${NOTES_REF}`, fixed ? `git fetch ${remotes[0] ?? "origin"}` : null, - fixed + fixed, + void 0, + { evidence: remoteEvidence } ); }; var checkPush = (opts) => { @@ -17359,13 +17408,21 @@ var checkPush = (opts) => { const remote = remotes[0] ?? "origin"; const command = `git push ${remote} ${NOTES_REF}`; const local = execGit(["rev-parse", "--verify", "--quiet", NOTES_REF], gitOptions3(opts)); + const localEvidence = { + remote, + local_sha: local.code === 0 ? local.stdout.trim() || "unknown" : "none" + }; if (local.code !== 0) { return check( "notes-push", "transport", title, "ok", - `no local mirror yet \u2014 nothing to push (${command}, once there is)` + `no local mirror yet \u2014 nothing to push (${command}, once there is)`, + null, + false, + void 0, + { evidence: { ...localEvidence, remote_sha: "not_queried" } } ); } const advertised = execGit(["ls-remote", remote, NOTES_REF], gitOptions3(opts)); @@ -17376,11 +17433,31 @@ var checkPush = (opts) => { title, "warn", `could not verify (${remote}: ${advertised.stderr.trim().split("\n")[0] ?? "git ls-remote failed"})`, - command + command, + false, + void 0, + { + evidence: { + ...localEvidence, + ls_remote_exit_code: String(advertised.code), + ...streamEvidence("ls_remote_stderr", advertised.stderr) + } + } ); } - if (advertised.stdout.split(/\s/)[0] === local.stdout.trim()) { - return check("notes-push", "transport", title, "ok", `${remote} has the current ${NOTES_REF}`); + const remoteSha = advertised.stdout.split(/\s/)[0] ?? ""; + if (remoteSha === local.stdout.trim()) { + return check( + "notes-push", + "transport", + title, + "ok", + `${remote} has the current ${NOTES_REF}`, + null, + false, + void 0, + { evidence: { ...localEvidence, remote_sha: remoteSha || "none" } } + ); } return check( "notes-push", @@ -17388,7 +17465,10 @@ var checkPush = (opts) => { title, "warn", `this clone has local records in ${NOTES_REF}; no command pushes them for you`, - command + command, + false, + void 0, + { evidence: { ...localEvidence, remote_sha: remoteSha || "none" } } ); }; var checkHook = (opts, runtime) => { @@ -17398,17 +17478,43 @@ var checkHook = (opts, runtime) => { const install = "commitlore hooks install"; const located = execGit(["rev-parse", "--git-path", "hooks/commit-msg"], gitOptions3(opts)); if (located.code !== 0) { - return check(id, category, title, "warn", "not inside a git repository", install); + return check( + id, + category, + title, + "warn", + "not inside a git repository", + install, + false, + void 0, + { evidence: { hook_path: "unavailable", bin: "not_recorded", node: "not_recorded" } } + ); } const path2 = resolve6(opts.cwd ?? process.cwd(), located.stdout.trim()); const target = readRecordedHookTarget(opts.cwd ?? process.cwd()); const override = process.env["COMMITLORE_BIN"]; + const hookEvidence = { + hook_path: path2, + bin: target.bin || "(unset)", + node: target.node || "(unset)", + ...override === void 0 || override === "" ? {} : { commitlore_bin_override: override } + }; const targetDetail = [ ...describeRecordedHookTarget(target), ...override === void 0 || override === "" ? [] : [`COMMITLORE_BIN: ${override}`] ].join("; "); if (!existsSync7(path2)) { - return check(id, category, title, "warn", `no commit-msg hook at ${path2}; ${targetDetail}`, install); + return check( + id, + category, + title, + "warn", + `no commit-msg hook at ${path2}; ${targetDetail}`, + install, + false, + void 0, + { evidence: hookEvidence } + ); } const contents = readFileSync10(path2, "utf8"); if (!contents.includes(HOOK_MARKER)) { @@ -17418,7 +17524,10 @@ var checkHook = (opts, runtime) => { title, "warn", `a commit-msg hook exists at ${path2} but does not invoke commitlore; ${targetDetail}`, - install + install, + false, + void 0, + { evidence: hookEvidence } ); } if (contents !== commitMsgStub()) { @@ -17428,7 +17537,10 @@ var checkHook = (opts, runtime) => { title, "warn", `installed at ${path2}, but the stub is out of date \u2014 it predates a change to how the hook finds the CLI; ${targetDetail}`, - install + install, + false, + void 0, + { evidence: hookEvidence } ); } const problems = [ @@ -17449,12 +17561,45 @@ var checkHook = (opts, runtime) => { install, false, false, - { skipReason: runtime.skipReason ?? "nothing_applicable" } + { + evidence: { ...hookEvidence, runtime_status: runtime.status }, + skipReason: runtime.skipReason ?? "nothing_applicable" + } ); } - return check(id, category, title, runtime.status, inherited, install); + return check( + id, + category, + title, + runtime.status, + inherited, + install, + false, + void 0, + { evidence: { ...hookEvidence, runtime_status: runtime.status } } + ); } - return problems.length === 0 ? check(id, category, title, "ok", `installed at ${path2}; ${targetDetail}`) : check(id, category, title, "warn", `installed at ${path2}; ${targetDetail}; ${problems.join("; ")}`, install); + return problems.length === 0 ? check( + id, + category, + title, + "ok", + `installed at ${path2}; ${targetDetail}`, + null, + false, + void 0, + { evidence: hookEvidence } + ) : check( + id, + category, + title, + "warn", + `installed at ${path2}; ${targetDetail}; ${problems.join("; ")}`, + install, + false, + void 0, + { evidence: hookEvidence } + ); }; var checkGit = (opts) => { const title = "git interpret-trailers"; @@ -17467,13 +17612,43 @@ var checkGit = (opts) => { trailers = parseCommitMessage(PROBE_MESSAGE); } catch (error2) { const reason = error2 instanceof Error ? error2.message : String(error2); - return check(id, category, title, "fail", `${version2 || "git"} could not parse a probe: ${reason}`, upgrade); + return check( + id, + category, + title, + "fail", + `${version2 || "git"} could not parse a probe: ${reason}`, + upgrade, + false, + void 0, + { evidence: { git_version: version2 || "unavailable", parsed: "unavailable" } } + ); } const parsed = trailers.map((trailer) => `${trailer.key}: ${trailer.value}`).join(", "); if (parsed !== "Limit: probe, Blast: local") { - return check(id, category, title, "fail", `${version2} parsed the probe as [${parsed}]`, upgrade); + return check( + id, + category, + title, + "fail", + `${version2} parsed the probe as [${parsed}]`, + upgrade, + false, + void 0, + { evidence: { git_version: version2 || "unavailable", parsed } } + ); } - return check(id, category, title, "ok", `${version2} parses trailers as the spec expects`); + return check( + id, + category, + title, + "ok", + `${version2} parses trailers as the spec expects`, + null, + false, + void 0, + { evidence: { git_version: version2 || "unavailable", parsed } } + ); }; var checkRuntime = (opts) => { const title = "cli runtime"; @@ -17488,7 +17663,16 @@ var checkRuntime = (opts) => { title, "fail", `no built CLI at ${candidates.join(" or ")} \u2014 this checkout has not been built`, - "npm install && npm run build" + "npm install && npm run build", + false, + void 0, + { + evidence: { + entry: candidates.join(" or "), + exit_code: "not_run", + ...streamEvidence("stderr", "") + } + } ); } const run = spawnSync3(process.execPath, [entry, "--version"], { @@ -17497,13 +17681,62 @@ var checkRuntime = (opts) => { ...gitOptions3(opts) }); if (run.error !== void 0) { - return check(id, category, title, "fail", `could not run ${entry}: ${run.error.message}`, null); + return check( + id, + category, + title, + "fail", + `could not run ${entry}: ${run.error.message}`, + null, + false, + void 0, + { + evidence: { + entry, + exit_code: String(run.status ?? "unavailable"), + error: run.error.message, + ...streamEvidence("stderr", run.stderr) + } + } + ); } if (run.status !== 0) { const detail = `${run.stderr ?? ""}`.trim().split("\n")[0] ?? `exit ${String(run.status)}`; - return check(id, category, title, "fail", `${entry} exits ${String(run.status)}: ${detail}`, "npm install"); + return check( + id, + category, + title, + "fail", + `${entry} exits ${String(run.status)}: ${detail}`, + "npm install", + false, + void 0, + { + evidence: { + entry, + exit_code: String(run.status), + ...streamEvidence("stderr", run.stderr) + } + } + ); } - return check(id, category, title, "ok", `${entry} runs (${run.stdout.trim()})`); + return check( + id, + category, + title, + "ok", + `${entry} runs (${run.stdout.trim()})`, + null, + false, + void 0, + { + evidence: { + entry, + version: boundedExcerpt(run.stdout).firstLine, + ...streamEvidence("stdout", run.stdout) + } + } + ); }; var checkHookRuntime = (opts) => { const title = "hook runtime"; @@ -17512,9 +17745,39 @@ var checkHookRuntime = (opts) => { const fix = "commitlore hooks install"; const cwd = opts.cwd ?? process.cwd(); const located = execGit(["rev-parse", "--git-path", "hooks/commit-msg"], gitOptions3(opts)); - if (located.code !== 0) return check(id, category, title, "warn", "not inside a git repository", fix); + if (located.code !== 0) { + return check( + id, + category, + title, + "warn", + "not inside a git repository", + fix, + false, + void 0, + { + evidence: { + hook_path: "unavailable", + exit_code: String(located.code), + ...streamEvidence("stderr", located.stderr) + } + } + ); + } const hook = resolve6(cwd, located.stdout.trim()); - if (!existsSync7(hook)) return check(id, category, title, "ok", "no hook installed \u2014 nothing to run"); + if (!existsSync7(hook)) { + return check( + id, + category, + title, + "ok", + "no hook installed \u2014 nothing to run", + null, + false, + void 0, + { evidence: { hook_path: hook } } + ); + } const probe = join6(tmpdirPath(), `commitlore-doctor-${String(process.pid)}.txt`); try { writeFileSync5(probe, PROBE_MESSAGE); @@ -17527,7 +17790,24 @@ var checkHookRuntime = (opts) => { env: { PATH: "/usr/bin:/bin", HOME: process.env["HOME"] ?? "" } }); if (run.error !== void 0) { - return check(id, category, title, "fail", `could not run the hook: ${run.error.message}`, fix); + return check( + id, + category, + title, + "fail", + `could not run the hook: ${run.error.message}`, + fix, + false, + void 0, + { + evidence: { + hook_path: hook, + exit_code: String(run.status ?? "unavailable"), + error: run.error.message, + ...streamEvidence("stderr", run.stderr) + } + } + ); } if (run.status !== 0) { const said = `${run.stderr ?? ""}`.trim().split("\n")[0] ?? ""; @@ -17541,9 +17821,35 @@ var checkHookRuntime = (opts) => { } else { detail = `the hook exited ${String(run.status)} under the restricted PATH \u2014 cause unclear: ${said || "no output"}`; } - return check(id, category, title, "fail", detail, fix); + return check( + id, + category, + title, + "fail", + detail, + fix, + false, + void 0, + { + evidence: { + hook_path: hook, + exit_code: String(run.status), + ...streamEvidence("stderr", run.stderr) + } + } + ); } - return check(id, category, title, "ok", "the hook runs and validates without node on PATH"); + return check( + id, + category, + title, + "ok", + "the hook runs and validates without node on PATH", + null, + false, + void 0, + { evidence: { hook_path: hook, exit_code: "0" } } + ); } catch (error2) { return check( id, @@ -17551,7 +17857,17 @@ var checkHookRuntime = (opts) => { title, "warn", `could not probe the hook: ${error2 instanceof Error ? error2.message : String(error2)}`, - fix + fix, + false, + void 0, + { + evidence: { + hook_path: hook, + exit_code: "unavailable", + error: error2 instanceof Error ? error2.message : String(error2), + ...streamEvidence("stderr", "") + } + } ); } finally { rmSync2(probe, { force: true }); @@ -17559,6 +17875,7 @@ var checkHookRuntime = (opts) => { }; var evaluateInjectRun = (run, ctx) => { const { id, category, title, executable, path: path2, fix, unavailableFix } = ctx; + const executionEvidence = { executable, path: path2 }; if (run.status === null || run.status === void 0) { if (run.error !== void 0 && "code" in run.error && run.error.code === "ENOENT") { return check( @@ -17567,7 +17884,16 @@ var evaluateInjectRun = (run, ctx) => { title, "fail", `configured PreToolUse hook executable ${JSON.stringify(executable)} is not resolvable from PATH`, - unavailableFix + unavailableFix, + false, + void 0, + { + evidence: { + ...executionEvidence, + exit_code: "unavailable", + ...streamEvidence("stderr", run.stderr) + } + } ); } return check( @@ -17576,7 +17902,17 @@ var evaluateInjectRun = (run, ctx) => { title, "fail", `could not run the PreToolUse hook: ${run.error?.message ?? "no diagnosis"}`, - fix + fix, + false, + void 0, + { + evidence: { + ...executionEvidence, + exit_code: "unavailable", + error: run.error?.message ?? "no diagnosis", + ...streamEvidence("stderr", run.stderr) + } + } ); } if (run.status !== 0) { @@ -17587,7 +17923,16 @@ var evaluateInjectRun = (run, ctx) => { title, "fail", `the PreToolUse hook exits ${String(run.status)}: ${said || "no diagnosis"}`, - fix + fix, + false, + void 0, + { + evidence: { + ...executionEvidence, + exit_code: String(run.status), + ...streamEvidence("stderr", run.stderr) + } + } ); } if (`${run.stdout ?? ""}`.trim() === "") { @@ -17598,10 +17943,36 @@ var evaluateInjectRun = (run, ctx) => { title, "fail", `the PreToolUse hook returned no context for a known-good payload${said === "" ? "" : `: ${said}`}`, - fix + fix, + false, + void 0, + { + evidence: { + ...executionEvidence, + exit_code: "0", + ...streamEvidence("stdout", run.stdout), + ...streamEvidence("stderr", run.stderr) + } + } ); } - return check(id, category, title, "ok", `the PreToolUse hook returned context for ${path2}`); + return check( + id, + category, + title, + "ok", + `the PreToolUse hook returned context for ${path2}`, + null, + false, + void 0, + { + evidence: { + ...executionEvidence, + exit_code: "0", + ...streamEvidence("stdout", run.stdout) + } + } + ); }; var checkInjectRuntime = (opts) => { const title = "PreToolUse hook runtime"; @@ -17623,19 +17994,88 @@ var checkInjectRuntime = (opts) => { null, false, false, - { skipReason: "command_unrecognized" } + { + evidence: { + settings_path: settings.settingsPath, + settings_state: settings.state, + configured_command: command2, + executable: "not_run", + exit_code: "not_run", + ...streamEvidence("stderr", "") + }, + skipReason: "command_unrecognized" + } ); } const detail = settings.state === "absent" ? `not installed in ${settings.settingsPath}` : `${settings.state} in ${settings.settingsPath}${settings.problem === void 0 ? "" : `: ${settings.problem}`}`; - return check(id, category, title, "warn", detail, "commitlore inject install-claude-hook"); + return check( + id, + category, + title, + "warn", + detail, + "commitlore inject install-claude-hook", + false, + void 0, + { + evidence: { + settings_path: settings.settingsPath, + settings_state: settings.state, + executable: "not_run", + exit_code: "not_run", + ...streamEvidence("stderr", ""), + ...settings.problem === void 0 ? {} : { problem: settings.problem } + } + } + ); } const command = settings.commands[0]; if (command !== CLAUDE_HOOK_COMMAND) { - return check(id, category, title, "skipped", "not checked: the configured command is not recognised", null, false, false, { skipReason: "command_unrecognized" }); + return check( + id, + category, + title, + "skipped", + "not checked: the configured command is not recognised", + null, + false, + false, + { + evidence: { + settings_path: settings.settingsPath, + settings_state: settings.state, + configured_command: command ?? "none", + executable: "not_run", + exit_code: "not_run", + ...streamEvidence("stderr", "") + }, + skipReason: "command_unrecognized" + } + ); } const path2 = runQuery({ cwd, noIndex: true }).records.flatMap((record2) => record2.paths).find((candidate) => candidate !== "" && candidate !== "."); if (path2 === void 0) { - return check(id, category, title, "skipped", "no recorded path is available for a runtime probe", null, false, false, { skipReason: "probe_path_unavailable" }); + return check( + id, + category, + title, + "skipped", + "no recorded path is available for a runtime probe", + null, + false, + false, + { + evidence: { + settings_path: settings.settingsPath, + settings_state: settings.state, + executable: "not_run", + probe_path: "unavailable", + exit_code: "not_run", + ...streamEvidence("stderr", "") + }, + skipReason: "probe_path_unavailable" + } + ); } const payload = JSON.stringify({ session_id: "commitlore-doctor", @@ -17672,11 +18112,42 @@ var checkInjectVersion = (opts) => { const mine = packageVersion(); const settings = readClaudeHookStatus(claudeSettingsPath(cwd)); if (settings.state !== "installed") { - return check(id, category, title, "skipped", `no installed hook to compare against ${mine}`, null, false, false, { skipReason: "hook_not_installed" }); + return check( + id, + category, + title, + "skipped", + `no installed hook to compare against ${mine}`, + null, + false, + false, + { + evidence: { executable: "not_run", theirs: "not_run", mine }, + skipReason: "hook_not_installed" + } + ); } const command = settings.commands[0]; if (command !== CLAUDE_HOOK_COMMAND) { - return check(id, category, title, "skipped", "not checked: the configured command is not recognised", null, false, false, { skipReason: "command_unrecognized" }); + return check( + id, + category, + title, + "skipped", + "not checked: the configured command is not recognised", + null, + false, + false, + { + evidence: { + executable: "not_run", + theirs: "not_run", + mine, + configured_command: command ?? "none" + }, + skipReason: "command_unrecognized" + } + ); } const configured = command.replace(` ${CLAUDE_HOOK_MARKER}`, ""); const executable = configured.slice(0, configured.indexOf(" ")); @@ -17689,8 +18160,26 @@ var checkInjectVersion = (opts) => { HOME: process.env["HOME"] ?? "" } }); + const reported = typeof run.stdout === "string" ? run.stdout : ""; + const versionEvidence = { + executable, + theirs: boundedExcerpt(reported).firstLine || "unavailable", + mine, + exit_code: String(run.status ?? "unavailable"), + ...streamEvidence("stdout", reported) + }; if (run.status !== 0 || typeof run.stdout !== "string") { - return check(id, category, title, "skipped", `${executable} did not report a version`, null, false, false, { skipReason: "version_unreadable" }); + return check( + id, + category, + title, + "skipped", + `${executable} did not report a version`, + null, + false, + false, + { evidence: versionEvidence, skipReason: "version_unreadable" } + ); } const theirs = run.stdout.trim(); if (!SEMVER_ISH.test(theirs)) { @@ -17703,11 +18192,21 @@ var checkInjectVersion = (opts) => { null, false, false, - { skipReason: "version_unreadable" } + { evidence: versionEvidence, skipReason: "version_unreadable" } ); } if (theirs === mine) { - return check(id, category, title, "ok", `the hook runs ${theirs}, the same build as this CLI`); + return check( + id, + category, + title, + "ok", + `the hook runs ${theirs}, the same build as this CLI`, + null, + false, + void 0, + { evidence: versionEvidence } + ); } return check( id, @@ -17715,7 +18214,10 @@ var checkInjectVersion = (opts) => { title, "warn", `the agent's hook runs ${theirs} but this CLI is ${mine} \u2014 every edit is graded by ${theirs}'s rules, not this one's`, - "update the installation the hook resolves to (for the plugin: /plugin marketplace update commitlore), then rerun: commitlore doctor" + "update the installation the hook resolves to (for the plugin: /plugin marketplace update commitlore), then rerun: commitlore doctor", + false, + void 0, + { evidence: versionEvidence } ); }; var checkMcpLifecycle = (opts) => { @@ -17725,7 +18227,17 @@ var checkMcpLifecycle = (opts) => { const cwd = opts.cwd ?? process.cwd(); const unfinished = unfinishedRuns(cwd); if (unfinished.length === 0) { - return check(id, category, title, "ok", "every recorded MCP session ended cleanly, or is still running"); + return check( + id, + category, + title, + "ok", + "every recorded MCP session ended cleanly, or is still running", + null, + false, + void 0, + { evidence: { unfinished_count: "0", last_pid: "none", last_at: "none" } } + ); } const last = unfinished[unfinished.length - 1]; return check( @@ -17734,7 +18246,16 @@ var checkMcpLifecycle = (opts) => { title, "warn", `${unfinished.length} MCP server session(s) started here and never recorded an exit \u2014 most recently pid ${String(last?.pid ?? 0)} at ${last?.at ?? "unknown"}. A killed server loses its tool registration in the client, which reports the same as a tool that never existed (#424)`, - "restart the client session; if this repeats, capture it with a client started under --debug" + "restart the client session; if this repeats, capture it with a client started under --debug", + false, + void 0, + { + evidence: { + unfinished_count: String(unfinished.length), + last_pid: String(last?.pid ?? 0), + last_at: last?.at ?? "unknown" + } + } ); }; var checkPendingBacklog = (opts) => { @@ -17746,7 +18267,17 @@ var checkPendingBacklog = (opts) => { try { listing = runPendingList({ cwd }); } catch { - return check(id, category, title, "ok", "no pending directory \u2014 nothing has been captured here yet"); + return check( + id, + category, + title, + "ok", + "no pending directory \u2014 nothing has been captured here yet", + null, + false, + void 0, + { evidence: { stranded: "0", staged_expired: "0", oldest: "none" } } + ); } if (listing.unreadable.length > 0) { return check( @@ -17755,7 +18286,17 @@ var checkPendingBacklog = (opts) => { title, "warn", `${listing.unreadable.length} pending file(s) cannot be read as a transaction`, - "commitlore pending ls" + "commitlore pending ls", + false, + void 0, + { + evidence: { + stranded: "0", + staged_expired: "0", + oldest: "none", + unreadable: String(listing.unreadable.length) + } + } ); } const stranded = listing.transactions.filter((transaction) => transaction.stale); @@ -17766,7 +18307,18 @@ var checkPendingBacklog = (opts) => { category, title, "ok", - held === 0 ? "no captures are waiting" : `${String(held)} capture(s) waiting, all still able to apply` + held === 0 ? "no captures are waiting" : `${String(held)} capture(s) waiting, all still able to apply`, + null, + false, + void 0, + { + evidence: { + stranded: "0", + staged_expired: "0", + oldest: "none", + waiting: String(held) + } + } ); } const lost = stranded.filter((transaction) => transaction.phase === "staged"); @@ -17778,7 +18330,16 @@ var checkPendingBacklog = (opts) => { title, "warn", `${detail}; oldest from ${oldest ?? "an unknown time"}. A staged record binds to the tree it was prepared for and is skipped once that tree moves, so these decisions were never written to the history (#458)`, - "commitlore pending ls" + "commitlore pending ls", + false, + void 0, + { + evidence: { + stranded: String(stranded.length), + staged_expired: String(lost.length), + oldest: oldest ?? "unknown" + } + } ); }; var checkIndex = (opts) => { @@ -17793,7 +18354,18 @@ var checkIndex = (opts) => { "index health", "warn", "no index yet \u2014 queries fall back to scanning the history", - "commitlore index --rebuild" + "commitlore index --rebuild", + false, + void 0, + { + evidence: { + trailers: "0", + commits: "0", + last_indexed_sha: "none", + head_sha: "not_queried", + fts: "unavailable" + } + } ); } try { @@ -17801,19 +18373,33 @@ var checkIndex = (opts) => { const head = execGit(["rev-parse", "HEAD"], gitOptions3(opts)); const behind = head.code === 0 && info.lastIndexedSha !== head.stdout.trim(); const fts = info.fts ? "FTS5" : "no FTS5 (value search falls back to LIKE)"; + const indexEvidence = { + trailers: String(info.trailers), + commits: String(info.commits), + last_indexed_sha: info.lastIndexedSha || "none", + head_sha: head.code === 0 ? head.stdout.trim() || "none" : "unavailable", + fts: info.fts ? "true" : "false" + }; return behind ? check( "index-health", "index", "index health", "warn", `${info.trailers} trailers over ${info.commits} commits, behind HEAD \u2014 ${fts}`, - "commitlore index" + "commitlore index", + false, + void 0, + { evidence: indexEvidence } ) : check( "index-health", "index", "index health", "ok", - `${info.trailers} trailers over ${info.commits} commits, current with HEAD \u2014 ${fts}` + `${info.trailers} trailers over ${info.commits} commits, current with HEAD \u2014 ${fts}`, + null, + false, + void 0, + { evidence: indexEvidence } ); } catch (error2) { return check( @@ -17822,7 +18408,18 @@ var checkIndex = (opts) => { "index health", "warn", `index unreadable (${error2 instanceof Error ? error2.message : String(error2)}) \u2014 queries still work without it`, - "commitlore index --rebuild" + "commitlore index --rebuild", + false, + void 0, + { + evidence: { + trailers: "unavailable", + commits: "unavailable", + last_indexed_sha: "unavailable", + head_sha: "unavailable", + fts: "unavailable" + } + } ); } finally { try { @@ -17837,8 +18434,21 @@ var checkHistoryDepth = (opts) => hasShallowHistory(opts.cwd ?? process.cwd()) ? "history depth", "warn", "this clone has shallow history, so queries may be missing records that exist upstream", - "git fetch --unshallow" -) : check("history-depth", "history", "history depth", "ok", "full history is available"); + "git fetch --unshallow", + false, + void 0, + { evidence: { shallow: "true" } } +) : check( + "history-depth", + "history", + "history depth", + "ok", + "full history is available", + null, + false, + void 0, + { evidence: { shallow: "false" } } +); var MAX_SQUASH_CANDIDATE_BRANCHES = 200; var squashCandidates = (opts, head) => { const listed = execGit( @@ -17870,7 +18480,20 @@ var checkSquashConservation = (opts) => { const cwd = opts.cwd ?? process.cwd(); const head = execGit(["rev-parse", "--verify", "--quiet", "HEAD"], gitOptions3(opts)); if (head.code !== 0) { - return check(id, category, title, "skipped", "no HEAD yet \u2014 nothing to compare against", null, false, false, { skipReason: "unborn_head" }); + return check( + id, + category, + title, + "skipped", + "no HEAD yet \u2014 nothing to compare against", + null, + false, + false, + { + evidence: { candidates: "0", checked: "0", uncheckable: "0", lost_count: "0" }, + skipReason: "unborn_head" + } + ); } const candidates = squashCandidates(opts, head.stdout.trim()); if (candidates.length === 0) { @@ -17883,7 +18506,10 @@ var checkSquashConservation = (opts) => { null, false, false, - { skipReason: "nothing_applicable" } + { + evidence: { candidates: "0", checked: "0", uncheckable: "0", lost_count: "0" }, + skipReason: "nothing_applicable" + } ); } let known = null; @@ -17925,7 +18551,15 @@ var checkSquashConservation = (opts) => { null, false, false, - { skipReason: "nothing_applicable" } + { + evidence: { + candidates: String(candidates.length), + checked: "0", + uncheckable: String(uncheckable), + lost_count: "0" + }, + skipReason: "nothing_applicable" + } ); } if (lost.length > 0) { @@ -17937,11 +18571,38 @@ var checkSquashConservation = (opts) => { title, "warn", `${lost.length} record(s) declared on a branch not reachable from HEAD do not appear in HEAD's history: ${named}${more}`, - "commitlore squash-preserve .. --target , then commit or attach the result" + "commitlore squash-preserve .. --target , then commit or attach the result", + false, + void 0, + { + evidence: { + candidates: String(candidates.length), + checked: String(checked), + uncheckable: String(uncheckable), + lost_count: String(lost.length) + } + } ); } const detail = uncheckable > 0 ? `${checked} squash-shaped branch(es) checked, every declared Record-Id is reachable from HEAD (${uncheckable} branch(es) recorded nothing with an id and could not be checked this way)` : `${checked} squash-shaped branch(es) checked, every declared Record-Id is reachable from HEAD`; - return check(id, category, title, "ok", detail); + return check( + id, + category, + title, + "ok", + detail, + null, + false, + void 0, + { + evidence: { + candidates: String(candidates.length), + checked: String(checked), + uncheckable: String(uncheckable), + lost_count: "0" + } + } + ); }; var hookRuntimeOf = (ctx) => { const cached2 = ctx.memo.get("hook-runtime"); diff --git a/src/commands/doctor.ts b/src/commands/doctor.ts index b8ce245..012c291 100644 --- a/src/commands/doctor.ts +++ b/src/commands/doctor.ts @@ -115,9 +115,8 @@ export interface DoctorCheck { /** Derived from `status`; never passed in, never read by the exit code. */ severity: Severity; /** - * The observation behind the conclusion. Populated per check by a later - * ticket; `{}` until then, so an absent field never has to be told apart - * from an empty one. + * The observation behind the conclusion. A row without one cannot explain + * why its status is trustworthy, so construction rejects empty evidence. */ evidence: Record; /** No shipping check is optional at introduction (PRD §1.4). */ @@ -162,6 +161,45 @@ const escapeConfigValuePattern = (value: string): string => const gitOptions = (opts: DoctorOptions) => (opts.cwd === undefined ? {} : { cwd: opts.cwd }); +/** The bound keeps a broken child process from making a JSON report unbounded. */ +const boundedExcerpt = (output: string | null | undefined): { + firstLine: string; + truncated: 'true' | 'false'; +} => { + const [firstLine = ''] = (output ?? '').split(/\r?\n/, 1); + return { + firstLine: firstLine.slice(0, 200), + truncated: firstLine.length > 200 ? 'true' : 'false', + }; +}; + +const streamEvidence = (stream: string, output: string | null | undefined): Record => { + const excerpt = boundedExcerpt(output); + return { + [`${stream}_first_line`]: excerpt.firstLine, + [`${stream}_truncated`]: excerpt.truncated, + }; +}; + +/** Reports keep paths useful in bug reports without carrying a user's home directory. */ +const homeRelativePath = (value: string): string => { + const home = process.env['HOME']; + if (home === undefined || home === '') return value; + const escapedHome = home.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + return value.replace(new RegExp(`${escapedHome}(?=$|/)`, 'g'), '~'); +}; + +const normaliseEvidence = (evidence: Record): Record => + Object.fromEntries( + Object.entries(evidence).map(([key, value]) => [key, homeRelativePath(value)]), + ); + +const evidenceKey = (value: string): string => + value + .replace(/[^A-Za-z0-9]+/g, '_') + .replace(/^_+|_+$/g, '') + .toLowerCase() || 'remote'; + /** * `severity` as a total function of `status` — the only place it is decided. * @@ -228,18 +266,22 @@ function check( needsAttention = status === 'warn' || status === 'fail', extra: CheckExtra = {}, ): DoctorCheck { + const evidence = extra.evidence ?? {}; + if (Object.keys(evidence).length === 0) { + throw new Error(`doctor check ${id} has no evidence`); + } return { - id, - title, - status, - needsAttention, - detail, - fix, - fixed, - category, - severity: severityOf(status), - evidence: extra.evidence ?? {}, - optional: extra.optional ?? false, + id, + title, + status, + needsAttention, + detail, + fix, + fixed, + category, + severity: severityOf(status), + evidence: normaliseEvidence(evidence), + optional: extra.optional ?? false, ...(extra.skipReason === undefined ? {} : { skipReason: extra.skipReason }), }; } @@ -247,6 +289,7 @@ function check( const checkRefspec = (opts: DoctorOptions): DoctorCheck => { const title = 'notes fetch refspec'; const remotes = listRemotes(opts); + const remoteEvidence = { remotes: remotes.join(', ') || 'none' }; if (remotes.length === 0) { return check( @@ -257,6 +300,7 @@ const checkRefspec = (opts: DoctorOptions): DoctorCheck => { 'add a remote, then rerun: commitlore doctor --fix', false, false, + { evidence: remoteEvidence }, ); } @@ -305,6 +349,8 @@ const checkRefspec = (opts: DoctorOptions): DoctorCheck => { .map((remote) => `git config --replace-all remote.${remote}.fetch '${NOTES_REFSPEC}' '^\\+refs/notes/'`) .join('\n'), fixed, + undefined, + { evidence: { ...remoteEvidence, forced: forced.join(', ') } }, ); } @@ -315,6 +361,9 @@ const checkRefspec = (opts: DoctorOptions): DoctorCheck => { 'warn', `${missing.join(', ')} does not fetch ${NOTES_REF}, so records pushed by others stay invisible here`, missing.map((remote) => `git config --add remote.${remote}.fetch '${NOTES_REFSPEC}'`).join('\n'), + false, + undefined, + { evidence: { ...remoteEvidence, missing: missing.join(', ') } }, ); } @@ -331,6 +380,18 @@ const checkRefspec = (opts: DoctorOptions): DoctorCheck => { .join('; ')})`, failed.map(({ remote }) => `git fetch ${remote}`).join('\n'), fixed, + undefined, + { + evidence: { + ...remoteEvidence, + ...Object.fromEntries( + failed.map(({ remote, result }) => [ + `fetch_exit_code_${evidenceKey(remote)}`, + String(result.code), + ]), + ), + }, + }, ); } @@ -348,6 +409,8 @@ const checkRefspec = (opts: DoctorOptions): DoctorCheck => { : `git fetch succeeds for ${remotes.join(', ')} and covers ${NOTES_REF}`, fixed ? `git fetch ${remotes[0] ?? 'origin'}` : null, fixed, + undefined, + { evidence: remoteEvidence }, ); }; @@ -361,6 +424,10 @@ const checkPush = (opts: DoctorOptions): DoctorCheck => { const remote = remotes[0] ?? 'origin'; const command = `git push ${remote} ${NOTES_REF}`; const local = execGit(['rev-parse', '--verify', '--quiet', NOTES_REF], gitOptions(opts)); + const localEvidence = { + remote, + local_sha: local.code === 0 ? local.stdout.trim() || 'unknown' : 'none', + }; if (local.code !== 0) { return check( @@ -368,6 +435,10 @@ const checkPush = (opts: DoctorOptions): DoctorCheck => { title, 'ok', `no local mirror yet — nothing to push (${command}, once there is)`, + null, + false, + undefined, + { evidence: { ...localEvidence, remote_sha: 'not_queried' } }, ); } @@ -379,10 +450,30 @@ const checkPush = (opts: DoctorOptions): DoctorCheck => { 'warn', `could not verify (${remote}: ${advertised.stderr.trim().split('\n')[0] ?? 'git ls-remote failed'})`, command, + false, + undefined, + { + evidence: { + ...localEvidence, + ls_remote_exit_code: String(advertised.code), + ...streamEvidence('ls_remote_stderr', advertised.stderr), + }, + }, ); } - if (advertised.stdout.split(/\s/)[0] === local.stdout.trim()) { - return check('notes-push', 'transport', title, 'ok', `${remote} has the current ${NOTES_REF}`); + const remoteSha = advertised.stdout.split(/\s/)[0] ?? ''; + if (remoteSha === local.stdout.trim()) { + return check( + 'notes-push', + 'transport', + title, + 'ok', + `${remote} has the current ${NOTES_REF}`, + null, + false, + undefined, + { evidence: { ...localEvidence, remote_sha: remoteSha || 'none' } }, + ); } return check( @@ -391,6 +482,9 @@ const checkPush = (opts: DoctorOptions): DoctorCheck => { 'warn', `this clone has local records in ${NOTES_REF}; no command pushes them for you`, command, + false, + undefined, + { evidence: { ...localEvidence, remote_sha: remoteSha || 'none' } }, ); }; @@ -410,18 +504,44 @@ const checkHook = (opts: DoctorOptions, runtime: DoctorCheck): DoctorCheck => { // somewhere else entirely. const located = execGit(['rev-parse', '--git-path', 'hooks/commit-msg'], gitOptions(opts)); if (located.code !== 0) { - return check(id, category, title, 'warn', 'not inside a git repository', install); + return check( + id, + category, + title, + 'warn', + 'not inside a git repository', + install, + false, + undefined, + { evidence: { hook_path: 'unavailable', bin: 'not_recorded', node: 'not_recorded' } }, + ); } const path = resolve(opts.cwd ?? process.cwd(), located.stdout.trim()); const target = readRecordedHookTarget(opts.cwd ?? process.cwd()); const override = process.env['COMMITLORE_BIN']; + const hookEvidence = { + hook_path: path, + bin: target.bin || '(unset)', + node: target.node || '(unset)', + ...(override === undefined || override === '' ? {} : { commitlore_bin_override: override }), + }; const targetDetail = [ ...describeRecordedHookTarget(target), ...(override === undefined || override === '' ? [] : [`COMMITLORE_BIN: ${override}`]), ].join('; '); if (!existsSync(path)) { - return check(id, category, title, 'warn', `no commit-msg hook at ${path}; ${targetDetail}`, install); + return check( + id, + category, + title, + 'warn', + `no commit-msg hook at ${path}; ${targetDetail}`, + install, + false, + undefined, + { evidence: hookEvidence }, + ); } const contents = readFileSync(path, 'utf8'); @@ -433,6 +553,9 @@ const checkHook = (opts: DoctorOptions, runtime: DoctorCheck): DoctorCheck => { 'warn', `a commit-msg hook exists at ${path} but does not invoke commitlore; ${targetDetail}`, install, + false, + undefined, + { evidence: hookEvidence }, ); } @@ -448,6 +571,9 @@ const checkHook = (opts: DoctorOptions, runtime: DoctorCheck): DoctorCheck => { 'warn', `installed at ${path}, but the stub is out of date — it predates a change to how the hook finds the CLI; ${targetDetail}`, install, + false, + undefined, + { evidence: hookEvidence }, ); } @@ -480,14 +606,47 @@ const checkHook = (opts: DoctorOptions, runtime: DoctorCheck): DoctorCheck => { install, false, false, - { skipReason: runtime.skipReason ?? 'nothing_applicable' }, + { + evidence: { ...hookEvidence, runtime_status: runtime.status }, + skipReason: runtime.skipReason ?? 'nothing_applicable', + }, ); } - return check(id, category, title, runtime.status, inherited, install); + return check( + id, + category, + title, + runtime.status, + inherited, + install, + false, + undefined, + { evidence: { ...hookEvidence, runtime_status: runtime.status } }, + ); } return problems.length === 0 - ? check(id, category, title, 'ok', `installed at ${path}; ${targetDetail}`) - : check(id, category, title, 'warn', `installed at ${path}; ${targetDetail}; ${problems.join('; ')}`, install); + ? check( + id, + category, + title, + 'ok', + `installed at ${path}; ${targetDetail}`, + null, + false, + undefined, + { evidence: hookEvidence }, + ) + : check( + id, + category, + title, + 'warn', + `installed at ${path}; ${targetDetail}; ${problems.join('; ')}`, + install, + false, + undefined, + { evidence: hookEvidence }, + ); }; /** @@ -511,15 +670,45 @@ const checkGit = (opts: DoctorOptions): DoctorCheck => { trailers = parseCommitMessage(PROBE_MESSAGE); } catch (error) { const reason = error instanceof Error ? error.message : String(error); - return check(id, category, title, 'fail', `${version || 'git'} could not parse a probe: ${reason}`, upgrade); + return check( + id, + category, + title, + 'fail', + `${version || 'git'} could not parse a probe: ${reason}`, + upgrade, + false, + undefined, + { evidence: { git_version: version || 'unavailable', parsed: 'unavailable' } }, + ); } const parsed = trailers.map((trailer) => `${trailer.key}: ${trailer.value}`).join(', '); if (parsed !== 'Limit: probe, Blast: local') { - return check(id, category, title, 'fail', `${version} parsed the probe as [${parsed}]`, upgrade); + return check( + id, + category, + title, + 'fail', + `${version} parsed the probe as [${parsed}]`, + upgrade, + false, + undefined, + { evidence: { git_version: version || 'unavailable', parsed } }, + ); } - return check(id, category, title, 'ok', `${version} parses trailers as the spec expects`); + return check( + id, + category, + title, + 'ok', + `${version} parses trailers as the spec expects`, + null, + false, + undefined, + { evidence: { git_version: version || 'unavailable', parsed } }, + ); }; /** @@ -560,6 +749,15 @@ const checkRuntime = (opts: DoctorOptions): DoctorCheck => { 'fail', `no built CLI at ${candidates.join(' or ')} — this checkout has not been built`, 'npm install && npm run build', + false, + undefined, + { + evidence: { + entry: candidates.join(' or '), + exit_code: 'not_run', + ...streamEvidence('stderr', ''), + }, + }, ); } @@ -570,14 +768,63 @@ const checkRuntime = (opts: DoctorOptions): DoctorCheck => { }); if (run.error !== undefined) { - return check(id, category, title, 'fail', `could not run ${entry}: ${run.error.message}`, null); + return check( + id, + category, + title, + 'fail', + `could not run ${entry}: ${run.error.message}`, + null, + false, + undefined, + { + evidence: { + entry, + exit_code: String(run.status ?? 'unavailable'), + error: run.error.message, + ...streamEvidence('stderr', run.stderr), + }, + }, + ); } if (run.status !== 0) { const detail = `${run.stderr ?? ''}`.trim().split('\n')[0] ?? `exit ${String(run.status)}`; - return check(id, category, title, 'fail', `${entry} exits ${String(run.status)}: ${detail}`, 'npm install'); + return check( + id, + category, + title, + 'fail', + `${entry} exits ${String(run.status)}: ${detail}`, + 'npm install', + false, + undefined, + { + evidence: { + entry, + exit_code: String(run.status), + ...streamEvidence('stderr', run.stderr), + }, + }, + ); } - return check(id, category, title, 'ok', `${entry} runs (${run.stdout.trim()})`); + return check( + id, + category, + title, + 'ok', + `${entry} runs (${run.stdout.trim()})`, + null, + false, + undefined, + { + evidence: { + entry, + version: boundedExcerpt(run.stdout).firstLine, + ...streamEvidence('stdout', run.stdout), + }, + }, + ); }; /** @@ -607,12 +854,42 @@ const checkHookRuntime = (opts: DoctorOptions): DoctorCheck => { const cwd = opts.cwd ?? process.cwd(); const located = execGit(['rev-parse', '--git-path', 'hooks/commit-msg'], gitOptions(opts)); - if (located.code !== 0) return check(id, category, title, 'warn', 'not inside a git repository', fix); + if (located.code !== 0) { + return check( + id, + category, + title, + 'warn', + 'not inside a git repository', + fix, + false, + undefined, + { + evidence: { + hook_path: 'unavailable', + exit_code: String(located.code), + ...streamEvidence('stderr', located.stderr), + }, + }, + ); + } const hook = resolve(cwd, located.stdout.trim()); // The hook's absence is `checkHook`'s finding; saying it twice teaches the // reader to skim both. - if (!existsSync(hook)) return check(id, category, title, 'ok', 'no hook installed — nothing to run'); + if (!existsSync(hook)) { + return check( + id, + category, + title, + 'ok', + 'no hook installed — nothing to run', + null, + false, + undefined, + { evidence: { hook_path: hook } }, + ); + } const probe = join(tmpdirPath(), `commitlore-doctor-${String(process.pid)}.txt`); try { @@ -627,7 +904,24 @@ const checkHookRuntime = (opts: DoctorOptions): DoctorCheck => { }); if (run.error !== undefined) { - return check(id, category, title, 'fail', `could not run the hook: ${run.error.message}`, fix); + return check( + id, + category, + title, + 'fail', + `could not run the hook: ${run.error.message}`, + fix, + false, + undefined, + { + evidence: { + hook_path: hook, + exit_code: String(run.status ?? 'unavailable'), + error: run.error.message, + ...streamEvidence('stderr', run.stderr), + }, + }, + ); } if (run.status !== 0) { const said = `${run.stderr ?? ''}`.trim().split('\n')[0] ?? ''; @@ -644,9 +938,35 @@ const checkHookRuntime = (opts: DoctorOptions): DoctorCheck => { } else { detail = `the hook exited ${String(run.status)} under the restricted PATH — cause unclear: ${said || 'no output'}`; } - return check(id, category, title, 'fail', detail, fix); + return check( + id, + category, + title, + 'fail', + detail, + fix, + false, + undefined, + { + evidence: { + hook_path: hook, + exit_code: String(run.status), + ...streamEvidence('stderr', run.stderr), + }, + }, + ); } - return check(id, category, title, 'ok', 'the hook runs and validates without node on PATH'); + return check( + id, + category, + title, + 'ok', + 'the hook runs and validates without node on PATH', + null, + false, + undefined, + { evidence: { hook_path: hook, exit_code: '0' } }, + ); } catch (error) { return check( id, @@ -655,6 +975,16 @@ const checkHookRuntime = (opts: DoctorOptions): DoctorCheck => { 'warn', `could not probe the hook: ${error instanceof Error ? error.message : String(error)}`, fix, + false, + undefined, + { + evidence: { + hook_path: hook, + exit_code: 'unavailable', + error: error instanceof Error ? error.message : String(error), + ...streamEvidence('stderr', ''), + }, + }, ); } finally { rmSync(probe, { force: true }); @@ -703,6 +1033,7 @@ export const evaluateInjectRun = ( }, ): DoctorCheck => { const { id, category, title, executable, path, fix, unavailableFix } = ctx; + const executionEvidence = { executable, path }; if (run.status === null || run.status === undefined) { if (run.error !== undefined && 'code' in run.error && run.error.code === 'ENOENT') { @@ -713,6 +1044,15 @@ export const evaluateInjectRun = ( 'fail', `configured PreToolUse hook executable ${JSON.stringify(executable)} is not resolvable from PATH`, unavailableFix, + false, + undefined, + { + evidence: { + ...executionEvidence, + exit_code: 'unavailable', + ...streamEvidence('stderr', run.stderr), + }, + }, ); } return check( @@ -722,6 +1062,16 @@ export const evaluateInjectRun = ( 'fail', `could not run the PreToolUse hook: ${run.error?.message ?? 'no diagnosis'}`, fix, + false, + undefined, + { + evidence: { + ...executionEvidence, + exit_code: 'unavailable', + error: run.error?.message ?? 'no diagnosis', + ...streamEvidence('stderr', run.stderr), + }, + }, ); } @@ -734,6 +1084,15 @@ export const evaluateInjectRun = ( 'fail', `the PreToolUse hook exits ${String(run.status)}: ${said || 'no diagnosis'}`, fix, + false, + undefined, + { + evidence: { + ...executionEvidence, + exit_code: String(run.status), + ...streamEvidence('stderr', run.stderr), + }, + }, ); } if (`${run.stdout ?? ''}`.trim() === '') { @@ -745,9 +1104,35 @@ export const evaluateInjectRun = ( 'fail', `the PreToolUse hook returned no context for a known-good payload${said === '' ? '' : `: ${said}`}`, fix, + false, + undefined, + { + evidence: { + ...executionEvidence, + exit_code: '0', + ...streamEvidence('stdout', run.stdout), + ...streamEvidence('stderr', run.stderr), + }, + }, ); } - return check(id, category, title, 'ok', `the PreToolUse hook returned context for ${path}`); + return check( + id, + category, + title, + 'ok', + `the PreToolUse hook returned context for ${path}`, + null, + false, + undefined, + { + evidence: { + ...executionEvidence, + exit_code: '0', + ...streamEvidence('stdout', run.stdout), + }, + }, + ); }; const checkInjectRuntime = (opts: DoctorOptions): DoctorCheck => { @@ -772,26 +1157,95 @@ const checkInjectRuntime = (opts: DoctorOptions): DoctorCheck => { null, false, false, - { skipReason: 'command_unrecognized' }, + { + evidence: { + settings_path: settings.settingsPath, + settings_state: settings.state, + configured_command: command, + executable: 'not_run', + exit_code: 'not_run', + ...streamEvidence('stderr', ''), + }, + skipReason: 'command_unrecognized', + }, ); } const detail = settings.state === 'absent' ? `not installed in ${settings.settingsPath}` : `${settings.state} in ${settings.settingsPath}${settings.problem === undefined ? '' : `: ${settings.problem}`}`; - return check(id, category, title, 'warn', detail, 'commitlore inject install-claude-hook'); + return check( + id, + category, + title, + 'warn', + detail, + 'commitlore inject install-claude-hook', + false, + undefined, + { + evidence: { + settings_path: settings.settingsPath, + settings_state: settings.state, + executable: 'not_run', + exit_code: 'not_run', + ...streamEvidence('stderr', ''), + ...(settings.problem === undefined ? {} : { problem: settings.problem }), + }, + }, + ); } const command = settings.commands[0]; if (command !== CLAUDE_HOOK_COMMAND) { - return check(id, category, title, 'skipped', 'not checked: the configured command is not recognised', null, false, false, { skipReason: 'command_unrecognized' }); + return check( + id, + category, + title, + 'skipped', + 'not checked: the configured command is not recognised', + null, + false, + false, + { + evidence: { + settings_path: settings.settingsPath, + settings_state: settings.state, + configured_command: command ?? 'none', + executable: 'not_run', + exit_code: 'not_run', + ...streamEvidence('stderr', ''), + }, + skipReason: 'command_unrecognized', + }, + ); } const path = runQuery({ cwd, noIndex: true }).records .flatMap((record) => record.paths) .find((candidate) => candidate !== '' && candidate !== '.'); if (path === undefined) { - return check(id, category, title, 'skipped', 'no recorded path is available for a runtime probe', null, false, false, { skipReason: 'probe_path_unavailable' }); + return check( + id, + category, + title, + 'skipped', + 'no recorded path is available for a runtime probe', + null, + false, + false, + { + evidence: { + settings_path: settings.settingsPath, + settings_state: settings.state, + executable: 'not_run', + probe_path: 'unavailable', + exit_code: 'not_run', + ...streamEvidence('stderr', ''), + }, + skipReason: 'probe_path_unavailable', + }, + ); } const payload = JSON.stringify({ @@ -863,11 +1317,42 @@ const checkInjectVersion = (opts: DoctorOptions): DoctorCheck => { const settings = readClaudeHookStatus(claudeSettingsPath(cwd)); if (settings.state !== 'installed') { - return check(id, category, title, 'skipped', `no installed hook to compare against ${mine}`, null, false, false, { skipReason: 'hook_not_installed' }); + return check( + id, + category, + title, + 'skipped', + `no installed hook to compare against ${mine}`, + null, + false, + false, + { + evidence: { executable: 'not_run', theirs: 'not_run', mine }, + skipReason: 'hook_not_installed', + }, + ); } const command = settings.commands[0]; if (command !== CLAUDE_HOOK_COMMAND) { - return check(id, category, title, 'skipped', 'not checked: the configured command is not recognised', null, false, false, { skipReason: 'command_unrecognized' }); + return check( + id, + category, + title, + 'skipped', + 'not checked: the configured command is not recognised', + null, + false, + false, + { + evidence: { + executable: 'not_run', + theirs: 'not_run', + mine, + configured_command: command ?? 'none', + }, + skipReason: 'command_unrecognized', + }, + ); } const configured = command.replace(` ${CLAUDE_HOOK_MARKER}`, ''); @@ -881,11 +1366,29 @@ const checkInjectVersion = (opts: DoctorOptions): DoctorCheck => { HOME: process.env['HOME'] ?? '', }, }); + const reported = typeof run.stdout === 'string' ? run.stdout : ''; + const versionEvidence = { + executable, + theirs: boundedExcerpt(reported).firstLine || 'unavailable', + mine, + exit_code: String(run.status ?? 'unavailable'), + ...streamEvidence('stdout', reported), + }; if (run.status !== 0 || typeof run.stdout !== 'string') { // `checkInjectRuntime` owns "the hook does not run at all" and reports it // with the remedy. Saying it twice would be noise. - return check(id, category, title, 'skipped', `${executable} did not report a version`, null, false, false, { skipReason: 'version_unreadable' }); + return check( + id, + category, + title, + 'skipped', + `${executable} did not report a version`, + null, + false, + false, + { evidence: versionEvidence, skipReason: 'version_unreadable' }, + ); } const theirs = run.stdout.trim(); @@ -903,11 +1406,21 @@ const checkInjectVersion = (opts: DoctorOptions): DoctorCheck => { null, false, false, - { skipReason: 'version_unreadable' }, + { evidence: versionEvidence, skipReason: 'version_unreadable' }, ); } if (theirs === mine) { - return check(id, category, title, 'ok', `the hook runs ${theirs}, the same build as this CLI`); + return check( + id, + category, + title, + 'ok', + `the hook runs ${theirs}, the same build as this CLI`, + null, + false, + undefined, + { evidence: versionEvidence }, + ); } return check( @@ -917,6 +1430,9 @@ const checkInjectVersion = (opts: DoctorOptions): DoctorCheck => { 'warn', `the agent's hook runs ${theirs} but this CLI is ${mine} — every edit is graded by ${theirs}'s rules, not this one's`, 'update the installation the hook resolves to (for the plugin: /plugin marketplace update commitlore), then rerun: commitlore doctor', + false, + undefined, + { evidence: versionEvidence }, ); }; @@ -943,7 +1459,17 @@ const checkMcpLifecycle = (opts: DoctorOptions): DoctorCheck => { const unfinished = unfinishedRuns(cwd); if (unfinished.length === 0) { - return check(id, category, title, 'ok', 'every recorded MCP session ended cleanly, or is still running'); + return check( + id, + category, + title, + 'ok', + 'every recorded MCP session ended cleanly, or is still running', + null, + false, + undefined, + { evidence: { unfinished_count: '0', last_pid: 'none', last_at: 'none' } }, + ); } const last = unfinished[unfinished.length - 1]; @@ -956,6 +1482,15 @@ const checkMcpLifecycle = (opts: DoctorOptions): DoctorCheck => { `most recently pid ${String(last?.pid ?? 0)} at ${last?.at ?? 'unknown'}. ` + 'A killed server loses its tool registration in the client, which reports the same as a tool that never existed (#424)', 'restart the client session; if this repeats, capture it with a client started under --debug', + false, + undefined, + { + evidence: { + unfinished_count: String(unfinished.length), + last_pid: String(last?.pid ?? 0), + last_at: last?.at ?? 'unknown', + }, + }, ); }; @@ -992,7 +1527,17 @@ const checkPendingBacklog = (opts: DoctorOptions): DoctorCheck => { try { listing = runPendingList({ cwd }); } catch { - return check(id, category, title, 'ok', 'no pending directory — nothing has been captured here yet'); + return check( + id, + category, + title, + 'ok', + 'no pending directory — nothing has been captured here yet', + null, + false, + undefined, + { evidence: { stranded: '0', staged_expired: '0', oldest: 'none' } }, + ); } if (listing.unreadable.length > 0) { @@ -1003,6 +1548,16 @@ const checkPendingBacklog = (opts: DoctorOptions): DoctorCheck => { 'warn', `${listing.unreadable.length} pending file(s) cannot be read as a transaction`, 'commitlore pending ls', + false, + undefined, + { + evidence: { + stranded: '0', + staged_expired: '0', + oldest: 'none', + unreadable: String(listing.unreadable.length), + }, + }, ); } @@ -1017,6 +1572,17 @@ const checkPendingBacklog = (opts: DoctorOptions): DoctorCheck => { title, 'ok', held === 0 ? 'no captures are waiting' : `${String(held)} capture(s) waiting, all still able to apply`, + null, + false, + undefined, + { + evidence: { + stranded: '0', + staged_expired: '0', + oldest: 'none', + waiting: String(held), + }, + }, ); } @@ -1043,8 +1609,17 @@ const checkPendingBacklog = (opts: DoctorOptions): DoctorCheck => { 'warn', `${detail}; oldest from ${oldest ?? 'an unknown time'}. ` + 'A staged record binds to the tree it was prepared for and is skipped once that tree moves, ' + - 'so these decisions were never written to the history (#458)', + 'so these decisions were never written to the history (#458)', 'commitlore pending ls', + false, + undefined, + { + evidence: { + stranded: String(stranded.length), + staged_expired: String(lost.length), + oldest: oldest ?? 'unknown', + }, + }, ); }; @@ -1060,6 +1635,17 @@ const checkIndex = (opts: DoctorOptions): DoctorCheck => { 'warn', 'no index yet — queries fall back to scanning the history', 'commitlore index --rebuild', + false, + undefined, + { + evidence: { + trailers: '0', + commits: '0', + last_indexed_sha: 'none', + head_sha: 'not_queried', + fts: 'unavailable', + }, + }, ); } try { @@ -1067,6 +1653,13 @@ const checkIndex = (opts: DoctorOptions): DoctorCheck => { const head = execGit(['rev-parse', 'HEAD'], gitOptions(opts)); const behind = head.code === 0 && info.lastIndexedSha !== head.stdout.trim(); const fts = info.fts ? 'FTS5' : 'no FTS5 (value search falls back to LIKE)'; + const indexEvidence = { + trailers: String(info.trailers), + commits: String(info.commits), + last_indexed_sha: info.lastIndexedSha || 'none', + head_sha: head.code === 0 ? head.stdout.trim() || 'none' : 'unavailable', + fts: info.fts ? 'true' : 'false', + }; return behind ? check( 'index-health', 'index', @@ -1074,12 +1667,19 @@ const checkIndex = (opts: DoctorOptions): DoctorCheck => { 'warn', `${info.trailers} trailers over ${info.commits} commits, behind HEAD — ${fts}`, 'commitlore index', + false, + undefined, + { evidence: indexEvidence }, ) : check( 'index-health', 'index', 'index health', 'ok', `${info.trailers} trailers over ${info.commits} commits, current with HEAD — ${fts}`, + null, + false, + undefined, + { evidence: indexEvidence }, ); } catch (error) { return check( @@ -1088,6 +1688,17 @@ const checkIndex = (opts: DoctorOptions): DoctorCheck => { 'warn', `index unreadable (${error instanceof Error ? error.message : String(error)}) — queries still work without it`, 'commitlore index --rebuild', + false, + undefined, + { + evidence: { + trailers: 'unavailable', + commits: 'unavailable', + last_indexed_sha: 'unavailable', + head_sha: 'unavailable', + fts: 'unavailable', + }, + }, ); } finally { try { @@ -1106,8 +1717,21 @@ const checkHistoryDepth = (opts: DoctorOptions): DoctorCheck => 'warn', 'this clone has shallow history, so queries may be missing records that exist upstream', 'git fetch --unshallow', + false, + undefined, + { evidence: { shallow: 'true' } }, ) - : check('history-depth', 'history', 'history depth', 'ok', 'full history is available'); + : check( + 'history-depth', + 'history', + 'history depth', + 'ok', + 'full history is available', + null, + false, + undefined, + { evidence: { shallow: 'false' } }, + ); /** Local branches this check will look at, past which a repository is skipped rather than walked exhaustively. */ const MAX_SQUASH_CANDIDATE_BRANCHES = 200; @@ -1196,7 +1820,20 @@ const checkSquashConservation = (opts: DoctorOptions): DoctorCheck => { const head = execGit(['rev-parse', '--verify', '--quiet', 'HEAD'], gitOptions(opts)); if (head.code !== 0) { - return check(id, category, title, 'skipped', 'no HEAD yet — nothing to compare against', null, false, false, { skipReason: 'unborn_head' }); + return check( + id, + category, + title, + 'skipped', + 'no HEAD yet — nothing to compare against', + null, + false, + false, + { + evidence: { candidates: '0', checked: '0', uncheckable: '0', lost_count: '0' }, + skipReason: 'unborn_head', + }, + ); } const candidates = squashCandidates(opts, head.stdout.trim()); @@ -1210,7 +1847,10 @@ const checkSquashConservation = (opts: DoctorOptions): DoctorCheck => { null, false, false, - { skipReason: 'nothing_applicable' }, + { + evidence: { candidates: '0', checked: '0', uncheckable: '0', lost_count: '0' }, + skipReason: 'nothing_applicable', + }, ); } @@ -1265,7 +1905,15 @@ const checkSquashConservation = (opts: DoctorOptions): DoctorCheck => { null, false, false, - { skipReason: 'nothing_applicable' }, + { + evidence: { + candidates: String(candidates.length), + checked: '0', + uncheckable: String(uncheckable), + lost_count: '0', + }, + skipReason: 'nothing_applicable', + }, ); } @@ -1283,6 +1931,16 @@ const checkSquashConservation = (opts: DoctorOptions): DoctorCheck => { `${lost.length} record(s) declared on a branch not reachable from HEAD do not appear in HEAD's history: ${named}${more}`, 'commitlore squash-preserve .. --target , ' + 'then commit or attach the result', + false, + undefined, + { + evidence: { + candidates: String(candidates.length), + checked: String(checked), + uncheckable: String(uncheckable), + lost_count: String(lost.length), + }, + }, ); } @@ -1291,7 +1949,24 @@ const checkSquashConservation = (opts: DoctorOptions): DoctorCheck => { ? `${checked} squash-shaped branch(es) checked, every declared Record-Id is reachable from HEAD ` + `(${uncheckable} branch(es) recorded nothing with an id and could not be checked this way)` : `${checked} squash-shaped branch(es) checked, every declared Record-Id is reachable from HEAD`; - return check(id, category, title, 'ok', detail); + return check( + id, + category, + title, + 'ok', + detail, + null, + false, + undefined, + { + evidence: { + candidates: String(candidates.length), + checked: String(checked), + uncheckable: String(uncheckable), + lost_count: '0', + }, + }, + ); }; /** diff --git a/test/doctor-snapshot.test.ts b/test/doctor-snapshot.test.ts index 800e199..862a9c4 100644 --- a/test/doctor-snapshot.test.ts +++ b/test/doctor-snapshot.test.ts @@ -13,8 +13,8 @@ * — which checks run, in what order, with what status and what fix line. */ -import { execFileSync } from 'node:child_process'; -import { mkdirSync, mkdtempSync, realpathSync, rmSync, writeFileSync } from 'node:fs'; +import { execFileSync, type SpawnSyncReturns } from 'node:child_process'; +import { chmodSync, mkdirSync, mkdtempSync, realpathSync, rmSync, writeFileSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { dirname, join, resolve } from 'node:path'; import { fileURLToPath } from 'node:url'; @@ -23,11 +23,14 @@ import { afterAll, describe, expect, it } from 'vitest'; import { CHECK_REGISTRY, + evaluateInjectRun, formatReport, runDoctor, type CheckDefinition, + type DoctorCheck, } from '../src/commands/doctor.js'; import { closeIndex, openIndex, rebuildIndex } from '../src/core/index-db.js'; +import { claudeSettingsPath, installClaudeHook } from '../src/hooks/claude-settings.js'; import { createTestRepo } from './git-fixtures.js'; const PACKAGE_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..'); @@ -347,3 +350,174 @@ describe('#464 typed skip reasons', () => { expect(row?.skipReason).toBe('unborn_head'); }); }); + +/** + * #465: a diagnostic conclusion is only as useful as the observation beside it. + * + * Text rendering deliberately ignores these fields until its own ticket, so + * these assertions look at the report object directly. That keeps the text + * snapshot meaningful while making the JSON contract hard to erode unnoticed. + */ +describe('#465 doctor evidence', () => { + const assertEvidence = (checks: readonly DoctorCheck[]): void => { + for (const row of checks) { + if (Object.keys(row.evidence).length === 0) { + throw new Error(`${row.id} is ${row.status} without evidence`); + } + } + }; + + const injectContext: Parameters[1] = { + id: 'inject-runtime', + category: 'delivery', + title: 'PreToolUse hook runtime', + executable: 'configured-commitlore', + path: 'probe.ts', + fix: 'reinstall the configured executable', + unavailableFix: 'make the configured executable available', + }; + + const injectRun = (stderr: string): SpawnSyncReturns => ({ + pid: 1, + output: [null, '', stderr], + stdout: '', + stderr, + status: 7, + signal: null, + }); + + it('gives every full-run row evidence, and rejects a deliberately bare finding', () => { + // A new failure path can otherwise read plausibly in text while dropping + // the observation a JSON consumer needs to distinguish it from another. + const reports = [ + runDoctor({ cwd: populated('evidence-working', resolve(PACKAGE_ROOT, 'dist/commitlore.mjs')) }), + runDoctor({ cwd: populated('evidence-broken', join(temp('evidence-missing'), 'missing.mjs')) }), + ]; + const rows = reports.flatMap((report) => report.checks); + + assertEvidence(rows); + expect(rows.some((row) => row.status !== 'ok')).toBe(true); + for (const row of rows) { + for (const [key, value] of Object.entries(row.evidence)) { + expect(key, `${row.id} emitted a non-contract evidence key`).toMatch(/^[a-z][a-z0-9_]*$/); + expect(value, `${row.id}.${key} is not a string`).toBeTypeOf('string'); + } + } + + const broken: DoctorCheck = { + id: 'test-only-bare-finding', + title: 'test-only bare finding', + status: 'fail', + needsAttention: true, + detail: 'this row exists only to exercise the invariant', + fix: null, + fixed: false, + category: 'runtime', + severity: 'error', + evidence: {}, + optional: false, + }; + expect(() => assertEvidence([broken])).toThrow('test-only-bare-finding is fail without evidence'); + }); + + it('renders paths under HOME as home-relative evidence', () => { + // Fixture paths are the path shape users paste into bug reports. Pointing + // HOME at their parent proves sanitisation reaches paths from every check, + // not only the one that introduced this field. + const home = temp('evidence-home'); + const repo = createTestRepo({ path: join(home, 'repo') }); + const previousHome = process.env['HOME']; + process.env['HOME'] = home; + try { + const values = runDoctor({ cwd: repo }).checks.flatMap((row) => Object.values(row.evidence)); + expect(values.some((value) => value.includes('~/'))).toBe(true); + for (const value of values) expect(value).not.toContain(home); + } finally { + if (previousHome === undefined) delete process.env['HOME']; + else process.env['HOME'] = previousHome; + } + }); + + it('bounds captured stderr while preserving whether anything was omitted', () => { + // The bound is what keeps a broken hook that prints a large stack trace + // from turning a diagnostic response into an unbounded JSON payload. + const truncated = evaluateInjectRun(injectRun(`${'x'.repeat(10_000)}\nsecond line`), injectContext); + const untruncated = evaluateInjectRun(injectRun('short diagnostic\nsecond line'), injectContext); + + expect(truncated.evidence['stderr_first_line']).toHaveLength(200); + expect(truncated.evidence['stderr_truncated']).toBe('true'); + expect(untruncated.evidence['stderr_first_line']).toBe('short diagnostic'); + expect(untruncated.evidence['stderr_truncated']).toBe('false'); + }); + + it('records the configured executable it runs and both sides of a hook version comparison', () => { + // #149 reconstructed a path that did not appear in settings; #382 had both + // versions in hand but left the skew trapped inside prose. This fixture + // makes the configured command do both jobs so the two observations stay + // coupled to the executions that produced them. + const repo = populated('evidence-inject', resolve(PACKAGE_ROOT, 'dist/commitlore.mjs')); + const bin = temp('evidence-inject-bin'); + const command = join(bin, 'commitlore'); + writeFileSync( + command, + '#!/bin/sh\nif [ "$1" = "--version" ]; then\n printf \'0.0.0\\n\'\nelse\n printf \'{"hookSpecificOutput":{"additionalContext":"context"}}\\n\'\nfi\n', + ); + chmodSync(command, 0o755); + installClaudeHook({ settingsPath: claudeSettingsPath(repo) }); + + const previousPath = process.env['PATH']; + process.env['PATH'] = `${bin}:/usr/bin:/bin`; + try { + const rows = runDoctor({ cwd: repo }).checks; + const runtime = rows.find((row) => row.id === 'inject-runtime'); + const version = rows.find((row) => row.id === 'inject-version'); + + expect(runtime?.status).toBe('ok'); + expect(runtime?.evidence['executable']).toBe('commitlore'); + expect(runtime?.evidence['exit_code']).toBe('0'); + expect(version?.evidence['executable']).toBe('commitlore'); + expect(version?.evidence['theirs']).toBe('0.0.0'); + expect(version?.evidence['mine']).not.toBe(''); + } finally { + if (previousPath === undefined) delete process.env['PATH']; + else process.env['PATH'] = previousPath; + } + }); + + it('surfaces the hook target recorded at installation and an active override', () => { + // #49 was invisible because doctor observed the target but kept it only in + // prose. The override matters for the same reason: it wins resolution. + const bin = resolve(PACKAGE_ROOT, 'dist/commitlore.mjs'); + const repo = populated('evidence-hook-target', bin); + const override = join(repo, 'override.mjs'); + const previousOverride = process.env['COMMITLORE_BIN']; + process.env['COMMITLORE_BIN'] = override; + try { + const hook = runDoctor({ cwd: repo }).checks.find((row) => row.id === 'commit-msg-hook'); + const home = process.env['HOME']; + const homeRelative = (value: string): string => + home !== undefined && value.startsWith(`${home}/`) ? `~/${value.slice(home.length + 1)}` : value; + + expect(hook?.evidence['hook_path']).toContain('hooks/commit-msg'); + expect(hook?.evidence['bin']).toBe(homeRelative(bin)); + expect(hook?.evidence['node']).toBe(homeRelative(process.execPath)); + expect(hook?.evidence['commitlore_bin_override']).toBe(override); + } finally { + if (previousOverride === undefined) delete process.env['COMMITLORE_BIN']; + else process.env['COMMITLORE_BIN'] = previousOverride; + } + }); + + it('keeps the counts that licence an index-health verdict', () => { + // Counting a different trailer convention produced a persuasive but wrong + // green report in #335/#458. Keeping these numbers structured lets a test + // compare the conclusion with the observation that licensed it. + const repo = populated('evidence-index-counts', resolve(PACKAGE_ROOT, 'dist/commitlore.mjs')); + const index = runDoctor({ cwd: repo }).checks.find((row) => row.id === 'index-health'); + + expect(index?.evidence['trailers']).not.toBe(''); + expect(index?.evidence['commits']).not.toBe(''); + expect(index?.detail).toContain(`${index?.evidence['trailers']} trailers`); + expect(index?.detail).toContain(`${index?.evidence['commits']} commits`); + }); +});