import { Type } from "@sinclair/typebox";
import { Text } from "@nerf/pi-tui";
import { findMilestoneIds, nextMilestoneId, claimReservedId, getReservedMilestoneIds } from "../guided-flow.js";
import { loadEffectiveNerfPreferences } from "../preferences.js";
import { ensureDbOpen } from "./dynamic-tools.js";
import { StringEnum } from "@nerf/pi-ai";
import { logError } from "../workflow-logger.js";
export function registerDbTools(pi) {
    // ─── nerf_decision_save (formerly nerf_save_decision) ─────────────────────
    const decisionSaveExecute = async (_toolCallId, params, _signal, _onUpdate, _ctx) => {
        const dbAvailable = await ensureDbOpen();
        if (!dbAvailable) {
            return {
                content: [{ type: "text", text: "Error: NERF database is not available. Cannot save decision." }],
                details: { operation: "save_decision", error: "db_unavailable" },
            };
        }
        try {
            const { saveDecisionToDb } = await import("../db-writer.js");
            const { id } = await saveDecisionToDb({
                scope: params.scope,
                decision: params.decision,
                choice: params.choice,
                rationale: params.rationale,
                revisable: params.revisable,
                when_context: params.when_context,
                made_by: params.made_by,
            }, process.cwd());
            return {
                content: [{ type: "text", text: `Saved decision ${id}` }],
                details: { operation: "save_decision", id },
            };
        }
        catch (err) {
            const msg = err instanceof Error ? err.message : String(err);
            logError("tool", `nerf_decision_save tool failed: ${msg}`, { tool: "nerf_decision_save", error: String(err) });
            return {
                content: [{ type: "text", text: `Error saving decision: ${msg}` }],
                details: { operation: "save_decision", error: msg },
            };
        }
    };
    const decisionSaveTool = {
        name: "nerf_decision_save",
        label: "Save Decision",
        description: "Record a project decision to the NERF database and regenerate DECISIONS.md. " +
            "Decision IDs are auto-assigned — never provide an ID manually.",
        promptSnippet: "Record a project decision to the NERF database (auto-assigns ID, regenerates DECISIONS.md)",
        promptGuidelines: [
            "Use nerf_decision_save when recording an architectural, pattern, library, or observability decision.",
            "Decision IDs are auto-assigned (D001, D002, ...) — never guess or provide an ID.",
            "All fields except revisable, when_context, and made_by are required.",
            "The tool writes to the DB and regenerates .nerf/DECISIONS.md automatically.",
            "Set made_by to 'human' when the user explicitly directed the decision, 'agent' when the LLM chose autonomously (default), or 'collaborative' when it was discussed and agreed together.",
        ],
        parameters: Type.Object({
            scope: Type.String({ description: "Scope of the decision (e.g. 'architecture', 'library', 'observability')" }),
            decision: Type.String({ description: "What is being decided" }),
            choice: Type.String({ description: "The choice made" }),
            rationale: Type.String({ description: "Why this choice was made" }),
            revisable: Type.Optional(Type.String({ description: "Whether this can be revisited (default: 'Yes')" })),
            when_context: Type.Optional(Type.String({ description: "When/context for the decision (e.g. milestone ID)" })),
            made_by: Type.Optional(Type.Union([
                Type.Literal("human"),
                Type.Literal("agent"),
                Type.Literal("collaborative"),
            ], { description: "Who made this decision: 'human' (user directed), 'agent' (LLM decided autonomously), or 'collaborative' (discussed and agreed). Default: 'agent'" })),
        }),
        execute: decisionSaveExecute,
        renderCall(args, theme) {
            let text = theme.fg("toolTitle", theme.bold("decision_save "));
            if (args.scope)
                text += theme.fg("accent", `[${args.scope}] `);
            if (args.decision)
                text += theme.fg("muted", args.decision);
            if (args.choice)
                text += theme.fg("dim", ` — ${args.choice}`);
            return new Text(text, 0, 0);
        },
        renderResult(result, _options, theme) {
            const d = result.details;
            if (result.isError || d?.error) {
                return new Text(theme.fg("error", `Error: ${d?.error ?? "unknown"}`), 0, 0);
            }
            let text = theme.fg("success", `Decision ${d?.id ?? ""} saved`);
            if (d?.id)
                text += theme.fg("dim", ` → DECISIONS.md`);
            return new Text(text, 0, 0);
        },
    };
    pi.registerTool(decisionSaveTool);
    // ─── nerf_requirement_update (formerly update_requirement) ───────────
    const requirementUpdateExecute = async (_toolCallId, params, _signal, _onUpdate, _ctx) => {
        const dbAvailable = await ensureDbOpen();
        if (!dbAvailable) {
            return {
                content: [{ type: "text", text: "Error: NERF database is not available. Cannot update requirement." }],
                details: { operation: "update_requirement", id: params.id, error: "db_unavailable" },
            };
        }
        try {
            const db = await import("../nerf-db.js");
            const existing = db.getRequirementById(params.id);
            if (!existing) {
                return {
                    content: [{ type: "text", text: `Error: Requirement ${params.id} not found.` }],
                    details: { operation: "update_requirement", id: params.id, error: "not_found" },
                };
            }
            const { updateRequirementInDb } = await import("../db-writer.js");
            const updates = {};
            if (params.status !== undefined)
                updates.status = params.status;
            if (params.validation !== undefined)
                updates.validation = params.validation;
            if (params.notes !== undefined)
                updates.notes = params.notes;
            if (params.description !== undefined)
                updates.description = params.description;
            if (params.primary_owner !== undefined)
                updates.primary_owner = params.primary_owner;
            if (params.supporting_slices !== undefined)
                updates.supporting_slices = params.supporting_slices;
            await updateRequirementInDb(params.id, updates, process.cwd());
            return {
                content: [{ type: "text", text: `Updated requirement ${params.id}` }],
                details: { operation: "update_requirement", id: params.id },
            };
        }
        catch (err) {
            const msg = err instanceof Error ? err.message : String(err);
            logError("tool", `nerf_requirement_update tool failed: ${msg}`, { tool: "nerf_requirement_update", error: String(err) });
            return {
                content: [{ type: "text", text: `Error updating requirement: ${msg}` }],
                details: { operation: "update_requirement", id: params.id, error: msg },
            };
        }
    };
    const requirementUpdateTool = {
        name: "nerf_requirement_update",
        label: "Update Requirement",
        description: "Update an existing requirement in the NERF database and regenerate REQUIREMENTS.md. " +
            "Provide the requirement ID (e.g. R001) and any fields to update.",
        promptSnippet: "Update an existing NERF requirement by ID (regenerates REQUIREMENTS.md)",
        promptGuidelines: [
            "Use nerf_requirement_update to change status, validation, notes, or other fields on an existing requirement.",
            "The id parameter is required — it must be an existing RXXX identifier.",
            "All other fields are optional — only provided fields are updated.",
            "The tool verifies the requirement exists before updating.",
        ],
        parameters: Type.Object({
            id: Type.String({ description: "The requirement ID (e.g. R001, R014)" }),
            status: Type.Optional(Type.String({ description: "New status (e.g. 'active', 'validated', 'deferred')" })),
            validation: Type.Optional(Type.String({ description: "Validation criteria or proof" })),
            notes: Type.Optional(Type.String({ description: "Additional notes" })),
            description: Type.Optional(Type.String({ description: "Updated description" })),
            primary_owner: Type.Optional(Type.String({ description: "Primary owning slice" })),
            supporting_slices: Type.Optional(Type.String({ description: "Supporting slices" })),
        }),
        execute: requirementUpdateExecute,
        renderCall(args, theme) {
            let text = theme.fg("toolTitle", theme.bold("requirement_update "));
            if (args.id)
                text += theme.fg("accent", args.id);
            const fields = ["status", "validation", "notes", "description"].filter((f) => args[f]);
            if (fields.length > 0)
                text += theme.fg("dim", ` (${fields.join(", ")})`);
            return new Text(text, 0, 0);
        },
        renderResult(result, _options, theme) {
            const d = result.details;
            if (result.isError || d?.error) {
                return new Text(theme.fg("error", `Error: ${d?.error ?? "unknown"}`), 0, 0);
            }
            let text = theme.fg("success", `Requirement ${d?.id ?? ""} updated`);
            text += theme.fg("dim", ` → REQUIREMENTS.md`);
            return new Text(text, 0, 0);
        },
    };
    pi.registerTool(requirementUpdateTool);
    // ─── nerf_summary_save (formerly save_summary) ──────────────────────
    const summarySaveExecute = async (_toolCallId, params, _signal, _onUpdate, _ctx) => {
        const dbAvailable = await ensureDbOpen();
        if (!dbAvailable) {
            return {
                content: [{ type: "text", text: "Error: NERF database is not available. Cannot save artifact." }],
                details: { operation: "save_summary", error: "db_unavailable" },
            };
        }
        const validTypes = ["SUMMARY", "RESEARCH", "CONTEXT", "ASSESSMENT"];
        if (!validTypes.includes(params.artifact_type)) {
            return {
                content: [{ type: "text", text: `Error: Invalid artifact_type "${params.artifact_type}". Must be one of: ${validTypes.join(", ")}` }],
                details: { operation: "save_summary", error: "invalid_artifact_type" },
            };
        }
        try {
            let relativePath;
            if (params.task_id && params.slice_id) {
                relativePath = `milestones/${params.milestone_id}/slices/${params.slice_id}/tasks/${params.task_id}-${params.artifact_type}.md`;
            }
            else if (params.slice_id) {
                relativePath = `milestones/${params.milestone_id}/slices/${params.slice_id}/${params.slice_id}-${params.artifact_type}.md`;
            }
            else {
                relativePath = `milestones/${params.milestone_id}/${params.milestone_id}-${params.artifact_type}.md`;
            }
            const { saveArtifactToDb } = await import("../db-writer.js");
            await saveArtifactToDb({
                path: relativePath,
                artifact_type: params.artifact_type,
                content: params.content,
                milestone_id: params.milestone_id,
                slice_id: params.slice_id,
                task_id: params.task_id,
            }, process.cwd());
            return {
                content: [{ type: "text", text: `Saved ${params.artifact_type} artifact to ${relativePath}` }],
                details: { operation: "save_summary", path: relativePath, artifact_type: params.artifact_type },
            };
        }
        catch (err) {
            const msg = err instanceof Error ? err.message : String(err);
            logError("tool", `nerf_summary_save tool failed: ${msg}`, { tool: "nerf_summary_save", error: String(err) });
            return {
                content: [{ type: "text", text: `Error saving artifact: ${msg}` }],
                details: { operation: "save_summary", error: msg },
            };
        }
    };
    const summarySaveTool = {
        name: "nerf_summary_save",
        label: "Save Summary",
        description: "Save a summary, research, context, or assessment artifact to the NERF database and write it to disk. " +
            "Computes the file path from milestone/slice/task IDs automatically.",
        promptSnippet: "Save a NERF artifact (summary/research/context/assessment) to DB and disk",
        promptGuidelines: [
            "Use nerf_summary_save to persist structured artifacts (SUMMARY, RESEARCH, CONTEXT, ASSESSMENT).",
            "milestone_id is required. slice_id and task_id are optional — they determine the file path.",
            "The tool computes the relative path automatically: milestones/M001/M001-SUMMARY.md, milestones/M001/slices/S01/S01-SUMMARY.md, etc.",
            "artifact_type must be one of: SUMMARY, RESEARCH, CONTEXT, ASSESSMENT.",
        ],
        parameters: Type.Object({
            milestone_id: Type.String({ description: "Milestone ID (e.g. M001)" }),
            slice_id: Type.Optional(Type.String({ description: "Slice ID (e.g. S01)" })),
            task_id: Type.Optional(Type.String({ description: "Task ID (e.g. T01)" })),
            artifact_type: Type.String({ description: "One of: SUMMARY, RESEARCH, CONTEXT, ASSESSMENT" }),
            content: Type.String({ description: "The full markdown content of the artifact" }),
        }),
        execute: summarySaveExecute,
        renderCall(args, theme) {
            let text = theme.fg("toolTitle", theme.bold("summary_save "));
            if (args.artifact_type)
                text += theme.fg("accent", args.artifact_type);
            const path = [args.milestone_id, args.slice_id, args.task_id].filter(Boolean).join("/");
            if (path)
                text += theme.fg("dim", ` ${path}`);
            return new Text(text, 0, 0);
        },
        renderResult(result, _options, theme) {
            const d = result.details;
            if (result.isError || d?.error) {
                return new Text(theme.fg("error", `Error: ${d?.error ?? "unknown"}`), 0, 0);
            }
            let text = theme.fg("success", `${d?.artifact_type ?? "Artifact"} saved`);
            if (d?.path)
                text += theme.fg("dim", ` → ${d.path}`);
            return new Text(text, 0, 0);
        },
    };
    pi.registerTool(summarySaveTool);
    // ─── nerf_milestone_generate_id (formerly generate_milestone_id) ────
    const milestoneGenerateIdExecute = async (_toolCallId, _params, _signal, _onUpdate, _ctx) => {
        try {
            // Claim a reserved ID if the guided-flow already previewed one to the user.
            // This guarantees the ID shown in the UI matches the one materialised on disk.
            const reserved = claimReservedId();
            if (reserved) {
                await ensureMilestoneDbRow(reserved);
                return {
                    content: [{ type: "text", text: reserved }],
                    details: { operation: "generate_milestone_id", id: reserved, source: "reserved" },
                };
            }
            const basePath = process.cwd();
            const existingIds = findMilestoneIds(basePath);
            const uniqueEnabled = !!loadEffectiveNerfPreferences()?.preferences?.unique_milestone_ids;
            const allIds = [...new Set([...existingIds, ...getReservedMilestoneIds()])];
            const newId = nextMilestoneId(allIds, uniqueEnabled);
            await ensureMilestoneDbRow(newId);
            return {
                content: [{ type: "text", text: newId }],
                details: { operation: "generate_milestone_id", id: newId, existingCount: existingIds.length, uniqueEnabled },
            };
        }
        catch (err) {
            const msg = err instanceof Error ? err.message : String(err);
            return {
                content: [{ type: "text", text: `Error generating milestone ID: ${msg}` }],
                details: { operation: "generate_milestone_id", error: msg },
            };
        }
    };
    /**
     * Insert a minimal DB row for a milestone ID so it's visible to the state
     * machine. Uses INSERT OR IGNORE — safe to call even if nerf_plan_milestone
     * later writes the full row. Silently skips if the DB isn't available yet
     * (pre-migration).
     */
    async function ensureMilestoneDbRow(milestoneId) {
        const dbAvailable = await ensureDbOpen();
        if (!dbAvailable)
            return;
        try {
            const { insertMilestone } = await import("../nerf-db.js");
            insertMilestone({ id: milestoneId, status: "queued" });
        }
        catch {
            // Non-fatal — the safety-net in deriveStateFromDb will catch this
        }
    }
    const milestoneGenerateIdTool = {
        name: "nerf_milestone_generate_id",
        label: "Generate Milestone ID",
        description: "Generate the next milestone ID for a new NERF milestone. " +
            "Scans existing milestones on disk and respects the unique_milestone_ids preference. " +
            "Always use this tool when creating a new milestone — never invent milestone IDs manually.",
        promptSnippet: "Generate a valid milestone ID (respects unique_milestone_ids preference)",
        promptGuidelines: [
            "ALWAYS call nerf_milestone_generate_id before creating a new milestone directory or writing milestone files.",
            "Never invent or hardcode milestone IDs like M001, M002 — always use this tool.",
            "Call it once per milestone you need to create. For multi-milestone projects, call it once for each milestone in sequence.",
            "The tool returns the correct format based on project preferences (e.g. M001 or M001-r5jzab).",
        ],
        parameters: Type.Object({}),
        execute: milestoneGenerateIdExecute,
        renderCall(_args, theme) {
            return new Text(theme.fg("toolTitle", theme.bold("milestone_generate_id")), 0, 0);
        },
        renderResult(result, _options, theme) {
            const d = result.details;
            if (result.isError || d?.error) {
                return new Text(theme.fg("error", `Error: ${d?.error ?? "unknown"}`), 0, 0);
            }
            let text = theme.fg("success", `Generated ${d?.id ?? "ID"}`);
            if (d?.source === "reserved")
                text += theme.fg("dim", " (reserved)");
            return new Text(text, 0, 0);
        },
    };
    pi.registerTool(milestoneGenerateIdTool);
    // ─── nerf_plan_milestone (milestone_plan alias) ─────────────────────
    const planMilestoneExecute = async (_toolCallId, params, _signal, _onUpdate, _ctx) => {
        const dbAvailable = await ensureDbOpen();
        if (!dbAvailable) {
            return {
                content: [{ type: "text", text: "Error: NERF database is not available. Cannot plan milestone." }],
                details: { operation: "plan_milestone", error: "db_unavailable" },
            };
        }
        try {
            const { handlePlanMilestone } = await import("../tools/plan-milestone.js");
            const result = await handlePlanMilestone(params, process.cwd());
            if ("error" in result) {
                return {
                    content: [{ type: "text", text: `Error planning milestone: ${result.error}` }],
                    details: { operation: "plan_milestone", error: result.error },
                };
            }
            return {
                content: [{ type: "text", text: `Planned milestone ${result.milestoneId}` }],
                details: {
                    operation: "plan_milestone",
                    milestoneId: result.milestoneId,
                    roadmapPath: result.roadmapPath,
                },
            };
        }
        catch (err) {
            const msg = err instanceof Error ? err.message : String(err);
            logError("tool", `plan_milestone tool failed: ${msg}`, { tool: "nerf_plan_milestone", error: String(err) });
            return {
                content: [{ type: "text", text: `Error planning milestone: ${msg}` }],
                details: { operation: "plan_milestone", error: msg },
            };
        }
    };
    const planMilestoneTool = {
        name: "nerf_plan_milestone",
        label: "Plan Milestone",
        description: "Write milestone planning state to the NERF database, render ROADMAP.md from DB, and clear caches after a successful render.",
        promptSnippet: "Plan a milestone via DB write + roadmap render + cache invalidation",
        promptGuidelines: [
            "Use nerf_plan_milestone for milestone planning instead of writing ROADMAP.md directly.",
            "Keep parameters flat and provide the full milestone planning payload, including slices.",
            "The tool validates input, writes milestone and slice planning data transactionally, renders ROADMAP.md from DB, and clears both state and parse caches after success.",
            "Use the canonical name nerf_plan_milestone; nerf_milestone_plan is the canonical name.",
        ],
        parameters: Type.Object({
            milestoneId: Type.String({ description: "Milestone ID (e.g. M001)" }),
            title: Type.String({ description: "Milestone title" }),
            status: Type.Optional(Type.String({ description: "Milestone status (defaults to active)" })),
            dependsOn: Type.Optional(Type.Array(Type.String(), { description: "Milestone dependencies" })),
            vision: Type.String({ description: "Milestone vision" }),
            successCriteria: Type.Array(Type.String(), { description: "Top-level success criteria bullets" }),
            keyRisks: Type.Array(Type.Object({
                risk: Type.String({ description: "Risk statement" }),
                whyItMatters: Type.String({ description: "Why the risk matters" }),
            }), { description: "Structured risk entries" }),
            proofStrategy: Type.Array(Type.Object({
                riskOrUnknown: Type.String({ description: "Risk or unknown to retire" }),
                retireIn: Type.String({ description: "Where it will be retired" }),
                whatWillBeProven: Type.String({ description: "What proof will be produced" }),
            }), { description: "Structured proof strategy entries" }),
            verificationContract: Type.String({ description: "Verification contract text" }),
            verificationIntegration: Type.String({ description: "Integration verification text" }),
            verificationOperational: Type.String({ description: "Operational verification text" }),
            verificationUat: Type.String({ description: "UAT verification text" }),
            definitionOfDone: Type.Array(Type.String(), { description: "Definition of done bullets" }),
            requirementCoverage: Type.String({ description: "Requirement coverage text" }),
            boundaryMapMarkdown: Type.String({ description: "Boundary map markdown block" }),
            slices: Type.Array(Type.Object({
                sliceId: Type.String({ description: "Slice ID (e.g. S01)" }),
                title: Type.String({ description: "Slice title" }),
                risk: Type.String({ description: "Slice risk" }),
                depends: Type.Array(Type.String(), { description: "Slice dependency IDs" }),
                demo: Type.String({ description: "Roadmap demo text / After this" }),
                goal: Type.String({ description: "Slice goal" }),
                successCriteria: Type.String({ description: "Slice success criteria block" }),
                proofLevel: Type.String({ description: "Slice proof level" }),
                integrationClosure: Type.String({ description: "Slice integration closure" }),
                observabilityImpact: Type.String({ description: "Slice observability impact" }),
            }), { description: "Planned slices for the milestone" }),
        }),
        execute: planMilestoneExecute,
    };
    pi.registerTool(planMilestoneTool);
    // ─── nerf_plan_slice (slice_plan alias) ─────────────────────────────
    const planSliceExecute = async (_toolCallId, params, _signal, _onUpdate, _ctx) => {
        const dbAvailable = await ensureDbOpen();
        if (!dbAvailable) {
            return {
                content: [{ type: "text", text: "Error: NERF database is not available. Cannot plan slice." }],
                details: { operation: "plan_slice", error: "db_unavailable" },
            };
        }
        try {
            const { handlePlanSlice } = await import("../tools/plan-slice.js");
            const result = await handlePlanSlice(params, process.cwd());
            if ("error" in result) {
                return {
                    content: [{ type: "text", text: `Error planning slice: ${result.error}` }],
                    details: { operation: "plan_slice", error: result.error },
                };
            }
            return {
                content: [{ type: "text", text: `Planned slice ${result.sliceId} (${result.milestoneId})` }],
                details: {
                    operation: "plan_slice",
                    milestoneId: result.milestoneId,
                    sliceId: result.sliceId,
                    planPath: result.planPath,
                    taskPlanPaths: result.taskPlanPaths,
                },
            };
        }
        catch (err) {
            const msg = err instanceof Error ? err.message : String(err);
            logError("tool", `plan_slice tool failed: ${msg}`, { tool: "nerf_plan_slice", error: String(err) });
            return {
                content: [{ type: "text", text: `Error planning slice: ${msg}` }],
                details: { operation: "plan_slice", error: msg },
            };
        }
    };
    const planSliceTool = {
        name: "nerf_plan_slice",
        label: "Plan Slice",
        description: "Write slice planning state to the NERF database, render S##-PLAN.md plus task PLAN artifacts from DB, and clear caches after a successful render.",
        promptSnippet: "Plan a slice via DB write + PLAN render + cache invalidation",
        promptGuidelines: [
            "Use nerf_plan_slice for slice planning instead of writing S##-PLAN.md or task PLAN files directly.",
            "Keep parameters flat and provide the full slice planning payload, including tasks.",
            "The tool validates input, requires an existing parent slice, writes slice/task planning data, renders PLAN.md and task plan files from DB, and clears both state and parse caches after success.",
            "Use the canonical name nerf_plan_slice; nerf_slice_plan is the canonical name.",
        ],
        parameters: Type.Object({
            milestoneId: Type.String({ description: "Milestone ID (e.g. M001)" }),
            sliceId: Type.String({ description: "Slice ID (e.g. S01)" }),
            goal: Type.String({ description: "Slice goal" }),
            successCriteria: Type.String({ description: "Slice success criteria block" }),
            proofLevel: Type.String({ description: "Slice proof level" }),
            integrationClosure: Type.String({ description: "Slice integration closure" }),
            observabilityImpact: Type.String({ description: "Slice observability impact" }),
            tasks: Type.Array(Type.Object({
                taskId: Type.String({ description: "Task ID (e.g. T01)" }),
                title: Type.String({ description: "Task title" }),
                description: Type.String({ description: "Task description / steps block" }),
                estimate: Type.String({ description: "Task estimate string" }),
                files: Type.Array(Type.String(), { description: "Files likely touched" }),
                verify: Type.String({ description: "Verification command or block" }),
                inputs: Type.Array(Type.String(), { description: "Input files or references" }),
                expectedOutput: Type.Array(Type.String(), { description: "Expected output files or artifacts" }),
                observabilityImpact: Type.Optional(Type.String({ description: "Task observability impact" })),
            }), { description: "Planned tasks for the slice" }),
        }),
        execute: planSliceExecute,
    };
    pi.registerTool(planSliceTool);
    // ─── nerf_plan_task (task_plan alias) ───────────────────────────────
    const planTaskExecute = async (_toolCallId, params, _signal, _onUpdate, _ctx) => {
        const dbAvailable = await ensureDbOpen();
        if (!dbAvailable) {
            return {
                content: [{ type: "text", text: "Error: NERF database is not available. Cannot plan task." }],
                details: { operation: "plan_task", error: "db_unavailable" },
            };
        }
        try {
            const { handlePlanTask } = await import("../tools/plan-task.js");
            const result = await handlePlanTask(params, process.cwd());
            if ("error" in result) {
                return {
                    content: [{ type: "text", text: `Error planning task: ${result.error}` }],
                    details: { operation: "plan_task", error: result.error },
                };
            }
            return {
                content: [{ type: "text", text: `Planned task ${result.taskId} (${result.sliceId}/${result.milestoneId})` }],
                details: {
                    operation: "plan_task",
                    milestoneId: result.milestoneId,
                    sliceId: result.sliceId,
                    taskId: result.taskId,
                    taskPlanPath: result.taskPlanPath,
                },
            };
        }
        catch (err) {
            const msg = err instanceof Error ? err.message : String(err);
            logError("tool", `plan_task tool failed: ${msg}`, { tool: "nerf_plan_task", error: String(err) });
            return {
                content: [{ type: "text", text: `Error planning task: ${msg}` }],
                details: { operation: "plan_task", error: msg },
            };
        }
    };
    const planTaskTool = {
        name: "nerf_plan_task",
        label: "Plan Task",
        description: "Write task planning state to the NERF database, render tasks/T##-PLAN.md from DB, and clear caches after a successful render.",
        promptSnippet: "Plan a task via DB write + task PLAN render + cache invalidation",
        promptGuidelines: [
            "Use nerf_plan_task for task planning instead of writing tasks/T##-PLAN.md directly.",
            "Keep parameters flat and provide the full task planning payload.",
            "The tool validates input, requires an existing parent slice, writes task planning data, renders the task PLAN file from DB, and clears both state and parse caches after success.",
            "Use the canonical name nerf_plan_task; nerf_task_plan is the canonical name.",
        ],
        parameters: Type.Object({
            milestoneId: Type.String({ description: "Milestone ID (e.g. M001)" }),
            sliceId: Type.String({ description: "Slice ID (e.g. S01)" }),
            taskId: Type.String({ description: "Task ID (e.g. T01)" }),
            title: Type.String({ description: "Task title" }),
            description: Type.String({ description: "Task description / steps block" }),
            estimate: Type.String({ description: "Task estimate string" }),
            files: Type.Array(Type.String(), { description: "Files likely touched" }),
            verify: Type.String({ description: "Verification command or block" }),
            inputs: Type.Array(Type.String(), { description: "Input files or references" }),
            expectedOutput: Type.Array(Type.String(), { description: "Expected output files or artifacts" }),
            observabilityImpact: Type.Optional(Type.String({ description: "Task observability impact" })),
        }),
        execute: planTaskExecute,
    };
    pi.registerTool(planTaskTool);
    // ─── nerf_task_complete (nerf_complete_task alias) ────────────────────────
    const taskCompleteExecute = async (_toolCallId, params, _signal, _onUpdate, _ctx) => {
        const dbAvailable = await ensureDbOpen();
        if (!dbAvailable) {
            return {
                content: [{ type: "text", text: "Error: NERF database is not available. Cannot complete task." }],
                details: { operation: "complete_task", error: "db_unavailable" },
            };
        }
        try {
            const { handleCompleteTask } = await import("../tools/complete-task.js");
            const result = await handleCompleteTask(params, process.cwd());
            if ("error" in result) {
                return {
                    content: [{ type: "text", text: `Error completing task: ${result.error}` }],
                    details: { operation: "complete_task", error: result.error },
                };
            }
            return {
                content: [{ type: "text", text: `Completed task ${result.taskId} (${result.sliceId}/${result.milestoneId})` }],
                details: {
                    operation: "complete_task",
                    taskId: result.taskId,
                    sliceId: result.sliceId,
                    milestoneId: result.milestoneId,
                    summaryPath: result.summaryPath,
                },
            };
        }
        catch (err) {
            const msg = err instanceof Error ? err.message : String(err);
            logError("tool", `complete_task tool failed: ${msg}`, { tool: "nerf_task_complete", error: String(err) });
            return {
                content: [{ type: "text", text: `Error completing task: ${msg}` }],
                details: { operation: "complete_task", error: msg },
            };
        }
    };
    const taskCompleteTool = {
        name: "nerf_task_complete",
        label: "Complete Task",
        description: "Record a completed task to the NERF database, render a SUMMARY.md to disk, and toggle the plan checkbox — all in one atomic operation. " +
            "Writes the task row inside a transaction, then performs filesystem writes outside the transaction.",
        promptSnippet: "Complete a NERF task (DB write + summary render + checkbox toggle)",
        promptGuidelines: [
            "Use nerf_task_complete (or nerf_complete_task) when a task is finished and needs to be recorded.",
            "All string fields are required. verificationEvidence is an array of objects with command, exitCode, verdict, durationMs.",
            "The tool validates required fields and returns an error message if any are missing.",
            "On success, returns the summaryPath where the SUMMARY.md was written.",
            "Idempotent — calling with the same params twice will upsert (INSERT OR REPLACE) without error.",
        ],
        parameters: Type.Object({
            taskId: Type.String({ description: "Task ID (e.g. T01)" }),
            sliceId: Type.String({ description: "Slice ID (e.g. S01)" }),
            milestoneId: Type.String({ description: "Milestone ID (e.g. M001)" }),
            oneLiner: Type.String({ description: "One-line summary of what was accomplished" }),
            narrative: Type.String({ description: "Detailed narrative of what happened during the task" }),
            verification: Type.String({ description: "What was verified and how — commands run, tests passed, behavior confirmed" }),
            deviations: Type.String({ description: "Deviations from the task plan, or 'None.'" }),
            knownIssues: Type.String({ description: "Known issues discovered but not fixed, or 'None.'" }),
            keyFiles: Type.Array(Type.String(), { description: "List of key files created or modified" }),
            keyDecisions: Type.Array(Type.String(), { description: "List of key decisions made during this task" }),
            blockerDiscovered: Type.Boolean({ description: "Whether a plan-invalidating blocker was discovered" }),
            verificationEvidence: Type.Array(Type.Object({
                command: Type.String({ description: "Verification command that was run" }),
                exitCode: Type.Number({ description: "Exit code of the command" }),
                verdict: Type.String({ description: "Pass/fail verdict (e.g. '✅ pass', '❌ fail')" }),
                durationMs: Type.Number({ description: "Duration of the command in milliseconds" }),
            }), { description: "Array of verification evidence entries" }),
        }),
        execute: taskCompleteExecute,
    };
    pi.registerTool(taskCompleteTool);
    // ─── nerf_slice_complete (nerf_complete_slice alias) ─────────────────────
    const sliceCompleteExecute = async (_toolCallId, params, _signal, _onUpdate, _ctx) => {
        const dbAvailable = await ensureDbOpen();
        if (!dbAvailable) {
            return {
                content: [{ type: "text", text: "Error: NERF database is not available. Cannot complete slice." }],
                details: { operation: "complete_slice", error: "db_unavailable" },
            };
        }
        try {
            const { handleCompleteSlice } = await import("../tools/complete-slice.js");
            const result = await handleCompleteSlice(params, process.cwd());
            if ("error" in result) {
                return {
                    content: [{ type: "text", text: `Error completing slice: ${result.error}` }],
                    details: { operation: "complete_slice", error: result.error },
                };
            }
            return {
                content: [{ type: "text", text: `Completed slice ${result.sliceId} (${result.milestoneId})` }],
                details: {
                    operation: "complete_slice",
                    sliceId: result.sliceId,
                    milestoneId: result.milestoneId,
                    summaryPath: result.summaryPath,
                    uatPath: result.uatPath,
                },
            };
        }
        catch (err) {
            const msg = err instanceof Error ? err.message : String(err);
            logError("tool", `complete_slice tool failed: ${msg}`, { tool: "nerf_slice_complete", error: String(err) });
            return {
                content: [{ type: "text", text: `Error completing slice: ${msg}` }],
                details: { operation: "complete_slice", error: msg },
            };
        }
    };
    const sliceCompleteTool = {
        name: "nerf_slice_complete",
        label: "Complete Slice",
        description: "Record a completed slice to the NERF database, render SUMMARY.md + UAT.md to disk, and toggle the roadmap checkbox — all in one atomic operation. " +
            "Validates all tasks are complete before proceeding. Writes the slice row inside a transaction, then performs filesystem writes outside the transaction.",
        promptSnippet: "Complete a NERF slice (DB write + summary/UAT render + roadmap checkbox toggle)",
        promptGuidelines: [
            "Use nerf_slice_complete (or nerf_complete_slice) when all tasks in a slice are finished and the slice needs to be recorded.",
            "All tasks in the slice must have status 'complete' — the handler validates this before proceeding.",
            "On success, returns summaryPath and uatPath where the files were written.",
            "Idempotent — calling with the same params twice will not crash.",
        ],
        parameters: Type.Object({
            sliceId: Type.String({ description: "Slice ID (e.g. S01)" }),
            milestoneId: Type.String({ description: "Milestone ID (e.g. M001)" }),
            sliceTitle: Type.String({ description: "Title of the slice" }),
            oneLiner: Type.String({ description: "One-line summary of what the slice accomplished" }),
            narrative: Type.String({ description: "Detailed narrative of what happened across all tasks" }),
            verification: Type.String({ description: "What was verified across all tasks" }),
            deviations: Type.String({ description: "Deviations from the slice plan, or 'None.'" }),
            knownLimitations: Type.String({ description: "Known limitations or gaps, or 'None.'" }),
            followUps: Type.String({ description: "Follow-up work discovered during execution, or 'None.'" }),
            keyFiles: Type.Array(Type.String(), { description: "Key files created or modified" }),
            keyDecisions: Type.Array(Type.String(), { description: "Key decisions made during this slice" }),
            patternsEstablished: Type.Array(Type.String(), { description: "Patterns established by this slice" }),
            observabilitySurfaces: Type.Array(Type.String(), { description: "Observability surfaces added" }),
            provides: Type.Array(Type.String(), { description: "What this slice provides to downstream slices" }),
            requirementsSurfaced: Type.Array(Type.String(), { description: "New requirements surfaced" }),
            drillDownPaths: Type.Array(Type.String(), { description: "Paths to task summaries for drill-down" }),
            affects: Type.Array(Type.String(), { description: "Downstream slices affected" }),
            requirementsAdvanced: Type.Array(Type.Object({
                id: Type.String({ description: "Requirement ID" }),
                how: Type.String({ description: "How it was advanced" }),
            }), { description: "Requirements advanced by this slice" }),
            requirementsValidated: Type.Array(Type.Object({
                id: Type.String({ description: "Requirement ID" }),
                proof: Type.String({ description: "What proof validates it" }),
            }), { description: "Requirements validated by this slice" }),
            requirementsInvalidated: Type.Array(Type.Object({
                id: Type.String({ description: "Requirement ID" }),
                what: Type.String({ description: "What changed" }),
            }), { description: "Requirements invalidated or re-scoped" }),
            filesModified: Type.Array(Type.Object({
                path: Type.String({ description: "File path" }),
                description: Type.String({ description: "What changed" }),
            }), { description: "Files modified with descriptions" }),
            requires: Type.Array(Type.Object({
                slice: Type.String({ description: "Dependency slice ID" }),
                provides: Type.String({ description: "What was consumed from it" }),
            }), { description: "Upstream slice dependencies consumed" }),
            uatContent: Type.String({ description: "UAT test content (markdown body)" }),
        }),
        execute: sliceCompleteExecute,
    };
    pi.registerTool(sliceCompleteTool);
    // ─── nerf_complete_milestone ────────────────────────────────────────────
    const milestoneCompleteExecute = async (_toolCallId, params, _signal, _onUpdate, _ctx) => {
        const dbAvailable = await ensureDbOpen();
        if (!dbAvailable) {
            return {
                content: [{ type: "text", text: "Error: NERF database is not available. Cannot complete milestone." }],
                details: { operation: "complete_milestone", error: "db_unavailable" },
            };
        }
        try {
            const { handleCompleteMilestone } = await import("../tools/complete-milestone.js");
            const result = await handleCompleteMilestone(params, process.cwd());
            if ("error" in result) {
                return {
                    content: [{ type: "text", text: `Error completing milestone: ${result.error}` }],
                    details: { operation: "complete_milestone", error: result.error },
                };
            }
            return {
                content: [{ type: "text", text: `Completed milestone ${result.milestoneId}. Summary written to ${result.summaryPath}` }],
                details: {
                    operation: "complete_milestone",
                    milestoneId: result.milestoneId,
                    summaryPath: result.summaryPath,
                },
            };
        }
        catch (err) {
            const msg = err instanceof Error ? err.message : String(err);
            logError("tool", `complete_milestone tool failed: ${msg}`, { tool: "nerf_complete_milestone", error: String(err) });
            return {
                content: [{ type: "text", text: `Error completing milestone: ${msg}` }],
                details: { operation: "complete_milestone", error: msg },
            };
        }
    };
    const milestoneCompleteTool = {
        name: "nerf_complete_milestone",
        label: "Complete Milestone",
        description: "Record a completed milestone to the NERF database, render MILESTONE-SUMMARY.md to disk — all in one atomic operation. " +
            "Validates all slices are complete before proceeding.",
        promptSnippet: "Complete a NERF milestone (DB write + summary render)",
        promptGuidelines: [
            "Use nerf_complete_milestone when all slices in a milestone are finished and the milestone needs to be recorded.",
            "All slices in the milestone must have status 'complete' — the handler validates this before proceeding.",
            "verificationPassed must be explicitly set to true — the handler rejects completion if verification did not pass.",
            "On success, returns summaryPath where the MILESTONE-SUMMARY.md was written.",
        ],
        parameters: Type.Object({
            milestoneId: Type.String({ description: "Milestone ID (e.g. M001)" }),
            title: Type.String({ description: "Milestone title" }),
            oneLiner: Type.String({ description: "One-sentence summary of what the milestone achieved" }),
            narrative: Type.String({ description: "Detailed narrative of what happened during the milestone" }),
            successCriteriaResults: Type.String({ description: "Markdown detailing how each success criterion was met or not met" }),
            definitionOfDoneResults: Type.String({ description: "Markdown detailing how each definition-of-done item was met" }),
            requirementOutcomes: Type.String({ description: "Markdown detailing requirement status transitions with evidence" }),
            keyDecisions: Type.Array(Type.String(), { description: "Key architectural/pattern decisions made during the milestone" }),
            keyFiles: Type.Array(Type.String(), { description: "Key files created or modified during the milestone" }),
            lessonsLearned: Type.Array(Type.String(), { description: "Lessons learned during the milestone" }),
            followUps: Type.Optional(Type.String({ description: "Follow-up items for future milestones" })),
            deviations: Type.Optional(Type.String({ description: "Deviations from the original plan" })),
            verificationPassed: Type.Boolean({ description: "Must be true — confirms that code change verification, success criteria, and definition of done checks all passed before completion" }),
        }),
        execute: milestoneCompleteExecute,
    };
    pi.registerTool(milestoneCompleteTool);
    // ─── nerf_validate_milestone (milestone_validate alias) ─────────────
    const milestoneValidateExecute = async (_toolCallId, params, _signal, _onUpdate, _ctx) => {
        const dbAvailable = await ensureDbOpen();
        if (!dbAvailable) {
            return {
                content: [{ type: "text", text: "Error: NERF database is not available. Cannot validate milestone." }],
                details: { operation: "validate_milestone", error: "db_unavailable" },
            };
        }
        try {
            const { handleValidateMilestone } = await import("../tools/validate-milestone.js");
            const result = await handleValidateMilestone(params, process.cwd());
            if ("error" in result) {
                return {
                    content: [{ type: "text", text: `Error validating milestone: ${result.error}` }],
                    details: { operation: "validate_milestone", error: result.error },
                };
            }
            return {
                content: [{ type: "text", text: `Validated milestone ${result.milestoneId} — verdict: ${result.verdict}. Written to ${result.validationPath}` }],
                details: {
                    operation: "validate_milestone",
                    milestoneId: result.milestoneId,
                    verdict: result.verdict,
                    validationPath: result.validationPath,
                },
            };
        }
        catch (err) {
            const msg = err instanceof Error ? err.message : String(err);
            logError("tool", `validate_milestone tool failed: ${msg}`, { tool: "nerf_validate_milestone", error: String(err) });
            return {
                content: [{ type: "text", text: `Error validating milestone: ${msg}` }],
                details: { operation: "validate_milestone", error: msg },
            };
        }
    };
    const milestoneValidateTool = {
        name: "nerf_validate_milestone",
        label: "Validate Milestone",
        description: "Validate a milestone before completion — persist validation results to the DB, render VALIDATION.md to disk. " +
            "Records verdict (pass/needs-attention/needs-remediation) and rationale.",
        promptSnippet: "Validate a NERF milestone (DB write + VALIDATION.md render)",
        promptGuidelines: [
            "Use nerf_validate_milestone when all slices are done and the milestone needs validation before completion.",
            "Parameters: milestoneId, verdict, remediationRound, successCriteriaChecklist, sliceDeliveryAudit, crossSliceIntegration, requirementCoverage, verificationClasses (optional), verdictRationale, remediationPlan (optional).",
            "If verdict is 'needs-remediation', also provide remediationPlan and use nerf_reassess_roadmap to add remediation slices to the roadmap.",
            "On success, returns validationPath where VALIDATION.md was written.",
        ],
        parameters: Type.Object({
            milestoneId: Type.String({ description: "Milestone ID (e.g. M001)" }),
            verdict: StringEnum(["pass", "needs-attention", "needs-remediation"], { description: "Validation verdict" }),
            remediationRound: Type.Number({ description: "Remediation round (0 for first validation)" }),
            successCriteriaChecklist: Type.String({ description: "Markdown checklist of success criteria with pass/fail and evidence" }),
            sliceDeliveryAudit: Type.String({ description: "Markdown table auditing each slice's claimed vs delivered output" }),
            crossSliceIntegration: Type.String({ description: "Markdown describing any cross-slice boundary mismatches" }),
            requirementCoverage: Type.String({ description: "Markdown describing any unaddressed requirements" }),
            verificationClasses: Type.Optional(Type.String({ description: "Markdown describing verification class compliance and gaps" })),
            verdictRationale: Type.String({ description: "Why this verdict was chosen" }),
            remediationPlan: Type.Optional(Type.String({ description: "Remediation plan (required if verdict is needs-remediation)" })),
        }),
        execute: milestoneValidateExecute,
    };
    pi.registerTool(milestoneValidateTool);
    // ─── nerf_replan_slice (slice_replan alias) ─────────────────────────
    const replanSliceExecute = async (_toolCallId, params, _signal, _onUpdate, _ctx) => {
        const dbAvailable = await ensureDbOpen();
        if (!dbAvailable) {
            return {
                content: [{ type: "text", text: "Error: NERF database is not available. Cannot replan slice." }],
                details: { operation: "replan_slice", error: "db_unavailable" },
            };
        }
        try {
            const { handleReplanSlice } = await import("../tools/replan-slice.js");
            const result = await handleReplanSlice(params, process.cwd());
            if ("error" in result) {
                return {
                    content: [{ type: "text", text: `Error replanning slice: ${result.error}` }],
                    details: { operation: "replan_slice", error: result.error },
                };
            }
            return {
                content: [{ type: "text", text: `Replanned slice ${result.sliceId} (${result.milestoneId})` }],
                details: {
                    operation: "replan_slice",
                    milestoneId: result.milestoneId,
                    sliceId: result.sliceId,
                    replanPath: result.replanPath,
                    planPath: result.planPath,
                },
            };
        }
        catch (err) {
            const msg = err instanceof Error ? err.message : String(err);
            logError("tool", `replan_slice tool failed: ${msg}`, { tool: "nerf_replan_slice", error: String(err) });
            return {
                content: [{ type: "text", text: `Error replanning slice: ${msg}` }],
                details: { operation: "replan_slice", error: msg },
            };
        }
    };
    const replanSliceTool = {
        name: "nerf_replan_slice",
        label: "Replan Slice",
        description: "Replan a slice after a blocker is discovered. Structurally enforces preservation of completed tasks — " +
            "mutations to completed task IDs are rejected with actionable error payloads. Writes replan history to DB, " +
            "applies task mutations, re-renders PLAN.md, and renders REPLAN.md.",
        promptSnippet: "Replan a NERF slice with structural enforcement of completed tasks",
        promptGuidelines: [
            "Use nerf_replan_slice (canonical) or nerf_slice_replan when a blocker is discovered and the slice plan needs rewriting.",
            "The tool structurally enforces that completed tasks cannot be updated or removed — violations return specific error payloads naming the blocked task ID.",
            "Parameters: milestoneId, sliceId, blockerTaskId, blockerDescription, whatChanged, updatedTasks (array), removedTaskIds (array).",
            "updatedTasks items: taskId, title, description, estimate, files, verify, inputs, expectedOutput.",
        ],
        parameters: Type.Object({
            milestoneId: Type.String({ description: "Milestone ID (e.g. M001)" }),
            sliceId: Type.String({ description: "Slice ID (e.g. S01)" }),
            blockerTaskId: Type.String({ description: "Task ID that discovered the blocker" }),
            blockerDescription: Type.String({ description: "Description of the blocker" }),
            whatChanged: Type.String({ description: "Summary of what changed in the plan" }),
            updatedTasks: Type.Array(Type.Object({
                taskId: Type.String({ description: "Task ID (e.g. T01)" }),
                title: Type.String({ description: "Task title" }),
                description: Type.String({ description: "Task description / steps block" }),
                estimate: Type.String({ description: "Task estimate string" }),
                files: Type.Array(Type.String(), { description: "Files likely touched" }),
                verify: Type.String({ description: "Verification command or block" }),
                inputs: Type.Array(Type.String(), { description: "Input files or references" }),
                expectedOutput: Type.Array(Type.String(), { description: "Expected output files or artifacts" }),
            }), { description: "Tasks to upsert (update existing or insert new)" }),
            removedTaskIds: Type.Array(Type.String(), { description: "Task IDs to remove from the slice" }),
        }),
        execute: replanSliceExecute,
    };
    pi.registerTool(replanSliceTool);
    // ─── nerf_reassess_roadmap (roadmap_reassess alias) ─────────────────
    const reassessRoadmapExecute = async (_toolCallId, params, _signal, _onUpdate, _ctx) => {
        const dbAvailable = await ensureDbOpen();
        if (!dbAvailable) {
            return {
                content: [{ type: "text", text: "Error: NERF database is not available. Cannot reassess roadmap." }],
                details: { operation: "reassess_roadmap", error: "db_unavailable" },
            };
        }
        try {
            const { handleReassessRoadmap } = await import("../tools/reassess-roadmap.js");
            const result = await handleReassessRoadmap(params, process.cwd());
            if ("error" in result) {
                return {
                    content: [{ type: "text", text: `Error reassessing roadmap: ${result.error}` }],
                    details: { operation: "reassess_roadmap", error: result.error },
                };
            }
            return {
                content: [{ type: "text", text: `Reassessed roadmap for milestone ${result.milestoneId} after ${result.completedSliceId}` }],
                details: {
                    operation: "reassess_roadmap",
                    milestoneId: result.milestoneId,
                    completedSliceId: result.completedSliceId,
                    assessmentPath: result.assessmentPath,
                    roadmapPath: result.roadmapPath,
                },
            };
        }
        catch (err) {
            const msg = err instanceof Error ? err.message : String(err);
            logError("tool", `reassess_roadmap tool failed: ${msg}`, { tool: "nerf_reassess_roadmap", error: String(err) });
            return {
                content: [{ type: "text", text: `Error reassessing roadmap: ${msg}` }],
                details: { operation: "reassess_roadmap", error: msg },
            };
        }
    };
    const reassessRoadmapTool = {
        name: "nerf_reassess_roadmap",
        label: "Reassess Roadmap",
        description: "Reassess the milestone roadmap after a slice completes. Structurally enforces preservation of completed slices — " +
            "mutations to completed slice IDs are rejected with actionable error payloads. Writes assessment to DB, " +
            "applies slice mutations, re-renders ROADMAP.md, and renders ASSESSMENT.md.",
        promptSnippet: "Reassess a NERF roadmap with structural enforcement of completed slices",
        promptGuidelines: [
            "Use nerf_reassess_roadmap (canonical) or nerf_roadmap_reassess after a slice completes to reassess the roadmap.",
            "The tool structurally enforces that completed slices cannot be modified or removed — violations return specific error payloads naming the blocked slice ID.",
            "Parameters: milestoneId, completedSliceId, verdict, assessment, sliceChanges (object with modified, added, removed arrays).",
            "sliceChanges.modified items: sliceId, title, risk (optional), depends (optional), demo (optional).",
        ],
        parameters: Type.Object({
            milestoneId: Type.String({ description: "Milestone ID (e.g. M001)" }),
            completedSliceId: Type.String({ description: "Slice ID that just completed" }),
            verdict: Type.String({ description: "Assessment verdict (e.g. 'roadmap-confirmed', 'roadmap-adjusted')" }),
            assessment: Type.String({ description: "Assessment text explaining the decision" }),
            sliceChanges: Type.Object({
                modified: Type.Array(Type.Object({
                    sliceId: Type.String({ description: "Slice ID to modify" }),
                    title: Type.String({ description: "Updated slice title" }),
                    risk: Type.Optional(Type.String({ description: "Updated risk level" })),
                    depends: Type.Optional(Type.Array(Type.String(), { description: "Updated dependencies" })),
                    demo: Type.Optional(Type.String({ description: "Updated demo text" })),
                }), { description: "Slices to modify" }),
                added: Type.Array(Type.Object({
                    sliceId: Type.String({ description: "New slice ID" }),
                    title: Type.String({ description: "New slice title" }),
                    risk: Type.Optional(Type.String({ description: "Risk level" })),
                    depends: Type.Optional(Type.Array(Type.String(), { description: "Dependencies" })),
                    demo: Type.Optional(Type.String({ description: "Demo text" })),
                }), { description: "New slices to add" }),
                removed: Type.Array(Type.String(), { description: "Slice IDs to remove" }),
            }, { description: "Slice changes to apply" }),
        }),
        execute: reassessRoadmapExecute,
    };
    pi.registerTool(reassessRoadmapTool);
    // ─── nerf_save_gate_result ──────────────────────────────────────────────
    const saveGateResultExecute = async (_toolCallId, params, _signal, _onUpdate, _ctx) => {
        const dbAvailable = await ensureDbOpen();
        if (!dbAvailable) {
            return {
                content: [{ type: "text", text: "Error: NERF database is not available." }],
                details: { operation: "save_gate_result", error: "db_unavailable" },
            };
        }
        const validGates = ["Q3", "Q4", "Q5", "Q6", "Q7", "Q8"];
        if (!validGates.includes(params.gateId)) {
            return {
                content: [{ type: "text", text: `Error: Invalid gateId "${params.gateId}". Must be one of: ${validGates.join(", ")}` }],
                details: { operation: "save_gate_result", error: "invalid_gate_id" },
            };
        }
        const validVerdicts = ["pass", "flag", "omitted"];
        if (!validVerdicts.includes(params.verdict)) {
            return {
                content: [{ type: "text", text: `Error: Invalid verdict "${params.verdict}". Must be one of: ${validVerdicts.join(", ")}` }],
                details: { operation: "save_gate_result", error: "invalid_verdict" },
            };
        }
        try {
            const { saveGateResult } = await import("../nerf-db.js");
            const { invalidateStateCache } = await import("../state.js");
            saveGateResult({
                milestoneId: params.milestoneId,
                sliceId: params.sliceId,
                gateId: params.gateId,
                taskId: params.taskId ?? "",
                verdict: params.verdict,
                rationale: params.rationale,
                findings: params.findings ?? "",
            });
            invalidateStateCache();
            return {
                content: [{ type: "text", text: `Gate ${params.gateId} result saved: verdict=${params.verdict}` }],
                details: { operation: "save_gate_result", gateId: params.gateId, verdict: params.verdict },
            };
        }
        catch (err) {
            const msg = err instanceof Error ? err.message : String(err);
            logError("tool", `nerf_save_gate_result failed: ${msg}`, { tool: "nerf_save_gate_result", error: String(err) });
            return {
                content: [{ type: "text", text: `Error saving gate result: ${msg}` }],
                details: { operation: "save_gate_result", error: msg },
            };
        }
    };
    const saveGateResultTool = {
        name: "nerf_save_gate_result",
        label: "Save Gate Result",
        description: "Save the result of a quality gate evaluation (Q3-Q8) to the NERF database. " +
            "Called by gate evaluation sub-agents after analyzing a specific quality question.",
        promptSnippet: "Save quality gate evaluation result (verdict, rationale, findings)",
        promptGuidelines: [
            "Use nerf_save_gate_result after evaluating a quality gate question.",
            "gateId must be one of: Q3, Q4, Q5, Q6, Q7, Q8.",
            "verdict must be: pass (no concerns), flag (concerns found), or omitted (not applicable).",
            "rationale should be a one-sentence justification for the verdict.",
            "findings should contain detailed markdown analysis (or empty string if omitted).",
        ],
        parameters: Type.Object({
            milestoneId: Type.String({ description: "Milestone ID (e.g. M001)" }),
            sliceId: Type.String({ description: "Slice ID (e.g. S01)" }),
            gateId: Type.String({ description: "Gate ID: Q3, Q4, Q5, Q6, Q7, or Q8" }),
            taskId: Type.Optional(Type.String({ description: "Task ID for task-scoped gates (Q5/Q6/Q7)" })),
            verdict: Type.String({ description: "pass, flag, or omitted" }),
            rationale: Type.String({ description: "One-sentence justification" }),
            findings: Type.Optional(Type.String({ description: "Detailed markdown findings" })),
        }),
        execute: saveGateResultExecute,
        renderCall(args, theme) {
            let text = theme.fg("toolTitle", theme.bold("save_gate_result "));
            text += theme.fg("accent", args.gateId ?? "");
            text += theme.fg("dim", ` → ${args.verdict ?? ""}`);
            return new Text(text, 0, 0);
        },
        renderResult(result, _options, theme) {
            const d = result.details;
            if (result.isError || d?.error) {
                return new Text(theme.fg("error", `Error: ${d?.error ?? "unknown"}`), 0, 0);
            }
            const color = d?.verdict === "flag" ? "warning" : "success";
            return new Text(theme.fg(color, `${d?.gateId}: ${d?.verdict}`), 0, 0);
        },
    };
    pi.registerTool(saveGateResultTool);
}
