@ornexus/neocortex 4.60.16
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/LICENSE +56 -0
- package/LICENSE-COMMERCIAL.md +70 -0
- package/README.md +58 -0
- package/dist/sbom.cdx.json +11159 -0
- package/docs/install/coderabbit-manual-setup.md +86 -0
- package/docs/install/installer-diagnostics.md +107 -0
- package/docs/install/linux-global-install.md +97 -0
- package/install.js +572 -0
- package/install.ps1 +2214 -0
- package/install.sh +2013 -0
- package/package.json +132 -0
- package/packages/client/dist/adapters/adapter-registry.d.ts +61 -0
- package/packages/client/dist/adapters/adapter-registry.js +1 -0
- package/packages/client/dist/adapters/antigravity-adapter.d.ts +18 -0
- package/packages/client/dist/adapters/antigravity-adapter.js +2 -0
- package/packages/client/dist/adapters/claude-code-adapter.d.ts +19 -0
- package/packages/client/dist/adapters/claude-code-adapter.js +3 -0
- package/packages/client/dist/adapters/codex-adapter.d.ts +19 -0
- package/packages/client/dist/adapters/codex-adapter.js +2 -0
- package/packages/client/dist/adapters/cursor-adapter.d.ts +19 -0
- package/packages/client/dist/adapters/cursor-adapter.js +4 -0
- package/packages/client/dist/adapters/gemini-adapter.d.ts +18 -0
- package/packages/client/dist/adapters/gemini-adapter.js +2 -0
- package/packages/client/dist/adapters/index.d.ts +19 -0
- package/packages/client/dist/adapters/index.js +1 -0
- package/packages/client/dist/adapters/platform-detector.d.ts +48 -0
- package/packages/client/dist/adapters/platform-detector.js +1 -0
- package/packages/client/dist/adapters/target-adapter.d.ts +70 -0
- package/packages/client/dist/adapters/target-adapter.js +0 -0
- package/packages/client/dist/adapters/vscode-adapter.d.ts +19 -0
- package/packages/client/dist/adapters/vscode-adapter.js +2 -0
- package/packages/client/dist/agent/refresh-stubs.d.ts +90 -0
- package/packages/client/dist/agent/refresh-stubs.js +2 -0
- package/packages/client/dist/agent/update-agent-yaml.d.ts +26 -0
- package/packages/client/dist/agent/update-agent-yaml.js +1 -0
- package/packages/client/dist/agent/update-description.d.ts +45 -0
- package/packages/client/dist/agent/update-description.js +1 -0
- package/packages/client/dist/cache/crypto-utils.d.ts +30 -0
- package/packages/client/dist/cache/crypto-utils.js +1 -0
- package/packages/client/dist/cache/encrypted-cache.d.ts +30 -0
- package/packages/client/dist/cache/encrypted-cache.js +1 -0
- package/packages/client/dist/cache/in-memory-asset-cache.d.ts +62 -0
- package/packages/client/dist/cache/in-memory-asset-cache.js +1 -0
- package/packages/client/dist/cache/index.d.ts +13 -0
- package/packages/client/dist/cache/index.js +1 -0
- package/packages/client/dist/cache/protected-pi-boundary.d.ts +19 -0
- package/packages/client/dist/cache/protected-pi-boundary.js +1 -0
- package/packages/client/dist/checkpoint/checkpoint-client-reader.d.ts +45 -0
- package/packages/client/dist/checkpoint/checkpoint-client-reader.js +2 -0
- package/packages/client/dist/checkpoint/index.d.ts +12 -0
- package/packages/client/dist/checkpoint/index.js +1 -0
- package/packages/client/dist/checkpoint/shared-checkpoint-types.d.ts +85 -0
- package/packages/client/dist/checkpoint/shared-checkpoint-types.js +1 -0
- package/packages/client/dist/cli.d.ts +14 -0
- package/packages/client/dist/cli.js +81 -0
- package/packages/client/dist/commands/activate.d.ts +55 -0
- package/packages/client/dist/commands/activate.js +8 -0
- package/packages/client/dist/commands/cache-status.d.ts +39 -0
- package/packages/client/dist/commands/cache-status.js +2 -0
- package/packages/client/dist/commands/invoke.d.ts +546 -0
- package/packages/client/dist/commands/invoke.js +140 -0
- package/packages/client/dist/commands/refresh-memory.d.ts +11 -0
- package/packages/client/dist/commands/refresh-memory.js +1 -0
- package/packages/client/dist/config/resolver-selection.d.ts +40 -0
- package/packages/client/dist/config/resolver-selection.js +1 -0
- package/packages/client/dist/config/secure-config.d.ts +78 -0
- package/packages/client/dist/config/secure-config.js +12 -0
- package/packages/client/dist/constants.d.ts +25 -0
- package/packages/client/dist/constants.js +1 -0
- package/packages/client/dist/context/context-collector.d.ts +28 -0
- package/packages/client/dist/context/context-collector.js +2 -0
- package/packages/client/dist/context/context-sanitizer.d.ts +28 -0
- package/packages/client/dist/context/context-sanitizer.js +1 -0
- package/packages/client/dist/continuity/autonomous-governance.d.ts +84 -0
- package/packages/client/dist/continuity/autonomous-governance.js +1 -0
- package/packages/client/dist/continuity/continuity-client-state-store.d.ts +302 -0
- package/packages/client/dist/continuity/continuity-client-state-store.js +1 -0
- package/packages/client/dist/continuity/invoke-hooks.d.ts +19 -0
- package/packages/client/dist/continuity/invoke-hooks.js +1 -0
- package/packages/client/dist/continuity/migrations/001-initial-schema.d.ts +11 -0
- package/packages/client/dist/continuity/migrations/001-initial-schema.js +263 -0
- package/packages/client/dist/continuity/migrations/002-processing-output-summary-indexes.d.ts +11 -0
- package/packages/client/dist/continuity/migrations/002-processing-output-summary-indexes.js +7 -0
- package/packages/client/dist/continuity/migrations/003-headless-execution-attempts.d.ts +11 -0
- package/packages/client/dist/continuity/migrations/003-headless-execution-attempts.js +62 -0
- package/packages/client/dist/continuity/migrations/004-outbox-delivery-state.d.ts +11 -0
- package/packages/client/dist/continuity/migrations/004-outbox-delivery-state.js +19 -0
- package/packages/client/dist/continuity/migrations/005-bounded-headless-queue.d.ts +11 -0
- package/packages/client/dist/continuity/migrations/005-bounded-headless-queue.js +35 -0
- package/packages/client/dist/continuity/outbox.d.ts +83 -0
- package/packages/client/dist/continuity/outbox.js +1 -0
- package/packages/client/dist/continuity/runner-bootstrap-policy.d.ts +50 -0
- package/packages/client/dist/continuity/runner-bootstrap-policy.js +1 -0
- package/packages/client/dist/continuity/sqlite-store.d.ts +926 -0
- package/packages/client/dist/continuity/sqlite-store.js +619 -0
- package/packages/client/dist/errors/error-messages.d.ts +40 -0
- package/packages/client/dist/errors/error-messages.js +2 -0
- package/packages/client/dist/graph-retrieval/pre-command-hook.d.ts +34 -0
- package/packages/client/dist/graph-retrieval/pre-command-hook.js +1 -0
- package/packages/client/dist/graph-retrieval/shared-graph-retrieval-contract.d.ts +99 -0
- package/packages/client/dist/graph-retrieval/shared-graph-retrieval-contract.js +1 -0
- package/packages/client/dist/i18n/first-run.d.ts +23 -0
- package/packages/client/dist/i18n/first-run.js +2 -0
- package/packages/client/dist/index.d.ts +56 -0
- package/packages/client/dist/index.js +1 -0
- package/packages/client/dist/license/index.d.ts +5 -0
- package/packages/client/dist/license/index.js +1 -0
- package/packages/client/dist/license/license-client.d.ts +79 -0
- package/packages/client/dist/license/license-client.js +1 -0
- package/packages/client/dist/machine/fingerprint.d.ts +34 -0
- package/packages/client/dist/machine/fingerprint.js +2 -0
- package/packages/client/dist/machine/index.d.ts +5 -0
- package/packages/client/dist/machine/index.js +1 -0
- package/packages/client/dist/memory/project-memory-writer.d.ts +74 -0
- package/packages/client/dist/memory/project-memory-writer.js +36 -0
- package/packages/client/dist/memory/shared-project-memory-types.d.ts +370 -0
- package/packages/client/dist/memory/shared-project-memory-types.js +2 -0
- package/packages/client/dist/policy/architecture-policy.d.ts +40 -0
- package/packages/client/dist/policy/architecture-policy.js +2 -0
- package/packages/client/dist/policy/index.d.ts +8 -0
- package/packages/client/dist/policy/index.js +1 -0
- package/packages/client/dist/policy/shared-policy-types.d.ts +89 -0
- package/packages/client/dist/policy/shared-policy-types.js +0 -0
- package/packages/client/dist/resilience/circuit-breaker.d.ts +70 -0
- package/packages/client/dist/resilience/circuit-breaker.js +1 -0
- package/packages/client/dist/resilience/degradation-manager.d.ts +67 -0
- package/packages/client/dist/resilience/degradation-manager.js +1 -0
- package/packages/client/dist/resilience/freshness-indicator.d.ts +59 -0
- package/packages/client/dist/resilience/freshness-indicator.js +1 -0
- package/packages/client/dist/resilience/index.d.ts +8 -0
- package/packages/client/dist/resilience/index.js +1 -0
- package/packages/client/dist/resilience/recovery-detector.d.ts +59 -0
- package/packages/client/dist/resilience/recovery-detector.js +1 -0
- package/packages/client/dist/resolvers/asset-resolver.d.ts +79 -0
- package/packages/client/dist/resolvers/asset-resolver.js +0 -0
- package/packages/client/dist/resolvers/local-resolver.d.ts +26 -0
- package/packages/client/dist/resolvers/local-resolver.js +8 -0
- package/packages/client/dist/resolvers/remote-resolver.d.ts +91 -0
- package/packages/client/dist/resolvers/remote-resolver.js +1 -0
- package/packages/client/dist/runner/binary.d.ts +115 -0
- package/packages/client/dist/runner/binary.js +1 -0
- package/packages/client/dist/runner/cli.d.ts +168 -0
- package/packages/client/dist/runner/cli.js +70 -0
- package/packages/client/dist/runner/headless/adapters.d.ts +20 -0
- package/packages/client/dist/runner/headless/adapters.js +1 -0
- package/packages/client/dist/runner/headless/claude-code-adapter.d.ts +8 -0
- package/packages/client/dist/runner/headless/claude-code-adapter.js +1 -0
- package/packages/client/dist/runner/headless/fake-adapter.d.ts +8 -0
- package/packages/client/dist/runner/headless/fake-adapter.js +1 -0
- package/packages/client/dist/runner/headless/opencode-adapter.d.ts +15 -0
- package/packages/client/dist/runner/headless/opencode-adapter.js +2 -0
- package/packages/client/dist/runner/headless/resolver.d.ts +68 -0
- package/packages/client/dist/runner/headless/resolver.js +1 -0
- package/packages/client/dist/runner/headless/run-yolo.d.ts +59 -0
- package/packages/client/dist/runner/headless/run-yolo.js +1 -0
- package/packages/client/dist/runner/headless/run-yoloop.d.ts +113 -0
- package/packages/client/dist/runner/headless/run-yoloop.js +1 -0
- package/packages/client/dist/runner/headless/types.d.ts +194 -0
- package/packages/client/dist/runner/headless/types.js +2 -0
- package/packages/client/dist/runner/local-console.d.ts +83 -0
- package/packages/client/dist/runner/local-console.js +13 -0
- package/packages/client/dist/runner/portal-sync-worker.d.ts +184 -0
- package/packages/client/dist/runner/portal-sync-worker.js +1 -0
- package/packages/client/dist/runner/project-identity.d.ts +19 -0
- package/packages/client/dist/runner/project-identity.js +1 -0
- package/packages/client/dist/runner/scheduler.d.ts +186 -0
- package/packages/client/dist/runner/scheduler.js +7 -0
- package/packages/client/dist/runner-cli.d.ts +9 -0
- package/packages/client/dist/runner-cli.js +3 -0
- package/packages/client/dist/state/project-state-snapshot.d.ts +24 -0
- package/packages/client/dist/state/project-state-snapshot.js +1 -0
- package/packages/client/dist/state/state-json-repair.d.ts +74 -0
- package/packages/client/dist/state/state-json-repair.js +3 -0
- package/packages/client/dist/telemetry/index.d.ts +5 -0
- package/packages/client/dist/telemetry/index.js +1 -0
- package/packages/client/dist/telemetry/offline-queue.d.ts +57 -0
- package/packages/client/dist/telemetry/offline-queue.js +1 -0
- package/packages/client/dist/tier/index.d.ts +5 -0
- package/packages/client/dist/tier/index.js +1 -0
- package/packages/client/dist/tier/tier-aware-client.d.ts +105 -0
- package/packages/client/dist/tier/tier-aware-client.js +1 -0
- package/packages/client/dist/types/index.d.ts +140 -0
- package/packages/client/dist/types/index.js +1 -0
- package/packages/client/dist/yoloop/discovery-hook.d.ts +85 -0
- package/packages/client/dist/yoloop/discovery-hook.js +2 -0
- package/packages/client/dist/yoloop/index.d.ts +10 -0
- package/packages/client/dist/yoloop/index.js +1 -0
- package/packages/client/dist/yoloop/invoke-hooks.d.ts +127 -0
- package/packages/client/dist/yoloop/invoke-hooks.js +5 -0
- package/packages/client/dist/yoloop/shared-discover-epics.d.ts +289 -0
- package/packages/client/dist/yoloop/shared-discover-epics.js +1 -0
- package/packages/client/dist/yoloop/shared-yoloop-types.d.ts +172 -0
- package/packages/client/dist/yoloop/shared-yoloop-types.js +1 -0
- package/packages/client/dist/yoloop/yoloop-client-state-store.d.ts +124 -0
- package/packages/client/dist/yoloop/yoloop-client-state-store.js +1 -0
- package/postinstall.js +754 -0
- package/targets-stubs/antigravity/README.md +36 -0
- package/targets-stubs/antigravity/gemini.md +29 -0
- package/targets-stubs/antigravity/install-antigravity.sh +153 -0
- package/targets-stubs/antigravity/mcp-config.json +30 -0
- package/targets-stubs/antigravity/skill/SKILL.md +166 -0
- package/targets-stubs/claude-code/.mcp.json +32 -0
- package/targets-stubs/claude-code/README.md +20 -0
- package/targets-stubs/claude-code/neocortex-root.agent.yaml +42 -0
- package/targets-stubs/claude-code/neocortex-root.md +317 -0
- package/targets-stubs/claude-code/neocortex.agent.yaml +42 -0
- package/targets-stubs/claude-code/neocortex.md +385 -0
- package/targets-stubs/codex/AGENTS.md +250 -0
- package/targets-stubs/codex/README.md +47 -0
- package/targets-stubs/codex/config-mcp.toml +22 -0
- package/targets-stubs/codex/install-codex.sh +63 -0
- package/targets-stubs/codex/neocortex.toml +33 -0
- package/targets-stubs/cursor/README.md +33 -0
- package/targets-stubs/cursor/agent.md +211 -0
- package/targets-stubs/cursor/install-cursor.sh +50 -0
- package/targets-stubs/cursor/mcp.json +30 -0
- package/targets-stubs/gemini-cli/README.md +34 -0
- package/targets-stubs/gemini-cli/agent.md +241 -0
- package/targets-stubs/gemini-cli/agents/neocortex.md +60 -0
- package/targets-stubs/gemini-cli/gemini.md +46 -0
- package/targets-stubs/gemini-cli/install-gemini.sh +70 -0
- package/targets-stubs/gemini-cli/settings-mcp.json +30 -0
- package/targets-stubs/kimi/mcp.json +33 -0
- package/targets-stubs/kimi/neocortex.md +60 -0
- package/targets-stubs/lib/mcp-merge.js +189 -0
- package/targets-stubs/openclaw/README.md +12 -0
- package/targets-stubs/openclaw/SKILL.md +92 -0
- package/targets-stubs/opencode/neocortex-root.md +267 -0
- package/targets-stubs/opencode/neocortex.md +65 -0
- package/targets-stubs/opencode/opencode-mcp.json +35 -0
- package/targets-stubs/vscode/README.md +34 -0
- package/targets-stubs/vscode/copilot-instructions.md +47 -0
- package/targets-stubs/vscode/install-vscode.sh +72 -0
- package/targets-stubs/vscode/mcp.json +36 -0
- package/targets-stubs/vscode/neocortex.agent.md +252 -0
|
@@ -0,0 +1,619 @@
|
|
|
1
|
+
import{Buffer as z}from"node:buffer";import{createHash as M}from"node:crypto";import{chmodSync as X,existsSync as ye,mkdirSync as Ie}from"node:fs";import{join as Z}from"node:path";import{INITIAL_CONTINUITY_SQLITE_MIGRATION as Ee}from"./migrations/001-initial-schema.js";import{PROCESSING_OUTPUT_SUMMARY_SQLITE_MIGRATION as be}from"./migrations/002-processing-output-summary-indexes.js";import{HEADLESS_EXECUTION_ATTEMPTS_SQLITE_MIGRATION as he}from"./migrations/003-headless-execution-attempts.js";import{OUTBOX_DELIVERY_STATE_SQLITE_MIGRATION as pe}from"./migrations/004-outbox-delivery-state.js";import{BOUNDED_HEADLESS_QUEUE_SQLITE_MIGRATION as Ce}from"./migrations/005-bounded-headless-queue.js";import{CONTINUITY_QUEUE_REASON_CODES as U,CONTINUITY_RECEIPT_COMPACTION_EVENT_TYPE as H,CONTINUITY_RECEIPT_RETENTION_REASON_CODES as W,DEFAULT_CONTINUITY_QUEUE_POLICY as fe,computeContinuityQueueRetryAt as Se,computeContinuityOutboxFailureDecision as Ae,normalizeContinuityQueuePolicy as F,normalizeContinuityQueuePriority as ge,normalizeContinuityQueueScope as xe,normalizeContinuityRetentionPolicy as Re}from"./outbox.js";const ee=".neocortex/continuity",Oe="continuity.sqlite",Ct=5,Te=5e3,O="processing_output_summary",Ne=2e3,te=20,Le=100,ae="Install the optional Enterprise continuity SQLite adapter with `npm install --workspace packages/client better-sqlite3 --include=optional` or reinstall Neocortex with optional dependencies enabled.",je=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"]),re=20,ve=new Set(je),Me=/^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}(?::\d{2}(?:\.\d{1,6})?)?(?:Z|[+-]\d{2}:?\d{2})?$/;function se(t){return typeof t=="string"&&ve.has(t)}function oe(t){if(typeof t!="string")return;const e=t.trim();if(!(e.length===0||e.length>40)&&Me.test(e))return e}function Ue(t){if(!Array.isArray(t))return[];const e=[];for(const a of t){if(!h(a)||!se(a.stage))continue;const r=oe(a.at);r&&e.push({stage:a.stage,at:r})}return e.slice(-re)}function De(t){if(!(typeof t!="number"||!Number.isFinite(t)||t<0))return Math.floor(t)}class _ 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 ke=[Ee,be,he,pe,Ce],qe=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"]),de=/(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,ne=/(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,we=new Set(["unsafe_key","raw_log","prompt_body","private_url","local_absolute_path","secret","protected_field","unbounded_text","unbounded_number","unknown_required_operation","missing"]),Pe=/(corrupt|malformed|not a database|file is not a database|database disk image is malformed)/i,He=/(foreign key constraint failed|SQLITE_CONSTRAINT_FOREIGNKEY)/i,V="p185:v1:",We=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"]),Fe=new Set(["foreground_invoke","scheduled_tick","runner_tick","manual_tick","headless_execution","jobs_command","invoke_watch","portal_render"]);function $e(t){return new Function("specifier","return import(specifier)")(t)}function Be(t){return`sha256:${M("sha256").update(t).digest("hex")}`}function h(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function Ye(t){return t instanceof Error?t.message:String(t)}function Ke(t){return h(t)&&typeof t.code=="string"?t.code:void 0}function m(t,e){if(t instanceof _)return t;const a=Ye(t),r=Ke(t);return r==="SQLITE_CORRUPT"||r==="SQLITE_NOTADB"||Pe.test(a)?new _("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"||He.test(a)?new _("sqlite-foreign-key-failed","Continuity SQLite foreign-key validation failed; mutation was rejected.",{cause:t}):new _(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)&&we.has(t))return;if(ne.test(t))throw new _("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(h(t)){for(const[a,r]of Object.entries(t)){if(de.test(a))throw new _("sqlite-public-safety-rejected",`Continuity SQLite metadata rejected unsafe key at ${e}.${a}.`);A(r,`${e}.${a}`)}return}throw new _("sqlite-public-safety-rejected",`Continuity SQLite metadata rejected unsupported value at ${e}.`)}}function b(t,e){if(t!==void 0&&ne.test(t))throw new _("sqlite-public-safety-rejected",`Continuity SQLite text rejected unsafe value at ${e}.`)}function $(t,e,a=240){if(t.trim().length===0)throw new _("sqlite-public-safety-rejected",`Continuity SQLite processing summary text is required at ${e}.`);if(b(t,e),t.length>a)throw new _("sqlite-public-safety-rejected",`Continuity SQLite processing summary text exceeded the public bound at ${e}.`)}function B(t){const e={};if(!t)return e;for(const[a,r]of Object.entries(t))if(We.has(a)&&!de.test(a))try{A(r,`metadata.${a}`),e[a]=r}catch{}return e}function Je(t){const e={...B(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&&Fe.has(t.source)&&(e.processingOutputSource=t.source),B(e)}function ie(t){const e=Math.floor(t??te);return Number.isFinite(e)?Math.max(1,Math.min(Le,e)):te}function Qe(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 Ve(t){return`${V}${z.from(JSON.stringify([t.created_at,t.event_id]),"utf8").toString("base64url")}`}function Ge(t){if(t?.startsWith(V))try{const e=t.slice(V.length),a=JSON.parse(z.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 D(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 ce(t){return t?q(t.map(e=>D("job",e)).filter(e=>!!e)):[]}function ue(t){const e=t.target;if(!e){const r=D("job",t.jobId);return r?{sql:" AND job_id = ?",params:[r]}:{sql:"",params:[]}}const a=e.selectorKind;if(a==="job"){const r=D("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=D("goal",e.goalId??e.targetId);if(!r)return{sql:" AND 1 = 0",params:[]};const s=ce(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=D("loop",e.loopId??e.targetId);if(!r)return{sql:" AND 1 = 0",params:[]};const s=ce(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 le(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:Ve(e)}}function S(t){return t?(A(t,"metadata"),JSON.stringify(t)):null}function ze(t,e,a){const r=i=>`sha256:${M("sha256").update(i.map(n=>[n.id,n.status,n.reasonCode].join(":")).sort().join(`
|
|
2
|
+
`)).digest("hex")}`,s=r(e),d=r(a);return{receipts:s,outputs:d,aggregate:`sha256:${M("sha256").update(`${t}:${s}:${d}`).digest("hex")}`}}function Xe(t){if(!t)return{};try{const e=JSON.parse(t);return h(e)?{...e}:{}}catch{return{}}}function o(t,e,a,r=!1){if(t===void 0){if(r)throw new _("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 _("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 _("sqlite-public-safety-rejected",`Continuity SQLite numeric value rejected at ${e}.`)}function j(t){o(t.outboxId,"outbox.outboxId",160,!0),o(t.jobId,"outbox.jobId",160),o(t.operationId,"outbox.operationId",160),o(t.idempotencyKey,"outbox.idempotencyKey",160),o(t.type,"outbox.type",80),o(t.status,"outbox.status",40),o(t.deliveryCursor,"outbox.deliveryCursor",200),o(t.timestamp,"outbox.timestamp",80),o(t.reasonCode,"outbox.reasonCode",100),o(t.summary,"outbox.summary",240)}function _e(t){return t==="pending"||t==="sent"||t==="acked"||t==="failed"||t==="dead_letter"}function Ze(t){return typeof t=="string"&&_e(t)?t:"failed"}function I(t){return typeof t=="string"&&t.length>0?t:void 0}function et(t){if(typeof t!="string"||t.trim().length===0)return{};try{const e=JSON.parse(t);return h(e)?(A(e,"outbox.payload"),e):{}}catch{return{}}}function tt(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:Ze(t.status),payload:et(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 f(t){return{...t,publicSafe:!0}}function N(t,e){return t===void 0?null:(A(t,e),JSON.stringify(t))}function k(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()){o(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 _("sqlite-public-safety-rejected",`Continuity SQLite rejected non-relative path at relativePaths[${a}].`)}return e}function Y(t){const e={...B(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=k(t.relativePaths)),B(e)}function L(t){o(t.attemptId,"headless_execution.attemptId",160,!0),o(t.executionId,"headless_execution.executionId",160,!0),o(t.jobId,"headless_execution.jobId",160,!0),o(t.directiveHash,"headless_execution.directiveHash",160),o(t.targetRef,"headless_execution.targetRef",240),o(t.storyId,"headless_execution.storyId",120),o(t.epicId,"headless_execution.epicId",120),o(t.runtimeId,"headless_execution.runtimeId",80),o(t.modelId,"headless_execution.modelId",120),o(t.runtimeSource,"headless_execution.runtimeSource",40),o(t.reasonCode,"headless_execution.reasonCode",100),o(t.publicSummary,"headless_execution.publicSummary",240),o(t.leaseId,"headless_execution.leaseId",160),o(t.runnerId,"headless_execution.runnerId",160),o(t.timestamp,"headless_execution.timestamp",80)}function K(t){if(Array.isArray(t)){const e=t[0];return h(e)?Object.values(e)[0]:e}return h(t)?Object.values(t)[0]:t}function at(t){return qe.includes(t)}function q(t){return Array.from(new Set(t))}function rt(t){const e=h(t)&&"default"in t?t.default:t;if(typeof e!="function")throw new _("sqlite-adapter-unavailable","Optional better-sqlite3 adapter did not export a database constructor.",{guidance:ae});const a=e;return{adapterName:"better-sqlite3",open(r,s){return new a(r,s)}}}async function st(t=$e){try{const e=await t("better-sqlite3");return{ok:!0,adapter:rt(e)}}catch(e){return e instanceof _?{ok:!1,error:e}:{ok:!1,error:new _("sqlite-adapter-unavailable","Optional Enterprise continuity SQLite adapter better-sqlite3 is unavailable.",{cause:e,guidance:ae})}}}function ot(t){return Z(t,ee,Oe)}function dt(t){const e=Z(t,ee);Ie(e,{recursive:!0,mode:448});try{X(e,448)}catch{}return e}async function ft(t){const e=t.adapter??await nt(t.adapterLoader);dt(t.projectRoot);const a=ot(t.projectRoot);let r;try{r=e.open(a)}catch(d){throw m(d,"sqlite-integrity-failed")}const s=new it({db:r,filePath:a,adapterName:e.adapterName,busyTimeoutMs:t.busyTimeoutMs??Te,integrityCheck:t.integrityCheck??!0,now:t.now??(()=>new Date().toISOString())});try{if(s.initialize(),ye(a))try{X(a,384)}catch{}return s}catch(d){try{r.close()}catch{}throw d}}async function nt(t){const e=t?await t():await st();if(!e.ok)throw e.error;return e.adapter}class it{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 K(this.db.pragma(e,{simple:!0}))}runIntegrityCheck(){try{if(String(K(this.db.pragma("integrity_check",{simple:!0}))??"").toLowerCase()!=="ok")throw this.mutationBlocked=!0,new _("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 h(e)&&typeof e.version=="number"?e.version:0}countRows(e){if(!at(e))throw new _("sqlite-public-safety-rejected","Unknown continuity table name.");const a=this.db.prepare(`SELECT COUNT(*) AS count FROM ${e}`).get();return h(a)&&typeof a.count=="number"?a.count:0}getLocalConsoleAttachmentState(e){o(e,"local_console.jobId",160,!0);const a=this.db.prepare(`
|
|
3
|
+
SELECT j.job_id AS job_id,
|
|
4
|
+
j.kind AS kind,
|
|
5
|
+
j.status AS status,
|
|
6
|
+
(SELECT COUNT(*) FROM job_leases l WHERE l.job_id = j.job_id AND l.released_at IS NULL) AS active_lease_count,
|
|
7
|
+
(SELECT COUNT(*) FROM headless_execution_attempts h WHERE h.job_id = j.job_id AND h.status = 'running' AND h.lease_released_at IS NULL) AS running_headless_attempt_count
|
|
8
|
+
FROM jobs j
|
|
9
|
+
WHERE j.job_id = ?
|
|
10
|
+
LIMIT 1
|
|
11
|
+
`).get(e);return!h(a)||typeof a.job_id!="string"?null:{jobId:a.job_id,kind:typeof a.kind=="string"?a.kind:"unknown",status:typeof a.status=="string"?a.status:"unknown",activeLeaseCount:typeof a.active_lease_count=="number"?a.active_lease_count:0,runningHeadlessAttemptCount:typeof a.running_headless_attempt_count=="number"?a.running_headless_attempt_count:0,publicSafe:!0}}recordJob(e){this.assertCanMutate(),b(e.summary,"jobs.summary");const a=S(e.metadata);try{const r=this.db.prepare(`
|
|
12
|
+
INSERT OR IGNORE INTO jobs (
|
|
13
|
+
job_id, kind, status, summary, reason_code, created_at, updated_at,
|
|
14
|
+
next_run_at, goal_id, loop_id, campaign_id, operation_id,
|
|
15
|
+
idempotency_key, metadata_json
|
|
16
|
+
) 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,a);return this.toWriteResult(r)}catch(r){throw m(r,"sqlite-mutation-failed")}}appendEvent(e){this.assertCanMutate(),b(e.summary,"job_events.summary");const a=S(e.metadata);try{const r=this.db.prepare(`
|
|
18
|
+
INSERT OR IGNORE INTO job_events (
|
|
19
|
+
event_id, job_id, operation_id, idempotency_key, event_sequence,
|
|
20
|
+
type, summary, reason_code, created_at, metadata_json
|
|
21
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
22
|
+
`).run(e.eventId,e.jobId,e.operationId,e.idempotencyKey??null,e.sequence??null,e.type,e.summary,e.reasonCode??null,e.createdAt,a);return this.toWriteResult(r)}catch(r){throw m(r,"sqlite-mutation-failed")}}recordProcessingOutputSummary(e){$(e.executionId,"processing_output_summary.executionId",160),$(e.jobId,"processing_output_summary.jobId",160),$(e.publicSummary,"processing_output_summary.publicSummary",Ne),$(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 a=this.appendEvent({eventId:Qe(e),jobId:e.jobId,operationId:e.executionId,idempotencyKey:e.idempotencyKey??e.executionId,type:O,summary:e.publicSummary,reasonCode:e.reasonCode,createdAt:e.createdAt,metadata:Je(e)});return a.inserted&&this.recordJobStageProgress({jobId:e.jobId,currentStage:e.metadata?.currentStage,iteration:e.metadata?.iteration,at:e.createdAt}),a}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}),o(e.notBeforeAt,"headless_execution.notBeforeAt",80),o(e.operationId,"headless_execution.operationId",160),o(e.idempotencyKey,"headless_execution.idempotencyKey",160),T(e.retryCount,"headless_execution.retryCount"),T(e.maxAttempts,"headless_execution.maxAttempts"),e.maxAttempts!==void 0&&e.maxAttempts<1)throw new _("sqlite-public-safety-rejected","Continuity SQLite maxAttempts must be greater than zero.");e.metadata&&A(e.metadata,"headless_execution.metadata");const a=F({maxItems:e.queueCap,maxAttempts:e.maxAttempts}),r=ge(e.queuePriority),s=xe(e.queueScope),d=k(e.relativePaths),i=Y({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:a.maxAttempts,queuePriority:r,queueScope:s,counts:e.counts,hashes:e.hashes,redactionSummary:e.redactionSummary,relativePaths:d,metadata:e.metadata});return this.runInTransaction(()=>{const n=this.db.prepare(`
|
|
23
|
+
SELECT value_json
|
|
24
|
+
FROM runner_config
|
|
25
|
+
WHERE key = 'headless_queue_policy'
|
|
26
|
+
LIMIT 1
|
|
27
|
+
`).get();let c=a.maxItems;if(e.queueCap===void 0&&h(n)&&typeof n.value_json=="string")try{const u=JSON.parse(n.value_json);h(u)&&typeof u.maxItems=="number"&&(c=F({maxItems:u.maxItems}).maxItems)}catch{}this.db.prepare(`
|
|
28
|
+
INSERT INTO runner_config (key, value_json, updated_at)
|
|
29
|
+
VALUES ('headless_queue_policy', ?, ?)
|
|
30
|
+
ON CONFLICT(key) DO UPDATE SET
|
|
31
|
+
value_json = excluded.value_json,
|
|
32
|
+
updated_at = excluded.updated_at
|
|
33
|
+
`).run(JSON.stringify({maxItems:c}),e.enqueuedAt);const p=this.db.prepare(`
|
|
34
|
+
SELECT attempt_id
|
|
35
|
+
FROM headless_execution_attempts
|
|
36
|
+
WHERE attempt_id = ?
|
|
37
|
+
OR (? IS NOT NULL AND operation_id = ?)
|
|
38
|
+
OR (? IS NOT NULL AND idempotency_key = ?)
|
|
39
|
+
LIMIT 1
|
|
40
|
+
`).get(e.attemptId,e.operationId??null,e.operationId??null,e.idempotencyKey??null,e.idempotencyKey??null),y=this.db.prepare(`
|
|
41
|
+
SELECT COUNT(*) AS count
|
|
42
|
+
FROM headless_execution_attempts
|
|
43
|
+
WHERE status IN ('queued', 'backoff', 'running')
|
|
44
|
+
AND dead_lettered_at IS NULL
|
|
45
|
+
`).get(),C=h(y)&&typeof y.count=="number"?y.count:0;if(p)return{inserted:!1,replay:!0,changes:0,accepted:!0,backpressure:C>=c,queueDepth:C,queueCap:c,publicSafe:!0};if(C>=c)return{inserted:!1,replay:!1,changes:0,accepted:!1,backpressure:!0,queueDepth:C,queueCap:c,reasonCode:U.CAP_REACHED,publicSafe:!0};const l=this.db.prepare(`
|
|
46
|
+
INSERT INTO headless_execution_attempts (
|
|
47
|
+
attempt_id, execution_id, job_id, directive_hash, directive_kind,
|
|
48
|
+
command_class, target_kind, target_ref, story_id, epic_id, runtime_id,
|
|
49
|
+
model_id, runtime_source, status, reason_code, public_summary,
|
|
50
|
+
enqueued_at, not_before_at, retry_count, max_attempts, operation_id,
|
|
51
|
+
idempotency_key, counts_json, hashes_json, redaction_summary_json,
|
|
52
|
+
relative_paths_json, metadata_json, queue_priority, queue_scope,
|
|
53
|
+
attempt_count, next_retry_at
|
|
54
|
+
) 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,a.maxAttempts,e.operationId??null,e.idempotencyKey??null,N(e.counts,"headless_execution.counts"),N(e.hashes,"headless_execution.hashes"),N(e.redactionSummary,"headless_execution.redactionSummary"),N(d,"headless_execution.relativePaths"),S(i),r,s,e.notBeforeAt??e.enqueuedAt);return{inserted:l.changes>0,replay:!1,changes:l.changes,accepted:l.changes>0,backpressure:C+l.changes>=c,queueDepth:C+l.changes,queueCap:c,publicSafe:!0}})}listDueHeadlessExecutionAttempts(e){const a=Math.max(1,Math.min(50,Math.floor(e.limit)));return o(e.nowIso,"headless_execution.nowIso",80,!0),this.db.prepare(`
|
|
56
|
+
SELECT attempt_id, execution_id, job_id, directive_hash, directive_kind,
|
|
57
|
+
command_class, target_kind, target_ref, story_id, epic_id,
|
|
58
|
+
runtime_id, model_id, runtime_source, status, reason_code,
|
|
59
|
+
public_summary, enqueued_at, not_before_at, started_at,
|
|
60
|
+
heartbeat_at, completed_at, duration_ms, retry_count,
|
|
61
|
+
max_attempts, lease_id, runner_id, lease_expires_at,
|
|
62
|
+
lease_released_at, counts_json, hashes_json,
|
|
63
|
+
redaction_summary_json, relative_paths_json, metadata_json,
|
|
64
|
+
queue_priority, queue_scope, attempt_count, next_retry_at,
|
|
65
|
+
dead_lettered_at, dead_letter_reason_code
|
|
66
|
+
FROM headless_execution_attempts
|
|
67
|
+
WHERE status IN ('queued', 'backoff')
|
|
68
|
+
AND dead_lettered_at IS NULL
|
|
69
|
+
AND (COALESCE(next_retry_at, not_before_at) IS NULL OR COALESCE(next_retry_at, not_before_at) <= ?)
|
|
70
|
+
AND (lease_id IS NULL OR lease_released_at IS NOT NULL OR lease_expires_at <= ?)
|
|
71
|
+
ORDER BY queue_priority DESC, COALESCE(next_retry_at, not_before_at, enqueued_at) ASC,
|
|
72
|
+
enqueued_at ASC, attempt_id ASC
|
|
73
|
+
LIMIT ?
|
|
74
|
+
`).all(e.nowIso,e.nowIso,a)}hasCompletedHeadlessExecutionDirectiveHash(e,a){o(e,"headless_execution.directiveHash",160,!0),o(a,"headless_execution.attemptId",160);const r=a?" AND attempt_id != ?":"",s=a?[e,a]:[e];return this.db.prepare(`
|
|
75
|
+
SELECT 1 AS found
|
|
76
|
+
FROM headless_execution_attempts
|
|
77
|
+
WHERE directive_hash = ?
|
|
78
|
+
AND status = 'completed'${r}
|
|
79
|
+
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}),o(e.leaseExpiresAt,"headless_execution.leaseExpiresAt",80,!0);try{const a=this.db.prepare(`
|
|
81
|
+
UPDATE headless_execution_attempts
|
|
82
|
+
SET status = 'running',
|
|
83
|
+
lease_id = ?,
|
|
84
|
+
runner_id = ?,
|
|
85
|
+
started_at = COALESCE(started_at, ?),
|
|
86
|
+
heartbeat_at = ?,
|
|
87
|
+
lease_expires_at = ?,
|
|
88
|
+
lease_released_at = NULL,
|
|
89
|
+
attempt_count = attempt_count + 1,
|
|
90
|
+
reason_code = COALESCE(?, reason_code)
|
|
91
|
+
WHERE attempt_id = ?
|
|
92
|
+
AND status IN ('queued', 'backoff')
|
|
93
|
+
AND dead_lettered_at IS NULL
|
|
94
|
+
AND (COALESCE(next_retry_at, not_before_at) IS NULL OR COALESCE(next_retry_at, not_before_at) <= ?)
|
|
95
|
+
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(a)}catch(a){throw m(a,"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}),o(e.leaseExpiresAt,"headless_execution.leaseExpiresAt",80,!0),this.runInTransaction(()=>{const a=this.db.prepare(`
|
|
97
|
+
SELECT attempt_id
|
|
98
|
+
FROM headless_execution_attempts
|
|
99
|
+
WHERE status IN ('queued', 'backoff')
|
|
100
|
+
AND dead_lettered_at IS NULL
|
|
101
|
+
AND (? IS NULL OR directive_kind = ?)
|
|
102
|
+
AND (COALESCE(next_retry_at, not_before_at) IS NULL OR COALESCE(next_retry_at, not_before_at) <= ?)
|
|
103
|
+
AND (lease_id IS NULL OR lease_released_at IS NOT NULL OR lease_expires_at <= ?)
|
|
104
|
+
ORDER BY queue_priority DESC,
|
|
105
|
+
COALESCE(next_retry_at, not_before_at, enqueued_at) ASC,
|
|
106
|
+
enqueued_at ASC,
|
|
107
|
+
attempt_id ASC
|
|
108
|
+
LIMIT 1
|
|
109
|
+
`).get(e.directiveKind??null,e.directiveKind??null,e.claimedAt,e.claimedAt);if(typeof a?.attempt_id!="string")return{acquired:!1,reasonCode:"continuity-ok",publicSafe:!0};if(this.db.prepare(`
|
|
110
|
+
UPDATE headless_execution_attempts
|
|
111
|
+
SET status = 'running',
|
|
112
|
+
lease_id = ?,
|
|
113
|
+
runner_id = ?,
|
|
114
|
+
started_at = COALESCE(started_at, ?),
|
|
115
|
+
heartbeat_at = ?,
|
|
116
|
+
lease_expires_at = ?,
|
|
117
|
+
lease_released_at = NULL,
|
|
118
|
+
attempt_count = attempt_count + 1,
|
|
119
|
+
reason_code = COALESCE(?, reason_code)
|
|
120
|
+
WHERE attempt_id = ?
|
|
121
|
+
AND status IN ('queued', 'backoff')
|
|
122
|
+
AND dead_lettered_at IS NULL
|
|
123
|
+
AND (COALESCE(next_retry_at, not_before_at) IS NULL OR COALESCE(next_retry_at, not_before_at) <= ?)
|
|
124
|
+
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,a.attempt_id,e.claimedAt,e.claimedAt).changes===0)return{acquired:!1,reasonCode:"lease-conflict",publicSafe:!0};const s=this.getHeadlessExecutionAttempt(a.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}),o(e.leaseExpiresAt,"headless_execution.leaseExpiresAt",80);try{const a=this.db.prepare(`
|
|
126
|
+
UPDATE headless_execution_attempts
|
|
127
|
+
SET heartbeat_at = ?,
|
|
128
|
+
lease_expires_at = COALESCE(?, lease_expires_at)
|
|
129
|
+
WHERE attempt_id = ?
|
|
130
|
+
AND lease_id = ?
|
|
131
|
+
AND runner_id = ?
|
|
132
|
+
AND status = 'running'
|
|
133
|
+
AND lease_released_at IS NULL
|
|
134
|
+
AND lease_expires_at > ?
|
|
135
|
+
`).run(e.heartbeatAt,e.leaseExpiresAt??null,e.attemptId,e.leaseId,e.runnerId,e.heartbeatAt);return this.toWriteResult(a)}catch(a){throw m(a,"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}),o(e.notBeforeAt,"headless_execution.notBeforeAt",80),T(e.retryCount,"headless_execution.retryCount");try{const a=this.db.prepare(`
|
|
136
|
+
UPDATE headless_execution_attempts
|
|
137
|
+
SET status = COALESCE(?, status),
|
|
138
|
+
reason_code = COALESCE(?, reason_code),
|
|
139
|
+
not_before_at = COALESCE(?, not_before_at),
|
|
140
|
+
retry_count = COALESCE(?, retry_count),
|
|
141
|
+
next_retry_at = CASE
|
|
142
|
+
WHEN ? = 'backoff' THEN COALESCE(?, next_retry_at, not_before_at)
|
|
143
|
+
WHEN ? = 'queued' THEN NULL
|
|
144
|
+
ELSE next_retry_at
|
|
145
|
+
END,
|
|
146
|
+
lease_released_at = ?
|
|
147
|
+
WHERE attempt_id = ?
|
|
148
|
+
AND lease_id = ?
|
|
149
|
+
AND status = 'running'
|
|
150
|
+
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(a)}catch(a){throw m(a,"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}),o(e.notBeforeAt,"headless_execution.notBeforeAt",80),T(e.durationMs,"headless_execution.durationMs"),T(e.retryCount,"headless_execution.retryCount"),e.metadata&&A(e.metadata,"headless_execution.metadata");const a=k(e.relativePaths),r=Y({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:a,metadata:e.metadata}),s=e.leaseId?` AND lease_id = ?
|
|
152
|
+
AND lease_released_at IS NULL${e.runnerId?" AND runner_id = ?":""}`:"",d=e.leaseId?"status = 'running'":"status NOT IN ('completed', 'failed', 'timed_out', 'skipped')",i=[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?N(e.counts,"headless_execution.counts"):null,e.hashes?N(e.hashes,"headless_execution.hashes"):null,e.redactionSummary?N(e.redactionSummary,"headless_execution.redactionSummary"):null,a?N(a,"headless_execution.relativePaths"):null,S(r),e.completedAt,e.attemptId];e.leaseId&&i.push(e.leaseId),e.leaseId&&e.runnerId&&i.push(e.runnerId);try{const n=this.db.prepare(`
|
|
153
|
+
UPDATE headless_execution_attempts
|
|
154
|
+
SET status = ?,
|
|
155
|
+
completed_at = ?,
|
|
156
|
+
duration_ms = COALESCE(?, duration_ms),
|
|
157
|
+
reason_code = COALESCE(?, reason_code),
|
|
158
|
+
public_summary = COALESCE(?, public_summary),
|
|
159
|
+
not_before_at = COALESCE(?, not_before_at),
|
|
160
|
+
retry_count = COALESCE(?, retry_count),
|
|
161
|
+
next_retry_at = CASE
|
|
162
|
+
WHEN ? = 'backoff' THEN COALESCE(?, next_retry_at, not_before_at)
|
|
163
|
+
ELSE NULL
|
|
164
|
+
END,
|
|
165
|
+
counts_json = COALESCE(?, counts_json),
|
|
166
|
+
hashes_json = COALESCE(?, hashes_json),
|
|
167
|
+
redaction_summary_json = COALESCE(?, redaction_summary_json),
|
|
168
|
+
relative_paths_json = COALESCE(?, relative_paths_json),
|
|
169
|
+
metadata_json = COALESCE(?, metadata_json),
|
|
170
|
+
lease_released_at = COALESCE(lease_released_at, ?)
|
|
171
|
+
WHERE attempt_id = ?${s}
|
|
172
|
+
AND ${d}
|
|
173
|
+
`).run(...i);return this.toWriteResult(n)}catch(n){throw m(n,"sqlite-mutation-failed")}}recordHeadlessExecutionReceipt(e){L({attemptId:e.attemptId,executionId:e.executionId,jobId:e.jobId,reasonCode:e.reasonCode,timestamp:e.createdAt}),e.metadata&&A(e.metadata,"headless_execution.metadata");const a=k(e.relativePaths),r=Y({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:a,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}),T(e.durationMs,"headless_execution.durationMs"),e.metadata&&A(e.metadata,"headless_execution.metadata");const a=k(e.relativePaths),r=Y({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:a,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 a=S(e.metadata);try{const r=this.db.prepare(`
|
|
174
|
+
INSERT OR IGNORE INTO job_receipts (
|
|
175
|
+
receipt_id, job_id, operation_id, idempotency_key, status, reason_code,
|
|
176
|
+
applied_operation_ids_json, ignored_operation_ids_json, created_at, metadata_json
|
|
177
|
+
) 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,a);return this.toWriteResult(r)}catch(r){throw m(r,"sqlite-mutation-failed")}}compactPublicReceiptsAndOutputs(e){this.assertCanMutate();const a=Date.parse(e.nowIso);if(!Number.isFinite(a))throw new _("sqlite-public-safety-rejected","Continuity receipt compaction requires a valid public timestamp.");const r=Re(e.policy),s=new Date(a-r.receipts.maxAgeMs).toISOString(),d=new Date(a-r.processingOutputs.maxAgeMs).toISOString();try{return this.runInTransaction(()=>{const i=this.selectReceiptRetentionCandidates({cutoff:s,maxItems:r.receipts.maxItems,maxBytes:r.receipts.maxBytes,limit:r.maxDeleteRowsPerRun}),n=this.selectOutputRetentionCandidates({cutoff:d,maxItems:r.processingOutputs.maxItems,maxBytes:r.processingOutputs.maxBytes,limit:r.maxDeleteRowsPerRun}),c=[...i,...n].sort((u,E)=>u.createdAt.localeCompare(E.createdAt)||u.id.localeCompare(E.id)).slice(0,r.maxDeleteRowsPerRun);if(c.length===0)return{status:"noop",summaries:[],counts:{receiptsRemoved:0,outputsRemoved:0,bytesRemoved:0,summariesCreated:0},reasonCode:W.NOOP,publicSafe:!0};const p=c.filter(u=>u.kind==="receipt"),y=c.filter(u=>u.kind==="output");for(const u of q(p.map(E=>E.jobId)))this.preserveReceiptDerivedIteration(u,e.nowIso);this.deleteRetentionCandidates("job_receipts","receipt_id",p.map(u=>u.id)),this.deleteRetentionCandidates("job_events","event_id",y.map(u=>u.id));const C=new Map;for(const u of c)C.set(u.jobId,[...C.get(u.jobId)??[],u]);const l=[];for(const[u,E]of[...C.entries()].sort(([x],[g])=>x.localeCompare(g))){const x=E.filter(v=>v.kind==="receipt"),g=E.filter(v=>v.kind==="output"),J=this.retainedReceiptOutputCounts(u),Q=ze(u,x,g),R={receiptsRemoved:x.length,receiptsRetained:J.receipts,outputsRemoved:g.length,outputsRetained:J.outputs,bytesRemoved:E.reduce((v,me)=>v+me.approxBytes,0),bytesRetained:J.bytes,redactions:0},w=`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}.`;o(w,"receipt_compaction.publicSummary",500,!0);const P=`receipt-compaction-${M("sha256").update(`${u}:${e.nowIso}:${Q.aggregate}`).digest("hex").slice(0,32)}`,G={schemaVersion:1,contractVersion:"continuity-v1",policyVersion:1,type:H,summaryId:P,jobId:u,scope:"local_sqlite",status:"compacted",createdAt:e.nowIso,reasonCodes:[W.COMPACTED],counts:R,hashes:Q,publicSummary:w,publicSafe:!0};this.appendEvent({eventId:P,jobId:u,operationId:`op-${P}`,idempotencyKey:`idem-${P}`,type:H,summary:w,reasonCode:W.COMPACTED,createdAt:e.nowIso,metadata:{schemaVersion:1,contractVersion:"continuity-v1",eventType:H,jobId:u,reasonCodes:G.reasonCodes,counts:R,hashes:Q,publicSummary:w}}),this.pruneReceiptCompactionSummaries(u,r.maxCompactionSummariesPerJob),l.push(G)}return{status:"compacted",summaries:l,counts:{receiptsRemoved:p.length,outputsRemoved:y.length,bytesRemoved:c.reduce((u,E)=>u+E.approxBytes,0),summariesCreated:l.length},reasonCode:W.COMPACTED,publicSafe:!0}})}catch(i){throw m(i,"sqlite-mutation-failed")}}updateJobStatus(e){this.assertCanMutate();try{const a=this.db.prepare(`
|
|
179
|
+
UPDATE jobs
|
|
180
|
+
SET status = ?,
|
|
181
|
+
reason_code = COALESCE(?, reason_code),
|
|
182
|
+
updated_at = ?,
|
|
183
|
+
next_run_at = COALESCE(?, next_run_at)
|
|
184
|
+
WHERE job_id = ?
|
|
185
|
+
`).run(e.status,e.reasonCode??null,e.updatedAt,e.nextRunAt??null,e.jobId);if(a.changes===0)throw new _("sqlite-foreign-key-failed",`Continuity SQLite job ${e.jobId} was not found for status update.`);return this.toWriteResult(a)}catch(a){throw m(a,"sqlite-mutation-failed")}}recordJobStageProgress(e){this.assertCanMutate(),o(e.jobId,"job_stage.jobId",160,!0);const a=se(e.currentStage)?e.currentStage:void 0,r=De(e.iteration);if(!a&&r===void 0)return{inserted:!1,replay:!1,changes:0};const s=oe(e.at);try{const d=this.db.prepare("SELECT metadata_json FROM jobs WHERE job_id = ?").get(e.jobId);if(!d)return{inserted:!1,replay:!1,changes:0};const i=Xe(typeof d.metadata_json=="string"?d.metadata_json:null);if(a&&(i.currentStage=a),r!==void 0&&(i.iteration=r),a&&s&&e.appendHistory!==!1){const c=Ue(i.stageHistory);c.push({stage:a,at:s}),i.stageHistory=c.slice(-re)}const n=this.db.prepare("UPDATE jobs SET metadata_json = ? WHERE job_id = ?").run(S(i),e.jobId);return this.toWriteResult(n)}catch(d){throw m(d,"sqlite-mutation-failed")}}updateJobAndExistingGoalCampaignStatus(e){return this.runInTransaction(()=>{const a=this.db.prepare(`
|
|
186
|
+
UPDATE jobs
|
|
187
|
+
SET status = ?,
|
|
188
|
+
reason_code = COALESCE(?, reason_code),
|
|
189
|
+
updated_at = ?,
|
|
190
|
+
next_run_at = COALESCE(?, next_run_at)
|
|
191
|
+
WHERE job_id = ?
|
|
192
|
+
`).run(e.status,e.reasonCode??null,e.updatedAt,e.nextRunAt??null,e.jobId);if(a.changes===0)throw new _("sqlite-foreign-key-failed",`Continuity SQLite job ${e.jobId} was not found for status parity update.`);const r=this.db.prepare(`
|
|
193
|
+
UPDATE goal_campaigns
|
|
194
|
+
SET status = ?,
|
|
195
|
+
reason_code = COALESCE(?, reason_code),
|
|
196
|
+
updated_at = ?
|
|
197
|
+
WHERE job_id = ?
|
|
198
|
+
`).run(e.status,e.reasonCode??null,e.updatedAt,e.jobId);return this.toWriteResult({changes:a.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 a=S(e.metadata);try{const r=this.db.prepare(`
|
|
199
|
+
INSERT OR IGNORE INTO job_leases (
|
|
200
|
+
lease_id, job_id, runner_id, status, acquired_at, expires_at,
|
|
201
|
+
operation_id, idempotency_key, metadata_json
|
|
202
|
+
) VALUES (?, ?, ?, 'acquired', ?, ?, ?, ?, ?)
|
|
203
|
+
`).run(e.leaseId,e.jobId,e.runnerId,e.acquiredAt,e.expiresAt,e.operationId??null,e.idempotencyKey??null,a);return this.toWriteResult(r)}catch(r){throw m(r,"sqlite-mutation-failed")}}releaseLease(e){this.assertCanMutate();try{const a=this.db.prepare(`
|
|
204
|
+
UPDATE job_leases
|
|
205
|
+
SET status = 'released', released_at = ?
|
|
206
|
+
WHERE lease_id = ? AND released_at IS NULL
|
|
207
|
+
`).run(e.releasedAt,e.leaseId);if(a.changes===0)throw new _("sqlite-foreign-key-failed",`Continuity SQLite lease ${e.leaseId} was not found for release.`);return this.toWriteResult(a)}catch(a){throw m(a,"sqlite-mutation-failed")}}recordStateSnapshot(e){this.assertCanMutate(),b(e.summary,"state_snapshots.summary"),b(e.relativePath,"state_snapshots.relative_path");const a=S(e.metadata);try{const r=this.db.prepare(`
|
|
208
|
+
INSERT OR IGNORE INTO state_snapshots (
|
|
209
|
+
snapshot_id, job_id, kind, relative_path, sha256, summary, captured_at,
|
|
210
|
+
operation_id, idempotency_key, metadata_json
|
|
211
|
+
) 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,a);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 a=S(e.metadata);try{const r=this.db.prepare(`
|
|
213
|
+
INSERT OR IGNORE INTO artifacts (
|
|
214
|
+
artifact_id, job_id, kind, relative_path, sha256, summary,
|
|
215
|
+
operation_id, idempotency_key, created_at, metadata_json
|
|
216
|
+
) 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,a);return this.toWriteResult(r)}catch(r){throw m(r,"sqlite-mutation-failed")}}enqueueOutbox(e){this.assertCanMutate(),j({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}),j({outboxId:e.outboxId,timestamp:e.updatedAt}),o(e.nextAttemptAt,"outbox.nextAttemptAt",80),o(e.lastAttemptAt,"outbox.lastAttemptAt",80),o(e.sentAt,"outbox.sentAt",80),o(e.ackedAt,"outbox.ackedAt",80),o(e.deadLetteredAt,"outbox.deadLetteredAt",80),T(e.retryCount,"outbox.retryCount"),T(e.attemptCount,"outbox.attemptCount");const a=S(e.payload);try{const r=this.db.prepare(`
|
|
218
|
+
INSERT OR IGNORE INTO outbox (
|
|
219
|
+
outbox_id, job_id, operation_id, idempotency_key, type, status,
|
|
220
|
+
payload_json, retry_count, attempt_count, delivery_cursor,
|
|
221
|
+
next_attempt_at, last_attempt_at, sent_at, acked_at, last_error_code,
|
|
222
|
+
last_error_reason, last_error_summary, dead_letter_summary,
|
|
223
|
+
dead_lettered_at, created_at, updated_at
|
|
224
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
225
|
+
`).run(e.outboxId,e.jobId??null,e.operationId,e.idempotencyKey??null,e.type,e.status??"pending",a??"{}",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){j({outboxId:"outbox-query",timestamp:e.nowIso});const a=Math.max(1,Math.min(100,Math.floor(e.limit))),r=q(e.statuses?.length?e.statuses:["pending","failed"]);for(const i of r)if(!_e(i))throw new _("sqlite-public-safety-rejected","Continuity SQLite outbox batch query rejected an unknown status.");const s=r.map(()=>"?").join(", ");return this.db.prepare(`
|
|
226
|
+
SELECT outbox_id, job_id, operation_id, idempotency_key, type, status,
|
|
227
|
+
payload_json, retry_count, attempt_count, delivery_cursor,
|
|
228
|
+
next_attempt_at, last_attempt_at, sent_at, acked_at, last_error_code,
|
|
229
|
+
last_error_reason, last_error_summary, dead_letter_summary,
|
|
230
|
+
dead_lettered_at, created_at, updated_at
|
|
231
|
+
FROM outbox
|
|
232
|
+
WHERE status IN (${s})
|
|
233
|
+
AND (status NOT IN ('pending', 'failed') OR next_attempt_at IS NULL OR next_attempt_at <= ?)
|
|
234
|
+
ORDER BY COALESCE(next_attempt_at, created_at) ASC, created_at ASC, outbox_id ASC
|
|
235
|
+
LIMIT ?
|
|
236
|
+
`).all(...r,e.nowIso,a).map(tt)}markOutboxSent(e){this.assertCanMutate(),j({outboxId:e.outboxId,deliveryCursor:e.deliveryCursor,timestamp:e.sentAt,reasonCode:e.reasonCode});try{return this.runInTransaction(()=>{const a=this.getOutboxTransitionRow(e.outboxId);if(!a)return f({outboxId:e.outboxId,status:"missing",changes:0,replay:!1,reasonCode:"outbox-missing"});if((a.status==="sent"||a.status==="acked")&&a.delivery_cursor===e.deliveryCursor)return f({outboxId:e.outboxId,status:a.status,changes:0,replay:!0,deliveryCursor:e.deliveryCursor,reasonCode:e.reasonCode??"outbox-delivery-replay"});if(a.status==="sent"||a.status==="acked"||a.status==="dead_letter")return f({outboxId:e.outboxId,status:"conflict",changes:0,replay:!1,deliveryCursor:a.delivery_cursor??void 0,reasonCode:"outbox-delivery-conflict"});const r=this.db.prepare(`
|
|
237
|
+
UPDATE outbox
|
|
238
|
+
SET status = 'sent',
|
|
239
|
+
delivery_cursor = ?,
|
|
240
|
+
attempt_count = attempt_count + 1,
|
|
241
|
+
next_attempt_at = NULL,
|
|
242
|
+
last_attempt_at = ?,
|
|
243
|
+
sent_at = ?,
|
|
244
|
+
updated_at = ?
|
|
245
|
+
WHERE outbox_id = ?
|
|
246
|
+
AND status IN ('pending', 'failed')
|
|
247
|
+
`).run(e.deliveryCursor,e.sentAt,e.sentAt,e.sentAt,e.outboxId);return f({outboxId:e.outboxId,status:"sent",changes:r.changes,replay:!1,deliveryCursor:e.deliveryCursor,reasonCode:e.reasonCode??"outbox-sent"})})}catch(a){throw m(a,"sqlite-mutation-failed")}}ackOutbox(e){this.assertCanMutate(),j({outboxId:e.outboxId,deliveryCursor:e.deliveryCursor,timestamp:e.ackedAt,reasonCode:e.reasonCode});try{return this.runInTransaction(()=>{const a=this.getOutboxTransitionRow(e.outboxId);if(!a)return f({outboxId:e.outboxId,status:"missing",changes:0,replay:!1,reasonCode:"outbox-missing"});if(a.status==="acked"&&(!e.deliveryCursor||a.delivery_cursor===e.deliveryCursor))return f({outboxId:e.outboxId,status:"acked",changes:0,replay:!0,deliveryCursor:a.delivery_cursor??void 0,reasonCode:e.reasonCode??"outbox-ack-replay"});if(a.status!=="sent"||e.deliveryCursor&&a.delivery_cursor!==e.deliveryCursor)return f({outboxId:e.outboxId,status:"conflict",changes:0,replay:!1,deliveryCursor:a.delivery_cursor??void 0,reasonCode:"outbox-ack-conflict"});const r=this.db.prepare(`
|
|
248
|
+
UPDATE outbox
|
|
249
|
+
SET status = 'acked',
|
|
250
|
+
acked_at = ?,
|
|
251
|
+
updated_at = ?,
|
|
252
|
+
next_attempt_at = NULL,
|
|
253
|
+
last_error_code = NULL,
|
|
254
|
+
last_error_reason = NULL
|
|
255
|
+
WHERE outbox_id = ?
|
|
256
|
+
AND status = 'sent'
|
|
257
|
+
`).run(e.ackedAt,e.ackedAt,e.outboxId);return f({outboxId:e.outboxId,status:"acked",changes:r.changes,replay:!1,deliveryCursor:a.delivery_cursor??void 0,reasonCode:e.reasonCode??"outbox-acked"})})}catch(a){throw m(a,"sqlite-mutation-failed")}}failOutboxDelivery(e){this.assertCanMutate(),j({outboxId:e.outboxId,deliveryCursor:e.deliveryCursor,timestamp:e.failedAt,reasonCode:e.reasonCode,summary:e.summary}),o(e.nextRetryAt,"outbox.nextRetryAt",80);try{return this.runInTransaction(()=>{const a=this.getOutboxTransitionRow(e.outboxId);if(!a)return f({outboxId:e.outboxId,status:"missing",changes:0,replay:!1,reasonCode:"outbox-missing"});if(a.status==="acked")return f({outboxId:e.outboxId,status:"acked",changes:0,replay:!0,deliveryCursor:a.delivery_cursor??void 0,reasonCode:"outbox-already-acked"});if(a.status==="dead_letter")return f({outboxId:e.outboxId,status:"dead_letter",changes:0,replay:!0,deliveryCursor:a.delivery_cursor??void 0,deadLetteredAt:a.dead_lettered_at??void 0,reasonCode:a.last_error_reason??a.last_error_code??e.reasonCode});if(e.deliveryCursor&&a.delivery_cursor&&a.delivery_cursor!==e.deliveryCursor)return f({outboxId:e.outboxId,status:"conflict",changes:0,replay:!1,deliveryCursor:a.delivery_cursor,reasonCode:"outbox-fail-conflict"});const r=Math.max(1,a.attempt_count??0,a.retry_count??0),s=Ae({nowIso:e.failedAt,attemptCount:r,reasonCode:e.reasonCode,summary:e.summary,nextRetryAt:e.nextRetryAt,policy:e.policy}),d=this.db.prepare(`
|
|
258
|
+
UPDATE outbox
|
|
259
|
+
SET status = ?,
|
|
260
|
+
retry_count = MAX(retry_count, ?),
|
|
261
|
+
next_attempt_at = ?,
|
|
262
|
+
last_error_code = ?,
|
|
263
|
+
last_error_reason = ?,
|
|
264
|
+
last_error_summary = ?,
|
|
265
|
+
dead_letter_summary = ?,
|
|
266
|
+
dead_lettered_at = ?,
|
|
267
|
+
updated_at = ?
|
|
268
|
+
WHERE outbox_id = ?
|
|
269
|
+
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 f({outboxId:e.outboxId,status:s.status,changes:d.changes,replay:!1,deliveryCursor:a.delivery_cursor??e.deliveryCursor,reasonCode:s.reasonCode,...s.nextRetryAt?{nextRetryAt:s.nextRetryAt}:{},...s.deadLetteredAt?{deadLetteredAt:s.deadLetteredAt}:{}})})}catch(a){throw m(a,"sqlite-mutation-failed")}}deadLetterOutbox(e){this.assertCanMutate(),j({outboxId:e.outboxId,timestamp:e.deadLetteredAt,reasonCode:e.reasonCode,summary:e.summary});try{return this.runInTransaction(()=>{const a=this.getOutboxTransitionRow(e.outboxId);if(!a)return f({outboxId:e.outboxId,status:"missing",changes:0,replay:!1,reasonCode:"outbox-missing"});if(a.status==="dead_letter")return f({outboxId:e.outboxId,status:"dead_letter",changes:0,replay:!0,deliveryCursor:a.delivery_cursor??void 0,deadLetteredAt:a.dead_lettered_at??void 0,reasonCode:a.last_error_reason??a.last_error_code??e.reasonCode});const r=this.db.prepare(`
|
|
271
|
+
UPDATE outbox
|
|
272
|
+
SET status = 'dead_letter',
|
|
273
|
+
next_attempt_at = NULL,
|
|
274
|
+
last_error_code = ?,
|
|
275
|
+
last_error_reason = ?,
|
|
276
|
+
last_error_summary = ?,
|
|
277
|
+
dead_letter_summary = ?,
|
|
278
|
+
dead_lettered_at = ?,
|
|
279
|
+
updated_at = ?
|
|
280
|
+
WHERE outbox_id = ?
|
|
281
|
+
AND status <> 'acked'
|
|
282
|
+
`).run(e.reasonCode,e.reasonCode,e.summary,e.summary,e.deadLetteredAt,e.deadLetteredAt,e.outboxId);return f({outboxId:e.outboxId,status:"dead_letter",changes:r.changes,replay:!1,deliveryCursor:a.delivery_cursor??void 0,deadLetteredAt:e.deadLetteredAt,reasonCode:e.reasonCode})})}catch(a){throw m(a,"sqlite-mutation-failed")}}retryOutboxEntries(e){this.assertCanMutate();const a=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 d=r.map(()=>"?").join(", "),n=this.db.prepare(`
|
|
283
|
+
SELECT outbox_id
|
|
284
|
+
FROM outbox
|
|
285
|
+
WHERE status IN (${d})
|
|
286
|
+
ORDER BY updated_at ASC, outbox_id ASC
|
|
287
|
+
LIMIT ?
|
|
288
|
+
`).all(...r,a).map(y=>y.outbox_id).filter(y=>typeof y=="string"&&y.length>0);if(n.length===0)return{retriedOutboxIds:[],changes:0,reasonCode:s,publicSafe:!0};const c=n.map(()=>"?").join(", "),p=this.db.prepare(`
|
|
289
|
+
UPDATE outbox
|
|
290
|
+
SET status = 'pending',
|
|
291
|
+
retry_count = retry_count + 1,
|
|
292
|
+
next_attempt_at = ?,
|
|
293
|
+
last_error_code = ?,
|
|
294
|
+
last_error_reason = ?,
|
|
295
|
+
delivery_cursor = NULL,
|
|
296
|
+
sent_at = NULL,
|
|
297
|
+
acked_at = NULL,
|
|
298
|
+
dead_letter_summary = NULL,
|
|
299
|
+
dead_lettered_at = NULL,
|
|
300
|
+
updated_at = ?
|
|
301
|
+
WHERE outbox_id IN (${c})
|
|
302
|
+
`).run(e.nextAttemptAt??e.nowIso,s,s,e.nowIso,...n);return{retriedOutboxIds:n,changes:p.changes,reasonCode:s,publicSafe:!0}})}catch(d){throw m(d,"sqlite-mutation-failed")}}upsertGoalCampaign(e){this.assertCanMutate(),b(e.title,"goal_campaigns.title"),b(e.publicSummary,"goal_campaigns.public_summary");const a=S(e.metadata);try{const r=this.db.prepare(`
|
|
303
|
+
INSERT INTO goal_campaigns (
|
|
304
|
+
campaign_id, job_id, status, title, public_summary, reason_code,
|
|
305
|
+
created_at, updated_at, operation_id, idempotency_key, metadata_json
|
|
306
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
307
|
+
ON CONFLICT(campaign_id) DO UPDATE SET
|
|
308
|
+
status = excluded.status,
|
|
309
|
+
title = COALESCE(excluded.title, goal_campaigns.title),
|
|
310
|
+
public_summary = COALESCE(excluded.public_summary, goal_campaigns.public_summary),
|
|
311
|
+
reason_code = excluded.reason_code,
|
|
312
|
+
updated_at = excluded.updated_at,
|
|
313
|
+
operation_id = excluded.operation_id,
|
|
314
|
+
idempotency_key = excluded.idempotency_key,
|
|
315
|
+
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,a);return this.toWriteResult(r)}catch(r){throw m(r,"sqlite-mutation-failed")}}upsertGoalLedgerItem(e){this.assertCanMutate(),b(e.summary,"goal_ledger_items.summary");const a=S(e.metadata);try{this.ensureGoalCampaign(e.campaignId,e.jobId,e.createdAt,e.updatedAt);const r=this.db.prepare(`
|
|
317
|
+
INSERT INTO goal_ledger_items (
|
|
318
|
+
item_id, campaign_id, operation_id, idempotency_key, item_type, status,
|
|
319
|
+
summary, reason_code, created_at, updated_at, metadata_json
|
|
320
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
321
|
+
ON CONFLICT(item_id) DO UPDATE SET
|
|
322
|
+
status = excluded.status,
|
|
323
|
+
summary = excluded.summary,
|
|
324
|
+
reason_code = excluded.reason_code,
|
|
325
|
+
updated_at = excluded.updated_at,
|
|
326
|
+
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,a);return this.toWriteResult(r)}catch(r){throw m(r,"sqlite-mutation-failed")}}upsertGoalVerifier(e){this.assertCanMutate(),b(e.summary,"goal_verifiers.summary");const a=S(e.metadata);try{const r=e.lastCheckedAt??this.now();this.ensureGoalCampaign(e.campaignId,e.jobId,r,r);const s=this.db.prepare(`
|
|
328
|
+
INSERT INTO goal_verifiers (
|
|
329
|
+
verifier_id, campaign_id, kind, status, summary, reason_code,
|
|
330
|
+
last_checked_at, operation_id, idempotency_key, metadata_json
|
|
331
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
332
|
+
ON CONFLICT(verifier_id) DO UPDATE SET
|
|
333
|
+
status = excluded.status,
|
|
334
|
+
summary = excluded.summary,
|
|
335
|
+
reason_code = excluded.reason_code,
|
|
336
|
+
last_checked_at = excluded.last_checked_at,
|
|
337
|
+
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,a);return this.toWriteResult(s)}catch(r){throw m(r,"sqlite-mutation-failed")}}upsertGoalReviewGate(e){this.assertCanMutate(),b(e.summary,"goal_review_gates.summary");const a=S(e.metadata);try{const r=this.now();this.ensureGoalCampaign(e.campaignId,e.jobId,r,r);const s=this.db.prepare(`
|
|
339
|
+
INSERT INTO goal_review_gates (
|
|
340
|
+
gate_id, campaign_id, status, summary, required, reason_code,
|
|
341
|
+
operation_id, idempotency_key, metadata_json
|
|
342
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
343
|
+
ON CONFLICT(gate_id) DO UPDATE SET
|
|
344
|
+
status = excluded.status,
|
|
345
|
+
summary = excluded.summary,
|
|
346
|
+
required = excluded.required,
|
|
347
|
+
reason_code = excluded.reason_code,
|
|
348
|
+
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,a);return this.toWriteResult(s)}catch(r){throw m(r,"sqlite-mutation-failed")}}recordOperationAudit(e){return this.appendReceipt(e)}hasOperationRef(e,a){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(n=>`SELECT 1 AS found FROM ${n} WHERE operation_id = ?${a?" OR idempotency_key = ?":""}`),d=r.flatMap(()=>a?[e,a]:[e]);return!!this.db.prepare(`${s.join(" UNION ALL ")} LIMIT 1`).get(...d)}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
|
+
SELECT attempt_id, execution_id, job_id, directive_hash, directive_kind,
|
|
351
|
+
command_class, target_kind, target_ref, story_id, epic_id,
|
|
352
|
+
runtime_id, model_id, runtime_source, status, reason_code,
|
|
353
|
+
public_summary, enqueued_at, not_before_at, started_at,
|
|
354
|
+
heartbeat_at, completed_at, duration_ms, retry_count,
|
|
355
|
+
max_attempts, lease_id, runner_id, lease_expires_at,
|
|
356
|
+
lease_released_at, counts_json, hashes_json,
|
|
357
|
+
redaction_summary_json, relative_paths_json, metadata_json,
|
|
358
|
+
queue_priority, queue_scope, attempt_count, next_retry_at,
|
|
359
|
+
dead_lettered_at, dead_letter_reason_code
|
|
360
|
+
FROM headless_execution_attempts
|
|
361
|
+
WHERE attempt_id = ?
|
|
362
|
+
LIMIT 1
|
|
363
|
+
`).get(e)}getOutboxTransitionRow(e){const a=this.db.prepare(`
|
|
364
|
+
SELECT outbox_id, status, delivery_cursor, retry_count, attempt_count,
|
|
365
|
+
last_error_code, last_error_reason, dead_lettered_at
|
|
366
|
+
FROM outbox
|
|
367
|
+
WHERE outbox_id = ?
|
|
368
|
+
LIMIT 1
|
|
369
|
+
`).get(e);if(!(!a||!h(a)))return a}selectReceiptRetentionCandidates(e){return this.db.prepare(`
|
|
370
|
+
WITH sized AS (
|
|
371
|
+
SELECT receipt_id, job_id, status, reason_code, created_at,
|
|
372
|
+
length(receipt_id) + length(job_id) + length(status) + length(created_at)
|
|
373
|
+
+ COALESCE(length(operation_id), 0) + COALESCE(length(idempotency_key), 0)
|
|
374
|
+
+ COALESCE(length(reason_code), 0) + COALESCE(length(applied_operation_ids_json), 0)
|
|
375
|
+
+ COALESCE(length(ignored_operation_ids_json), 0) + COALESCE(length(metadata_json), 0) AS approx_bytes
|
|
376
|
+
FROM job_receipts
|
|
377
|
+
), ranked AS (
|
|
378
|
+
SELECT *,
|
|
379
|
+
ROW_NUMBER() OVER (ORDER BY created_at DESC, receipt_id DESC) AS retain_rank,
|
|
380
|
+
SUM(approx_bytes) OVER (ORDER BY created_at DESC, receipt_id DESC ROWS UNBOUNDED PRECEDING) AS cumulative_bytes
|
|
381
|
+
FROM sized
|
|
382
|
+
)
|
|
383
|
+
SELECT receipt_id, job_id, status, reason_code, created_at, approx_bytes
|
|
384
|
+
FROM ranked
|
|
385
|
+
WHERE created_at < ? OR retain_rank > ? OR cumulative_bytes > ?
|
|
386
|
+
ORDER BY created_at ASC, receipt_id ASC
|
|
387
|
+
LIMIT ?
|
|
388
|
+
`).all(e.cutoff,e.maxItems,e.maxBytes,e.limit).flatMap(r=>typeof r.receipt_id!="string"||typeof r.job_id!="string"?[]:[{kind:"receipt",id:r.receipt_id,jobId:r.job_id,status:typeof r.status=="string"?r.status:"unknown",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}])}selectOutputRetentionCandidates(e){return this.db.prepare(`
|
|
389
|
+
WITH sized AS (
|
|
390
|
+
SELECT event_id, job_id, type, reason_code, created_at,
|
|
391
|
+
length(event_id) + length(job_id) + length(operation_id) + length(type)
|
|
392
|
+
+ length(summary) + length(created_at) + COALESCE(length(idempotency_key), 0)
|
|
393
|
+
+ COALESCE(length(reason_code), 0) + COALESCE(length(metadata_json), 0) AS approx_bytes
|
|
394
|
+
FROM job_events
|
|
395
|
+
WHERE type = ?
|
|
396
|
+
), ranked AS (
|
|
397
|
+
SELECT *,
|
|
398
|
+
ROW_NUMBER() OVER (ORDER BY created_at DESC, event_id DESC) AS retain_rank,
|
|
399
|
+
SUM(approx_bytes) OVER (ORDER BY created_at DESC, event_id DESC ROWS UNBOUNDED PRECEDING) AS cumulative_bytes
|
|
400
|
+
FROM sized
|
|
401
|
+
)
|
|
402
|
+
SELECT event_id, job_id, type, reason_code, created_at, approx_bytes
|
|
403
|
+
FROM ranked
|
|
404
|
+
WHERE created_at < ? OR retain_rank > ? OR cumulative_bytes > ?
|
|
405
|
+
ORDER BY created_at ASC, event_id ASC
|
|
406
|
+
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,a,r){if(r.length===0)return;const s=r.map(()=>"?").join(", ");this.db.prepare(`DELETE FROM ${e} WHERE ${a} IN (${s})`).run(...r)}preserveReceiptDerivedIteration(e,a){const r=this.db.prepare(`
|
|
408
|
+
SELECT COUNT(*) AS iteration
|
|
409
|
+
FROM job_receipts
|
|
410
|
+
WHERE job_id = ?
|
|
411
|
+
AND (operation_id LIKE 'tick-%' OR operation_id LIKE 'loop-tick-%')
|
|
412
|
+
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:a,appendHistory:!1})}retainedReceiptOutputCounts(e){const a=this.db.prepare(`
|
|
414
|
+
SELECT COUNT(*) AS count,
|
|
415
|
+
COALESCE(SUM(length(receipt_id) + length(job_id) + length(status) + length(created_at)
|
|
416
|
+
+ COALESCE(length(operation_id), 0) + COALESCE(length(idempotency_key), 0)
|
|
417
|
+
+ COALESCE(length(reason_code), 0) + COALESCE(length(applied_operation_ids_json), 0)
|
|
418
|
+
+ COALESCE(length(ignored_operation_ids_json), 0) + COALESCE(length(metadata_json), 0)), 0) AS bytes
|
|
419
|
+
FROM job_receipts
|
|
420
|
+
WHERE job_id = ?
|
|
421
|
+
`).get(e),r=this.db.prepare(`
|
|
422
|
+
SELECT COUNT(*) AS count,
|
|
423
|
+
COALESCE(SUM(length(event_id) + length(job_id) + length(operation_id) + length(type)
|
|
424
|
+
+ length(summary) + length(created_at) + COALESCE(length(idempotency_key), 0)
|
|
425
|
+
+ COALESCE(length(reason_code), 0) + COALESCE(length(metadata_json), 0)), 0) AS bytes
|
|
426
|
+
FROM job_events
|
|
427
|
+
WHERE job_id = ? AND type = ?
|
|
428
|
+
`).get(e,O);return{receipts:typeof a?.count=="number"?a.count:0,outputs:typeof r?.count=="number"?r.count:0,bytes:(typeof a?.bytes=="number"?a.bytes:0)+(typeof r?.bytes=="number"?r.bytes:0)}}pruneReceiptCompactionSummaries(e,a){this.db.prepare(`
|
|
429
|
+
DELETE FROM job_events
|
|
430
|
+
WHERE event_id IN (
|
|
431
|
+
SELECT event_id
|
|
432
|
+
FROM job_events
|
|
433
|
+
WHERE job_id = ? AND type = ?
|
|
434
|
+
ORDER BY created_at DESC, event_id DESC
|
|
435
|
+
LIMIT -1 OFFSET ?
|
|
436
|
+
)
|
|
437
|
+
`).run(e,H,a)}runInTransaction(e){this.assertCanMutate();const a=this.db.transaction(e);try{return typeof a.immediate=="function"?a.immediate():a()}catch(r){throw m(r,"sqlite-mutation-failed")}}collectSnapshotRows(e){const a=(E,...x)=>{const g=this.db.prepare(E).get(...x);return h(g)&&typeof g.count=="number"?g.count:0},r=this.db.prepare(`
|
|
438
|
+
SELECT status, COUNT(*) AS count FROM outbox GROUP BY status
|
|
439
|
+
`).all(),s={};for(const E of r)typeof E.status=="string"&&typeof E.count=="number"&&(s[E.status]=E.count);const d=this.db.prepare(`
|
|
440
|
+
SELECT value_json
|
|
441
|
+
FROM runner_config
|
|
442
|
+
WHERE key = 'headless_queue_policy'
|
|
443
|
+
LIMIT 1
|
|
444
|
+
`).get();let i=fe;if(h(d)&&typeof d.value_json=="string")try{const E=JSON.parse(d.value_json);h(E)&&typeof E.maxItems=="number"&&(i=F({maxItems:E.maxItems}))}catch{}const n=a("SELECT COUNT(*) AS count FROM headless_execution_attempts WHERE status = 'queued' AND dead_lettered_at IS NULL"),c=a("SELECT COUNT(*) AS count FROM headless_execution_attempts WHERE status = 'backoff' AND dead_lettered_at IS NULL"),p=a("SELECT COUNT(*) AS count FROM headless_execution_attempts WHERE status = 'running' AND dead_lettered_at IS NULL"),y=a("SELECT COUNT(*) AS count FROM headless_execution_attempts WHERE dead_lettered_at IS NOT NULL"),C=n+c+p,l=this.db.prepare(`
|
|
445
|
+
SELECT MIN(next_retry_at) AS next_retry_at
|
|
446
|
+
FROM headless_execution_attempts
|
|
447
|
+
WHERE status = 'backoff'
|
|
448
|
+
AND dead_lettered_at IS NULL
|
|
449
|
+
AND next_retry_at IS NOT NULL
|
|
450
|
+
`).get(),u=h(l)&&typeof l.next_retry_at=="string"?l.next_retry_at:void 0;return{schemaVersion:this.getSchemaVersion(),jobs:this.db.prepare(`
|
|
451
|
+
SELECT job_id, kind, status, summary, reason_code, created_at, updated_at,
|
|
452
|
+
next_run_at, metadata_json,
|
|
453
|
+
(SELECT COUNT(*)
|
|
454
|
+
FROM job_receipts r
|
|
455
|
+
WHERE r.job_id = jobs.job_id
|
|
456
|
+
AND (r.operation_id LIKE 'tick-%' OR r.operation_id LIKE 'loop-tick-%')
|
|
457
|
+
AND r.status IN ('accepted', 'applied')) AS iteration,
|
|
458
|
+
(SELECT COUNT(*)
|
|
459
|
+
FROM goal_campaigns c
|
|
460
|
+
JOIN goal_ledger_items i ON i.campaign_id = c.campaign_id
|
|
461
|
+
WHERE c.job_id = jobs.job_id) AS goal_ledger_item_count,
|
|
462
|
+
(SELECT COUNT(*)
|
|
463
|
+
FROM goal_campaigns c
|
|
464
|
+
JOIN goal_ledger_items i ON i.campaign_id = c.campaign_id
|
|
465
|
+
WHERE c.job_id = jobs.job_id
|
|
466
|
+
AND i.status = 'blocked') AS blocked_goal_ledger_item_count,
|
|
467
|
+
(SELECT COUNT(*)
|
|
468
|
+
FROM goal_campaigns c
|
|
469
|
+
JOIN goal_ledger_items i ON i.campaign_id = c.campaign_id
|
|
470
|
+
WHERE c.job_id = jobs.job_id
|
|
471
|
+
AND i.item_type = 'security_issue'
|
|
472
|
+
AND i.status = 'blocked') AS security_issue_blocked_count,
|
|
473
|
+
(SELECT COUNT(*)
|
|
474
|
+
FROM goal_campaigns c
|
|
475
|
+
JOIN goal_verifiers v ON v.campaign_id = c.campaign_id
|
|
476
|
+
WHERE c.job_id = jobs.job_id) AS goal_verifier_count,
|
|
477
|
+
(SELECT COUNT(*)
|
|
478
|
+
FROM goal_campaigns c
|
|
479
|
+
JOIN goal_verifiers v ON v.campaign_id = c.campaign_id
|
|
480
|
+
WHERE c.job_id = jobs.job_id
|
|
481
|
+
AND v.status = 'failed') AS failed_verifier_count,
|
|
482
|
+
(SELECT COUNT(*)
|
|
483
|
+
FROM goal_campaigns c
|
|
484
|
+
JOIN goal_verifiers v ON v.campaign_id = c.campaign_id
|
|
485
|
+
WHERE c.job_id = jobs.job_id
|
|
486
|
+
AND v.status = 'unavailable') AS unavailable_verifier_count,
|
|
487
|
+
(SELECT COUNT(*)
|
|
488
|
+
FROM goal_campaigns c
|
|
489
|
+
JOIN goal_review_gates g ON g.campaign_id = c.campaign_id
|
|
490
|
+
WHERE c.job_id = jobs.job_id) AS goal_review_gate_count,
|
|
491
|
+
(SELECT COUNT(*)
|
|
492
|
+
FROM goal_campaigns c
|
|
493
|
+
JOIN goal_review_gates g ON g.campaign_id = c.campaign_id
|
|
494
|
+
WHERE c.job_id = jobs.job_id
|
|
495
|
+
AND g.required = 1
|
|
496
|
+
AND g.status IN ('failed', 'blocked')) AS failed_required_review_gate_count
|
|
497
|
+
FROM jobs
|
|
498
|
+
ORDER BY updated_at DESC, job_id ASC
|
|
499
|
+
LIMIT ?
|
|
500
|
+
`).all(e.jobLimit),staleLeases:this.db.prepare(`
|
|
501
|
+
SELECT lease_id, job_id, runner_id, expires_at
|
|
502
|
+
FROM job_leases
|
|
503
|
+
WHERE released_at IS NULL AND expires_at <= ?
|
|
504
|
+
ORDER BY expires_at ASC, lease_id ASC
|
|
505
|
+
LIMIT ?
|
|
506
|
+
`).all(e.nowIso,e.staleLeaseLimit),receipts:this.db.prepare(`
|
|
507
|
+
SELECT receipt_id, job_id, operation_id, status, reason_code, created_at, metadata_json
|
|
508
|
+
FROM job_receipts
|
|
509
|
+
ORDER BY created_at DESC, receipt_id ASC
|
|
510
|
+
LIMIT ?
|
|
511
|
+
`).all(e.receiptLimit),events:this.db.prepare(`
|
|
512
|
+
SELECT event_id, job_id, operation_id, type, summary, reason_code, created_at, metadata_json
|
|
513
|
+
FROM job_events
|
|
514
|
+
ORDER BY created_at DESC, event_id ASC
|
|
515
|
+
LIMIT ?
|
|
516
|
+
`).all(e.eventLimit),stateSnapshots:this.db.prepare(`
|
|
517
|
+
SELECT snapshot_id, job_id, kind, relative_path, sha256, summary,
|
|
518
|
+
captured_at, operation_id, metadata_json
|
|
519
|
+
FROM state_snapshots
|
|
520
|
+
WHERE kind = 'context_compaction'
|
|
521
|
+
ORDER BY captured_at DESC, snapshot_id ASC
|
|
522
|
+
LIMIT ?
|
|
523
|
+
`).all(e.snapshotLimit),headlessExecutionAttempts:this.db.prepare(`
|
|
524
|
+
SELECT attempt_id, execution_id, job_id, status, reason_code, runtime_id,
|
|
525
|
+
model_id, retry_count, max_attempts, lease_id, runner_id,
|
|
526
|
+
lease_expires_at, heartbeat_at, public_summary, enqueued_at,
|
|
527
|
+
not_before_at, duration_ms, counts_json, hashes_json,
|
|
528
|
+
redaction_summary_json, queue_priority, queue_scope,
|
|
529
|
+
attempt_count, next_retry_at, dead_lettered_at,
|
|
530
|
+
dead_letter_reason_code
|
|
531
|
+
FROM headless_execution_attempts
|
|
532
|
+
ORDER BY enqueued_at DESC, attempt_id ASC
|
|
533
|
+
LIMIT ?
|
|
534
|
+
`).all(e.jobLimit),counts:{jobs:a("SELECT COUNT(*) AS count FROM jobs"),activeJobs:a("SELECT COUNT(*) AS count FROM jobs WHERE status IN ('planned', 'active', 'running', 'waiting_external', 'waiting_human', 'backoff', 'paused', 'blocked')"),activeLeases:a("SELECT COUNT(*) AS count FROM job_leases WHERE released_at IS NULL"),dueJobs:a("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:a("SELECT COUNT(*) AS count FROM job_leases WHERE released_at IS NULL AND expires_at <= ?",e.nowIso),receipts:a("SELECT COUNT(*) AS count FROM job_receipts"),events:a("SELECT COUNT(*) AS count FROM job_events"),processingOutputSummaries:a("SELECT COUNT(*) AS count FROM job_events WHERE type = ?",O),goalLedgerItems:a("SELECT COUNT(*) AS count FROM goal_ledger_items"),goalVerifiers:a("SELECT COUNT(*) AS count FROM goal_verifiers"),goalReviewGates:a("SELECT COUNT(*) AS count FROM goal_review_gates"),stateSnapshots:a("SELECT COUNT(*) AS count FROM state_snapshots"),headlessExecutionAttempts:a("SELECT COUNT(*) AS count FROM headless_execution_attempts"),headlessQueuedAttempts:a("SELECT COUNT(*) AS count FROM headless_execution_attempts WHERE status IN ('queued', 'backoff')"),headlessRunningAttempts:a("SELECT COUNT(*) AS count FROM headless_execution_attempts WHERE status = 'running'"),headlessRetryingAttempts:c,headlessDeadLetterAttempts:y,staleHeadlessExecutionAttempts:a("SELECT COUNT(*) AS count FROM headless_execution_attempts WHERE status = 'running' AND lease_released_at IS NULL AND lease_expires_at <= ?",e.nowIso),outbox:a("SELECT COUNT(*) AS count FROM outbox")},outboxCounts:s,queue:{depth:C,queued:n,running:p,retrying:c,deadLetter:y,capacity:i.maxItems,available:Math.max(0,i.maxItems-C),backpressure:C>=i.maxItems,generatedAt:e.nowIso,...u?{nextRetryAt:u}:{},...C>=i.maxItems?{reasonCode:U.CAP_REACHED}:{},publicSafe:!0}}}listProcessingOutputSummaries(e={}){const a=ie(e.limit),r=ue(e),s=`
|
|
535
|
+
SELECT event_id, job_id, operation_id, summary, reason_code, created_at, metadata_json
|
|
536
|
+
FROM job_events
|
|
537
|
+
WHERE type = ?${r.sql}
|
|
538
|
+
ORDER BY created_at DESC, event_id DESC
|
|
539
|
+
LIMIT ?
|
|
540
|
+
`;return this.db.prepare(`SELECT * FROM (${s}) ORDER BY created_at ASC, event_id ASC`).all(O,...r.params,a).map(le)}pollProcessingOutputSummaries(e={}){const a=ie(e.limit),r=Ge(e.cursor),s=ue(e),d=r?" AND (created_at > ? OR (created_at = ? AND event_id > ?))":"",i=`
|
|
541
|
+
SELECT event_id, job_id, operation_id, summary, reason_code, created_at, metadata_json
|
|
542
|
+
FROM job_events
|
|
543
|
+
WHERE type = ?${s.sql}${d}
|
|
544
|
+
ORDER BY created_at ASC, event_id ASC
|
|
545
|
+
LIMIT ?
|
|
546
|
+
`,n=[O];n.push(...s.params),r&&n.push(r.createdAt,r.createdAt,r.eventId),n.push(a+1);const c=this.db.prepare(i).all(...n),p=c.slice(0,a).map(le),y=p[p.length-1];return{summaries:p,...y?{nextCursor:y.cursor}:e.cursor?{nextCursor:e.cursor}:{},hasMore:c.length>a,publicSafe:!0}}listDueJobs(e){const a=Math.max(1,Math.min(50,Math.floor(e.limit)));return this.db.prepare(`
|
|
547
|
+
SELECT j.job_id, j.kind, j.status, j.summary, j.reason_code, j.created_at,
|
|
548
|
+
j.updated_at, j.next_run_at, j.metadata_json,
|
|
549
|
+
(SELECT COUNT(*)
|
|
550
|
+
FROM job_receipts r
|
|
551
|
+
WHERE r.job_id = j.job_id
|
|
552
|
+
AND (r.operation_id LIKE 'tick-%' OR r.operation_id LIKE 'loop-tick-%')
|
|
553
|
+
AND r.status IN ('accepted', 'applied')) AS iteration,
|
|
554
|
+
(SELECT COUNT(*)
|
|
555
|
+
FROM job_leases l
|
|
556
|
+
WHERE l.job_id = j.job_id
|
|
557
|
+
AND l.released_at IS NULL) AS active_lease_count
|
|
558
|
+
FROM jobs j
|
|
559
|
+
WHERE j.next_run_at IS NOT NULL
|
|
560
|
+
AND j.next_run_at <= ?
|
|
561
|
+
AND j.status NOT IN ('waiting_external', 'waiting_human', 'paused', 'blocked', 'completed', 'aborted', 'cancelled')
|
|
562
|
+
ORDER BY j.next_run_at ASC, j.job_id ASC
|
|
563
|
+
LIMIT ?
|
|
564
|
+
`).all(e.nowIso,a)}recoverStaleLeases(e){this.assertCanMutate();const a=Date.parse(e.nowIso);if(!Number.isFinite(a))throw new _("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))),d=new Date(a-r).toISOString();try{return this.runInTransaction(()=>{const n=this.db.prepare(`
|
|
565
|
+
SELECT lease_id
|
|
566
|
+
FROM job_leases
|
|
567
|
+
WHERE released_at IS NULL
|
|
568
|
+
AND expires_at <= ?
|
|
569
|
+
ORDER BY expires_at ASC, lease_id ASC
|
|
570
|
+
LIMIT ?
|
|
571
|
+
`).all(d,s).map(y=>y.lease_id).filter(y=>typeof y=="string"&&y.length>0);if(n.length===0)return{recoveredLeaseIds:[],safeExpiredAtOrBefore:d,changes:0};const c=n.map(()=>"?").join(", "),p=this.db.prepare(`
|
|
572
|
+
UPDATE job_leases
|
|
573
|
+
SET status = 'expired', released_at = ?
|
|
574
|
+
WHERE released_at IS NULL
|
|
575
|
+
AND lease_id IN (${c})
|
|
576
|
+
`).run(e.nowIso,...n);return{recoveredLeaseIds:n,safeExpiredAtOrBefore:d,changes:p.changes}})}catch(i){throw m(i,"sqlite-mutation-failed")}}recoverStaleHeadlessExecutionAttempts(e){this.assertCanMutate();const a=Date.parse(e.nowIso);if(!Number.isFinite(a))throw new _("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))),d=new Date(a-r).toISOString();try{return this.runInTransaction(()=>{const i=this.db.prepare(`
|
|
577
|
+
SELECT attempt_id, retry_count, max_attempts, attempt_count
|
|
578
|
+
FROM headless_execution_attempts
|
|
579
|
+
WHERE status = 'running'
|
|
580
|
+
AND lease_released_at IS NULL
|
|
581
|
+
AND lease_expires_at <= ?
|
|
582
|
+
ORDER BY lease_expires_at ASC, attempt_id ASC
|
|
583
|
+
LIMIT ?
|
|
584
|
+
`).all(d,s),n=[],c=[],p=F(e.policy);for(const l of i){if(typeof l.attempt_id!="string"||l.attempt_id.length===0)continue;const u=typeof l.retry_count=="number"?l.retry_count:0,E=typeof l.max_attempts=="number"?l.max_attempts:1,x=typeof l.attempt_count=="number"?l.attempt_count:0;Math.max(x,u+1)>=E?c.push(l.attempt_id):n.push({attemptId:l.attempt_id,nextRetryAt:Se(e.nowIso,u+1,p)})}let y=0;for(const l of n)y+=this.db.prepare(`
|
|
585
|
+
UPDATE headless_execution_attempts
|
|
586
|
+
SET status = 'backoff',
|
|
587
|
+
retry_count = retry_count + 1,
|
|
588
|
+
reason_code = ?,
|
|
589
|
+
lease_released_at = ?,
|
|
590
|
+
not_before_at = ?,
|
|
591
|
+
next_retry_at = ?
|
|
592
|
+
WHERE attempt_id = ?
|
|
593
|
+
AND status = 'running'
|
|
594
|
+
AND lease_released_at IS NULL
|
|
595
|
+
`).run(U.LEASE_TIMEOUT_RETRY,e.nowIso,l.nextRetryAt,l.nextRetryAt,l.attemptId).changes;if(c.length>0){const l=c.map(()=>"?").join(", ");y+=this.db.prepare(`
|
|
596
|
+
UPDATE headless_execution_attempts
|
|
597
|
+
SET status = 'failed',
|
|
598
|
+
retry_count = retry_count + 1,
|
|
599
|
+
reason_code = ?,
|
|
600
|
+
completed_at = ?,
|
|
601
|
+
lease_released_at = ?,
|
|
602
|
+
dead_lettered_at = ?,
|
|
603
|
+
dead_letter_reason_code = ?,
|
|
604
|
+
next_retry_at = NULL
|
|
605
|
+
WHERE attempt_id IN (${l})
|
|
606
|
+
AND status = 'running'
|
|
607
|
+
AND lease_released_at IS NULL
|
|
608
|
+
`).run(U.ATTEMPTS_EXHAUSTED,e.nowIso,e.nowIso,e.nowIso,U.ATTEMPTS_EXHAUSTED,...c).changes}const C=n.map(l=>l.attemptId);return{recoveredAttemptIds:[...C,...c],failedAttemptIds:c,retryingAttemptIds:C,deadLetteredAttemptIds:c,safeExpiredAtOrBefore:d,changes:y,publicSafe:!0}})}catch(i){throw m(i,"sqlite-mutation-failed")}}ensureGoalCampaign(e,a,r,s){this.db.prepare(`
|
|
609
|
+
INSERT OR IGNORE INTO goal_campaigns (
|
|
610
|
+
campaign_id, job_id, status, public_summary, created_at, updated_at
|
|
611
|
+
) VALUES (?, ?, 'active', 'Public goal campaign summary unavailable', ?, ?)
|
|
612
|
+
`).run(e,a,r,s)}configureConnection(){const e=String(K(this.db.pragma("journal_mode = WAL",{simple:!0}))??"").toLowerCase();if(e!=="wal")throw new _("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(K(this.db.pragma("foreign_keys",{simple:!0}))??0)!==1)throw new _("sqlite-migration-failed","Continuity SQLite foreign_keys pragma is not enabled.")}ensureMigrationTable(){this.db.exec(`
|
|
613
|
+
CREATE TABLE IF NOT EXISTS continuity_migrations (
|
|
614
|
+
version INTEGER PRIMARY KEY,
|
|
615
|
+
name TEXT NOT NULL,
|
|
616
|
+
checksum TEXT NOT NULL,
|
|
617
|
+
applied_at TEXT NOT NULL
|
|
618
|
+
);
|
|
619
|
+
`)}applyMigrations(){this.db.transaction(()=>{for(const a of ke){const r=Be(a.sql),s=this.db.prepare("SELECT version, name, checksum FROM continuity_migrations WHERE version = ?").get(a.version);if(s){if(s.checksum!==r||s.name!==a.name)throw new _("sqlite-migration-conflict",`Continuity SQLite migration ${a.version} checksum conflict.`);continue}this.db.exec(a.sql),this.db.prepare("INSERT INTO continuity_migrations (version, name, checksum, applied_at) VALUES (?, ?, ?, ?)").run(a.version,a.name,r,this.now()),this.db.pragma(`user_version = ${a.version}`)}})()}assertCanMutate(){if(this.mutationBlocked)throw new _("sqlite-mutation-blocked","Continuity SQLite mutation is blocked after integrity failure.",{mutationBlocked:!0})}toWriteResult(e){const a=e.changes>0;return{inserted:a,replay:!a,changes:e.changes}}}export{O as CONTINUITY_PROCESSING_OUTPUT_SUMMARY_EVENT_TYPE,Ne as CONTINUITY_PROCESSING_OUTPUT_SUMMARY_MAX_CHARS,je as CONTINUITY_PUBLIC_STAGES,Oe as CONTINUITY_SQLITE_FILENAME,ee as CONTINUITY_SQLITE_RELATIVE_DIR,Ct as CONTINUITY_SQLITE_SCHEMA_VERSION,re as CONTINUITY_STAGE_HISTORY_MAX,it as ContinuitySqliteStore,_ as ContinuitySqliteStoreError,te as DEFAULT_CONTINUITY_PROCESSING_SUMMARY_LIMIT,Te as DEFAULT_CONTINUITY_SQLITE_BUSY_TIMEOUT_MS,Le as MAX_CONTINUITY_PROCESSING_SUMMARY_LIMIT,ae as SQLITE_ADAPTER_INSTALL_GUIDANCE,ot as continuitySqliteStorePath,se as isContinuityPublicStage,st as loadBetterSqlite3Adapter,De as normalizeContinuityStageIteration,ft as openContinuitySqliteStore,Ue as sanitizeContinuityStageHistory,oe as sanitizeContinuityStageTimestamp};
|