"use strict";
// SPDX-License-Identifier: AGPL-3.0-or-later
// Copyright (C) 2024-2026 Gracker (Chris)
// This file is part of SmartPerfetto. See LICENSE for details.
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.promoteSkillNote = promoteSkillNote;
/**
 * CLI to promote a runtime skill note (under logs/skill_notes/) to the
 * curated baseline (backend/skills/curated_skill_notes/) which is checked
 * into git. The promoted note is removed from the runtime file so it
 * doesn't double-count at injection time.
 *
 * Usage:
 *   npx tsx src/agentv3/selfImprove/promoteSkillNote.ts <skillId> <noteId> [--dry-run]
 *
 * The runtime file lives in `logs/` (gitignored) so skill notes don't
 * pollute repo history with auto-generated content. Promotion is a manual
 * gate — a human reviews the note and explicitly elevates it.
 */
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const skillNotesWriter_1 = require("./skillNotesWriter");
const runtimePaths_1 = require("../../runtimePaths");
const RUNTIME_DIR = (0, runtimePaths_1.backendLogPath)('skill_notes');
const CURATED_DIR = path.resolve(__dirname, '..', '..', '..', 'skills', 'curated_skill_notes');
/**
 * Move a single note from runtime → curated. Idempotent: a second call with
 * the same arguments is a no-op once the runtime entry is gone.
 */
function promoteSkillNote(skillId, noteId, opts = {}) {
    const runtimeDir = opts.runtimeDir ?? RUNTIME_DIR;
    const curatedDir = opts.curatedDir ?? CURATED_DIR;
    const runtimeFile = path.join(runtimeDir, `${skillId}.notes.json`);
    const curatedFile = path.join(curatedDir, `${skillId}.notes.json`);
    if (!fs.existsSync(runtimeFile)) {
        return { ok: false, reason: 'skill_not_found', details: `${runtimeFile} does not exist` };
    }
    const runtime = (0, skillNotesWriter_1.readSkillNotesFile)(runtimeFile);
    const noteIdx = runtime.notes.findIndex(n => n.id === noteId);
    if (noteIdx < 0) {
        return { ok: false, reason: 'note_not_found', details: `noteId ${noteId} not found in ${runtimeFile}` };
    }
    const note = runtime.notes[noteIdx];
    const curated = fs.existsSync(curatedFile)
        ? (0, skillNotesWriter_1.readSkillNotesFile)(curatedFile)
        : { schemaVersion: 1, skillId, notes: [], lastUpdated: 0, totalBytes: 0 };
    if (curated.notes.some(n => n.id === note.id)) {
        return { ok: false, reason: 'already_curated', details: `note ${note.id} already in curated baseline` };
    }
    if (opts.dryRun) {
        return {
            ok: true,
            curatedPath: curatedFile,
            details: 'dry-run — no files modified',
        };
    }
    try {
        if (!fs.existsSync(curatedDir))
            fs.mkdirSync(curatedDir, { recursive: true });
        const updatedCurated = {
            ...curated,
            notes: [...curated.notes, note],
            lastUpdated: Date.now(),
        };
        updatedCurated.totalBytes = Buffer.byteLength(JSON.stringify(updatedCurated, null, 2), 'utf-8');
        atomicWrite(curatedFile, updatedCurated);
        const updatedRuntime = {
            ...runtime,
            notes: runtime.notes.filter(n => n.id !== note.id),
            lastUpdated: Date.now(),
        };
        updatedRuntime.totalBytes = Buffer.byteLength(JSON.stringify(updatedRuntime, null, 2), 'utf-8');
        atomicWrite(runtimeFile, updatedRuntime);
        return { ok: true, curatedPath: curatedFile };
    }
    catch (err) {
        return { ok: false, reason: 'io_error', details: err.message };
    }
}
function atomicWrite(file, data) {
    const tmp = `${file}.tmp`;
    fs.writeFileSync(tmp, JSON.stringify(data, null, 2));
    fs.renameSync(tmp, file);
}
function printUsage() {
    console.error('Usage: npx tsx src/agentv3/selfImprove/promoteSkillNote.ts <skillId> <noteId> [--dry-run]');
}
async function main() {
    const args = process.argv.slice(2);
    if (args.length < 2) {
        printUsage();
        process.exit(2);
    }
    const [skillId, noteId, ...rest] = args;
    const dryRun = rest.includes('--dry-run');
    const result = promoteSkillNote(skillId, noteId, { dryRun });
    if (result.ok) {
        console.log(`[promote] ${dryRun ? 'would promote' : 'promoted'} ${skillId}/${noteId}`);
        if (result.curatedPath)
            console.log(`[promote] target: ${result.curatedPath}`);
    }
    else {
        console.error(`[promote] failed (${result.reason}): ${result.details}`);
        process.exit(1);
    }
}
if (require.main === module) {
    main().catch(err => {
        console.error('[promote] unhandled:', err);
        process.exit(1);
    });
}
//# sourceMappingURL=promoteSkillNote.js.map