open-multi-agent-kit 0.98.3 → 0.98.4

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 (262) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +11 -2
  3. package/dist/cli/args.d.ts +1 -0
  4. package/dist/cli/args.d.ts.map +1 -1
  5. package/dist/cli/args.js +14 -0
  6. package/dist/cli/args.js.map +1 -1
  7. package/dist/cli/help.d.ts.map +1 -1
  8. package/dist/cli/help.js +3 -0
  9. package/dist/cli/help.js.map +1 -1
  10. package/dist/cli/mcp-attach.d.ts +3 -3
  11. package/dist/cli/mcp-attach.d.ts.map +1 -1
  12. package/dist/cli/mcp-attach.js +5 -4
  13. package/dist/cli/mcp-attach.js.map +1 -1
  14. package/dist/cli/model-contract.d.ts +5 -0
  15. package/dist/cli/model-contract.d.ts.map +1 -0
  16. package/dist/cli/model-contract.js +45 -0
  17. package/dist/cli/model-contract.js.map +1 -0
  18. package/dist/commands/adaptorch-doctor-cli.d.ts.map +1 -1
  19. package/dist/commands/adaptorch-doctor-cli.js +32 -10
  20. package/dist/commands/adaptorch-doctor-cli.js.map +1 -1
  21. package/dist/commands/init-cli.d.ts +12 -0
  22. package/dist/commands/init-cli.d.ts.map +1 -0
  23. package/dist/commands/init-cli.js +76 -0
  24. package/dist/commands/init-cli.js.map +1 -0
  25. package/dist/commands/provider-sync-cli.d.ts +27 -0
  26. package/dist/commands/provider-sync-cli.d.ts.map +1 -0
  27. package/dist/commands/provider-sync-cli.js +177 -0
  28. package/dist/commands/provider-sync-cli.js.map +1 -0
  29. package/dist/commands/run-command.d.ts +8 -0
  30. package/dist/commands/run-command.d.ts.map +1 -0
  31. package/dist/commands/run-command.js +26 -0
  32. package/dist/commands/run-command.js.map +1 -0
  33. package/dist/core/active-skill-state.d.ts +7 -0
  34. package/dist/core/active-skill-state.d.ts.map +1 -0
  35. package/dist/core/active-skill-state.js +25 -0
  36. package/dist/core/active-skill-state.js.map +1 -0
  37. package/dist/core/agent-session-services.d.ts +2 -0
  38. package/dist/core/agent-session-services.d.ts.map +1 -1
  39. package/dist/core/agent-session-services.js +2 -0
  40. package/dist/core/agent-session-services.js.map +1 -1
  41. package/dist/core/agent-session.d.ts +0 -1
  42. package/dist/core/agent-session.d.ts.map +1 -1
  43. package/dist/core/agent-session.js +30 -85
  44. package/dist/core/agent-session.js.map +1 -1
  45. package/dist/core/codex-chatgpt-web-bridge.d.ts +99 -0
  46. package/dist/core/codex-chatgpt-web-bridge.d.ts.map +1 -0
  47. package/dist/core/codex-chatgpt-web-bridge.js +192 -0
  48. package/dist/core/codex-chatgpt-web-bridge.js.map +1 -0
  49. package/dist/core/codex-chatgpt-web-sync.d.ts +50 -0
  50. package/dist/core/codex-chatgpt-web-sync.d.ts.map +1 -0
  51. package/dist/core/codex-chatgpt-web-sync.js +119 -0
  52. package/dist/core/codex-chatgpt-web-sync.js.map +1 -0
  53. package/dist/core/compaction/compaction-headroom.d.ts +30 -0
  54. package/dist/core/compaction/compaction-headroom.d.ts.map +1 -0
  55. package/dist/core/compaction/compaction-headroom.js +48 -0
  56. package/dist/core/compaction/compaction-headroom.js.map +1 -0
  57. package/dist/core/compaction/compaction.d.ts +2 -29
  58. package/dist/core/compaction/compaction.d.ts.map +1 -1
  59. package/dist/core/compaction/compaction.js +19 -47
  60. package/dist/core/compaction/compaction.js.map +1 -1
  61. package/dist/core/compaction/overflow-retry-guard.d.ts +20 -0
  62. package/dist/core/compaction/overflow-retry-guard.d.ts.map +1 -0
  63. package/dist/core/compaction/overflow-retry-guard.js +38 -0
  64. package/dist/core/compaction/overflow-retry-guard.js.map +1 -0
  65. package/dist/core/context-budget-headroom-types.d.ts.map +1 -1
  66. package/dist/core/context-budget-headroom-types.js +1 -1
  67. package/dist/core/context-budget-headroom-types.js.map +1 -1
  68. package/dist/core/context-budget-token-counter-types.d.ts +27 -0
  69. package/dist/core/context-budget-token-counter-types.d.ts.map +1 -0
  70. package/dist/core/context-budget-token-counter-types.js +2 -0
  71. package/dist/core/context-budget-token-counter-types.js.map +1 -0
  72. package/dist/core/context-budget-token-counter.d.ts +2 -26
  73. package/dist/core/context-budget-token-counter.d.ts.map +1 -1
  74. package/dist/core/context-budget-token-counter.js +2 -0
  75. package/dist/core/context-budget-token-counter.js.map +1 -1
  76. package/dist/core/context-budget-v2-scoring.d.ts.map +1 -1
  77. package/dist/core/context-budget-v2-scoring.js +14 -10
  78. package/dist/core/context-budget-v2-scoring.js.map +1 -1
  79. package/dist/core/domain-router.d.ts.map +1 -1
  80. package/dist/core/domain-router.js +1 -1
  81. package/dist/core/domain-router.js.map +1 -1
  82. package/dist/core/grok-harness-dispatch.d.ts +4 -0
  83. package/dist/core/grok-harness-dispatch.d.ts.map +1 -1
  84. package/dist/core/grok-harness-dispatch.js +20 -3
  85. package/dist/core/grok-harness-dispatch.js.map +1 -1
  86. package/dist/core/grok-harness.d.ts +15 -9
  87. package/dist/core/grok-harness.d.ts.map +1 -1
  88. package/dist/core/grok-harness.js +34 -8
  89. package/dist/core/grok-harness.js.map +1 -1
  90. package/dist/core/mcp/tools.d.ts +2 -2
  91. package/dist/core/mcp/tools.d.ts.map +1 -1
  92. package/dist/core/mcp/tools.js +29 -3
  93. package/dist/core/mcp/tools.js.map +1 -1
  94. package/dist/core/model-registry-schema.d.ts +1081 -0
  95. package/dist/core/model-registry-schema.d.ts.map +1 -0
  96. package/dist/core/model-registry-schema.js +148 -0
  97. package/dist/core/model-registry-schema.js.map +1 -0
  98. package/dist/core/model-registry.d.ts.map +1 -1
  99. package/dist/core/model-registry.js +1 -146
  100. package/dist/core/model-registry.js.map +1 -1
  101. package/dist/core/model-resolver.d.ts +2 -1
  102. package/dist/core/model-resolver.d.ts.map +1 -1
  103. package/dist/core/model-resolver.js +2 -1
  104. package/dist/core/model-resolver.js.map +1 -1
  105. package/dist/core/prompt-preset.d.ts +1 -1
  106. package/dist/core/prompt-preset.d.ts.map +1 -1
  107. package/dist/core/prompt-preset.js +16 -1
  108. package/dist/core/prompt-preset.js.map +1 -1
  109. package/dist/core/provider-display-names.d.ts.map +1 -1
  110. package/dist/core/provider-display-names.js +1 -0
  111. package/dist/core/provider-display-names.js.map +1 -1
  112. package/dist/core/provider-resilience.d.ts +8 -0
  113. package/dist/core/provider-resilience.d.ts.map +1 -1
  114. package/dist/core/provider-resilience.js +20 -3
  115. package/dist/core/provider-resilience.js.map +1 -1
  116. package/dist/core/provider-usage-types.d.ts +42 -0
  117. package/dist/core/provider-usage-types.d.ts.map +1 -0
  118. package/dist/core/provider-usage-types.js +2 -0
  119. package/dist/core/provider-usage-types.js.map +1 -0
  120. package/dist/core/provider-usage.d.ts +2 -31
  121. package/dist/core/provider-usage.d.ts.map +1 -1
  122. package/dist/core/provider-usage.js +4 -0
  123. package/dist/core/provider-usage.js.map +1 -1
  124. package/dist/core/redaction.d.ts.map +1 -1
  125. package/dist/core/redaction.js +18 -2
  126. package/dist/core/redaction.js.map +1 -1
  127. package/dist/core/sandbox/policy-merge.d.ts +6 -0
  128. package/dist/core/sandbox/policy-merge.d.ts.map +1 -0
  129. package/dist/core/sandbox/policy-merge.js +74 -0
  130. package/dist/core/sandbox/policy-merge.js.map +1 -0
  131. package/dist/core/sandbox/policy-paths.d.ts +4 -0
  132. package/dist/core/sandbox/policy-paths.d.ts.map +1 -0
  133. package/dist/core/sandbox/policy-paths.js +21 -0
  134. package/dist/core/sandbox/policy-paths.js.map +1 -0
  135. package/dist/core/sandbox/policy-types.d.ts +75 -0
  136. package/dist/core/sandbox/policy-types.d.ts.map +1 -0
  137. package/dist/core/sandbox/policy-types.js +2 -0
  138. package/dist/core/sandbox/policy-types.js.map +1 -0
  139. package/dist/core/sandbox/policy.d.ts +3 -77
  140. package/dist/core/sandbox/policy.d.ts.map +1 -1
  141. package/dist/core/sandbox/policy.js +3 -98
  142. package/dist/core/sandbox/policy.js.map +1 -1
  143. package/dist/core/sdk-provider-stream.d.ts +14 -0
  144. package/dist/core/sdk-provider-stream.d.ts.map +1 -0
  145. package/dist/core/sdk-provider-stream.js +38 -0
  146. package/dist/core/sdk-provider-stream.js.map +1 -0
  147. package/dist/core/sdk.d.ts +5 -1
  148. package/dist/core/sdk.d.ts.map +1 -1
  149. package/dist/core/sdk.js +17 -33
  150. package/dist/core/sdk.js.map +1 -1
  151. package/dist/core/session-failure-cause.d.ts.map +1 -1
  152. package/dist/core/session-failure-cause.js +10 -3
  153. package/dist/core/session-failure-cause.js.map +1 -1
  154. package/dist/core/session-run-termination.d.ts +18 -0
  155. package/dist/core/session-run-termination.d.ts.map +1 -0
  156. package/dist/core/session-run-termination.js +61 -0
  157. package/dist/core/session-run-termination.js.map +1 -0
  158. package/dist/core/session-termination.d.ts.map +1 -1
  159. package/dist/core/session-termination.js +1 -1
  160. package/dist/core/session-termination.js.map +1 -1
  161. package/dist/core/skill-selector.d.ts +40 -0
  162. package/dist/core/skill-selector.d.ts.map +1 -0
  163. package/dist/core/skill-selector.js +102 -0
  164. package/dist/core/skill-selector.js.map +1 -0
  165. package/dist/core/tools/render-utils.d.ts.map +1 -1
  166. package/dist/core/tools/render-utils.js +2 -4
  167. package/dist/core/tools/render-utils.js.map +1 -1
  168. package/dist/core/turn-metrics-record.d.ts +55 -0
  169. package/dist/core/turn-metrics-record.d.ts.map +1 -0
  170. package/dist/core/turn-metrics-record.js +149 -0
  171. package/dist/core/turn-metrics-record.js.map +1 -0
  172. package/dist/core/turn-metrics.d.ts +4 -56
  173. package/dist/core/turn-metrics.d.ts.map +1 -1
  174. package/dist/core/turn-metrics.js +12 -60
  175. package/dist/core/turn-metrics.js.map +1 -1
  176. package/dist/guardrails/evidence-system.d.ts +1 -1
  177. package/dist/guardrails/evidence-system.d.ts.map +1 -1
  178. package/dist/guardrails/evidence-system.js +18 -29
  179. package/dist/guardrails/evidence-system.js.map +1 -1
  180. package/dist/guardrails/merge-gate-result.d.ts +4 -0
  181. package/dist/guardrails/merge-gate-result.d.ts.map +1 -0
  182. package/dist/guardrails/merge-gate-result.js +32 -0
  183. package/dist/guardrails/merge-gate-result.js.map +1 -0
  184. package/dist/main.d.ts.map +1 -1
  185. package/dist/main.js +22 -22
  186. package/dist/main.js.map +1 -1
  187. package/dist/modes/interactive/interactive-login-options.d.ts +27 -0
  188. package/dist/modes/interactive/interactive-login-options.d.ts.map +1 -0
  189. package/dist/modes/interactive/interactive-login-options.js +54 -0
  190. package/dist/modes/interactive/interactive-login-options.js.map +1 -0
  191. package/dist/modes/interactive/interactive-mode.d.ts +7 -4
  192. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  193. package/dist/modes/interactive/interactive-mode.js +138 -140
  194. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  195. package/dist/modes/interactive/interactive-resume-command.d.ts +3 -0
  196. package/dist/modes/interactive/interactive-resume-command.d.ts.map +1 -0
  197. package/dist/modes/interactive/interactive-resume-command.js +24 -0
  198. package/dist/modes/interactive/interactive-resume-command.js.map +1 -0
  199. package/dist/modes/interactive/interactive-tool-result.d.ts +32 -0
  200. package/dist/modes/interactive/interactive-tool-result.d.ts.map +1 -0
  201. package/dist/modes/interactive/interactive-tool-result.js +59 -0
  202. package/dist/modes/interactive/interactive-tool-result.js.map +1 -0
  203. package/dist/modes/print-mode.d.ts.map +1 -1
  204. package/dist/modes/print-mode.js +22 -0
  205. package/dist/modes/print-mode.js.map +1 -1
  206. package/dist/utils/clipboard-image.d.ts.map +1 -1
  207. package/dist/utils/clipboard-image.js +10 -60
  208. package/dist/utils/clipboard-image.js.map +1 -1
  209. package/dist/utils/terminal-links.d.ts +13 -0
  210. package/dist/utils/terminal-links.d.ts.map +1 -0
  211. package/dist/utils/terminal-links.js +68 -0
  212. package/dist/utils/terminal-links.js.map +1 -0
  213. package/dist/utils/windows-clipboard-image.d.ts +16 -0
  214. package/dist/utils/windows-clipboard-image.d.ts.map +1 -0
  215. package/dist/utils/windows-clipboard-image.js +87 -0
  216. package/dist/utils/windows-clipboard-image.js.map +1 -0
  217. package/docs/adaptorch-onboarding.md +80 -0
  218. package/docs/containerization.md +12 -0
  219. package/docs/context-files.md +97 -0
  220. package/docs/correctness-wall.md +8 -0
  221. package/docs/custom-provider.md +35 -0
  222. package/docs/development.md +18 -3
  223. package/docs/environment-variables.md +2 -0
  224. package/docs/grok-harness.md +4 -0
  225. package/docs/harness-boundaries.md +154 -0
  226. package/docs/harness-improvements.md +90 -0
  227. package/docs/json.md +19 -0
  228. package/docs/keybindings.md +1 -1
  229. package/docs/mcp.md +22 -2
  230. package/docs/metrics.md +66 -16
  231. package/docs/model-catalog-refresh.md +190 -0
  232. package/docs/model-contract.md +168 -0
  233. package/docs/models.md +21 -4
  234. package/docs/provider-resilience.md +5 -3
  235. package/docs/providers.md +68 -1
  236. package/docs/quickstart.md +4 -0
  237. package/docs/release-audit-0.98.4.md +112 -0
  238. package/docs/review-bundle-followup.md +195 -0
  239. package/docs/runtime-algorithms.md +19 -0
  240. package/docs/sdk.md +11 -2
  241. package/docs/sessions.md +1 -1
  242. package/docs/settings.md +17 -1
  243. package/docs/skills.md +2 -0
  244. package/docs/tb21-audit.md +131 -0
  245. package/docs/terminal-setup.md +20 -0
  246. package/docs/usage.md +23 -1
  247. package/docs/windows.md +48 -0
  248. package/examples/README.md +4 -0
  249. package/examples/context/AGENTS.md +64 -0
  250. package/examples/context/CLAUDE.md +17 -0
  251. package/examples/context/INTERNET.md +42 -0
  252. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  253. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  254. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  255. package/examples/extensions/gondolin/package-lock.json +2 -2
  256. package/examples/extensions/gondolin/package.json +1 -1
  257. package/examples/extensions/sandbox/package-lock.json +2 -2
  258. package/examples/extensions/sandbox/package.json +1 -1
  259. package/examples/extensions/with-deps/package-lock.json +2 -2
  260. package/examples/extensions/with-deps/package.json +1 -1
  261. package/npm-shrinkwrap.json +18 -18
  262. package/package.json +6 -6
@@ -1 +1 @@
1
- {"version":3,"file":"evidence-system.js","sourceRoot":"","sources":["../../src/guardrails/evidence-system.ts"],"names":[],"mappings":"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","sourcesContent":["// allow: SIZE_OK - evidence ledger guardrails: tamper-evident replay chain + fail-closed parsing.\nimport { createHash } from \"node:crypto\";\nimport { existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport type {\n\tEvidenceCommandDescriptor,\n\tEvidenceItem,\n\tEvidenceReceiptMode,\n\tEvidenceStatus,\n\tMergeGateResult,\n\tMergeGateStatus,\n\tReplayEvent,\n\tReplayLedger,\n\tReplayLedgerHead,\n\tTaskContract,\n\tVerifiedReplayLedgerSnapshot,\n\tWorkspaceScope,\n} from \"../types/evidence.ts\";\nimport { redactCommandDescriptor } from \"./command-redaction.ts\";\nimport {\n\ttype CommandHmacBinder,\n\tlatestRelevantWorkspaceMutationSeq,\n\tparseVerifiedLedgerSnapshot,\n\treplayPayloadMatches,\n\tverifyCommandAttestation,\n\tverifyWorkspaceBinding,\n} from \"./evidence-attestation.ts\";\n\nexport { latestRelevantWorkspaceMutationSeq } from \"./evidence-attestation.ts\";\n\nimport {\n\tcomputeEvidenceCommandSha256,\n\tconstantTimeSha256Equal,\n\tevidenceReceiptReplayPayload,\n\tparseSha256Hex,\n\tvalidateEvidenceReceipt,\n} from \"./evidence-receipt.ts\";\nimport { ReplayLedgerStore, replayLedgerHeadsEqual } from \"./replay-ledger-store.ts\";\nimport {\n\tcomputeReplayPayloadHash,\n\tJCS_REPLAY_PAYLOAD_HASH_ALGORITHM,\n\tLEGACY_REPLAY_PAYLOAD_HASH_ALGORITHM,\n} from \"./replay-payload-hash.ts\";\n\nfunction sha256(input: string): string {\n\treturn createHash(\"sha256\").update(input).digest(\"hex\");\n}\n\nfunction ensureDir(path: string): void {\n\tconst dir = dirname(path);\n\tif (!existsSync(dir)) {\n\t\tmkdirSync(dir, { recursive: true });\n\t}\n}\n\n// ============================================================================\n// TaskContract\n// ============================================================================\n\nexport class TaskContractBuilder {\n\tprivate goalId: string;\n\tprivate completionClaim: string = \"\";\n\tprivate requiredEvidence: EvidenceItem[] = [];\n\tprivate finalRisk: string = \"\";\n\tprivate verdict: \"pass\" | \"fail\" | \"conditional\" = \"fail\";\n\tprivate createdAt: string;\n\tprivate updatedAt: string;\n\n\tconstructor(goalId: string) {\n\t\tthis.goalId = goalId;\n\t\tconst now = new Date().toISOString();\n\t\tthis.createdAt = now;\n\t\tthis.updatedAt = now;\n\t}\n\n\tsetClaim(claim: string): this {\n\t\tthis.completionClaim = claim;\n\t\tthis.touch();\n\t\treturn this;\n\t}\n\n\taddRequiredEvidence(evidence: Omit<EvidenceItem, \"timestamp\" | \"status\">): this {\n\t\tthis.requiredEvidence.push({\n\t\t\t...evidence,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tstatus: \"pending\",\n\t\t});\n\t\tthis.touch();\n\t\treturn this;\n\t}\n\n\tsetFinalRisk(risk: string): this {\n\t\tthis.finalRisk = risk;\n\t\tthis.touch();\n\t\treturn this;\n\t}\n\n\t/** @deprecated Use `evaluateTask()` from `omk-protocol`; verdicts are derived, not mutated. */\n\tsetVerdict(verdict: \"pass\" | \"fail\" | \"conditional\"): this {\n\t\tthis.verdict = verdict;\n\t\tthis.touch();\n\t\treturn this;\n\t}\n\n\t/** @deprecated Append a protocol Observation and re-evaluate instead of mutating evidence state. */\n\tupdateEvidenceStatus(claim: string, status: EvidenceStatus, gapReason?: string): this {\n\t\tconst item = this.requiredEvidence.find((e) => e.claim === claim);\n\t\tif (item) {\n\t\t\titem.status = status;\n\t\t\titem.gapReason = gapReason;\n\t\t\titem.timestamp = new Date().toISOString();\n\t\t\tthis.touch();\n\t\t}\n\t\treturn this;\n\t}\n\n\tprivate touch(): void {\n\t\tthis.updatedAt = new Date().toISOString();\n\t}\n\n\tbuild(): TaskContract {\n\t\treturn structuredClone({\n\t\t\tgoalId: this.goalId,\n\t\t\tcompletionClaim: this.completionClaim,\n\t\t\trequiredEvidence: this.requiredEvidence,\n\t\t\tfinalRisk: this.finalRisk,\n\t\t\tverdict: this.verdict,\n\t\t\tcreatedAt: this.createdAt,\n\t\t\tupdatedAt: this.updatedAt,\n\t\t});\n\t}\n\n\t/** Parse and validate a serialized TaskContract. Fails closed on any shape violation. */\n\tstatic fromJSON(json: string): TaskContract {\n\t\tconst raw: unknown = JSON.parse(json);\n\t\tif (raw === null || typeof raw !== \"object\" || Array.isArray(raw)) {\n\t\t\tthrow new Error(\"TaskContract JSON must be an object\");\n\t\t}\n\t\tconst { goalId, completionClaim, finalRisk, verdict, createdAt, updatedAt, requiredEvidence } = raw as Record<\n\t\t\tstring,\n\t\t\tunknown\n\t\t>;\n\t\tif (\n\t\t\ttypeof goalId !== \"string\" ||\n\t\t\ttypeof completionClaim !== \"string\" ||\n\t\t\ttypeof finalRisk !== \"string\" ||\n\t\t\ttypeof createdAt !== \"string\" ||\n\t\t\ttypeof updatedAt !== \"string\"\n\t\t) {\n\t\t\tthrow new Error(\"TaskContract JSON has missing or mistyped string fields\");\n\t\t}\n\t\tif (verdict !== \"pass\" && verdict !== \"fail\" && verdict !== \"conditional\") {\n\t\t\tthrow new Error(`TaskContract verdict must be pass|fail|conditional, got ${String(verdict)}`);\n\t\t}\n\t\tif (!Array.isArray(requiredEvidence)) {\n\t\t\tthrow new Error(\"TaskContract requiredEvidence must be an array\");\n\t\t}\n\t\treturn {\n\t\t\tgoalId,\n\t\t\tcompletionClaim,\n\t\t\tfinalRisk,\n\t\t\tverdict,\n\t\t\tcreatedAt,\n\t\t\tupdatedAt,\n\t\t\trequiredEvidence: requiredEvidence.map((item, index) => parseEvidenceItem(item, index)),\n\t\t};\n\t}\n\n\tstatic toJSON(contract: TaskContract): string {\n\t\treturn JSON.stringify(contract, null, 2);\n\t}\n}\n\nconst EVIDENCE_STATUSES: ReadonlySet<string> = new Set([\"pending\", \"gathering\", \"satisfied\", \"failed\", \"waived\"]);\n\nfunction optionalStringField(value: unknown, field: string, index: number): string | undefined {\n\tif (value !== undefined && typeof value !== \"string\") {\n\t\tthrow new Error(`TaskContract evidence[${index}].${field} must be a string when present`);\n\t}\n\treturn value;\n}\n\nfunction parseEvidenceItem(raw: unknown, index: number): EvidenceItem {\n\tif (raw === null || typeof raw !== \"object\" || Array.isArray(raw)) {\n\t\tthrow new Error(`TaskContract evidence[${index}] must be an object`);\n\t}\n\tconst item = raw as Record<string, unknown>;\n\tconst { claim, category, timestamp, status } = item;\n\tif (typeof claim !== \"string\" || typeof category !== \"string\" || typeof timestamp !== \"string\") {\n\t\tthrow new Error(`TaskContract evidence[${index}] has missing or mistyped fields`);\n\t}\n\tif (typeof status !== \"string\" || !EVIDENCE_STATUSES.has(status)) {\n\t\tthrow new Error(`TaskContract evidence[${index}] has invalid status ${String(status)}`);\n\t}\n\tconst receiptSchemaVersion = item.receiptSchemaVersion;\n\tif (receiptSchemaVersion !== undefined && receiptSchemaVersion !== 3) {\n\t\tthrow new Error(`TaskContract evidence[${index}].receiptSchemaVersion must be 3 when present`);\n\t}\n\tconst receiptCommandSha256 = optionalStringField(item.receiptCommandSha256, \"receiptCommandSha256\", index);\n\treturn {\n\t\tclaim,\n\t\tcategory: category as EvidenceItem[\"category\"],\n\t\ttimestamp,\n\t\tstatus: status as EvidenceStatus,\n\t\tartifactPath: optionalStringField(item.artifactPath, \"artifactPath\", index),\n\t\tverificationCommand: optionalStringField(item.verificationCommand, \"verificationCommand\", index),\n\t\thash: optionalStringField(item.hash, \"hash\", index),\n\t\treceiptId: optionalStringField(item.receiptId, \"receiptId\", index),\n\t\treceiptSchemaVersion,\n\t\t...(receiptCommandSha256 !== undefined\n\t\t\t? { receiptCommandSha256: parseSha256Hex(receiptCommandSha256, \"receiptCommandSha256\") }\n\t\t\t: {}),\n\t\treceiptLaneId: optionalStringField(item.receiptLaneId, \"receiptLaneId\", index),\n\t\tgapReason: optionalStringField(item.gapReason, \"gapReason\", index),\n\t};\n}\n\n// ============================================================================\n// ReplayLedger\n// ============================================================================\n\n/** prevHash sentinel for the first event in a replay chain. */\nconst GENESIS_HASH = \"genesis\";\n\nfunction computeEventHash(event: Omit<ReplayEvent, \"eventHash\">): string {\n\tconst metadata = [event.seq, event.type, event.timestamp, event.goalId, event.laneId ?? null];\n\tconst material =\n\t\tevent.payloadHashAlgorithm === undefined\n\t\t\t? [...metadata, event.payloadHash, event.prevHash]\n\t\t\t: [...metadata, event.payloadHashAlgorithm, event.payloadHash, event.prevHash];\n\treturn sha256(JSON.stringify(material));\n}\n\nfunction parseReplayEventLine(line: string, lineNumber: number): ReplayEvent {\n\tlet raw: unknown;\n\ttry {\n\t\traw = JSON.parse(line);\n\t} catch {\n\t\tthrow new Error(`Replay ledger corrupted at line ${lineNumber}: invalid JSON`);\n\t}\n\tif (raw === null || typeof raw !== \"object\" || Array.isArray(raw)) {\n\t\tthrow new Error(`Replay ledger corrupted at line ${lineNumber}: event must be an object`);\n\t}\n\tconst event = raw as Record<string, unknown>;\n\tconst { seq, type, timestamp, goalId, laneId, payloadHashAlgorithm, payloadHash, prevHash, eventHash } = event;\n\tif (\n\t\ttypeof seq !== \"number\" ||\n\t\ttypeof type !== \"string\" ||\n\t\ttypeof timestamp !== \"string\" ||\n\t\ttypeof goalId !== \"string\" ||\n\t\ttypeof payloadHash !== \"string\" ||\n\t\ttypeof prevHash !== \"string\" ||\n\t\ttypeof eventHash !== \"string\" ||\n\t\t(laneId !== undefined && typeof laneId !== \"string\") ||\n\t\t!(\"payload\" in event)\n\t) {\n\t\tthrow new Error(`Replay ledger corrupted at line ${lineNumber}: event fields are missing or mistyped`);\n\t}\n\tif (\n\t\tpayloadHashAlgorithm !== undefined &&\n\t\tpayloadHashAlgorithm !== LEGACY_REPLAY_PAYLOAD_HASH_ALGORITHM &&\n\t\tpayloadHashAlgorithm !== JCS_REPLAY_PAYLOAD_HASH_ALGORITHM\n\t) {\n\t\tthrow new Error(`Replay ledger corrupted at line ${lineNumber}: unsupported payload hash algorithm`);\n\t}\n\tconst parsed: ReplayEvent = {\n\t\tseq,\n\t\ttype: type as ReplayEvent[\"type\"],\n\t\ttimestamp,\n\t\tgoalId,\n\t\tlaneId,\n\t\tpayload: event.payload,\n\t\tpayloadHash,\n\t\tprevHash,\n\t\teventHash,\n\t};\n\treturn payloadHashAlgorithm === undefined ? parsed : { ...parsed, payloadHashAlgorithm };\n}\n\nfunction parseReplayLedgerBytes(bytes: Buffer, goalId: string): ReplayEvent[] {\n\tconst lines = bytes\n\t\t.toString(\"utf8\")\n\t\t.split(\"\\n\")\n\t\t.filter((line) => line.trim().length > 0);\n\tconst events: ReplayEvent[] = [];\n\tlet prevHash = GENESIS_HASH;\n\tfor (let index = 0; index < lines.length; index++) {\n\t\tconst event = parseReplayEventLine(lines[index], index + 1);\n\t\tif (event.goalId !== goalId) throw new Error(`Replay ledger goal mismatch at line ${index + 1}`);\n\t\tif (event.seq !== index + 1) {\n\t\t\tthrow new Error(`Replay ledger corrupted at line ${index + 1}: expected seq ${index + 1}, got ${event.seq}`);\n\t\t}\n\t\tif (event.prevHash !== prevHash) throw new Error(`Replay ledger chain broken at line ${index + 1}`);\n\t\tconst payloadHashAlgorithm = event.payloadHashAlgorithm ?? LEGACY_REPLAY_PAYLOAD_HASH_ALGORITHM;\n\t\tif (computeReplayPayloadHash(event.payload, payloadHashAlgorithm) !== event.payloadHash) {\n\t\t\tthrow new Error(`Replay ledger payload tampered at line ${index + 1} (seq ${event.seq})`);\n\t\t}\n\t\tif (computeEventHash(event) !== event.eventHash) {\n\t\t\tthrow new Error(`Replay ledger event hash mismatch at line ${index + 1} (seq ${event.seq})`);\n\t\t}\n\t\tprevHash = event.eventHash;\n\t\tevents.push(event);\n\t}\n\treturn events;\n}\n\nexport class ReplayLedgerManager {\n\tprivate readonly goalId: string;\n\tprivate readonly ledgerPath: string;\n\tprivate readonly store: ReplayLedgerStore;\n\tprivate events: ReplayEvent[] = [];\n\tprivate committedHead: ReplayLedgerHead;\n\n\tconstructor(goalId: string, ledgerPath: string, expectedHead?: ReplayLedgerHead) {\n\t\tthis.goalId = goalId;\n\t\tthis.ledgerPath = ledgerPath;\n\t\tthis.committedHead = { fileIdentity: null, size: 0, lastSeq: 0, lastHash: GENESIS_HASH };\n\t\tthis.store = new ReplayLedgerStore(ledgerPath, (bytes) => {\n\t\t\tconst events = parseReplayLedgerBytes(bytes, goalId);\n\t\t\tconst last = events[events.length - 1];\n\t\t\treturn { lastSeq: last?.seq ?? 0, lastHash: last?.eventHash ?? GENESIS_HASH };\n\t\t});\n\t\tthis.refresh(expectedHead);\n\t}\n\n\tprivate refresh(expectedHead?: ReplayLedgerHead): void {\n\t\tconst snapshot = this.store.load(expectedHead);\n\t\tthis.events = parseReplayLedgerBytes(snapshot.bytes, this.goalId);\n\t\tthis.committedHead = snapshot.head;\n\t}\n\n\tappend(\n\t\tevent: Omit<ReplayEvent, \"seq\" | \"timestamp\" | \"payloadHashAlgorithm\" | \"payloadHash\" | \"prevHash\" | \"eventHash\">,\n\t\texpectedHead: ReplayLedgerHead = this.committedHead,\n\t): ReplayEvent {\n\t\tif (event.goalId !== this.goalId) throw new Error(\"Replay event goalId does not match the ledger\");\n\t\tif (!replayLedgerHeadsEqual(expectedHead, this.committedHead)) {\n\t\t\tthrow new Error(\"Replay manager expected-head CAS is stale\");\n\t\t}\n\t\tconst payloadHashAlgorithm = JCS_REPLAY_PAYLOAD_HASH_ALGORITHM;\n\t\tconst payloadHash = computeReplayPayloadHash(event.payload, payloadHashAlgorithm);\n\t\tconst chained: Omit<ReplayEvent, \"eventHash\"> = {\n\t\t\t...event,\n\t\t\tseq: expectedHead.lastSeq + 1,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tpayloadHashAlgorithm,\n\t\t\tpayloadHash,\n\t\t\tprevHash: expectedHead.lastHash,\n\t\t};\n\t\tconst fullEvent: ReplayEvent = { ...chained, eventHash: computeEventHash(chained) };\n\t\tthis.committedHead = this.store.append(\n\t\t\tBuffer.from(`${JSON.stringify(fullEvent)}\\n`, \"utf8\"),\n\t\t\tfullEvent.seq,\n\t\t\tfullEvent.eventHash,\n\t\t\texpectedHead,\n\t\t);\n\t\tthis.events.push(fullEvent);\n\t\treturn structuredClone(fullEvent);\n\t}\n\n\t/** Compatibility no-op that still verifies the caller's expected committed head. */\n\tpersist(expectedHead: ReplayLedgerHead = this.committedHead): void {\n\t\tthis.getVerifiedSnapshot(expectedHead);\n\t}\n\n\tload(expectedHead: ReplayLedgerHead = this.committedHead): void {\n\t\tthis.refresh(expectedHead);\n\t}\n\n\tgetCommittedHead(): ReplayLedgerHead {\n\t\treturn structuredClone(this.committedHead);\n\t}\n\n\tgetVerifiedSnapshot(expectedHead: ReplayLedgerHead = this.committedHead): VerifiedReplayLedgerSnapshot {\n\t\tthis.refresh(expectedHead);\n\t\treturn structuredClone({ events: this.events, head: this.committedHead });\n\t}\n\n\tgetEvents(): ReadonlyArray<ReplayEvent> {\n\t\treturn structuredClone(this.events);\n\t}\n\n\tgetLedger(): Readonly<ReplayLedger> {\n\t\treturn structuredClone({\n\t\t\tgoalId: this.goalId,\n\t\t\tevents: this.events,\n\t\t\tledgerPath: this.ledgerPath,\n\t\t\tlastPersistedSeq: this.committedHead.lastSeq,\n\t\t});\n\t}\n\n\treplay<T>(handler: (event: ReplayEvent) => T | undefined): T[] {\n\t\treturn this.events.map(handler).filter((result): result is T => result !== undefined);\n\t}\n\n\texportToFile(path: string): void {\n\t\tensureDir(path);\n\t\twriteFileSync(path, JSON.stringify(this.events, null, 2), \"utf8\");\n\t}\n}\n\n// ============================================================================\n// EvidenceGate\n// ============================================================================\n\nexport interface EvidenceGateOptions {\n\t/** Minimum number of satisfied evidence items required. */\n\tminEvidenceCount?: number;\n\t/** Require at least one artifact with a SHA-256 hash in explicit legacy mode. */\n\trequireHash?: boolean;\n\t/** Require at least one verification command in explicit legacy mode. */\n\trequireVerificationCommand?: boolean;\n\t/** Receipt policy. Defaults to prefer; legacy must be selected explicitly. */\n\treceiptMode?: EvidenceReceiptMode;\n\t/** Resolve a serialized or decoded receipt by ID. The gate validates the returned value. */\n\tresolveReceipt?: (receiptId: string) => unknown;\n\t/** Strict source: one expected-head, file-identity, suffix, and chain-verified snapshot. */\n\tresolveVerifiedLedgerSnapshot?: () => VerifiedReplayLedgerSnapshot;\n\t/** Prefer-mode migration source; strict mode requires resolveVerifiedLedgerSnapshot. */\n\tresolveLedgerEvent?: (seq: number) => ReplayEvent | undefined;\n\t/** Recapture the receipt's workspace scope (same kind and scope) for freshness comparison. */\n\tcaptureWorkspaceFingerprint?: (scope: WorkspaceScope) => unknown;\n\t/**\n\t * Optional freshness source: the latest replay-ledger sequence of a workspace mutation\n\t * relevant to the given scope, or null/undefined when none is known. When configured,\n\t * the receipt's verified ledger seq must strictly exceed this value; a throwing or\n\t * out-of-contract source is a hard block (positive safe integers only).\n\t */\n\tresolveLatestWorkspaceMutationSeq?: (scope: WorkspaceScope) => number | null | undefined;\n\t/** Ephemeral trust anchor used to verify the original command's keyed attestation. */\n\tcommandAttestationBinder?: Pick<CommandHmacBinder, \"verify\">;\n\t/** Resolve the original command inside the same trust boundary as the binder. */\n\tresolveAttestedCommand?: (receiptId: string) => EvidenceCommandDescriptor | undefined;\n}\n\ninterface ReceiptCheckIssue {\n\treadonly message: string;\n\treadonly hard: boolean;\n}\n\nfunction receiptCheckIssue(message: string, hard: boolean): ReceiptCheckIssue {\n\treturn { message, hard };\n}\n\nfunction receiptIssue(\n\titem: EvidenceItem,\n\tcontract: TaskContract,\n\toptions: EvidenceGateOptions,\n): ReceiptCheckIssue | undefined {\n\tif (!item.receiptId) {\n\t\treturn receiptCheckIssue(`Execution receipt is missing for evidence \"${item.claim}\".`, false);\n\t}\n\tconst strict = options.receiptMode === \"strict\";\n\tif (item.receiptSchemaVersion !== 3 && (item.receiptSchemaVersion !== undefined || strict)) {\n\t\treturn receiptCheckIssue(`Execution receipt schema metadata is invalid for evidence \"${item.claim}\".`, true);\n\t}\n\tif (!options.resolveReceipt) {\n\t\treturn receiptCheckIssue(`Execution receipt resolver is missing for evidence \"${item.claim}\".`, false);\n\t}\n\n\tlet rawReceipt: unknown;\n\ttry {\n\t\trawReceipt = options.resolveReceipt(item.receiptId);\n\t} catch {\n\t\treturn receiptCheckIssue(`Execution receipt resolver failed for evidence \"${item.claim}\".`, true);\n\t}\n\tif (rawReceipt === undefined) {\n\t\treturn receiptCheckIssue(`Execution receipt is missing for evidence \"${item.claim}\".`, false);\n\t}\n\n\ttry {\n\t\tconst receipt = validateEvidenceReceipt(rawReceipt);\n\t\tif (receipt.core.receiptId !== item.receiptId) {\n\t\t\treturn receiptCheckIssue(`Execution receipt ID does not match evidence \"${item.claim}\".`, true);\n\t\t}\n\t\tif (receipt.core.goalId !== contract.goalId) {\n\t\t\treturn receiptCheckIssue(`Execution receipt goal does not match evidence \"${item.claim}\".`, true);\n\t\t}\n\t\tif (receipt.core.claim !== item.claim) {\n\t\t\treturn receiptCheckIssue(`Execution receipt claim does not match evidence \"${item.claim}\".`, true);\n\t\t}\n\t\tif (receipt.core.status !== \"passed\" || receipt.core.exitCode !== 0) {\n\t\t\treturn receiptCheckIssue(\n\t\t\t\t`Execution receipt for evidence \"${item.claim}\" did not pass with exit code 0.`,\n\t\t\t\ttrue,\n\t\t\t);\n\t\t}\n\n\t\tif (item.receiptCommandSha256 === undefined) {\n\t\t\treturn receiptCheckIssue(`Execution receipt command binding is missing for evidence \"${item.claim}\".`, false);\n\t\t}\n\t\tconst receiptCommandSha256 = computeEvidenceCommandSha256(receipt.core.command);\n\t\tif (!constantTimeSha256Equal(item.receiptCommandSha256, receiptCommandSha256)) {\n\t\t\treturn receiptCheckIssue(`Execution receipt command does not match evidence \"${item.claim}\".`, true);\n\t\t}\n\t\tconst attestationIssue = verifyCommandAttestation({\n\t\t\treceiptId: receipt.core.receiptId,\n\t\t\tbinding: receipt.core.commandBinding,\n\t\t\tpersistedCommand: receipt.core.command,\n\t\t\tpersistedSummary: receipt.core.commandRedaction,\n\t\t\tbinder: options.commandAttestationBinder,\n\t\t\tresolveCommand: options.resolveAttestedCommand,\n\t\t\tredact: redactCommandDescriptor,\n\t\t});\n\t\tif (attestationIssue !== undefined) {\n\t\t\treturn receiptCheckIssue(\n\t\t\t\t`Execution receipt command attestation ${attestationIssue.detail} for evidence \"${item.claim}\".`,\n\t\t\t\tattestationIssue.hard,\n\t\t\t);\n\t\t}\n\n\t\tif (receipt.core.laneId !== undefined && item.receiptLaneId === undefined) {\n\t\t\treturn receiptCheckIssue(`Execution receipt lane binding is missing for evidence \"${item.claim}\".`, false);\n\t\t}\n\t\tif (item.receiptLaneId !== receipt.core.laneId) {\n\t\t\treturn receiptCheckIssue(`Execution receipt lane does not match evidence \"${item.claim}\".`, true);\n\t\t}\n\n\t\tconst workspaceIssue = verifyWorkspaceBinding(receipt.core.workspaceAfter, options.captureWorkspaceFingerprint);\n\t\tif (workspaceIssue !== undefined) {\n\t\t\treturn receiptCheckIssue(\n\t\t\t\t`Execution receipt ${workspaceIssue.detail} for evidence \"${item.claim}\".`,\n\t\t\t\tworkspaceIssue.hard,\n\t\t\t);\n\t\t}\n\n\t\tlet snapshot: VerifiedReplayLedgerSnapshot | undefined;\n\t\tif (options.resolveVerifiedLedgerSnapshot !== undefined) {\n\t\t\ttry {\n\t\t\t\tsnapshot = parseVerifiedLedgerSnapshot(\n\t\t\t\t\toptions.resolveVerifiedLedgerSnapshot(),\n\t\t\t\t\tcontract.goalId,\n\t\t\t\t\tparseReplayLedgerBytes,\n\t\t\t\t);\n\t\t\t} catch {\n\t\t\t\treturn receiptCheckIssue(\n\t\t\t\t\t`Execution receipt verified ledger snapshot failed for evidence \"${item.claim}\".`,\n\t\t\t\t\ttrue,\n\t\t\t\t);\n\t\t\t}\n\t\t} else if (strict) {\n\t\t\treturn receiptCheckIssue(\n\t\t\t\t`Execution receipt verified ledger snapshot is missing for evidence \"${item.claim}\".`,\n\t\t\t\tfalse,\n\t\t\t);\n\t\t}\n\t\tlet latestMutationSeq =\n\t\t\tsnapshot === undefined\n\t\t\t\t? null\n\t\t\t\t: latestRelevantWorkspaceMutationSeq(snapshot.events, receipt.core.workspaceAfter.scope);\n\t\tif (snapshot === undefined && options.resolveLatestWorkspaceMutationSeq !== undefined) {\n\t\t\tlet resolved: unknown;\n\t\t\ttry {\n\t\t\t\tresolved = options.resolveLatestWorkspaceMutationSeq(receipt.core.workspaceAfter.scope);\n\t\t\t} catch {\n\t\t\t\treturn receiptCheckIssue(\n\t\t\t\t\t`Execution receipt workspace-mutation freshness source failed for evidence \"${item.claim}\".`,\n\t\t\t\t\ttrue,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (resolved !== null && resolved !== undefined) {\n\t\t\t\tif (!Number.isSafeInteger(resolved) || (resolved as number) <= 0) {\n\t\t\t\t\treturn receiptCheckIssue(\n\t\t\t\t\t\t`Execution receipt workspace-mutation freshness source is malformed for evidence \"${item.claim}\".`,\n\t\t\t\t\t\ttrue,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tlatestMutationSeq = resolved as number;\n\t\t\t}\n\t\t}\n\n\t\tconst binding = receipt.envelope.ledgerBinding;\n\t\tif (!binding) {\n\t\t\treturn receiptCheckIssue(\n\t\t\t\t`Execution receipt ledger binding is missing for evidence \"${item.claim}\".`,\n\t\t\t\tlatestMutationSeq !== null,\n\t\t\t);\n\t\t}\n\t\tconst event = snapshot\n\t\t\t? snapshot.events.find((candidate) => candidate.seq === binding.seq)\n\t\t\t: options.resolveLedgerEvent?.(binding.seq);\n\t\tif (!event && snapshot === undefined && !options.resolveLedgerEvent) {\n\t\t\treturn receiptCheckIssue(\n\t\t\t\t`Execution receipt ledger resolver is missing for evidence \"${item.claim}\".`,\n\t\t\t\tlatestMutationSeq !== null,\n\t\t\t);\n\t\t}\n\t\tconst replayPayload = evidenceReceiptReplayPayload(receipt);\n\t\tif (\n\t\t\t!event ||\n\t\t\tevent.seq !== binding.seq ||\n\t\t\tevent.type !== \"evidence_receipt\" ||\n\t\t\tevent.goalId !== contract.goalId ||\n\t\t\tevent.laneId !== receipt.core.laneId ||\n\t\t\t!constantTimeSha256Equal(event.eventHash, binding.eventHash) ||\n\t\t\t!replayPayloadMatches(event.payload, replayPayload.receiptId, replayPayload.coreSha256)\n\t\t) {\n\t\t\treturn receiptCheckIssue(`Execution receipt ledger binding does not match evidence \"${item.claim}\".`, true);\n\t\t}\n\t\tif (latestMutationSeq !== null && event.seq <= latestMutationSeq) {\n\t\t\treturn receiptCheckIssue(\n\t\t\t\t`Execution receipt is stale: workspace mutation seq ${latestMutationSeq} does not precede receipt ledger seq ${event.seq} for evidence \"${item.claim}\".`,\n\t\t\t\ttrue,\n\t\t\t);\n\t\t}\n\t} catch {\n\t\treturn receiptCheckIssue(`Execution receipt is invalid for evidence \"${item.claim}\".`, true);\n\t}\n\treturn undefined;\n}\n\nexport class EvidenceGate {\n\tprivate options: EvidenceGateOptions;\n\n\tconstructor(options: EvidenceGateOptions = {}) {\n\t\tthis.options = {\n\t\t\tminEvidenceCount: 1,\n\t\t\trequireHash: true,\n\t\t\trequireVerificationCommand: true,\n\t\t\treceiptMode: \"prefer\",\n\t\t\t...options,\n\t\t};\n\t}\n\n\tcheck(contract: TaskContract): MergeGateResult {\n\t\tconst evidence = contract.requiredEvidence;\n\t\tconst satisfied = evidence.filter((e) => e.status === \"satisfied\");\n\t\tconst failed = evidence.filter((e) => e.status === \"failed\");\n\t\tconst pending = evidence.filter((e) => e.status === \"pending\" || e.status === \"gathering\");\n\t\tconst mode = this.options.receiptMode ?? \"prefer\";\n\t\tconst checks: string[] = [];\n\t\tlet hardReceiptFailure = false;\n\n\t\tif (satisfied.length < (this.options.minEvidenceCount ?? 1)) {\n\t\t\tchecks.push(`Only ${satisfied.length}/${this.options.minEvidenceCount} required evidence items satisfied.`);\n\t\t}\n\t\tif (failed.length > 0) {\n\t\t\tchecks.push(`${failed.length} evidence item(s) failed.`);\n\t\t}\n\n\t\tif (mode === \"legacy\") {\n\t\t\tif (this.options.requireHash) {\n\t\t\t\tconst hashed = satisfied.filter((e) => e.hash && e.hash.length > 0);\n\t\t\t\tif (hashed.length === 0) checks.push(\"No satisfied evidence has a SHA-256 hash.\");\n\t\t\t}\n\t\t\tif (this.options.requireVerificationCommand) {\n\t\t\t\tconst withCommand = satisfied.filter((e) => e.verificationCommand && e.verificationCommand.length > 0);\n\t\t\t\tif (withCommand.length === 0) checks.push(\"No satisfied evidence has a verification command.\");\n\t\t\t}\n\t\t} else {\n\t\t\tconst unsatisfied = evidence.filter((item) => item.status !== \"satisfied\");\n\t\t\tif (unsatisfied.length > 0) {\n\t\t\t\tchecks.push(`${unsatisfied.length} required evidence item(s) are not satisfied.`);\n\t\t\t}\n\t\t\tfor (const item of satisfied) {\n\t\t\t\tconst issue = receiptIssue(item, contract, this.options);\n\t\t\t\tif (issue) {\n\t\t\t\t\tchecks.push(issue.message);\n\t\t\t\t\thardReceiptFailure ||= issue.hard;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (contract.verdict === \"fail\" || (mode !== \"legacy\" && contract.verdict !== \"pass\")) {\n\t\t\tchecks.push(`Task contract verdict is '${contract.verdict}'.`);\n\t\t}\n\n\t\tlet status: MergeGateStatus;\n\t\tlet reason: string;\n\t\tlet suggestion: string | undefined;\n\t\tif (checks.length === 0) {\n\t\t\tstatus = \"open\";\n\t\t\treason = `Evidence gate passed: ${satisfied.length}/${evidence.length} evidence items satisfied.`;\n\t\t} else {\n\t\t\tconst contractFailure = mode === \"legacy\" ? contract.verdict === \"fail\" : contract.verdict !== \"pass\";\n\t\t\tconst hasHardFailure = failed.length > 0 || contractFailure || hardReceiptFailure || mode === \"strict\";\n\t\t\tstatus = hasHardFailure ? \"blocked\" : mode === \"prefer\" || pending.length > 0 ? \"conditional\" : \"blocked\";\n\t\t\treason = checks.join(\"; \");\n\t\t\tsuggestion = `Gather remaining evidence (${pending.length} pending) and re-run verification.`;\n\t\t}\n\n\t\treturn {\n\t\t\tgateId: \"evidence-gate\",\n\t\t\tstatus,\n\t\t\treason,\n\t\t\tsuggestion,\n\t\t\tevidenceChecked: evidence,\n\t\t};\n\t}\n}\n\n// ============================================================================\n// FailClosedMergeGate\n// ============================================================================\n\nexport class FailClosedMergeGate {\n\tprivate gates: EvidenceGate[];\n\n\tconstructor(gates: EvidenceGate[] = [new EvidenceGate()]) {\n\t\tthis.gates = gates;\n\t}\n\n\tcheck(contract: TaskContract): MergeGateResult {\n\t\tconst results = this.gates.map((gate) => gate.check(contract));\n\t\tconst blocked = results.filter((r) => r.status === \"blocked\");\n\t\tconst conditional = results.filter((r) => r.status === \"conditional\");\n\n\t\tif (blocked.length > 0) {\n\t\t\treturn {\n\t\t\t\tgateId: \"fail-closed-merge-gate\",\n\t\t\t\tstatus: \"blocked\",\n\t\t\t\treason: `Blocked by ${blocked.length} gate(s): ${blocked.map((b) => b.reason).join(\"; \")}`,\n\t\t\t\tsuggestion: \"Resolve all blocking conditions before merge.\",\n\t\t\t\tevidenceChecked: contract.requiredEvidence,\n\t\t\t};\n\t\t}\n\n\t\tif (conditional.length > 0) {\n\t\t\treturn {\n\t\t\t\tgateId: \"fail-closed-merge-gate\",\n\t\t\t\tstatus: \"conditional\",\n\t\t\t\treason: `Conditional pass: ${conditional.length} gate(s) have pending conditions.`,\n\t\t\t\tsuggestion: \"Complete pending evidence or waive with explicit approval.\",\n\t\t\t\tevidenceChecked: contract.requiredEvidence,\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tgateId: \"fail-closed-merge-gate\",\n\t\t\tstatus: \"open\",\n\t\t\treason: \"All merge gates passed. Evidence verified and contract verdict is acceptable.\",\n\t\t\tevidenceChecked: contract.requiredEvidence,\n\t\t};\n\t}\n}\n\n// ============================================================================\n// Verify Reporter v2\n// ============================================================================\n\n/** Escape pipes/newlines so untrusted claim or command text cannot restructure the report table. */\nfunction escapeTableCell(value: string): string {\n\treturn value.replace(/\\\\/g, \"\\\\\\\\\").replace(/\\|/g, \"\\\\|\").replace(/\\r?\\n/g, \" \");\n}\n\nexport interface VerifyReporterV2Options {\n\toutputDir: string;\n\tgoalId: string;\n}\n\nexport class VerifyReporterV2 {\n\tprivate options: VerifyReporterV2Options;\n\n\tconstructor(options: VerifyReporterV2Options) {\n\t\tthis.options = options;\n\t}\n\n\trender(contract: TaskContract, mergeGate: MergeGateResult): string {\n\t\tconst lines: string[] = [\n\t\t\t`## OMK Verification Report v2 — ${contract.goalId}`,\n\t\t\t\"\",\n\t\t\t\"### Contract\",\n\t\t\t\"\",\n\t\t\t`| Field | Value |`,\n\t\t\t`|-------|-------|`,\n\t\t\t`| Claim | ${escapeTableCell(contract.completionClaim)} |`,\n\t\t\t`| Verdict | ${contract.verdict} |`,\n\t\t\t`| Final Risk | ${escapeTableCell(contract.finalRisk)} |`,\n\t\t\t\"\",\n\t\t\t\"### Evidence\",\n\t\t\t\"\",\n\t\t\t`| Claim | Status | Artifact | Command |`,\n\t\t\t`|-------|--------|----------|----------|`,\n\t\t];\n\n\t\tfor (const ev of contract.requiredEvidence) {\n\t\t\tlines.push(\n\t\t\t\t`| ${escapeTableCell(ev.claim)} | ${ev.status} | ${escapeTableCell(ev.artifactPath ?? \"—\")} | ${escapeTableCell(ev.verificationCommand ?? \"—\")} |`,\n\t\t\t);\n\t\t}\n\n\t\tlines.push(\n\t\t\t\"\",\n\t\t\t\"### Merge Gate\",\n\t\t\t\"\",\n\t\t\t`| Gate | Status | Reason |`,\n\t\t\t`|------|--------|--------|`,\n\t\t\t`| ${mergeGate.gateId} | ${mergeGate.status} | ${escapeTableCell(mergeGate.reason)} |`,\n\t\t\t\"\",\n\t\t);\n\n\t\tif (mergeGate.suggestion) {\n\t\t\tlines.push(`**Suggestion:** ${mergeGate.suggestion}`, \"\");\n\t\t}\n\n\t\treturn lines.join(\"\\n\");\n\t}\n\n\twrite(contract: TaskContract, mergeGate: MergeGateResult): string {\n\t\tconst markdown = this.render(contract, mergeGate);\n\t\tconst path = join(this.options.outputDir, `${this.options.goalId}.verify.md`);\n\t\tensureDir(path);\n\t\twriteFileSync(path, markdown, \"utf-8\");\n\t\treturn path;\n\t}\n}\n"]}
1
+ {"version":3,"file":"evidence-system.js","sourceRoot":"","sources":["../../src/guardrails/evidence-system.ts"],"names":[],"mappings":"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","sourcesContent":["// allow: SIZE_OK - evidence ledger guardrails: tamper-evident replay chain + fail-closed parsing.\nimport { createHash } from \"node:crypto\";\nimport { existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport type {\n\tEvidenceCommandDescriptor,\n\tEvidenceItem,\n\tEvidenceReceiptMode,\n\tEvidenceStatus,\n\tMergeGateResult,\n\tMergeGateStatus,\n\tReplayEvent,\n\tReplayLedger,\n\tReplayLedgerHead,\n\tTaskContract,\n\tVerifiedReplayLedgerSnapshot,\n\tWorkspaceScope,\n} from \"../types/evidence.ts\";\nimport { redactCommandDescriptor } from \"./command-redaction.ts\";\nimport {\n\ttype CommandHmacBinder,\n\tlatestRelevantWorkspaceMutationSeq,\n\tparseVerifiedLedgerSnapshot,\n\treplayPayloadMatches,\n\tverifyCommandAttestation,\n\tverifyWorkspaceBinding,\n} from \"./evidence-attestation.ts\";\n\nexport { latestRelevantWorkspaceMutationSeq } from \"./evidence-attestation.ts\";\n\nimport {\n\tcomputeEvidenceCommandSha256,\n\tconstantTimeSha256Equal,\n\tevidenceReceiptReplayPayload,\n\tparseSha256Hex,\n\tvalidateEvidenceReceipt,\n} from \"./evidence-receipt.ts\";\nimport { combineMergeGateResults } from \"./merge-gate-result.ts\";\nimport { ReplayLedgerStore, replayLedgerHeadsEqual } from \"./replay-ledger-store.ts\";\nimport {\n\tcomputeReplayPayloadHash,\n\tJCS_REPLAY_PAYLOAD_HASH_ALGORITHM,\n\tLEGACY_REPLAY_PAYLOAD_HASH_ALGORITHM,\n} from \"./replay-payload-hash.ts\";\n\nfunction sha256(input: string): string {\n\treturn createHash(\"sha256\").update(input).digest(\"hex\");\n}\n\nfunction ensureDir(path: string): void {\n\tconst dir = dirname(path);\n\tif (!existsSync(dir)) {\n\t\tmkdirSync(dir, { recursive: true });\n\t}\n}\n\n// ============================================================================\n// TaskContract\n// ============================================================================\n\nexport class TaskContractBuilder {\n\tprivate goalId: string;\n\tprivate completionClaim: string = \"\";\n\tprivate requiredEvidence: EvidenceItem[] = [];\n\tprivate finalRisk: string = \"\";\n\tprivate verdict: \"pass\" | \"fail\" | \"conditional\" = \"fail\";\n\tprivate createdAt: string;\n\tprivate updatedAt: string;\n\n\tconstructor(goalId: string) {\n\t\tthis.goalId = goalId;\n\t\tconst now = new Date().toISOString();\n\t\tthis.createdAt = now;\n\t\tthis.updatedAt = now;\n\t}\n\n\tsetClaim(claim: string): this {\n\t\tthis.completionClaim = claim;\n\t\tthis.touch();\n\t\treturn this;\n\t}\n\n\taddRequiredEvidence(evidence: Omit<EvidenceItem, \"timestamp\" | \"status\">): this {\n\t\tthis.requiredEvidence.push({\n\t\t\t...evidence,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tstatus: \"pending\",\n\t\t});\n\t\tthis.touch();\n\t\treturn this;\n\t}\n\n\tsetFinalRisk(risk: string): this {\n\t\tthis.finalRisk = risk;\n\t\tthis.touch();\n\t\treturn this;\n\t}\n\n\t/** @deprecated Use `evaluateTask()` from `omk-protocol`; verdicts are derived, not mutated. */\n\tsetVerdict(verdict: \"pass\" | \"fail\" | \"conditional\"): this {\n\t\tthis.verdict = verdict;\n\t\tthis.touch();\n\t\treturn this;\n\t}\n\n\t/** @deprecated Append a protocol Observation and re-evaluate instead of mutating evidence state. */\n\tupdateEvidenceStatus(claim: string, status: EvidenceStatus, gapReason?: string): this {\n\t\tconst item = this.requiredEvidence.find((e) => e.claim === claim);\n\t\tif (item) {\n\t\t\titem.status = status;\n\t\t\titem.gapReason = gapReason;\n\t\t\titem.timestamp = new Date().toISOString();\n\t\t\tthis.touch();\n\t\t}\n\t\treturn this;\n\t}\n\n\tprivate touch(): void {\n\t\tthis.updatedAt = new Date().toISOString();\n\t}\n\n\tbuild(): TaskContract {\n\t\treturn structuredClone({\n\t\t\tgoalId: this.goalId,\n\t\t\tcompletionClaim: this.completionClaim,\n\t\t\trequiredEvidence: this.requiredEvidence,\n\t\t\tfinalRisk: this.finalRisk,\n\t\t\tverdict: this.verdict,\n\t\t\tcreatedAt: this.createdAt,\n\t\t\tupdatedAt: this.updatedAt,\n\t\t});\n\t}\n\n\t/** Parse and validate a serialized TaskContract. Fails closed on any shape violation. */\n\tstatic fromJSON(json: string): TaskContract {\n\t\tlet raw: unknown;\n\t\ttry {\n\t\t\traw = JSON.parse(json);\n\t\t} catch (error) {\n\t\t\tif (error instanceof SyntaxError) throw new SyntaxError(\"Invalid TaskContract JSON\");\n\t\t\tthrow error;\n\t\t}\n\t\tif (raw === null || typeof raw !== \"object\" || Array.isArray(raw)) {\n\t\t\tthrow new Error(\"TaskContract JSON must be an object\");\n\t\t}\n\t\tconst { goalId, completionClaim, finalRisk, verdict, createdAt, updatedAt, requiredEvidence } = raw as Record<\n\t\t\tstring,\n\t\t\tunknown\n\t\t>;\n\t\tif (\n\t\t\ttypeof goalId !== \"string\" ||\n\t\t\ttypeof completionClaim !== \"string\" ||\n\t\t\ttypeof finalRisk !== \"string\" ||\n\t\t\ttypeof createdAt !== \"string\" ||\n\t\t\ttypeof updatedAt !== \"string\"\n\t\t) {\n\t\t\tthrow new Error(\"TaskContract JSON has missing or mistyped string fields\");\n\t\t}\n\t\tif (verdict !== \"pass\" && verdict !== \"fail\" && verdict !== \"conditional\") {\n\t\t\tthrow new Error(`TaskContract verdict must be pass|fail|conditional, got ${String(verdict)}`);\n\t\t}\n\t\tif (!Array.isArray(requiredEvidence)) {\n\t\t\tthrow new Error(\"TaskContract requiredEvidence must be an array\");\n\t\t}\n\t\treturn {\n\t\t\tgoalId,\n\t\t\tcompletionClaim,\n\t\t\tfinalRisk,\n\t\t\tverdict,\n\t\t\tcreatedAt,\n\t\t\tupdatedAt,\n\t\t\trequiredEvidence: requiredEvidence.map((item, index) => parseEvidenceItem(item, index)),\n\t\t};\n\t}\n\n\tstatic toJSON(contract: TaskContract): string {\n\t\treturn JSON.stringify(contract, null, 2);\n\t}\n}\n\nconst EVIDENCE_STATUSES: ReadonlySet<string> = new Set([\"pending\", \"gathering\", \"satisfied\", \"failed\", \"waived\"]);\n\nfunction optionalStringField(value: unknown, field: string, index: number): string | undefined {\n\tif (value !== undefined && typeof value !== \"string\") {\n\t\tthrow new Error(`TaskContract evidence[${index}].${field} must be a string when present`);\n\t}\n\treturn value;\n}\n\nfunction parseEvidenceItem(raw: unknown, index: number): EvidenceItem {\n\tif (raw === null || typeof raw !== \"object\" || Array.isArray(raw)) {\n\t\tthrow new Error(`TaskContract evidence[${index}] must be an object`);\n\t}\n\tconst item = raw as Record<string, unknown>;\n\tconst { claim, category, timestamp, status } = item;\n\tif (typeof claim !== \"string\" || typeof category !== \"string\" || typeof timestamp !== \"string\") {\n\t\tthrow new Error(`TaskContract evidence[${index}] has missing or mistyped fields`);\n\t}\n\tif (typeof status !== \"string\" || !EVIDENCE_STATUSES.has(status)) {\n\t\tthrow new Error(`TaskContract evidence[${index}] has invalid status ${String(status)}`);\n\t}\n\tconst receiptSchemaVersion = item.receiptSchemaVersion;\n\tif (receiptSchemaVersion !== undefined && receiptSchemaVersion !== 3) {\n\t\tthrow new Error(`TaskContract evidence[${index}].receiptSchemaVersion must be 3 when present`);\n\t}\n\tconst receiptCommandSha256 = optionalStringField(item.receiptCommandSha256, \"receiptCommandSha256\", index);\n\treturn {\n\t\tclaim,\n\t\tcategory: category as EvidenceItem[\"category\"],\n\t\ttimestamp,\n\t\tstatus: status as EvidenceStatus,\n\t\tartifactPath: optionalStringField(item.artifactPath, \"artifactPath\", index),\n\t\tverificationCommand: optionalStringField(item.verificationCommand, \"verificationCommand\", index),\n\t\thash: optionalStringField(item.hash, \"hash\", index),\n\t\treceiptId: optionalStringField(item.receiptId, \"receiptId\", index),\n\t\treceiptSchemaVersion,\n\t\t...(receiptCommandSha256 !== undefined\n\t\t\t? { receiptCommandSha256: parseSha256Hex(receiptCommandSha256, \"receiptCommandSha256\") }\n\t\t\t: {}),\n\t\treceiptLaneId: optionalStringField(item.receiptLaneId, \"receiptLaneId\", index),\n\t\tgapReason: optionalStringField(item.gapReason, \"gapReason\", index),\n\t};\n}\n\n// ============================================================================\n// ReplayLedger\n// ============================================================================\n\n/** prevHash sentinel for the first event in a replay chain. */\nconst GENESIS_HASH = \"genesis\";\n\nfunction computeEventHash(event: Omit<ReplayEvent, \"eventHash\">): string {\n\tconst metadata = [event.seq, event.type, event.timestamp, event.goalId, event.laneId ?? null];\n\tconst material =\n\t\tevent.payloadHashAlgorithm === undefined\n\t\t\t? [...metadata, event.payloadHash, event.prevHash]\n\t\t\t: [...metadata, event.payloadHashAlgorithm, event.payloadHash, event.prevHash];\n\treturn sha256(JSON.stringify(material));\n}\n\nfunction parseReplayEventLine(line: string, lineNumber: number): ReplayEvent {\n\tlet raw: unknown;\n\ttry {\n\t\traw = JSON.parse(line);\n\t} catch {\n\t\tthrow new Error(`Replay ledger corrupted at line ${lineNumber}: invalid JSON`);\n\t}\n\tif (raw === null || typeof raw !== \"object\" || Array.isArray(raw)) {\n\t\tthrow new Error(`Replay ledger corrupted at line ${lineNumber}: event must be an object`);\n\t}\n\tconst event = raw as Record<string, unknown>;\n\tconst { seq, type, timestamp, goalId, laneId, payloadHashAlgorithm, payloadHash, prevHash, eventHash } = event;\n\tif (\n\t\ttypeof seq !== \"number\" ||\n\t\ttypeof type !== \"string\" ||\n\t\ttypeof timestamp !== \"string\" ||\n\t\ttypeof goalId !== \"string\" ||\n\t\ttypeof payloadHash !== \"string\" ||\n\t\ttypeof prevHash !== \"string\" ||\n\t\ttypeof eventHash !== \"string\" ||\n\t\t(laneId !== undefined && typeof laneId !== \"string\") ||\n\t\t!(\"payload\" in event)\n\t) {\n\t\tthrow new Error(`Replay ledger corrupted at line ${lineNumber}: event fields are missing or mistyped`);\n\t}\n\tif (\n\t\tpayloadHashAlgorithm !== undefined &&\n\t\tpayloadHashAlgorithm !== LEGACY_REPLAY_PAYLOAD_HASH_ALGORITHM &&\n\t\tpayloadHashAlgorithm !== JCS_REPLAY_PAYLOAD_HASH_ALGORITHM\n\t) {\n\t\tthrow new Error(`Replay ledger corrupted at line ${lineNumber}: unsupported payload hash algorithm`);\n\t}\n\tconst parsed: ReplayEvent = {\n\t\tseq,\n\t\ttype: type as ReplayEvent[\"type\"],\n\t\ttimestamp,\n\t\tgoalId,\n\t\tlaneId,\n\t\tpayload: event.payload,\n\t\tpayloadHash,\n\t\tprevHash,\n\t\teventHash,\n\t};\n\treturn payloadHashAlgorithm === undefined ? parsed : { ...parsed, payloadHashAlgorithm };\n}\n\nfunction parseReplayLedgerBytes(bytes: Buffer, goalId: string): ReplayEvent[] {\n\tconst lines = bytes\n\t\t.toString(\"utf8\")\n\t\t.split(\"\\n\")\n\t\t.filter((line) => line.trim().length > 0);\n\tconst events: ReplayEvent[] = [];\n\tlet prevHash = GENESIS_HASH;\n\tfor (let index = 0; index < lines.length; index++) {\n\t\tconst event = parseReplayEventLine(lines[index], index + 1);\n\t\tif (event.goalId !== goalId) throw new Error(`Replay ledger goal mismatch at line ${index + 1}`);\n\t\tif (event.seq !== index + 1) {\n\t\t\tthrow new Error(`Replay ledger corrupted at line ${index + 1}: expected seq ${index + 1}, got ${event.seq}`);\n\t\t}\n\t\tif (event.prevHash !== prevHash) throw new Error(`Replay ledger chain broken at line ${index + 1}`);\n\t\tconst payloadHashAlgorithm = event.payloadHashAlgorithm ?? LEGACY_REPLAY_PAYLOAD_HASH_ALGORITHM;\n\t\tif (computeReplayPayloadHash(event.payload, payloadHashAlgorithm) !== event.payloadHash) {\n\t\t\tthrow new Error(`Replay ledger payload tampered at line ${index + 1} (seq ${event.seq})`);\n\t\t}\n\t\tif (computeEventHash(event) !== event.eventHash) {\n\t\t\tthrow new Error(`Replay ledger event hash mismatch at line ${index + 1} (seq ${event.seq})`);\n\t\t}\n\t\tprevHash = event.eventHash;\n\t\tevents.push(event);\n\t}\n\treturn events;\n}\n\nexport class ReplayLedgerManager {\n\tprivate readonly goalId: string;\n\tprivate readonly ledgerPath: string;\n\tprivate readonly store: ReplayLedgerStore;\n\tprivate events: ReplayEvent[] = [];\n\tprivate committedHead: ReplayLedgerHead;\n\n\tconstructor(goalId: string, ledgerPath: string, expectedHead?: ReplayLedgerHead) {\n\t\tthis.goalId = goalId;\n\t\tthis.ledgerPath = ledgerPath;\n\t\tthis.committedHead = { fileIdentity: null, size: 0, lastSeq: 0, lastHash: GENESIS_HASH };\n\t\tthis.store = new ReplayLedgerStore(ledgerPath, (bytes) => {\n\t\t\tconst events = parseReplayLedgerBytes(bytes, goalId);\n\t\t\tconst last = events[events.length - 1];\n\t\t\treturn { lastSeq: last?.seq ?? 0, lastHash: last?.eventHash ?? GENESIS_HASH };\n\t\t});\n\t\tthis.refresh(expectedHead);\n\t}\n\n\tprivate refresh(expectedHead?: ReplayLedgerHead): void {\n\t\tconst snapshot = this.store.load(expectedHead);\n\t\tthis.events = parseReplayLedgerBytes(snapshot.bytes, this.goalId);\n\t\tthis.committedHead = snapshot.head;\n\t}\n\n\tappend(\n\t\tevent: Omit<ReplayEvent, \"seq\" | \"timestamp\" | \"payloadHashAlgorithm\" | \"payloadHash\" | \"prevHash\" | \"eventHash\">,\n\t\texpectedHead: ReplayLedgerHead = this.committedHead,\n\t): ReplayEvent {\n\t\tif (event.goalId !== this.goalId) throw new Error(\"Replay event goalId does not match the ledger\");\n\t\tif (!replayLedgerHeadsEqual(expectedHead, this.committedHead)) {\n\t\t\tthrow new Error(\"Replay manager expected-head CAS is stale\");\n\t\t}\n\t\tconst payloadHashAlgorithm = JCS_REPLAY_PAYLOAD_HASH_ALGORITHM;\n\t\tconst payloadHash = computeReplayPayloadHash(event.payload, payloadHashAlgorithm);\n\t\tconst chained: Omit<ReplayEvent, \"eventHash\"> = {\n\t\t\t...event,\n\t\t\tseq: expectedHead.lastSeq + 1,\n\t\t\ttimestamp: new Date().toISOString(),\n\t\t\tpayloadHashAlgorithm,\n\t\t\tpayloadHash,\n\t\t\tprevHash: expectedHead.lastHash,\n\t\t};\n\t\tconst fullEvent: ReplayEvent = { ...chained, eventHash: computeEventHash(chained) };\n\t\tthis.committedHead = this.store.append(\n\t\t\tBuffer.from(`${JSON.stringify(fullEvent)}\\n`, \"utf8\"),\n\t\t\tfullEvent.seq,\n\t\t\tfullEvent.eventHash,\n\t\t\texpectedHead,\n\t\t);\n\t\tthis.events.push(fullEvent);\n\t\treturn structuredClone(fullEvent);\n\t}\n\n\t/** Compatibility no-op that still verifies the caller's expected committed head. */\n\tpersist(expectedHead: ReplayLedgerHead = this.committedHead): void {\n\t\tthis.getVerifiedSnapshot(expectedHead);\n\t}\n\n\tload(expectedHead: ReplayLedgerHead = this.committedHead): void {\n\t\tthis.refresh(expectedHead);\n\t}\n\n\tgetCommittedHead(): ReplayLedgerHead {\n\t\treturn structuredClone(this.committedHead);\n\t}\n\n\tgetVerifiedSnapshot(expectedHead: ReplayLedgerHead = this.committedHead): VerifiedReplayLedgerSnapshot {\n\t\tthis.refresh(expectedHead);\n\t\treturn structuredClone({ events: this.events, head: this.committedHead });\n\t}\n\n\tgetEvents(): ReadonlyArray<ReplayEvent> {\n\t\treturn structuredClone(this.events);\n\t}\n\n\tgetLedger(): Readonly<ReplayLedger> {\n\t\treturn structuredClone({\n\t\t\tgoalId: this.goalId,\n\t\t\tevents: this.events,\n\t\t\tledgerPath: this.ledgerPath,\n\t\t\tlastPersistedSeq: this.committedHead.lastSeq,\n\t\t});\n\t}\n\n\treplay<T>(handler: (event: ReplayEvent) => T | undefined): T[] {\n\t\treturn this.events.map(handler).filter((result): result is T => result !== undefined);\n\t}\n\n\texportToFile(path: string): void {\n\t\tensureDir(path);\n\t\twriteFileSync(path, JSON.stringify(this.events, null, 2), \"utf8\");\n\t}\n}\n\n// ============================================================================\n// EvidenceGate\n// ============================================================================\n\nexport interface EvidenceGateOptions {\n\t/** Minimum number of satisfied evidence items required. */\n\tminEvidenceCount?: number;\n\t/** Require at least one artifact with a SHA-256 hash in explicit legacy mode. */\n\trequireHash?: boolean;\n\t/** Require at least one verification command in explicit legacy mode. */\n\trequireVerificationCommand?: boolean;\n\t/** Receipt policy. Defaults to prefer; legacy must be selected explicitly. */\n\treceiptMode?: EvidenceReceiptMode;\n\t/** Resolve a serialized or decoded receipt by ID. The gate validates the returned value. */\n\tresolveReceipt?: (receiptId: string) => unknown;\n\t/** Strict source: one expected-head, file-identity, suffix, and chain-verified snapshot. */\n\tresolveVerifiedLedgerSnapshot?: () => VerifiedReplayLedgerSnapshot;\n\t/** Prefer-mode migration source; strict mode requires resolveVerifiedLedgerSnapshot. */\n\tresolveLedgerEvent?: (seq: number) => ReplayEvent | undefined;\n\t/** Recapture the receipt's workspace scope (same kind and scope) for freshness comparison. */\n\tcaptureWorkspaceFingerprint?: (scope: WorkspaceScope) => unknown;\n\t/**\n\t * Optional freshness source: the latest replay-ledger sequence of a workspace mutation\n\t * relevant to the given scope, or null/undefined when none is known. When configured,\n\t * the receipt's verified ledger seq must strictly exceed this value; a throwing or\n\t * out-of-contract source is a hard block (positive safe integers only).\n\t */\n\tresolveLatestWorkspaceMutationSeq?: (scope: WorkspaceScope) => number | null | undefined;\n\t/** Ephemeral trust anchor used to verify the original command's keyed attestation. */\n\tcommandAttestationBinder?: Pick<CommandHmacBinder, \"verify\">;\n\t/** Resolve the original command inside the same trust boundary as the binder. */\n\tresolveAttestedCommand?: (receiptId: string) => EvidenceCommandDescriptor | undefined;\n}\n\ninterface ReceiptCheckIssue {\n\treadonly message: string;\n\treadonly hard: boolean;\n}\n\nfunction receiptCheckIssue(message: string, hard: boolean): ReceiptCheckIssue {\n\treturn { message, hard };\n}\n\nfunction receiptIssue(\n\titem: EvidenceItem,\n\tcontract: TaskContract,\n\toptions: EvidenceGateOptions,\n): ReceiptCheckIssue | undefined {\n\tif (!item.receiptId) {\n\t\treturn receiptCheckIssue(`Execution receipt is missing for evidence \"${item.claim}\".`, false);\n\t}\n\tconst strict = options.receiptMode === \"strict\";\n\tif (item.receiptSchemaVersion !== 3 && (item.receiptSchemaVersion !== undefined || strict)) {\n\t\treturn receiptCheckIssue(`Execution receipt schema metadata is invalid for evidence \"${item.claim}\".`, true);\n\t}\n\tif (!options.resolveReceipt) {\n\t\treturn receiptCheckIssue(`Execution receipt resolver is missing for evidence \"${item.claim}\".`, false);\n\t}\n\n\tlet rawReceipt: unknown;\n\ttry {\n\t\trawReceipt = options.resolveReceipt(item.receiptId);\n\t} catch {\n\t\treturn receiptCheckIssue(`Execution receipt resolver failed for evidence \"${item.claim}\".`, true);\n\t}\n\tif (rawReceipt === undefined) {\n\t\treturn receiptCheckIssue(`Execution receipt is missing for evidence \"${item.claim}\".`, false);\n\t}\n\n\ttry {\n\t\tconst receipt = validateEvidenceReceipt(rawReceipt);\n\t\tif (receipt.core.receiptId !== item.receiptId) {\n\t\t\treturn receiptCheckIssue(`Execution receipt ID does not match evidence \"${item.claim}\".`, true);\n\t\t}\n\t\tif (receipt.core.goalId !== contract.goalId) {\n\t\t\treturn receiptCheckIssue(`Execution receipt goal does not match evidence \"${item.claim}\".`, true);\n\t\t}\n\t\tif (receipt.core.claim !== item.claim) {\n\t\t\treturn receiptCheckIssue(`Execution receipt claim does not match evidence \"${item.claim}\".`, true);\n\t\t}\n\t\tif (receipt.core.status !== \"passed\" || receipt.core.exitCode !== 0) {\n\t\t\treturn receiptCheckIssue(\n\t\t\t\t`Execution receipt for evidence \"${item.claim}\" did not pass with exit code 0.`,\n\t\t\t\ttrue,\n\t\t\t);\n\t\t}\n\n\t\tif (item.receiptCommandSha256 === undefined) {\n\t\t\treturn receiptCheckIssue(`Execution receipt command binding is missing for evidence \"${item.claim}\".`, false);\n\t\t}\n\t\tconst receiptCommandSha256 = computeEvidenceCommandSha256(receipt.core.command);\n\t\tif (!constantTimeSha256Equal(item.receiptCommandSha256, receiptCommandSha256)) {\n\t\t\treturn receiptCheckIssue(`Execution receipt command does not match evidence \"${item.claim}\".`, true);\n\t\t}\n\t\tconst attestationIssue = verifyCommandAttestation({\n\t\t\treceiptId: receipt.core.receiptId,\n\t\t\tbinding: receipt.core.commandBinding,\n\t\t\tpersistedCommand: receipt.core.command,\n\t\t\tpersistedSummary: receipt.core.commandRedaction,\n\t\t\tbinder: options.commandAttestationBinder,\n\t\t\tresolveCommand: options.resolveAttestedCommand,\n\t\t\tredact: redactCommandDescriptor,\n\t\t});\n\t\tif (attestationIssue !== undefined) {\n\t\t\treturn receiptCheckIssue(\n\t\t\t\t`Execution receipt command attestation ${attestationIssue.detail} for evidence \"${item.claim}\".`,\n\t\t\t\tattestationIssue.hard,\n\t\t\t);\n\t\t}\n\n\t\tif (receipt.core.laneId !== undefined && item.receiptLaneId === undefined) {\n\t\t\treturn receiptCheckIssue(`Execution receipt lane binding is missing for evidence \"${item.claim}\".`, false);\n\t\t}\n\t\tif (item.receiptLaneId !== receipt.core.laneId) {\n\t\t\treturn receiptCheckIssue(`Execution receipt lane does not match evidence \"${item.claim}\".`, true);\n\t\t}\n\n\t\tconst workspaceIssue = verifyWorkspaceBinding(receipt.core.workspaceAfter, options.captureWorkspaceFingerprint);\n\t\tif (workspaceIssue !== undefined) {\n\t\t\treturn receiptCheckIssue(\n\t\t\t\t`Execution receipt ${workspaceIssue.detail} for evidence \"${item.claim}\".`,\n\t\t\t\tworkspaceIssue.hard,\n\t\t\t);\n\t\t}\n\n\t\tlet snapshot: VerifiedReplayLedgerSnapshot | undefined;\n\t\tif (options.resolveVerifiedLedgerSnapshot !== undefined) {\n\t\t\ttry {\n\t\t\t\tsnapshot = parseVerifiedLedgerSnapshot(\n\t\t\t\t\toptions.resolveVerifiedLedgerSnapshot(),\n\t\t\t\t\tcontract.goalId,\n\t\t\t\t\tparseReplayLedgerBytes,\n\t\t\t\t);\n\t\t\t} catch {\n\t\t\t\treturn receiptCheckIssue(\n\t\t\t\t\t`Execution receipt verified ledger snapshot failed for evidence \"${item.claim}\".`,\n\t\t\t\t\ttrue,\n\t\t\t\t);\n\t\t\t}\n\t\t} else if (strict) {\n\t\t\treturn receiptCheckIssue(\n\t\t\t\t`Execution receipt verified ledger snapshot is missing for evidence \"${item.claim}\".`,\n\t\t\t\tfalse,\n\t\t\t);\n\t\t}\n\t\tlet latestMutationSeq =\n\t\t\tsnapshot === undefined\n\t\t\t\t? null\n\t\t\t\t: latestRelevantWorkspaceMutationSeq(snapshot.events, receipt.core.workspaceAfter.scope);\n\t\tif (snapshot === undefined && options.resolveLatestWorkspaceMutationSeq !== undefined) {\n\t\t\tlet resolved: unknown;\n\t\t\ttry {\n\t\t\t\tresolved = options.resolveLatestWorkspaceMutationSeq(receipt.core.workspaceAfter.scope);\n\t\t\t} catch {\n\t\t\t\treturn receiptCheckIssue(\n\t\t\t\t\t`Execution receipt workspace-mutation freshness source failed for evidence \"${item.claim}\".`,\n\t\t\t\t\ttrue,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (resolved !== null && resolved !== undefined) {\n\t\t\t\tif (!Number.isSafeInteger(resolved) || (resolved as number) <= 0) {\n\t\t\t\t\treturn receiptCheckIssue(\n\t\t\t\t\t\t`Execution receipt workspace-mutation freshness source is malformed for evidence \"${item.claim}\".`,\n\t\t\t\t\t\ttrue,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tlatestMutationSeq = resolved as number;\n\t\t\t}\n\t\t}\n\n\t\tconst binding = receipt.envelope.ledgerBinding;\n\t\tif (!binding) {\n\t\t\treturn receiptCheckIssue(\n\t\t\t\t`Execution receipt ledger binding is missing for evidence \"${item.claim}\".`,\n\t\t\t\tlatestMutationSeq !== null,\n\t\t\t);\n\t\t}\n\t\tconst event = snapshot\n\t\t\t? snapshot.events.find((candidate) => candidate.seq === binding.seq)\n\t\t\t: options.resolveLedgerEvent?.(binding.seq);\n\t\tif (!event && snapshot === undefined && !options.resolveLedgerEvent) {\n\t\t\treturn receiptCheckIssue(\n\t\t\t\t`Execution receipt ledger resolver is missing for evidence \"${item.claim}\".`,\n\t\t\t\tlatestMutationSeq !== null,\n\t\t\t);\n\t\t}\n\t\tconst replayPayload = evidenceReceiptReplayPayload(receipt);\n\t\tif (\n\t\t\t!event ||\n\t\t\tevent.seq !== binding.seq ||\n\t\t\tevent.type !== \"evidence_receipt\" ||\n\t\t\tevent.goalId !== contract.goalId ||\n\t\t\tevent.laneId !== receipt.core.laneId ||\n\t\t\t!constantTimeSha256Equal(event.eventHash, binding.eventHash) ||\n\t\t\t!replayPayloadMatches(event.payload, replayPayload.receiptId, replayPayload.coreSha256)\n\t\t) {\n\t\t\treturn receiptCheckIssue(`Execution receipt ledger binding does not match evidence \"${item.claim}\".`, true);\n\t\t}\n\t\tif (latestMutationSeq !== null && event.seq <= latestMutationSeq) {\n\t\t\treturn receiptCheckIssue(\n\t\t\t\t`Execution receipt is stale: workspace mutation seq ${latestMutationSeq} does not precede receipt ledger seq ${event.seq} for evidence \"${item.claim}\".`,\n\t\t\t\ttrue,\n\t\t\t);\n\t\t}\n\t} catch {\n\t\treturn receiptCheckIssue(`Execution receipt is invalid for evidence \"${item.claim}\".`, true);\n\t}\n\treturn undefined;\n}\n\nexport class EvidenceGate {\n\tprivate options: EvidenceGateOptions;\n\n\tconstructor(options: EvidenceGateOptions = {}) {\n\t\tthis.options = {\n\t\t\tminEvidenceCount: 1,\n\t\t\trequireHash: true,\n\t\t\trequireVerificationCommand: true,\n\t\t\treceiptMode: \"prefer\",\n\t\t\t...options,\n\t\t};\n\t}\n\n\tcheck(contract: TaskContract): MergeGateResult {\n\t\tconst evidence = contract.requiredEvidence;\n\t\tconst satisfied = evidence.filter((e) => e.status === \"satisfied\");\n\t\tconst failed = evidence.filter((e) => e.status === \"failed\");\n\t\tconst pending = evidence.filter((e) => e.status === \"pending\" || e.status === \"gathering\");\n\t\tconst mode = this.options.receiptMode ?? \"prefer\";\n\t\tconst checks: string[] = [];\n\t\tlet hardReceiptFailure = false;\n\n\t\tif (satisfied.length < (this.options.minEvidenceCount ?? 1)) {\n\t\t\tchecks.push(`Only ${satisfied.length}/${this.options.minEvidenceCount} required evidence items satisfied.`);\n\t\t}\n\t\tif (failed.length > 0) {\n\t\t\tchecks.push(`${failed.length} evidence item(s) failed.`);\n\t\t}\n\n\t\tif (mode === \"legacy\") {\n\t\t\tif (this.options.requireHash) {\n\t\t\t\tconst hashed = satisfied.filter((e) => e.hash && e.hash.length > 0);\n\t\t\t\tif (hashed.length === 0) checks.push(\"No satisfied evidence has a SHA-256 hash.\");\n\t\t\t}\n\t\t\tif (this.options.requireVerificationCommand) {\n\t\t\t\tconst withCommand = satisfied.filter((e) => e.verificationCommand && e.verificationCommand.length > 0);\n\t\t\t\tif (withCommand.length === 0) checks.push(\"No satisfied evidence has a verification command.\");\n\t\t\t}\n\t\t} else {\n\t\t\tconst unsatisfied = evidence.filter((item) => item.status !== \"satisfied\");\n\t\t\tif (unsatisfied.length > 0) {\n\t\t\t\tchecks.push(`${unsatisfied.length} required evidence item(s) are not satisfied.`);\n\t\t\t}\n\t\t\tfor (const item of satisfied) {\n\t\t\t\tconst issue = receiptIssue(item, contract, this.options);\n\t\t\t\tif (issue) {\n\t\t\t\t\tchecks.push(issue.message);\n\t\t\t\t\thardReceiptFailure ||= issue.hard;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (contract.verdict === \"fail\" || (mode !== \"legacy\" && contract.verdict !== \"pass\")) {\n\t\t\tchecks.push(`Task contract verdict is '${contract.verdict}'.`);\n\t\t}\n\n\t\tlet status: MergeGateStatus;\n\t\tlet reason: string;\n\t\tlet suggestion: string | undefined;\n\t\tif (checks.length === 0) {\n\t\t\tstatus = \"open\";\n\t\t\treason = `Evidence gate passed: ${satisfied.length}/${evidence.length} evidence items satisfied.`;\n\t\t} else {\n\t\t\tconst contractFailure = mode === \"legacy\" ? contract.verdict === \"fail\" : contract.verdict !== \"pass\";\n\t\t\tconst hasHardFailure = failed.length > 0 || contractFailure || hardReceiptFailure || mode === \"strict\";\n\t\t\tstatus = hasHardFailure ? \"blocked\" : mode === \"prefer\" || pending.length > 0 ? \"conditional\" : \"blocked\";\n\t\t\treason = checks.join(\"; \");\n\t\t\tsuggestion = `Gather remaining evidence (${pending.length} pending) and re-run verification.`;\n\t\t}\n\n\t\treturn {\n\t\t\tgateId: \"evidence-gate\",\n\t\t\tstatus,\n\t\t\treason,\n\t\t\tsuggestion,\n\t\t\tevidenceChecked: evidence,\n\t\t};\n\t}\n}\n\n// ============================================================================\n// FailClosedMergeGate\n// ============================================================================\n\nexport class FailClosedMergeGate {\n\tprivate readonly gates: readonly EvidenceGate[];\n\n\tconstructor(gates: EvidenceGate[] = [new EvidenceGate()]) {\n\t\tif (!Array.isArray(gates) || gates.length === 0) throw new TypeError(\"At least one evidence gate is required\");\n\t\tthis.gates = Object.freeze(\n\t\t\tArray.from(gates, (gate) => {\n\t\t\t\tif (!(gate instanceof EvidenceGate)) throw new TypeError(\"Invalid evidence gate\");\n\t\t\t\treturn gate;\n\t\t\t}),\n\t\t);\n\t}\n\n\tcheck(contract: TaskContract): MergeGateResult {\n\t\treturn combineMergeGateResults(\n\t\t\tcontract,\n\t\t\tthis.gates.map((gate) => gate.check(contract)),\n\t\t);\n\t}\n}\n\n// ============================================================================\n// Verify Reporter v2\n// ============================================================================\n\n/** Escape pipes/newlines so untrusted claim or command text cannot restructure the report table. */\nfunction escapeTableCell(value: string): string {\n\treturn value.replace(/\\\\/g, \"\\\\\\\\\").replace(/\\|/g, \"\\\\|\").replace(/\\r?\\n/g, \" \");\n}\n\nexport interface VerifyReporterV2Options {\n\toutputDir: string;\n\tgoalId: string;\n}\n\nexport class VerifyReporterV2 {\n\tprivate options: VerifyReporterV2Options;\n\n\tconstructor(options: VerifyReporterV2Options) {\n\t\tthis.options = options;\n\t}\n\n\trender(contract: TaskContract, mergeGate: MergeGateResult): string {\n\t\tconst lines: string[] = [\n\t\t\t`## OMK Verification Report v2 — ${contract.goalId}`,\n\t\t\t\"\",\n\t\t\t\"### Contract\",\n\t\t\t\"\",\n\t\t\t`| Field | Value |`,\n\t\t\t`|-------|-------|`,\n\t\t\t`| Claim | ${escapeTableCell(contract.completionClaim)} |`,\n\t\t\t`| Verdict | ${contract.verdict} |`,\n\t\t\t`| Final Risk | ${escapeTableCell(contract.finalRisk)} |`,\n\t\t\t\"\",\n\t\t\t\"### Evidence\",\n\t\t\t\"\",\n\t\t\t`| Claim | Status | Artifact | Command |`,\n\t\t\t`|-------|--------|----------|----------|`,\n\t\t];\n\n\t\tfor (const ev of contract.requiredEvidence) {\n\t\t\tlines.push(\n\t\t\t\t`| ${escapeTableCell(ev.claim)} | ${ev.status} | ${escapeTableCell(ev.artifactPath ?? \"—\")} | ${escapeTableCell(ev.verificationCommand ?? \"—\")} |`,\n\t\t\t);\n\t\t}\n\n\t\tlines.push(\n\t\t\t\"\",\n\t\t\t\"### Merge Gate\",\n\t\t\t\"\",\n\t\t\t`| Gate | Status | Reason |`,\n\t\t\t`|------|--------|--------|`,\n\t\t\t`| ${mergeGate.gateId} | ${mergeGate.status} | ${escapeTableCell(mergeGate.reason)} |`,\n\t\t\t\"\",\n\t\t);\n\n\t\tif (mergeGate.suggestion) {\n\t\t\tlines.push(`**Suggestion:** ${mergeGate.suggestion}`, \"\");\n\t\t}\n\n\t\treturn lines.join(\"\\n\");\n\t}\n\n\twrite(contract: TaskContract, mergeGate: MergeGateResult): string {\n\t\tconst markdown = this.render(contract, mergeGate);\n\t\tconst path = join(this.options.outputDir, `${this.options.goalId}.verify.md`);\n\t\tensureDir(path);\n\t\twriteFileSync(path, markdown, \"utf-8\");\n\t\treturn path;\n\t}\n}\n"]}
@@ -0,0 +1,4 @@
1
+ import type { MergeGateResult, TaskContract } from "../types/evidence.ts";
2
+ /** Combine already-evaluated gates without letting an empty set authorize a merge. */
3
+ export declare function combineMergeGateResults(contract: TaskContract, results: readonly MergeGateResult[]): MergeGateResult;
4
+ //# sourceMappingURL=merge-gate-result.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge-gate-result.d.ts","sourceRoot":"","sources":["../../src/guardrails/merge-gate-result.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAE1E,sFAAsF;AACtF,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,SAAS,eAAe,EAAE,GAAG,eAAe,CA4BpH","sourcesContent":["import type { MergeGateResult, TaskContract } from \"../types/evidence.ts\";\n\n/** Combine already-evaluated gates without letting an empty set authorize a merge. */\nexport function combineMergeGateResults(contract: TaskContract, results: readonly MergeGateResult[]): MergeGateResult {\n\tif (results.length === 0) throw new TypeError(\"At least one evidence gate result is required\");\n\tconst blocked = results.filter((result) => result.status === \"blocked\");\n\tconst conditional = results.filter((result) => result.status === \"conditional\");\n\tif (blocked.length > 0) {\n\t\treturn {\n\t\t\tgateId: \"fail-closed-merge-gate\",\n\t\t\tstatus: \"blocked\",\n\t\t\treason: `Blocked by ${blocked.length} gate(s): ${blocked.map((result) => result.reason).join(\"; \")}`,\n\t\t\tsuggestion: \"Resolve all blocking conditions before merge.\",\n\t\t\tevidenceChecked: contract.requiredEvidence,\n\t\t};\n\t}\n\tif (conditional.length > 0) {\n\t\treturn {\n\t\t\tgateId: \"fail-closed-merge-gate\",\n\t\t\tstatus: \"conditional\",\n\t\t\treason: `Conditional pass: ${conditional.length} gate(s) have pending conditions.`,\n\t\t\tsuggestion: \"Complete pending evidence or waive with explicit approval.\",\n\t\t\tevidenceChecked: contract.requiredEvidence,\n\t\t};\n\t}\n\treturn {\n\t\tgateId: \"fail-closed-merge-gate\",\n\t\tstatus: \"open\",\n\t\treason: \"All merge gates passed. Evidence verified and contract verdict is acceptable.\",\n\t\tevidenceChecked: contract.requiredEvidence,\n\t};\n}\n"]}
@@ -0,0 +1,32 @@
1
+ /** Combine already-evaluated gates without letting an empty set authorize a merge. */
2
+ export function combineMergeGateResults(contract, results) {
3
+ if (results.length === 0)
4
+ throw new TypeError("At least one evidence gate result is required");
5
+ const blocked = results.filter((result) => result.status === "blocked");
6
+ const conditional = results.filter((result) => result.status === "conditional");
7
+ if (blocked.length > 0) {
8
+ return {
9
+ gateId: "fail-closed-merge-gate",
10
+ status: "blocked",
11
+ reason: `Blocked by ${blocked.length} gate(s): ${blocked.map((result) => result.reason).join("; ")}`,
12
+ suggestion: "Resolve all blocking conditions before merge.",
13
+ evidenceChecked: contract.requiredEvidence,
14
+ };
15
+ }
16
+ if (conditional.length > 0) {
17
+ return {
18
+ gateId: "fail-closed-merge-gate",
19
+ status: "conditional",
20
+ reason: `Conditional pass: ${conditional.length} gate(s) have pending conditions.`,
21
+ suggestion: "Complete pending evidence or waive with explicit approval.",
22
+ evidenceChecked: contract.requiredEvidence,
23
+ };
24
+ }
25
+ return {
26
+ gateId: "fail-closed-merge-gate",
27
+ status: "open",
28
+ reason: "All merge gates passed. Evidence verified and contract verdict is acceptable.",
29
+ evidenceChecked: contract.requiredEvidence,
30
+ };
31
+ }
32
+ //# sourceMappingURL=merge-gate-result.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge-gate-result.js","sourceRoot":"","sources":["../../src/guardrails/merge-gate-result.ts"],"names":[],"mappings":"AAEA,sFAAsF;AACtF,MAAM,UAAU,uBAAuB,CAAC,QAAsB,EAAE,OAAmC,EAAmB;IACrH,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,SAAS,CAAC,+CAA+C,CAAC,CAAC;IAC/F,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC;IACxE,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,KAAK,aAAa,CAAC,CAAC;IAChF,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,OAAO;YACN,MAAM,EAAE,wBAAwB;YAChC,MAAM,EAAE,SAAS;YACjB,MAAM,EAAE,cAAc,OAAO,CAAC,MAAM,aAAa,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YACpG,UAAU,EAAE,+CAA+C;YAC3D,eAAe,EAAE,QAAQ,CAAC,gBAAgB;SAC1C,CAAC;IACH,CAAC;IACD,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,OAAO;YACN,MAAM,EAAE,wBAAwB;YAChC,MAAM,EAAE,aAAa;YACrB,MAAM,EAAE,qBAAqB,WAAW,CAAC,MAAM,mCAAmC;YAClF,UAAU,EAAE,4DAA4D;YACxE,eAAe,EAAE,QAAQ,CAAC,gBAAgB;SAC1C,CAAC;IACH,CAAC;IACD,OAAO;QACN,MAAM,EAAE,wBAAwB;QAChC,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,+EAA+E;QACvF,eAAe,EAAE,QAAQ,CAAC,gBAAgB;KAC1C,CAAC;AAAA,CACF","sourcesContent":["import type { MergeGateResult, TaskContract } from \"../types/evidence.ts\";\n\n/** Combine already-evaluated gates without letting an empty set authorize a merge. */\nexport function combineMergeGateResults(contract: TaskContract, results: readonly MergeGateResult[]): MergeGateResult {\n\tif (results.length === 0) throw new TypeError(\"At least one evidence gate result is required\");\n\tconst blocked = results.filter((result) => result.status === \"blocked\");\n\tconst conditional = results.filter((result) => result.status === \"conditional\");\n\tif (blocked.length > 0) {\n\t\treturn {\n\t\t\tgateId: \"fail-closed-merge-gate\",\n\t\t\tstatus: \"blocked\",\n\t\t\treason: `Blocked by ${blocked.length} gate(s): ${blocked.map((result) => result.reason).join(\"; \")}`,\n\t\t\tsuggestion: \"Resolve all blocking conditions before merge.\",\n\t\t\tevidenceChecked: contract.requiredEvidence,\n\t\t};\n\t}\n\tif (conditional.length > 0) {\n\t\treturn {\n\t\t\tgateId: \"fail-closed-merge-gate\",\n\t\t\tstatus: \"conditional\",\n\t\t\treason: `Conditional pass: ${conditional.length} gate(s) have pending conditions.`,\n\t\t\tsuggestion: \"Complete pending evidence or waive with explicit approval.\",\n\t\t\tevidenceChecked: contract.requiredEvidence,\n\t\t};\n\t}\n\treturn {\n\t\tgateId: \"fail-closed-merge-gate\",\n\t\tstatus: \"open\",\n\t\treason: \"All merge gates passed. Evidence verified and contract verdict is acceptable.\",\n\t\tevidenceChecked: contract.requiredEvidence,\n\t};\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAaH,OAAO,EAAE,6BAA6B,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAqBzF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAwBnE,OAAO,EAAE,6BAA6B,EAAE,eAAe,EAAE,CAAC;AAmf1D,MAAM,WAAW,WAAW;IAC3B,kBAAkB,CAAC,EAAE,gBAAgB,EAAE,CAAC;CACxC;AAED,wBAAsB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,WAAW,iBA2W/D","sourcesContent":["/**\n * Main entry point for the coding agent CLI.\n *\n * This file handles CLI argument parsing and translates them into\n * createAgentSession() options. The SDK does the heavy lifting.\n */\n\nimport * as fs from \"node:fs\";\nimport * as net from \"node:net\";\nimport { createInterface } from \"node:readline\";\nimport chalk from \"chalk\";\nimport { type ImageContent, modelsAreEqual } from \"omk-ai\";\nimport { ProcessTerminal, setKeybindings, TUI } from \"omk-tui\";\nimport { type Args, type Mode, parseArgs, printHelp } from \"./cli/args.ts\";\nimport { processFileArguments } from \"./cli/file-processor.ts\";\nimport { buildInitialMessage } from \"./cli/initial-message.ts\";\nimport { listModels } from \"./cli/list-models.ts\";\nimport { mcpAttachDiagnostics } from \"./cli/mcp-attach.ts\";\nimport { isExplicitExtensionDiagnostic, resolveCliPaths } from \"./cli/resource-paths.ts\";\nimport { selectSession } from \"./cli/session-picker.ts\";\nimport { handleCodexBarQuotaCommand } from \"./codexbar-cli.ts\";\nimport { runAdaptOrchDoctorCli } from \"./commands/adaptorch-doctor-cli.ts\";\nimport { runDoctorProviderCli } from \"./commands/doctor-provider-cli.ts\";\nimport { runPackageDoctorCli } from \"./commands/package-doctor-cli.ts\";\nimport { runResourceDoctorCli } from \"./commands/resource-doctor-cli.ts\";\nimport { runRouterFeedbackCli } from \"./commands/router-feedback-cli.ts\";\nimport { runSdkSessionCli } from \"./commands/sdk-session-cli.ts\";\nimport { runSessionDoctorCli } from \"./commands/session-doctor-cli.ts\";\nimport { runStatsCli } from \"./commands/stats-cli.ts\";\nimport { ENV_SESSION_DIR, expandTildePath, getAgentDir, getPackageDir, VERSION } from \"./config.ts\";\nimport { type CreateAgentSessionRuntimeFactory, createAgentSessionRuntime } from \"./core/agent-session-runtime.ts\";\nimport {\n\ttype AgentSessionRuntimeDiagnostic,\n\tcreateAgentSessionFromServices,\n\tcreateAgentSessionServices,\n} from \"./core/agent-session-services.ts\";\nimport { formatNoModelsAvailableMessage } from \"./core/auth-guidance.ts\";\nimport { AuthStorage } from \"./core/auth-storage.ts\";\nimport { exportFromFile } from \"./core/export-html/index.ts\";\nimport type { ExtensionFactory } from \"./core/extensions/types.ts\";\nimport { configureHttpDispatcher } from \"./core/http-dispatcher.ts\";\nimport { KeybindingsManager } from \"./core/keybindings.ts\";\nimport type { ModelRegistry } from \"./core/model-registry.ts\";\nimport { resolveCliModel, resolveModelScope, type ScopedModel } from \"./core/model-resolver.ts\";\nimport { restoreStdout, takeOverStdout } from \"./core/output-guard.ts\";\nimport type { CreateAgentSessionOptions } from \"./core/sdk.ts\";\nimport {\n\tformatMissingSessionCwdPrompt,\n\tgetMissingSessionCwdIssue,\n\tMissingSessionCwdError,\n\ttype SessionCwdIssue,\n} from \"./core/session-cwd.ts\";\nimport { assertValidSessionId, SessionManager } from \"./core/session-manager.ts\";\nimport { SettingsManager } from \"./core/settings-manager.ts\";\nimport { printTimings, resetTimings, time } from \"./core/timings.ts\";\nimport { runMigrations, showDeprecationWarnings } from \"./migrations.ts\";\nimport { InteractiveMode, runPrintMode, runRpcMode } from \"./modes/index.ts\";\nimport { ExtensionSelectorComponent } from \"./modes/interactive/components/extension-selector.ts\";\nimport { initTheme, stopThemeWatcher } from \"./modes/interactive/theme/theme.ts\";\nimport { handleConfigCommand, handlePackageCommand } from \"./package-manager-cli.ts\";\nimport { normalizePath, resolvePath } from \"./utils/paths.ts\";\nimport { cleanupWindowsSelfUpdateQuarantine } from \"./utils/windows-self-update.ts\";\n\nexport { isExplicitExtensionDiagnostic, resolveCliPaths };\n\n/**\n * Read all content from piped stdin.\n * Returns undefined if stdin is a TTY (interactive terminal).\n *\n * Non-TTY stdin that never ends (some IDE/terminal hosts keep fd0 open) used to\n * hang forever here — that looked like \"omk\" with no response. Bound the wait:\n * if no bytes arrive quickly and nothing is buffered, treat as empty.\n */\nasync function readPipedStdin(): Promise<string | undefined> {\n\t// If stdin is a TTY, we're running interactively - don't read stdin\n\tif (process.stdin.isTTY) {\n\t\treturn undefined;\n\t}\n\n\t// Already drained\n\tif (process.stdin.readableEnded) {\n\t\treturn undefined;\n\t}\n\n\tconst idleMs = Number(process.env.OMK_STDIN_IDLE_MS || 50);\n\treturn new Promise((resolve) => {\n\t\tlet data = \"\";\n\t\tlet settled = false;\n\t\tconst finish = () => {\n\t\t\tif (settled) return;\n\t\t\tsettled = true;\n\t\t\tclearTimeout(timer);\n\t\t\tprocess.stdin.off(\"data\", onData);\n\t\t\tprocess.stdin.off(\"end\", onEnd);\n\t\t\tprocess.stdin.off(\"error\", onEnd);\n\t\t\tresolve(data.trim() || undefined);\n\t\t};\n\t\tconst onData = (chunk: string | Buffer) => {\n\t\t\tdata += typeof chunk === \"string\" ? chunk : chunk.toString(\"utf8\");\n\t\t\t// Once data starts flowing, wait for natural end (or a long idle).\n\t\t\tclearTimeout(timer);\n\t\t\ttimer = setTimeout(finish, Math.max(idleMs * 20, 1000));\n\t\t};\n\t\tconst onEnd = () => finish();\n\t\tlet timer = setTimeout(finish, Number.isFinite(idleMs) ? Math.max(0, idleMs) : 50);\n\t\tprocess.stdin.setEncoding(\"utf8\");\n\t\tprocess.stdin.on(\"data\", onData);\n\t\tprocess.stdin.on(\"end\", onEnd);\n\t\tprocess.stdin.on(\"error\", onEnd);\n\t\tprocess.stdin.resume();\n\t});\n}\n\nfunction collectSettingsDiagnostics(\n\tsettingsManager: SettingsManager,\n\tcontext: string,\n): AgentSessionRuntimeDiagnostic[] {\n\treturn settingsManager.drainErrors().map(({ scope, error }) => ({\n\t\ttype: \"warning\",\n\t\tmessage: `(${context}, ${scope} settings) ${error.message}`,\n\t}));\n}\n\nfunction reportDiagnostics(diagnostics: readonly AgentSessionRuntimeDiagnostic[]): void {\n\tfor (const diagnostic of diagnostics) {\n\t\tconst color = diagnostic.type === \"error\" ? chalk.red : diagnostic.type === \"warning\" ? chalk.yellow : chalk.dim;\n\t\tconst prefix = diagnostic.type === \"error\" ? \"Error: \" : diagnostic.type === \"warning\" ? \"Warning: \" : \"\";\n\t\tconsole.error(color(`${prefix}${diagnostic.message}`));\n\t}\n}\n\nfunction isTruthyEnvFlag(value: string | undefined): boolean {\n\tif (!value) return false;\n\treturn value === \"1\" || value.toLowerCase() === \"true\" || value.toLowerCase() === \"yes\";\n}\n\ntype AppMode = \"interactive\" | \"print\" | \"json\" | \"rpc\";\n\nfunction hasPromptIntent(parsed: Args): boolean {\n\treturn (\n\t\tparsed.print === true ||\n\t\tparsed.messages.length > 0 ||\n\t\tparsed.fileArgs.length > 0 ||\n\t\tparsed.mode === \"json\" ||\n\t\tparsed.mode === \"rpc\"\n\t);\n}\n\n/**\n * When stdin/stdout were detached from the TTY (some IDE hosts / wrappers),\n * rebind them to /dev/tty so InteractiveMode/ProcessTerminal can run.\n * No-op if already a TTY or /dev/tty is unavailable.\n */\nfunction attachStdioToControllingTty(): boolean {\n\tif (process.stdin.isTTY && process.stdout.isTTY) return true;\n\ttry {\n\t\t// Prefer reopening stdio FDs against the controlling terminal.\n\t\t// Socket-over-/dev/tty is enough for isTTY detection + raw mode shim.\n\t\tconst fd = fs.openSync(\"/dev/tty\", \"r+\");\n\t\tconst sock = new net.Socket({ fd, readable: true, writable: true });\n\t\tObject.defineProperty(sock, \"isTTY\", { value: true, configurable: true });\n\t\tObject.defineProperty(sock, \"isRaw\", { value: false, writable: true, configurable: true });\n\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t(sock as any).setRawMode = (mode: boolean) => {\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\t(sock as any).isRaw = !!mode;\n\t\t\treturn sock;\n\t\t};\n\t\tif (!process.stdin.isTTY) {\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\t(process as any).stdin = sock;\n\t\t}\n\t\tif (!process.stdout.isTTY) {\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\t(process as any).stdout = sock;\n\t\t}\n\t\treturn !!(process.stdin.isTTY && process.stdout.isTTY);\n\t} catch {\n\t\treturn !!(process.stdin.isTTY && process.stdout.isTTY);\n\t}\n}\n\nfunction resolveAppMode(parsed: Args, stdinIsTTY: boolean, stdoutIsTTY: boolean = !!process.stdout.isTTY): AppMode {\n\tif (parsed.mode === \"rpc\") {\n\t\treturn \"rpc\";\n\t}\n\tif (parsed.mode === \"json\") {\n\t\treturn \"json\";\n\t}\n\t// Explicit single-shot (-p / --print)\n\tif (parsed.print) {\n\t\treturn \"print\";\n\t}\n\t// Bare `omk` (no prompt args) must open the TUI. Never fall into silent/empty print.\n\tif (!hasPromptIntent(parsed)) {\n\t\treturn \"interactive\";\n\t}\n\t// Piped automation: non-tty stdin with a prompt → print mode\n\tif (!stdinIsTTY || !stdoutIsTTY) {\n\t\treturn \"print\";\n\t}\n\treturn \"interactive\";\n}\n\nfunction toPrintOutputMode(appMode: AppMode): Exclude<Mode, \"rpc\"> {\n\treturn appMode === \"json\" ? \"json\" : \"text\";\n}\n\nasync function prepareInitialMessage(\n\tparsed: Args,\n\tautoResizeImages: boolean,\n\tstdinContent?: string,\n): Promise<{\n\tinitialMessage?: string;\n\tinitialImages?: ImageContent[];\n}> {\n\tif (parsed.fileArgs.length === 0) {\n\t\treturn buildInitialMessage({ parsed, stdinContent });\n\t}\n\n\tconst { text, images } = await processFileArguments(parsed.fileArgs, { autoResizeImages });\n\treturn buildInitialMessage({\n\t\tparsed,\n\t\tfileText: text,\n\t\tfileImages: images,\n\t\tstdinContent,\n\t});\n}\n\n/** Result from resolving a session argument */\ntype ResolvedSession =\n\t| { type: \"path\"; path: string } // Direct file path\n\t| { type: \"local\"; path: string } // Found in current project\n\t| { type: \"global\"; path: string; cwd: string } // Found in different project\n\t| { type: \"not_found\"; arg: string }; // Not found anywhere\n\n/**\n * Resolve a session argument to a file path.\n * If it looks like a path, use as-is. Otherwise try to match as session ID prefix.\n */\nasync function findLocalSessionByExactId(\n\tsessionId: string,\n\tcwd: string,\n\tsessionDir?: string,\n): Promise<{ type: \"local\"; path: string } | undefined> {\n\tconst localSessions = await SessionManager.list(cwd, sessionDir);\n\tconst localMatch = localSessions.find((s) => s.id === sessionId);\n\treturn localMatch ? { type: \"local\", path: localMatch.path } : undefined;\n}\n\nasync function resolveSessionPath(sessionArg: string, cwd: string, sessionDir?: string): Promise<ResolvedSession> {\n\t// If it looks like a file path, resolve it before handing it to the session manager.\n\tif (sessionArg.includes(\"/\") || sessionArg.includes(\"\\\\\") || sessionArg.endsWith(\".jsonl\")) {\n\t\treturn { type: \"path\", path: resolvePath(sessionArg, cwd) };\n\t}\n\n\t// Try to match as session ID in current project first\n\tconst localSessions = await SessionManager.list(cwd, sessionDir);\n\tconst localMatch =\n\t\tlocalSessions.find((s) => s.id === sessionArg) ?? localSessions.find((s) => s.id.startsWith(sessionArg));\n\n\tif (localMatch) {\n\t\treturn { type: \"local\", path: localMatch.path };\n\t}\n\n\t// Try global search across all projects\n\tconst allSessions = await SessionManager.listAll(sessionDir);\n\tconst globalMatch =\n\t\tallSessions.find((s) => s.id === sessionArg) ?? allSessions.find((s) => s.id.startsWith(sessionArg));\n\n\tif (globalMatch) {\n\t\treturn { type: \"global\", path: globalMatch.path, cwd: globalMatch.cwd };\n\t}\n\n\t// Not found anywhere\n\treturn { type: \"not_found\", arg: sessionArg };\n}\n\n/** Prompt user for yes/no confirmation */\nasync function promptConfirm(message: string): Promise<boolean> {\n\treturn new Promise((resolve) => {\n\t\tconst rl = createInterface({\n\t\t\tinput: process.stdin,\n\t\t\toutput: process.stdout,\n\t\t});\n\t\trl.question(`${message} [y/N] `, (answer) => {\n\t\t\trl.close();\n\t\t\tresolve(answer.toLowerCase() === \"y\" || answer.toLowerCase() === \"yes\");\n\t\t});\n\t});\n}\n\nfunction validateForkFlags(parsed: Args): void {\n\tif (!parsed.fork) return;\n\n\tconst conflictingFlags = [\n\t\tparsed.session ? \"--session\" : undefined,\n\t\tparsed.continue ? \"--continue\" : undefined,\n\t\tparsed.resume ? \"--resume\" : undefined,\n\t\tparsed.noSession ? \"--no-session\" : undefined,\n\t].filter((flag): flag is string => flag !== undefined);\n\n\tif (conflictingFlags.length > 0) {\n\t\tconsole.error(chalk.red(`Error: --fork cannot be combined with ${conflictingFlags.join(\", \")}`));\n\t\tprocess.exit(1);\n\t}\n}\n\nfunction validateSessionIdFlags(parsed: Args): void {\n\tif (parsed.sessionId === undefined) return;\n\n\tconst conflictingFlags = [\n\t\tparsed.session ? \"--session\" : undefined,\n\t\tparsed.continue ? \"--continue\" : undefined,\n\t\tparsed.resume ? \"--resume\" : undefined,\n\t\tparsed.noSession ? \"--no-session\" : undefined,\n\t].filter((flag): flag is string => flag !== undefined);\n\n\tif (conflictingFlags.length > 0) {\n\t\tconsole.error(chalk.red(`Error: --session-id cannot be combined with ${conflictingFlags.join(\", \")}`));\n\t\tprocess.exit(1);\n\t}\n\n\ttry {\n\t\tassertValidSessionId(parsed.sessionId);\n\t} catch (error: unknown) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tconsole.error(chalk.red(`Error: ${message}`));\n\t\tprocess.exit(1);\n\t}\n}\n\nfunction forkSessionOrExit(sourcePath: string, cwd: string, sessionDir?: string, sessionId?: string): SessionManager {\n\ttry {\n\t\treturn SessionManager.forkFrom(sourcePath, cwd, sessionDir, { id: sessionId });\n\t} catch (error: unknown) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tconsole.error(chalk.red(`Error: ${message}`));\n\t\tprocess.exit(1);\n\t}\n}\n\nasync function createSessionManager(\n\tparsed: Args,\n\tcwd: string,\n\tsessionDir: string | undefined,\n\tsettingsManager: SettingsManager,\n): Promise<SessionManager> {\n\tif (parsed.noSession || parsed.help || parsed.listModels !== undefined) {\n\t\treturn SessionManager.inMemory(cwd);\n\t}\n\n\tif (parsed.fork) {\n\t\tif (parsed.sessionId) {\n\t\t\tconst existingTarget = await findLocalSessionByExactId(parsed.sessionId, cwd, sessionDir);\n\t\t\tif (existingTarget) {\n\t\t\t\tconsole.error(chalk.red(`Session already exists with id '${parsed.sessionId}'`));\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t}\n\n\t\tconst resolved = await resolveSessionPath(parsed.fork, cwd, sessionDir);\n\n\t\tswitch (resolved.type) {\n\t\t\tcase \"path\":\n\t\t\tcase \"local\":\n\t\t\tcase \"global\":\n\t\t\t\treturn forkSessionOrExit(resolved.path, cwd, sessionDir, parsed.sessionId);\n\n\t\t\tcase \"not_found\":\n\t\t\t\tconsole.error(chalk.red(`No session found matching '${resolved.arg}'`));\n\t\t\t\tprocess.exit(1);\n\t\t}\n\t}\n\n\tif (parsed.session) {\n\t\tconst resolved = await resolveSessionPath(parsed.session, cwd, sessionDir);\n\n\t\tswitch (resolved.type) {\n\t\t\tcase \"path\":\n\t\t\tcase \"local\":\n\t\t\t\treturn SessionManager.open(resolved.path, sessionDir);\n\n\t\t\tcase \"global\": {\n\t\t\t\tconsole.log(chalk.yellow(`Session found in different project: ${resolved.cwd}`));\n\t\t\t\tconst shouldFork = await promptConfirm(\"Fork this session into current directory?\");\n\t\t\t\tif (!shouldFork) {\n\t\t\t\t\tconsole.log(chalk.dim(\"Aborted.\"));\n\t\t\t\t\tprocess.exit(0);\n\t\t\t\t}\n\t\t\t\treturn forkSessionOrExit(resolved.path, cwd, sessionDir);\n\t\t\t}\n\n\t\t\tcase \"not_found\":\n\t\t\t\tconsole.error(chalk.red(`No session found matching '${resolved.arg}'`));\n\t\t\t\tprocess.exit(1);\n\t\t}\n\t}\n\n\tif (parsed.resume) {\n\t\tinitTheme(settingsManager.getTheme(), true);\n\t\ttry {\n\t\t\tconst selectedPath = await selectSession(\n\t\t\t\t(onProgress) => SessionManager.list(cwd, sessionDir, onProgress),\n\t\t\t\t(onProgress) => SessionManager.listAll(sessionDir, onProgress),\n\t\t\t);\n\t\t\tif (!selectedPath) {\n\t\t\t\tconsole.log(chalk.dim(\"No session selected\"));\n\t\t\t\tprocess.exit(0);\n\t\t\t}\n\t\t\treturn SessionManager.open(selectedPath, sessionDir);\n\t\t} finally {\n\t\t\tstopThemeWatcher();\n\t\t}\n\t}\n\n\tif (parsed.continue) {\n\t\treturn SessionManager.continueRecent(cwd, sessionDir);\n\t}\n\n\tif (parsed.sessionId) {\n\t\tconst existingSession = await findLocalSessionByExactId(parsed.sessionId, cwd, sessionDir);\n\t\tif (existingSession) {\n\t\t\treturn SessionManager.open(existingSession.path, sessionDir);\n\t\t}\n\t}\n\n\treturn SessionManager.create(cwd, sessionDir, { id: parsed.sessionId });\n}\n\nfunction buildSessionOptions(\n\tparsed: Args,\n\tscopedModels: ScopedModel[],\n\thasExistingSession: boolean,\n\tmodelRegistry: ModelRegistry,\n\tsettingsManager: SettingsManager,\n): {\n\toptions: CreateAgentSessionOptions;\n\tcliThinkingFromModel: boolean;\n\tdiagnostics: AgentSessionRuntimeDiagnostic[];\n} {\n\tconst options: CreateAgentSessionOptions = {};\n\tconst diagnostics: AgentSessionRuntimeDiagnostic[] = [];\n\tlet cliThinkingFromModel = false;\n\n\t// Model from CLI\n\t// - supports --provider <name> --model <pattern>\n\t// - supports --model <provider>/<pattern>\n\tif (parsed.model) {\n\t\tconst resolved = resolveCliModel({\n\t\t\tcliProvider: parsed.provider,\n\t\t\tcliModel: parsed.model,\n\t\t\tmodelRegistry,\n\t\t});\n\t\tif (resolved.warning) {\n\t\t\tdiagnostics.push({ type: \"warning\", message: resolved.warning });\n\t\t}\n\t\tif (resolved.error) {\n\t\t\tdiagnostics.push({ type: \"error\", message: resolved.error });\n\t\t}\n\t\tif (resolved.model) {\n\t\t\toptions.model = resolved.model;\n\t\t\toptions.modelPinned = true;\n\t\t\t// Allow \"--model <pattern>:<thinking>\" as a shorthand.\n\t\t\t// Explicit --thinking still takes precedence (applied later).\n\t\t\tif (!parsed.thinking && resolved.thinkingLevel) {\n\t\t\t\toptions.thinkingLevel = resolved.thinkingLevel;\n\t\t\t\tcliThinkingFromModel = true;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (!options.model && scopedModels.length > 0 && !hasExistingSession) {\n\t\t// Check if saved default is in scoped models - use it if so, otherwise first scoped model\n\t\tconst savedProvider = settingsManager.getDefaultProvider();\n\t\tconst savedModelId = settingsManager.getDefaultModel();\n\t\tconst savedModel = savedProvider && savedModelId ? modelRegistry.find(savedProvider, savedModelId) : undefined;\n\t\tconst savedInScope = savedModel ? scopedModels.find((sm) => modelsAreEqual(sm.model, savedModel)) : undefined;\n\n\t\tif (savedInScope) {\n\t\t\toptions.model = savedInScope.model;\n\t\t\t// Use thinking level from scoped model config if explicitly set\n\t\t\tif (!parsed.thinking && savedInScope.thinkingLevel) {\n\t\t\t\toptions.thinkingLevel = savedInScope.thinkingLevel;\n\t\t\t}\n\t\t} else {\n\t\t\toptions.model = scopedModels[0].model;\n\t\t\t// Use thinking level from first scoped model if explicitly set\n\t\t\tif (!parsed.thinking && scopedModels[0].thinkingLevel) {\n\t\t\t\toptions.thinkingLevel = scopedModels[0].thinkingLevel;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Thinking level from CLI (takes precedence over scoped model thinking levels set above)\n\tif (parsed.thinking) {\n\t\toptions.thinkingLevel = parsed.thinking;\n\t}\n\n\t// Scoped models for Ctrl+P cycling\n\t// Keep thinking level undefined when not explicitly set in the model pattern.\n\t// Undefined means \"inherit current session thinking level\" during cycling.\n\tif (scopedModels.length > 0) {\n\t\toptions.scopedModels = scopedModels.map((sm) => ({\n\t\t\tmodel: sm.model,\n\t\t\tthinkingLevel: sm.thinkingLevel,\n\t\t}));\n\t}\n\n\t// API key from CLI - set in authStorage\n\t// (handled by caller before createAgentSession)\n\n\t// Tools\n\tif (parsed.noTools) {\n\t\toptions.noTools = \"all\";\n\t} else if (parsed.noBuiltinTools) {\n\t\toptions.noTools = \"builtin\";\n\t}\n\tif (parsed.tools) {\n\t\toptions.tools = [...parsed.tools];\n\t}\n\tif (parsed.excludeTools) {\n\t\toptions.excludeTools = [...parsed.excludeTools];\n\t}\n\n\treturn { options, cliThinkingFromModel, diagnostics };\n}\n\nasync function promptForMissingSessionCwd(\n\tissue: SessionCwdIssue,\n\tsettingsManager: SettingsManager,\n): Promise<string | undefined> {\n\tinitTheme(settingsManager.getTheme());\n\tsetKeybindings(KeybindingsManager.create());\n\n\treturn new Promise((resolve) => {\n\t\tconst ui = new TUI(new ProcessTerminal(), settingsManager.getShowHardwareCursor());\n\t\tui.setClearOnShrink(settingsManager.getClearOnShrink());\n\n\t\tlet settled = false;\n\t\tconst finish = (result: string | undefined) => {\n\t\t\tif (settled) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tsettled = true;\n\t\t\tui.stop();\n\t\t\tresolve(result);\n\t\t};\n\n\t\tconst selector = new ExtensionSelectorComponent(\n\t\t\tformatMissingSessionCwdPrompt(issue),\n\t\t\t[\"Continue\", \"Cancel\"],\n\t\t\t(option) => finish(option === \"Continue\" ? issue.fallbackCwd : undefined),\n\t\t\t() => finish(undefined),\n\t\t\t{ tui: ui },\n\t\t);\n\t\tui.addChild(selector);\n\t\tui.setFocus(selector);\n\t\tui.start();\n\t});\n}\n\nexport interface MainOptions {\n\textensionFactories?: ExtensionFactory[];\n}\n\nexport async function main(args: string[], options?: MainOptions) {\n\tresetTimings();\n\tconst offlineMode = args.includes(\"--offline\") || isTruthyEnvFlag(process.env.OMK_OFFLINE);\n\tif (offlineMode) {\n\t\tprocess.env.OMK_OFFLINE = \"1\";\n\t\tprocess.env.OMK_SKIP_VERSION_CHECK = \"1\";\n\t}\n\n\tif (process.platform === \"win32\") {\n\t\tcleanupWindowsSelfUpdateQuarantine(getPackageDir());\n\t}\n\n\tconst packageDoctor = await runPackageDoctorCli(args);\n\tif (packageDoctor.handled) {\n\t\tprocess.exitCode = packageDoctor.exitCode;\n\t\treturn;\n\t}\n\n\tif (await handlePackageCommand(args)) {\n\t\treturn;\n\t}\n\n\tif (await handleConfigCommand(args)) {\n\t\treturn;\n\t}\n\n\tif (await handleCodexBarQuotaCommand(args)) {\n\t\treturn;\n\t}\n\n\t// Subcommands that report their own outcome, tried in order. Each claims a\n\t// distinct command prefix, so the first one that reports `handled` wins.\n\ttype CliOutcome = { readonly handled: boolean; readonly exitCode: number };\n\tconst outcomeCommands: ReadonlyArray<(argv: string[]) => CliOutcome | Promise<CliOutcome>> = [\n\t\trunSessionDoctorCli,\n\t\trunDoctorProviderCli,\n\t\trunResourceDoctorCli,\n\t\trunAdaptOrchDoctorCli,\n\t\trunStatsCli,\n\t\trunSdkSessionCli,\n\t\trunRouterFeedbackCli,\n\t];\n\tfor (const runCommand of outcomeCommands) {\n\t\tconst outcome = await runCommand(args);\n\t\tif (outcome.handled) {\n\t\t\tprocess.exitCode = outcome.exitCode;\n\t\t\treturn;\n\t\t}\n\t}\n\n\tconst parsed = parseArgs(args);\n\tif (parsed.diagnostics.length > 0) {\n\t\tfor (const d of parsed.diagnostics) {\n\t\t\tconst color = d.type === \"error\" ? chalk.red : chalk.yellow;\n\t\t\tconsole.error(color(`${d.type === \"error\" ? \"Error\" : \"Warning\"}: ${d.message}`));\n\t\t}\n\t\tif (parsed.diagnostics.some((d) => d.type === \"error\")) {\n\t\t\tprocess.exit(1);\n\t\t}\n\t}\n\ttime(\"parseArgs\");\n\tlet appMode = resolveAppMode(parsed, !!process.stdin.isTTY, !!process.stdout.isTTY);\n\t// Bare interactive launch: try to reclaim the controlling TTY when a host\n\t// detached stdio. Launcher may already have re-exec'd under `script`.\n\tif (appMode === \"interactive\" && !hasPromptIntent(parsed)) {\n\t\tif (!process.stdin.isTTY || !process.stdout.isTTY) {\n\t\t\tattachStdioToControllingTty();\n\t\t}\n\t\t// Do not hard-exit here — ProcessTerminal still works on many WSL/Windows\n\t\t// hosts even when Node's isTTY is false after a PTY re-exec race.\n\t}\n\tconst shouldTakeOverStdout = appMode !== \"interactive\";\n\tif (shouldTakeOverStdout) {\n\t\ttakeOverStdout();\n\t}\n\n\tif (parsed.version) {\n\t\tconsole.log(VERSION);\n\t\tprocess.exit(0);\n\t}\n\n\tif (parsed.export) {\n\t\tlet result: string;\n\t\ttry {\n\t\t\tconst outputPath = parsed.messages.length > 0 ? parsed.messages[0] : undefined;\n\t\t\tresult = await exportFromFile(parsed.export, outputPath);\n\t\t} catch (error: unknown) {\n\t\t\tconst message = error instanceof Error ? error.message : \"Failed to export session\";\n\t\t\tconsole.error(chalk.red(`Error: ${message}`));\n\t\t\tprocess.exit(1);\n\t\t}\n\t\tconsole.log(`Exported to: ${result}`);\n\t\tprocess.exit(0);\n\t}\n\n\tif (parsed.mode === \"rpc\" && parsed.fileArgs.length > 0) {\n\t\tconsole.error(chalk.red(\"Error: @file arguments are not supported in RPC mode\"));\n\t\tprocess.exit(1);\n\t}\n\n\tvalidateForkFlags(parsed);\n\tvalidateSessionIdFlags(parsed);\n\n\t// Run migrations (pass cwd for project-local migrations)\n\tconst { migratedAuthProviders: migratedProviders, deprecationWarnings } = runMigrations(process.cwd());\n\ttime(\"runMigrations\");\n\n\tconst cwd = process.cwd();\n\tconst agentDir = getAgentDir();\n\tconst startupSettingsManager = SettingsManager.create(cwd, agentDir);\n\treportDiagnostics(collectSettingsDiagnostics(startupSettingsManager, \"startup session lookup\"));\n\n\t// Decide the final runtime cwd before creating cwd-bound runtime services.\n\t// --session and --resume may select a session from another project, so project-local\n\t// settings, resources, provider registrations, and models must be resolved only after\n\t// the target session cwd is known. The startup-cwd settings manager is used only for\n\t// sessionDir lookup during session selection.\n\tconst envSessionDir = process.env[ENV_SESSION_DIR];\n\tconst sessionDir =\n\t\t(parsed.sessionDir ? normalizePath(parsed.sessionDir) : undefined) ??\n\t\t(envSessionDir ? expandTildePath(envSessionDir) : undefined) ??\n\t\tstartupSettingsManager.getSessionDir();\n\tlet sessionManager = await createSessionManager(parsed, cwd, sessionDir, startupSettingsManager);\n\tconst missingSessionCwdIssue = getMissingSessionCwdIssue(sessionManager, cwd);\n\tif (missingSessionCwdIssue) {\n\t\tif (appMode === \"interactive\") {\n\t\t\tconst selectedCwd = await promptForMissingSessionCwd(missingSessionCwdIssue, startupSettingsManager);\n\t\t\tif (!selectedCwd) {\n\t\t\t\tprocess.exit(0);\n\t\t\t}\n\t\t\tsessionManager = SessionManager.open(missingSessionCwdIssue.sessionFile!, sessionDir, selectedCwd);\n\t\t} else {\n\t\t\tconsole.error(chalk.red(new MissingSessionCwdError(missingSessionCwdIssue).message));\n\t\t\tprocess.exit(1);\n\t\t}\n\t}\n\tif (parsed.name !== undefined) {\n\t\tconst name = parsed.name.trim();\n\t\tif (!name) {\n\t\t\tconsole.error(chalk.red(\"Error: --name requires a non-empty value\"));\n\t\t\tprocess.exit(1);\n\t\t}\n\t\tsessionManager.appendSessionInfo(name);\n\t}\n\ttime(\"createSessionManager\");\n\n\tconst resolvedExtensionPaths = resolveCliPaths(cwd, parsed.extensions);\n\tconst resolvedSkillPaths = resolveCliPaths(cwd, parsed.skills);\n\tconst resolvedPromptTemplatePaths = resolveCliPaths(cwd, parsed.promptTemplates);\n\tconst resolvedThemePaths = resolveCliPaths(cwd, parsed.themes);\n\tconst authStorage = AuthStorage.create();\n\tconst createRuntime: CreateAgentSessionRuntimeFactory = async ({\n\t\tcwd,\n\t\tagentDir,\n\t\tsessionManager,\n\t\tsessionStartEvent,\n\t}) => {\n\t\tconst services = await createAgentSessionServices({\n\t\t\tcwd,\n\t\t\tagentDir,\n\t\t\tauthStorage,\n\t\t\textensionFlagValues: parsed.unknownFlags,\n\t\t\tresourceLoaderOptions: {\n\t\t\t\tadditionalExtensionPaths: resolvedExtensionPaths,\n\t\t\t\tadditionalSkillPaths: resolvedSkillPaths,\n\t\t\t\tadditionalPromptTemplatePaths: resolvedPromptTemplatePaths,\n\t\t\t\tadditionalThemePaths: resolvedThemePaths,\n\t\t\t\tnoExtensions: parsed.noExtensions,\n\t\t\t\tnoSkills: parsed.noSkills,\n\t\t\t\tnoPromptTemplates: parsed.noPromptTemplates,\n\t\t\t\tnoThemes: parsed.noThemes,\n\t\t\t\tnoContextFiles: parsed.noContextFiles,\n\t\t\t\tsystemPrompt: parsed.systemPrompt,\n\t\t\t\tappendSystemPrompt: parsed.appendSystemPrompt,\n\t\t\t\textensionFactories: options?.extensionFactories,\n\t\t\t},\n\t\t});\n\t\tconst { settingsManager, modelRegistry, resourceLoader } = services;\n\t\t// A discovered package extension that fails to load must not kill the process.\n\t\t// Any \"error\" diagnostic exits 1 below, and headless runs (subagents, review and\n\t\t// QA lanes) go through this same path — so one stale third-party package takes\n\t\t// down every spawned agent while the interactive session looks healthy. Only an\n\t\t// extension the user asked for by hand (-e/--extension) stays fatal.\n\t\tconst diagnostics: AgentSessionRuntimeDiagnostic[] = [\n\t\t\t...services.diagnostics,\n\t\t\t...collectSettingsDiagnostics(settingsManager, \"runtime creation\"),\n\t\t\t...resourceLoader.getExtensions().errors.map(({ path, error }) => ({\n\t\t\t\ttype: isExplicitExtensionDiagnostic(path, resolvedExtensionPaths)\n\t\t\t\t\t? (\"error\" as const)\n\t\t\t\t\t: (\"warning\" as const),\n\t\t\t\tmessage: `Failed to load extension \"${path}\": ${error}`,\n\t\t\t})),\n\t\t];\n\n\t\tconst modelPatterns = parsed.models ?? settingsManager.getEnabledModels();\n\t\tconst scopedModels =\n\t\t\tmodelPatterns && modelPatterns.length > 0 ? await resolveModelScope(modelPatterns, modelRegistry) : [];\n\t\tconst {\n\t\t\toptions: sessionOptions,\n\t\t\tcliThinkingFromModel,\n\t\t\tdiagnostics: sessionOptionDiagnostics,\n\t\t} = buildSessionOptions(\n\t\t\tparsed,\n\t\t\tscopedModels,\n\t\t\tsessionManager.buildSessionContext().messages.length > 0,\n\t\t\tmodelRegistry,\n\t\t\tsettingsManager,\n\t\t);\n\t\tdiagnostics.push(...sessionOptionDiagnostics);\n\n\t\tif (parsed.apiKey) {\n\t\t\tif (!sessionOptions.model) {\n\t\t\t\tdiagnostics.push({\n\t\t\t\t\ttype: \"error\",\n\t\t\t\t\tmessage: \"--api-key requires a model to be specified via --model, --provider/--model, or --models\",\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tauthStorage.setRuntimeApiKey(sessionOptions.model.provider, parsed.apiKey);\n\t\t\t}\n\t\t}\n\n\t\tconst created = await createAgentSessionFromServices({\n\t\t\tservices,\n\t\t\tsessionManager,\n\t\t\tsessionStartEvent,\n\t\t\tmodel: sessionOptions.model,\n\t\t\tthinkingLevel: sessionOptions.thinkingLevel,\n\t\t\tscopedModels: sessionOptions.scopedModels,\n\t\t\tmodelPinned: sessionOptions.modelPinned,\n\t\t\ttools: sessionOptions.tools,\n\t\t\texcludeTools: sessionOptions.excludeTools,\n\t\t\tnoTools: sessionOptions.noTools,\n\t\t\tcustomTools: sessionOptions.customTools,\n\t\t});\n\t\tconst cliThinkingOverride = parsed.thinking !== undefined || cliThinkingFromModel;\n\t\tif (created.session.model && cliThinkingOverride) {\n\t\t\tcreated.session.setThinkingLevel(created.session.thinkingLevel);\n\t\t}\n\t\t// Connect configured MCP servers so their tools reach the model in every CLI\n\t\t// mode and on every session switch. No configuration returns at once; a server\n\t\t// that fails to start is a warning, never fatal. Help/list-models never spawn.\n\t\tif (!parsed.help && parsed.listModels === undefined) {\n\t\t\tdiagnostics.push(...mcpAttachDiagnostics(await created.session.attachMcpServers()));\n\t\t}\n\n\t\treturn {\n\t\t\t...created,\n\t\t\tservices,\n\t\t\tdiagnostics,\n\t\t};\n\t};\n\ttime(\"createRuntime\");\n\tconst runtime = await createAgentSessionRuntime(createRuntime, {\n\t\tcwd: sessionManager.getCwd(),\n\t\tagentDir,\n\t\tsessionManager,\n\t});\n\ttime(\"createAgentSessionRuntime\");\n\tconst { services, session, modelFallbackMessage } = runtime;\n\tconst { settingsManager, modelRegistry, resourceLoader } = services;\n\tconfigureHttpDispatcher(settingsManager.getHttpIdleTimeoutMs());\n\n\tif (parsed.help) {\n\t\tconst extensionFlags = resourceLoader\n\t\t\t.getExtensions()\n\t\t\t.extensions.flatMap((extension) => Array.from(extension.flags.values()));\n\t\tprintHelp(extensionFlags);\n\t\tprocess.exit(0);\n\t}\n\n\tif (parsed.listModels !== undefined) {\n\t\tconst searchPattern = typeof parsed.listModels === \"string\" ? parsed.listModels : undefined;\n\t\tawait listModels(modelRegistry, searchPattern);\n\t\tprocess.exit(0);\n\t}\n\n\t// Read piped stdin content (if any) - skip for RPC mode which uses stdin for JSON-RPC.\n\t// Also skip on bare interactive launches so a stuck/non-tty stdin cannot force print mode.\n\tlet stdinContent: string | undefined;\n\tif (appMode !== \"rpc\" && !(appMode === \"interactive\" && !hasPromptIntent(parsed))) {\n\t\tstdinContent = await readPipedStdin();\n\t\tif (stdinContent !== undefined && appMode === \"interactive\") {\n\t\t\tappMode = \"print\";\n\t\t}\n\t}\n\ttime(\"readPipedStdin\");\n\n\tconst { initialMessage, initialImages } = await prepareInitialMessage(\n\t\tparsed,\n\t\tsettingsManager.getImageAutoResize(),\n\t\tstdinContent,\n\t);\n\ttime(\"prepareInitialMessage\");\n\tinitTheme(settingsManager.getTheme(), appMode === \"interactive\");\n\ttime(\"initTheme\");\n\n\t// Show deprecation warnings in interactive mode\n\tif (appMode === \"interactive\" && deprecationWarnings.length > 0) {\n\t\tawait showDeprecationWarnings(deprecationWarnings);\n\t}\n\n\ttime(\"resolveModelScope\");\n\treportDiagnostics(runtime.diagnostics);\n\tif (runtime.diagnostics.some((diagnostic) => diagnostic.type === \"error\")) {\n\t\tprocess.exit(1);\n\t}\n\ttime(\"createAgentSession\");\n\n\tif (appMode !== \"interactive\" && !session.model) {\n\t\tconsole.error(chalk.red(formatNoModelsAvailableMessage()));\n\t\tprocess.exit(1);\n\t}\n\n\tconst startupBenchmark = isTruthyEnvFlag(process.env.OMK_STARTUP_BENCHMARK);\n\tif (startupBenchmark && appMode !== \"interactive\") {\n\t\tconsole.error(chalk.red(\"Error: OMK_STARTUP_BENCHMARK only supports interactive mode\"));\n\t\tprocess.exit(1);\n\t}\n\n\tif (appMode === \"rpc\") {\n\t\tprintTimings();\n\t\tawait runRpcMode(runtime);\n\t} else if (appMode === \"interactive\") {\n\t\tconst interactiveMode = new InteractiveMode(runtime, {\n\t\t\tmigratedProviders,\n\t\t\tmodelFallbackMessage,\n\t\t\tinitialMessage,\n\t\t\tinitialImages,\n\t\t\tinitialMessages: parsed.messages,\n\t\t\tverbose: parsed.verbose,\n\t\t});\n\t\tif (startupBenchmark) {\n\t\t\tawait interactiveMode.init();\n\t\t\ttime(\"interactiveMode.init\");\n\t\t\tprintTimings();\n\t\t\tinteractiveMode.stop();\n\t\t\tstopThemeWatcher();\n\t\t\tif (process.stdout.writableLength > 0) {\n\t\t\t\tawait new Promise<void>((resolve) => process.stdout.once(\"drain\", resolve));\n\t\t\t}\n\t\t\tif (process.stderr.writableLength > 0) {\n\t\t\t\tawait new Promise<void>((resolve) => process.stderr.once(\"drain\", resolve));\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tprintTimings();\n\t\tawait interactiveMode.run();\n\t} else {\n\t\tprintTimings();\n\t\tconst exitCode = await runPrintMode(runtime, {\n\t\t\tmode: toPrintOutputMode(appMode),\n\t\t\tmessages: parsed.messages,\n\t\t\tinitialMessage,\n\t\t\tinitialImages,\n\t\t});\n\t\tstopThemeWatcher();\n\t\trestoreStdout();\n\t\tif (exitCode !== 0) {\n\t\t\tprocess.exitCode = exitCode;\n\t\t}\n\t\treturn;\n\t}\n}\n"]}
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAcH,OAAO,EAAE,6BAA6B,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAiBzF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAwBnE,OAAO,EAAE,6BAA6B,EAAE,eAAe,EAAE,CAAC;AAmf1D,MAAM,WAAW,WAAW;IAC3B,kBAAkB,CAAC,EAAE,gBAAgB,EAAE,CAAC;CACxC;AAED,wBAAsB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,WAAW,iBA8W/D","sourcesContent":["/**\n * Main entry point for the coding agent CLI.\n *\n * This file handles CLI argument parsing and translates them into\n * createAgentSession() options. The SDK does the heavy lifting.\n */\n\nimport * as fs from \"node:fs\";\nimport * as net from \"node:net\";\nimport { createInterface } from \"node:readline\";\nimport chalk from \"chalk\";\nimport { type ImageContent, modelsAreEqual } from \"omk-ai\";\nimport { ProcessTerminal, setKeybindings, TUI } from \"omk-tui\";\nimport { type Args, type Mode, parseArgs, printHelp } from \"./cli/args.ts\";\nimport { processFileArguments } from \"./cli/file-processor.ts\";\nimport { buildInitialMessage } from \"./cli/initial-message.ts\";\nimport { listModels } from \"./cli/list-models.ts\";\nimport { mcpAttachDiagnostics } from \"./cli/mcp-attach.ts\";\nimport { loadModelContractOrExit } from \"./cli/model-contract.ts\";\nimport { isExplicitExtensionDiagnostic, resolveCliPaths } from \"./cli/resource-paths.ts\";\nimport { selectSession } from \"./cli/session-picker.ts\";\nimport { handleCodexBarQuotaCommand } from \"./codexbar-cli.ts\";\nimport { runInitCli } from \"./commands/init-cli.ts\";\nimport { runPackageDoctorCli } from \"./commands/package-doctor-cli.ts\";\nimport { runProviderSyncCli } from \"./commands/provider-sync-cli.ts\";\nimport { runCommand } from \"./commands/run-command.ts\";\nimport { ENV_SESSION_DIR, expandTildePath, getAgentDir, getPackageDir, VERSION } from \"./config.ts\";\nimport { type CreateAgentSessionRuntimeFactory, createAgentSessionRuntime } from \"./core/agent-session-runtime.ts\";\nimport {\n\ttype AgentSessionRuntimeDiagnostic,\n\tcreateAgentSessionFromServices,\n\tcreateAgentSessionServices,\n} from \"./core/agent-session-services.ts\";\nimport { formatNoModelsAvailableMessage } from \"./core/auth-guidance.ts\";\nimport { AuthStorage } from \"./core/auth-storage.ts\";\nimport { exportFromFile } from \"./core/export-html/index.ts\";\nimport type { ExtensionFactory } from \"./core/extensions/types.ts\";\nimport { configureHttpDispatcher } from \"./core/http-dispatcher.ts\";\nimport { KeybindingsManager } from \"./core/keybindings.ts\";\nimport type { ModelRegistry } from \"./core/model-registry.ts\";\nimport { resolveCliModel, resolveModelScope, type ScopedModel } from \"./core/model-resolver.ts\";\nimport { restoreStdout, takeOverStdout } from \"./core/output-guard.ts\";\nimport type { CreateAgentSessionOptions } from \"./core/sdk.ts\";\nimport {\n\tformatMissingSessionCwdPrompt,\n\tgetMissingSessionCwdIssue,\n\tMissingSessionCwdError,\n\ttype SessionCwdIssue,\n} from \"./core/session-cwd.ts\";\nimport { assertValidSessionId, SessionManager } from \"./core/session-manager.ts\";\nimport { SettingsManager } from \"./core/settings-manager.ts\";\nimport { printTimings, resetTimings, time } from \"./core/timings.ts\";\nimport { runMigrations, showDeprecationWarnings } from \"./migrations.ts\";\nimport { InteractiveMode, runPrintMode, runRpcMode } from \"./modes/index.ts\";\nimport { ExtensionSelectorComponent } from \"./modes/interactive/components/extension-selector.ts\";\nimport { initTheme, stopThemeWatcher } from \"./modes/interactive/theme/theme.ts\";\nimport { handleConfigCommand, handlePackageCommand } from \"./package-manager-cli.ts\";\nimport { normalizePath, resolvePath } from \"./utils/paths.ts\";\nimport { cleanupWindowsSelfUpdateQuarantine } from \"./utils/windows-self-update.ts\";\n\nexport { isExplicitExtensionDiagnostic, resolveCliPaths };\n\n/**\n * Read all content from piped stdin.\n * Returns undefined if stdin is a TTY (interactive terminal).\n *\n * Non-TTY stdin that never ends (some IDE/terminal hosts keep fd0 open) used to\n * hang forever here — that looked like \"omk\" with no response. Bound the wait:\n * if no bytes arrive quickly and nothing is buffered, treat as empty.\n */\nasync function readPipedStdin(): Promise<string | undefined> {\n\t// If stdin is a TTY, we're running interactively - don't read stdin\n\tif (process.stdin.isTTY) {\n\t\treturn undefined;\n\t}\n\n\t// Already drained\n\tif (process.stdin.readableEnded) {\n\t\treturn undefined;\n\t}\n\n\tconst idleMs = Number(process.env.OMK_STDIN_IDLE_MS || 50);\n\treturn new Promise((resolve) => {\n\t\tlet data = \"\";\n\t\tlet settled = false;\n\t\tconst finish = () => {\n\t\t\tif (settled) return;\n\t\t\tsettled = true;\n\t\t\tclearTimeout(timer);\n\t\t\tprocess.stdin.off(\"data\", onData);\n\t\t\tprocess.stdin.off(\"end\", onEnd);\n\t\t\tprocess.stdin.off(\"error\", onEnd);\n\t\t\tresolve(data.trim() || undefined);\n\t\t};\n\t\tconst onData = (chunk: string | Buffer) => {\n\t\t\tdata += typeof chunk === \"string\" ? chunk : chunk.toString(\"utf8\");\n\t\t\t// Once data starts flowing, wait for natural end (or a long idle).\n\t\t\tclearTimeout(timer);\n\t\t\ttimer = setTimeout(finish, Math.max(idleMs * 20, 1000));\n\t\t};\n\t\tconst onEnd = () => finish();\n\t\tlet timer = setTimeout(finish, Number.isFinite(idleMs) ? Math.max(0, idleMs) : 50);\n\t\tprocess.stdin.setEncoding(\"utf8\");\n\t\tprocess.stdin.on(\"data\", onData);\n\t\tprocess.stdin.on(\"end\", onEnd);\n\t\tprocess.stdin.on(\"error\", onEnd);\n\t\tprocess.stdin.resume();\n\t});\n}\n\nfunction collectSettingsDiagnostics(\n\tsettingsManager: SettingsManager,\n\tcontext: string,\n): AgentSessionRuntimeDiagnostic[] {\n\treturn settingsManager.drainErrors().map(({ scope, error }) => ({\n\t\ttype: \"warning\",\n\t\tmessage: `(${context}, ${scope} settings) ${error.message}`,\n\t}));\n}\n\nfunction reportDiagnostics(diagnostics: readonly AgentSessionRuntimeDiagnostic[]): void {\n\tfor (const diagnostic of diagnostics) {\n\t\tconst color = diagnostic.type === \"error\" ? chalk.red : diagnostic.type === \"warning\" ? chalk.yellow : chalk.dim;\n\t\tconst prefix = diagnostic.type === \"error\" ? \"Error: \" : diagnostic.type === \"warning\" ? \"Warning: \" : \"\";\n\t\tconsole.error(color(`${prefix}${diagnostic.message}`));\n\t}\n}\n\nfunction isTruthyEnvFlag(value: string | undefined): boolean {\n\tif (!value) return false;\n\treturn value === \"1\" || value.toLowerCase() === \"true\" || value.toLowerCase() === \"yes\";\n}\n\ntype AppMode = \"interactive\" | \"print\" | \"json\" | \"rpc\";\n\nfunction hasPromptIntent(parsed: Args): boolean {\n\treturn (\n\t\tparsed.print === true ||\n\t\tparsed.messages.length > 0 ||\n\t\tparsed.fileArgs.length > 0 ||\n\t\tparsed.mode === \"json\" ||\n\t\tparsed.mode === \"rpc\"\n\t);\n}\n\n/**\n * When stdin/stdout were detached from the TTY (some IDE hosts / wrappers),\n * rebind them to /dev/tty so InteractiveMode/ProcessTerminal can run.\n * No-op if already a TTY or /dev/tty is unavailable.\n */\nfunction attachStdioToControllingTty(): boolean {\n\tif (process.stdin.isTTY && process.stdout.isTTY) return true;\n\ttry {\n\t\t// Prefer reopening stdio FDs against the controlling terminal.\n\t\t// Socket-over-/dev/tty is enough for isTTY detection + raw mode shim.\n\t\tconst fd = fs.openSync(\"/dev/tty\", \"r+\");\n\t\tconst sock = new net.Socket({ fd, readable: true, writable: true });\n\t\tObject.defineProperty(sock, \"isTTY\", { value: true, configurable: true });\n\t\tObject.defineProperty(sock, \"isRaw\", { value: false, writable: true, configurable: true });\n\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t(sock as any).setRawMode = (mode: boolean) => {\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\t(sock as any).isRaw = !!mode;\n\t\t\treturn sock;\n\t\t};\n\t\tif (!process.stdin.isTTY) {\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\t(process as any).stdin = sock;\n\t\t}\n\t\tif (!process.stdout.isTTY) {\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\t(process as any).stdout = sock;\n\t\t}\n\t\treturn !!(process.stdin.isTTY && process.stdout.isTTY);\n\t} catch {\n\t\treturn !!(process.stdin.isTTY && process.stdout.isTTY);\n\t}\n}\n\nfunction resolveAppMode(parsed: Args, stdinIsTTY: boolean, stdoutIsTTY: boolean = !!process.stdout.isTTY): AppMode {\n\tif (parsed.mode === \"rpc\") {\n\t\treturn \"rpc\";\n\t}\n\tif (parsed.mode === \"json\") {\n\t\treturn \"json\";\n\t}\n\t// Explicit single-shot (-p / --print)\n\tif (parsed.print) {\n\t\treturn \"print\";\n\t}\n\t// Bare `omk` (no prompt args) must open the TUI. Never fall into silent/empty print.\n\tif (!hasPromptIntent(parsed)) {\n\t\treturn \"interactive\";\n\t}\n\t// Piped automation: non-tty stdin with a prompt → print mode\n\tif (!stdinIsTTY || !stdoutIsTTY) {\n\t\treturn \"print\";\n\t}\n\treturn \"interactive\";\n}\n\nfunction toPrintOutputMode(appMode: AppMode): Exclude<Mode, \"rpc\"> {\n\treturn appMode === \"json\" ? \"json\" : \"text\";\n}\n\nasync function prepareInitialMessage(\n\tparsed: Args,\n\tautoResizeImages: boolean,\n\tstdinContent?: string,\n): Promise<{\n\tinitialMessage?: string;\n\tinitialImages?: ImageContent[];\n}> {\n\tif (parsed.fileArgs.length === 0) {\n\t\treturn buildInitialMessage({ parsed, stdinContent });\n\t}\n\n\tconst { text, images } = await processFileArguments(parsed.fileArgs, { autoResizeImages });\n\treturn buildInitialMessage({\n\t\tparsed,\n\t\tfileText: text,\n\t\tfileImages: images,\n\t\tstdinContent,\n\t});\n}\n\n/** Result from resolving a session argument */\ntype ResolvedSession =\n\t| { type: \"path\"; path: string } // Direct file path\n\t| { type: \"local\"; path: string } // Found in current project\n\t| { type: \"global\"; path: string; cwd: string } // Found in different project\n\t| { type: \"not_found\"; arg: string }; // Not found anywhere\n\n/**\n * Resolve a session argument to a file path.\n * If it looks like a path, use as-is. Otherwise try to match as session ID prefix.\n */\nasync function findLocalSessionByExactId(\n\tsessionId: string,\n\tcwd: string,\n\tsessionDir?: string,\n): Promise<{ type: \"local\"; path: string } | undefined> {\n\tconst localSessions = await SessionManager.list(cwd, sessionDir);\n\tconst localMatch = localSessions.find((s) => s.id === sessionId);\n\treturn localMatch ? { type: \"local\", path: localMatch.path } : undefined;\n}\n\nasync function resolveSessionPath(sessionArg: string, cwd: string, sessionDir?: string): Promise<ResolvedSession> {\n\t// If it looks like a file path, resolve it before handing it to the session manager.\n\tif (sessionArg.includes(\"/\") || sessionArg.includes(\"\\\\\") || sessionArg.endsWith(\".jsonl\")) {\n\t\treturn { type: \"path\", path: resolvePath(sessionArg, cwd) };\n\t}\n\n\t// Try to match as session ID in current project first\n\tconst localSessions = await SessionManager.list(cwd, sessionDir);\n\tconst localMatch =\n\t\tlocalSessions.find((s) => s.id === sessionArg) ?? localSessions.find((s) => s.id.startsWith(sessionArg));\n\n\tif (localMatch) {\n\t\treturn { type: \"local\", path: localMatch.path };\n\t}\n\n\t// Try global search across all projects\n\tconst allSessions = await SessionManager.listAll(sessionDir);\n\tconst globalMatch =\n\t\tallSessions.find((s) => s.id === sessionArg) ?? allSessions.find((s) => s.id.startsWith(sessionArg));\n\n\tif (globalMatch) {\n\t\treturn { type: \"global\", path: globalMatch.path, cwd: globalMatch.cwd };\n\t}\n\n\t// Not found anywhere\n\treturn { type: \"not_found\", arg: sessionArg };\n}\n\n/** Prompt user for yes/no confirmation */\nasync function promptConfirm(message: string): Promise<boolean> {\n\treturn new Promise((resolve) => {\n\t\tconst rl = createInterface({\n\t\t\tinput: process.stdin,\n\t\t\toutput: process.stdout,\n\t\t});\n\t\trl.question(`${message} [y/N] `, (answer) => {\n\t\t\trl.close();\n\t\t\tresolve(answer.toLowerCase() === \"y\" || answer.toLowerCase() === \"yes\");\n\t\t});\n\t});\n}\n\nfunction validateForkFlags(parsed: Args): void {\n\tif (!parsed.fork) return;\n\n\tconst conflictingFlags = [\n\t\tparsed.session ? \"--session\" : undefined,\n\t\tparsed.continue ? \"--continue\" : undefined,\n\t\tparsed.resume ? \"--resume\" : undefined,\n\t\tparsed.noSession ? \"--no-session\" : undefined,\n\t].filter((flag): flag is string => flag !== undefined);\n\n\tif (conflictingFlags.length > 0) {\n\t\tconsole.error(chalk.red(`Error: --fork cannot be combined with ${conflictingFlags.join(\", \")}`));\n\t\tprocess.exit(1);\n\t}\n}\n\nfunction validateSessionIdFlags(parsed: Args): void {\n\tif (parsed.sessionId === undefined) return;\n\n\tconst conflictingFlags = [\n\t\tparsed.session ? \"--session\" : undefined,\n\t\tparsed.continue ? \"--continue\" : undefined,\n\t\tparsed.resume ? \"--resume\" : undefined,\n\t\tparsed.noSession ? \"--no-session\" : undefined,\n\t].filter((flag): flag is string => flag !== undefined);\n\n\tif (conflictingFlags.length > 0) {\n\t\tconsole.error(chalk.red(`Error: --session-id cannot be combined with ${conflictingFlags.join(\", \")}`));\n\t\tprocess.exit(1);\n\t}\n\n\ttry {\n\t\tassertValidSessionId(parsed.sessionId);\n\t} catch (error: unknown) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tconsole.error(chalk.red(`Error: ${message}`));\n\t\tprocess.exit(1);\n\t}\n}\n\nfunction forkSessionOrExit(sourcePath: string, cwd: string, sessionDir?: string, sessionId?: string): SessionManager {\n\ttry {\n\t\treturn SessionManager.forkFrom(sourcePath, cwd, sessionDir, { id: sessionId });\n\t} catch (error: unknown) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\tconsole.error(chalk.red(`Error: ${message}`));\n\t\tprocess.exit(1);\n\t}\n}\n\nasync function createSessionManager(\n\tparsed: Args,\n\tcwd: string,\n\tsessionDir: string | undefined,\n\tsettingsManager: SettingsManager,\n): Promise<SessionManager> {\n\tif (parsed.noSession || parsed.help || parsed.listModels !== undefined) {\n\t\treturn SessionManager.inMemory(cwd);\n\t}\n\n\tif (parsed.fork) {\n\t\tif (parsed.sessionId) {\n\t\t\tconst existingTarget = await findLocalSessionByExactId(parsed.sessionId, cwd, sessionDir);\n\t\t\tif (existingTarget) {\n\t\t\t\tconsole.error(chalk.red(`Session already exists with id '${parsed.sessionId}'`));\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t}\n\n\t\tconst resolved = await resolveSessionPath(parsed.fork, cwd, sessionDir);\n\n\t\tswitch (resolved.type) {\n\t\t\tcase \"path\":\n\t\t\tcase \"local\":\n\t\t\tcase \"global\":\n\t\t\t\treturn forkSessionOrExit(resolved.path, cwd, sessionDir, parsed.sessionId);\n\n\t\t\tcase \"not_found\":\n\t\t\t\tconsole.error(chalk.red(`No session found matching '${resolved.arg}'`));\n\t\t\t\tprocess.exit(1);\n\t\t}\n\t}\n\n\tif (parsed.session) {\n\t\tconst resolved = await resolveSessionPath(parsed.session, cwd, sessionDir);\n\n\t\tswitch (resolved.type) {\n\t\t\tcase \"path\":\n\t\t\tcase \"local\":\n\t\t\t\treturn SessionManager.open(resolved.path, sessionDir);\n\n\t\t\tcase \"global\": {\n\t\t\t\tconsole.log(chalk.yellow(`Session found in different project: ${resolved.cwd}`));\n\t\t\t\tconst shouldFork = await promptConfirm(\"Fork this session into current directory?\");\n\t\t\t\tif (!shouldFork) {\n\t\t\t\t\tconsole.log(chalk.dim(\"Aborted.\"));\n\t\t\t\t\tprocess.exit(0);\n\t\t\t\t}\n\t\t\t\treturn forkSessionOrExit(resolved.path, cwd, sessionDir);\n\t\t\t}\n\n\t\t\tcase \"not_found\":\n\t\t\t\tconsole.error(chalk.red(`No session found matching '${resolved.arg}'`));\n\t\t\t\tprocess.exit(1);\n\t\t}\n\t}\n\n\tif (parsed.resume) {\n\t\tinitTheme(settingsManager.getTheme(), true);\n\t\ttry {\n\t\t\tconst selectedPath = await selectSession(\n\t\t\t\t(onProgress) => SessionManager.list(cwd, sessionDir, onProgress),\n\t\t\t\t(onProgress) => SessionManager.listAll(sessionDir, onProgress),\n\t\t\t);\n\t\t\tif (!selectedPath) {\n\t\t\t\tconsole.log(chalk.dim(\"No session selected\"));\n\t\t\t\tprocess.exit(0);\n\t\t\t}\n\t\t\treturn SessionManager.open(selectedPath, sessionDir);\n\t\t} finally {\n\t\t\tstopThemeWatcher();\n\t\t}\n\t}\n\n\tif (parsed.continue) {\n\t\treturn SessionManager.continueRecent(cwd, sessionDir);\n\t}\n\n\tif (parsed.sessionId) {\n\t\tconst existingSession = await findLocalSessionByExactId(parsed.sessionId, cwd, sessionDir);\n\t\tif (existingSession) {\n\t\t\treturn SessionManager.open(existingSession.path, sessionDir);\n\t\t}\n\t}\n\n\treturn SessionManager.create(cwd, sessionDir, { id: parsed.sessionId });\n}\n\nfunction buildSessionOptions(\n\tparsed: Args,\n\tscopedModels: ScopedModel[],\n\thasExistingSession: boolean,\n\tmodelRegistry: ModelRegistry,\n\tsettingsManager: SettingsManager,\n): {\n\toptions: CreateAgentSessionOptions;\n\tcliThinkingFromModel: boolean;\n\tdiagnostics: AgentSessionRuntimeDiagnostic[];\n} {\n\tconst options: CreateAgentSessionOptions = {};\n\tconst diagnostics: AgentSessionRuntimeDiagnostic[] = [];\n\tlet cliThinkingFromModel = false;\n\n\t// Model from CLI\n\t// - supports --provider <name> --model <pattern>\n\t// - supports --model <provider>/<pattern>\n\tif (parsed.model) {\n\t\tconst resolved = resolveCliModel({\n\t\t\tcliProvider: parsed.provider,\n\t\t\tcliModel: parsed.model,\n\t\t\tmodelRegistry,\n\t\t});\n\t\tif (resolved.warning) {\n\t\t\tdiagnostics.push({ type: \"warning\", message: resolved.warning });\n\t\t}\n\t\tif (resolved.error) {\n\t\t\tdiagnostics.push({ type: \"error\", message: resolved.error });\n\t\t}\n\t\tif (resolved.model) {\n\t\t\toptions.model = resolved.model;\n\t\t\toptions.modelPinned = true;\n\t\t\t// Allow \"--model <pattern>:<thinking>\" as a shorthand.\n\t\t\t// Explicit --thinking still takes precedence (applied later).\n\t\t\tif (!parsed.thinking && resolved.thinkingLevel) {\n\t\t\t\toptions.thinkingLevel = resolved.thinkingLevel;\n\t\t\t\tcliThinkingFromModel = true;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (!options.model && scopedModels.length > 0 && !hasExistingSession) {\n\t\t// Check if saved default is in scoped models - use it if so, otherwise first scoped model\n\t\tconst savedProvider = settingsManager.getDefaultProvider();\n\t\tconst savedModelId = settingsManager.getDefaultModel();\n\t\tconst savedModel = savedProvider && savedModelId ? modelRegistry.find(savedProvider, savedModelId) : undefined;\n\t\tconst savedInScope = savedModel ? scopedModels.find((sm) => modelsAreEqual(sm.model, savedModel)) : undefined;\n\n\t\tif (savedInScope) {\n\t\t\toptions.model = savedInScope.model;\n\t\t\t// Use thinking level from scoped model config if explicitly set\n\t\t\tif (!parsed.thinking && savedInScope.thinkingLevel) {\n\t\t\t\toptions.thinkingLevel = savedInScope.thinkingLevel;\n\t\t\t}\n\t\t} else {\n\t\t\toptions.model = scopedModels[0].model;\n\t\t\t// Use thinking level from first scoped model if explicitly set\n\t\t\tif (!parsed.thinking && scopedModels[0].thinkingLevel) {\n\t\t\t\toptions.thinkingLevel = scopedModels[0].thinkingLevel;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Thinking level from CLI (takes precedence over scoped model thinking levels set above)\n\tif (parsed.thinking) {\n\t\toptions.thinkingLevel = parsed.thinking;\n\t}\n\n\t// Scoped models for Ctrl+P cycling\n\t// Keep thinking level undefined when not explicitly set in the model pattern.\n\t// Undefined means \"inherit current session thinking level\" during cycling.\n\tif (scopedModels.length > 0) {\n\t\toptions.scopedModels = scopedModels.map((sm) => ({\n\t\t\tmodel: sm.model,\n\t\t\tthinkingLevel: sm.thinkingLevel,\n\t\t}));\n\t}\n\n\t// API key from CLI - set in authStorage\n\t// (handled by caller before createAgentSession)\n\n\t// Tools\n\tif (parsed.noTools) {\n\t\toptions.noTools = \"all\";\n\t} else if (parsed.noBuiltinTools) {\n\t\toptions.noTools = \"builtin\";\n\t}\n\tif (parsed.tools) {\n\t\toptions.tools = [...parsed.tools];\n\t}\n\tif (parsed.excludeTools) {\n\t\toptions.excludeTools = [...parsed.excludeTools];\n\t}\n\n\treturn { options, cliThinkingFromModel, diagnostics };\n}\n\nasync function promptForMissingSessionCwd(\n\tissue: SessionCwdIssue,\n\tsettingsManager: SettingsManager,\n): Promise<string | undefined> {\n\tinitTheme(settingsManager.getTheme());\n\tsetKeybindings(KeybindingsManager.create());\n\n\treturn new Promise((resolve) => {\n\t\tconst ui = new TUI(new ProcessTerminal(), settingsManager.getShowHardwareCursor());\n\t\tui.setClearOnShrink(settingsManager.getClearOnShrink());\n\n\t\tlet settled = false;\n\t\tconst finish = (result: string | undefined) => {\n\t\t\tif (settled) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tsettled = true;\n\t\t\tui.stop();\n\t\t\tresolve(result);\n\t\t};\n\n\t\tconst selector = new ExtensionSelectorComponent(\n\t\t\tformatMissingSessionCwdPrompt(issue),\n\t\t\t[\"Continue\", \"Cancel\"],\n\t\t\t(option) => finish(option === \"Continue\" ? issue.fallbackCwd : undefined),\n\t\t\t() => finish(undefined),\n\t\t\t{ tui: ui },\n\t\t);\n\t\tui.addChild(selector);\n\t\tui.setFocus(selector);\n\t\tui.start();\n\t});\n}\n\nexport interface MainOptions {\n\textensionFactories?: ExtensionFactory[];\n}\n\nexport async function main(args: string[], options?: MainOptions) {\n\tconst initialization = runInitCli(args);\n\tif (initialization.handled) {\n\t\tprocess.exitCode = initialization.exitCode;\n\t\treturn;\n\t}\n\tresetTimings();\n\tconst offlineMode = args.includes(\"--offline\") || isTruthyEnvFlag(process.env.OMK_OFFLINE);\n\tif (offlineMode) {\n\t\tprocess.env.OMK_OFFLINE = \"1\";\n\t\tprocess.env.OMK_SKIP_VERSION_CHECK = \"1\";\n\t}\n\n\tif (process.platform === \"win32\") {\n\t\tcleanupWindowsSelfUpdateQuarantine(getPackageDir());\n\t}\n\n\tconst packageDoctor = await runPackageDoctorCli(args);\n\tif (packageDoctor.handled) {\n\t\tprocess.exitCode = packageDoctor.exitCode;\n\t\treturn;\n\t}\n\n\tif (await handlePackageCommand(args)) {\n\t\treturn;\n\t}\n\n\tif (await handleConfigCommand(args)) {\n\t\treturn;\n\t}\n\n\tif (await handleCodexBarQuotaCommand(args)) {\n\t\treturn;\n\t}\n\n\tconst providerSync = await runProviderSyncCli(args);\n\tif (providerSync.handled) {\n\t\tprocess.exitCode = providerSync.exitCode;\n\t\treturn;\n\t}\n\n\tconst outcome = await runCommand(args);\n\tif (outcome.handled) {\n\t\tprocess.exitCode = outcome.exitCode;\n\t\treturn;\n\t}\n\n\tconst parsed = parseArgs(args);\n\tif (parsed.diagnostics.length > 0) {\n\t\tfor (const d of parsed.diagnostics) {\n\t\t\tconst color = d.type === \"error\" ? chalk.red : chalk.yellow;\n\t\t\tconsole.error(color(`${d.type === \"error\" ? \"Error\" : \"Warning\"}: ${d.message}`));\n\t\t}\n\t\tif (parsed.diagnostics.some((d) => d.type === \"error\")) {\n\t\t\tprocess.exit(1);\n\t\t}\n\t}\n\ttime(\"parseArgs\");\n\tlet appMode = resolveAppMode(parsed, !!process.stdin.isTTY, !!process.stdout.isTTY);\n\t// Bare interactive launch: try to reclaim the controlling TTY when a host\n\t// detached stdio. Launcher may already have re-exec'd under `script`.\n\tif (appMode === \"interactive\" && !hasPromptIntent(parsed)) {\n\t\tif (!process.stdin.isTTY || !process.stdout.isTTY) {\n\t\t\tattachStdioToControllingTty();\n\t\t}\n\t\t// Do not hard-exit here — ProcessTerminal still works on many WSL/Windows\n\t\t// hosts even when Node's isTTY is false after a PTY re-exec race.\n\t}\n\tconst shouldTakeOverStdout = appMode !== \"interactive\";\n\tif (shouldTakeOverStdout) {\n\t\ttakeOverStdout();\n\t}\n\n\tif (parsed.version) {\n\t\tconsole.log(VERSION);\n\t\tprocess.exit(0);\n\t}\n\n\tif (parsed.export) {\n\t\tlet result: string;\n\t\ttry {\n\t\t\tconst outputPath = parsed.messages.length > 0 ? parsed.messages[0] : undefined;\n\t\t\tresult = await exportFromFile(parsed.export, outputPath);\n\t\t} catch (error: unknown) {\n\t\t\tconst message = error instanceof Error ? error.message : \"Failed to export session\";\n\t\t\tconsole.error(chalk.red(`Error: ${message}`));\n\t\t\tprocess.exit(1);\n\t\t}\n\t\tconsole.log(`Exported to: ${result}`);\n\t\tprocess.exit(0);\n\t}\n\n\tif (parsed.mode === \"rpc\" && parsed.fileArgs.length > 0) {\n\t\tconsole.error(chalk.red(\"Error: @file arguments are not supported in RPC mode\"));\n\t\tprocess.exit(1);\n\t}\n\n\tvalidateForkFlags(parsed);\n\tvalidateSessionIdFlags(parsed);\n\n\tconst modelContract =\n\t\tparsed.modelContractFile && !parsed.help\n\t\t\t? loadModelContractOrExit(resolvePath(parsed.modelContractFile))\n\t\t\t: undefined;\n\n\t// Run migrations (pass cwd for project-local migrations)\n\tconst { migratedAuthProviders: migratedProviders, deprecationWarnings } = runMigrations(process.cwd());\n\ttime(\"runMigrations\");\n\n\tconst cwd = process.cwd();\n\tconst agentDir = getAgentDir();\n\tconst startupSettingsManager = SettingsManager.create(cwd, agentDir);\n\treportDiagnostics(collectSettingsDiagnostics(startupSettingsManager, \"startup session lookup\"));\n\n\t// Decide the final runtime cwd before creating cwd-bound runtime services.\n\t// --session and --resume may select a session from another project, so project-local\n\t// settings, resources, provider registrations, and models must be resolved only after\n\t// the target session cwd is known. The startup-cwd settings manager is used only for\n\t// sessionDir lookup during session selection.\n\tconst envSessionDir = process.env[ENV_SESSION_DIR];\n\tconst sessionDir =\n\t\t(parsed.sessionDir ? normalizePath(parsed.sessionDir) : undefined) ??\n\t\t(envSessionDir ? expandTildePath(envSessionDir) : undefined) ??\n\t\tstartupSettingsManager.getSessionDir();\n\tlet sessionManager = await createSessionManager(parsed, cwd, sessionDir, startupSettingsManager);\n\tconst missingSessionCwdIssue = getMissingSessionCwdIssue(sessionManager, cwd);\n\tif (missingSessionCwdIssue) {\n\t\tif (appMode === \"interactive\") {\n\t\t\tconst selectedCwd = await promptForMissingSessionCwd(missingSessionCwdIssue, startupSettingsManager);\n\t\t\tif (!selectedCwd) {\n\t\t\t\tprocess.exit(0);\n\t\t\t}\n\t\t\tsessionManager = SessionManager.open(missingSessionCwdIssue.sessionFile!, sessionDir, selectedCwd);\n\t\t} else {\n\t\t\tconsole.error(chalk.red(new MissingSessionCwdError(missingSessionCwdIssue).message));\n\t\t\tprocess.exit(1);\n\t\t}\n\t}\n\tif (parsed.name !== undefined) {\n\t\tconst name = parsed.name.trim();\n\t\tif (!name) {\n\t\t\tconsole.error(chalk.red(\"Error: --name requires a non-empty value\"));\n\t\t\tprocess.exit(1);\n\t\t}\n\t\tsessionManager.appendSessionInfo(name);\n\t}\n\ttime(\"createSessionManager\");\n\n\tconst resolvedExtensionPaths = resolveCliPaths(cwd, parsed.extensions);\n\tconst resolvedSkillPaths = resolveCliPaths(cwd, parsed.skills);\n\tconst resolvedPromptTemplatePaths = resolveCliPaths(cwd, parsed.promptTemplates);\n\tconst resolvedThemePaths = resolveCliPaths(cwd, parsed.themes);\n\tconst authStorage = AuthStorage.create();\n\tconst createRuntime: CreateAgentSessionRuntimeFactory = async ({\n\t\tcwd,\n\t\tagentDir,\n\t\tsessionManager,\n\t\tsessionStartEvent,\n\t}) => {\n\t\tconst services = await createAgentSessionServices({\n\t\t\tcwd,\n\t\t\tagentDir,\n\t\t\tauthStorage,\n\t\t\textensionFlagValues: parsed.unknownFlags,\n\t\t\tresourceLoaderOptions: {\n\t\t\t\tadditionalExtensionPaths: resolvedExtensionPaths,\n\t\t\t\tadditionalSkillPaths: resolvedSkillPaths,\n\t\t\t\tadditionalPromptTemplatePaths: resolvedPromptTemplatePaths,\n\t\t\t\tadditionalThemePaths: resolvedThemePaths,\n\t\t\t\tnoExtensions: parsed.noExtensions,\n\t\t\t\tnoSkills: parsed.noSkills,\n\t\t\t\tnoPromptTemplates: parsed.noPromptTemplates,\n\t\t\t\tnoThemes: parsed.noThemes,\n\t\t\t\tnoContextFiles: parsed.noContextFiles,\n\t\t\t\tsystemPrompt: parsed.systemPrompt,\n\t\t\t\tappendSystemPrompt: parsed.appendSystemPrompt,\n\t\t\t\textensionFactories: options?.extensionFactories,\n\t\t\t},\n\t\t});\n\t\tconst { settingsManager, modelRegistry, resourceLoader } = services;\n\t\t// A discovered package extension that fails to load must not kill the process.\n\t\t// Any \"error\" diagnostic exits 1 below, and headless runs (subagents, review and\n\t\t// QA lanes) go through this same path — so one stale third-party package takes\n\t\t// down every spawned agent while the interactive session looks healthy. Only an\n\t\t// extension the user asked for by hand (-e/--extension) stays fatal.\n\t\tconst diagnostics: AgentSessionRuntimeDiagnostic[] = [\n\t\t\t...services.diagnostics,\n\t\t\t...collectSettingsDiagnostics(settingsManager, \"runtime creation\"),\n\t\t\t...resourceLoader.getExtensions().errors.map(({ path, error }) => ({\n\t\t\t\ttype: isExplicitExtensionDiagnostic(path, resolvedExtensionPaths)\n\t\t\t\t\t? (\"error\" as const)\n\t\t\t\t\t: (\"warning\" as const),\n\t\t\t\tmessage: `Failed to load extension \"${path}\": ${error}`,\n\t\t\t})),\n\t\t];\n\n\t\tconst modelPatterns = parsed.models ?? settingsManager.getEnabledModels();\n\t\tconst scopedModels =\n\t\t\tmodelPatterns && modelPatterns.length > 0 ? await resolveModelScope(modelPatterns, modelRegistry) : [];\n\t\tconst {\n\t\t\toptions: sessionOptions,\n\t\t\tcliThinkingFromModel,\n\t\t\tdiagnostics: sessionOptionDiagnostics,\n\t\t} = buildSessionOptions(\n\t\t\tparsed,\n\t\t\tscopedModels,\n\t\t\tsessionManager.buildSessionContext().messages.length > 0,\n\t\t\tmodelRegistry,\n\t\t\tsettingsManager,\n\t\t);\n\t\tdiagnostics.push(...sessionOptionDiagnostics);\n\n\t\tif (parsed.apiKey) {\n\t\t\tif (!sessionOptions.model) {\n\t\t\t\tdiagnostics.push({\n\t\t\t\t\ttype: \"error\",\n\t\t\t\t\tmessage: \"--api-key requires a model to be specified via --model, --provider/--model, or --models\",\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tauthStorage.setRuntimeApiKey(sessionOptions.model.provider, parsed.apiKey);\n\t\t\t}\n\t\t}\n\n\t\tconst created = await createAgentSessionFromServices({\n\t\t\tservices,\n\t\t\tsessionManager,\n\t\t\tsessionStartEvent,\n\t\t\tmodel: sessionOptions.model,\n\t\t\tmodelContract,\n\t\t\tthinkingLevel: sessionOptions.thinkingLevel,\n\t\t\tscopedModels: sessionOptions.scopedModels,\n\t\t\tmodelPinned: sessionOptions.modelPinned,\n\t\t\ttools: sessionOptions.tools,\n\t\t\texcludeTools: sessionOptions.excludeTools,\n\t\t\tnoTools: sessionOptions.noTools,\n\t\t\tcustomTools: sessionOptions.customTools,\n\t\t});\n\t\tconst cliThinkingOverride = parsed.thinking !== undefined || cliThinkingFromModel;\n\t\tif (created.session.model && cliThinkingOverride) {\n\t\t\tcreated.session.setThinkingLevel(created.session.thinkingLevel);\n\t\t}\n\t\t// Connect configured MCP servers so their tools reach the model in every CLI\n\t\t// mode and on every session switch. No configuration returns at once; a server\n\t\t// that fails to start is a warning, never fatal. Help/list-models never spawn.\n\t\tif (!parsed.help && parsed.listModels === undefined) {\n\t\t\tdiagnostics.push(...mcpAttachDiagnostics(await created.session.attachMcpServers()));\n\t\t}\n\n\t\treturn {\n\t\t\t...created,\n\t\t\tservices,\n\t\t\tdiagnostics,\n\t\t};\n\t};\n\ttime(\"createRuntime\");\n\tconst runtime = await createAgentSessionRuntime(createRuntime, {\n\t\tcwd: sessionManager.getCwd(),\n\t\tagentDir,\n\t\tsessionManager,\n\t});\n\ttime(\"createAgentSessionRuntime\");\n\tconst { services, session, modelFallbackMessage } = runtime;\n\tconst { settingsManager, modelRegistry, resourceLoader } = services;\n\tconfigureHttpDispatcher(settingsManager.getHttpIdleTimeoutMs());\n\n\tif (parsed.help) {\n\t\tconst extensionFlags = resourceLoader\n\t\t\t.getExtensions()\n\t\t\t.extensions.flatMap((extension) => Array.from(extension.flags.values()));\n\t\tprintHelp(extensionFlags);\n\t\tprocess.exit(0);\n\t}\n\n\tif (parsed.listModels !== undefined) {\n\t\tconst searchPattern = typeof parsed.listModels === \"string\" ? parsed.listModels : undefined;\n\t\tawait listModels(modelRegistry, searchPattern);\n\t\tprocess.exit(0);\n\t}\n\n\t// Read piped stdin content (if any) - skip for RPC mode which uses stdin for JSON-RPC.\n\t// Also skip on bare interactive launches so a stuck/non-tty stdin cannot force print mode.\n\tlet stdinContent: string | undefined;\n\tif (appMode !== \"rpc\" && !(appMode === \"interactive\" && !hasPromptIntent(parsed))) {\n\t\tstdinContent = await readPipedStdin();\n\t\tif (stdinContent !== undefined && appMode === \"interactive\") {\n\t\t\tappMode = \"print\";\n\t\t}\n\t}\n\ttime(\"readPipedStdin\");\n\n\tconst { initialMessage, initialImages } = await prepareInitialMessage(\n\t\tparsed,\n\t\tsettingsManager.getImageAutoResize(),\n\t\tstdinContent,\n\t);\n\ttime(\"prepareInitialMessage\");\n\tinitTheme(settingsManager.getTheme(), appMode === \"interactive\");\n\ttime(\"initTheme\");\n\n\t// Show deprecation warnings in interactive mode\n\tif (appMode === \"interactive\" && deprecationWarnings.length > 0) {\n\t\tawait showDeprecationWarnings(deprecationWarnings);\n\t}\n\n\ttime(\"resolveModelScope\");\n\treportDiagnostics(runtime.diagnostics);\n\tif (runtime.diagnostics.some((diagnostic) => diagnostic.type === \"error\")) {\n\t\tprocess.exit(1);\n\t}\n\ttime(\"createAgentSession\");\n\n\tif (appMode !== \"interactive\" && !session.model) {\n\t\tconsole.error(chalk.red(formatNoModelsAvailableMessage()));\n\t\tprocess.exit(1);\n\t}\n\n\tconst startupBenchmark = isTruthyEnvFlag(process.env.OMK_STARTUP_BENCHMARK);\n\tif (startupBenchmark && appMode !== \"interactive\") {\n\t\tconsole.error(chalk.red(\"Error: OMK_STARTUP_BENCHMARK only supports interactive mode\"));\n\t\tprocess.exit(1);\n\t}\n\n\tif (appMode === \"rpc\") {\n\t\tprintTimings();\n\t\tawait runRpcMode(runtime);\n\t} else if (appMode === \"interactive\") {\n\t\tconst interactiveMode = new InteractiveMode(runtime, {\n\t\t\tmigratedProviders,\n\t\t\tmodelFallbackMessage,\n\t\t\tinitialMessage,\n\t\t\tinitialImages,\n\t\t\tinitialMessages: parsed.messages,\n\t\t\tverbose: parsed.verbose,\n\t\t});\n\t\tif (startupBenchmark) {\n\t\t\tawait interactiveMode.init();\n\t\t\ttime(\"interactiveMode.init\");\n\t\t\tprintTimings();\n\t\t\tinteractiveMode.stop();\n\t\t\tstopThemeWatcher();\n\t\t\tif (process.stdout.writableLength > 0) {\n\t\t\t\tawait new Promise<void>((resolve) => process.stdout.once(\"drain\", resolve));\n\t\t\t}\n\t\t\tif (process.stderr.writableLength > 0) {\n\t\t\t\tawait new Promise<void>((resolve) => process.stderr.once(\"drain\", resolve));\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\tprintTimings();\n\t\tawait interactiveMode.run();\n\t} else {\n\t\tprintTimings();\n\t\tconst exitCode = await runPrintMode(runtime, {\n\t\t\tmode: toPrintOutputMode(appMode),\n\t\t\tmessages: parsed.messages,\n\t\t\tinitialMessage,\n\t\t\tinitialImages,\n\t\t});\n\t\tstopThemeWatcher();\n\t\trestoreStdout();\n\t\tif (exitCode !== 0) {\n\t\t\tprocess.exitCode = exitCode;\n\t\t}\n\t\treturn;\n\t}\n}\n"]}
package/dist/main.js CHANGED
@@ -15,17 +15,14 @@ import { processFileArguments } from "./cli/file-processor.js";
15
15
  import { buildInitialMessage } from "./cli/initial-message.js";
16
16
  import { listModels } from "./cli/list-models.js";
17
17
  import { mcpAttachDiagnostics } from "./cli/mcp-attach.js";
18
+ import { loadModelContractOrExit } from "./cli/model-contract.js";
18
19
  import { isExplicitExtensionDiagnostic, resolveCliPaths } from "./cli/resource-paths.js";
19
20
  import { selectSession } from "./cli/session-picker.js";
20
21
  import { handleCodexBarQuotaCommand } from "./codexbar-cli.js";
21
- import { runAdaptOrchDoctorCli } from "./commands/adaptorch-doctor-cli.js";
22
- import { runDoctorProviderCli } from "./commands/doctor-provider-cli.js";
22
+ import { runInitCli } from "./commands/init-cli.js";
23
23
  import { runPackageDoctorCli } from "./commands/package-doctor-cli.js";
24
- import { runResourceDoctorCli } from "./commands/resource-doctor-cli.js";
25
- import { runRouterFeedbackCli } from "./commands/router-feedback-cli.js";
26
- import { runSdkSessionCli } from "./commands/sdk-session-cli.js";
27
- import { runSessionDoctorCli } from "./commands/session-doctor-cli.js";
28
- import { runStatsCli } from "./commands/stats-cli.js";
24
+ import { runProviderSyncCli } from "./commands/provider-sync-cli.js";
25
+ import { runCommand } from "./commands/run-command.js";
29
26
  import { ENV_SESSION_DIR, expandTildePath, getAgentDir, getPackageDir, VERSION } from "./config.js";
30
27
  import { createAgentSessionRuntime } from "./core/agent-session-runtime.js";
31
28
  import { createAgentSessionFromServices, createAgentSessionServices, } from "./core/agent-session-services.js";
@@ -449,6 +446,11 @@ async function promptForMissingSessionCwd(issue, settingsManager) {
449
446
  });
450
447
  }
451
448
  export async function main(args, options) {
449
+ const initialization = runInitCli(args);
450
+ if (initialization.handled) {
451
+ process.exitCode = initialization.exitCode;
452
+ return;
453
+ }
452
454
  resetTimings();
453
455
  const offlineMode = args.includes("--offline") || isTruthyEnvFlag(process.env.OMK_OFFLINE);
454
456
  if (offlineMode) {
@@ -472,21 +474,15 @@ export async function main(args, options) {
472
474
  if (await handleCodexBarQuotaCommand(args)) {
473
475
  return;
474
476
  }
475
- const outcomeCommands = [
476
- runSessionDoctorCli,
477
- runDoctorProviderCli,
478
- runResourceDoctorCli,
479
- runAdaptOrchDoctorCli,
480
- runStatsCli,
481
- runSdkSessionCli,
482
- runRouterFeedbackCli,
483
- ];
484
- for (const runCommand of outcomeCommands) {
485
- const outcome = await runCommand(args);
486
- if (outcome.handled) {
487
- process.exitCode = outcome.exitCode;
488
- return;
489
- }
477
+ const providerSync = await runProviderSyncCli(args);
478
+ if (providerSync.handled) {
479
+ process.exitCode = providerSync.exitCode;
480
+ return;
481
+ }
482
+ const outcome = await runCommand(args);
483
+ if (outcome.handled) {
484
+ process.exitCode = outcome.exitCode;
485
+ return;
490
486
  }
491
487
  const parsed = parseArgs(args);
492
488
  if (parsed.diagnostics.length > 0) {
@@ -537,6 +533,9 @@ export async function main(args, options) {
537
533
  }
538
534
  validateForkFlags(parsed);
539
535
  validateSessionIdFlags(parsed);
536
+ const modelContract = parsed.modelContractFile && !parsed.help
537
+ ? loadModelContractOrExit(resolvePath(parsed.modelContractFile))
538
+ : undefined;
540
539
  // Run migrations (pass cwd for project-local migrations)
541
540
  const { migratedAuthProviders: migratedProviders, deprecationWarnings } = runMigrations(process.cwd());
542
541
  time("runMigrations");
@@ -639,6 +638,7 @@ export async function main(args, options) {
639
638
  sessionManager,
640
639
  sessionStartEvent,
641
640
  model: sessionOptions.model,
641
+ modelContract,
642
642
  thinkingLevel: sessionOptions.thinkingLevel,
643
643
  scopedModels: sessionOptions.scopedModels,
644
644
  modelPinned: sessionOptions.modelPinned,