/** * Agent registry doctor — reconcile `.cant` files on disk against the * global `agent_registry_agents` table. * * The doctor walks the tier filesystems (global + optional project) and the * `agents` rows that have a `cant_path`, then emits typed * {@link AgentDoctorFinding} objects for every drift scenario it detects. * * Diagnostic codes (stable for the lifetime of the v3 schema): * * - **D-001** `orphan-file` — `.cant` exists in a tier directory but no * matching row is present in the registry for that tier. * - **D-002** `orphan-row` — row references a `cant_path` that does not * exist on disk. * - **D-003** `sha256-mismatch` — file on disk has a different digest than * the stored `cant_sha256`. * - **D-004** `unattached-global` — `tier='global'` row is not attached to any * project via `conduit.db:project_agent_refs` (emitted only when the * caller supplies `projectRoot`). * - **D-005** `missing-skills` — `.cant` declares a skill in `skills[]` * that the `agent_skills` junction is missing (requires a parseable file). * - **D-006** `extra-skills` — `agent_skills` binds a skill that is not * present in the manifest's declared `skills[]`. * - **D-007** `cant-parse-error` — the file on disk failed to parse. * - **D-008** `legacy-path` — row uses the pre-T889 `.cleo/agents/` * path instead of `.cleo/cant/agents/`. * - **D-009** `deprecated-live` — a deprecated agent is still registered * without an alias redirect row. * - **D-010** `legacy-json` — discovered `~/.cleo/agent-registry.json` * from a pre-T889 install. * * The module is intentionally dependency-light and does NOT import * `@cleocode/cant` (a circular dependency) — skill-list extraction reuses * the same minimal parser that `agent-install.ts` does, trimmed to the * fields the doctor needs. * * @module agent-doctor * @task T889 / T901 / W2-7 * @epic T889 */ import type { DatabaseSync } from 'node:sqlite'; import type { AgentDoctorCode, AgentDoctorFinding, DoctorReport } from '@cleocode/contracts'; /** * Options accepted by {@link buildDoctorReport}. * * @task T889 / W2-7 */ export interface BuildDoctorReportOptions { /** * Absolute path to the project root. When supplied, the project-tier * directory `/.cleo/cant/agents/` is also scanned and * D-004 / D-008 checks are activated. When omitted, only the global * tier is inspected. */ projectRoot?: string; /** * Override the global `.cant` agents directory. Tests pass a tmp path * here; production callers should leave it `undefined` so the default * {@link getCleoGlobalCantAgentsDir} is used. */ globalCantDir?: string; /** * Override `~/` for the D-010 legacy-json probe. Tests pass a tmp path * here; production callers should leave it `undefined`. */ homeDir?: string; } /** * Options accepted by {@link reconcileDoctor}. * * The default ({} / no flags) performs only safe, non-destructive repairs: * deleting orphan rows and refreshing SHA-256 values. All other remediations * are opt-in because they could mutate the filesystem or pull in seed data. * * @task T889 / W2-7 */ export interface ReconcileDoctorOptions { /** * When `true`, allow path migrations (D-008) to rewrite `cant_path` from * the legacy `.cleo/agents/` location to the canonical * `.cleo/cant/agents/` location. */ allowPathMigration?: boolean; /** * When `true`, import a discovered `~/.cleo/agent-registry.json` (D-010). * No-op if no legacy JSON is found. */ importLegacyJson?: boolean; /** * When `true`, register orphan files (D-001) by dispatching to the * packaged seed installer. Defaults to `false` because it can mutate * the registry from disk state that wasn't vetted. */ rehydrateFromSeed?: boolean; } /** * Summary returned by {@link reconcileDoctor}. Lists every finding code that * was acted on (`repaired`) versus every code that was intentionally skipped * (`skipped`). * * @task T889 / W2-7 */ export interface ReconcileDoctorResult { /** Codes the reconciler actioned. */ repaired: AgentDoctorCode[]; /** Codes that fell outside the current reconcile scope or the supplied flags. */ skipped: AgentDoctorCode[]; } /** * Produce a {@link DoctorReport} describing every drift between the * filesystem tiers and the `agents` table. * * The function only READS from the database and filesystem. It never * mutates state — use {@link reconcileDoctor} when you want to apply * remediations. * * @param db - Open handle to the global cleo.db (Agent Registry). * @param options - Scope options (project root, directory overrides). * @returns Ordered list of findings + severity histogram. * @task T889 / W2-7 */ export declare function buildDoctorReport(db: DatabaseSync, options?: BuildDoctorReportOptions): Promise; /** * Apply safe remediations for the supplied doctor findings. The default * behaviour repairs only the codes whose remediation cannot destroy user * data (D-002 row deletion, D-003 hash refresh). Codes that could rewrite * paths or re-register agents from disk state are opt-in via * {@link ReconcileDoctorOptions}. * * The function is idempotent: invoking it twice with the same findings * leaves the second invocation with nothing to do. * * @param db - Open handle to the global cleo.db (Agent Registry). * @param findings - Findings from {@link buildDoctorReport}. * @param options - Opt-in flags for destructive or seed-driven repairs. * @returns Summary of which codes were repaired vs skipped. * @task T889 / W2-7 */ export declare function reconcileDoctor(db: DatabaseSync, findings: AgentDoctorFinding[], options?: ReconcileDoctorOptions): Promise; //# sourceMappingURL=agent-doctor.d.ts.map