UNPKG

paqad-ai

Version:

Spec-driven development framework — AI agents that think before they type

103 lines (100 loc) • 3.57 kB
import { createRequire as __paqadCreateRequire } from 'module'; const require = __paqadCreateRequire(import.meta.url); import { FEATURE_EVIDENCE_SCHEMA_VERSION, FEATURE_SESSION_DOC_TYPE, featureSessionControlPath } from "./chunk-AZLA53A6.js"; import { init_esm_shims } from "./chunk-IDFRWBMN.js"; // src/feature-evidence/session-control.ts init_esm_shims(); import { mkdirSync, readFileSync, writeFileSync } from "fs"; import { dirname, join } from "path"; function emptyControl(sessionId, now = () => /* @__PURE__ */ new Date()) { return { schema_version: FEATURE_EVIDENCE_SCHEMA_VERSION, doc_type: FEATURE_SESSION_DOC_TYPE, session_id: sessionId, active: null, paused: [], lane: null, updated_at: now().toISOString() }; } function readSessionControl(projectRoot, sessionId, now = () => /* @__PURE__ */ new Date()) { try { const raw = readFileSync(join(projectRoot, featureSessionControlPath(sessionId)), "utf8"); const parsed = JSON.parse(raw); if (isControl(parsed)) { return parsed; } } catch { } return emptyControl(sessionId, now); } function writeSessionControl(projectRoot, control, now = () => /* @__PURE__ */ new Date(), writtenBy) { const stamped = { ...control, written_by: writtenBy ?? control.written_by ?? "unknown", pid: process.pid, updated_at: now().toISOString() }; const abs = join(projectRoot, featureSessionControlPath(control.session_id)); mkdirSync(dirname(abs), { recursive: true }); writeFileSync(abs, `${JSON.stringify(stamped, null, 2)} `, "utf8"); return stamped; } function setActiveFeature(projectRoot, sessionId, dirName, options = {}) { const now = options.now ?? (() => /* @__PURE__ */ new Date()); const control = readSessionControl(projectRoot, sessionId, now); const paused = control.paused.filter((name) => name !== dirName); if (control.active && control.active !== dirName) { paused.push(control.active); } const next = { ...control, active: dirName, paused, lane: options.lane !== void 0 ? options.lane : control.lane }; return writeSessionControl(projectRoot, next, now, options.writtenBy ?? "set-active"); } function resumeFeature(projectRoot, sessionId, dirName, now = () => /* @__PURE__ */ new Date(), writtenBy = "resume") { const control = readSessionControl(projectRoot, sessionId, now); if (control.active === dirName) { return control; } if (!control.paused.includes(dirName)) { return null; } const paused = control.paused.filter((name) => name !== dirName); if (control.active) { paused.push(control.active); } return writeSessionControl(projectRoot, { ...control, active: dirName, paused }, now, writtenBy); } function markDone(projectRoot, sessionId, dirName, now = () => /* @__PURE__ */ new Date()) { const control = readSessionControl(projectRoot, sessionId, now); const next = { ...control, active: control.active === dirName ? null : control.active, paused: control.paused.filter((name) => name !== dirName) }; return writeSessionControl(projectRoot, next, now, "mark-done"); } function isControl(value) { if (typeof value !== "object" || value === null) { return false; } const c = value; return c.doc_type === FEATURE_SESSION_DOC_TYPE && typeof c.session_id === "string" && (c.active === null || typeof c.active === "string") && Array.isArray(c.paused) && c.paused.every((name) => typeof name === "string"); } export { readSessionControl, writeSessionControl, setActiveFeature, resumeFeature, markDone };