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`); + }); +});