/** * Type definitions for the doctor command. */ import type { IntegrationId } from '@/bin/integration-metadata'; /** Hook platform identifiers */ export type HookPlatform = IntegrationId; /** Self-test case definition */ export interface SelfTestCase { command: string; description: string; expectBlocked: boolean; } /** Self-test result for a single command */ export interface SelfTestResult { command: string; description: string; expected: 'blocked' | 'allowed'; actual: 'blocked' | 'allowed'; passed: boolean; reason?: string; } /** Self-test summary for a hook */ export interface SelfTestSummary { passed: number; failed: number; total: number; results: SelfTestResult[]; } /** Hook configuration status */ export type HookConfigStatus = 'configured' | 'n/a' | 'disabled'; /** Hook detection result with integrated self-test */ export interface HookStatus { platform: HookPlatform; status: HookConfigStatus; method?: string; configPath?: string; configPaths?: readonly string[]; errors?: string[]; selfTest?: SelfTestSummary; } /** Config source info */ export interface ConfigSourceInfo { path: string; exists: boolean; valid: boolean; ruleCount: number; errors?: string[]; } /** Effective rule with source tracking */ export interface EffectiveRule { source: 'user' | 'project'; name: string; command: string; subcommand?: string; blockArgs: string[]; reason: string; } /** Shadowed rule info */ export interface ShadowedRule { name: string; shadowedBy: 'project'; } /** Environment variable info */ export interface EnvVarInfo { name: string; value: string | undefined; isSet: boolean; legacyName?: string; legacyValue?: string; legacyIsSet?: boolean; description: string; defaultBehavior: string; } /** Audit activity summary */ export interface ActivitySummary { totalBlocked: number; sessionCount: number; recentEntries: Array<{ timestamp: string; command: string; reason: string; relativeTime: string; }>; oldestEntry?: string; newestEntry?: string; } /** Update check result */ export interface UpdateInfo { currentVersion: string; latestVersion: string | null; updateAvailable: boolean; error?: string; } export type PiProbeStatus = 'configured' | 'not-found' | 'unavailable' | 'error'; export interface PiProbeResource { kind: 'command' | 'tool'; name: string; path?: string; source?: string; } export interface PiProbeInfo { status: PiProbeStatus; installedAndEnabled: boolean; matched: PiProbeResource[]; error?: string; } /** System information */ export interface SystemInfo { /** cc-safety-net version */ version: string; /** Claude Code version (from `claude --version`) */ claudeCodeVersion: string | null; /** Claude Code plugin list output (from `claude plugin list`) */ claudePluginListOutput: string | null; /** OpenCode version (from `opencode --version`) */ openCodeVersion: string | null; /** Codex CLI version (from `codex --version`) */ codexCliVersion: string | null; /** Gemini CLI version (from `gemini --version`) */ geminiCliVersion: string | null; /** Gemini CLI extension list output (from `gemini extensions list`) */ geminiExtensionsListOutput: string | null; /** Copilot CLI version (from `copilot --binary-version`, falling back to `copilot --version`) */ copilotCliVersion: string | null; /** Kimi Code version (from `kimi --version`) */ kimiCodeVersion: string | null; /** Pi CLI version (from `pi --version`) */ piCliVersion: string | null; /** Node.js version (from `node --version`) */ nodeVersion: string | null; /** npm version (from `npm --version`) */ npmVersion: string | null; /** Bun version (from `bun --version`) */ bunVersion: string | null; /** Whether the copilot-safety-net plugin is installed (from `copilot plugin list`) */ copilotPluginInstalled: boolean; /** Whether the Pi extension sentinel is runtime-visible */ piSafetyNetProbe: PiProbeInfo; /** Platform (e.g., "darwin arm64") */ platform: string; } /** Full doctor report */ export interface DoctorReport { hooks: HookStatus[]; userConfig: ConfigSourceInfo; projectConfig: ConfigSourceInfo; effectiveRules: EffectiveRule[]; shadowedRules: ShadowedRule[]; environment: EnvVarInfo[]; activity: ActivitySummary; update: UpdateInfo; system: SystemInfo; } /** Doctor command options */ export interface DoctorOptions { json?: boolean; cwd?: string; skipUpdateCheck?: boolean; }