@ornexus/neocortex 4.60.48 → 4.60.50
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/sbom.cdx.json +23 -23
- package/install.ps1 +1 -1
- package/install.sh +1 -1
- package/package.json +2 -2
- package/packages/client/dist/adapters/platform-detector.d.ts +9 -0
- package/packages/client/dist/adapters/platform-detector.js +1 -1
- package/packages/client/dist/cli.js +3 -2
- package/packages/client/dist/commands/invoke.d.ts +4 -0
- package/packages/client/dist/commands/invoke.js +54 -54
- package/packages/client/dist/commands/native-agent.d.ts +1 -0
- package/packages/client/dist/commands/native-agent.js +2 -0
- package/packages/client/dist/continuity/migrations/006-native-agent-dispatches.d.ts +9 -0
- package/packages/client/dist/continuity/migrations/006-native-agent-dispatches.js +48 -0
- package/packages/client/dist/continuity/native-agent-store.d.ts +13 -0
- package/packages/client/dist/continuity/native-agent-store.js +1 -0
- package/packages/client/dist/continuity/native-agent-types.d.ts +54 -0
- package/packages/client/dist/continuity/native-agent-types.js +1 -0
- package/packages/client/dist/continuity/sqlite-store.d.ts +43 -2
- package/packages/client/dist/continuity/sqlite-store.js +88 -62
- package/packages/client/dist/git/git-lifecycle-store.d.ts +36 -1
- package/packages/client/dist/git/git-lifecycle-store.js +4 -4
- package/packages/client/dist/index.d.ts +1 -0
- package/packages/client/dist/index.js +1 -1
- package/packages/client/dist/state/project-state-snapshot.js +1 -1
- package/targets-stubs/antigravity/gemini.md +1 -1
- package/targets-stubs/antigravity/skill/SKILL.md +1 -1
- package/targets-stubs/claude-code/neocortex-root.agent.yaml +1 -1
- package/targets-stubs/claude-code/neocortex-root.md +2 -2
- package/targets-stubs/claude-code/neocortex.agent.yaml +1 -1
- package/targets-stubs/claude-code/neocortex.md +2 -2
- package/targets-stubs/codex/AGENTS.md +35 -2
- package/targets-stubs/codex/neocortex.toml +6 -0
- package/targets-stubs/cursor/agent.md +2 -2
- package/targets-stubs/gemini-cli/agent.md +2 -2
- package/targets-stubs/opencode/neocortex-root.md +1 -1
- package/targets-stubs/vscode/neocortex.agent.md +2 -2
|
@@ -1,5 +1,31 @@
|
|
|
1
|
-
import{Buffer as V}from"node:buffer";import{createHash as M}from"node:crypto";import{chmodSync as X,closeSync as Ee,existsSync as Z,mkdirSync as pe,openSync as fe,readSync as Ce}from"node:fs";import{join as ee}from"node:path";import{INITIAL_CONTINUITY_SQLITE_MIGRATION as Se}from"./migrations/001-initial-schema.js";import{PROCESSING_OUTPUT_SUMMARY_SQLITE_MIGRATION as Ae}from"./migrations/002-processing-output-summary-indexes.js";import{HEADLESS_EXECUTION_ATTEMPTS_SQLITE_MIGRATION as ge}from"./migrations/003-headless-execution-attempts.js";import{OUTBOX_DELIVERY_STATE_SQLITE_MIGRATION as xe}from"./migrations/004-outbox-delivery-state.js";import{BOUNDED_HEADLESS_QUEUE_SQLITE_MIGRATION as Re}from"./migrations/005-bounded-headless-queue.js";import{CONTINUITY_QUEUE_REASON_CODES as k,CONTINUITY_RECEIPT_COMPACTION_EVENT_TYPE as W,CONTINUITY_RECEIPT_RETENTION_REASON_CODES as F,DEFAULT_CONTINUITY_QUEUE_POLICY as Oe,computeContinuityQueueRetryAt as Te,computeContinuityOutboxFailureDecision as Ne,normalizeContinuityQueuePolicy as B,normalizeContinuityQueuePriority as Le,normalizeContinuityQueueScope as je,normalizeContinuityRetentionPolicy as ve}from"./outbox.js";const te=".neocortex/continuity",Me="continuity.sqlite",gt=5,ke=5e3,O="processing_output_summary",Ue=2e3,ae=20,De=100,re="Install the optional Enterprise continuity SQLite adapter with `npm install --workspace packages/client better-sqlite3 --include=optional` or reinstall Neocortex with optional dependencies enabled.",we=Object.freeze(["discover_more","create_epic","run_yoloop","run_yolo","run_verifier","run_review_gate","compact_context","wait_external","backoff","waiting_human","complete","abort","scheduled","running","overlap_skipped","missed_run_catchup","completed","aborted","cancelled","blocked","draft","planned"]),se=20,qe=new Set(we),Pe=/^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}(?::\d{2}(?:\.\d{1,6})?)?(?:Z|[+-]\d{2}:?\d{2})?$/;function oe(t){return typeof t=="string"&&qe.has(t)}function de(t){if(typeof t!="string")return;const e=t.trim();if(!(e.length===0||e.length>40)&&Pe.test(e))return e}function He(t){if(!Array.isArray(t))return[];const e=[];for(const a of t){if(!E(a)||!oe(a.stage))continue;const r=de(a.at);r&&e.push({stage:a.stage,at:r})}return e.slice(-se)}function We(t){if(!(typeof t!="number"||!Number.isFinite(t)||t<0))return Math.floor(t)}class l extends Error{code;reasonCode;guidance;mutationBlocked;cause;constructor(e,a,r={}){super(a),this.name="ContinuitySqliteStoreError",this.code=e,this.reasonCode=e,this.guidance=r.guidance,this.cause=r.cause,this.mutationBlocked=r.mutationBlocked??e==="sqlite-integrity-failed"}}const Fe=[Se,Ae,ge,xe,Re],Be=Object.freeze(["continuity_migrations","jobs","job_leases","job_events","job_receipts","goal_campaigns","goal_ledger_items","goal_verifiers","goal_review_gates","loop_jobs","artifacts","state_snapshots","headless_execution_attempts","runner_config","outbox"]),ne=/(raw[_-]?(?:logs?|payloads?)|std(?:out|err)|stack(?:[_-]?trace)?|transcript|objective(?:[_-]?(?:text|body|prompt))|prompt(?:[_-]?(?:body|text))?|private[_-]?(?:urls?|prompts?)|secret|token|password|protected(?:[_-]?(?:field|body|bodies|internals))?|workflow(?:[_-]?body)?|step(?:[_-]?body)?|customer(?:[_-]?(?:pii|data))?|\bpii\b|authorization|api[_-]?key|license[_-]?key|argv|args|executable(?:[_-]?path)?|binary(?:[_-]?path)?|shell|cwd|command[_-]?path|vendor(?:[_-]?(?:payload|corpus|response|output)))/i,ie=/(https?:\/\/\S+|(?:^|\s)(?:\/(?:home|Users|media|mnt|tmp|var|etc|private)\/\S+|[A-Za-z]:\\\S+)|ghp_[A-Za-z0-9_]+|sk-[A-Za-z0-9_-]+|-----BEGIN [A-Z ]*PRIVATE KEY-----|authorization\s*:|password\s*=|token\s*=|api[_-]?key\s*=|license[_-]?key\s*=|raw[_ -]?(?:logs?|outputs?)\s*[:=]|transcript|stack\s*trace|stderr:|stdout:|system prompt|prompt[_ -]?(?:body|text)|workflow body|step body|\bargv\b|(?:bash|sh|zsh|powershell|pwsh)\s+-c\b|(?:\.{0,2}\/|[A-Za-z]:\\|\/)[^\s]*(?:\.exe|\.bat|\.cmd|\.ps1|\.sh|\/bin\/[^\s]+)|\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b|PROTECTED_|PRIVATE_INTERNALS|CUSTOMER_PII|\bPII\b|VENDOR_CORPUS|P180[_-]?SYNTHETIC[_-]?CONTINUITY|P185[_-]?SYNTHETIC[_-]?CONTINUITY|P187[_-]?SYNTHETIC[_-]?(?:CONTINUITY|RUNNER|WATCH)|P190[_-]?SYNTHETIC[_-]?(?:HEADLESS|CONTINUITY)|P192[_-]?SYNTHETIC[_-]?(?:PORTAL|RUNNER|SYNC))/i,$e=new Set(["unsafe_key","raw_log","prompt_body","private_url","local_absolute_path","secret","protected_field","unbounded_text","unbounded_number","unknown_required_operation","missing"]),Ye=/(corrupt|malformed|not a database|file is not a database|database disk image is malformed)/i,Ke=/(foreign key constraint failed|SQLITE_CONSTRAINT_FOREIGNKEY)/i,G="p185:v1:",Qe=new Set(["schemaVersion","contractVersion","eventType","executionId","jobId","operationId","idempotencyKey","goalId","loopId","campaignId","itemId","ledgerItemIds","verifierId","verifierIds","gateId","reviewGateIds","runnerId","leaseId","status","reasonCode","reasonCodes","runtimeId","modelId","runtimeSource","headlessRuntime","headlessModel","headlessRuntimeReasonCode","originRuntime","originModel","targetRef","attemptId","attemptStatus","directiveHash","timeoutMs","leaseExpiresAt","heartbeatAt","notBeforeAt","maxAttempts","counts","hashes","relativePaths","artifactRefs","evidenceRefs","validationRefs","registryRefs","storyIds","epicIds","debtIds","iteration","currentStage","stageHistory","durationMs","retryCount","attemptCount","queuePriority","queueScope","queueCap","queueDepth","queueAvailable","queueBackpressure","nextTickAt","nextAttemptAt","nextRetryAt","deadLetterReasonCode","deliveryCursor","lastAttemptAt","sentAt","ackedAt","lastErrorReason","lastErrorSummary","deadLetterSummary","deadLetteredAt","processingOutputSource","publicSummary","redactionEvidence","selectorKind","targetId","targetJobId","relatedJobIds","serverAccessToLocalhost","serverHeldStream","initialCursor","targetResolutionState","targetKind","relatedJobCount","snapshotStatus","snapshotGeneratedAt","renderedSummaryCount","cursorState","currentCursor","nextCursor","cursorAdvanced","eventId","latestEventId","watchStatus","stopReason","syncVersion","transportKind","envelopeId","workspaceId","workspaceLabel","projectId","projectLabel","snapshotId","syncCursor","previousSyncCursor","nextSyncCursor","commandId","receiptId","acknowledgedAt","observedAt","generatedAt","syncStatus","commandStatus","receiptStatus","actorType","actorId","tenantId","commandKind","auditStatus","redactionCount","autonomousGovernance","governanceVersion","governanceEvidence","governanceSource","publicSafe"]),Je=new Set(["foreground_invoke","scheduled_tick","runner_tick","manual_tick","headless_execution","jobs_command","invoke_watch","portal_render"]);function Ve(t){return import(t)}function Ge(t){return`sha256:${M("sha256").update(t).digest("hex")}`}function E(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function ze(t){return t instanceof Error?t.message:String(t)}function Xe(t){return E(t)&&typeof t.code=="string"?t.code:void 0}function m(t,e){if(t instanceof l)return t;const a=ze(t),r=Xe(t);return r==="SQLITE_CORRUPT"||r==="SQLITE_NOTADB"||Ye.test(a)?new l("sqlite-integrity-failed","Continuity SQLite integrity check failed; durable mutation is blocked until the store is repaired or rebuilt.",{cause:t,mutationBlocked:!0}):r==="SQLITE_CONSTRAINT_FOREIGNKEY"||Ke.test(a)?new l("sqlite-foreign-key-failed","Continuity SQLite foreign-key validation failed; mutation was rejected.",{cause:t}):new l(e,a,{cause:t})}function A(t,e){if(typeof t=="string"){if(/\.(?:redactionEvidence|redactionSummary)\[\d+\]\.field$/.test(e)&&/^[A-Za-z0-9_.:[\]-]{1,120}$/.test(t)||/\.(?:redactionEvidence|redactionSummary)\[\d+\]\.reason$/.test(e)&&$e.has(t))return;if(ie.test(t))throw new l("sqlite-public-safety-rejected",`Continuity SQLite metadata rejected unsafe value at ${e}.`);return}if(!(t===null||typeof t=="number"||typeof t=="boolean")){if(Array.isArray(t)){t.forEach((a,r)=>A(a,`${e}[${r}]`));return}if(E(t)){for(const[a,r]of Object.entries(t)){if(ne.test(a))throw new l("sqlite-public-safety-rejected",`Continuity SQLite metadata rejected unsafe key at ${e}.${a}.`);A(r,`${e}.${a}`)}return}throw new l("sqlite-public-safety-rejected",`Continuity SQLite metadata rejected unsupported value at ${e}.`)}}function b(t,e){if(t!==void 0&&ie.test(t))throw new l("sqlite-public-safety-rejected",`Continuity SQLite text rejected unsafe value at ${e}.`)}function $(t,e,a=240){if(t.trim().length===0)throw new l("sqlite-public-safety-rejected",`Continuity SQLite processing summary text is required at ${e}.`);if(b(t,e),t.length>a)throw new l("sqlite-public-safety-rejected",`Continuity SQLite processing summary text exceeded the public bound at ${e}.`)}function Y(t){const e={};if(!t)return e;for(const[a,r]of Object.entries(t))if(Qe.has(a)&&!ne.test(a))try{A(r,`metadata.${a}`),e[a]=r}catch{}return e}function Ze(t){const e={...Y(t.metadata),schemaVersion:1,contractVersion:"continuity-v1",eventType:O,executionId:t.executionId,jobId:t.jobId,operationId:t.executionId,publicSummary:t.publicSummary};return t.idempotencyKey&&(e.idempotencyKey=t.idempotencyKey),t.goalId&&(e.goalId=t.goalId),t.loopId&&(e.loopId=t.loopId),t.reasonCode&&(e.reasonCode=t.reasonCode),t.source&&Je.has(t.source)&&(e.processingOutputSource=t.source),Y(e)}function ce(t){const e=Math.floor(t??ae);return Number.isFinite(e)?Math.max(1,Math.min(De,e)):ae}function et(t){if(t.eventId&&t.eventId.trim().length>0)return t.eventId;const e=t.executionId.replace(/[^a-z0-9_.:-]+/gi,"-").replace(/^-+|-+$/g,"");return e.length>0?`event-processing-summary-${e.slice(0,160)}`:`event-processing-summary-${M("sha256").update(t.executionId).digest("hex").slice(0,32)}`}function tt(t){return`${G}${V.from(JSON.stringify([t.created_at,t.event_id]),"utf8").toString("base64url")}`}function at(t){if(t?.startsWith(G))try{const e=t.slice(G.length),a=JSON.parse(V.from(e,"base64url").toString("utf8"));if(!Array.isArray(a)||a.length!==2)return;const[r,s]=a;return typeof r!="string"||typeof s!="string"?void 0:{createdAt:r,eventId:s}}catch{return}}function U(t,e){if(!e)return;const a=e.trim().replace(/^@/,"");if(t==="job"&&/^job-J\d{3,}$/i.test(a))return`job-J${a.match(/\d+$/)?.[0]??""}`;if(t==="goal"&&/^goal-G\d{3,}$/i.test(a))return`goal-G${a.match(/\d+$/)?.[0]??""}`;if(t==="loop"&&/^loop-L\d{3,}$/i.test(a))return`loop-L${a.match(/\d+$/)?.[0]??""}`}function ue(t){return t?q(t.map(e=>U("job",e)).filter(e=>!!e)):[]}function le(t){const e=t.target;if(!e){const r=U("job",t.jobId);return r?{sql:" AND job_id = ?",params:[r]}:{sql:"",params:[]}}const a=e.selectorKind;if(a==="job"){const r=U("job",e.jobId??e.targetId??t.jobId);return r?{sql:" AND job_id = ?",params:[r]}:{sql:" AND 1 = 0",params:[]}}if(a==="goal"){const r=U("goal",e.goalId??e.targetId);if(!r)return{sql:" AND 1 = 0",params:[]};const s=ue(e.relatedJobIds);return{sql:` AND (job_id = ? OR json_extract(metadata_json, '$.goalId') = ?${s.length>0?` OR job_id IN (${s.map(()=>"?").join(", ")})`:""})`,params:[r,r,...s]}}if(a==="loop"){const r=U("loop",e.loopId??e.targetId);if(!r)return{sql:" AND 1 = 0",params:[]};const s=ue(e.relatedJobIds);return{sql:` AND (job_id = ? OR json_extract(metadata_json, '$.loopId') = ?${s.length>0?` OR job_id IN (${s.map(()=>"?").join(", ")})`:""})`,params:[r,r,...s]}}return{sql:" AND 1 = 0",params:[]}}function _e(t){const e={event_id:t.event_id,job_id:t.job_id,execution_id:t.operation_id,public_summary:t.summary,reason_code:t.reason_code,created_at:t.created_at,metadata_json:t.metadata_json};return{...e,cursor:tt(e)}}function S(t){return t?(A(t,"metadata"),JSON.stringify(t)):null}function rt(t,e,a){const r=n=>`sha256:${M("sha256").update(n.map(i=>[i.id,i.status,i.reasonCode].join(":")).sort().join(`
|
|
2
|
-
`)).digest("hex")}`,s=r(e),o=r(a);return{receipts:s,outputs:o,aggregate:`sha256:${M("sha256").update(`${t}:${s}:${o}`).digest("hex")}`}}function st(t){if(!t)return{};try{const e=JSON.parse(t);return E(e)?{...e}:{}}catch{return{}}}function d(t,e,a,r=!1){if(t===void 0){if(r)throw new l("sqlite-public-safety-rejected",`Continuity SQLite text is required at ${e}.`);return}if(b(t,e),t.trim().length===0||t.length>a)throw new l("sqlite-public-safety-rejected",`Continuity SQLite text exceeded the public bound at ${e}.`)}function T(t,e){if(t!==void 0&&(!Number.isFinite(t)||t<0||Math.floor(t)!==t))throw new l("sqlite-public-safety-rejected",`Continuity SQLite numeric value rejected at ${e}.`)}function j(t){d(t.outboxId,"outbox.outboxId",160,!0),d(t.jobId,"outbox.jobId",160),d(t.operationId,"outbox.operationId",160),d(t.idempotencyKey,"outbox.idempotencyKey",160),d(t.type,"outbox.type",80),d(t.status,"outbox.status",40),d(t.deliveryCursor,"outbox.deliveryCursor",200),d(t.timestamp,"outbox.timestamp",80),d(t.reasonCode,"outbox.reasonCode",100),d(t.summary,"outbox.summary",240)}function me(t){return t==="pending"||t==="sent"||t==="acked"||t==="failed"||t==="dead_letter"}function ot(t){return typeof t=="string"&&me(t)?t:"failed"}function I(t){return typeof t=="string"&&t.length>0?t:void 0}function dt(t){if(typeof t!="string"||t.trim().length===0)return{};try{const e=JSON.parse(t);return E(e)?(A(e,"outbox.payload"),e):{}}catch{return{}}}function nt(t){return{outboxId:String(t.outbox_id??""),...I(t.job_id)?{jobId:I(t.job_id)}:{},operationId:String(t.operation_id??""),...I(t.idempotency_key)?{idempotencyKey:I(t.idempotency_key)}:{},type:String(t.type??""),status:ot(t.status),payload:dt(t.payload_json),retryCount:typeof t.retry_count=="number"?t.retry_count:0,attemptCount:typeof t.attempt_count=="number"?t.attempt_count:0,...I(t.delivery_cursor)?{deliveryCursor:I(t.delivery_cursor)}:{},...I(t.next_attempt_at)?{nextAttemptAt:I(t.next_attempt_at)}:{},...I(t.last_attempt_at)?{lastAttemptAt:I(t.last_attempt_at)}:{},...I(t.sent_at)?{sentAt:I(t.sent_at)}:{},...I(t.acked_at)?{ackedAt:I(t.acked_at)}:{},...I(t.last_error_code)?{lastErrorCode:I(t.last_error_code)}:{},...I(t.last_error_reason)?{lastErrorReason:I(t.last_error_reason)}:{},...I(t.last_error_summary)?{lastErrorSummary:I(t.last_error_summary)}:{},...I(t.dead_letter_summary)?{deadLetterSummary:I(t.dead_letter_summary)}:{},...I(t.dead_lettered_at)?{deadLetteredAt:I(t.dead_lettered_at)}:{},createdAt:String(t.created_at??""),updatedAt:String(t.updated_at??""),publicSafe:!0}}function C(t){return{...t,publicSafe:!0}}function N(t,e){return t===void 0?null:(A(t,e),JSON.stringify(t))}function D(t){if(!t)return;const e=q(t.map(a=>a.replace(/\\/g,"/"))).filter(a=>a.length>0).slice(0,50);for(const[a,r]of e.entries()){d(r,`relativePaths[${a}]`,240,!0);const s=r.split("/").filter(Boolean);if(r.startsWith("/")||r.startsWith("~")||r.includes("://")||/^[A-Za-z]:\//.test(r)||s.includes(".."))throw new l("sqlite-public-safety-rejected",`Continuity SQLite rejected non-relative path at relativePaths[${a}].`)}return e}function K(t){const e={...Y(t.metadata),schemaVersion:1,contractVersion:"continuity-v1",attemptId:t.attemptId,executionId:t.executionId,jobId:t.jobId};return t.directiveHash&&(e.directiveHash=t.directiveHash),t.runtimeId&&(e.runtimeId=t.runtimeId),t.modelId&&(e.modelId=t.modelId),t.runtimeSource&&(e.runtimeSource=t.runtimeSource),t.status&&(e.attemptStatus=t.status),t.reasonCode&&(e.reasonCode=t.reasonCode),t.durationMs!==void 0&&(e.durationMs=t.durationMs),t.retryCount!==void 0&&(e.retryCount=t.retryCount),t.attemptCount!==void 0&&(e.attemptCount=t.attemptCount),t.maxAttempts!==void 0&&(e.maxAttempts=t.maxAttempts),t.queuePriority!==void 0&&(e.queuePriority=t.queuePriority),t.queueScope&&(e.queueScope=t.queueScope),t.nextRetryAt&&(e.nextRetryAt=t.nextRetryAt),t.deadLetterReasonCode&&(e.deadLetterReasonCode=t.deadLetterReasonCode),t.counts&&(e.counts=t.counts),t.hashes&&(e.hashes=t.hashes),t.redactionSummary&&(e.redactionEvidence=t.redactionSummary),t.relativePaths&&(e.relativePaths=D(t.relativePaths)),Y(e)}function L(t){d(t.attemptId,"headless_execution.attemptId",160,!0),d(t.executionId,"headless_execution.executionId",160,!0),d(t.jobId,"headless_execution.jobId",160,!0),d(t.directiveHash,"headless_execution.directiveHash",160),d(t.targetRef,"headless_execution.targetRef",240),d(t.storyId,"headless_execution.storyId",120),d(t.epicId,"headless_execution.epicId",120),d(t.runtimeId,"headless_execution.runtimeId",80),d(t.modelId,"headless_execution.modelId",120),d(t.runtimeSource,"headless_execution.runtimeSource",40),d(t.reasonCode,"headless_execution.reasonCode",100),d(t.publicSummary,"headless_execution.publicSummary",240),d(t.leaseId,"headless_execution.leaseId",160),d(t.runnerId,"headless_execution.runnerId",160),d(t.timestamp,"headless_execution.timestamp",80)}function w(t){if(Array.isArray(t)){const e=t[0];return E(e)?Object.values(e)[0]:e}return E(t)?Object.values(t)[0]:t}function it(t){return Be.includes(t)}function q(t){return Array.from(new Set(t))}function ct(t){const e=E(t)&&"default"in t?t.default:t;if(typeof e!="function")throw new l("sqlite-adapter-unavailable","Optional better-sqlite3 adapter did not export a database constructor.",{guidance:re});const a=e;return{adapterName:"better-sqlite3",open(r,s){return new a(r,s)}}}async function ut(t=Ve){try{const e=await t("better-sqlite3");return{ok:!0,adapter:ct(e)}}catch(e){return e instanceof l?{ok:!1,error:e}:{ok:!1,error:new l("sqlite-adapter-unavailable","Optional Enterprise continuity SQLite adapter better-sqlite3 is unavailable.",{cause:e,guidance:re})}}}function ye(t){return ee(t,te,Me)}function lt(t){const e=ee(t,te);pe(e,{recursive:!0,mode:448});try{X(e,448)}catch{}return e}async function xt(t){const e=t.adapter??await he(t.adapterLoader),a=ye(t.projectRoot);t.strictReadOnly?Ie(a):lt(t.projectRoot);let r;try{r=e.open(a,t.strictReadOnly?{fileMustExist:!0,readonly:!0}:void 0)}catch(o){throw m(o,"sqlite-integrity-failed")}const s=new _t({db:r,filePath:a,adapterName:e.adapterName,busyTimeoutMs:t.busyTimeoutMs??ke,integrityCheck:t.integrityCheck??!0,now:t.now??(()=>new Date().toISOString())});try{if(t.strictReadOnly)return s.runIntegrityCheck(),s.getSchemaVersion(),s;if(s.initialize(),Z(a))try{X(a,384)}catch{}return s}catch(o){try{r.close()}catch{}throw o}}function Ie(t){if(!Z(t))throw new l("sqlite-integrity-failed","Continuity database is unavailable for physical read-only inspection.",{mutationBlocked:!0});let e;try{const a=fe(t,"r");try{if(e=V.alloc(20),Ce(a,e,0,e.length,0)<e.length)throw new Error("short-header")}finally{Ee(a)}}catch(a){throw new l("sqlite-integrity-failed","Continuity database header could not be inspected read-only.",{cause:a,mutationBlocked:!0})}if(e.subarray(0,16).toString("ascii")!=="SQLite format 3\0"||e[18]===2||e[19]===2)throw new l("sqlite-integrity-failed","Continuity database requires an unsafe WAL read profile.",{mutationBlocked:!0})}async function Rt(t){const e=ye(t.projectRoot);Ie(e);const a=t.adapter??await he(t.adapterLoader);let r;try{r=a.open(e,{fileMustExist:!0,readonly:!0});const o=w(r.pragma("integrity_check",{simple:!0}));if(String(o).toLowerCase()!=="ok")throw new Error("integrity")}catch(o){throw new l("sqlite-integrity-failed","Continuity database failed physical read-only inspection.",{cause:o,mutationBlocked:!0})}const s=o=>{const n=o.trim().replace(/^\(+/u,"").toLowerCase();if(!/^(select|with\s)/u.test(n)||/\b(insert|update|delete|replace|create|alter|drop|pragma|attach|detach|vacuum|reindex)\b/u.test(n))throw new l("sqlite-mutation-blocked","Statement is not in the physical read-only query profile.",{mutationBlocked:!0})};return Object.freeze({filePath:e,adapterName:a.adapterName,all(o,...n){return s(o),r.prepare(o).all(...n)},get(o,...n){return s(o),r.prepare(o).get(...n)},close(){r.close()}})}async function he(t){const e=t?await t():await ut();if(!e.ok)throw e.error;return e.adapter}class _t{filePath;adapterName;db;busyTimeoutMs;integrityCheck;now;mutationBlocked=!1;constructor(e){this.db=e.db,this.filePath=e.filePath,this.adapterName=e.adapterName,this.busyTimeoutMs=e.busyTimeoutMs,this.integrityCheck=e.integrityCheck,this.now=e.now}initialize(){try{this.configureConnection(),this.integrityCheck&&this.runIntegrityCheck(),this.ensureMigrationTable(),this.applyMigrations(),this.integrityCheck&&this.runIntegrityCheck()}catch(e){throw m(e,"sqlite-migration-failed")}}close(){this.db.close()}pragmaValue(e){return w(this.db.pragma(e,{simple:!0}))}runIntegrityCheck(){try{if(String(w(this.db.pragma("integrity_check",{simple:!0}))??"").toLowerCase()!=="ok")throw this.mutationBlocked=!0,new l("sqlite-integrity-failed","Continuity SQLite integrity check failed; durable mutation is blocked until the store is repaired or rebuilt.",{mutationBlocked:!0})}catch(e){throw this.mutationBlocked=!0,m(e,"sqlite-integrity-failed")}}getSchemaVersion(){const e=this.db.prepare("SELECT COALESCE(MAX(version), 0) AS version FROM continuity_migrations").get();return E(e)&&typeof e.version=="number"?e.version:0}countRows(e){if(!it(e))throw new l("sqlite-public-safety-rejected","Unknown continuity table name.");const a=this.db.prepare(`SELECT COUNT(*) AS count FROM ${e}`).get();return E(a)&&typeof a.count=="number"?a.count:0}getLocalConsoleAttachmentState(e){d(e,"local_console.jobId",160,!0);const a=this.db.prepare(`
|
|
1
|
+
import{Buffer as J}from"node:buffer";import{createHash as M}from"node:crypto";import{chmodSync as z,closeSync as ge,existsSync as te,mkdirSync as ae,openSync as Ae,readSync as xe}from"node:fs";import{dirname as re,join as se}from"node:path";import{INITIAL_CONTINUITY_SQLITE_MIGRATION as Re}from"./migrations/001-initial-schema.js";import{PROCESSING_OUTPUT_SUMMARY_SQLITE_MIGRATION as Oe}from"./migrations/002-processing-output-summary-indexes.js";import{HEADLESS_EXECUTION_ATTEMPTS_SQLITE_MIGRATION as Ne}from"./migrations/003-headless-execution-attempts.js";import{OUTBOX_DELIVERY_STATE_SQLITE_MIGRATION as Te}from"./migrations/004-outbox-delivery-state.js";import{BOUNDED_HEADLESS_QUEUE_SQLITE_MIGRATION as Le}from"./migrations/005-bounded-headless-queue.js";import{NATIVE_AGENT_DISPATCHES_SQLITE_MIGRATION as ve}from"./migrations/006-native-agent-dispatches.js";import{NATIVE_AGENT_TERMINAL_STATES as oe,isNativeAgentDispatchReceiptV1 as X,isNativeAgentStateTransitionAllowed as je,isNativeDispatchBindingV1 as Me,isNativeHostAttestationV1 as ke}from"./native-agent-types.js";import{CONTINUITY_QUEUE_REASON_CODES as k,CONTINUITY_RECEIPT_COMPACTION_EVENT_TYPE as W,CONTINUITY_RECEIPT_RETENTION_REASON_CODES as F,DEFAULT_CONTINUITY_QUEUE_POLICY as De,computeContinuityQueueRetryAt as Ue,computeContinuityOutboxFailureDecision as we,normalizeContinuityQueuePolicy as B,normalizeContinuityQueuePriority as qe,normalizeContinuityQueueScope as Pe,normalizeContinuityRetentionPolicy as He}from"./outbox.js";const ne=".neocortex/continuity",We="continuity.sqlite",kt=6,Fe=5e3,O="processing_output_summary",Be=2e3,de=20,$e=100,ie="Install the optional Enterprise continuity SQLite adapter with `npm install --workspace packages/client better-sqlite3 --include=optional` or reinstall Neocortex with optional dependencies enabled.",Ye=Object.freeze(["discover_more","create_epic","run_yoloop","run_yolo","run_verifier","run_review_gate","compact_context","wait_external","backoff","waiting_human","complete","abort","scheduled","running","overlap_skipped","missed_run_catchup","completed","aborted","cancelled","blocked","draft","planned"]),ce=20,Ke=new Set(Ye),Ve=/^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}(?::\d{2}(?:\.\d{1,6})?)?(?:Z|[+-]\d{2}:?\d{2})?$/;function le(a){return typeof a=="string"&&Ke.has(a)}function ue(a){if(typeof a!="string")return;const e=a.trim();if(!(e.length===0||e.length>40)&&Ve.test(e))return e}function Ge(a){if(!Array.isArray(a))return[];const e=[];for(const t of a){if(!E(t)||!le(t.stage))continue;const r=ue(t.at);r&&e.push({stage:t.stage,at:r})}return e.slice(-ce)}function Qe(a){if(!(typeof a!="number"||!Number.isFinite(a)||a<0))return Math.floor(a)}class i extends Error{code;reasonCode;guidance;mutationBlocked;cause;constructor(e,t,r={}){super(t),this.name="ContinuitySqliteStoreError",this.code=e,this.reasonCode=e,this.guidance=r.guidance,this.cause=r.cause,this.mutationBlocked=r.mutationBlocked??e==="sqlite-integrity-failed"}}function $(a){const e=Object.freeze({schemaVersion:1,storyId:a.story_id,graphRevision:a.graph_revision,dispatchKey:a.dispatch_key,profile:a.profile,parentHandle:a.parent_handle,handle:a.handle,topology:a.topology,state:a.state,requestedAt:a.requested_at,observedAt:a.observed_at,terminalAt:a.terminal_at,freshness:a.freshness,observationSource:a.observation_source,reasonCode:a.reason_code,revision:a.revision,publicSafe:!0});if(!X(e))throw new i("sqlite-integrity-failed","Native-agent receipt failed its closed public contract.",{mutationBlocked:!0});return e}const Je=[Re,Oe,Ne,Te,Le,ve],ze=Object.freeze(["continuity_migrations","jobs","job_leases","job_events","job_receipts","goal_campaigns","goal_ledger_items","goal_verifiers","goal_review_gates","loop_jobs","artifacts","state_snapshots","headless_execution_attempts","runner_config","outbox","native_agent_dispatches","native_agent_observations"]),_e=/(raw[_-]?(?:logs?|payloads?)|std(?:out|err)|stack(?:[_-]?trace)?|transcript|objective(?:[_-]?(?:text|body|prompt))|prompt(?:[_-]?(?:body|text))?|private[_-]?(?:urls?|prompts?)|secret|token|password|protected(?:[_-]?(?:field|body|bodies|internals))?|workflow(?:[_-]?body)?|step(?:[_-]?body)?|customer(?:[_-]?(?:pii|data))?|\bpii\b|authorization|api[_-]?key|license[_-]?key|argv|args|executable(?:[_-]?path)?|binary(?:[_-]?path)?|shell|cwd|command[_-]?path|vendor(?:[_-]?(?:payload|corpus|response|output)))/i,me=/(https?:\/\/\S+|(?:^|\s)(?:\/(?:home|Users|media|mnt|tmp|var|etc|private)\/\S+|[A-Za-z]:\\\S+)|ghp_[A-Za-z0-9_]+|sk-[A-Za-z0-9_-]+|-----BEGIN [A-Z ]*PRIVATE KEY-----|authorization\s*:|password\s*=|token\s*=|api[_-]?key\s*=|license[_-]?key\s*=|raw[_ -]?(?:logs?|outputs?)\s*[:=]|transcript|stack\s*trace|stderr:|stdout:|system prompt|prompt[_ -]?(?:body|text)|workflow body|step body|\bargv\b|(?:bash|sh|zsh|powershell|pwsh)\s+-c\b|(?:\.{0,2}\/|[A-Za-z]:\\|\/)[^\s]*(?:\.exe|\.bat|\.cmd|\.ps1|\.sh|\/bin\/[^\s]+)|\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b|PROTECTED_|PRIVATE_INTERNALS|CUSTOMER_PII|\bPII\b|VENDOR_CORPUS|P180[_-]?SYNTHETIC[_-]?CONTINUITY|P185[_-]?SYNTHETIC[_-]?CONTINUITY|P187[_-]?SYNTHETIC[_-]?(?:CONTINUITY|RUNNER|WATCH)|P190[_-]?SYNTHETIC[_-]?(?:HEADLESS|CONTINUITY)|P192[_-]?SYNTHETIC[_-]?(?:PORTAL|RUNNER|SYNC))/i,Xe=new Set(["unsafe_key","raw_log","prompt_body","private_url","local_absolute_path","secret","protected_field","unbounded_text","unbounded_number","unknown_required_operation","missing"]),Ze=/(corrupt|malformed|not a database|file is not a database|database disk image is malformed)/i,et=/(foreign key constraint failed|SQLITE_CONSTRAINT_FOREIGNKEY)/i,Z="p185:v1:",tt=new Set(["schemaVersion","contractVersion","eventType","executionId","jobId","operationId","idempotencyKey","goalId","loopId","campaignId","itemId","ledgerItemIds","verifierId","verifierIds","gateId","reviewGateIds","runnerId","leaseId","status","reasonCode","reasonCodes","runtimeId","modelId","runtimeSource","headlessRuntime","headlessModel","headlessRuntimeReasonCode","originRuntime","originModel","targetRef","attemptId","attemptStatus","directiveHash","timeoutMs","leaseExpiresAt","heartbeatAt","notBeforeAt","maxAttempts","counts","hashes","relativePaths","artifactRefs","evidenceRefs","validationRefs","registryRefs","storyIds","epicIds","debtIds","iteration","currentStage","stageHistory","durationMs","retryCount","attemptCount","queuePriority","queueScope","queueCap","queueDepth","queueAvailable","queueBackpressure","nextTickAt","nextAttemptAt","nextRetryAt","deadLetterReasonCode","deliveryCursor","lastAttemptAt","sentAt","ackedAt","lastErrorReason","lastErrorSummary","deadLetterSummary","deadLetteredAt","processingOutputSource","publicSummary","redactionEvidence","selectorKind","targetId","targetJobId","relatedJobIds","serverAccessToLocalhost","serverHeldStream","initialCursor","targetResolutionState","targetKind","relatedJobCount","snapshotStatus","snapshotGeneratedAt","renderedSummaryCount","cursorState","currentCursor","nextCursor","cursorAdvanced","eventId","latestEventId","watchStatus","stopReason","syncVersion","transportKind","envelopeId","workspaceId","workspaceLabel","projectId","projectLabel","snapshotId","syncCursor","previousSyncCursor","nextSyncCursor","commandId","receiptId","acknowledgedAt","observedAt","generatedAt","syncStatus","commandStatus","receiptStatus","actorType","actorId","tenantId","commandKind","auditStatus","redactionCount","autonomousGovernance","governanceVersion","governanceEvidence","governanceSource","publicSafe"]),at=new Set(["foreground_invoke","scheduled_tick","runner_tick","manual_tick","headless_execution","jobs_command","invoke_watch","portal_render"]);function rt(a){return import(a)}function st(a){return`sha256:${M("sha256").update(a).digest("hex")}`}function E(a){return typeof a=="object"&&a!==null&&!Array.isArray(a)}function ot(a){return a instanceof Error?a.message:String(a)}function nt(a){return E(a)&&typeof a.code=="string"?a.code:void 0}function m(a,e){if(a instanceof i)return a;const t=ot(a),r=nt(a);return r==="SQLITE_CORRUPT"||r==="SQLITE_NOTADB"||Ze.test(t)?new i("sqlite-integrity-failed","Continuity SQLite integrity check failed; durable mutation is blocked until the store is repaired or rebuilt.",{cause:a,mutationBlocked:!0}):r==="SQLITE_CONSTRAINT_FOREIGNKEY"||et.test(t)?new i("sqlite-foreign-key-failed","Continuity SQLite foreign-key validation failed; mutation was rejected.",{cause:a}):new i(e,t,{cause:a})}function g(a,e){if(typeof a=="string"){if(/\.(?:redactionEvidence|redactionSummary)\[\d+\]\.field$/.test(e)&&/^[A-Za-z0-9_.:[\]-]{1,120}$/.test(a)||/\.(?:redactionEvidence|redactionSummary)\[\d+\]\.reason$/.test(e)&&Xe.has(a))return;if(me.test(a))throw new i("sqlite-public-safety-rejected",`Continuity SQLite metadata rejected unsafe value at ${e}.`);return}if(!(a===null||typeof a=="number"||typeof a=="boolean")){if(Array.isArray(a)){a.forEach((t,r)=>g(t,`${e}[${r}]`));return}if(E(a)){for(const[t,r]of Object.entries(a)){if(_e.test(t))throw new i("sqlite-public-safety-rejected",`Continuity SQLite metadata rejected unsafe key at ${e}.${t}.`);g(r,`${e}.${t}`)}return}throw new i("sqlite-public-safety-rejected",`Continuity SQLite metadata rejected unsupported value at ${e}.`)}}function b(a,e){if(a!==void 0&&me.test(a))throw new i("sqlite-public-safety-rejected",`Continuity SQLite text rejected unsafe value at ${e}.`)}function Y(a,e,t=240){if(a.trim().length===0)throw new i("sqlite-public-safety-rejected",`Continuity SQLite processing summary text is required at ${e}.`);if(b(a,e),a.length>t)throw new i("sqlite-public-safety-rejected",`Continuity SQLite processing summary text exceeded the public bound at ${e}.`)}function K(a){const e={};if(!a)return e;for(const[t,r]of Object.entries(a))if(tt.has(t)&&!_e.test(t))try{g(r,`metadata.${t}`),e[t]=r}catch{}return e}function dt(a){const e={...K(a.metadata),schemaVersion:1,contractVersion:"continuity-v1",eventType:O,executionId:a.executionId,jobId:a.jobId,operationId:a.executionId,publicSummary:a.publicSummary};return a.idempotencyKey&&(e.idempotencyKey=a.idempotencyKey),a.goalId&&(e.goalId=a.goalId),a.loopId&&(e.loopId=a.loopId),a.reasonCode&&(e.reasonCode=a.reasonCode),a.source&&at.has(a.source)&&(e.processingOutputSource=a.source),K(e)}function ye(a){const e=Math.floor(a??de);return Number.isFinite(e)?Math.max(1,Math.min($e,e)):de}function it(a){if(a.eventId&&a.eventId.trim().length>0)return a.eventId;const e=a.executionId.replace(/[^a-z0-9_.:-]+/gi,"-").replace(/^-+|-+$/g,"");return e.length>0?`event-processing-summary-${e.slice(0,160)}`:`event-processing-summary-${M("sha256").update(a.executionId).digest("hex").slice(0,32)}`}function ct(a){return`${Z}${J.from(JSON.stringify([a.created_at,a.event_id]),"utf8").toString("base64url")}`}function lt(a){if(a?.startsWith(Z))try{const e=a.slice(Z.length),t=JSON.parse(J.from(e,"base64url").toString("utf8"));if(!Array.isArray(t)||t.length!==2)return;const[r,s]=t;return typeof r!="string"||typeof s!="string"?void 0:{createdAt:r,eventId:s}}catch{return}}function D(a,e){if(!e)return;const t=e.trim().replace(/^@/,"");if(a==="job"&&/^job-J\d{3,}$/i.test(t))return`job-J${t.match(/\d+$/)?.[0]??""}`;if(a==="goal"&&/^goal-G\d{3,}$/i.test(t))return`goal-G${t.match(/\d+$/)?.[0]??""}`;if(a==="loop"&&/^loop-L\d{3,}$/i.test(t))return`loop-L${t.match(/\d+$/)?.[0]??""}`}function he(a){return a?q(a.map(e=>D("job",e)).filter(e=>!!e)):[]}function pe(a){const e=a.target;if(!e){const r=D("job",a.jobId);return r?{sql:" AND job_id = ?",params:[r]}:{sql:"",params:[]}}const t=e.selectorKind;if(t==="job"){const r=D("job",e.jobId??e.targetId??a.jobId);return r?{sql:" AND job_id = ?",params:[r]}:{sql:" AND 1 = 0",params:[]}}if(t==="goal"){const r=D("goal",e.goalId??e.targetId);if(!r)return{sql:" AND 1 = 0",params:[]};const s=he(e.relatedJobIds);return{sql:` AND (job_id = ? OR json_extract(metadata_json, '$.goalId') = ?${s.length>0?` OR job_id IN (${s.map(()=>"?").join(", ")})`:""})`,params:[r,r,...s]}}if(t==="loop"){const r=D("loop",e.loopId??e.targetId);if(!r)return{sql:" AND 1 = 0",params:[]};const s=he(e.relatedJobIds);return{sql:` AND (job_id = ? OR json_extract(metadata_json, '$.loopId') = ?${s.length>0?` OR job_id IN (${s.map(()=>"?").join(", ")})`:""})`,params:[r,r,...s]}}return{sql:" AND 1 = 0",params:[]}}function be(a){const e={event_id:a.event_id,job_id:a.job_id,execution_id:a.operation_id,public_summary:a.summary,reason_code:a.reason_code,created_at:a.created_at,metadata_json:a.metadata_json};return{...e,cursor:ct(e)}}function S(a){return a?(g(a,"metadata"),JSON.stringify(a)):null}function ut(a,e,t){const r=d=>`sha256:${M("sha256").update(d.map(o=>[o.id,o.status,o.reasonCode].join(":")).sort().join(`
|
|
2
|
+
`)).digest("hex")}`,s=r(e),n=r(t);return{receipts:s,outputs:n,aggregate:`sha256:${M("sha256").update(`${a}:${s}:${n}`).digest("hex")}`}}function _t(a){if(!a)return{};try{const e=JSON.parse(a);return E(e)?{...e}:{}}catch{return{}}}function c(a,e,t,r=!1){if(a===void 0){if(r)throw new i("sqlite-public-safety-rejected",`Continuity SQLite text is required at ${e}.`);return}if(b(a,e),a.trim().length===0||a.length>t)throw new i("sqlite-public-safety-rejected",`Continuity SQLite text exceeded the public bound at ${e}.`)}function N(a,e){if(a!==void 0&&(!Number.isFinite(a)||a<0||Math.floor(a)!==a))throw new i("sqlite-public-safety-rejected",`Continuity SQLite numeric value rejected at ${e}.`)}function v(a){c(a.outboxId,"outbox.outboxId",160,!0),c(a.jobId,"outbox.jobId",160),c(a.operationId,"outbox.operationId",160),c(a.idempotencyKey,"outbox.idempotencyKey",160),c(a.type,"outbox.type",80),c(a.status,"outbox.status",40),c(a.deliveryCursor,"outbox.deliveryCursor",200),c(a.timestamp,"outbox.timestamp",80),c(a.reasonCode,"outbox.reasonCode",100),c(a.summary,"outbox.summary",240)}function Ie(a){return a==="pending"||a==="sent"||a==="acked"||a==="failed"||a==="dead_letter"}function mt(a){return typeof a=="string"&&Ie(a)?a:"failed"}function h(a){return typeof a=="string"&&a.length>0?a:void 0}function yt(a){if(typeof a!="string"||a.trim().length===0)return{};try{const e=JSON.parse(a);return E(e)?(g(e,"outbox.payload"),e):{}}catch{return{}}}function ht(a){return{outboxId:String(a.outbox_id??""),...h(a.job_id)?{jobId:h(a.job_id)}:{},operationId:String(a.operation_id??""),...h(a.idempotency_key)?{idempotencyKey:h(a.idempotency_key)}:{},type:String(a.type??""),status:mt(a.status),payload:yt(a.payload_json),retryCount:typeof a.retry_count=="number"?a.retry_count:0,attemptCount:typeof a.attempt_count=="number"?a.attempt_count:0,...h(a.delivery_cursor)?{deliveryCursor:h(a.delivery_cursor)}:{},...h(a.next_attempt_at)?{nextAttemptAt:h(a.next_attempt_at)}:{},...h(a.last_attempt_at)?{lastAttemptAt:h(a.last_attempt_at)}:{},...h(a.sent_at)?{sentAt:h(a.sent_at)}:{},...h(a.acked_at)?{ackedAt:h(a.acked_at)}:{},...h(a.last_error_code)?{lastErrorCode:h(a.last_error_code)}:{},...h(a.last_error_reason)?{lastErrorReason:h(a.last_error_reason)}:{},...h(a.last_error_summary)?{lastErrorSummary:h(a.last_error_summary)}:{},...h(a.dead_letter_summary)?{deadLetterSummary:h(a.dead_letter_summary)}:{},...h(a.dead_lettered_at)?{deadLetteredAt:h(a.dead_lettered_at)}:{},createdAt:String(a.created_at??""),updatedAt:String(a.updated_at??""),publicSafe:!0}}function C(a){return{...a,publicSafe:!0}}function T(a,e){return a===void 0?null:(g(a,e),JSON.stringify(a))}function U(a){if(!a)return;const e=q(a.map(t=>t.replace(/\\/g,"/"))).filter(t=>t.length>0).slice(0,50);for(const[t,r]of e.entries()){c(r,`relativePaths[${t}]`,240,!0);const s=r.split("/").filter(Boolean);if(r.startsWith("/")||r.startsWith("~")||r.includes("://")||/^[A-Za-z]:\//.test(r)||s.includes(".."))throw new i("sqlite-public-safety-rejected",`Continuity SQLite rejected non-relative path at relativePaths[${t}].`)}return e}function V(a){const e={...K(a.metadata),schemaVersion:1,contractVersion:"continuity-v1",attemptId:a.attemptId,executionId:a.executionId,jobId:a.jobId};return a.directiveHash&&(e.directiveHash=a.directiveHash),a.runtimeId&&(e.runtimeId=a.runtimeId),a.modelId&&(e.modelId=a.modelId),a.runtimeSource&&(e.runtimeSource=a.runtimeSource),a.status&&(e.attemptStatus=a.status),a.reasonCode&&(e.reasonCode=a.reasonCode),a.durationMs!==void 0&&(e.durationMs=a.durationMs),a.retryCount!==void 0&&(e.retryCount=a.retryCount),a.attemptCount!==void 0&&(e.attemptCount=a.attemptCount),a.maxAttempts!==void 0&&(e.maxAttempts=a.maxAttempts),a.queuePriority!==void 0&&(e.queuePriority=a.queuePriority),a.queueScope&&(e.queueScope=a.queueScope),a.nextRetryAt&&(e.nextRetryAt=a.nextRetryAt),a.deadLetterReasonCode&&(e.deadLetterReasonCode=a.deadLetterReasonCode),a.counts&&(e.counts=a.counts),a.hashes&&(e.hashes=a.hashes),a.redactionSummary&&(e.redactionEvidence=a.redactionSummary),a.relativePaths&&(e.relativePaths=U(a.relativePaths)),K(e)}function L(a){c(a.attemptId,"headless_execution.attemptId",160,!0),c(a.executionId,"headless_execution.executionId",160,!0),c(a.jobId,"headless_execution.jobId",160,!0),c(a.directiveHash,"headless_execution.directiveHash",160),c(a.targetRef,"headless_execution.targetRef",240),c(a.storyId,"headless_execution.storyId",120),c(a.epicId,"headless_execution.epicId",120),c(a.runtimeId,"headless_execution.runtimeId",80),c(a.modelId,"headless_execution.modelId",120),c(a.runtimeSource,"headless_execution.runtimeSource",40),c(a.reasonCode,"headless_execution.reasonCode",100),c(a.publicSummary,"headless_execution.publicSummary",240),c(a.leaseId,"headless_execution.leaseId",160),c(a.runnerId,"headless_execution.runnerId",160),c(a.timestamp,"headless_execution.timestamp",80)}function w(a){if(Array.isArray(a)){const e=a[0];return E(e)?Object.values(e)[0]:e}return E(a)?Object.values(a)[0]:a}function pt(a){return ze.includes(a)}function q(a){return Array.from(new Set(a))}function bt(a){const e=E(a)&&"default"in a?a.default:a;if(typeof e!="function")throw new i("sqlite-adapter-unavailable","Optional better-sqlite3 adapter did not export a database constructor.",{guidance:ie});const t=e;return{adapterName:"better-sqlite3",open(r,s){return new t(r,s)}}}async function It(a=rt){try{const e=await a("better-sqlite3");return{ok:!0,adapter:bt(e)}}catch(e){return e instanceof i?{ok:!1,error:e}:{ok:!1,error:new i("sqlite-adapter-unavailable","Optional Enterprise continuity SQLite adapter better-sqlite3 is unavailable.",{cause:e,guidance:ie})}}}function Ee(a){return se(a,ne,We)}function Et(a){const e=se(a,ne);ae(e,{recursive:!0,mode:448});try{z(e,448)}catch{}return e}async function Dt(a){const e=a.adapter??await Ce(a.adapterLoader),t=a.filePath??Ee(a.projectRoot);if(a.strictReadOnly)fe(t);else if(a.filePath){ae(re(t),{recursive:!0,mode:448});try{z(re(t),448)}catch{}}else Et(a.projectRoot);let r;try{r=e.open(t,a.strictReadOnly?{fileMustExist:!0,readonly:!0}:void 0)}catch(n){throw m(n,"sqlite-integrity-failed")}const s=new ft({db:r,filePath:t,adapterName:e.adapterName,busyTimeoutMs:a.busyTimeoutMs??Fe,integrityCheck:a.integrityCheck??!0,now:a.now??(()=>new Date().toISOString())});try{if(a.strictReadOnly)return s.runIntegrityCheck(),s.getSchemaVersion(),s;if(s.initialize(),te(t))try{z(t,384)}catch{}return s}catch(n){try{r.close()}catch{}throw n}}function fe(a){if(!te(a))throw new i("sqlite-integrity-failed","Continuity database is unavailable for physical read-only inspection.",{mutationBlocked:!0});let e;try{const t=Ae(a,"r");try{if(e=J.alloc(20),xe(t,e,0,e.length,0)<e.length)throw new Error("short-header")}finally{ge(t)}}catch(t){throw new i("sqlite-integrity-failed","Continuity database header could not be inspected read-only.",{cause:t,mutationBlocked:!0})}if(e.subarray(0,16).toString("ascii")!=="SQLite format 3\0"||e[18]===2||e[19]===2)throw new i("sqlite-integrity-failed","Continuity database requires an unsafe WAL read profile.",{mutationBlocked:!0})}async function Ut(a){const e=Ee(a.projectRoot);fe(e);const t=a.adapter??await Ce(a.adapterLoader);let r;try{r=t.open(e,{fileMustExist:!0,readonly:!0});const n=w(r.pragma("integrity_check",{simple:!0}));if(String(n).toLowerCase()!=="ok")throw new Error("integrity")}catch(n){throw new i("sqlite-integrity-failed","Continuity database failed physical read-only inspection.",{cause:n,mutationBlocked:!0})}const s=n=>{const d=n.trim().replace(/^\(+/u,"").toLowerCase();if(!/^(select|with\s)/u.test(d)||/\b(insert|update|delete|replace|create|alter|drop|pragma|attach|detach|vacuum|reindex)\b/u.test(d))throw new i("sqlite-mutation-blocked","Statement is not in the physical read-only query profile.",{mutationBlocked:!0})};return Object.freeze({filePath:e,adapterName:t.adapterName,all(n,...d){return s(n),r.prepare(n).all(...d)},get(n,...d){return s(n),r.prepare(n).get(...d)},close(){r.close()}})}async function Ce(a){const e=a?await a():await It();if(!e.ok)throw e.error;return e.adapter}class ft{filePath;adapterName;db;busyTimeoutMs;integrityCheck;now;mutationBlocked=!1;constructor(e){this.db=e.db,this.filePath=e.filePath,this.adapterName=e.adapterName,this.busyTimeoutMs=e.busyTimeoutMs,this.integrityCheck=e.integrityCheck,this.now=e.now}initialize(){try{this.configureConnection(),this.integrityCheck&&this.runIntegrityCheck(),this.ensureMigrationTable(),this.applyMigrations(),this.integrityCheck&&this.runIntegrityCheck()}catch(e){throw m(e,"sqlite-migration-failed")}}close(){this.db.close()}pragmaValue(e){return w(this.db.pragma(e,{simple:!0}))}runIntegrityCheck(){try{if(String(w(this.db.pragma("integrity_check",{simple:!0}))??"").toLowerCase()!=="ok")throw this.mutationBlocked=!0,new i("sqlite-integrity-failed","Continuity SQLite integrity check failed; durable mutation is blocked until the store is repaired or rebuilt.",{mutationBlocked:!0})}catch(e){throw this.mutationBlocked=!0,m(e,"sqlite-integrity-failed")}}getSchemaVersion(){const e=this.db.prepare("SELECT COALESCE(MAX(version), 0) AS version FROM continuity_migrations").get();return E(e)&&typeof e.version=="number"?e.version:0}countRows(e){if(!pt(e))throw new i("sqlite-public-safety-rejected","Unknown continuity table name.");const t=this.db.prepare(`SELECT COUNT(*) AS count FROM ${e}`).get();return E(t)&&typeof t.count=="number"?t.count:0}reserveNativeAgentDispatch(e){if(this.assertCanMutate(),!Me(e.binding)||!ke(e.hostAttestation))throw new i("sqlite-public-safety-rejected","Native-agent reservation rejected invalid binding or host evidence.");const t={schemaVersion:1,storyId:e.binding.storyId,graphRevision:e.binding.graphRevision.replace(/^sha256:/,"").toLowerCase(),dispatchKey:e.binding.dispatchKey.toLowerCase(),profile:"neocortex",parentHandle:null,handle:null,topology:e.topology??"native-agent",state:"requested",requestedAt:e.requestedAt,observedAt:null,terminalAt:null,freshness:"unknown",observationSource:"local-reservation",reasonCode:e.reasonCode??"native-agent-dispatch-reserved",revision:0,publicSafe:!0};if(!X(t))throw new i("sqlite-public-safety-rejected","Native-agent reservation rejected unsafe public fields.");try{return this.runInTransaction(()=>{const r=this.db.prepare(`
|
|
3
|
+
INSERT OR IGNORE INTO native_agent_dispatches (
|
|
4
|
+
dispatch_key, story_id, graph_revision, profile,
|
|
5
|
+
host_kind, host_version, host_origin, host_confidence,
|
|
6
|
+
parent_handle, handle, topology, state, requested_at, observed_at,
|
|
7
|
+
terminal_at, freshness, observation_source, reason_code, revision
|
|
8
|
+
) VALUES (?, ?, ?, 'neocortex', ?, ?, ?, ?, NULL, NULL, ?, 'requested', ?, NULL, NULL, 'unknown', 'local-reservation', ?, 0)
|
|
9
|
+
`).run(t.dispatchKey,t.storyId,t.graphRevision,e.hostAttestation.hostKind,e.hostAttestation.hostVersion,e.hostAttestation.origin,e.hostAttestation.confidence,t.topology,t.requestedAt,t.reasonCode),s=this.findNativeAgentDispatchRow(t.dispatchKey,t.storyId,t.graphRevision);if(!s)throw new Error("native-agent-reservation-readback-missing");if(s.dispatch_key!==t.dispatchKey||s.story_id!==t.storyId||s.graph_revision!==t.graphRevision)throw new i("sqlite-mutation-failed","Native-agent reservation conflicts with an existing story graph binding.");return Object.freeze({receipt:$(s),reserved:r.changes===1,replay:r.changes===0})})}catch(r){throw m(r,"sqlite-mutation-failed")}}observeNativeAgentDispatch(e){this.assertCanMutate();try{return this.runInTransaction(()=>{const t=this.db.prepare("SELECT * FROM native_agent_dispatches WHERE dispatch_key = ?").get(e.dispatchKey);if(!t)throw new i("sqlite-mutation-failed","Native-agent dispatch reservation is missing.");const r=$(t),s=oe.has(e.state)?e.terminalAt??e.observedAt:null,n=e.handle??r.handle,d=e.parentHandle===void 0?r.parentHandle:e.parentHandle,o={...r,handle:n,parentHandle:d,topology:e.topology,state:e.state,observedAt:e.observedAt,terminalAt:s,freshness:e.freshness,observationSource:e.observationSource,reasonCode:e.reasonCode,revision:r.revision+1};if(!X(o))throw new i("sqlite-public-safety-rejected","Native-agent observation rejected unsafe or inconsistent fields.");if(r.handle&&e.handle&&r.handle!==e.handle)throw new i("sqlite-mutation-failed","Native-agent observation handle conflicts with the reserved dispatch.");if(!je(r.state,e.state))throw new i("sqlite-mutation-failed","Native-agent observation attempted a terminal or non-monotonic regression.");if(r.state===o.state&&r.handle===o.handle&&r.parentHandle===o.parentHandle&&r.topology===o.topology&&r.observedAt===o.observedAt&&r.terminalAt===o.terminalAt&&r.freshness===o.freshness&&r.observationSource===o.observationSource&&r.reasonCode===o.reasonCode)return Object.freeze({receipt:r,applied:!1,replay:!0});if(e.expectedRevision!==r.revision)throw new i("sqlite-mutation-failed","Native-agent observation CAS revision conflict.");if(r.observedAt&&Date.parse(e.observedAt)<Date.parse(r.observedAt))throw new i("sqlite-mutation-failed","Native-agent observation timestamp regressed.");if(this.db.prepare(`
|
|
10
|
+
UPDATE native_agent_dispatches
|
|
11
|
+
SET parent_handle = ?, handle = ?, topology = ?, state = ?, observed_at = ?,
|
|
12
|
+
terminal_at = ?, freshness = ?, observation_source = ?, reason_code = ?, revision = revision + 1
|
|
13
|
+
WHERE dispatch_key = ? AND revision = ?
|
|
14
|
+
`).run(o.parentHandle,o.handle,o.topology,o.state,o.observedAt,o.terminalAt,o.freshness,o.observationSource,o.reasonCode,o.dispatchKey,e.expectedRevision).changes!==1)throw new i("sqlite-mutation-failed","Native-agent observation CAS update was not applied.");return this.db.prepare(`
|
|
15
|
+
INSERT INTO native_agent_observations (
|
|
16
|
+
dispatch_key, sequence, state, handle, parent_handle, topology,
|
|
17
|
+
observed_at, terminal_at, freshness, observation_source, reason_code
|
|
18
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
19
|
+
`).run(o.dispatchKey,o.revision,o.state,o.handle,o.parentHandle,o.topology,o.observedAt,o.terminalAt,o.freshness,o.observationSource,o.reasonCode),Object.freeze({receipt:o,applied:!0,replay:!1})})}catch(t){throw m(t,"sqlite-mutation-failed")}}getNativeAgentDispatchStatus(e,t={}){const r=this.db.prepare("SELECT * FROM native_agent_dispatches WHERE dispatch_key = ?").get(e);if(!r)return null;const s=$(r),n=Math.max(1e3,t.staleAfterMs??3e4),d=Date.parse(t.nowIso??this.now()),o=s.observedAt?Date.parse(s.observedAt):NaN;return!oe.has(s.state)&&Number.isFinite(d)&&(!Number.isFinite(o)||d-o>n)?Object.freeze({...s,state:"unknown",freshness:s.observedAt?"stale":"unknown",reasonCode:s.observedAt?"native-agent-observation-stale":"native-agent-awaiting-host-evidence"}):s}listRecentNativeAgentDispatches(e=20){const t=Math.max(1,Math.min(50,Math.floor(e))),r=this.db.prepare(`
|
|
20
|
+
SELECT * FROM native_agent_dispatches
|
|
21
|
+
ORDER BY COALESCE(observed_at, requested_at) DESC, dispatch_key DESC
|
|
22
|
+
LIMIT ?
|
|
23
|
+
`).all(t);return Object.freeze(r.map($))}findNativeAgentDispatchRow(e,t,r){return this.db.prepare(`
|
|
24
|
+
SELECT * FROM native_agent_dispatches
|
|
25
|
+
WHERE dispatch_key = ? OR (story_id = ? AND graph_revision = ?)
|
|
26
|
+
ORDER BY CASE WHEN dispatch_key = ? THEN 0 ELSE 1 END
|
|
27
|
+
LIMIT 1
|
|
28
|
+
`).get(e,t,r,e)}getLocalConsoleAttachmentState(e){c(e,"local_console.jobId",160,!0);const t=this.db.prepare(`
|
|
3
29
|
SELECT j.job_id AS job_id,
|
|
4
30
|
j.kind AS kind,
|
|
5
31
|
j.status AS status,
|
|
@@ -8,29 +34,29 @@ import{Buffer as V}from"node:buffer";import{createHash as M}from"node:crypto";im
|
|
|
8
34
|
FROM jobs j
|
|
9
35
|
WHERE j.job_id = ?
|
|
10
36
|
LIMIT 1
|
|
11
|
-
`).get(e);return!E(
|
|
37
|
+
`).get(e);return!E(t)||typeof t.job_id!="string"?null:{jobId:t.job_id,kind:typeof t.kind=="string"?t.kind:"unknown",status:typeof t.status=="string"?t.status:"unknown",activeLeaseCount:typeof t.active_lease_count=="number"?t.active_lease_count:0,runningHeadlessAttemptCount:typeof t.running_headless_attempt_count=="number"?t.running_headless_attempt_count:0,publicSafe:!0}}recordJob(e){this.assertCanMutate(),b(e.summary,"jobs.summary");const t=S(e.metadata);try{const r=this.db.prepare(`
|
|
12
38
|
INSERT OR IGNORE INTO jobs (
|
|
13
39
|
job_id, kind, status, summary, reason_code, created_at, updated_at,
|
|
14
40
|
next_run_at, goal_id, loop_id, campaign_id, operation_id,
|
|
15
41
|
idempotency_key, metadata_json
|
|
16
42
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
17
|
-
`).run(e.jobId,e.kind,e.status,e.summary??null,e.reasonCode??null,e.createdAt,e.updatedAt,e.nextRunAt??null,e.goalId??null,e.loopId??null,e.campaignId??null,e.operationId??null,e.idempotencyKey??null,
|
|
43
|
+
`).run(e.jobId,e.kind,e.status,e.summary??null,e.reasonCode??null,e.createdAt,e.updatedAt,e.nextRunAt??null,e.goalId??null,e.loopId??null,e.campaignId??null,e.operationId??null,e.idempotencyKey??null,t);return this.toWriteResult(r)}catch(r){throw m(r,"sqlite-mutation-failed")}}appendEvent(e){this.assertCanMutate(),b(e.summary,"job_events.summary");const t=S(e.metadata);try{const r=this.db.prepare(`
|
|
18
44
|
INSERT OR IGNORE INTO job_events (
|
|
19
45
|
event_id, job_id, operation_id, idempotency_key, event_sequence,
|
|
20
46
|
type, summary, reason_code, created_at, metadata_json
|
|
21
47
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
22
|
-
`).run(e.eventId,e.jobId,e.operationId,e.idempotencyKey??null,e.sequence??null,e.type,e.summary,e.reasonCode??null,e.createdAt,
|
|
48
|
+
`).run(e.eventId,e.jobId,e.operationId,e.idempotencyKey??null,e.sequence??null,e.type,e.summary,e.reasonCode??null,e.createdAt,t);return this.toWriteResult(r)}catch(r){throw m(r,"sqlite-mutation-failed")}}recordProcessingOutputSummary(e){Y(e.executionId,"processing_output_summary.executionId",160),Y(e.jobId,"processing_output_summary.jobId",160),Y(e.publicSummary,"processing_output_summary.publicSummary",Be),Y(e.createdAt,"processing_output_summary.createdAt",80),b(e.eventId,"processing_output_summary.eventId"),b(e.idempotencyKey,"processing_output_summary.idempotencyKey"),b(e.goalId,"processing_output_summary.goalId"),b(e.loopId,"processing_output_summary.loopId"),b(e.reasonCode,"processing_output_summary.reasonCode"),b(e.source,"processing_output_summary.source");const t=this.appendEvent({eventId:it(e),jobId:e.jobId,operationId:e.executionId,idempotencyKey:e.idempotencyKey??e.executionId,type:O,summary:e.publicSummary,reasonCode:e.reasonCode,createdAt:e.createdAt,metadata:dt(e)});return t.inserted&&this.recordJobStageProgress({jobId:e.jobId,currentStage:e.metadata?.currentStage,iteration:e.metadata?.iteration,at:e.createdAt}),t}enqueueHeadlessExecutionAttempt(e){if(this.assertCanMutate(),L({attemptId:e.attemptId,executionId:e.executionId,jobId:e.jobId,directiveHash:e.directiveHash,targetRef:e.targetRef,storyId:e.storyId,epicId:e.epicId,runtimeId:e.runtimeId,modelId:e.modelId,runtimeSource:e.runtimeSource,reasonCode:e.reasonCode,publicSummary:e.publicSummary,timestamp:e.enqueuedAt}),c(e.notBeforeAt,"headless_execution.notBeforeAt",80),c(e.operationId,"headless_execution.operationId",160),c(e.idempotencyKey,"headless_execution.idempotencyKey",160),N(e.retryCount,"headless_execution.retryCount"),N(e.maxAttempts,"headless_execution.maxAttempts"),e.maxAttempts!==void 0&&e.maxAttempts<1)throw new i("sqlite-public-safety-rejected","Continuity SQLite maxAttempts must be greater than zero.");e.metadata&&g(e.metadata,"headless_execution.metadata");const t=B({maxItems:e.queueCap,maxAttempts:e.maxAttempts}),r=qe(e.queuePriority),s=Pe(e.queueScope),n=U(e.relativePaths),d=V({attemptId:e.attemptId,executionId:e.executionId,jobId:e.jobId,directiveHash:e.directiveHash,runtimeId:e.runtimeId,modelId:e.modelId,runtimeSource:e.runtimeSource,status:e.status??"queued",reasonCode:e.reasonCode,retryCount:e.retryCount??0,attemptCount:0,maxAttempts:t.maxAttempts,queuePriority:r,queueScope:s,counts:e.counts,hashes:e.hashes,redactionSummary:e.redactionSummary,relativePaths:n,metadata:e.metadata});return this.runInTransaction(()=>{const o=this.db.prepare(`
|
|
23
49
|
SELECT value_json
|
|
24
50
|
FROM runner_config
|
|
25
51
|
WHERE key = 'headless_queue_policy'
|
|
26
52
|
LIMIT 1
|
|
27
|
-
`).get();let
|
|
53
|
+
`).get();let l=t.maxItems;if(e.queueCap===void 0&&E(o)&&typeof o.value_json=="string")try{const u=JSON.parse(o.value_json);E(u)&&typeof u.maxItems=="number"&&(l=B({maxItems:u.maxItems}).maxItems)}catch{}this.db.prepare(`
|
|
28
54
|
INSERT INTO runner_config (key, value_json, updated_at)
|
|
29
55
|
VALUES ('headless_queue_policy', ?, ?)
|
|
30
56
|
ON CONFLICT(key) DO UPDATE SET
|
|
31
57
|
value_json = excluded.value_json,
|
|
32
58
|
updated_at = excluded.updated_at
|
|
33
|
-
`).run(JSON.stringify({maxItems:
|
|
59
|
+
`).run(JSON.stringify({maxItems:l}),e.enqueuedAt);const I=this.db.prepare(`
|
|
34
60
|
SELECT attempt_id
|
|
35
61
|
FROM headless_execution_attempts
|
|
36
62
|
WHERE attempt_id = ?
|
|
@@ -42,7 +68,7 @@ import{Buffer as V}from"node:buffer";import{createHash as M}from"node:crypto";im
|
|
|
42
68
|
FROM headless_execution_attempts
|
|
43
69
|
WHERE status IN ('queued', 'backoff', 'running')
|
|
44
70
|
AND dead_lettered_at IS NULL
|
|
45
|
-
`).get(),f=E(y)&&typeof y.count=="number"?y.count:0;if(
|
|
71
|
+
`).get(),f=E(y)&&typeof y.count=="number"?y.count:0;if(I)return{inserted:!1,replay:!0,changes:0,accepted:!0,backpressure:f>=l,queueDepth:f,queueCap:l,publicSafe:!0};if(f>=l)return{inserted:!1,replay:!1,changes:0,accepted:!1,backpressure:!0,queueDepth:f,queueCap:l,reasonCode:k.CAP_REACHED,publicSafe:!0};const _=this.db.prepare(`
|
|
46
72
|
INSERT INTO headless_execution_attempts (
|
|
47
73
|
attempt_id, execution_id, job_id, directive_hash, directive_kind,
|
|
48
74
|
command_class, target_kind, target_ref, story_id, epic_id, runtime_id,
|
|
@@ -52,7 +78,7 @@ import{Buffer as V}from"node:buffer";import{createHash as M}from"node:crypto";im
|
|
|
52
78
|
relative_paths_json, metadata_json, queue_priority, queue_scope,
|
|
53
79
|
attempt_count, next_retry_at
|
|
54
80
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, ?)
|
|
55
|
-
`).run(e.attemptId,e.executionId,e.jobId,e.directiveHash,e.directiveKind,e.commandClass,e.targetKind,e.targetRef,e.storyId??null,e.epicId??null,e.runtimeId??null,e.modelId??null,e.runtimeSource??null,e.status??"queued",e.reasonCode??null,e.publicSummary??null,e.enqueuedAt,e.status==="backoff"?e.notBeforeAt??e.enqueuedAt:null,e.retryCount??0,
|
|
81
|
+
`).run(e.attemptId,e.executionId,e.jobId,e.directiveHash,e.directiveKind,e.commandClass,e.targetKind,e.targetRef,e.storyId??null,e.epicId??null,e.runtimeId??null,e.modelId??null,e.runtimeSource??null,e.status??"queued",e.reasonCode??null,e.publicSummary??null,e.enqueuedAt,e.status==="backoff"?e.notBeforeAt??e.enqueuedAt:null,e.retryCount??0,t.maxAttempts,e.operationId??null,e.idempotencyKey??null,T(e.counts,"headless_execution.counts"),T(e.hashes,"headless_execution.hashes"),T(e.redactionSummary,"headless_execution.redactionSummary"),T(n,"headless_execution.relativePaths"),S(d),r,s,e.notBeforeAt??e.enqueuedAt);return{inserted:_.changes>0,replay:!1,changes:_.changes,accepted:_.changes>0,backpressure:f+_.changes>=l,queueDepth:f+_.changes,queueCap:l,publicSafe:!0}})}listDueHeadlessExecutionAttempts(e){const t=Math.max(1,Math.min(50,Math.floor(e.limit)));return c(e.nowIso,"headless_execution.nowIso",80,!0),this.db.prepare(`
|
|
56
82
|
SELECT attempt_id, execution_id, job_id, directive_hash, directive_kind,
|
|
57
83
|
command_class, target_kind, target_ref, story_id, epic_id,
|
|
58
84
|
runtime_id, model_id, runtime_source, status, reason_code,
|
|
@@ -71,13 +97,13 @@ import{Buffer as V}from"node:buffer";import{createHash as M}from"node:crypto";im
|
|
|
71
97
|
ORDER BY queue_priority DESC, COALESCE(next_retry_at, not_before_at, enqueued_at) ASC,
|
|
72
98
|
enqueued_at ASC, attempt_id ASC
|
|
73
99
|
LIMIT ?
|
|
74
|
-
`).all(e.nowIso,e.nowIso,
|
|
100
|
+
`).all(e.nowIso,e.nowIso,t)}hasCompletedHeadlessExecutionDirectiveHash(e,t){c(e,"headless_execution.directiveHash",160,!0),c(t,"headless_execution.attemptId",160);const r=t?" AND attempt_id != ?":"",s=t?[e,t]:[e];return this.db.prepare(`
|
|
75
101
|
SELECT 1 AS found
|
|
76
102
|
FROM headless_execution_attempts
|
|
77
103
|
WHERE directive_hash = ?
|
|
78
104
|
AND status = 'completed'${r}
|
|
79
105
|
LIMIT 1
|
|
80
|
-
`).get(...s)?.found===1}claimHeadlessExecutionAttempt(e){this.assertCanMutate(),L({attemptId:e.attemptId,executionId:e.attemptId,jobId:e.attemptId,leaseId:e.leaseId,runnerId:e.runnerId,reasonCode:e.reasonCode,timestamp:e.claimedAt}),
|
|
106
|
+
`).get(...s)?.found===1}claimHeadlessExecutionAttempt(e){this.assertCanMutate(),L({attemptId:e.attemptId,executionId:e.attemptId,jobId:e.attemptId,leaseId:e.leaseId,runnerId:e.runnerId,reasonCode:e.reasonCode,timestamp:e.claimedAt}),c(e.leaseExpiresAt,"headless_execution.leaseExpiresAt",80,!0);try{const t=this.db.prepare(`
|
|
81
107
|
UPDATE headless_execution_attempts
|
|
82
108
|
SET status = 'running',
|
|
83
109
|
lease_id = ?,
|
|
@@ -93,7 +119,7 @@ import{Buffer as V}from"node:buffer";import{createHash as M}from"node:crypto";im
|
|
|
93
119
|
AND dead_lettered_at IS NULL
|
|
94
120
|
AND (COALESCE(next_retry_at, not_before_at) IS NULL OR COALESCE(next_retry_at, not_before_at) <= ?)
|
|
95
121
|
AND (lease_id IS NULL OR lease_released_at IS NOT NULL OR lease_expires_at <= ?)
|
|
96
|
-
`).run(e.leaseId,e.runnerId,e.claimedAt,e.claimedAt,e.leaseExpiresAt,e.reasonCode??null,e.attemptId,e.claimedAt,e.claimedAt);return this.toWriteResult(
|
|
122
|
+
`).run(e.leaseId,e.runnerId,e.claimedAt,e.claimedAt,e.leaseExpiresAt,e.reasonCode??null,e.attemptId,e.claimedAt,e.claimedAt);return this.toWriteResult(t)}catch(t){throw m(t,"sqlite-mutation-failed")}}acquireNextHeadlessExecutionAttempt(e){return this.assertCanMutate(),L({attemptId:e.leaseId,executionId:e.leaseId,jobId:e.leaseId,leaseId:e.leaseId,runnerId:e.runnerId,reasonCode:e.reasonCode,timestamp:e.claimedAt}),c(e.leaseExpiresAt,"headless_execution.leaseExpiresAt",80,!0),this.runInTransaction(()=>{const t=this.db.prepare(`
|
|
97
123
|
SELECT attempt_id
|
|
98
124
|
FROM headless_execution_attempts
|
|
99
125
|
WHERE status IN ('queued', 'backoff')
|
|
@@ -106,7 +132,7 @@ import{Buffer as V}from"node:buffer";import{createHash as M}from"node:crypto";im
|
|
|
106
132
|
enqueued_at ASC,
|
|
107
133
|
attempt_id ASC
|
|
108
134
|
LIMIT 1
|
|
109
|
-
`).get(e.directiveKind??null,e.directiveKind??null,e.claimedAt,e.claimedAt);if(typeof
|
|
135
|
+
`).get(e.directiveKind??null,e.directiveKind??null,e.claimedAt,e.claimedAt);if(typeof t?.attempt_id!="string")return{acquired:!1,reasonCode:"continuity-ok",publicSafe:!0};if(this.db.prepare(`
|
|
110
136
|
UPDATE headless_execution_attempts
|
|
111
137
|
SET status = 'running',
|
|
112
138
|
lease_id = ?,
|
|
@@ -122,7 +148,7 @@ import{Buffer as V}from"node:buffer";import{createHash as M}from"node:crypto";im
|
|
|
122
148
|
AND dead_lettered_at IS NULL
|
|
123
149
|
AND (COALESCE(next_retry_at, not_before_at) IS NULL OR COALESCE(next_retry_at, not_before_at) <= ?)
|
|
124
150
|
AND (lease_id IS NULL OR lease_released_at IS NOT NULL OR lease_expires_at <= ?)
|
|
125
|
-
`).run(e.leaseId,e.runnerId,e.claimedAt,e.claimedAt,e.leaseExpiresAt,e.reasonCode??null,
|
|
151
|
+
`).run(e.leaseId,e.runnerId,e.claimedAt,e.claimedAt,e.leaseExpiresAt,e.reasonCode??null,t.attempt_id,e.claimedAt,e.claimedAt).changes===0)return{acquired:!1,reasonCode:"lease-conflict",publicSafe:!0};const s=this.getHeadlessExecutionAttempt(t.attempt_id);return s?{acquired:!0,attempt:s,reasonCode:e.reasonCode??"continuity-ok",publicSafe:!0}:{acquired:!1,reasonCode:"lease-conflict",publicSafe:!0}})}heartbeatHeadlessExecutionAttempt(e){this.assertCanMutate(),L({attemptId:e.attemptId,executionId:e.attemptId,jobId:e.attemptId,leaseId:e.leaseId,runnerId:e.runnerId,timestamp:e.heartbeatAt}),c(e.leaseExpiresAt,"headless_execution.leaseExpiresAt",80);try{const t=this.db.prepare(`
|
|
126
152
|
UPDATE headless_execution_attempts
|
|
127
153
|
SET heartbeat_at = ?,
|
|
128
154
|
lease_expires_at = COALESCE(?, lease_expires_at)
|
|
@@ -132,7 +158,7 @@ import{Buffer as V}from"node:buffer";import{createHash as M}from"node:crypto";im
|
|
|
132
158
|
AND status = 'running'
|
|
133
159
|
AND lease_released_at IS NULL
|
|
134
160
|
AND lease_expires_at > ?
|
|
135
|
-
`).run(e.heartbeatAt,e.leaseExpiresAt??null,e.attemptId,e.leaseId,e.runnerId,e.heartbeatAt);return this.toWriteResult(
|
|
161
|
+
`).run(e.heartbeatAt,e.leaseExpiresAt??null,e.attemptId,e.leaseId,e.runnerId,e.heartbeatAt);return this.toWriteResult(t)}catch(t){throw m(t,"sqlite-mutation-failed")}}releaseHeadlessExecutionAttempt(e){this.assertCanMutate(),L({attemptId:e.attemptId,executionId:e.attemptId,jobId:e.attemptId,leaseId:e.leaseId,reasonCode:e.reasonCode,timestamp:e.releasedAt}),c(e.notBeforeAt,"headless_execution.notBeforeAt",80),N(e.retryCount,"headless_execution.retryCount");try{const t=this.db.prepare(`
|
|
136
162
|
UPDATE headless_execution_attempts
|
|
137
163
|
SET status = COALESCE(?, status),
|
|
138
164
|
reason_code = COALESCE(?, reason_code),
|
|
@@ -148,8 +174,8 @@ import{Buffer as V}from"node:buffer";import{createHash as M}from"node:crypto";im
|
|
|
148
174
|
AND lease_id = ?
|
|
149
175
|
AND status = 'running'
|
|
150
176
|
AND lease_released_at IS NULL
|
|
151
|
-
`).run(e.status??null,e.reasonCode??null,e.notBeforeAt??null,e.retryCount??null,e.status??null,e.notBeforeAt??null,e.status??null,e.releasedAt,e.attemptId,e.leaseId);return this.toWriteResult(
|
|
152
|
-
AND lease_released_at IS NULL${e.runnerId?" AND runner_id = ?":""}`:"",
|
|
177
|
+
`).run(e.status??null,e.reasonCode??null,e.notBeforeAt??null,e.retryCount??null,e.status??null,e.notBeforeAt??null,e.status??null,e.releasedAt,e.attemptId,e.leaseId);return this.toWriteResult(t)}catch(t){throw m(t,"sqlite-mutation-failed")}}completeHeadlessExecutionAttempt(e){this.assertCanMutate(),L({attemptId:e.attemptId,executionId:e.attemptId,jobId:e.attemptId,leaseId:e.leaseId,runnerId:e.runnerId,reasonCode:e.reasonCode,publicSummary:e.publicSummary,timestamp:e.completedAt}),c(e.notBeforeAt,"headless_execution.notBeforeAt",80),N(e.durationMs,"headless_execution.durationMs"),N(e.retryCount,"headless_execution.retryCount"),e.metadata&&g(e.metadata,"headless_execution.metadata");const t=U(e.relativePaths),r=V({attemptId:e.attemptId,executionId:e.executionId??e.attemptId,jobId:e.jobId??e.attemptId,status:e.status,reasonCode:e.reasonCode,durationMs:e.durationMs,retryCount:e.retryCount,counts:e.counts,hashes:e.hashes,redactionSummary:e.redactionSummary,relativePaths:t,metadata:e.metadata}),s=e.leaseId?` AND lease_id = ?
|
|
178
|
+
AND lease_released_at IS NULL${e.runnerId?" AND runner_id = ?":""}`:"",n=e.leaseId?"status = 'running'":"status NOT IN ('completed', 'failed', 'timed_out', 'skipped')",d=[e.status,e.completedAt,e.durationMs??null,e.reasonCode??null,e.publicSummary??null,e.notBeforeAt??null,e.retryCount??null,e.status,e.notBeforeAt??null,e.counts?T(e.counts,"headless_execution.counts"):null,e.hashes?T(e.hashes,"headless_execution.hashes"):null,e.redactionSummary?T(e.redactionSummary,"headless_execution.redactionSummary"):null,t?T(t,"headless_execution.relativePaths"):null,S(r),e.completedAt,e.attemptId];e.leaseId&&d.push(e.leaseId),e.leaseId&&e.runnerId&&d.push(e.runnerId);try{const o=this.db.prepare(`
|
|
153
179
|
UPDATE headless_execution_attempts
|
|
154
180
|
SET status = ?,
|
|
155
181
|
completed_at = ?,
|
|
@@ -169,52 +195,52 @@ import{Buffer as V}from"node:buffer";import{createHash as M}from"node:crypto";im
|
|
|
169
195
|
metadata_json = COALESCE(?, metadata_json),
|
|
170
196
|
lease_released_at = COALESCE(lease_released_at, ?)
|
|
171
197
|
WHERE attempt_id = ?${s}
|
|
172
|
-
AND ${
|
|
173
|
-
`).run(...
|
|
198
|
+
AND ${n}
|
|
199
|
+
`).run(...d);return this.toWriteResult(o)}catch(o){throw m(o,"sqlite-mutation-failed")}}recordHeadlessExecutionReceipt(e){L({attemptId:e.attemptId,executionId:e.executionId,jobId:e.jobId,reasonCode:e.reasonCode,timestamp:e.createdAt}),e.metadata&&g(e.metadata,"headless_execution.metadata");const t=U(e.relativePaths),r=V({attemptId:e.attemptId,executionId:e.executionId,jobId:e.jobId,status:e.status,reasonCode:e.reasonCode,counts:e.counts,hashes:e.hashes,redactionSummary:e.redactionSummary,relativePaths:t,metadata:e.metadata});return this.appendReceipt({receiptId:e.receiptId,jobId:e.jobId,operationId:e.operationId??e.executionId,idempotencyKey:e.idempotencyKey??e.executionId,status:e.status,reasonCode:e.reasonCode,appliedOperationIds:e.status==="applied"?[e.executionId]:void 0,ignoredOperationIds:e.status==="ignored"?[e.executionId]:void 0,createdAt:e.createdAt,metadata:r})}recordHeadlessExecutionSummary(e){L({attemptId:e.attemptId,executionId:e.executionId,jobId:e.jobId,runtimeId:e.runtimeId,modelId:e.modelId,reasonCode:e.reasonCode,publicSummary:e.publicSummary,timestamp:e.createdAt}),N(e.durationMs,"headless_execution.durationMs"),e.metadata&&g(e.metadata,"headless_execution.metadata");const t=U(e.relativePaths),r=V({attemptId:e.attemptId,executionId:e.executionId,jobId:e.jobId,runtimeId:e.runtimeId,modelId:e.modelId,status:e.status??"completed",reasonCode:e.reasonCode,durationMs:e.durationMs,counts:e.counts,hashes:e.hashes,redactionSummary:e.redactionSummary,relativePaths:t,metadata:e.metadata});return this.recordProcessingOutputSummary({eventId:e.eventId,executionId:e.executionId,jobId:e.jobId,idempotencyKey:e.executionId,publicSummary:e.publicSummary,reasonCode:e.reasonCode,createdAt:e.createdAt,source:"headless_execution",metadata:r})}appendReceipt(e){this.assertCanMutate();const t=S(e.metadata);try{const r=this.db.prepare(`
|
|
174
200
|
INSERT OR IGNORE INTO job_receipts (
|
|
175
201
|
receipt_id, job_id, operation_id, idempotency_key, status, reason_code,
|
|
176
202
|
applied_operation_ids_json, ignored_operation_ids_json, created_at, metadata_json
|
|
177
203
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
178
|
-
`).run(e.receiptId,e.jobId,e.operationId??null,e.idempotencyKey??null,e.status,e.reasonCode??null,e.appliedOperationIds?JSON.stringify(e.appliedOperationIds):null,e.ignoredOperationIds?JSON.stringify(e.ignoredOperationIds):null,e.createdAt,
|
|
204
|
+
`).run(e.receiptId,e.jobId,e.operationId??null,e.idempotencyKey??null,e.status,e.reasonCode??null,e.appliedOperationIds?JSON.stringify(e.appliedOperationIds):null,e.ignoredOperationIds?JSON.stringify(e.ignoredOperationIds):null,e.createdAt,t);return this.toWriteResult(r)}catch(r){throw m(r,"sqlite-mutation-failed")}}compactPublicReceiptsAndOutputs(e){this.assertCanMutate();const t=Date.parse(e.nowIso);if(!Number.isFinite(t))throw new i("sqlite-public-safety-rejected","Continuity receipt compaction requires a valid public timestamp.");const r=He(e.policy),s=new Date(t-r.receipts.maxAgeMs).toISOString(),n=new Date(t-r.processingOutputs.maxAgeMs).toISOString();try{return this.runInTransaction(()=>{const d=this.selectReceiptRetentionCandidates({cutoff:s,maxItems:r.receipts.maxItems,maxBytes:r.receipts.maxBytes,limit:r.maxDeleteRowsPerRun}),o=this.selectOutputRetentionCandidates({cutoff:n,maxItems:r.processingOutputs.maxItems,maxBytes:r.processingOutputs.maxBytes,limit:r.maxDeleteRowsPerRun}),l=[...d,...o].sort((u,p)=>u.createdAt.localeCompare(p.createdAt)||u.id.localeCompare(p.id)).slice(0,r.maxDeleteRowsPerRun);if(l.length===0)return{status:"noop",summaries:[],counts:{receiptsRemoved:0,outputsRemoved:0,bytesRemoved:0,summariesCreated:0},reasonCode:F.NOOP,publicSafe:!0};const I=l.filter(u=>u.kind==="receipt"),y=l.filter(u=>u.kind==="output");for(const u of q(I.map(p=>p.jobId)))this.preserveReceiptDerivedIteration(u,e.nowIso);this.deleteRetentionCandidates("job_receipts","receipt_id",I.map(u=>u.id)),this.deleteRetentionCandidates("job_events","event_id",y.map(u=>u.id));const f=new Map;for(const u of l)f.set(u.jobId,[...f.get(u.jobId)??[],u]);const _=[];for(const[u,p]of[...f.entries()].sort(([x],[A])=>x.localeCompare(A))){const x=p.filter(j=>j.kind==="receipt"),A=p.filter(j=>j.kind==="output"),G=this.retainedReceiptOutputCounts(u),Q=ut(u,x,A),R={receiptsRemoved:x.length,receiptsRetained:G.receipts,outputsRemoved:A.length,outputsRetained:G.outputs,bytesRemoved:p.reduce((j,Se)=>j+Se.approxBytes,0),bytesRetained:G.bytes,redactions:0},P=`Compacted public receipt and processing evidence: receipts removed ${R.receiptsRemoved}, retained ${R.receiptsRetained}; summaries removed ${R.outputsRemoved}, retained ${R.outputsRetained}; bytes removed ${R.bytesRemoved}, retained ${R.bytesRetained}.`;c(P,"receipt_compaction.publicSummary",500,!0);const H=`receipt-compaction-${M("sha256").update(`${u}:${e.nowIso}:${Q.aggregate}`).digest("hex").slice(0,32)}`,ee={schemaVersion:1,contractVersion:"continuity-v1",policyVersion:1,type:W,summaryId:H,jobId:u,scope:"local_sqlite",status:"compacted",createdAt:e.nowIso,reasonCodes:[F.COMPACTED],counts:R,hashes:Q,publicSummary:P,publicSafe:!0};this.appendEvent({eventId:H,jobId:u,operationId:`op-${H}`,idempotencyKey:`idem-${H}`,type:W,summary:P,reasonCode:F.COMPACTED,createdAt:e.nowIso,metadata:{schemaVersion:1,contractVersion:"continuity-v1",eventType:W,jobId:u,reasonCodes:ee.reasonCodes,counts:R,hashes:Q,publicSummary:P}}),this.pruneReceiptCompactionSummaries(u,r.maxCompactionSummariesPerJob),_.push(ee)}return{status:"compacted",summaries:_,counts:{receiptsRemoved:I.length,outputsRemoved:y.length,bytesRemoved:l.reduce((u,p)=>u+p.approxBytes,0),summariesCreated:_.length},reasonCode:F.COMPACTED,publicSafe:!0}})}catch(d){throw m(d,"sqlite-mutation-failed")}}updateJobStatus(e){this.assertCanMutate();try{const t=this.db.prepare(`
|
|
179
205
|
UPDATE jobs
|
|
180
206
|
SET status = ?,
|
|
181
207
|
reason_code = COALESCE(?, reason_code),
|
|
182
208
|
updated_at = ?,
|
|
183
209
|
next_run_at = COALESCE(?, next_run_at)
|
|
184
210
|
WHERE job_id = ?
|
|
185
|
-
`).run(e.status,e.reasonCode??null,e.updatedAt,e.nextRunAt??null,e.jobId);if(
|
|
211
|
+
`).run(e.status,e.reasonCode??null,e.updatedAt,e.nextRunAt??null,e.jobId);if(t.changes===0)throw new i("sqlite-foreign-key-failed",`Continuity SQLite job ${e.jobId} was not found for status update.`);return this.toWriteResult(t)}catch(t){throw m(t,"sqlite-mutation-failed")}}recordJobStageProgress(e){this.assertCanMutate(),c(e.jobId,"job_stage.jobId",160,!0);const t=le(e.currentStage)?e.currentStage:void 0,r=Qe(e.iteration);if(!t&&r===void 0)return{inserted:!1,replay:!1,changes:0};const s=ue(e.at);try{const n=this.db.prepare("SELECT metadata_json FROM jobs WHERE job_id = ?").get(e.jobId);if(!n)return{inserted:!1,replay:!1,changes:0};const d=_t(typeof n.metadata_json=="string"?n.metadata_json:null);if(t&&(d.currentStage=t),r!==void 0&&(d.iteration=r),t&&s&&e.appendHistory!==!1){const l=Ge(d.stageHistory);l.push({stage:t,at:s}),d.stageHistory=l.slice(-ce)}const o=this.db.prepare("UPDATE jobs SET metadata_json = ? WHERE job_id = ?").run(S(d),e.jobId);return this.toWriteResult(o)}catch(n){throw m(n,"sqlite-mutation-failed")}}updateJobAndExistingGoalCampaignStatus(e){return this.runInTransaction(()=>{const t=this.db.prepare(`
|
|
186
212
|
UPDATE jobs
|
|
187
213
|
SET status = ?,
|
|
188
214
|
reason_code = COALESCE(?, reason_code),
|
|
189
215
|
updated_at = ?,
|
|
190
216
|
next_run_at = COALESCE(?, next_run_at)
|
|
191
217
|
WHERE job_id = ?
|
|
192
|
-
`).run(e.status,e.reasonCode??null,e.updatedAt,e.nextRunAt??null,e.jobId);if(
|
|
218
|
+
`).run(e.status,e.reasonCode??null,e.updatedAt,e.nextRunAt??null,e.jobId);if(t.changes===0)throw new i("sqlite-foreign-key-failed",`Continuity SQLite job ${e.jobId} was not found for status parity update.`);const r=this.db.prepare(`
|
|
193
219
|
UPDATE goal_campaigns
|
|
194
220
|
SET status = ?,
|
|
195
221
|
reason_code = COALESCE(?, reason_code),
|
|
196
222
|
updated_at = ?
|
|
197
223
|
WHERE job_id = ?
|
|
198
|
-
`).run(e.status,e.reasonCode??null,e.updatedAt,e.jobId);return this.toWriteResult({changes:
|
|
224
|
+
`).run(e.status,e.reasonCode??null,e.updatedAt,e.jobId);return this.toWriteResult({changes:t.changes+r.changes})})}scheduleNextTick(e){return this.updateJobStatus({jobId:e.jobId,status:"active",updatedAt:e.updatedAt,reasonCode:e.reasonCode,nextRunAt:e.scheduledAt})}acquireLease(e){this.assertCanMutate();const t=S(e.metadata);try{const r=this.db.prepare(`
|
|
199
225
|
INSERT OR IGNORE INTO job_leases (
|
|
200
226
|
lease_id, job_id, runner_id, status, acquired_at, expires_at,
|
|
201
227
|
operation_id, idempotency_key, metadata_json
|
|
202
228
|
) VALUES (?, ?, ?, 'acquired', ?, ?, ?, ?, ?)
|
|
203
|
-
`).run(e.leaseId,e.jobId,e.runnerId,e.acquiredAt,e.expiresAt,e.operationId??null,e.idempotencyKey??null,
|
|
229
|
+
`).run(e.leaseId,e.jobId,e.runnerId,e.acquiredAt,e.expiresAt,e.operationId??null,e.idempotencyKey??null,t);return this.toWriteResult(r)}catch(r){throw m(r,"sqlite-mutation-failed")}}releaseLease(e){this.assertCanMutate();try{const t=this.db.prepare(`
|
|
204
230
|
UPDATE job_leases
|
|
205
231
|
SET status = 'released', released_at = ?
|
|
206
232
|
WHERE lease_id = ? AND released_at IS NULL
|
|
207
|
-
`).run(e.releasedAt,e.leaseId);if(
|
|
233
|
+
`).run(e.releasedAt,e.leaseId);if(t.changes===0)throw new i("sqlite-foreign-key-failed",`Continuity SQLite lease ${e.leaseId} was not found for release.`);return this.toWriteResult(t)}catch(t){throw m(t,"sqlite-mutation-failed")}}recordStateSnapshot(e){this.assertCanMutate(),b(e.summary,"state_snapshots.summary"),b(e.relativePath,"state_snapshots.relative_path");const t=S(e.metadata);try{const r=this.db.prepare(`
|
|
208
234
|
INSERT OR IGNORE INTO state_snapshots (
|
|
209
235
|
snapshot_id, job_id, kind, relative_path, sha256, summary, captured_at,
|
|
210
236
|
operation_id, idempotency_key, metadata_json
|
|
211
237
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
212
|
-
`).run(e.snapshotId,e.jobId??null,e.kind,e.relativePath??null,e.sha256??null,e.summary??null,e.capturedAt,e.operationId??null,e.idempotencyKey??null,
|
|
238
|
+
`).run(e.snapshotId,e.jobId??null,e.kind,e.relativePath??null,e.sha256??null,e.summary??null,e.capturedAt,e.operationId??null,e.idempotencyKey??null,t);return this.toWriteResult(r)}catch(r){throw m(r,"sqlite-mutation-failed")}}recordArtifact(e){this.assertCanMutate(),b(e.kind,"artifacts.kind"),b(e.relativePath,"artifacts.relative_path"),b(e.summary,"artifacts.summary");const t=S(e.metadata);try{const r=this.db.prepare(`
|
|
213
239
|
INSERT OR IGNORE INTO artifacts (
|
|
214
240
|
artifact_id, job_id, kind, relative_path, sha256, summary,
|
|
215
241
|
operation_id, idempotency_key, created_at, metadata_json
|
|
216
242
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
217
|
-
`).run(e.artifactId,e.jobId??null,e.kind,e.relativePath,e.sha256??null,e.summary??null,e.operationId??null,e.idempotencyKey??null,e.createdAt,
|
|
243
|
+
`).run(e.artifactId,e.jobId??null,e.kind,e.relativePath,e.sha256??null,e.summary??null,e.operationId??null,e.idempotencyKey??null,e.createdAt,t);return this.toWriteResult(r)}catch(r){throw m(r,"sqlite-mutation-failed")}}enqueueOutbox(e){this.assertCanMutate(),v({outboxId:e.outboxId,jobId:e.jobId,operationId:e.operationId,idempotencyKey:e.idempotencyKey,type:e.type,status:e.status,deliveryCursor:e.deliveryCursor,timestamp:e.createdAt,reasonCode:e.lastErrorReason??e.lastErrorCode,summary:e.lastErrorSummary??e.deadLetterSummary}),v({outboxId:e.outboxId,timestamp:e.updatedAt}),c(e.nextAttemptAt,"outbox.nextAttemptAt",80),c(e.lastAttemptAt,"outbox.lastAttemptAt",80),c(e.sentAt,"outbox.sentAt",80),c(e.ackedAt,"outbox.ackedAt",80),c(e.deadLetteredAt,"outbox.deadLetteredAt",80),N(e.retryCount,"outbox.retryCount"),N(e.attemptCount,"outbox.attemptCount");const t=S(e.payload);try{const r=this.db.prepare(`
|
|
218
244
|
INSERT OR IGNORE INTO outbox (
|
|
219
245
|
outbox_id, job_id, operation_id, idempotency_key, type, status,
|
|
220
246
|
payload_json, retry_count, attempt_count, delivery_cursor,
|
|
@@ -222,7 +248,7 @@ import{Buffer as V}from"node:buffer";import{createHash as M}from"node:crypto";im
|
|
|
222
248
|
last_error_reason, last_error_summary, dead_letter_summary,
|
|
223
249
|
dead_lettered_at, created_at, updated_at
|
|
224
250
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
225
|
-
`).run(e.outboxId,e.jobId??null,e.operationId,e.idempotencyKey??null,e.type,e.status??"pending",
|
|
251
|
+
`).run(e.outboxId,e.jobId??null,e.operationId,e.idempotencyKey??null,e.type,e.status??"pending",t??"{}",e.retryCount??0,e.attemptCount??0,e.deliveryCursor??null,e.nextAttemptAt??null,e.lastAttemptAt??null,e.sentAt??null,e.ackedAt??null,e.lastErrorCode??null,e.lastErrorReason??e.lastErrorCode??null,e.lastErrorSummary??null,e.deadLetterSummary??null,e.deadLetteredAt??null,e.createdAt,e.updatedAt);return this.toWriteResult(r)}catch(r){throw m(r,"sqlite-mutation-failed")}}selectOutboxBatch(e){v({outboxId:"outbox-query",timestamp:e.nowIso});const t=Math.max(1,Math.min(100,Math.floor(e.limit))),r=q(e.statuses?.length?e.statuses:["pending","failed"]);for(const d of r)if(!Ie(d))throw new i("sqlite-public-safety-rejected","Continuity SQLite outbox batch query rejected an unknown status.");const s=r.map(()=>"?").join(", ");return this.db.prepare(`
|
|
226
252
|
SELECT outbox_id, job_id, operation_id, idempotency_key, type, status,
|
|
227
253
|
payload_json, retry_count, attempt_count, delivery_cursor,
|
|
228
254
|
next_attempt_at, last_attempt_at, sent_at, acked_at, last_error_code,
|
|
@@ -233,7 +259,7 @@ import{Buffer as V}from"node:buffer";import{createHash as M}from"node:crypto";im
|
|
|
233
259
|
AND (status NOT IN ('pending', 'failed') OR next_attempt_at IS NULL OR next_attempt_at <= ?)
|
|
234
260
|
ORDER BY COALESCE(next_attempt_at, created_at) ASC, created_at ASC, outbox_id ASC
|
|
235
261
|
LIMIT ?
|
|
236
|
-
`).all(...r,e.nowIso,
|
|
262
|
+
`).all(...r,e.nowIso,t).map(ht)}markOutboxSent(e){this.assertCanMutate(),v({outboxId:e.outboxId,deliveryCursor:e.deliveryCursor,timestamp:e.sentAt,reasonCode:e.reasonCode});try{return this.runInTransaction(()=>{const t=this.getOutboxTransitionRow(e.outboxId);if(!t)return C({outboxId:e.outboxId,status:"missing",changes:0,replay:!1,reasonCode:"outbox-missing"});if((t.status==="sent"||t.status==="acked")&&t.delivery_cursor===e.deliveryCursor)return C({outboxId:e.outboxId,status:t.status,changes:0,replay:!0,deliveryCursor:e.deliveryCursor,reasonCode:e.reasonCode??"outbox-delivery-replay"});if(t.status==="sent"||t.status==="acked"||t.status==="dead_letter")return C({outboxId:e.outboxId,status:"conflict",changes:0,replay:!1,deliveryCursor:t.delivery_cursor??void 0,reasonCode:"outbox-delivery-conflict"});const r=this.db.prepare(`
|
|
237
263
|
UPDATE outbox
|
|
238
264
|
SET status = 'sent',
|
|
239
265
|
delivery_cursor = ?,
|
|
@@ -244,7 +270,7 @@ import{Buffer as V}from"node:buffer";import{createHash as M}from"node:crypto";im
|
|
|
244
270
|
updated_at = ?
|
|
245
271
|
WHERE outbox_id = ?
|
|
246
272
|
AND status IN ('pending', 'failed')
|
|
247
|
-
`).run(e.deliveryCursor,e.sentAt,e.sentAt,e.sentAt,e.outboxId);return C({outboxId:e.outboxId,status:"sent",changes:r.changes,replay:!1,deliveryCursor:e.deliveryCursor,reasonCode:e.reasonCode??"outbox-sent"})})}catch(
|
|
273
|
+
`).run(e.deliveryCursor,e.sentAt,e.sentAt,e.sentAt,e.outboxId);return C({outboxId:e.outboxId,status:"sent",changes:r.changes,replay:!1,deliveryCursor:e.deliveryCursor,reasonCode:e.reasonCode??"outbox-sent"})})}catch(t){throw m(t,"sqlite-mutation-failed")}}ackOutbox(e){this.assertCanMutate(),v({outboxId:e.outboxId,deliveryCursor:e.deliveryCursor,timestamp:e.ackedAt,reasonCode:e.reasonCode});try{return this.runInTransaction(()=>{const t=this.getOutboxTransitionRow(e.outboxId);if(!t)return C({outboxId:e.outboxId,status:"missing",changes:0,replay:!1,reasonCode:"outbox-missing"});if(t.status==="acked"&&(!e.deliveryCursor||t.delivery_cursor===e.deliveryCursor))return C({outboxId:e.outboxId,status:"acked",changes:0,replay:!0,deliveryCursor:t.delivery_cursor??void 0,reasonCode:e.reasonCode??"outbox-ack-replay"});if(t.status!=="sent"||e.deliveryCursor&&t.delivery_cursor!==e.deliveryCursor)return C({outboxId:e.outboxId,status:"conflict",changes:0,replay:!1,deliveryCursor:t.delivery_cursor??void 0,reasonCode:"outbox-ack-conflict"});const r=this.db.prepare(`
|
|
248
274
|
UPDATE outbox
|
|
249
275
|
SET status = 'acked',
|
|
250
276
|
acked_at = ?,
|
|
@@ -254,7 +280,7 @@ import{Buffer as V}from"node:buffer";import{createHash as M}from"node:crypto";im
|
|
|
254
280
|
last_error_reason = NULL
|
|
255
281
|
WHERE outbox_id = ?
|
|
256
282
|
AND status = 'sent'
|
|
257
|
-
`).run(e.ackedAt,e.ackedAt,e.outboxId);return C({outboxId:e.outboxId,status:"acked",changes:r.changes,replay:!1,deliveryCursor:
|
|
283
|
+
`).run(e.ackedAt,e.ackedAt,e.outboxId);return C({outboxId:e.outboxId,status:"acked",changes:r.changes,replay:!1,deliveryCursor:t.delivery_cursor??void 0,reasonCode:e.reasonCode??"outbox-acked"})})}catch(t){throw m(t,"sqlite-mutation-failed")}}failOutboxDelivery(e){this.assertCanMutate(),v({outboxId:e.outboxId,deliveryCursor:e.deliveryCursor,timestamp:e.failedAt,reasonCode:e.reasonCode,summary:e.summary}),c(e.nextRetryAt,"outbox.nextRetryAt",80);try{return this.runInTransaction(()=>{const t=this.getOutboxTransitionRow(e.outboxId);if(!t)return C({outboxId:e.outboxId,status:"missing",changes:0,replay:!1,reasonCode:"outbox-missing"});if(t.status==="acked")return C({outboxId:e.outboxId,status:"acked",changes:0,replay:!0,deliveryCursor:t.delivery_cursor??void 0,reasonCode:"outbox-already-acked"});if(t.status==="dead_letter")return C({outboxId:e.outboxId,status:"dead_letter",changes:0,replay:!0,deliveryCursor:t.delivery_cursor??void 0,deadLetteredAt:t.dead_lettered_at??void 0,reasonCode:t.last_error_reason??t.last_error_code??e.reasonCode});if(e.deliveryCursor&&t.delivery_cursor&&t.delivery_cursor!==e.deliveryCursor)return C({outboxId:e.outboxId,status:"conflict",changes:0,replay:!1,deliveryCursor:t.delivery_cursor,reasonCode:"outbox-fail-conflict"});const r=Math.max(1,t.attempt_count??0,t.retry_count??0),s=we({nowIso:e.failedAt,attemptCount:r,reasonCode:e.reasonCode,summary:e.summary,nextRetryAt:e.nextRetryAt,policy:e.policy}),n=this.db.prepare(`
|
|
258
284
|
UPDATE outbox
|
|
259
285
|
SET status = ?,
|
|
260
286
|
retry_count = MAX(retry_count, ?),
|
|
@@ -267,7 +293,7 @@ import{Buffer as V}from"node:buffer";import{createHash as M}from"node:crypto";im
|
|
|
267
293
|
updated_at = ?
|
|
268
294
|
WHERE outbox_id = ?
|
|
269
295
|
AND status IN ('pending', 'sent', 'failed')
|
|
270
|
-
`).run(s.status,r,s.status==="failed"?s.nextRetryAt??e.failedAt:null,e.reasonCode,e.reasonCode,e.summary??null,s.status==="dead_letter"?e.summary??e.reasonCode:null,s.deadLetteredAt??null,e.failedAt,e.outboxId);return C({outboxId:e.outboxId,status:s.status,changes:
|
|
296
|
+
`).run(s.status,r,s.status==="failed"?s.nextRetryAt??e.failedAt:null,e.reasonCode,e.reasonCode,e.summary??null,s.status==="dead_letter"?e.summary??e.reasonCode:null,s.deadLetteredAt??null,e.failedAt,e.outboxId);return C({outboxId:e.outboxId,status:s.status,changes:n.changes,replay:!1,deliveryCursor:t.delivery_cursor??e.deliveryCursor,reasonCode:s.reasonCode,...s.nextRetryAt?{nextRetryAt:s.nextRetryAt}:{},...s.deadLetteredAt?{deadLetteredAt:s.deadLetteredAt}:{}})})}catch(t){throw m(t,"sqlite-mutation-failed")}}deadLetterOutbox(e){this.assertCanMutate(),v({outboxId:e.outboxId,timestamp:e.deadLetteredAt,reasonCode:e.reasonCode,summary:e.summary});try{return this.runInTransaction(()=>{const t=this.getOutboxTransitionRow(e.outboxId);if(!t)return C({outboxId:e.outboxId,status:"missing",changes:0,replay:!1,reasonCode:"outbox-missing"});if(t.status==="dead_letter")return C({outboxId:e.outboxId,status:"dead_letter",changes:0,replay:!0,deliveryCursor:t.delivery_cursor??void 0,deadLetteredAt:t.dead_lettered_at??void 0,reasonCode:t.last_error_reason??t.last_error_code??e.reasonCode});const r=this.db.prepare(`
|
|
271
297
|
UPDATE outbox
|
|
272
298
|
SET status = 'dead_letter',
|
|
273
299
|
next_attempt_at = NULL,
|
|
@@ -279,13 +305,13 @@ import{Buffer as V}from"node:buffer";import{createHash as M}from"node:crypto";im
|
|
|
279
305
|
updated_at = ?
|
|
280
306
|
WHERE outbox_id = ?
|
|
281
307
|
AND status <> 'acked'
|
|
282
|
-
`).run(e.reasonCode,e.reasonCode,e.summary,e.summary,e.deadLetteredAt,e.deadLetteredAt,e.outboxId);return C({outboxId:e.outboxId,status:"dead_letter",changes:r.changes,replay:!1,deliveryCursor:
|
|
308
|
+
`).run(e.reasonCode,e.reasonCode,e.summary,e.summary,e.deadLetteredAt,e.deadLetteredAt,e.outboxId);return C({outboxId:e.outboxId,status:"dead_letter",changes:r.changes,replay:!1,deliveryCursor:t.delivery_cursor??void 0,deadLetteredAt:e.deadLetteredAt,reasonCode:e.reasonCode})})}catch(t){throw m(t,"sqlite-mutation-failed")}}retryOutboxEntries(e){this.assertCanMutate();const t=Math.max(1,Math.min(100,Math.floor(e.limit))),r=q(e.statuses?.length?e.statuses:["failed","dead_letter"]),s=e.reasonCode??"backoff-scheduled";b(s,"outbox.last_error_code"),b(e.nextAttemptAt,"outbox.next_attempt_at");try{return this.runInTransaction(()=>{const n=r.map(()=>"?").join(", "),o=this.db.prepare(`
|
|
283
309
|
SELECT outbox_id
|
|
284
310
|
FROM outbox
|
|
285
|
-
WHERE status IN (${
|
|
311
|
+
WHERE status IN (${n})
|
|
286
312
|
ORDER BY updated_at ASC, outbox_id ASC
|
|
287
313
|
LIMIT ?
|
|
288
|
-
`).all(...r,
|
|
314
|
+
`).all(...r,t).map(y=>y.outbox_id).filter(y=>typeof y=="string"&&y.length>0);if(o.length===0)return{retriedOutboxIds:[],changes:0,reasonCode:s,publicSafe:!0};const l=o.map(()=>"?").join(", "),I=this.db.prepare(`
|
|
289
315
|
UPDATE outbox
|
|
290
316
|
SET status = 'pending',
|
|
291
317
|
retry_count = retry_count + 1,
|
|
@@ -298,8 +324,8 @@ import{Buffer as V}from"node:buffer";import{createHash as M}from"node:crypto";im
|
|
|
298
324
|
dead_letter_summary = NULL,
|
|
299
325
|
dead_lettered_at = NULL,
|
|
300
326
|
updated_at = ?
|
|
301
|
-
WHERE outbox_id IN (${
|
|
302
|
-
`).run(e.nextAttemptAt??e.nowIso,s,s,e.nowIso,...
|
|
327
|
+
WHERE outbox_id IN (${l})
|
|
328
|
+
`).run(e.nextAttemptAt??e.nowIso,s,s,e.nowIso,...o);return{retriedOutboxIds:o,changes:I.changes,reasonCode:s,publicSafe:!0}})}catch(n){throw m(n,"sqlite-mutation-failed")}}upsertGoalCampaign(e){this.assertCanMutate(),b(e.title,"goal_campaigns.title"),b(e.publicSummary,"goal_campaigns.public_summary");const t=S(e.metadata);try{const r=this.db.prepare(`
|
|
303
329
|
INSERT INTO goal_campaigns (
|
|
304
330
|
campaign_id, job_id, status, title, public_summary, reason_code,
|
|
305
331
|
created_at, updated_at, operation_id, idempotency_key, metadata_json
|
|
@@ -313,7 +339,7 @@ import{Buffer as V}from"node:buffer";import{createHash as M}from"node:crypto";im
|
|
|
313
339
|
operation_id = excluded.operation_id,
|
|
314
340
|
idempotency_key = excluded.idempotency_key,
|
|
315
341
|
metadata_json = excluded.metadata_json
|
|
316
|
-
`).run(e.campaignId,e.jobId,e.status,e.title??null,e.publicSummary??null,e.reasonCode??null,e.createdAt,e.updatedAt,e.operationId??null,e.idempotencyKey??null,
|
|
342
|
+
`).run(e.campaignId,e.jobId,e.status,e.title??null,e.publicSummary??null,e.reasonCode??null,e.createdAt,e.updatedAt,e.operationId??null,e.idempotencyKey??null,t);return this.toWriteResult(r)}catch(r){throw m(r,"sqlite-mutation-failed")}}upsertGoalLedgerItem(e){this.assertCanMutate(),b(e.summary,"goal_ledger_items.summary");const t=S(e.metadata);try{this.ensureGoalCampaign(e.campaignId,e.jobId,e.createdAt,e.updatedAt);const r=this.db.prepare(`
|
|
317
343
|
INSERT INTO goal_ledger_items (
|
|
318
344
|
item_id, campaign_id, operation_id, idempotency_key, item_type, status,
|
|
319
345
|
summary, reason_code, created_at, updated_at, metadata_json
|
|
@@ -324,7 +350,7 @@ import{Buffer as V}from"node:buffer";import{createHash as M}from"node:crypto";im
|
|
|
324
350
|
reason_code = excluded.reason_code,
|
|
325
351
|
updated_at = excluded.updated_at,
|
|
326
352
|
metadata_json = excluded.metadata_json
|
|
327
|
-
`).run(e.itemId,e.campaignId,e.operationId??null,e.idempotencyKey??null,e.itemType,e.status,e.summary,e.reasonCode??null,e.createdAt,e.updatedAt,
|
|
353
|
+
`).run(e.itemId,e.campaignId,e.operationId??null,e.idempotencyKey??null,e.itemType,e.status,e.summary,e.reasonCode??null,e.createdAt,e.updatedAt,t);return this.toWriteResult(r)}catch(r){throw m(r,"sqlite-mutation-failed")}}upsertGoalVerifier(e){this.assertCanMutate(),b(e.summary,"goal_verifiers.summary");const t=S(e.metadata);try{const r=e.lastCheckedAt??this.now();this.ensureGoalCampaign(e.campaignId,e.jobId,r,r);const s=this.db.prepare(`
|
|
328
354
|
INSERT INTO goal_verifiers (
|
|
329
355
|
verifier_id, campaign_id, kind, status, summary, reason_code,
|
|
330
356
|
last_checked_at, operation_id, idempotency_key, metadata_json
|
|
@@ -335,7 +361,7 @@ import{Buffer as V}from"node:buffer";import{createHash as M}from"node:crypto";im
|
|
|
335
361
|
reason_code = excluded.reason_code,
|
|
336
362
|
last_checked_at = excluded.last_checked_at,
|
|
337
363
|
metadata_json = excluded.metadata_json
|
|
338
|
-
`).run(e.verifierId,e.campaignId,e.kind,e.status,e.summary??null,e.reasonCode??null,e.lastCheckedAt??null,e.operationId??null,e.idempotencyKey??null,
|
|
364
|
+
`).run(e.verifierId,e.campaignId,e.kind,e.status,e.summary??null,e.reasonCode??null,e.lastCheckedAt??null,e.operationId??null,e.idempotencyKey??null,t);return this.toWriteResult(s)}catch(r){throw m(r,"sqlite-mutation-failed")}}upsertGoalReviewGate(e){this.assertCanMutate(),b(e.summary,"goal_review_gates.summary");const t=S(e.metadata);try{const r=this.now();this.ensureGoalCampaign(e.campaignId,e.jobId,r,r);const s=this.db.prepare(`
|
|
339
365
|
INSERT INTO goal_review_gates (
|
|
340
366
|
gate_id, campaign_id, status, summary, required, reason_code,
|
|
341
367
|
operation_id, idempotency_key, metadata_json
|
|
@@ -346,7 +372,7 @@ import{Buffer as V}from"node:buffer";import{createHash as M}from"node:crypto";im
|
|
|
346
372
|
required = excluded.required,
|
|
347
373
|
reason_code = excluded.reason_code,
|
|
348
374
|
metadata_json = excluded.metadata_json
|
|
349
|
-
`).run(e.gateId,e.campaignId,e.status,e.summary??null,e.required?1:0,e.reasonCode??null,e.operationId??null,e.idempotencyKey??null,
|
|
375
|
+
`).run(e.gateId,e.campaignId,e.status,e.summary??null,e.required?1:0,e.reasonCode??null,e.operationId??null,e.idempotencyKey??null,t);return this.toWriteResult(s)}catch(r){throw m(r,"sqlite-mutation-failed")}}recordOperationAudit(e){return this.appendReceipt(e)}hasOperationRef(e,t){this.assertCanMutate();const r=["jobs","job_leases","job_events","job_receipts","goal_campaigns","goal_ledger_items","goal_verifiers","goal_review_gates","loop_jobs","artifacts","state_snapshots","headless_execution_attempts","runner_config","outbox"],s=r.map(o=>`SELECT 1 AS found FROM ${o} WHERE operation_id = ?${t?" OR idempotency_key = ?":""}`),n=r.flatMap(()=>t?[e,t]:[e]);return!!this.db.prepare(`${s.join(" UNION ALL ")} LIMIT 1`).get(...n)}jobExists(e){return!!this.db.prepare("SELECT 1 AS found FROM jobs WHERE job_id = ? LIMIT 1").get(e)}getHeadlessExecutionAttempt(e){return this.db.prepare(`
|
|
350
376
|
SELECT attempt_id, execution_id, job_id, directive_hash, directive_kind,
|
|
351
377
|
command_class, target_kind, target_ref, story_id, epic_id,
|
|
352
378
|
runtime_id, model_id, runtime_source, status, reason_code,
|
|
@@ -360,13 +386,13 @@ import{Buffer as V}from"node:buffer";import{createHash as M}from"node:crypto";im
|
|
|
360
386
|
FROM headless_execution_attempts
|
|
361
387
|
WHERE attempt_id = ?
|
|
362
388
|
LIMIT 1
|
|
363
|
-
`).get(e)}getOutboxTransitionRow(e){const
|
|
389
|
+
`).get(e)}getOutboxTransitionRow(e){const t=this.db.prepare(`
|
|
364
390
|
SELECT outbox_id, status, delivery_cursor, retry_count, attempt_count,
|
|
365
391
|
last_error_code, last_error_reason, dead_lettered_at
|
|
366
392
|
FROM outbox
|
|
367
393
|
WHERE outbox_id = ?
|
|
368
394
|
LIMIT 1
|
|
369
|
-
`).get(e);if(!(!
|
|
395
|
+
`).get(e);if(!(!t||!E(t)))return t}selectReceiptRetentionCandidates(e){return this.db.prepare(`
|
|
370
396
|
WITH sized AS (
|
|
371
397
|
SELECT receipt_id, job_id, status, reason_code, created_at,
|
|
372
398
|
length(receipt_id) + length(job_id) + length(status) + length(created_at)
|
|
@@ -404,13 +430,13 @@ import{Buffer as V}from"node:buffer";import{createHash as M}from"node:crypto";im
|
|
|
404
430
|
WHERE created_at < ? OR retain_rank > ? OR cumulative_bytes > ?
|
|
405
431
|
ORDER BY created_at ASC, event_id ASC
|
|
406
432
|
LIMIT ?
|
|
407
|
-
`).all(O,e.cutoff,e.maxItems,e.maxBytes,e.limit).flatMap(r=>typeof r.event_id!="string"||typeof r.job_id!="string"?[]:[{kind:"output",id:r.event_id,jobId:r.job_id,status:typeof r.type=="string"?r.type:O,reasonCode:typeof r.reason_code=="string"?r.reason_code:"continuity-ok",createdAt:typeof r.created_at=="string"?r.created_at:e.cutoff,approxBytes:typeof r.approx_bytes=="number"&&r.approx_bytes>=0?Math.floor(r.approx_bytes):0}])}deleteRetentionCandidates(e,
|
|
433
|
+
`).all(O,e.cutoff,e.maxItems,e.maxBytes,e.limit).flatMap(r=>typeof r.event_id!="string"||typeof r.job_id!="string"?[]:[{kind:"output",id:r.event_id,jobId:r.job_id,status:typeof r.type=="string"?r.type:O,reasonCode:typeof r.reason_code=="string"?r.reason_code:"continuity-ok",createdAt:typeof r.created_at=="string"?r.created_at:e.cutoff,approxBytes:typeof r.approx_bytes=="number"&&r.approx_bytes>=0?Math.floor(r.approx_bytes):0}])}deleteRetentionCandidates(e,t,r){if(r.length===0)return;const s=r.map(()=>"?").join(", ");this.db.prepare(`DELETE FROM ${e} WHERE ${t} IN (${s})`).run(...r)}preserveReceiptDerivedIteration(e,t){const r=this.db.prepare(`
|
|
408
434
|
SELECT COUNT(*) AS iteration
|
|
409
435
|
FROM job_receipts
|
|
410
436
|
WHERE job_id = ?
|
|
411
437
|
AND (operation_id LIKE 'tick-%' OR operation_id LIKE 'loop-tick-%')
|
|
412
438
|
AND status IN ('accepted', 'applied')
|
|
413
|
-
`).get(e),s=typeof r?.iteration=="number"?r.iteration:0;s>0&&this.recordJobStageProgress({jobId:e,iteration:s,at:
|
|
439
|
+
`).get(e),s=typeof r?.iteration=="number"?r.iteration:0;s>0&&this.recordJobStageProgress({jobId:e,iteration:s,at:t,appendHistory:!1})}retainedReceiptOutputCounts(e){const t=this.db.prepare(`
|
|
414
440
|
SELECT COUNT(*) AS count,
|
|
415
441
|
COALESCE(SUM(length(receipt_id) + length(job_id) + length(status) + length(created_at)
|
|
416
442
|
+ COALESCE(length(operation_id), 0) + COALESCE(length(idempotency_key), 0)
|
|
@@ -425,7 +451,7 @@ import{Buffer as V}from"node:buffer";import{createHash as M}from"node:crypto";im
|
|
|
425
451
|
+ COALESCE(length(reason_code), 0) + COALESCE(length(metadata_json), 0)), 0) AS bytes
|
|
426
452
|
FROM job_events
|
|
427
453
|
WHERE job_id = ? AND type = ?
|
|
428
|
-
`).get(e,O);return{receipts:typeof
|
|
454
|
+
`).get(e,O);return{receipts:typeof t?.count=="number"?t.count:0,outputs:typeof r?.count=="number"?r.count:0,bytes:(typeof t?.bytes=="number"?t.bytes:0)+(typeof r?.bytes=="number"?r.bytes:0)}}pruneReceiptCompactionSummaries(e,t){this.db.prepare(`
|
|
429
455
|
DELETE FROM job_events
|
|
430
456
|
WHERE event_id IN (
|
|
431
457
|
SELECT event_id
|
|
@@ -434,14 +460,14 @@ import{Buffer as V}from"node:buffer";import{createHash as M}from"node:crypto";im
|
|
|
434
460
|
ORDER BY created_at DESC, event_id DESC
|
|
435
461
|
LIMIT -1 OFFSET ?
|
|
436
462
|
)
|
|
437
|
-
`).run(e,W,
|
|
463
|
+
`).run(e,W,t)}runInTransaction(e){this.assertCanMutate();const t=this.db.transaction(e);try{return typeof t.immediate=="function"?t.immediate():t()}catch(r){throw m(r,"sqlite-mutation-failed")}}collectSnapshotRows(e){const t=(p,...x)=>{const A=this.db.prepare(p).get(...x);return E(A)&&typeof A.count=="number"?A.count:0},r=this.db.prepare(`
|
|
438
464
|
SELECT status, COUNT(*) AS count FROM outbox GROUP BY status
|
|
439
|
-
`).all(),s={};for(const
|
|
465
|
+
`).all(),s={};for(const p of r)typeof p.status=="string"&&typeof p.count=="number"&&(s[p.status]=p.count);const n=this.db.prepare(`
|
|
440
466
|
SELECT value_json
|
|
441
467
|
FROM runner_config
|
|
442
468
|
WHERE key = 'headless_queue_policy'
|
|
443
469
|
LIMIT 1
|
|
444
|
-
`).get();let
|
|
470
|
+
`).get();let d=De;if(E(n)&&typeof n.value_json=="string")try{const p=JSON.parse(n.value_json);E(p)&&typeof p.maxItems=="number"&&(d=B({maxItems:p.maxItems}))}catch{}const o=t("SELECT COUNT(*) AS count FROM headless_execution_attempts WHERE status = 'queued' AND dead_lettered_at IS NULL"),l=t("SELECT COUNT(*) AS count FROM headless_execution_attempts WHERE status = 'backoff' AND dead_lettered_at IS NULL"),I=t("SELECT COUNT(*) AS count FROM headless_execution_attempts WHERE status = 'running' AND dead_lettered_at IS NULL"),y=t("SELECT COUNT(*) AS count FROM headless_execution_attempts WHERE dead_lettered_at IS NOT NULL"),f=o+l+I,_=this.db.prepare(`
|
|
445
471
|
SELECT MIN(next_retry_at) AS next_retry_at
|
|
446
472
|
FROM headless_execution_attempts
|
|
447
473
|
WHERE status = 'backoff'
|
|
@@ -531,19 +557,19 @@ import{Buffer as V}from"node:buffer";import{createHash as M}from"node:crypto";im
|
|
|
531
557
|
FROM headless_execution_attempts
|
|
532
558
|
ORDER BY enqueued_at DESC, attempt_id ASC
|
|
533
559
|
LIMIT ?
|
|
534
|
-
`).all(e.jobLimit),counts:{jobs:
|
|
560
|
+
`).all(e.jobLimit),counts:{jobs:t("SELECT COUNT(*) AS count FROM jobs"),activeJobs:t("SELECT COUNT(*) AS count FROM jobs WHERE status IN ('planned', 'active', 'running', 'waiting_external', 'waiting_human', 'backoff', 'paused', 'blocked')"),activeLeases:t("SELECT COUNT(*) AS count FROM job_leases WHERE released_at IS NULL"),dueJobs:t("SELECT COUNT(*) AS count FROM jobs WHERE next_run_at IS NOT NULL AND next_run_at <= ? AND status NOT IN ('completed', 'aborted', 'cancelled')",e.nowIso),staleLeases:t("SELECT COUNT(*) AS count FROM job_leases WHERE released_at IS NULL AND expires_at <= ?",e.nowIso),receipts:t("SELECT COUNT(*) AS count FROM job_receipts"),events:t("SELECT COUNT(*) AS count FROM job_events"),processingOutputSummaries:t("SELECT COUNT(*) AS count FROM job_events WHERE type = ?",O),goalLedgerItems:t("SELECT COUNT(*) AS count FROM goal_ledger_items"),goalVerifiers:t("SELECT COUNT(*) AS count FROM goal_verifiers"),goalReviewGates:t("SELECT COUNT(*) AS count FROM goal_review_gates"),stateSnapshots:t("SELECT COUNT(*) AS count FROM state_snapshots"),headlessExecutionAttempts:t("SELECT COUNT(*) AS count FROM headless_execution_attempts"),headlessQueuedAttempts:t("SELECT COUNT(*) AS count FROM headless_execution_attempts WHERE status IN ('queued', 'backoff')"),headlessRunningAttempts:t("SELECT COUNT(*) AS count FROM headless_execution_attempts WHERE status = 'running'"),headlessRetryingAttempts:l,headlessDeadLetterAttempts:y,staleHeadlessExecutionAttempts:t("SELECT COUNT(*) AS count FROM headless_execution_attempts WHERE status = 'running' AND lease_released_at IS NULL AND lease_expires_at <= ?",e.nowIso),outbox:t("SELECT COUNT(*) AS count FROM outbox")},outboxCounts:s,queue:{depth:f,queued:o,running:I,retrying:l,deadLetter:y,capacity:d.maxItems,available:Math.max(0,d.maxItems-f),backpressure:f>=d.maxItems,generatedAt:e.nowIso,...u?{nextRetryAt:u}:{},...f>=d.maxItems?{reasonCode:k.CAP_REACHED}:{},publicSafe:!0}}}listProcessingOutputSummaries(e={}){const t=ye(e.limit),r=pe(e),s=`
|
|
535
561
|
SELECT event_id, job_id, operation_id, summary, reason_code, created_at, metadata_json
|
|
536
562
|
FROM job_events
|
|
537
563
|
WHERE type = ?${r.sql}
|
|
538
564
|
ORDER BY created_at DESC, event_id DESC
|
|
539
565
|
LIMIT ?
|
|
540
|
-
`;return this.db.prepare(`SELECT * FROM (${s}) ORDER BY created_at ASC, event_id ASC`).all(O,...r.params,
|
|
566
|
+
`;return this.db.prepare(`SELECT * FROM (${s}) ORDER BY created_at ASC, event_id ASC`).all(O,...r.params,t).map(be)}pollProcessingOutputSummaries(e={}){const t=ye(e.limit),r=lt(e.cursor),s=pe(e),n=r?" AND (created_at > ? OR (created_at = ? AND event_id > ?))":"",d=`
|
|
541
567
|
SELECT event_id, job_id, operation_id, summary, reason_code, created_at, metadata_json
|
|
542
568
|
FROM job_events
|
|
543
|
-
WHERE type = ?${s.sql}${
|
|
569
|
+
WHERE type = ?${s.sql}${n}
|
|
544
570
|
ORDER BY created_at ASC, event_id ASC
|
|
545
571
|
LIMIT ?
|
|
546
|
-
`,
|
|
572
|
+
`,o=[O];o.push(...s.params),r&&o.push(r.createdAt,r.createdAt,r.eventId),o.push(t+1);const l=this.db.prepare(d).all(...o),I=l.slice(0,t).map(be),y=I[I.length-1];return{summaries:I,...y?{nextCursor:y.cursor}:e.cursor?{nextCursor:e.cursor}:{},hasMore:l.length>t,publicSafe:!0}}listDueJobs(e){const t=Math.max(1,Math.min(50,Math.floor(e.limit)));return this.db.prepare(`
|
|
547
573
|
SELECT j.job_id, j.kind, j.status, j.summary, j.reason_code, j.created_at,
|
|
548
574
|
j.updated_at, j.next_run_at, j.metadata_json,
|
|
549
575
|
(SELECT COUNT(*)
|
|
@@ -561,19 +587,19 @@ import{Buffer as V}from"node:buffer";import{createHash as M}from"node:crypto";im
|
|
|
561
587
|
AND j.status NOT IN ('waiting_external', 'waiting_human', 'paused', 'blocked', 'completed', 'aborted', 'cancelled')
|
|
562
588
|
ORDER BY j.next_run_at ASC, j.job_id ASC
|
|
563
589
|
LIMIT ?
|
|
564
|
-
`).all(e.nowIso,
|
|
590
|
+
`).all(e.nowIso,t)}recoverStaleLeases(e){this.assertCanMutate();const t=Date.parse(e.nowIso);if(!Number.isFinite(t))throw new i("sqlite-public-safety-rejected","Continuity SQLite stale lease recovery received an invalid timestamp.");const r=Math.max(0,Math.floor(e.staleAfterMs)),s=Math.max(1,Math.min(100,Math.floor(e.limit))),n=new Date(t-r).toISOString();try{return this.runInTransaction(()=>{const o=this.db.prepare(`
|
|
565
591
|
SELECT lease_id
|
|
566
592
|
FROM job_leases
|
|
567
593
|
WHERE released_at IS NULL
|
|
568
594
|
AND expires_at <= ?
|
|
569
595
|
ORDER BY expires_at ASC, lease_id ASC
|
|
570
596
|
LIMIT ?
|
|
571
|
-
`).all(
|
|
597
|
+
`).all(n,s).map(y=>y.lease_id).filter(y=>typeof y=="string"&&y.length>0);if(o.length===0)return{recoveredLeaseIds:[],safeExpiredAtOrBefore:n,changes:0};const l=o.map(()=>"?").join(", "),I=this.db.prepare(`
|
|
572
598
|
UPDATE job_leases
|
|
573
599
|
SET status = 'expired', released_at = ?
|
|
574
600
|
WHERE released_at IS NULL
|
|
575
|
-
AND lease_id IN (${
|
|
576
|
-
`).run(e.nowIso,...
|
|
601
|
+
AND lease_id IN (${l})
|
|
602
|
+
`).run(e.nowIso,...o);return{recoveredLeaseIds:o,safeExpiredAtOrBefore:n,changes:I.changes}})}catch(d){throw m(d,"sqlite-mutation-failed")}}recoverStaleHeadlessExecutionAttempts(e){this.assertCanMutate();const t=Date.parse(e.nowIso);if(!Number.isFinite(t))throw new i("sqlite-public-safety-rejected","Continuity SQLite headless stale recovery received an invalid timestamp.");const r=Math.max(0,Math.floor(e.staleAfterMs)),s=Math.max(1,Math.min(100,Math.floor(e.limit))),n=new Date(t-r).toISOString();try{return this.runInTransaction(()=>{const d=this.db.prepare(`
|
|
577
603
|
SELECT attempt_id, retry_count, max_attempts, attempt_count
|
|
578
604
|
FROM headless_execution_attempts
|
|
579
605
|
WHERE status = 'running'
|
|
@@ -581,7 +607,7 @@ import{Buffer as V}from"node:buffer";import{createHash as M}from"node:crypto";im
|
|
|
581
607
|
AND lease_expires_at <= ?
|
|
582
608
|
ORDER BY lease_expires_at ASC, attempt_id ASC
|
|
583
609
|
LIMIT ?
|
|
584
|
-
`).all(
|
|
610
|
+
`).all(n,s),o=[],l=[],I=B(e.policy);for(const _ of d){if(typeof _.attempt_id!="string"||_.attempt_id.length===0)continue;const u=typeof _.retry_count=="number"?_.retry_count:0,p=typeof _.max_attempts=="number"?_.max_attempts:1,x=typeof _.attempt_count=="number"?_.attempt_count:0;Math.max(x,u+1)>=p?l.push(_.attempt_id):o.push({attemptId:_.attempt_id,nextRetryAt:Ue(e.nowIso,u+1,I)})}let y=0;for(const _ of o)y+=this.db.prepare(`
|
|
585
611
|
UPDATE headless_execution_attempts
|
|
586
612
|
SET status = 'backoff',
|
|
587
613
|
retry_count = retry_count + 1,
|
|
@@ -592,7 +618,7 @@ import{Buffer as V}from"node:buffer";import{createHash as M}from"node:crypto";im
|
|
|
592
618
|
WHERE attempt_id = ?
|
|
593
619
|
AND status = 'running'
|
|
594
620
|
AND lease_released_at IS NULL
|
|
595
|
-
`).run(k.LEASE_TIMEOUT_RETRY,e.nowIso,_.nextRetryAt,_.nextRetryAt,_.attemptId).changes;if(
|
|
621
|
+
`).run(k.LEASE_TIMEOUT_RETRY,e.nowIso,_.nextRetryAt,_.nextRetryAt,_.attemptId).changes;if(l.length>0){const _=l.map(()=>"?").join(", ");y+=this.db.prepare(`
|
|
596
622
|
UPDATE headless_execution_attempts
|
|
597
623
|
SET status = 'failed',
|
|
598
624
|
retry_count = retry_count + 1,
|
|
@@ -605,15 +631,15 @@ import{Buffer as V}from"node:buffer";import{createHash as M}from"node:crypto";im
|
|
|
605
631
|
WHERE attempt_id IN (${_})
|
|
606
632
|
AND status = 'running'
|
|
607
633
|
AND lease_released_at IS NULL
|
|
608
|
-
`).run(k.ATTEMPTS_EXHAUSTED,e.nowIso,e.nowIso,e.nowIso,k.ATTEMPTS_EXHAUSTED,...
|
|
634
|
+
`).run(k.ATTEMPTS_EXHAUSTED,e.nowIso,e.nowIso,e.nowIso,k.ATTEMPTS_EXHAUSTED,...l).changes}const f=o.map(_=>_.attemptId);return{recoveredAttemptIds:[...f,...l],failedAttemptIds:l,retryingAttemptIds:f,deadLetteredAttemptIds:l,safeExpiredAtOrBefore:n,changes:y,publicSafe:!0}})}catch(d){throw m(d,"sqlite-mutation-failed")}}ensureGoalCampaign(e,t,r,s){this.db.prepare(`
|
|
609
635
|
INSERT OR IGNORE INTO goal_campaigns (
|
|
610
636
|
campaign_id, job_id, status, public_summary, created_at, updated_at
|
|
611
637
|
) VALUES (?, ?, 'active', 'Public goal campaign summary unavailable', ?, ?)
|
|
612
|
-
`).run(e,
|
|
638
|
+
`).run(e,t,r,s)}configureConnection(){const e=String(w(this.db.pragma("journal_mode = WAL",{simple:!0}))??"").toLowerCase();if(e!=="wal")throw new i("sqlite-migration-failed",`Continuity SQLite journal_mode did not switch to WAL (observed ${e||"unknown"}).`);if(this.db.pragma("foreign_keys = ON"),this.db.pragma(`busy_timeout = ${this.busyTimeoutMs}`),Number(w(this.db.pragma("foreign_keys",{simple:!0}))??0)!==1)throw new i("sqlite-migration-failed","Continuity SQLite foreign_keys pragma is not enabled.")}ensureMigrationTable(){this.db.exec(`
|
|
613
639
|
CREATE TABLE IF NOT EXISTS continuity_migrations (
|
|
614
640
|
version INTEGER PRIMARY KEY,
|
|
615
641
|
name TEXT NOT NULL,
|
|
616
642
|
checksum TEXT NOT NULL,
|
|
617
643
|
applied_at TEXT NOT NULL
|
|
618
644
|
);
|
|
619
|
-
`)}applyMigrations(){this.db.transaction(()=>{for(const
|
|
645
|
+
`)}applyMigrations(){this.db.transaction(()=>{for(const t of Je){const r=st(t.sql),s=this.db.prepare("SELECT version, name, checksum FROM continuity_migrations WHERE version = ?").get(t.version);if(s){if(s.checksum!==r||s.name!==t.name)throw new i("sqlite-migration-conflict",`Continuity SQLite migration ${t.version} checksum conflict.`);continue}this.db.exec(t.sql),this.db.prepare("INSERT INTO continuity_migrations (version, name, checksum, applied_at) VALUES (?, ?, ?, ?)").run(t.version,t.name,r,this.now()),this.db.pragma(`user_version = ${t.version}`)}})()}assertCanMutate(){if(this.mutationBlocked)throw new i("sqlite-mutation-blocked","Continuity SQLite mutation is blocked after integrity failure.",{mutationBlocked:!0})}toWriteResult(e){const t=e.changes>0;return{inserted:t,replay:!t,changes:e.changes}}}export{O as CONTINUITY_PROCESSING_OUTPUT_SUMMARY_EVENT_TYPE,Be as CONTINUITY_PROCESSING_OUTPUT_SUMMARY_MAX_CHARS,Ye as CONTINUITY_PUBLIC_STAGES,We as CONTINUITY_SQLITE_FILENAME,ne as CONTINUITY_SQLITE_RELATIVE_DIR,kt as CONTINUITY_SQLITE_SCHEMA_VERSION,ce as CONTINUITY_STAGE_HISTORY_MAX,ft as ContinuitySqliteStore,i as ContinuitySqliteStoreError,de as DEFAULT_CONTINUITY_PROCESSING_SUMMARY_LIMIT,Fe as DEFAULT_CONTINUITY_SQLITE_BUSY_TIMEOUT_MS,$e as MAX_CONTINUITY_PROCESSING_SUMMARY_LIMIT,ie as SQLITE_ADAPTER_INSTALL_GUIDANCE,Ee as continuitySqliteStorePath,le as isContinuityPublicStage,It as loadBetterSqlite3Adapter,Qe as normalizeContinuityStageIteration,Ut as openContinuitySqliteReadOnly,Dt as openContinuitySqliteStore,Ge as sanitizeContinuityStageHistory,ue as sanitizeContinuityStageTimestamp};
|