lib/autonomous-run-record.js
Rama main · réplica de lectura del repositorio original.
var crypto = require("crypto");
var ACTIVE_STATES = ["armed", "running", "reviewing", "waiting-worker", "waiting-user", "paused"];
var TERMINAL_STATES = ["completed", "stopped", "limit", "error"];
function clean(value, max) { return typeof value === "string" ? value.trim().substring(0, max) : ""; }
function integer(value, fallback, max) { var number = Number(value); return Number.isFinite(number) ? Math.max(1, Math.min(max, Math.floor(number))) : fallback; }
function criteria(value) { return (Array.isArray(value) ? value : []).slice(0, 10).map(function (item) { return clean(item, 1000); }).filter(Boolean); }
function project(run) {
if (!run) return null;
return { id: run.id, state: run.state, objective: run.objective || "", successCriteria: run.successCriteria || [], continuationCount: run.continuationCount || 0,
maxContinuations: run.maxContinuations, startedAt: run.startedAt || null, deadlineAt: run.deadlineAt || null, maxMinutes: run.maxMinutes,
waitingReason: run.waitingReason || "", terminalReason: run.terminalReason || "", outcome: run.outcome || null, pausedAfterRestart: !!run.pausedAfterRestart,
armToken: run.state === "armed" ? run.armToken : undefined };
}
function restore(value) {
if (!value || typeof value !== "object" || ACTIVE_STATES.concat(TERMINAL_STATES).indexOf(value.state) === -1) return null;
var evidence = value.outcome && Array.isArray(value.outcome.evidence) ? value.outcome.evidence.slice(0, 20).map(function (item) { return clean(item, 2000); }).filter(Boolean) : [];
var assessments = value.outcome && Array.isArray(value.outcome.criteria) ? value.outcome.criteria.slice(0, 10).map(function (item) {
return item && { criterion: clean(item.criterion, 1000), met: item.met === true, evidence: clean(item.evidence, 2000) };
}).filter(function (item) { return item && item.criterion && item.evidence; }) : [];
var snapshot = value.permissionSnapshot && typeof value.permissionSnapshot === "object" ? value.permissionSnapshot : {};
var run = { version: 1, id: clean(value.id, 200) || crypto.randomUUID(), state: value.state, objective: clean(value.objective, 20000), successCriteria: criteria(value.successCriteria),
continuationCount: Math.max(0, Math.min(100, Math.floor(Number(value.continuationCount) || 0))), maxContinuations: integer(value.maxContinuations, 10, 100), maxMinutes: integer(value.maxMinutes, 60, 1440),
createdAt: Number.isFinite(value.createdAt) ? value.createdAt : Date.now(), startedAt: Number.isFinite(value.startedAt) ? value.startedAt : null, deadlineAt: Number.isFinite(value.deadlineAt) ? value.deadlineAt : null,
finishedAt: Number.isFinite(value.finishedAt) ? value.finishedAt : null, waitingReason: clean(value.waitingReason, 2000), terminalReason: clean(value.terminalReason, 2000), pausedAfterRestart: !!value.pausedAfterRestart,
cancellationEpoch: Math.max(0, Math.floor(Number(value.cancellationEpoch) || 0)), rateLimitUntil: Number.isFinite(value.rateLimitUntil) ? value.rateLimitUntil : null, continuationPending: false,
wakeSequence: Math.max(0, Math.floor(Number(value.wakeSequence) || 0)), completionRequested: !!value.completionRequested,
permissionSnapshot: { permissionMode: clean(snapshot.permissionMode, 100) || null, permissionModeBeforeFullAccess: clean(snapshot.permissionModeBeforeFullAccess, 100) || null, enabled: snapshot.enabled === true } };
if (value.state === "armed") run.armToken = clean(value.armToken, 200) || crypto.randomUUID();
if (value.outcome && typeof value.outcome === "object") run.outcome = { assessment: clean(value.outcome.assessment, 40), summary: clean(value.outcome.summary, 4000), evidence: evidence, criteria: assessments, reportedAt: Number.isFinite(value.outcome.reportedAt) ? value.outcome.reportedAt : null };
return run;
}
module.exports = { project: project, restore: restore };