@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.
Files changed (235) hide show
  1. package/LICENSE +56 -0
  2. package/LICENSE-COMMERCIAL.md +70 -0
  3. package/README.md +58 -0
  4. package/dist/sbom.cdx.json +11159 -0
  5. package/docs/install/coderabbit-manual-setup.md +86 -0
  6. package/docs/install/installer-diagnostics.md +107 -0
  7. package/docs/install/linux-global-install.md +97 -0
  8. package/install.js +572 -0
  9. package/install.ps1 +2214 -0
  10. package/install.sh +2013 -0
  11. package/package.json +132 -0
  12. package/packages/client/dist/adapters/adapter-registry.d.ts +61 -0
  13. package/packages/client/dist/adapters/adapter-registry.js +1 -0
  14. package/packages/client/dist/adapters/antigravity-adapter.d.ts +18 -0
  15. package/packages/client/dist/adapters/antigravity-adapter.js +2 -0
  16. package/packages/client/dist/adapters/claude-code-adapter.d.ts +19 -0
  17. package/packages/client/dist/adapters/claude-code-adapter.js +3 -0
  18. package/packages/client/dist/adapters/codex-adapter.d.ts +19 -0
  19. package/packages/client/dist/adapters/codex-adapter.js +2 -0
  20. package/packages/client/dist/adapters/cursor-adapter.d.ts +19 -0
  21. package/packages/client/dist/adapters/cursor-adapter.js +4 -0
  22. package/packages/client/dist/adapters/gemini-adapter.d.ts +18 -0
  23. package/packages/client/dist/adapters/gemini-adapter.js +2 -0
  24. package/packages/client/dist/adapters/index.d.ts +19 -0
  25. package/packages/client/dist/adapters/index.js +1 -0
  26. package/packages/client/dist/adapters/platform-detector.d.ts +48 -0
  27. package/packages/client/dist/adapters/platform-detector.js +1 -0
  28. package/packages/client/dist/adapters/target-adapter.d.ts +70 -0
  29. package/packages/client/dist/adapters/target-adapter.js +0 -0
  30. package/packages/client/dist/adapters/vscode-adapter.d.ts +19 -0
  31. package/packages/client/dist/adapters/vscode-adapter.js +2 -0
  32. package/packages/client/dist/agent/refresh-stubs.d.ts +90 -0
  33. package/packages/client/dist/agent/refresh-stubs.js +2 -0
  34. package/packages/client/dist/agent/update-agent-yaml.d.ts +26 -0
  35. package/packages/client/dist/agent/update-agent-yaml.js +1 -0
  36. package/packages/client/dist/agent/update-description.d.ts +45 -0
  37. package/packages/client/dist/agent/update-description.js +1 -0
  38. package/packages/client/dist/cache/crypto-utils.d.ts +30 -0
  39. package/packages/client/dist/cache/crypto-utils.js +1 -0
  40. package/packages/client/dist/cache/encrypted-cache.d.ts +30 -0
  41. package/packages/client/dist/cache/encrypted-cache.js +1 -0
  42. package/packages/client/dist/cache/in-memory-asset-cache.d.ts +62 -0
  43. package/packages/client/dist/cache/in-memory-asset-cache.js +1 -0
  44. package/packages/client/dist/cache/index.d.ts +13 -0
  45. package/packages/client/dist/cache/index.js +1 -0
  46. package/packages/client/dist/cache/protected-pi-boundary.d.ts +19 -0
  47. package/packages/client/dist/cache/protected-pi-boundary.js +1 -0
  48. package/packages/client/dist/checkpoint/checkpoint-client-reader.d.ts +45 -0
  49. package/packages/client/dist/checkpoint/checkpoint-client-reader.js +2 -0
  50. package/packages/client/dist/checkpoint/index.d.ts +12 -0
  51. package/packages/client/dist/checkpoint/index.js +1 -0
  52. package/packages/client/dist/checkpoint/shared-checkpoint-types.d.ts +85 -0
  53. package/packages/client/dist/checkpoint/shared-checkpoint-types.js +1 -0
  54. package/packages/client/dist/cli.d.ts +14 -0
  55. package/packages/client/dist/cli.js +81 -0
  56. package/packages/client/dist/commands/activate.d.ts +55 -0
  57. package/packages/client/dist/commands/activate.js +8 -0
  58. package/packages/client/dist/commands/cache-status.d.ts +39 -0
  59. package/packages/client/dist/commands/cache-status.js +2 -0
  60. package/packages/client/dist/commands/invoke.d.ts +546 -0
  61. package/packages/client/dist/commands/invoke.js +140 -0
  62. package/packages/client/dist/commands/refresh-memory.d.ts +11 -0
  63. package/packages/client/dist/commands/refresh-memory.js +1 -0
  64. package/packages/client/dist/config/resolver-selection.d.ts +40 -0
  65. package/packages/client/dist/config/resolver-selection.js +1 -0
  66. package/packages/client/dist/config/secure-config.d.ts +78 -0
  67. package/packages/client/dist/config/secure-config.js +12 -0
  68. package/packages/client/dist/constants.d.ts +25 -0
  69. package/packages/client/dist/constants.js +1 -0
  70. package/packages/client/dist/context/context-collector.d.ts +28 -0
  71. package/packages/client/dist/context/context-collector.js +2 -0
  72. package/packages/client/dist/context/context-sanitizer.d.ts +28 -0
  73. package/packages/client/dist/context/context-sanitizer.js +1 -0
  74. package/packages/client/dist/continuity/autonomous-governance.d.ts +84 -0
  75. package/packages/client/dist/continuity/autonomous-governance.js +1 -0
  76. package/packages/client/dist/continuity/continuity-client-state-store.d.ts +302 -0
  77. package/packages/client/dist/continuity/continuity-client-state-store.js +1 -0
  78. package/packages/client/dist/continuity/invoke-hooks.d.ts +19 -0
  79. package/packages/client/dist/continuity/invoke-hooks.js +1 -0
  80. package/packages/client/dist/continuity/migrations/001-initial-schema.d.ts +11 -0
  81. package/packages/client/dist/continuity/migrations/001-initial-schema.js +263 -0
  82. package/packages/client/dist/continuity/migrations/002-processing-output-summary-indexes.d.ts +11 -0
  83. package/packages/client/dist/continuity/migrations/002-processing-output-summary-indexes.js +7 -0
  84. package/packages/client/dist/continuity/migrations/003-headless-execution-attempts.d.ts +11 -0
  85. package/packages/client/dist/continuity/migrations/003-headless-execution-attempts.js +62 -0
  86. package/packages/client/dist/continuity/migrations/004-outbox-delivery-state.d.ts +11 -0
  87. package/packages/client/dist/continuity/migrations/004-outbox-delivery-state.js +19 -0
  88. package/packages/client/dist/continuity/migrations/005-bounded-headless-queue.d.ts +11 -0
  89. package/packages/client/dist/continuity/migrations/005-bounded-headless-queue.js +35 -0
  90. package/packages/client/dist/continuity/outbox.d.ts +83 -0
  91. package/packages/client/dist/continuity/outbox.js +1 -0
  92. package/packages/client/dist/continuity/runner-bootstrap-policy.d.ts +50 -0
  93. package/packages/client/dist/continuity/runner-bootstrap-policy.js +1 -0
  94. package/packages/client/dist/continuity/sqlite-store.d.ts +926 -0
  95. package/packages/client/dist/continuity/sqlite-store.js +619 -0
  96. package/packages/client/dist/errors/error-messages.d.ts +40 -0
  97. package/packages/client/dist/errors/error-messages.js +2 -0
  98. package/packages/client/dist/graph-retrieval/pre-command-hook.d.ts +34 -0
  99. package/packages/client/dist/graph-retrieval/pre-command-hook.js +1 -0
  100. package/packages/client/dist/graph-retrieval/shared-graph-retrieval-contract.d.ts +99 -0
  101. package/packages/client/dist/graph-retrieval/shared-graph-retrieval-contract.js +1 -0
  102. package/packages/client/dist/i18n/first-run.d.ts +23 -0
  103. package/packages/client/dist/i18n/first-run.js +2 -0
  104. package/packages/client/dist/index.d.ts +56 -0
  105. package/packages/client/dist/index.js +1 -0
  106. package/packages/client/dist/license/index.d.ts +5 -0
  107. package/packages/client/dist/license/index.js +1 -0
  108. package/packages/client/dist/license/license-client.d.ts +79 -0
  109. package/packages/client/dist/license/license-client.js +1 -0
  110. package/packages/client/dist/machine/fingerprint.d.ts +34 -0
  111. package/packages/client/dist/machine/fingerprint.js +2 -0
  112. package/packages/client/dist/machine/index.d.ts +5 -0
  113. package/packages/client/dist/machine/index.js +1 -0
  114. package/packages/client/dist/memory/project-memory-writer.d.ts +74 -0
  115. package/packages/client/dist/memory/project-memory-writer.js +36 -0
  116. package/packages/client/dist/memory/shared-project-memory-types.d.ts +370 -0
  117. package/packages/client/dist/memory/shared-project-memory-types.js +2 -0
  118. package/packages/client/dist/policy/architecture-policy.d.ts +40 -0
  119. package/packages/client/dist/policy/architecture-policy.js +2 -0
  120. package/packages/client/dist/policy/index.d.ts +8 -0
  121. package/packages/client/dist/policy/index.js +1 -0
  122. package/packages/client/dist/policy/shared-policy-types.d.ts +89 -0
  123. package/packages/client/dist/policy/shared-policy-types.js +0 -0
  124. package/packages/client/dist/resilience/circuit-breaker.d.ts +70 -0
  125. package/packages/client/dist/resilience/circuit-breaker.js +1 -0
  126. package/packages/client/dist/resilience/degradation-manager.d.ts +67 -0
  127. package/packages/client/dist/resilience/degradation-manager.js +1 -0
  128. package/packages/client/dist/resilience/freshness-indicator.d.ts +59 -0
  129. package/packages/client/dist/resilience/freshness-indicator.js +1 -0
  130. package/packages/client/dist/resilience/index.d.ts +8 -0
  131. package/packages/client/dist/resilience/index.js +1 -0
  132. package/packages/client/dist/resilience/recovery-detector.d.ts +59 -0
  133. package/packages/client/dist/resilience/recovery-detector.js +1 -0
  134. package/packages/client/dist/resolvers/asset-resolver.d.ts +79 -0
  135. package/packages/client/dist/resolvers/asset-resolver.js +0 -0
  136. package/packages/client/dist/resolvers/local-resolver.d.ts +26 -0
  137. package/packages/client/dist/resolvers/local-resolver.js +8 -0
  138. package/packages/client/dist/resolvers/remote-resolver.d.ts +91 -0
  139. package/packages/client/dist/resolvers/remote-resolver.js +1 -0
  140. package/packages/client/dist/runner/binary.d.ts +115 -0
  141. package/packages/client/dist/runner/binary.js +1 -0
  142. package/packages/client/dist/runner/cli.d.ts +168 -0
  143. package/packages/client/dist/runner/cli.js +70 -0
  144. package/packages/client/dist/runner/headless/adapters.d.ts +20 -0
  145. package/packages/client/dist/runner/headless/adapters.js +1 -0
  146. package/packages/client/dist/runner/headless/claude-code-adapter.d.ts +8 -0
  147. package/packages/client/dist/runner/headless/claude-code-adapter.js +1 -0
  148. package/packages/client/dist/runner/headless/fake-adapter.d.ts +8 -0
  149. package/packages/client/dist/runner/headless/fake-adapter.js +1 -0
  150. package/packages/client/dist/runner/headless/opencode-adapter.d.ts +15 -0
  151. package/packages/client/dist/runner/headless/opencode-adapter.js +2 -0
  152. package/packages/client/dist/runner/headless/resolver.d.ts +68 -0
  153. package/packages/client/dist/runner/headless/resolver.js +1 -0
  154. package/packages/client/dist/runner/headless/run-yolo.d.ts +59 -0
  155. package/packages/client/dist/runner/headless/run-yolo.js +1 -0
  156. package/packages/client/dist/runner/headless/run-yoloop.d.ts +113 -0
  157. package/packages/client/dist/runner/headless/run-yoloop.js +1 -0
  158. package/packages/client/dist/runner/headless/types.d.ts +194 -0
  159. package/packages/client/dist/runner/headless/types.js +2 -0
  160. package/packages/client/dist/runner/local-console.d.ts +83 -0
  161. package/packages/client/dist/runner/local-console.js +13 -0
  162. package/packages/client/dist/runner/portal-sync-worker.d.ts +184 -0
  163. package/packages/client/dist/runner/portal-sync-worker.js +1 -0
  164. package/packages/client/dist/runner/project-identity.d.ts +19 -0
  165. package/packages/client/dist/runner/project-identity.js +1 -0
  166. package/packages/client/dist/runner/scheduler.d.ts +186 -0
  167. package/packages/client/dist/runner/scheduler.js +7 -0
  168. package/packages/client/dist/runner-cli.d.ts +9 -0
  169. package/packages/client/dist/runner-cli.js +3 -0
  170. package/packages/client/dist/state/project-state-snapshot.d.ts +24 -0
  171. package/packages/client/dist/state/project-state-snapshot.js +1 -0
  172. package/packages/client/dist/state/state-json-repair.d.ts +74 -0
  173. package/packages/client/dist/state/state-json-repair.js +3 -0
  174. package/packages/client/dist/telemetry/index.d.ts +5 -0
  175. package/packages/client/dist/telemetry/index.js +1 -0
  176. package/packages/client/dist/telemetry/offline-queue.d.ts +57 -0
  177. package/packages/client/dist/telemetry/offline-queue.js +1 -0
  178. package/packages/client/dist/tier/index.d.ts +5 -0
  179. package/packages/client/dist/tier/index.js +1 -0
  180. package/packages/client/dist/tier/tier-aware-client.d.ts +105 -0
  181. package/packages/client/dist/tier/tier-aware-client.js +1 -0
  182. package/packages/client/dist/types/index.d.ts +140 -0
  183. package/packages/client/dist/types/index.js +1 -0
  184. package/packages/client/dist/yoloop/discovery-hook.d.ts +85 -0
  185. package/packages/client/dist/yoloop/discovery-hook.js +2 -0
  186. package/packages/client/dist/yoloop/index.d.ts +10 -0
  187. package/packages/client/dist/yoloop/index.js +1 -0
  188. package/packages/client/dist/yoloop/invoke-hooks.d.ts +127 -0
  189. package/packages/client/dist/yoloop/invoke-hooks.js +5 -0
  190. package/packages/client/dist/yoloop/shared-discover-epics.d.ts +289 -0
  191. package/packages/client/dist/yoloop/shared-discover-epics.js +1 -0
  192. package/packages/client/dist/yoloop/shared-yoloop-types.d.ts +172 -0
  193. package/packages/client/dist/yoloop/shared-yoloop-types.js +1 -0
  194. package/packages/client/dist/yoloop/yoloop-client-state-store.d.ts +124 -0
  195. package/packages/client/dist/yoloop/yoloop-client-state-store.js +1 -0
  196. package/postinstall.js +754 -0
  197. package/targets-stubs/antigravity/README.md +36 -0
  198. package/targets-stubs/antigravity/gemini.md +29 -0
  199. package/targets-stubs/antigravity/install-antigravity.sh +153 -0
  200. package/targets-stubs/antigravity/mcp-config.json +30 -0
  201. package/targets-stubs/antigravity/skill/SKILL.md +166 -0
  202. package/targets-stubs/claude-code/.mcp.json +32 -0
  203. package/targets-stubs/claude-code/README.md +20 -0
  204. package/targets-stubs/claude-code/neocortex-root.agent.yaml +42 -0
  205. package/targets-stubs/claude-code/neocortex-root.md +317 -0
  206. package/targets-stubs/claude-code/neocortex.agent.yaml +42 -0
  207. package/targets-stubs/claude-code/neocortex.md +385 -0
  208. package/targets-stubs/codex/AGENTS.md +250 -0
  209. package/targets-stubs/codex/README.md +47 -0
  210. package/targets-stubs/codex/config-mcp.toml +22 -0
  211. package/targets-stubs/codex/install-codex.sh +63 -0
  212. package/targets-stubs/codex/neocortex.toml +33 -0
  213. package/targets-stubs/cursor/README.md +33 -0
  214. package/targets-stubs/cursor/agent.md +211 -0
  215. package/targets-stubs/cursor/install-cursor.sh +50 -0
  216. package/targets-stubs/cursor/mcp.json +30 -0
  217. package/targets-stubs/gemini-cli/README.md +34 -0
  218. package/targets-stubs/gemini-cli/agent.md +241 -0
  219. package/targets-stubs/gemini-cli/agents/neocortex.md +60 -0
  220. package/targets-stubs/gemini-cli/gemini.md +46 -0
  221. package/targets-stubs/gemini-cli/install-gemini.sh +70 -0
  222. package/targets-stubs/gemini-cli/settings-mcp.json +30 -0
  223. package/targets-stubs/kimi/mcp.json +33 -0
  224. package/targets-stubs/kimi/neocortex.md +60 -0
  225. package/targets-stubs/lib/mcp-merge.js +189 -0
  226. package/targets-stubs/openclaw/README.md +12 -0
  227. package/targets-stubs/openclaw/SKILL.md +92 -0
  228. package/targets-stubs/opencode/neocortex-root.md +267 -0
  229. package/targets-stubs/opencode/neocortex.md +65 -0
  230. package/targets-stubs/opencode/opencode-mcp.json +35 -0
  231. package/targets-stubs/vscode/README.md +34 -0
  232. package/targets-stubs/vscode/copilot-instructions.md +47 -0
  233. package/targets-stubs/vscode/install-vscode.sh +72 -0
  234. package/targets-stubs/vscode/mcp.json +36 -0
  235. package/targets-stubs/vscode/neocortex.agent.md +252 -0
@@ -0,0 +1,168 @@
1
+ /**
2
+ * @license FSL-1.1
3
+ * Copyright (c) 2026 OrNexus AI
4
+ *
5
+ * P180.06 -- neocortex-runner core tick loop, leases, receipts and recovery.
6
+ */
7
+ import { type ContinuitySqliteAdapter, type ContinuitySqliteAdapterLoadResult } from '../continuity/sqlite-store.js';
8
+ import { type RunnerSchedulerCommandOptions } from './scheduler.js';
9
+ import { type RunYoloExecutionPhaseSummary } from './headless/run-yolo.js';
10
+ import { type RunYoloopExecutionPhaseSummary, type RunYoloopRootInvoker } from './headless/run-yoloop.js';
11
+ import { type RunnerPortalHeartbeatSummary, type RunnerPortalSyncOptions, type RunnerPortalSyncSummary } from './portal-sync-worker.js';
12
+ import type { HeadlessAdapterRegistry } from './headless/adapters.js';
13
+ import type { HeadlessAdapterExecutionOptions } from './headless/types.js';
14
+ export { RUNNER_BINARY_REASON_CODES, checkRunnerBinaryTrust, runnerTrustRelativePath } from './binary.js';
15
+ export type { RunnerBinaryTrustResult } from './binary.js';
16
+ export { LOCAL_JOBS_CONSOLE_REASON_CODES, createLocalJobConsoleServer, isLocalJobsConsoleArgs, localJobConsoleSocketPath, parseLocalJobsConsoleArgs, runLocalJobsConsoleCommand, type LocalJobConsoleRegistration, type LocalJobsConsoleCommandResult, } from './local-console.js';
17
+ export declare const RUNNER_REASON_CODES: Readonly<{
18
+ readonly OK: "continuity-ok";
19
+ readonly LEASE_CONFLICT: "lease-conflict";
20
+ readonly LEASE_EXPIRED: "lease-expired";
21
+ readonly RUNNER_BINARY_UNTRUSTED: "runner-binary-untrusted";
22
+ readonly RUNNER_DIRECTIVE_UNTRUSTED: "runner-directive-untrusted";
23
+ readonly RUNNER_SERVER_INVOKE_FAILED: "runner-server-invoke-failed";
24
+ readonly SQLITE_ADAPTER_UNAVAILABLE: "sqlite-adapter-unavailable";
25
+ readonly SQLITE_INTEGRITY_FAILED: "sqlite-integrity-failed";
26
+ readonly BACKOFF_SCHEDULED: "backoff-scheduled";
27
+ readonly MISSED_RUN_CATCHUP: "missed-run-catchup";
28
+ readonly HEADLESS_RUNTIME_UNRESOLVED: "headless-runtime-unresolved";
29
+ readonly HEADLESS_RUNTIME_UNTRUSTED: "headless-runtime-untrusted";
30
+ readonly HEADLESS_ADAPTER_UNAVAILABLE: "headless-adapter-unavailable";
31
+ readonly HEADLESS_RUNTIME_AUTH_REQUIRED: "headless-runtime-auth-required";
32
+ readonly HEADLESS_EXECUTION_BACKOFF: "headless-execution-backoff";
33
+ readonly HEADLESS_EXECUTION_TIMEOUT: "headless-execution-timeout";
34
+ readonly HEADLESS_EXECUTION_FAILED: "headless-execution-failed";
35
+ readonly HEADLESS_RECEIPT_REDACTED: "headless-receipt-redacted";
36
+ readonly AUTONOMOUS_GOVERNANCE_BYPASS_BLOCKED: "headless-directive-rejected";
37
+ }>;
38
+ export type RunnerReasonCode = (typeof RUNNER_REASON_CODES)[keyof typeof RUNNER_REASON_CODES] | string;
39
+ export declare const DEFAULT_RUNNER_LEASE_MS: number;
40
+ export declare const DEFAULT_STALE_LEASE_AFTER_MS: number;
41
+ export declare const DEFAULT_RUNNER_BACKOFF_MS: number;
42
+ export declare const DEFAULT_DUE_JOB_LIMIT = 1;
43
+ export declare const MAX_DUE_JOB_LIMIT = 10;
44
+ export interface RunnerServerInvokeInput {
45
+ readonly projectRoot: string;
46
+ readonly args: string;
47
+ readonly jobId: string;
48
+ readonly tickId: string;
49
+ readonly leaseId: string;
50
+ readonly runnerId: string;
51
+ readonly serverUrl?: string;
52
+ }
53
+ export interface RunnerServerInvokeResult {
54
+ readonly success: boolean;
55
+ readonly instructions?: string;
56
+ readonly metadata?: Record<string, unknown>;
57
+ readonly error?: string;
58
+ readonly exitCode?: number;
59
+ }
60
+ export type RunnerServerInvoker = (input: RunnerServerInvokeInput) => Promise<RunnerServerInvokeResult>;
61
+ export interface RunnerTickOptions {
62
+ readonly projectRoot?: string;
63
+ readonly runnerId?: string;
64
+ readonly dueJobLimit?: number;
65
+ readonly leaseMs?: number;
66
+ readonly staleLeaseAfterMs?: number;
67
+ readonly now?: () => string;
68
+ readonly serverUrl?: string;
69
+ readonly adapter?: ContinuitySqliteAdapter;
70
+ readonly adapterLoader?: () => Promise<ContinuitySqliteAdapterLoadResult>;
71
+ readonly serverInvoker?: RunnerServerInvoker;
72
+ readonly idFactory?: (prefix: string, jobId: string) => string;
73
+ readonly trustCheck?: boolean;
74
+ readonly executablePath?: string;
75
+ readonly tickMode?: RunnerTickMode;
76
+ readonly processingSummarySource?: RunnerProcessingSummarySource;
77
+ readonly headlessAdapterRegistry?: HeadlessAdapterRegistry;
78
+ readonly headlessAdapterOptions?: HeadlessAdapterExecutionOptions;
79
+ readonly headlessRuntimeDefaults?: unknown;
80
+ readonly headlessRuntimeFallback?: unknown | false;
81
+ readonly headlessExecutionLimit?: number;
82
+ readonly headlessExecutionLeaseMs?: number;
83
+ readonly headlessExecutionStaleLeaseAfterMs?: number;
84
+ readonly headlessExecutionTimeoutMs?: number;
85
+ readonly headlessExecutionBackoffMs?: number;
86
+ readonly headlessExecutionMaxAttempts?: number;
87
+ readonly headlessExecutionQueueCap?: number;
88
+ readonly headlessExecutionIdFactory?: (prefix: string, attemptId: string) => string;
89
+ readonly headlessYoloopInvoker?: RunYoloopRootInvoker;
90
+ readonly headlessYoloopMaxIterations?: number;
91
+ readonly headlessYoloopMaxDurationMs?: number;
92
+ readonly headlessYoloopLocalConcurrencyCap?: number;
93
+ readonly portalSync?: false | RunnerPortalSyncOptions;
94
+ readonly portalSyncIntervalMs?: number;
95
+ readonly portalSyncMaxRuns?: number;
96
+ readonly portalHeartbeatIntervalMs?: number;
97
+ readonly portalHeartbeatBackoffMs?: number;
98
+ readonly portalHeartbeatJitterRatio?: number;
99
+ readonly portalHeartbeatTimeoutMs?: number;
100
+ readonly portalHeartbeatSessionId?: string;
101
+ }
102
+ export interface RunnerCliOptions extends RunnerTickOptions {
103
+ readonly scheduler?: Partial<RunnerSchedulerCommandOptions>;
104
+ }
105
+ export interface RunnerJobTickReceipt {
106
+ readonly jobId: string;
107
+ readonly tickId: string;
108
+ readonly leaseId?: string;
109
+ readonly outcome: 'applied' | 'failed' | 'ignored' | 'deferred';
110
+ readonly reasonCode: RunnerReasonCode;
111
+ readonly timestamp: string;
112
+ readonly redactionSummary: readonly string[];
113
+ readonly publicSafe: true;
114
+ }
115
+ export type RunnerTickMode = 'manual' | 'scheduled';
116
+ export type RunnerProcessingSummarySource = 'manual_tick' | 'scheduled_tick' | 'runner_tick';
117
+ export interface RunnerTickProcessingSummary {
118
+ readonly eventId: string;
119
+ readonly executionId: string;
120
+ readonly jobId: string;
121
+ readonly publicSummary: string;
122
+ readonly reasonCode?: RunnerReasonCode;
123
+ readonly createdAt: string;
124
+ readonly source: RunnerProcessingSummarySource;
125
+ readonly publicSafe: true;
126
+ }
127
+ export interface RunnerTickSummary {
128
+ readonly ok: boolean;
129
+ readonly runnerId: string;
130
+ readonly processedJobCount: number;
131
+ readonly dueJobCount: number;
132
+ readonly recoveredLeaseIds: readonly string[];
133
+ readonly receipts: readonly RunnerJobTickReceipt[];
134
+ readonly processingSummaries?: readonly RunnerTickProcessingSummary[];
135
+ readonly headlessExecution?: RunYoloExecutionPhaseSummary;
136
+ readonly headlessYoloopExecution?: RunYoloopExecutionPhaseSummary;
137
+ readonly portalSync?: RunnerPortalSyncSummary;
138
+ readonly portalHeartbeat?: RunnerPortalHeartbeatSummary;
139
+ readonly reasonCodes: readonly RunnerReasonCode[];
140
+ readonly publicSafe: true;
141
+ }
142
+ export interface RunnerDoctorCheck {
143
+ readonly id: 'db-integrity' | 'sqlite-wal' | 'migrations' | 'runner' | 'scheduler' | 'leases' | 'headless-execution' | 'outbox' | 'metering' | 'portal-sync';
144
+ readonly label: string;
145
+ readonly status: 'ok' | 'delegated' | 'degraded' | 'blocked';
146
+ readonly reasonCodes: readonly RunnerReasonCode[];
147
+ readonly summary: string;
148
+ readonly counts?: Readonly<Record<string, number>>;
149
+ readonly publicSafe: true;
150
+ }
151
+ export interface RunnerDoctorSummary {
152
+ readonly ok: boolean;
153
+ readonly generatedAt: string;
154
+ readonly checks: Readonly<Record<RunnerDoctorCheck['id'], RunnerDoctorCheck>>;
155
+ readonly reasonCodes: readonly RunnerReasonCode[];
156
+ readonly publicSafe: true;
157
+ }
158
+ interface RunnerDirective extends Record<string, unknown> {
159
+ readonly kind: string;
160
+ readonly commandClass?: string;
161
+ readonly publicSafe: true;
162
+ }
163
+ export declare function defaultRunnerServerInvoker(input: RunnerServerInvokeInput): Promise<RunnerServerInvokeResult>;
164
+ export declare function runRunnerTick(options?: RunnerTickOptions): Promise<RunnerTickSummary>;
165
+ export declare function runRunnerDoctor(options?: RunnerCliOptions): Promise<RunnerDoctorSummary>;
166
+ export declare function extractRunnerDirectives(metadata: Record<string, unknown> | undefined): readonly RunnerDirective[];
167
+ export declare function assertRunnerDirectiveTrusted(directive: unknown, jobId: string): asserts directive is RunnerDirective;
168
+ export declare function runRunnerCli(argv: readonly string[], options?: RunnerCliOptions): Promise<number>;
@@ -0,0 +1,70 @@
1
+ import{createHash as W,randomBytes as Ee}from"node:crypto";import{resolve as G}from"node:path";import{CONTINUITY_PROCESSING_OUTPUT_SUMMARY_EVENT_TYPE as X,ContinuitySqliteStoreError as Ie,openContinuitySqliteStore as Z}from"../continuity/sqlite-store.js";import{invoke as ye}from"../commands/invoke.js";import{checkRunnerBinaryTrust as P}from"./binary.js";import{runRunnerSchedulerCommand as ee}from"./scheduler.js";import{runYoloExecutionPhase as Se}from"./headless/run-yolo.js";import{runYoloopExecutionPhase as Re}from"./headless/run-yoloop.js";import{DEFAULT_RUNNER_HEARTBEAT_BACKOFF_MS as _e,DEFAULT_RUNNER_HEARTBEAT_INTERVAL_MS as ke,DEFAULT_RUNNER_HEARTBEAT_JITTER_RATIO as ge,DEFAULT_RUNNER_HEARTBEAT_TIMEOUT_MS as Ae,runRunnerPortalHeartbeat as V,runRunnerPortalHeartbeatLoop as ve,runRunnerPortalSync as te,runRunnerPortalSyncLoop as we}from"./portal-sync-worker.js";import{RUNNER_BINARY_REASON_CODES as Tt,checkRunnerBinaryTrust as jt,runnerTrustRelativePath as Nt}from"./binary.js";import{LOCAL_JOBS_CONSOLE_REASON_CODES as Dt,createLocalJobConsoleServer as Ot,isLocalJobsConsoleArgs as Mt,localJobConsoleSocketPath as xt,parseLocalJobsConsoleArgs as Ft,runLocalJobsConsoleCommand as Ht}from"./local-console.js";const d=Object.freeze({OK:"continuity-ok",LEASE_CONFLICT:"lease-conflict",LEASE_EXPIRED:"lease-expired",RUNNER_BINARY_UNTRUSTED:"runner-binary-untrusted",RUNNER_DIRECTIVE_UNTRUSTED:"runner-directive-untrusted",RUNNER_SERVER_INVOKE_FAILED:"runner-server-invoke-failed",SQLITE_ADAPTER_UNAVAILABLE:"sqlite-adapter-unavailable",SQLITE_INTEGRITY_FAILED:"sqlite-integrity-failed",BACKOFF_SCHEDULED:"backoff-scheduled",MISSED_RUN_CATCHUP:"missed-run-catchup",HEADLESS_RUNTIME_UNRESOLVED:"headless-runtime-unresolved",HEADLESS_RUNTIME_UNTRUSTED:"headless-runtime-untrusted",HEADLESS_ADAPTER_UNAVAILABLE:"headless-adapter-unavailable",HEADLESS_RUNTIME_AUTH_REQUIRED:"headless-runtime-auth-required",HEADLESS_EXECUTION_BACKOFF:"headless-execution-backoff",HEADLESS_EXECUTION_TIMEOUT:"headless-execution-timeout",HEADLESS_EXECUTION_FAILED:"headless-execution-failed",HEADLESS_RECEIPT_REDACTED:"headless-receipt-redacted",AUTONOMOUS_GOVERNANCE_BYPASS_BLOCKED:"headless-directive-rejected"}),Le=300*1e3,Ce=30*1e3,Te=30*1e3,je=1,Ne=10,Ue=new Set(["append_event","append_receipt","update_job_status","schedule_next_tick","release_lease","noop"]),De=new Set(["goal-tick","loop-tick","jobs","runner"]),Oe=new Set(["accepted","applied","ignored","failed","deferred"]),Me=new Set(["draft","planned","active","running","waiting_external","waiting_human","backoff","paused","blocked","completed","aborted","cancelled"]),xe=/(raw[_-]?logs?|prompt(?:[_-]?(?:body|text))?|private[_-]?urls?|secret|token|password|protected(?:[_-]?(?:field|body|internals))?|workflow(?:[_-]?body)?|step(?:[_-]?body)?|customer(?:[_-]?(?:pii|data))?|authorization|api[_-]?key|license[_-]?key)/i,q=/(https?:\/\/\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[_-]?log|transcript|stack trace|stderr:|stdout:|system prompt|workflow body|step body|PROTECTED_|PRIVATE_INTERNALS|CUSTOMER_PII|VENDOR_CORPUS|P180[_-]?SYNTHETIC[_-]?CONTINUITY|P187[_-]?SYNTHETIC[_-]?(?:CONTINUITY|RUNNER|WATCH))/i,re=new Set([d.HEADLESS_RUNTIME_UNRESOLVED,d.HEADLESS_RUNTIME_UNTRUSTED,"headless-model-rejected","headless-directive-rejected","headless-prompt-rejected","headless-yoloop-metadata-invalid","headless-yoloop-isolation-violation"]),oe=new Set([d.HEADLESS_ADAPTER_UNAVAILABLE]),ae=new Set([d.HEADLESS_RUNTIME_AUTH_REQUIRED]),se=new Set([d.HEADLESS_EXECUTION_BACKOFF]),ne=new Set([d.HEADLESS_EXECUTION_TIMEOUT]),ce=new Set([d.HEADLESS_EXECUTION_FAILED]);async function Fe(e){const t=await ye({args:e.args,projectRoot:e.projectRoot,format:"json",platformTarget:"runner",serverUrl:e.serverUrl});return{success:t.success,instructions:t.instructions,metadata:t.metadata,error:t.error,exitCode:t.exitCode}}async function He(e={}){const t=G(e.projectRoot??process.cwd()),r=Y(e.runnerId??nt(t)),o=e.now??(()=>new Date().toISOString()),a=F(e.dueJobLimit??je,1,Ne),s=F(e.leaseMs??Le,1e3,3600*1e3),l=F(e.staleLeaseAfterMs??Ce,0,1440*60*1e3),c=e.idFactory??ct,I=he(e.processingSummarySource??(e.tickMode==="scheduled"?"scheduled_tick":"manual_tick")),y=[],R=[],i=[],u=[];if(e.trustCheck!==!1){const A=P(e.executablePath??process.argv[1]);if(!A.trusted)return{ok:!1,runnerId:r,processedJobCount:0,dueJobCount:0,recoveredLeaseIds:[],receipts:[],reasonCodes:[A.reasonCode??d.RUNNER_BINARY_UNTRUSTED],publicSafe:!0}}const m=await Z({projectRoot:t,adapter:e.adapter,adapterLoader:e.adapterLoader,now:o}),L=Be({options:e,projectRoot:t,runnerId:r,now:o});let C;try{const A=m.recoverStaleLeases({nowIso:o(),staleAfterMs:l,limit:a*2});if(A.recoveredLeaseIds.length>0){y.push(d.LEASE_EXPIRED);for(const E of A.recoveredLeaseIds);}const T=m.listDueJobs({nowIso:o(),limit:a});for(const E of T){const g=await Ve({store:m,job:E,projectRoot:t,runnerId:r,leaseMs:s,now:o,idFactory:c,processingSummarySource:I,serverUrl:e.serverUrl,serverInvoker:e.serverInvoker??Fe});R.push(g.receipt),i.push(...g.processingSummaries),g.executionMetadata&&u.push(g.executionMetadata),y.push(g.receipt.reasonCode)}const b=await Se({store:m,projectRoot:t,runnerId:r,now:o,metadata:u,adapterRegistry:e.headlessAdapterRegistry,adapterOptions:e.headlessAdapterOptions,runtimeDefaults:e.headlessRuntimeDefaults,runtimeFallback:e.headlessRuntimeFallback,limit:e.headlessExecutionLimit,leaseMs:e.headlessExecutionLeaseMs??s,staleLeaseAfterMs:e.headlessExecutionStaleLeaseAfterMs??l,timeoutMs:e.headlessExecutionTimeoutMs,backoffMs:e.headlessExecutionBackoffMs,maxAttempts:e.headlessExecutionMaxAttempts,queueCap:e.headlessExecutionQueueCap,idFactory:e.headlessExecutionIdFactory});y.push(...b.reasonCodes);const k=await Re({store:m,projectRoot:t,runnerId:r,now:o,metadata:u,adapterRegistry:e.headlessAdapterRegistry,adapterOptions:e.headlessAdapterOptions,runtimeDefaults:e.headlessRuntimeDefaults,runtimeFallback:e.headlessRuntimeFallback,limit:e.headlessExecutionLimit,leaseMs:e.headlessExecutionLeaseMs??s,staleLeaseAfterMs:e.headlessExecutionStaleLeaseAfterMs??l,timeoutMs:e.headlessExecutionTimeoutMs,backoffMs:e.headlessExecutionBackoffMs,maxAttempts:e.headlessExecutionMaxAttempts,queueCap:e.headlessExecutionQueueCap,maxIterations:e.headlessYoloopMaxIterations,maxDurationMs:e.headlessYoloopMaxDurationMs,localConcurrencyCap:e.headlessYoloopLocalConcurrencyCap,yoloopInvoker:e.headlessYoloopInvoker,serverUrl:e.serverUrl,idFactory:e.headlessExecutionIdFactory});y.push(...k.reasonCodes),C={ok:R.every(E=>E.outcome!=="failed")&&b.ok&&k.ok,runnerId:r,processedJobCount:R.length,dueJobCount:T.length,recoveredLeaseIds:A.recoveredLeaseIds,receipts:R,...i.length>0?{processingSummaries:i}:{},headlessExecution:b,headlessYoloopExecution:k,reasonCodes:J(y.length>0?y:[d.OK]),publicSafe:!0}}finally{await L.stop(),m.close()}if(!C)throw new Error("runner-tick-failed");return await Pe(C,{options:e,projectRoot:t,runnerId:r,localStateChanged:$e(C)})}async function Pe(e,t){const r=t.options.portalSync;if(r===!1||r===void 0)return e;if(!t.localStateChanged){const a=await V({...r,projectRoot:r.projectRoot??t.projectRoot,runnerId:r.runnerId??t.runnerId,sessionId:r.sessionId??t.options.portalHeartbeatSessionId,serverUrl:r.serverUrl??t.options.serverUrl,adapter:r.adapter??t.options.adapter,adapterLoader:r.adapterLoader??t.options.adapterLoader,now:r.now??t.options.now,mode:r.mode??(t.options.tickMode==="scheduled"?"scheduled":"background"),timeoutMs:r.heartbeatTimeoutMs??t.options.portalHeartbeatTimeoutMs});return{...e,portalHeartbeat:a}}const o=await te({...r,projectRoot:r.projectRoot??t.projectRoot,runnerId:r.runnerId??t.runnerId,sessionId:r.sessionId??t.options.portalHeartbeatSessionId,serverUrl:r.serverUrl??t.options.serverUrl,adapter:r.adapter??t.options.adapter,adapterLoader:r.adapterLoader??t.options.adapterLoader,now:r.now??t.options.now,mode:r.mode??(t.options.tickMode==="scheduled"?"scheduled":"background")});return{...e,portalSync:o}}function $e(e){return e.recoveredLeaseIds.length>0||e.receipts.length>0||(e.processingSummaries?.length??0)>0||(e.headlessExecution?.processedAttemptCount??0)>0||(e.headlessExecution?.recoveredAttemptIds.length??0)>0||(e.headlessYoloopExecution?.processedAttemptCount??0)>0||(e.headlessYoloopExecution?.recoveredAttemptIds.length??0)>0}function Be(e){const t=e.options.portalSync;if(t===!1||t===void 0)return{stop:async()=>{}};const r=F(e.options.portalHeartbeatIntervalMs??ke,0,1440*60*1e3);if(r<=0)return{stop:async()=>{}};const o=F(e.options.portalHeartbeatBackoffMs??_e,1e3,1800*1e3),a=pe(e.options.portalHeartbeatJitterRatio??ge,0,.5),s=F(e.options.portalHeartbeatTimeoutMs??t.heartbeatTimeoutMs??Ae,1e3,6e4);let l=!1,c,I,y=me(r,a,Math.random);const R=u=>new Promise(m=>{I=m,c=setTimeout(m,u),typeof c.unref=="function"&&c.unref()}),i=(async()=>{for(;!l&&(y>0&&await R(y),!l);){const u=await V({...t,projectRoot:t.projectRoot??e.projectRoot,runnerId:t.runnerId??e.runnerId,sessionId:t.sessionId??e.options.portalHeartbeatSessionId,serverUrl:t.serverUrl??e.options.serverUrl,adapter:t.adapter??e.options.adapter,adapterLoader:t.adapterLoader??e.options.adapterLoader,now:t.now??e.now,mode:t.mode??(e.options.tickMode==="scheduled"?"scheduled":"background"),timeoutMs:s}).catch(()=>({ok:!1,runnerId:e.runnerId,workspaceId:"workspace-default",workspaceLabel:"Workspace workspace-default",projectId:"project-default",projectLabel:"Project project-default",mode:e.options.tickMode==="scheduled"?"scheduled":"background",generatedAt:e.now(),serverAccessToLocalhost:!1,serverHeldStream:!1,localhostCallback:!1,posted:{heartbeat:!1},counts:{redactions:0},reasonCodes:[d.BACKOFF_SCHEDULED],redactionEvidence:[],publicSafe:!0}));y=me(u.ok?r:o,a,Math.random)}})();return{stop:async()=>{l=!0,c&&clearTimeout(c),I?.(),await i.catch(()=>{})}}}async function Ke(e={}){const t=G(e.projectRoot??process.cwd()),r=e.now??(()=>new Date().toISOString()),o=r(),a={};let s=null,l=null;try{l=await Z({projectRoot:t,adapter:e.adapter,adapterLoader:e.adapterLoader,now:r}),s=l.collectSnapshotRows({nowIso:o,jobLimit:10,staleLeaseLimit:10,receiptLimit:10,eventLimit:10,snapshotLimit:5});const f=String(l.pragmaValue("journal_mode")??"").toLowerCase();a["db-integrity"]=w("db-integrity","DB integrity","ok",[d.OK],"Continuity SQLite integrity check completed.",{jobs:_(s.counts,"jobs"),receipts:_(s.counts,"receipts"),events:_(s.counts,"events")}),a["sqlite-wal"]=w("sqlite-wal","SQLite WAL",f==="wal"?"ok":"blocked",f==="wal"?[d.OK]:[d.SQLITE_INTEGRITY_FAILED],f==="wal"?"SQLite journal mode is WAL.":"SQLite journal mode is not WAL."),a.migrations=w("migrations","Migrations",s.schemaVersion>=1?"ok":"blocked",s.schemaVersion>=1?[d.OK]:[d.SQLITE_INTEGRITY_FAILED],`Continuity schema version ${s.schemaVersion} is readable.`)}catch(f){const p=ue(f);a["db-integrity"]=w("db-integrity","DB integrity","blocked",[p],"Continuity SQLite could not be opened safely."),a["sqlite-wal"]=w("sqlite-wal","SQLite WAL","blocked",[p],"SQLite WAL could not be verified."),a.migrations=w("migrations","Migrations","blocked",[p],"Continuity migrations could not be verified.")}finally{if(l)try{l.close()}catch{}}const c=s?_(s.counts,"staleLeases"):0,I=s?_(s.counts,"staleHeadlessExecutionAttempts"):0;a.leases=w("leases","Lease health",c+I>0?"degraded":"ok",c+I>0?[d.LEASE_EXPIRED]:[d.OK],c+I>0?"Stale job leases or headless execution attempts are eligible for bounded recovery.":"No stale leases or headless attempts reported.",{staleLeases:c,staleHeadlessExecutionAttempts:I});const y=s?.headlessExecutionAttempts??[],R=J(y.map(f=>f.reason_code).filter(f=>typeof f=="string"&&f.length>0)),i=ft(y,R),u=new Set([d.HEADLESS_RUNTIME_UNRESOLVED,d.HEADLESS_RUNTIME_UNTRUSTED,d.HEADLESS_ADAPTER_UNAVAILABLE,d.HEADLESS_RUNTIME_AUTH_REQUIRED,"headless-model-rejected","headless-directive-rejected","headless-prompt-rejected","headless-yoloop-metadata-invalid","headless-yoloop-isolation-violation"]),m=s?_(s.counts,"headlessExecutionAttempts"):0,L=R.some(f=>u.has(f)),C=R.includes(d.HEADLESS_EXECUTION_BACKOFF)||y.some(f=>f.status==="backoff"),A=R.includes(d.HEADLESS_RECEIPT_REDACTED),T=i.authRequired>0,b=i.trustFailures>0||i.adapterUnavailable>0,k=I>0||C||A||i.timeout>0||i.genericFailed>0||i.redactions>0;a["headless-execution"]=w("headless-execution","Headless execution",L?"blocked":k?"degraded":m>0?"ok":"delegated",R.length>0?R:m>0?[d.OK]:[d.HEADLESS_RUNTIME_UNRESOLVED],L?T&&!b?"Complete local runtime login/auth setup before starting a new headless attempt; default retry/backoff is not scheduled for auth-required.":"Resolve public runtime/model trust, adapter availability or protected directive hard-stop reason codes before executing headless attempts.":k?"Headless attempts need bounded recovery, retry/backoff, timeout/generic failure follow-up or redaction review.":m>0?"Headless attempts are represented by public status, runtime/model and reason-code evidence.":"Headless resolver checks are delegated until durable headless work is queued.",{attempts:m,queuedBackoff:s?_(s.counts,"headlessQueuedAttempts"):0,running:s?_(s.counts,"headlessRunningAttempts"):0,staleHeadlessExecutionAttempts:I,trustFailures:i.trustFailures,adapterUnavailable:i.adapterUnavailable,authRequired:i.authRequired,retryBackoff:i.retryBackoff,timeout:i.timeout,genericFailed:i.genericFailed,redactions:i.redactions});const E=s?.outboxCounts??{},g=_(E,"failed")+_(E,"dead_letter");a.outbox=w("outbox","Outbox state",g>0?"degraded":"ok",g>0?[d.BACKOFF_SCHEDULED]:[d.OK],g>0?"Failed/dead-letter outbox entries can be retried with dedupe.":"Outbox has no failed/dead-letter entries.",{pending:_(E,"pending"),failed:_(E,"failed"),deadLetter:_(E,"dead_letter")}),a.metering=w("metering","Metering receipts","ok",[d.OK],"Metering evidence is represented by public job receipts and counts only.",{receipts:s?_(s.counts,"receipts"):0}),a["portal-sync"]=w("portal-sync","Portal sync",g>0?"degraded":"ok",g>0?[d.BACKOFF_SCHEDULED]:[d.OK],g>0?"Portal sync worker is enabled but has retryable outbox debt; outbound sync remains client-owned.":"Portal sync worker is enabled for outbound heartbeat, jobs sync, command polling and acknowledgement only.",{pending:_(E,"pending"),failed:_(E,"failed"),deadLetter:_(E,"dead_letter")});const N=e.trustCheck===!1?{trusted:!0,publicSafe:!0}:P(e.executablePath??process.argv[1]);a.runner=w("runner","Runner health",N.trusted?"ok":"blocked",N.trusted?[d.OK]:[N.reasonCode??d.RUNNER_BINARY_UNTRUSTED],N.trusted?"Runner binary trust check passed.":"Runner binary trust check failed.");try{const f=await ee({command:"doctor",projectRoot:t,executablePath:e.scheduler?.executablePath??e.executablePath??process.argv[1],platform:e.scheduler?.platform,env:e.scheduler?.env,dryRun:!0,intervalSeconds:e.scheduler?.intervalSeconds,strategy:e.scheduler?.strategy,allowCronFallback:e.scheduler?.allowCronFallback,trustCheck:e.scheduler?.trustCheck??e.trustCheck,uid:e.scheduler?.uid,commandAvailable:e.scheduler?.commandAvailable,commandRunner:e.scheduler?.commandRunner,trustChecker:e.scheduler?.trustChecker??P}),p=f.reasonCodes.includes(d.RUNNER_BINARY_UNTRUSTED)||f.reasonCodes.some(h=>h.startsWith("runner-binary-"))||f.reasonCodes.includes("scheduler-install-unsafe");a.scheduler=w("scheduler","Scheduler install",p?"blocked":f.ok?"ok":"degraded",f.reasonCodes,f.ok?"Scheduler doctor selected a user-scope strategy.":"Scheduler doctor found public guidance or degraded capability.",{manifests:f.manifestPaths.length,controlCommands:f.controlCommands.length,legacyEntries:f.legacyEntries.length})}catch(f){a.scheduler=w("scheduler","Scheduler install","degraded",["scheduler-command-failed"],x(f))}const v=a,H=J(Object.values(v).flatMap(f=>f.reasonCodes));return{ok:Object.values(v).every(f=>f.status!=="blocked"),generatedAt:o,checks:v,reasonCodes:H,publicSafe:!0}}function de(e){if(!e)return[];const t=[e.continuityRunnerDirectives,e.runnerDirectives,e.continuityDirectives];for(const r of t)if(Array.isArray(r))return r.filter(j).map(it).filter(lt);return[]}function Je(e,t){if(!j(e))throw new U("Directive is not a public record.");if(e.publicSafe!==!0)throw new U("Directive is not marked public-safe.");const r=typeof e.kind=="string"?e.kind:typeof e.type=="string"?e.type:"";if(!Ue.has(r))throw new U("Directive kind is not allowlisted.");const o=typeof e.commandClass=="string"?e.commandClass:"runner";if(!De.has(o))throw new U("Directive command class is not allowlisted.");if((typeof e.jobId=="string"?e.jobId:t)!==t)throw new U("Directive job ID does not match the leased job.");Q(e,"directive")}async function wt(e,t={}){const r=tt(e);if(r.command==="help")return process.stdout.write(`${ot}
2
+ `),0;if(r.command==="version"){const o=P(t.executablePath??process.argv[1]);return process.stdout.write(`${o.packageVersion??"0.0.0"}
3
+ `),o.trusted?0:1}if(r.command==="doctor")try{const o=await Ke({...t,projectRoot:r.projectRoot??t.projectRoot,executablePath:t.executablePath??process.argv[1],scheduler:{...t.scheduler,strategy:r.strategy??t.scheduler?.strategy,allowCronFallback:r.allowCronFallback??t.scheduler?.allowCronFallback,executablePath:t.scheduler?.executablePath??t.executablePath??process.argv[1]}});return process.stdout.write(JSON.stringify(o)+`
4
+ `),o.ok?0:1}catch(o){return process.stderr.write(JSON.stringify({error_code:"runner-doctor-failed",message:x(o)})+`
5
+ `),1}if(le(r.command))try{const o=await ee({command:r.command,projectRoot:r.projectRoot??t.projectRoot,executablePath:t.scheduler?.executablePath??t.executablePath??process.argv[1],platform:t.scheduler?.platform,env:t.scheduler?.env,dryRun:r.dryRun??t.scheduler?.dryRun,intervalSeconds:r.intervalSeconds??t.scheduler?.intervalSeconds,strategy:r.strategy??t.scheduler?.strategy,allowCronFallback:r.allowCronFallback??t.scheduler?.allowCronFallback,trustCheck:t.scheduler?.trustCheck,uid:t.scheduler?.uid,commandAvailable:t.scheduler?.commandAvailable,commandRunner:t.scheduler?.commandRunner,trustChecker:t.scheduler?.trustChecker??P});return process.stdout.write(JSON.stringify(st(o))+`
6
+ `),o.ok?0:1}catch(o){return process.stderr.write(JSON.stringify({error_code:"scheduler-command-failed",message:x(o)})+`
7
+ `),1}if(r.command==="heartbeat")try{if(r.loop){const a=await ve({...t,projectRoot:r.projectRoot??t.projectRoot,runnerId:r.runnerId??t.runnerId,sessionId:r.sessionId??t.portalHeartbeatSessionId,serverUrl:r.serverUrl??t.serverUrl,workspaceId:r.workspaceId,workspaceLabel:r.workspaceLabel,projectId:r.projectId,projectLabel:r.projectLabel,mode:r.scheduled?"scheduled":"background",intervalMs:r.intervalMs??t.portalHeartbeatIntervalMs,maxRuns:r.maxRuns??t.portalSyncMaxRuns,backoffMs:r.heartbeatBackoffMs??t.portalHeartbeatBackoffMs,timeoutMs:r.heartbeatTimeoutMs??t.portalHeartbeatTimeoutMs,jitterRatio:r.heartbeatJitterRatio??t.portalHeartbeatJitterRatio});return process.stdout.write(JSON.stringify(a)+`
8
+ `),a.ok?0:1}const o=await V({...t,projectRoot:r.projectRoot??t.projectRoot,runnerId:r.runnerId??t.runnerId,sessionId:r.sessionId??t.portalHeartbeatSessionId,serverUrl:r.serverUrl??t.serverUrl,workspaceId:r.workspaceId,workspaceLabel:r.workspaceLabel,projectId:r.projectId,projectLabel:r.projectLabel,mode:r.scheduled?"scheduled":"manual",timeoutMs:r.heartbeatTimeoutMs??t.portalHeartbeatTimeoutMs});return process.stdout.write(JSON.stringify(o)+`
9
+ `),o.ok?0:1}catch(o){return process.stderr.write(JSON.stringify({error_code:"portal-heartbeat-failed",message:x(o)})+`
10
+ `),1}if(r.command==="sync")try{if(r.loop){const a=await we({...t,projectRoot:r.projectRoot??t.projectRoot,runnerId:r.runnerId??t.runnerId,serverUrl:r.serverUrl??t.serverUrl,workspaceId:r.workspaceId,workspaceLabel:r.workspaceLabel,projectId:r.projectId,projectLabel:r.projectLabel,syncCursor:r.syncCursor,mode:r.scheduled?"scheduled":"background",intervalMs:r.intervalMs??t.portalSyncIntervalMs,maxRuns:r.maxRuns??t.portalSyncMaxRuns});return process.stdout.write(JSON.stringify(a)+`
11
+ `),a.ok?0:1}const o=await te({...t,projectRoot:r.projectRoot??t.projectRoot,runnerId:r.runnerId??t.runnerId,serverUrl:r.serverUrl??t.serverUrl,workspaceId:r.workspaceId,workspaceLabel:r.workspaceLabel,projectId:r.projectId,projectLabel:r.projectLabel,syncCursor:r.syncCursor,mode:r.scheduled?"scheduled":"manual"});return process.stdout.write(JSON.stringify(o)+`
12
+ `),o.ok?0:1}catch(o){return process.stderr.write(JSON.stringify({error_code:"portal-sync-failed",message:x(o)})+`
13
+ `),1}if(r.command!=="tick")return process.stderr.write(JSON.stringify({error_code:"runner-command-unknown",message:"Unknown neocortex-runner command."})+`
14
+ `),1;try{const o=await He({...t,projectRoot:r.projectRoot??t.projectRoot,runnerId:r.runnerId??t.runnerId,dueJobLimit:r.limit??t.dueJobLimit,leaseMs:r.leaseMs??t.leaseMs,staleLeaseAfterMs:r.staleLeaseAfterMs??t.staleLeaseAfterMs,headlessYoloopLocalConcurrencyCap:r.yoloopLocalCap??t.headlessYoloopLocalConcurrencyCap,tickMode:r.scheduled?"scheduled":t.tickMode,processingSummarySource:r.scheduled?"scheduled_tick":t.processingSummarySource,serverUrl:r.serverUrl??t.serverUrl,portalSync:rt(r,t,r.scheduled?"scheduled":"background")});return process.stdout.write(JSON.stringify(o)+`
15
+ `),o.ok?0:1}catch(o){const a=ue(o);return process.stderr.write(JSON.stringify({error_code:a,message:x(o)})+`
16
+ `),1}}async function Ve(e){const{store:t,job:r,projectRoot:o,runnerId:a,leaseMs:s,now:l,idFactory:c,processingSummarySource:I,serverUrl:y,serverInvoker:R}=e,i=r.job_id,u=c("tick",i),m=c("lease",i),L=l(),C=new Date(Date.parse(L)+s).toISOString();let A=!1,T=!1,b=d.OK,k="applied",E=[];if(!t.acquireLease({leaseId:m,jobId:i,runnerId:a,acquiredAt:L,expiresAt:C,operationId:`${u}:acquire`,idempotencyKey:`${u}:acquire`,metadata:M({jobId:i,operationId:u,runnerId:a,leaseId:m,status:"running",reasonCode:d.OK})}).inserted)return{receipt:K(t,{jobId:i,tickId:u,leaseId:m,status:"ignored",reasonCode:d.LEASE_CONFLICT,createdAt:l(),redactionSummary:E}),processingSummaries:[]};A=!0;try{t.appendEvent({eventId:`${u}:started`,jobId:i,operationId:`${u}:event:started`,idempotencyKey:`${u}:event:started`,type:"runner_tick_started",summary:`Runner tick started for ${i}.`,reasonCode:d.OK,createdAt:L,metadata:M({jobId:i,operationId:u,runnerId:a,leaseId:m,status:"running",reasonCode:d.OK})});const N=r.kind==="loop"?`*loop tick @${i} --tick-id ${u} --lease-id ${m} --runner-id ${a}`:r.kind==="goal"?`*goal tick @${i} --tick-id ${u} --lease-id ${m} --runner-id ${a}`:`*runner tick --job-id ${i} --tick-id ${u} --lease-id ${m} --runner-id ${a}`,v=await R({projectRoot:o,args:N,jobId:i,tickId:u,leaseId:m,runnerId:a,serverUrl:y});if(!v.success){b=d.RUNNER_SERVER_INVOKE_FAILED,k="failed";const O=l();return t.updateJobStatus({jobId:i,status:"backoff",updatedAt:O,reasonCode:d.BACKOFF_SCHEDULED,nextRunAt:dt(O,Te)}),t.appendEvent({eventId:`${u}:server-failed`,jobId:i,operationId:`${u}:event:server-failed`,idempotencyKey:`${u}:event:server-failed`,type:"runner_tick_failed",summary:"Runner server tick invocation failed with public reason code.",reasonCode:b,createdAt:O,metadata:M({jobId:i,operationId:u,runnerId:a,leaseId:m,status:"failed",reasonCode:b})}),{receipt:K(t,{jobId:i,tickId:u,leaseId:m,status:k,reasonCode:b,createdAt:l(),redactionSummary:E}),processingSummaries:[]}}const f=de(v.metadata).filter(O=>!ie(O));let p={appliedCount:0,releasedLease:!1,changedStatus:!1,redactionSummary:[]};try{p=qe(t,f,{jobId:i,tickId:u,leaseId:m,runnerId:a,now:l}),T=p.releasedLease,E=[...p.redactionSummary],b=et(v.metadata)??b}catch(O){return b=d.RUNNER_DIRECTIVE_UNTRUSTED,k="failed",E=[O instanceof Error?O.message:"Directive rejected."],t.updateJobStatus({jobId:i,status:"blocked",updatedAt:l(),reasonCode:b}),t.appendEvent({eventId:`${u}:directive-rejected`,jobId:i,operationId:`${u}:event:directive-rejected`,idempotencyKey:`${u}:event:directive-rejected`,type:"runner_directive_rejected",summary:"Runner rejected an untrusted continuity directive.",reasonCode:b,createdAt:l(),metadata:M({jobId:i,operationId:u,runnerId:a,leaseId:m,status:"failed",reasonCode:b,redactionSummary:E})}),{receipt:K(t,{jobId:i,tickId:u,leaseId:m,status:k,reasonCode:b,createdAt:l(),redactionSummary:E}),processingSummaries:[]}}const h=Ye(t,v.metadata,{jobId:i,tickId:u,leaseId:m,runnerId:a,source:I,createdAt:l()}),S=!!v.metadata?.continuityStateUpdate;return!p.changedStatus&&!S&&t.updateJobStatus({jobId:i,status:"active",updatedAt:l(),reasonCode:d.OK}),t.appendEvent({eventId:`${u}:completed`,jobId:i,operationId:`${u}:event:completed`,idempotencyKey:`${u}:event:completed`,type:"runner_tick_completed",summary:`Runner tick completed with ${p.appliedCount} public directive(s).`,reasonCode:b,createdAt:l(),metadata:M({jobId:i,operationId:u,runnerId:a,leaseId:m,status:"applied",reasonCode:b})}),{receipt:K(t,{jobId:i,tickId:u,leaseId:m,status:k,reasonCode:b,createdAt:l(),redactionSummary:E}),processingSummaries:h,...v.metadata?{executionMetadata:v.metadata}:{}}}finally{if(A&&!T)try{t.releaseLease({leaseId:m,releasedAt:l(),reasonCode:b})}catch{}}}function qe(e,t,r){let o=0,a=!1,s=!1;const l=[];for(const c of t){switch(Je(c,r.jobId),c.kind){case"noop":o+=1;break;case"append_event":e.appendEvent({eventId:n(c,"eventId")??`${r.tickId}:directive:${o}:event`,jobId:r.jobId,operationId:n(c,"operationId")??`${r.tickId}:directive:${o}:event`,idempotencyKey:n(c,"idempotencyKey")??`${r.tickId}:directive:${o}:event`,type:n(c,"eventType")??"runner_directive_event",summary:n(c,"summary")??"Runner applied public continuity event directive.",reasonCode:n(c,"reasonCode")??d.OK,createdAt:n(c,"createdAt")??r.now(),metadata:fe(c)}),o+=1;break;case"append_receipt":e.appendReceipt({receiptId:n(c,"receiptId")??`${r.tickId}:directive:${o}:receipt`,jobId:r.jobId,operationId:n(c,"operationId")??`${r.tickId}:directive:${o}:receipt`,idempotencyKey:n(c,"idempotencyKey")??`${r.tickId}:directive:${o}:receipt`,status:pt(n(c,"status")),reasonCode:n(c,"reasonCode")??d.OK,createdAt:n(c,"createdAt")??r.now(),metadata:fe(c)}),o+=1;break;case"update_job_status":e.updateJobStatus({jobId:r.jobId,status:mt(n(c,"status")),updatedAt:n(c,"updatedAt")??r.now(),reasonCode:n(c,"reasonCode")??d.OK,nextRunAt:n(c,"nextRunAt")}),o+=1,s=!0;break;case"schedule_next_tick":e.scheduleNextTick({jobId:r.jobId,scheduledAt:ut(c,"scheduledAt"),updatedAt:n(c,"updatedAt")??r.now(),reasonCode:n(c,"reasonCode")??d.OK}),o+=1,s=!0;break;case"release_lease":e.releaseLease({leaseId:n(c,"leaseId")??r.leaseId,releasedAt:n(c,"releasedAt")??r.now(),reasonCode:n(c,"reasonCode")??d.OK}),o+=1,a=!0;break}const I=c.redactionSummary;Array.isArray(I)&&l.push(...I.filter(y=>typeof y=="string").slice(0,5))}return{appliedCount:o,releasedLease:a,changedStatus:s,redactionSummary:l}}function Ye(e,t,r){const o=[],a=new Set;for(const s of Qe(t)){const l=ze(s,r);if(!(!l||a.has(l.executionId))){a.add(l.executionId);try{e.recordProcessingOutputSummary(l),o.push(Xe(l))}catch(c){if(c instanceof Ie&&c.code==="sqlite-public-safety-rejected")continue;throw c}}}return o}function Qe(e){if(!e)return[];const t=[],r=D(e,"continuityStateUpdate"),o=$(r,"operations");for(const a of o){if(!j(a))continue;const s=D(a,"event");!s||n(s,"type")!==X||t.push({operation:a,event:s,summary:D(s,"processingOutputSummary")??s})}for(const a of de(e))ie(a)&&t.push({directive:a,event:a,summary:D(a,"processingOutputSummary")??a});for(const a of[...$(e,"processingSummaries"),...$(e,"processingOutputSummaries"),...$(e,"continuityProcessingSummaries"),...$(D(e,"continuity"),"processingSummaries")])j(a)&&t.push({event:a,summary:a});return t}function ze(e,t){if(!We(e))return null;const r=e.event??{},o=e.summary??r,a=e.operation??{},s=e.directive??{},l=n(o,"executionId")??n(r,"executionId")??n(a,"operationId")??n(s,"operationId")??t.tickId,c=n(o,"jobId")??n(r,"jobId")??n(a,"jobId")??n(s,"jobId")??t.jobId;if(c!==t.jobId)return null;const I=n(o,"publicSummary")??n(r,"publicSummary")??n(r,"summary")??n(s,"summary");if(!l||!I)return null;const y=Ge(D(a,"metadata"),D(r,"metadata"),D(o,"metadata"),D(s,"metadata"),{schemaVersion:1,contractVersion:"continuity-v1",executionId:l,jobId:c,operationId:l,runnerId:t.runnerId,leaseId:t.leaseId,processingOutputSource:t.source,publicSummary:I});return{eventId:n(r,"eventId")??n(o,"eventId")??n(s,"eventId"),executionId:l,jobId:c,idempotencyKey:n(a,"idempotencyKey")??n(s,"idempotencyKey")??l,goalId:n(o,"goalId")??n(r,"goalId")??n(a,"goalId"),loopId:n(o,"loopId")??n(r,"loopId")??n(a,"loopId"),publicSummary:I,reasonCode:n(o,"reasonCode")??n(r,"reasonCode")??n(a,"reasonCode")??n(s,"reasonCode"),createdAt:n(o,"createdAt")??n(r,"createdAt")??n(a,"createdAt")??n(s,"createdAt")??t.createdAt,source:t.source,metadata:y}}function ie(e){return e.kind==="append_event"&&(n(e,"eventType")??n(e,"type"))===X}function We(e){const t=[e.operation,e.event,e.summary,e.directive].filter(r=>!!r).map(r=>r.publicSafe);return t.some(r=>r===!1)?!1:t.some(r=>r===!0)}function Ge(...e){const t={};for(const r of e)r&&Object.assign(t,r);return t}function Xe(e){return{eventId:e.eventId??Ze(e.executionId),executionId:e.executionId,jobId:e.jobId,publicSummary:e.publicSummary,...e.reasonCode?{reasonCode:e.reasonCode}:{},createdAt:e.createdAt,source:he(e.source),publicSafe:!0}}function Ze(e){const t=e.replace(/[^a-z0-9_.:-]+/gi,"-").replace(/^-+|-+$/g,"");return t.length>0?`event-processing-summary-${t.slice(0,160)}`:`event-processing-summary-${W("sha256").update(e).digest("hex").slice(0,32)}`}function K(e,t){const r={receiptId:`receipt-${Y(t.tickId)}`,jobId:t.jobId,operationId:t.tickId,idempotencyKey:t.tickId,status:t.status,reasonCode:t.reasonCode,appliedOperationIds:t.status==="applied"?[t.tickId]:void 0,ignoredOperationIds:t.status==="ignored"?[t.tickId]:void 0,createdAt:t.createdAt,metadata:M({jobId:t.jobId,operationId:t.tickId,leaseId:t.leaseId,status:t.status,reasonCode:t.reasonCode,redactionSummary:t.redactionSummary})};return e.appendReceipt(r),{jobId:t.jobId,tickId:t.tickId,leaseId:t.leaseId,outcome:t.status,reasonCode:t.reasonCode,timestamp:t.createdAt,redactionSummary:t.redactionSummary,publicSafe:!0}}function M(e){return{schemaVersion:1,contractVersion:"continuity-v1",jobId:e.jobId,operationId:e.operationId,...e.runnerId?{runnerId:e.runnerId}:{},...e.leaseId?{leaseId:e.leaseId}:{},status:e.status,reasonCode:e.reasonCode,redactionEvidence:(e.redactionSummary??[]).slice(0,20).map(t=>({field:z(t,80),reason:"unsafe_key",evidence:"operation-denied",publicSafe:!0}))}}function et(e){if(!e)return null;const t=j(e.continuity)?e.continuity:void 0,r=t&&j(t.loop)?t.loop:void 0,o=t&&j(t.goal)?t.goal:void 0,a=[r?.reasonCode,o?.reasonCode,t?.reasonCode];for(const s of a)if(typeof s=="string"&&/^[a-z0-9][a-z0-9-]{0,79}$/.test(s)&&!q.test(s))return s;return null}function tt(e){const t=e[0];if(!t||t==="--help"||t==="-h"||t==="help")return{command:"help"};if(t==="--version"||t==="-v"||t==="version")return{command:"version"};if(t!=="tick"&&t!=="sync"&&t!=="heartbeat"&&!le(t))return{command:"unknown"};let r,o,a,s,l,c,I,y,R,i,u,m,L,C,A,T,b,k,E,g,N,v,H,f;for(let p=1;p<e.length;p++){const h=e[p],S=e[p+1];if(h==="--project-root"){r=S,p+=1;continue}if(h==="--runner-id"){o=S,p+=1;continue}if(h==="--server-url"){a=S,p+=1;continue}if(h==="--limit"){s=Number(S),p+=1;continue}if(h==="--lease-ms"){l=Number(S),p+=1;continue}if(h==="--stale-lease-after-ms"){c=Number(S),p+=1;continue}if(h==="--dry-run"){I=!0;continue}if(h==="--interval-seconds"){y=Number(S),p+=1;continue}if(h==="--interval-ms"){R=Number(S),p+=1;continue}if(h==="--max-runs"){i=Number(S),p+=1;continue}if(h==="--backoff-ms"){u=Number(S),p+=1;continue}if(h==="--heartbeat-timeout-ms"||h==="--timeout-ms"){m=Number(S),p+=1;continue}if(h==="--jitter-ratio"){L=Number(S),p+=1;continue}if(h==="--session-id"){C=S,p+=1;continue}if(h==="--strategy"&&at(S)){A=S,p+=1;continue}if(h==="--allow-cron-fallback"){T=!0;continue}if(h==="--no-cron-fallback"){T=!1;continue}if(h==="--scheduled"){b=!0;continue}if(h==="--manual"){b=!1;continue}if(h==="--loop"||h==="--background"){k=!0;continue}if(h==="--once"){k=!1;continue}if(h==="--workspace-id"){E=S,p+=1;continue}if(h==="--workspace-label"){g=S,p+=1;continue}if(h==="--project-id"){N=S,p+=1;continue}if(h==="--project-label"){v=S,p+=1;continue}if(h==="--sync-cursor"){H=S,p+=1;continue}if(h==="--yoloop-local-cap"){f=Number(S),p+=1;continue}}return{command:t,projectRoot:r,runnerId:o,serverUrl:a,limit:s,leaseMs:l,staleLeaseAfterMs:c,dryRun:I,intervalSeconds:y,intervalMs:R,maxRuns:i,heartbeatBackoffMs:u,heartbeatTimeoutMs:m,heartbeatJitterRatio:L,sessionId:C,strategy:A,allowCronFallback:T,scheduled:b,loop:k,workspaceId:E,workspaceLabel:g,projectId:N,projectLabel:v,syncCursor:H,yoloopLocalCap:f}}function rt(e,t,r){return t.portalSync===!1?!1:{...t.portalSync??{},...e.projectRoot??t.projectRoot?{projectRoot:e.projectRoot??t.projectRoot}:{},...e.runnerId??t.runnerId?{runnerId:e.runnerId??t.runnerId}:{},...e.sessionId??t.portalHeartbeatSessionId?{sessionId:e.sessionId??t.portalHeartbeatSessionId}:{},...e.serverUrl??t.serverUrl?{serverUrl:e.serverUrl??t.serverUrl}:{},...e.workspaceId?{workspaceId:e.workspaceId}:{},...e.workspaceLabel?{workspaceLabel:e.workspaceLabel}:{},...e.projectId?{projectId:e.projectId}:{},...e.projectLabel?{projectLabel:e.projectLabel}:{},...e.heartbeatTimeoutMs??t.portalHeartbeatTimeoutMs?{heartbeatTimeoutMs:e.heartbeatTimeoutMs??t.portalHeartbeatTimeoutMs}:{},mode:r}}const ot=`
17
+ neocortex-runner - Enterprise continuity local runner
18
+
19
+ Usage:
20
+ neocortex-runner install [--project-root <path>] [--strategy <strategy>] [--interval-seconds <n>] [--dry-run]
21
+ neocortex-runner start|stop|status [--project-root <path>] [--strategy <strategy>] [--dry-run]
22
+ neocortex-runner doctor [--project-root <path>] [--strategy <strategy>]
23
+ neocortex-runner tick [--project-root <path>] [--limit <n>] [--lease-ms <ms>] [--stale-lease-after-ms <ms>] [--yoloop-local-cap <1..10>] [--workspace-id <id>] [--workspace-label <label>] [--project-id <id>] [--project-label <label>] [--scheduled]
24
+ neocortex-runner heartbeat [--project-root <path>] [--runner-id <id>] [--session-id <id>] [--workspace-id <id>] [--project-id <id>] [--scheduled]
25
+ neocortex-runner heartbeat --loop [--interval-ms <ms>] [--backoff-ms <ms>] [--jitter-ratio <n>] [--heartbeat-timeout-ms <ms>] [--max-runs <n>] [--project-root <path>]
26
+ neocortex-runner sync [--project-root <path>] [--runner-id <id>] [--server-url <url>] [--workspace-id <id>] [--workspace-label <label>] [--project-id <id>] [--project-label <label>] [--scheduled]
27
+ neocortex-runner sync --loop [--interval-ms <ms>] [--max-runs <n>] [--project-root <path>]
28
+ neocortex-runner --version
29
+ neocortex-runner --help
30
+
31
+ Portal sync evidence:
32
+ heartbeat posts only a public runner_heartbeat with bounded counts, status,
33
+ runner/session/workspace/project IDs and timestamps. sync posts outbound
34
+ runner_heartbeat plus runner_sync summaries, polls queued Portal commands,
35
+ applies only allowlisted local controls, and acknowledges with public command
36
+ IDs, statuses, reason codes, bounded counts and timestamps. The server never
37
+ holds a stream, never calls localhost, and never stores local executable paths
38
+ or argv/runtime selection details.
39
+
40
+ Watch public processing summaries:
41
+ neocortex-client invoke --args '*jobs watch @job-J001' --watch
42
+ neocortex-client invoke --args '*jobs watch @goal-G001 --watch' --format json
43
+ neocortex-client invoke --args '*jobs watch @loop-L001' --watch
44
+
45
+ Local raw console (Plane B):
46
+ neocortex-client invoke --args '*jobs console @job-J001'
47
+ The console is foreground and local-only. It attaches to the runner-owned child
48
+ process when present, streams raw stdout/stderr only in the operator terminal,
49
+ gates stdin behind explicit local confirmation, and offers /pause, /resume and
50
+ /cancel without any hosted raw-output transport.
51
+
52
+ Watch evidence:
53
+ Select only the explicit Neocortex command payload for --args. Active watch
54
+ uses serverHeldStream=false foreground local SQLite polling and reports target
55
+ resolution, target kind/id, related job counts, snapshot counts, cursor/event
56
+ evidence and stop reasons. JSON without active watch stays one document;
57
+ active JSON watch is typed NDJSON with watch_status and processing_summary
58
+ records.
59
+
60
+ Headless durable examples:
61
+ neocortex-client invoke --args '*goal --plan "prepare synthetic release evidence" --headless-runtime opencode --headless-model openai/gpt-5.5'
62
+ neocortex-client invoke --args '*loop 10m "continue synthetic release" --headless-runtime claude-code --headless-model sonnet'
63
+
64
+ Headless doctor evidence:
65
+ Resolver order is explicit flags, persisted origin runtime/model, safe defaults,
66
+ safe fallback, then a public hard-stop. Doctor/watch/status/logs surfaces render
67
+ only bounded attempt status, runtime/model IDs, counts, reason codes, cursors and
68
+ redaction counts; raw adapter stdout/stderr, prompts, transcripts, private URLs,
69
+ local absolute paths, secrets and vendor payloads are never printed.
70
+ `.trim();function le(e){return e==="install"||e==="start"||e==="stop"||e==="status"||e==="doctor"}function at(e){return e==="systemd-user"||e==="launchd-user"||e==="windows-task-scheduler"||e==="cron-fallback"}class U extends Error{constructor(t){super(t),this.name="RunnerDirectiveError"}}function ue(e){if(j(e)){const r=typeof e.reasonCode=="string"?e.reasonCode:typeof e.code=="string"?e.code:void 0;if(r===d.SQLITE_ADAPTER_UNAVAILABLE||r===d.SQLITE_INTEGRITY_FAILED)return r}const t=e instanceof Error?e.message:String(e);return/sqlite-adapter-unavailable/i.test(t)?d.SQLITE_ADAPTER_UNAVAILABLE:/sqlite-integrity-failed|not a database|file is not a database|database disk image is malformed|malformed/i.test(t)?d.SQLITE_INTEGRITY_FAILED:"runner-tick-failed"}function x(e){return z(e instanceof Error?e.message:String(e),240)}function st(e){return e.manifests.length===0?e:{...e,manifests:e.manifests.map(t=>({...t,content:`[redacted ${t.kind} for project ${e.identity.projectKey}]`}))}}function nt(e){return`runner-${W("sha256").update(e).update(process.pid.toString()).digest("hex").slice(0,12)}`}function ct(e,t){const r=Ee(4).toString("hex");return`${e}-${Y(t)}-${Date.now()}-${r}`}function Y(e){return e.replace(/[^a-z0-9_.:-]+/gi,"-").slice(0,120)}function F(e,t,r){return Number.isFinite(e)?Math.max(t,Math.min(r,Math.floor(e))):t}function pe(e,t,r){return Number.isFinite(e)?Math.max(t,Math.min(r,e)):t}function me(e,t,r){if(e<=0)return 0;if(t<=0)return e;const o=pe(r(),0,1);return Math.max(0,e+Math.floor(e*t*o))}function dt(e,t){const r=Date.parse(e);return new Date((Number.isFinite(r)?r:Date.now())+t).toISOString()}function it(e){return typeof e.kind=="string"?e:{...e,kind:e.type}}function lt(e){return typeof e.kind=="string"&&e.publicSafe===!0}function Q(e,t){if(typeof e=="string"){if(q.test(e))throw new U(`Unsafe directive value at ${t}.`);return}if(!(e===null||typeof e=="number"||typeof e=="boolean")){if(Array.isArray(e)){e.forEach((r,o)=>Q(r,`${t}[${o}]`));return}if(j(e)){for(const[r,o]of Object.entries(e)){if(xe.test(r))throw new U(`Unsafe directive key at ${t}.${r}.`);Q(o,`${t}.${r}`)}return}throw new U(`Unsupported directive value at ${t}.`)}}function n(e,t){const r=e[t];return typeof r=="string"&&r.length>0?r:void 0}function ut(e,t){const r=n(e,t);if(!r)throw new U(`Directive missing ${t}.`);return r}function fe(e){const t=e.metadata;return j(t)?t:void 0}function D(e,t){if(!e)return;const r=e[t];return j(r)?r:void 0}function $(e,t){if(!e)return[];const r=e[t];return Array.isArray(r)?r:[]}function pt(e){return e&&Oe.has(e)?e:"applied"}function mt(e){if(!e||!Me.has(e))throw new U("Directive status is not allowlisted.");return e}function he(e){return e==="scheduled_tick"||e==="runner_tick"||e==="manual_tick"?e:"manual_tick"}function j(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function J(e){return Array.from(new Set(e))}function _(e,t){return typeof e[t]=="number"?e[t]:0}function ft(e,t){return{trustFailures:B(e,t,re),adapterUnavailable:B(e,t,oe),authRequired:B(e,t,ae),retryBackoff:B(e,t,se,new Set(["backoff"])),timeout:B(e,t,ne,new Set(["timed_out"])),genericFailed:ht(e,t),redactions:e.reduce((r,o)=>r+bt(o),0)}}function B(e,t,r,o=new Set){const a=e.filter(s=>(s.reason_code?r.has(s.reason_code):!1)||o.has(s.status)).length;return a>0?a:t.some(s=>r.has(s))?1:0}function ht(e,t){const r=e.filter(o=>o.reason_code&&ce.has(o.reason_code)?!0:o.status!=="failed"?!1:!o.reason_code||!re.has(o.reason_code)&&!oe.has(o.reason_code)&&!ae.has(o.reason_code)&&!se.has(o.reason_code)&&!ne.has(o.reason_code)).length;return r>0?r:t.some(o=>ce.has(o))?1:0}function bt(e){if(!e.redaction_summary_json)return 0;try{const t=JSON.parse(e.redaction_summary_json);return Array.isArray(t)?t.length:0}catch{return 0}}function w(e,t,r,o,a,s){return{id:e,label:t,status:r,reasonCodes:J(o.length>0?o:[d.OK]),summary:z(a,180),...s?{counts:s}:{},publicSafe:!0}}function z(e,t){const r=q.test(e)?"[REDACTED]":e;return r.length<=t?r:`${r.slice(0,t)}\u2026[TRUNCATED:${r.length-t}]`}export{je as DEFAULT_DUE_JOB_LIMIT,Te as DEFAULT_RUNNER_BACKOFF_MS,Le as DEFAULT_RUNNER_LEASE_MS,Ce as DEFAULT_STALE_LEASE_AFTER_MS,Dt as LOCAL_JOBS_CONSOLE_REASON_CODES,Ne as MAX_DUE_JOB_LIMIT,Tt as RUNNER_BINARY_REASON_CODES,d as RUNNER_REASON_CODES,Je as assertRunnerDirectiveTrusted,jt as checkRunnerBinaryTrust,Ot as createLocalJobConsoleServer,Fe as defaultRunnerServerInvoker,de as extractRunnerDirectives,Mt as isLocalJobsConsoleArgs,xt as localJobConsoleSocketPath,Ft as parseLocalJobsConsoleArgs,Ht as runLocalJobsConsoleCommand,wt as runRunnerCli,Ke as runRunnerDoctor,He as runRunnerTick,Nt as runnerTrustRelativePath};
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @license FSL-1.1
3
+ * Copyright (c) 2026 OrNexus AI
4
+ *
5
+ * P190.04 -- allowlisted headless adapter registry.
6
+ */
7
+ import { type HeadlessAdapter, type HeadlessAdapterId, type HeadlessAdapterRejectedResult } from './types.js';
8
+ export type HeadlessAdapterRegistryLookup = {
9
+ readonly ok: true;
10
+ readonly adapter: HeadlessAdapter;
11
+ readonly publicSafe: true;
12
+ } | HeadlessAdapterRejectedResult;
13
+ export declare class HeadlessAdapterRegistry {
14
+ private readonly adapters;
15
+ constructor(adapters: readonly HeadlessAdapter[]);
16
+ listAdapterIds(): readonly HeadlessAdapterId[];
17
+ hasAdapter(id: string): boolean;
18
+ getAdapter(id: string): HeadlessAdapterRegistryLookup;
19
+ }
20
+ export declare function createDefaultHeadlessAdapterRegistry(): HeadlessAdapterRegistry;
@@ -0,0 +1 @@
1
+ import{HEADLESS_ADAPTER_IDS as o,HEADLESS_REASON_CODES as s,isHeadlessAdapterId as a,redaction as p}from"./types.js";import{createClaudeCodeHeadlessAdapter as i}from"./claude-code-adapter.js";import{createFakeHeadlessAdapter as d}from"./fake-adapter.js";import{createOpenCodeHeadlessAdapter as n}from"./opencode-adapter.js";class u{adapters;constructor(e){const r=new Map;for(const t of e)a(t.id)&&r.set(t.id,t);this.adapters=r}listAdapterIds(){return o.filter(e=>this.adapters.has(e))}hasAdapter(e){return a(e)&&this.adapters.has(e)}getAdapter(e){return!a(e)||!this.adapters.has(e)?{ok:!1,reasonCode:s.RUNTIME_UNTRUSTED,reasonCodes:[s.RUNTIME_UNTRUSTED],publicSummary:"Headless adapter id is not allowlisted.",redactionSummary:[p("runtimeId","unsafe_key","value-denied")],publicSafe:!0}:{ok:!0,adapter:this.adapters.get(e),publicSafe:!0}}}function S(){return new u([d("fake"),d("test"),n(),i()])}export{u as HeadlessAdapterRegistry,S as createDefaultHeadlessAdapterRegistry};
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @license FSL-1.1
3
+ * Copyright (c) 2026 OrNexus AI
4
+ *
5
+ * P190.04 -- trusted Claude Code headless adapter interface.
6
+ */
7
+ import { type HeadlessAdapter } from './types.js';
8
+ export declare function createClaudeCodeHeadlessAdapter(): HeadlessAdapter;
@@ -0,0 +1 @@
1
+ import{createRejectedExecutionResult as c,createUnavailableExecutionResult as l,normalizeHeadlessCommandResult as s,runHeadlessCommand as p,validateHeadlessAdapterExecutionInput as r}from"./types.js";import{checkRuntimeAvailability as m}from"./opencode-adapter.js";const a="claude-code",o="claude";function f(){return{id:a,displayName:"Claude Code Headless Adapter",async checkAvailability(i={}){return m(a,o,i,{realpathBasenamePolicy:"claude-code-versioned",versionEvidence:"claude-code"})},buildInvocation(i){const e=r(i,a);return e.ok?{ok:!0,invocation:{adapterId:a,commandName:o,args:v(e.prompt,e.input.modelId),promptHash:e.promptHash,...e.input.modelId?{modelId:e.input.modelId}:{},timeoutMs:e.input.timeoutMs??600*1e3,publicSafe:!0},publicSafe:!0}:e},async execute(i,e={}){const t=r(i,a);if(!t.ok)return c(a,a,t);const u=await this.checkAvailability(e);if(!u.ok)return l(a,t.input,u);const n=this.buildInvocation(t.input);if(!n.ok)return c(a,a,n);const d=await(e.commandRunner??p)(u.executablePath??o,n.invocation.args,{cwd:e.cwd,env:e.env,timeoutMs:n.invocation.timeoutMs,maxOutputBytes:e.maxOutputBytes,...t.input.receipt?.jobId?{localConsole:{projectRoot:e.cwd,jobId:t.input.receipt.jobId,attemptId:t.input.receipt.attemptId,executionId:t.input.receipt.executionId,publicSafe:!0}}:{}});return s(a,t.input,d)}}}function v(i,e){const t=[];return e&&t.push("--model",e),t.push("-p",i),t}export{f as createClaudeCodeHeadlessAdapter};
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @license FSL-1.1
3
+ * Copyright (c) 2026 OrNexus AI
4
+ *
5
+ * P190.04 -- deterministic fake headless adapter for tests.
6
+ */
7
+ import { type HeadlessAdapter, type HeadlessAdapterId } from './types.js';
8
+ export declare function createFakeHeadlessAdapter(id?: Extract<HeadlessAdapterId, 'fake' | 'test'>): HeadlessAdapter;
@@ -0,0 +1 @@
1
+ import{HEADLESS_REASON_CODES as i,adapterAvailabilitySuccess as u,createRejectedExecutionResult as s,hashPublicValue as n,redaction as d,renderHeadlessPrompt as c,validateHeadlessAdapterExecutionInput as p}from"./types.js";function m(t="fake"){return{id:t,displayName:t==="test"?"Headless Test Adapter":"Headless Fake Adapter",async checkAvailability(){return u(t,"neocortex-headless-fake","Fake headless adapter is available for deterministic tests.")},buildInvocation(r){const a=p(r,t);return a.ok?{ok:!0,invocation:{adapterId:t,commandName:"neocortex-headless-fake",args:[a.input.promptKind,a.input.targetRef],promptHash:a.promptHash,...a.input.modelId?{modelId:a.input.modelId}:{},timeoutMs:a.input.timeoutMs??600*1e3,publicSafe:!0},publicSafe:!0}:a},async execute(r,a){const e=p(r,t);if(!e.ok)return s(t,t,e);const o=c(e.input);return{status:"completed",adapterId:t,runtimeId:t,...e.input.modelId?{modelId:e.input.modelId}:{},...e.input.runtimeSource?{runtimeSource:e.input.runtimeSource}:{},reasonCode:i.EXECUTION_COMPLETED,reasonCodes:[i.EXECUTION_COMPLETED,i.RECEIPT_REDACTED],exitCode:0,signal:null,durationMs:0,counts:{prompts:1,syntheticRuns:1},hashes:{prompt:n(o),receipt:n(`${t}:${e.input.targetRef}:${e.input.modelId??""}`)},publicSummary:"Fake headless adapter completed deterministic public-safe execution.",redactionSummary:[d("prompt","prompt_body",n(o))],relativePaths:[e.input.targetRef],...e.input.receipt?{receipt:e.input.receipt}:{},publicSafe:!0}}}}export{m as createFakeHeadlessAdapter};
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @license FSL-1.1
3
+ * Copyright (c) 2026 OrNexus AI
4
+ *
5
+ * P190.04 -- trusted OpenCode headless adapter interface.
6
+ */
7
+ import { type HeadlessRuntimeRealpathBasenamePolicy } from '../binary.js';
8
+ import { type HeadlessAdapter, type HeadlessAdapterAvailability, type HeadlessAdapterExecutionOptions } from './types.js';
9
+ interface RuntimeAvailabilityPolicy {
10
+ readonly realpathBasenamePolicy?: HeadlessRuntimeRealpathBasenamePolicy;
11
+ readonly versionEvidence?: 'generic-public' | 'claude-code';
12
+ }
13
+ export declare function createOpenCodeHeadlessAdapter(): HeadlessAdapter;
14
+ export declare function checkRuntimeAvailability(adapterId: 'opencode' | 'claude-code', commandName: string, options: HeadlessAdapterExecutionOptions, policy?: RuntimeAvailabilityPolicy): Promise<HeadlessAdapterAvailability>;
15
+ export {};
@@ -0,0 +1,2 @@
1
+ import{checkTrustedHeadlessRuntimeBinary as v}from"../binary.js";import{HEADLESS_REASON_CODES as o,adapterAvailabilityFailure as d,adapterAvailabilitySuccess as b,createRejectedExecutionResult as l,createUnavailableExecutionResult as _,hashPublicValue as R,normalizeHeadlessCommandResult as I,redaction as m,runHeadlessCommand as p,validateHeadlessAdapterExecutionInput as E}from"./types.js";const i="opencode",c="opencode",S=2e3,y=2e3,T=/(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?)\s*[:=]|transcript|stack\s*trace|stderr:|stdout:|system prompt|workflow body|step body|PROTECTED_|PRIVATE_INTERNALS|CUSTOMER_PII|\bPII\b|VENDOR_CORPUS|\bPRIVATE\b)/i,h=/\b(?:Claude\s+Code|claude-code|@anthropic-ai\/claude-code)\b/i,C=/\bv?\d+\.\d+\.\d+(?:[-+][0-9A-Za-z][0-9A-Za-z.-]*)?\b/;function D(){return{id:i,displayName:"OpenCode Headless Adapter",async checkAvailability(n={}){return f(i,c,n)},buildInvocation(n){const t=E(n,i);return t.ok?{ok:!0,invocation:{adapterId:i,commandName:c,args:N(t.prompt,t.input.modelId),promptHash:t.promptHash,...t.input.modelId?{modelId:t.input.modelId}:{},timeoutMs:t.input.timeoutMs??600*1e3,publicSafe:!0},publicSafe:!0}:t},async execute(n,t={}){const e=E(n,i);if(!e.ok)return l(i,i,e);const a=await this.checkAvailability(t);if(!a.ok)return _(i,e.input,a);const r=this.buildInvocation(e.input);if(!r.ok)return l(i,i,r);const s=await(t.commandRunner??p)(a.executablePath??c,r.invocation.args,{cwd:t.cwd,env:t.env,timeoutMs:r.invocation.timeoutMs,maxOutputBytes:t.maxOutputBytes,...e.input.receipt?.jobId?{localConsole:{projectRoot:t.cwd,jobId:e.input.receipt.jobId,attemptId:e.input.receipt.attemptId,executionId:e.input.receipt.executionId,publicSafe:!0}}:{}});return I(i,e.input,s)}}}async function f(n,t,e,a={}){const r=v({commandName:t,env:e.env,platform:e.platform,commandLocator:e.commandLocator,realpathBasenamePolicy:a.realpathBasenamePolicy});if(!r.ok)return d(n,t,r.reasonCode===o.ADAPTER_UNAVAILABLE?o.ADAPTER_UNAVAILABLE:o.RUNTIME_UNTRUSTED,r.publicSummary,r.redactionSummary);const s=await(e.versionRunner??e.commandRunner??p)(r.executablePath,["--version"],{env:e.env,timeoutMs:5e3,maxOutputBytes:2e3}),u=O(s,a.versionEvidence??"generic-public");return u.ok?b(n,t,k(t,a.versionEvidence),{executablePath:r.executablePath,versionText:u.versionText}):d(n,t,o.ADAPTER_UNAVAILABLE,u.publicSummary,u.redactionSummary)}function O(n,t){const e=P(`${n.stdout}
2
+ ${n.stderr}`.trim()),a=e?[m("runtimeVersion","raw_log",R(e))]:[m("runtimeVersion","missing","value-denied")];return n.timedOut||n.exitCode!==0||e.length===0||e.length>S||n.stdoutBytes+n.stderrBytes>y||T.test(e)?{ok:!1,publicSummary:"Headless runtime version check did not return a bounded public result.",redactionSummary:a}:t==="claude-code"&&(!h.test(e)||!C.test(e))?{ok:!1,publicSummary:"Headless runtime version check did not return bounded Claude Code product/version evidence.",redactionSummary:a}:{ok:!0,versionText:e}}function P(n){return n.replace(/\s+/g," ").trim()}function k(n,t){return t==="claude-code"?`Trusted ${n} runtime is available with bounded Claude Code version evidence.`:`Trusted ${n} runtime is available.`}function N(n,t){const e=["run"];return t&&e.push("--model",t),e.push("--",n),e}export{f as checkRuntimeAvailability,D as createOpenCodeHeadlessAdapter};
@@ -0,0 +1,68 @@
1
+ /**
2
+ * @license FSL-1.1
3
+ * Copyright (c) 2026 OrNexus AI
4
+ *
5
+ * P190.04 -- deterministic headless runtime/model resolver.
6
+ */
7
+ import { type HeadlessAdapterId, type HeadlessReasonCode, type HeadlessRedactionEvidence, type HeadlessRuntimeSource } from './types.js';
8
+ export interface HeadlessRuntimeRegistryLike {
9
+ hasAdapter(id: string): boolean;
10
+ }
11
+ export interface HeadlessRuntimeHintInput {
12
+ readonly runtimeId?: unknown;
13
+ readonly modelId?: unknown;
14
+ readonly source?: unknown;
15
+ readonly publicSafe?: unknown;
16
+ readonly [key: string]: unknown;
17
+ }
18
+ export interface ResolveHeadlessRuntimeInput {
19
+ readonly explicit?: unknown;
20
+ readonly origin?: unknown;
21
+ readonly projectDefault?: unknown;
22
+ readonly userDefault?: unknown;
23
+ readonly defaults?: unknown | readonly unknown[];
24
+ readonly fallback?: unknown | false;
25
+ readonly registry?: HeadlessRuntimeRegistryLike;
26
+ }
27
+ export type HeadlessRuntimeResolution = {
28
+ readonly ok: true;
29
+ readonly runtimeId: HeadlessAdapterId;
30
+ readonly modelId?: string;
31
+ readonly runtimeSource: Exclude<HeadlessRuntimeSource, 'unresolved'>;
32
+ readonly modelSource?: Exclude<HeadlessRuntimeSource, 'unresolved'>;
33
+ readonly reasonCode: HeadlessReasonCode;
34
+ readonly reasonCodes: readonly HeadlessReasonCode[];
35
+ readonly publicSummary: string;
36
+ readonly redactionSummary: readonly HeadlessRedactionEvidence[];
37
+ readonly publicSafe: true;
38
+ } | {
39
+ readonly ok: false;
40
+ readonly runtimeSource: 'unresolved';
41
+ readonly reasonCode: HeadlessReasonCode;
42
+ readonly reasonCodes: readonly HeadlessReasonCode[];
43
+ readonly publicSummary: string;
44
+ readonly redactionSummary: readonly HeadlessRedactionEvidence[];
45
+ readonly publicSafe: true;
46
+ };
47
+ export interface HeadlessRuntimeDefaultsLookupOptions {
48
+ readonly projectRoot?: string;
49
+ readonly homeDir?: string;
50
+ readonly maxBytes?: number;
51
+ }
52
+ export type HeadlessRuntimeDefaultsLookupResult = {
53
+ readonly ok: true;
54
+ readonly defaults?: HeadlessRuntimeHintInput;
55
+ readonly source?: 'project' | 'user';
56
+ readonly reasonCodes: readonly HeadlessReasonCode[];
57
+ readonly publicSummary: string;
58
+ readonly publicSafe: true;
59
+ } | {
60
+ readonly ok: false;
61
+ readonly reasonCode: HeadlessReasonCode;
62
+ readonly reasonCodes: readonly HeadlessReasonCode[];
63
+ readonly publicSummary: string;
64
+ readonly redactionSummary: readonly HeadlessRedactionEvidence[];
65
+ readonly publicSafe: true;
66
+ };
67
+ export declare function resolveHeadlessRuntime(input?: ResolveHeadlessRuntimeInput): HeadlessRuntimeResolution;
68
+ export declare function loadHeadlessRuntimeDefaults(options?: HeadlessRuntimeDefaultsLookupOptions): HeadlessRuntimeDefaultsLookupResult;
@@ -0,0 +1 @@
1
+ import{existsSync as h,readFileSync as T,statSync as _}from"node:fs";import{homedir as k}from"node:os";import{isAbsolute as I,join as S,resolve as R}from"node:path";import{HEADLESS_REASON_CODES as o,boundPublicSummary as D,isHeadlessAdapterId as b,isSafeHeadlessModelId as U,redaction as c}from"./types.js";const N=Object.freeze({runtimeId:"opencode",source:"fallback",publicSafe:!0}),E=".neocortex/headless-runtime.json",A=8*1024,C=new Set(["runtimeId","modelId","source","reasonCode","publicSafe"]),g=/(raw|prompt|private|secret|token|password|authorization|api[_-]?key|license|argv|args|executable|binary|shell|cwd|command|path|url|vendor|stdout|stderr|transcript|workflow|step|customer|pii)/i;function P(e={}){const t=e.registry??O,u=L(e),r=[],d=[];for(const i of u){if(i.value===void 0)continue;const a=M(i,t);if(!a.ok)return a.resolution;d.push(...a.candidate.redactions),r.push(a.candidate)}const n=r.find(i=>i.runtimeId),s=r.find(i=>i.modelId);if(!n?.runtimeId)return{ok:!1,runtimeSource:"unresolved",reasonCode:o.RUNTIME_UNRESOLVED,reasonCodes:[o.RUNTIME_UNRESOLVED],publicSummary:"Headless runtime could not be resolved from explicit, origin, default or fallback sources.",redactionSummary:d,publicSafe:!0};const l=w(n.source);return{ok:!0,runtimeId:n.runtimeId,...s?.modelId?{modelId:s.modelId}:{},runtimeSource:n.source,...s?.source?{modelSource:s.source}:{},reasonCode:l,reasonCodes:[l],publicSummary:`Resolved headless runtime from ${n.source} source.`,redactionSummary:d,publicSafe:!0}}function G(e={}){const t=e.maxBytes??A,u=x(e);for(const r of u)if(h(r.path))try{const d=_(r.path);if(!d.isFile()||d.size>t)return p("Default headless runtime config was not a bounded file.","defaultConfig","unbounded_file");const n=JSON.parse(T(r.path,"utf8")),s=H(n);return s?{ok:!0,defaults:{...s,source:"default",publicSafe:!0},source:r.kind,reasonCodes:[o.RUNTIME_DEFAULT],publicSummary:`Loaded ${r.kind} headless runtime defaults.`,publicSafe:!0}:p("Default headless runtime config did not contain a public object.","defaultConfig","unsafe_key")}catch{return p("Default headless runtime config could not be parsed safely.","defaultConfig","unsafe_key")}return{ok:!0,defaults:void 0,reasonCodes:[],publicSummary:"No headless runtime defaults were found; resolver will continue without guessing.",publicSafe:!0}}function L(e){const t=[{source:"explicit",value:e.explicit},{source:"origin",value:e.origin}];for(const u of v(e))t.push({source:"default",value:u});return e.projectDefault!==void 0&&t.push({source:"default",value:e.projectDefault}),e.userDefault!==void 0&&t.push({source:"default",value:e.userDefault}),e.fallback!==!1&&t.push({source:"fallback",value:e.fallback??N}),t}function v(e){return e.defaults===void 0?[]:Array.isArray(e.defaults)?e.defaults:[e.defaults]}function M(e,t){const u=F(e.value);if(u===void 0)return{ok:!0,candidate:{source:e.source,redactions:[]}};if(!m(u))return f(o.RUNTIME_UNTRUSTED,"Headless runtime hint must be a public object.",e.source,[c("runtime","unsafe_key","value-denied")]);const r=[];for(const a of Object.keys(u))(!C.has(a)||g.test(a))&&r.push(c(`runtime.${a}`,"unsafe_key","key-denied"));u.publicSafe!==!0&&r.push(c("runtime.publicSafe","unsafe_key","value-denied")),(typeof u.source=="string"?u.source:e.source)!==e.source&&r.push(c("runtime.source","unsafe_key","value-denied"));const n=typeof u.runtimeId=="string"?u.runtimeId:void 0,s=typeof u.modelId=="string"?u.modelId:void 0;let l;if(n!==void 0){if(!j(n)||!b(n)||!t.hasAdapter(n))return r.push(c("runtime.runtimeId","unsafe_key","value-denied")),f(o.RUNTIME_UNTRUSTED,"Headless runtime was not trusted or allowlisted.",e.source,r);l=n}let i;if(s!==void 0){if(!U(s))return r.push(c("runtime.modelId","unsafe_key","value-denied")),f(o.MODEL_REJECTED,"Headless model id failed bounded public-safety validation.",e.source,r);i=s}return r.length>0?f(o.RUNTIME_UNTRUSTED,"Headless runtime hint failed public-safety validation.",e.source,r):{ok:!0,candidate:{source:e.source,...l?{runtimeId:l}:{},...i?{modelId:i}:{},redactions:[]}}}function F(e){return m(e)&&e.ok===!0&&"defaults"in e?e.defaults:e}function f(e,t,u,r){return{ok:!1,resolution:{ok:!1,runtimeSource:"unresolved",reasonCode:e,reasonCodes:[e],publicSummary:D(`${t} Source=${u}.`),redactionSummary:r,publicSafe:!0}}}function w(e){switch(e){case"explicit":return o.RUNTIME_EXPLICIT;case"origin":return o.RUNTIME_ORIGIN;case"default":return o.RUNTIME_DEFAULT;case"fallback":return o.RUNTIME_FALLBACK}}function x(e){const t=[],u=y(e.projectRoot);u&&t.push({kind:"project",path:S(u,E)});const r=y(e.homeDir??k());return r&&t.push({kind:"user",path:S(r,E)}),t}function y(e){if(!e||/[\r\n\0]/.test(e))return;const t=I(e)?e:R(e);return I(t)?t:void 0}function H(e){if(!m(e))return;const t=m(e.headless)?e.headless:e;return{...typeof t.runtimeId=="string"?{runtimeId:t.runtimeId}:{},...typeof t.modelId=="string"?{modelId:t.modelId}:{},publicSafe:!0}}function p(e,t,u){return{ok:!1,reasonCode:o.RUNTIME_UNTRUSTED,reasonCodes:[o.RUNTIME_UNTRUSTED],publicSummary:e,redactionSummary:[c(t,u,"value-denied")],publicSafe:!0}}function j(e){return/^[A-Za-z0-9][A-Za-z0-9._:-]{0,79}$/.test(e)&&!/[\/\s;&|`$<>]/.test(e)}function m(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}const O=Object.freeze({hasAdapter(e){return b(e)}});export{G as loadHeadlessRuntimeDefaults,P as resolveHeadlessRuntime};
@@ -0,0 +1,59 @@
1
+ /**
2
+ * @license FSL-1.1
3
+ * Copyright (c) 2026 OrNexus AI
4
+ *
5
+ * P190.05 -- runner execution plane for one-story run_yolo directives.
6
+ */
7
+ import { type ContinuityHeadlessExecutionAttemptStatus, type ContinuitySqliteStore } from '../../continuity/sqlite-store.js';
8
+ import { HeadlessAdapterRegistry } from './adapters.js';
9
+ import { type HeadlessAdapterExecutionOptions, type HeadlessRedactionEvidence } from './types.js';
10
+ export declare const DEFAULT_HEADLESS_EXECUTION_LEASE_MS: number;
11
+ export declare const DEFAULT_HEADLESS_EXECUTION_STALE_LEASE_AFTER_MS: number;
12
+ export declare const DEFAULT_HEADLESS_EXECUTION_BACKOFF_MS: number;
13
+ export declare const DEFAULT_HEADLESS_EXECUTION_TIMEOUT_MS: number;
14
+ export declare const DEFAULT_HEADLESS_EXECUTION_LIMIT = 1;
15
+ export declare const DEFAULT_HEADLESS_EXECUTION_MAX_ATTEMPTS = 3;
16
+ export interface RunYoloExecutionPhaseOptions {
17
+ readonly store: ContinuitySqliteStore;
18
+ readonly projectRoot: string;
19
+ readonly runnerId: string;
20
+ readonly now: () => string;
21
+ readonly metadata?: Record<string, unknown> | readonly Record<string, unknown>[];
22
+ readonly adapterRegistry?: HeadlessAdapterRegistry;
23
+ readonly adapterOptions?: HeadlessAdapterExecutionOptions;
24
+ readonly runtimeDefaults?: unknown;
25
+ readonly runtimeFallback?: unknown | false;
26
+ readonly limit?: number;
27
+ readonly leaseMs?: number;
28
+ readonly staleLeaseAfterMs?: number;
29
+ readonly timeoutMs?: number;
30
+ readonly backoffMs?: number;
31
+ readonly maxAttempts?: number;
32
+ readonly queueCap?: number;
33
+ readonly idFactory?: (prefix: string, attemptId: string) => string;
34
+ /** Optional narrow execution filter used by root-owned run_yoloop child delegation. */
35
+ readonly attemptIds?: readonly string[];
36
+ }
37
+ export interface RunYoloExecutionReceipt {
38
+ readonly attemptId: string;
39
+ readonly executionId: string;
40
+ readonly jobId: string;
41
+ readonly status: ContinuityHeadlessExecutionAttemptStatus;
42
+ readonly outcome: 'applied' | 'failed' | 'ignored' | 'deferred';
43
+ readonly reasonCode: string;
44
+ readonly timestamp: string;
45
+ readonly redactionSummary: readonly HeadlessRedactionEvidence[];
46
+ readonly publicSafe: true;
47
+ }
48
+ export interface RunYoloExecutionPhaseSummary {
49
+ readonly ok: boolean;
50
+ readonly enqueuedAttemptCount: number;
51
+ readonly dueAttemptCount: number;
52
+ readonly processedAttemptCount: number;
53
+ readonly recoveredAttemptIds: readonly string[];
54
+ readonly receipts: readonly RunYoloExecutionReceipt[];
55
+ readonly reasonCodes: readonly string[];
56
+ readonly publicSafe: true;
57
+ }
58
+ export declare function runYoloExecutionPhase(options: RunYoloExecutionPhaseOptions): Promise<RunYoloExecutionPhaseSummary>;
59
+ export declare function headlessExecutionEntityId(prefix: string, value: string): string;
@@ -0,0 +1 @@
1
+ import{createHash as F,randomBytes as z}from"node:crypto";import{AUTONOMOUS_GOVERNANCE_EVIDENCE_TAG as V,AUTONOMOUS_GOVERNANCE_REASON_CODES as N,autonomousGovernanceMetadata as B,buildAutonomousGovernanceEnvelope as X,readAutonomousGovernanceEnvelopeFromMetadata as q,recordAutonomousGovernance as Y}from"../../continuity/autonomous-governance.js";import{createDefaultHeadlessAdapterRegistry as Z}from"./adapters.js";import{loadHeadlessRuntimeDefaults as G,resolveHeadlessRuntime as J}from"./resolver.js";import{HEADLESS_REASON_CODES as m,boundPublicSummary as C,hashPublicValue as w,redaction as i}from"./types.js";const W=300*1e3,Q=30*1e3,ee=30*1e3,te=600*1e3,re=1,oe=3,D=/^docs\/stories\/[A-Za-z0-9._-]+\.story\.md$/,ae=/^[A-Za-z0-9][A-Za-z0-9._:-]{0,159}$/,ne=new Set(["schemaVersion","contractVersion","kind","commandClass","jobId","operationId","idempotencyKey","targetKind","targetRef","commandRef","storyId","runtime","publicSummary","reasonCode","attempts","metadata","redactionSummary","publicSafe"]),se=new Set(["runtimeId","modelId","source","reasonCode","publicSafe"]),g=/(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,p=/(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?)\s*[:=]|transcript|stack\s*trace|stderr:|stdout:|system prompt|workflow body|step body|PROTECTED_|PRIVATE_INTERNALS|CUSTOMER_PII|\bPII\b|VENDOR_CORPUS|P190[_-]?SYNTHETIC[_-]?(?:HEADLESS|CONTINUITY))/i,E=/(?:[;&|`$<>]|\$\(|\n|\r|\0)/;async function xe(e){const t=e.adapterRegistry??Z(),r=h(e.limit??re,1,10),a=h(e.leaseMs??W,1e3,3600*1e3),n=h(e.staleLeaseAfterMs??Q,0,1440*60*1e3),s=h(e.maxAttempts??oe,1,10),o=[],u=[],d=e.now(),c=de({store:e.store,metadata:e.metadata,nowIso:d,maxAttempts:s,queueCap:e.queueCap});o.push(...c.reasonCodes);const l=e.store.recoverStaleHeadlessExecutionAttempts({nowIso:d,staleAfterMs:n,limit:r*2});l.recoveredAttemptIds.length>0&&(o.push(m.EXECUTION_BACKOFF),l.failedAttemptIds.length>0&&o.push(m.EXECUTION_TIMEOUT));const _=new Set(e.attemptIds??[]),I=e.store.listDueHeadlessExecutionAttempts({nowIso:e.now(),limit:Math.max(r*5,10)}).filter(y=>y.directive_kind==="run_yolo").filter(y=>_.size===0||_.has(y.attempt_id)).slice(0,r);for(const y of I){const b=await ie({store:e.store,projectRoot:e.projectRoot,runnerId:e.runnerId,attempt:y,registry:t,now:e.now,leaseMs:a,timeoutMs:h(e.timeoutMs??te,1e3,18e5),backoffMs:h(e.backoffMs??ee,1e3,36e5),maxAttempts:s,adapterOptions:e.adapterOptions,runtimeDefaults:e.runtimeDefaults,runtimeFallback:e.runtimeFallback,idFactory:e.idFactory??be});u.push(b),o.push(b.reasonCode)}return{ok:u.every(y=>y.outcome!=="failed")&&c.rejectedCount===0,enqueuedAttemptCount:c.enqueuedCount,dueAttemptCount:I.length,processedAttemptCount:u.filter(y=>y.outcome!=="ignored").length,recoveredAttemptIds:l.recoveredAttemptIds,receipts:u,reasonCodes:L(o.length>0?o:[m.OK]),publicSafe:!0}}function de(e){let t=0,r=0;const a=[];for(const n of _e(e.metadata)){if(!S(n)||n.kind!=="run_yolo")continue;const s=le(n);if(!s.ok){r+=1,a.push(s.reasonCode);continue}const o=s.directive;if(!e.store.jobExists(o.jobId)){r+=1,a.push(N.BYPASS_BLOCKED);continue}const u=Ie(o);if(e.store.hasCompletedHeadlessExecutionDirectiveHash(u)){a.push(m.EXECUTION_COMPLETED);continue}const d=X({autonomousKind:"run_yolo",source:fe(o.metadata,"headless-run-yolo"),targetKind:"story",targetRef:o.targetRef,storyId:o.storyId??x(o.targetRef),jobId:o.jobId,operationSeed:o.operationId,commandHash:w(o.commandRef)}),c=Y(e.store,d,e.nowIso,{requireExistingJob:!0});if(!c.ok){r+=1,a.push(c.reasonCode);continue}const l=U("attempt",o.idempotencyKey),_=U("exec",o.operationId),I=e.store.enqueueHeadlessExecutionAttempt({attemptId:l,executionId:_,jobId:o.jobId,directiveHash:u,directiveKind:"run_yolo",commandClass:o.commandClass,targetKind:"story",targetRef:o.targetRef,storyId:o.storyId??x(o.targetRef),runtimeId:o.runtime?.runtimeId,modelId:o.runtime?.modelId,runtimeSource:he(o.runtime?.source),reasonCode:o.reasonCode,publicSummary:o.publicSummary,enqueuedAt:e.nowIso,notBeforeAt:e.nowIso,maxAttempts:e.maxAttempts,queueCap:e.queueCap,operationId:`${o.operationId}:enqueue`,idempotencyKey:o.idempotencyKey,counts:{directives:1},hashes:{directive:u},redactionSummary:o.redactionSummary,relativePaths:[o.targetRef],metadata:B(d,{schemaVersion:1,contractVersion:"continuity-v1",jobId:o.jobId,operationId:o.operationId,reasonCode:o.reasonCode??m.OK,targetRef:o.targetRef,directiveHash:u})});if(!I.accepted){r+=1,a.push(I.reasonCode??"queue-cap-reached");continue}I.inserted&&(t+=1),a.push(m.OK)}return{enqueuedCount:t,rejectedCount:r,reasonCodes:L(a)}}async function ie(e){const t=e.now(),r=e.idFactory("lease",e.attempt.attempt_id),a=$(t,e.leaseMs);if(!e.store.claimHeadlessExecutionAttempt({attemptId:e.attempt.attempt_id,leaseId:r,runnerId:e.runnerId,claimedAt:t,leaseExpiresAt:a,reasonCode:m.OK}).inserted)return{attemptId:e.attempt.attempt_id,executionId:e.attempt.execution_id,jobId:e.attempt.job_id,status:e.attempt.status,outcome:"ignored",reasonCode:"lease-conflict",timestamp:t,redactionSummary:[],publicSafe:!0};if(e.store.hasCompletedHeadlessExecutionDirectiveHash(e.attempt.directive_hash,e.attempt.attempt_id))return R(e.store,e.attempt,{leaseId:r,runnerId:e.runnerId,status:"skipped",receiptStatus:"ignored",reasonCode:m.EXECUTION_COMPLETED,publicSummary:"Skipped duplicate run_yolo directive because the directive hash is already completed.",completedAt:e.now(),counts:{duplicateDirectiveHashes:1},hashes:{directive:e.attempt.directive_hash},redactionSummary:[],relativePaths:[e.attempt.target_ref]});const o=ue(e);if(!o.ok)return R(e.store,e.attempt,{leaseId:r,runnerId:e.runnerId,status:o.status,receiptStatus:o.receiptStatus,reasonCode:o.reasonCode,publicSummary:o.publicSummary,completedAt:e.now(),counts:{rejectedDirectives:1},hashes:{directive:e.attempt.directive_hash},redactionSummary:o.redactionSummary,relativePaths:K(e.attempt)});const u=e.registry.getAdapter(o.input.runtimeId);if(!u.ok)return R(e.store,e.attempt,{leaseId:r,runnerId:e.runnerId,status:"failed",receiptStatus:"failed",reasonCode:u.reasonCode,publicSummary:u.publicSummary,completedAt:e.now(),counts:{rejectedAdapters:1},hashes:{directive:e.attempt.directive_hash},redactionSummary:u.redactionSummary,relativePaths:[e.attempt.target_ref],runtimeId:o.input.runtimeId,modelId:o.input.modelId,runtimeSource:o.input.runtimeSource});let d;try{d=await u.adapter.execute(o.input,{...e.adapterOptions,cwd:e.adapterOptions?.cwd??e.projectRoot})}catch{d={status:"failed",adapterId:o.input.runtimeId,runtimeId:o.input.runtimeId,...o.input.modelId?{modelId:o.input.modelId}:{},...o.input.runtimeSource?{runtimeSource:o.input.runtimeSource}:{},reasonCode:m.EXECUTION_FAILED,reasonCodes:[m.EXECUTION_FAILED,m.RECEIPT_REDACTED],exitCode:1,signal:null,durationMs:0,counts:{adapterExceptions:1},hashes:{directive:e.attempt.directive_hash},publicSummary:"Headless adapter failed with public-safe exception summary.",redactionSummary:[i("adapter","raw_log","value-denied")],relativePaths:[e.attempt.target_ref],receipt:o.input.receipt,publicSafe:!0}}const c=ye(e.attempt,d,e.maxAttempts,e.backoffMs,e.now()),l=c.retry?"backoff":d.status,_=c.retry?m.EXECUTION_BACKOFF:d.reasonCode,I=l==="completed"?"applied":l==="backoff"?"deferred":l==="skipped"?"ignored":"failed";return R(e.store,e.attempt,{leaseId:r,runnerId:e.runnerId,status:l,receiptStatus:I,reasonCode:_,publicSummary:c.retry?"Headless run_yolo execution scheduled bounded retry after transient adapter outcome.":d.publicSummary,completedAt:e.now(),durationMs:d.durationMs,notBeforeAt:c.notBeforeAt,retryCount:c.retryCount,counts:d.counts,hashes:{...d.hashes,directive:e.attempt.directive_hash},redactionSummary:d.redactionSummary,relativePaths:d.relativePaths.length>0?d.relativePaths:[e.attempt.target_ref],runtimeId:d.runtimeId,modelId:d.modelId,runtimeSource:d.runtimeSource})}function ue(e){const t=q(e.attempt.metadata_json,{autonomousKind:"run_yolo",jobId:e.attempt.job_id,targetKind:"story",targetRef:e.attempt.target_ref});if(!t.ok)return{ok:!1,status:"failed",receiptStatus:"failed",reasonCode:m.DIRECTIVE_REJECTED,publicSummary:t.publicSummary,redactionSummary:t.redactionSummary};const r=me(e.attempt);if(!r.ok)return r;const a=ce(e);return a.ok?{ok:!0,input:{promptKind:"yolo",targetKind:"story",targetRef:e.attempt.target_ref,...e.attempt.story_id?{storyId:e.attempt.story_id}:{},runtimeId:a.runtimeId,...a.modelId?{modelId:a.modelId}:{},runtimeSource:a.runtimeSource,timeoutMs:e.timeoutMs,receipt:{attemptId:e.attempt.attempt_id,executionId:e.attempt.execution_id,jobId:e.attempt.job_id,operationId:e.attempt.execution_id,idempotencyKey:e.attempt.directive_hash,runnerId:e.runnerId},publicSummary:C(e.attempt.public_summary??"Headless run_yolo execution attempt."),publicSafe:!0}}:{ok:!1,status:"failed",receiptStatus:"failed",reasonCode:a.reasonCode,publicSummary:a.publicSummary,redactionSummary:a.redactionSummary}}function ce(e){const t=e.runtimeDefaults!==void 0?e.runtimeDefaults:G({projectRoot:e.projectRoot});if(S(t)&&t.ok===!1)return{ok:!1,reasonCode:m.RUNTIME_UNTRUSTED,publicSummary:typeof t.publicSummary=="string"?t.publicSummary:"Headless runtime defaults failed public-safety validation.",redactionSummary:Array.isArray(t.redactionSummary)?t.redactionSummary:[]};const r=Ee(e.attempt.runtime_source)??"explicit",a=e.attempt.runtime_id||e.attempt.model_id?{...e.attempt.runtime_id?{runtimeId:e.attempt.runtime_id}:{},...e.attempt.model_id?{modelId:e.attempt.model_id}:{},source:r,publicSafe:!0}:void 0,n={registry:e.registry,defaults:t,fallback:e.runtimeFallback};a&&(r==="origin"?n.origin=a:r==="default"?n.projectDefault=a:r==="fallback"?n.fallback=a:n.explicit=a);const s=J(n);return s.ok?{ok:!0,runtimeId:s.runtimeId,...s.modelId?{modelId:s.modelId}:{},runtimeSource:s.runtimeSource}:{ok:!1,reasonCode:s.reasonCode,publicSummary:s.publicSummary,redactionSummary:s.redactionSummary}}function me(e){const t=[];e.directive_kind!=="run_yolo"&&t.push(i("directiveKind","unsafe_key","value-denied")),e.target_kind!=="story"&&t.push(i("targetKind","prompt_body","value-denied")),(!D.test(e.target_ref)||E.test(e.target_ref)||p.test(e.target_ref))&&t.push(i("targetRef","prompt_body","value-denied"));const r=x(e.target_ref);return e.story_id&&e.story_id!==r&&t.push(i("storyId","prompt_body","value-denied")),t.length>0?{ok:!1,status:"failed",receiptStatus:"failed",reasonCode:m.PROMPT_REJECTED,publicSummary:"Headless run_yolo attempt did not match the canonical public story prompt shape.",redactionSummary:t}:{ok:!0,input:{promptKind:"yolo",targetKind:"story",targetRef:e.target_ref,...e.story_id?{storyId:e.story_id}:{},runtimeId:"fake",publicSafe:!0}}}function le(e){const t=[];for(const A of Object.keys(e))(!ne.has(A)||g.test(A))&&t.push(i(A,T(A),"key-denied"));e.publicSafe!==!0&&t.push(i("publicSafe","unsafe_key","value-denied"));const r=f(e,"kind"),a=f(e,"commandClass"),n=f(e,"jobId"),s=f(e,"operationId"),o=f(e,"idempotencyKey"),u=f(e,"targetKind"),d=f(e,"targetRef"),c=f(e,"commandRef"),l=f(e,"publicSummary"),_=f(e,"storyId");r!=="run_yolo"&&t.push(i("kind","unsafe_key","value-denied")),a!=="goal-tick"&&a!=="loop-tick"&&t.push(i("commandClass","unsafe_key","value-denied")),j(n)||t.push(i("jobId","unsafe_key","value-denied")),j(s)||t.push(i("operationId","unsafe_key","value-denied")),j(o)||t.push(i("idempotencyKey","unsafe_key","value-denied")),(u!=="story"||!d||!D.test(d)||p.test(d))&&t.push(i("targetRef","prompt_body","value-denied"));const I=d?`*yolo @${d}`:void 0;(!c||c!==I||c.includes("@neocortex")||E.test(c)||p.test(c))&&t.push(i("commandRef","prompt_body","value-denied")),_&&d&&_!==x(d)&&t.push(i("storyId","prompt_body","value-denied")),(!l||l.length>240||p.test(l))&&t.push(i("publicSummary","unbounded_text","value-denied")),e.reasonCode!==void 0&&(typeof e.reasonCode!="string"||p.test(e.reasonCode))&&t.push(i("reasonCode","unsafe_key","value-denied"));const y=pe(e.runtime,t);e.attempts!==void 0&&k(e.attempts,"attempts",t),e.metadata!==void 0&&k(e.metadata,"metadata",t);const b=S(e.metadata)?e.metadata:void 0,M=Se(e.redactionSummary,t);return t.length>0||r!=="run_yolo"||!a||!n||!s||!o||!d||!c||!l?{ok:!1,reasonCode:t.some(H=>H.reason==="prompt_body")?m.PROMPT_REJECTED:m.DIRECTIVE_REJECTED,redactionSummary:t}:{ok:!0,directive:{kind:"run_yolo",commandClass:a,jobId:n,operationId:s,idempotencyKey:o,targetKind:"story",targetRef:d,commandRef:c,..._?{storyId:_}:{},...y?{runtime:y}:{},publicSummary:l,...typeof e.reasonCode=="string"?{reasonCode:e.reasonCode}:{},...b?{metadata:b}:{},...M.length>0?{redactionSummary:M}:{},publicSafe:!0}}}function fe(e,t){return e?.governanceSource==="delegated-subagent"?"delegated-subagent":t}function pe(e,t){if(e===void 0)return;if(!S(e)){t.push(i("runtime","unsafe_key","value-denied"));return}for(const s of Object.keys(e))(!se.has(s)||g.test(s))&&t.push(i(`runtime.${s}`,T(s),"key-denied"));e.publicSafe!==!0&&t.push(i("runtime.publicSafe","unsafe_key","value-denied"));const r=f(e,"runtimeId"),a=f(e,"modelId"),n=f(e,"source");if(r&&(!/^[A-Za-z0-9][A-Za-z0-9._:-]{0,79}$/.test(r)||p.test(r)||E.test(r))&&t.push(i("runtime.runtimeId","unsafe_key","value-denied")),a&&(!/^[A-Za-z0-9][A-Za-z0-9._:+/-]{0,119}$/.test(a)||p.test(a)||E.test(a))&&t.push(i("runtime.modelId","unsafe_key","value-denied")),n!==void 0&&n!=="explicit"&&n!=="origin"&&n!=="default"&&n!=="fallback"&&n!=="unspecified"&&t.push(i("runtime.source","unsafe_key","value-denied")),e.reasonCode!==void 0&&(typeof e.reasonCode!="string"||p.test(e.reasonCode))&&t.push(i("runtime.reasonCode","unsafe_key","value-denied")),e.publicSafe===!0)return{...r?{runtimeId:r}:{},...a?{modelId:a}:{},...n==="explicit"||n==="origin"||n==="default"||n==="fallback"||n==="unspecified"?{source:n}:{},...typeof e.reasonCode=="string"?{reasonCode:e.reasonCode}:{},publicSafe:!0}}function R(e,t,r){const a=r.redactionSummary??[],n=r.relativePaths??K(t),s=P(r.counts),o=P(r.hashes),u={schemaVersion:1,contractVersion:"continuity-v1",attemptId:t.attempt_id,executionId:t.execution_id,jobId:t.job_id,directiveHash:t.directive_hash,status:r.status,reasonCode:r.reasonCode,...r.runtimeId?{runtimeId:r.runtimeId}:{},...r.modelId?{modelId:r.modelId}:{},...r.runtimeSource?{runtimeSource:r.runtimeSource}:{},...r.retryCount!==void 0?{retryCount:r.retryCount}:{},...r.reasonCode===N.BYPASS_BLOCKED?{governanceEvidence:V}:{},publicSummary:C(r.publicSummary)};return e.completeHeadlessExecutionAttempt({attemptId:t.attempt_id,executionId:t.execution_id,jobId:t.job_id,leaseId:r.leaseId,runnerId:r.runnerId,status:r.status,completedAt:r.completedAt,durationMs:r.durationMs,reasonCode:r.reasonCode,publicSummary:C(r.publicSummary),notBeforeAt:r.notBeforeAt,retryCount:r.retryCount,counts:s,hashes:o,redactionSummary:a,relativePaths:n,metadata:u}),e.recordHeadlessExecutionReceipt({receiptId:`receipt-${v("headless",`${t.attempt_id}-${r.status}`)}`,attemptId:t.attempt_id,executionId:t.execution_id,jobId:t.job_id,status:r.receiptStatus,reasonCode:r.reasonCode,createdAt:r.completedAt,operationId:`${t.execution_id}:${r.status}:receipt`,idempotencyKey:`${t.directive_hash}:${r.status}:receipt`,counts:s,hashes:o,redactionSummary:a,relativePaths:n,metadata:u}),e.recordHeadlessExecutionSummary({eventId:`event-${v("headless-summary",`${t.attempt_id}-${r.status}`)}`,attemptId:t.attempt_id,executionId:t.execution_id,jobId:t.job_id,status:r.status,runtimeId:r.runtimeId,modelId:r.modelId,publicSummary:C(r.publicSummary),reasonCode:r.reasonCode,createdAt:r.completedAt,durationMs:r.durationMs,counts:s,hashes:o,redactionSummary:a,relativePaths:n,metadata:u}),{attemptId:t.attempt_id,executionId:t.execution_id,jobId:t.job_id,status:r.status,outcome:r.receiptStatus,reasonCode:r.reasonCode,timestamp:r.completedAt,redactionSummary:a,publicSafe:!0}}function ye(e,t,r,a,n){if(!(t.status==="timed_out"||t.reasonCode===m.EXECUTION_FAILED||t.reasonCode===m.ADAPTER_UNAVAILABLE))return{retry:!1};const o=e.retry_count+1;if(o>=Math.max(1,e.max_attempts||r))return{retry:!1,retryCount:o};const u=Math.min(8,2**Math.max(0,e.retry_count));return{retry:!0,retryCount:o,notBeforeAt:$(n,a*u)}}function _e(e){const t=Array.isArray(e)?e:e?[e]:[],r=[];for(const a of t){const n=a.continuityExecutionDirectives;Array.isArray(n)&&r.push(...n)}return r}function Ie(e){return w(O({kind:e.kind,commandClass:e.commandClass,jobId:e.jobId,targetRef:e.targetRef,commandRef:e.commandRef,storyId:e.storyId,runtime:e.runtime}))}function O(e){return Array.isArray(e)?`[${e.map(O).join(",")}]`:S(e)?`{${Object.keys(e).sort().map(t=>`${JSON.stringify(t)}:${O(e[t])}`).join(",")}}`:JSON.stringify(e)}function k(e,t,r){if(typeof e=="string"){(p.test(e)||E.test(e))&&r.push(i(t,T(t),"value-denied"));return}if(!(e==null||typeof e=="number"||typeof e=="boolean")){if(Array.isArray(e)){e.forEach((a,n)=>k(a,`${t}.${n}`,r));return}if(S(e)){for(const[a,n]of Object.entries(e)){const s=`${t}.${a}`;g.test(a)&&r.push(i(s,T(a),"key-denied")),k(n,s,r)}return}r.push(i(t,"unsafe_key","value-denied"))}}function Se(e,t){if(e===void 0)return[];if(!Array.isArray(e))return t.push(i("redactionSummary","unsafe_key","value-denied")),[];const r=[];for(const[a,n]of e.entries()){if(!S(n)||n.publicSafe!==!0){t.push(i(`redactionSummary.${a}`,"unsafe_key","value-denied"));continue}const s=f(n,"field"),o=f(n,"reason"),u=f(n,"evidence");if(!s||!o||!u||p.test(s)||p.test(o)||p.test(u)){t.push(i(`redactionSummary.${a}`,"unsafe_key","value-denied"));continue}r.push({field:s,reason:o,evidence:u,publicSafe:!0})}return r}function K(e){return D.test(e.target_ref)?[e.target_ref]:[]}function P(e){if(!e)return;const t={};for(const[r,a]of Object.entries(e))!/^[A-Za-z0-9_.:-]{1,80}$/.test(r)||g.test(r)||p.test(r)||typeof a=="string"&&p.test(a)||(t[r]=a);return Object.keys(t).length>0?t:void 0}function x(e){return e.replace(/^docs\/stories\//,"").replace(/\.story\.md$/,"")}function Ee(e){if(e==="explicit"||e==="origin"||e==="default"||e==="fallback")return e}function he(e){if(e==="explicit"||e==="origin"||e==="default"||e==="fallback"||e==="unspecified")return e}function T(e){return/prompt|commandRef/i.test(e)?"prompt_body":/std(?:out|err)|raw|log|transcript|stack/i.test(e)?"raw_log":/url/i.test(e)?"private_url":/path|cwd|argv|args|shell|command|binary|executable/i.test(e)?"executable_path":/secret|token|password|authorization|api[_-]?key|license/i.test(e)?"secret_or_pii":"unsafe_key"}function f(e,t){return typeof e[t]=="string"?e[t]:void 0}function j(e){return!!(e&&ae.test(e)&&!p.test(e)&&!E.test(e))}function S(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function v(e,t){const r=`${e}-${t}`.replace(/[^A-Za-z0-9_.:-]+/g,"-").replace(/^-+|-+$/g,"");return r.length>0&&r.length<=120?r:`${e}-${F("sha256").update(t).digest("hex").slice(0,32)}`}function U(e,t){return v(e,t)}function be(e,t){return v(e,`${t}-${Date.now()}-${z(4).toString("hex")}`)}function $(e,t){const r=Date.parse(e);return new Date((Number.isFinite(r)?r:Date.now())+t).toISOString()}function h(e,t,r){return Number.isFinite(e)?Math.max(t,Math.min(r,Math.floor(e))):t}function L(e){return Array.from(new Set(e))}export{ee as DEFAULT_HEADLESS_EXECUTION_BACKOFF_MS,W as DEFAULT_HEADLESS_EXECUTION_LEASE_MS,re as DEFAULT_HEADLESS_EXECUTION_LIMIT,oe as DEFAULT_HEADLESS_EXECUTION_MAX_ATTEMPTS,Q as DEFAULT_HEADLESS_EXECUTION_STALE_LEASE_AFTER_MS,te as DEFAULT_HEADLESS_EXECUTION_TIMEOUT_MS,U as headlessExecutionEntityId,xe as runYoloExecutionPhase};