import { mkdir, writeFile } from "node:fs/promises";
import { dirname } from "node:path";
// ---------------------------------------------------------------------------
// Reclassify gate for :KnowledgeDocument operator-solicited classification.
//
// Sole consumer today: kd-classify (memory plugin, generic). Email no longer
// ships a per-thread reclassify wrapper — the conversation-archive ingest
// pipeline writes sections at archive time (Task 445).
//
// Task 401.
// ---------------------------------------------------------------------------
/**
 * Body-growth threshold above which a reclassify is allowed. Below this the
 * gate returns "skip" because section topology is unlikely to have shifted.
 * Picked to fire on roughly 2-3 new messages in a 10-message thread.
 */
export const KD_CLASSIFY_GROWTH_THRESHOLD = 0.25;
/** Decide whether a classify call should proceed based on body-length delta. */
export function decideGate({ bodyLen, lastClassifiedBodyLength }) {
    if (lastClassifiedBodyLength <= 0) {
        // First-time classify — no prior stamp.
        return { action: "proceed", growthPct: 1, reason: null };
    }
    const growth = (bodyLen - lastClassifiedBodyLength) / lastClassifiedBodyLength;
    if (growth >= KD_CLASSIFY_GROWTH_THRESHOLD) {
        return { action: "proceed", growthPct: growth, reason: null };
    }
    const pctRounded = Math.round(growth * 100);
    return {
        action: "skip",
        growthPct: growth,
        reason: `no classification needed (body grew ${pctRounded}% since last ingest; threshold ${Math.round(KD_CLASSIFY_GROWTH_THRESHOLD * 100)}%)`,
    };
}
/**
 * Write the KD's body to a deterministic temp-file path so the librarian can
 * feed it through memory-ingest-extract → memory-ingest unchanged. Deterministic
 * path = idempotent under repeat calls; the file is overwritten if it exists.
 */
export async function writeClassifyTempFile(accountDir, attachmentId, body) {
    const path = `${accountDir}/tmp/kd-classify-${attachmentId}.txt`;
    await mkdir(dirname(path), { recursive: true });
    await writeFile(path, body, "utf-8");
    return path;
}
/**
 * Build the dispatch envelope the operator-visible tool returns. Admin reads
 * the envelope and uses the Task tool to dispatch the librarian specialist;
 * librarian runs the document-ingest skill against `tempFilePath` with the
 * named `attachmentId` so the resulting :Section children land under the
 * pre-existing :KnowledgeDocument (memory-ingest is keyed on attachmentId).
 */
export function buildDispatchEnvelope(opts) {
    const growthLabel = opts.lastClassifiedBodyLength > 0
        ? `${Math.round(opts.growthPct * 100)}% growth since last ingest`
        : "first classify";
    return [
        `Ready to classify ${opts.source} :KnowledgeDocument into sections.`,
        `attachmentId: ${opts.attachmentId}`,
        `bodyLen: ${opts.bodyLen} chars (${growthLabel})`,
        `tempFilePath: ${opts.tempFilePath}`,
        ``,
        `Next: dispatch the \`librarian\` specialist via the Task tool with this brief —`,
        `  "Ingest the document at ${opts.tempFilePath} using mode=document, attachmentId=${opts.attachmentId},`,
        `   anchor=LocalBusiness. The :KnowledgeDocument already exists and has source=${opts.source};`,
        `   memory-ingest will MERGE by attachmentId and write :Section children, replacing any prior."`,
    ].join("\n");
}
//# sourceMappingURL=kd-classify-gate.js.map