// engine/cascade-hooks/core/append-releases.ts — SPEC-714: Core action 2
// Appends spec to releases/pending.json within a 2-second AbortController budget.
// Logic extracted verbatim from src/tools/update-status-actions.ts (SPEC-649/SPEC-660 block).
import { join } from 'node:path';
import { readFile, writeFile, mkdir } from 'node:fs/promises';
import { specStore } from '../../../storage/index.js';
const CORE_ACTION_BUDGET_MS = 2000;
async function actuallyAppendReleasesPending(ctx, opts) {
    const { projectPath, projectId, specId } = ctx;
    if (!projectPath || ctx.newStatus !== 'done') {
        return;
    }
    if (opts.signal.aborted) {
        throw new Error('append-releases-pending aborted before start');
    }
    const releasesDir = join(projectPath, 'planu', 'releases');
    const pendingPath = join(releasesDir, 'pending.json');
    await new Promise((resolve, reject) => {
        opts.signal.addEventListener('abort', () => {
            reject(new Error('CoreActionTimeoutError: append-releases-pending timed out'));
        });
        (async () => {
            await mkdir(releasesDir, { recursive: true });
            const spec = await specStore.getSpec(projectId, specId);
            let pendingList = [];
            try {
                const raw = await readFile(pendingPath, 'utf-8');
                const parsed = JSON.parse(raw);
                if (Array.isArray(parsed)) {
                    pendingList = parsed;
                }
            }
            catch {
                /* file doesn't exist yet — start fresh */
            }
            const completedAt = new Date().toISOString().substring(0, 10);
            pendingList = pendingList.filter((entry) => entry.specId !== specId);
            pendingList.push({ specId, title: spec?.title ?? specId, completedAt });
            await writeFile(pendingPath, JSON.stringify(pendingList, null, 2), 'utf-8');
            // Auto-commit planu/ changes so pending.json is never left unstaged
            void (async () => {
                try {
                    const { planuAutoCommit } = await import('../../git/planu-autocommit.js');
                    await planuAutoCommit({ projectPath, reason: 'status-update' });
                }
                catch {
                    /* best-effort */
                }
            })();
        })()
            .then(() => {
            resolve();
        })
            .catch((err) => {
            void err; // best-effort — surface as result, not throw
            resolve();
        });
    });
}
export async function appendReleasesPending(ctx) {
    const controller = new AbortController();
    const timer = setTimeout(() => {
        controller.abort();
    }, CORE_ACTION_BUDGET_MS);
    try {
        await actuallyAppendReleasesPending(ctx, { signal: controller.signal });
        return { ok: true };
    }
    catch (err) {
        return { ok: false, error: err instanceof Error ? err.message : String(err) };
    }
    finally {
        clearTimeout(timer);
    }
}
//# sourceMappingURL=append-releases.js.map