open-multi-agent-kit 0.90.8 → 0.90.9

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 (306) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +7 -1
  3. package/dist/cli/args.d.ts.map +1 -1
  4. package/dist/cli/args.js +4 -0
  5. package/dist/cli/args.js.map +1 -1
  6. package/dist/commands/doctor-provider-cli.d.ts +33 -0
  7. package/dist/commands/doctor-provider-cli.d.ts.map +1 -0
  8. package/dist/commands/doctor-provider-cli.js +215 -0
  9. package/dist/commands/doctor-provider-cli.js.map +1 -0
  10. package/dist/commands/doctor-provider-transport.d.ts +35 -0
  11. package/dist/commands/doctor-provider-transport.d.ts.map +1 -0
  12. package/dist/commands/doctor-provider-transport.js +185 -0
  13. package/dist/commands/doctor-provider-transport.js.map +1 -0
  14. package/dist/commands/doctor-provider.d.ts +121 -7
  15. package/dist/commands/doctor-provider.d.ts.map +1 -1
  16. package/dist/commands/doctor-provider.js +1295 -102
  17. package/dist/commands/doctor-provider.js.map +1 -1
  18. package/dist/commands/session-doctor-cli.d.ts +43 -0
  19. package/dist/commands/session-doctor-cli.d.ts.map +1 -0
  20. package/dist/commands/session-doctor-cli.js +494 -0
  21. package/dist/commands/session-doctor-cli.js.map +1 -0
  22. package/dist/commands/verify-ci.d.ts +21 -0
  23. package/dist/commands/verify-ci.d.ts.map +1 -0
  24. package/dist/commands/verify-ci.js +66 -0
  25. package/dist/commands/verify-ci.js.map +1 -0
  26. package/dist/core/agent-session-services.d.ts +3 -0
  27. package/dist/core/agent-session-services.d.ts.map +1 -1
  28. package/dist/core/agent-session-services.js +3 -0
  29. package/dist/core/agent-session-services.js.map +1 -1
  30. package/dist/core/agent-session.d.ts +113 -2
  31. package/dist/core/agent-session.d.ts.map +1 -1
  32. package/dist/core/agent-session.js +993 -72
  33. package/dist/core/agent-session.js.map +1 -1
  34. package/dist/core/agent-tool-settings.d.ts +35 -0
  35. package/dist/core/agent-tool-settings.d.ts.map +1 -0
  36. package/dist/core/agent-tool-settings.js +155 -0
  37. package/dist/core/agent-tool-settings.js.map +1 -0
  38. package/dist/core/atomic-session-file.d.ts +14 -0
  39. package/dist/core/atomic-session-file.d.ts.map +1 -0
  40. package/dist/core/atomic-session-file.js +104 -0
  41. package/dist/core/atomic-session-file.js.map +1 -0
  42. package/dist/core/compaction/compaction.d.ts +6 -0
  43. package/dist/core/compaction/compaction.d.ts.map +1 -1
  44. package/dist/core/compaction/compaction.js +12 -1
  45. package/dist/core/compaction/compaction.js.map +1 -1
  46. package/dist/core/compaction/hysteresis.d.ts +27 -0
  47. package/dist/core/compaction/hysteresis.d.ts.map +1 -0
  48. package/dist/core/compaction/hysteresis.js +84 -0
  49. package/dist/core/compaction/hysteresis.js.map +1 -0
  50. package/dist/core/compaction/index.d.ts +2 -0
  51. package/dist/core/compaction/index.d.ts.map +1 -1
  52. package/dist/core/compaction/index.js +2 -0
  53. package/dist/core/compaction/index.js.map +1 -1
  54. package/dist/core/compaction/transaction.d.ts +172 -0
  55. package/dist/core/compaction/transaction.d.ts.map +1 -0
  56. package/dist/core/compaction/transaction.js +824 -0
  57. package/dist/core/compaction/transaction.js.map +1 -0
  58. package/dist/core/context-budget-governor-v2.d.ts +2 -1
  59. package/dist/core/context-budget-governor-v2.d.ts.map +1 -1
  60. package/dist/core/context-budget-governor-v2.js +2 -1
  61. package/dist/core/context-budget-governor-v2.js.map +1 -1
  62. package/dist/core/context-budget-reserved-tokens.d.ts +110 -0
  63. package/dist/core/context-budget-reserved-tokens.d.ts.map +1 -0
  64. package/dist/core/context-budget-reserved-tokens.js +188 -0
  65. package/dist/core/context-budget-reserved-tokens.js.map +1 -0
  66. package/dist/core/context-budget-v2-cache-invalidation.d.ts +133 -0
  67. package/dist/core/context-budget-v2-cache-invalidation.d.ts.map +1 -0
  68. package/dist/core/context-budget-v2-cache-invalidation.js +452 -0
  69. package/dist/core/context-budget-v2-cache-invalidation.js.map +1 -0
  70. package/dist/core/context-budget-v2-cache-keys.d.ts +3 -0
  71. package/dist/core/context-budget-v2-cache-keys.d.ts.map +1 -1
  72. package/dist/core/context-budget-v2-cache-keys.js +6 -0
  73. package/dist/core/context-budget-v2-cache-keys.js.map +1 -1
  74. package/dist/core/context-budget-v2-cache-provider.d.ts +4 -0
  75. package/dist/core/context-budget-v2-cache-provider.d.ts.map +1 -1
  76. package/dist/core/context-budget-v2-cache-provider.js +19 -0
  77. package/dist/core/context-budget-v2-cache-provider.js.map +1 -1
  78. package/dist/core/context-budget-v2-plan-cache-keys.d.ts.map +1 -1
  79. package/dist/core/context-budget-v2-plan-cache-keys.js +1 -0
  80. package/dist/core/context-budget-v2-plan-cache-keys.js.map +1 -1
  81. package/dist/core/context-budget-v2-planner.d.ts.map +1 -1
  82. package/dist/core/context-budget-v2-planner.js +1 -0
  83. package/dist/core/context-budget-v2-planner.js.map +1 -1
  84. package/dist/core/context-budget-v2-types.d.ts +4 -0
  85. package/dist/core/context-budget-v2-types.d.ts.map +1 -1
  86. package/dist/core/context-budget-v2-types.js.map +1 -1
  87. package/dist/core/durable-file-directory.d.ts +4 -0
  88. package/dist/core/durable-file-directory.d.ts.map +1 -0
  89. package/dist/core/durable-file-directory.js +76 -0
  90. package/dist/core/durable-file-directory.js.map +1 -0
  91. package/dist/core/durable-file-identity.d.ts +26 -0
  92. package/dist/core/durable-file-identity.d.ts.map +1 -0
  93. package/dist/core/durable-file-identity.js +118 -0
  94. package/dist/core/durable-file-identity.js.map +1 -0
  95. package/dist/core/durable-file-io.d.ts +29 -0
  96. package/dist/core/durable-file-io.d.ts.map +1 -0
  97. package/dist/core/durable-file-io.js +179 -0
  98. package/dist/core/durable-file-io.js.map +1 -0
  99. package/dist/core/durable-file-lock-cleanup.d.ts +12 -0
  100. package/dist/core/durable-file-lock-cleanup.d.ts.map +1 -0
  101. package/dist/core/durable-file-lock-cleanup.js +39 -0
  102. package/dist/core/durable-file-lock-cleanup.js.map +1 -0
  103. package/dist/core/durable-file-lock-owner.d.ts +18 -0
  104. package/dist/core/durable-file-lock-owner.d.ts.map +1 -0
  105. package/dist/core/durable-file-lock-owner.js +78 -0
  106. package/dist/core/durable-file-lock-owner.js.map +1 -0
  107. package/dist/core/durable-file-lock-storage.d.ts +35 -0
  108. package/dist/core/durable-file-lock-storage.d.ts.map +1 -0
  109. package/dist/core/durable-file-lock-storage.js +263 -0
  110. package/dist/core/durable-file-lock-storage.js.map +1 -0
  111. package/dist/core/durable-file-mode.d.ts +8 -0
  112. package/dist/core/durable-file-mode.d.ts.map +1 -0
  113. package/dist/core/durable-file-mode.js +41 -0
  114. package/dist/core/durable-file-mode.js.map +1 -0
  115. package/dist/core/extensions/loader.d.ts +12 -0
  116. package/dist/core/extensions/loader.d.ts.map +1 -1
  117. package/dist/core/extensions/loader.js +46 -37
  118. package/dist/core/extensions/loader.js.map +1 -1
  119. package/dist/core/index.d.ts +6 -2
  120. package/dist/core/index.d.ts.map +1 -1
  121. package/dist/core/index.js +5 -0
  122. package/dist/core/index.js.map +1 -1
  123. package/dist/core/model-resolver.d.ts.map +1 -1
  124. package/dist/core/model-resolver.js +1 -1
  125. package/dist/core/model-resolver.js.map +1 -1
  126. package/dist/core/redaction.d.ts +8 -0
  127. package/dist/core/redaction.d.ts.map +1 -0
  128. package/dist/core/redaction.js +31 -0
  129. package/dist/core/redaction.js.map +1 -0
  130. package/dist/core/resource-loader.d.ts.map +1 -1
  131. package/dist/core/resource-loader.js +36 -0
  132. package/dist/core/resource-loader.js.map +1 -1
  133. package/dist/core/run-journal-store.d.ts +53 -0
  134. package/dist/core/run-journal-store.d.ts.map +1 -0
  135. package/dist/core/run-journal-store.js +278 -0
  136. package/dist/core/run-journal-store.js.map +1 -0
  137. package/dist/core/run-journal.d.ts +172 -0
  138. package/dist/core/run-journal.d.ts.map +1 -0
  139. package/dist/core/run-journal.js +1053 -0
  140. package/dist/core/run-journal.js.map +1 -0
  141. package/dist/core/sdk.d.ts +7 -0
  142. package/dist/core/sdk.d.ts.map +1 -1
  143. package/dist/core/sdk.js +94 -3
  144. package/dist/core/sdk.js.map +1 -1
  145. package/dist/core/session-doctor-plan.d.ts +128 -0
  146. package/dist/core/session-doctor-plan.d.ts.map +1 -0
  147. package/dist/core/session-doctor-plan.js +833 -0
  148. package/dist/core/session-doctor-plan.js.map +1 -0
  149. package/dist/core/session-file-compaction.d.ts +6 -0
  150. package/dist/core/session-file-compaction.d.ts.map +1 -0
  151. package/dist/core/session-file-compaction.js +169 -0
  152. package/dist/core/session-file-compaction.js.map +1 -0
  153. package/dist/core/session-file-head.d.ts +10 -0
  154. package/dist/core/session-file-head.d.ts.map +1 -0
  155. package/dist/core/session-file-head.js +78 -0
  156. package/dist/core/session-file-head.js.map +1 -0
  157. package/dist/core/session-file-persistence.d.ts +30 -0
  158. package/dist/core/session-file-persistence.d.ts.map +1 -0
  159. package/dist/core/session-file-persistence.js +106 -0
  160. package/dist/core/session-file-persistence.js.map +1 -0
  161. package/dist/core/session-integrity.d.ts +43 -0
  162. package/dist/core/session-integrity.d.ts.map +1 -0
  163. package/dist/core/session-integrity.js +420 -0
  164. package/dist/core/session-integrity.js.map +1 -0
  165. package/dist/core/session-manager.d.ts +24 -4
  166. package/dist/core/session-manager.d.ts.map +1 -1
  167. package/dist/core/session-manager.js +242 -125
  168. package/dist/core/session-manager.js.map +1 -1
  169. package/dist/core/session-owner-lease.d.ts +22 -0
  170. package/dist/core/session-owner-lease.d.ts.map +1 -0
  171. package/dist/core/session-owner-lease.js +176 -0
  172. package/dist/core/session-owner-lease.js.map +1 -0
  173. package/dist/core/session-path-policy.d.ts +132 -0
  174. package/dist/core/session-path-policy.d.ts.map +1 -0
  175. package/dist/core/session-path-policy.js +780 -0
  176. package/dist/core/session-path-policy.js.map +1 -0
  177. package/dist/core/session-repair-plan.d.ts +49 -0
  178. package/dist/core/session-repair-plan.d.ts.map +1 -0
  179. package/dist/core/session-repair-plan.js +202 -0
  180. package/dist/core/session-repair-plan.js.map +1 -0
  181. package/dist/core/session-termination.d.ts +100 -0
  182. package/dist/core/session-termination.d.ts.map +1 -0
  183. package/dist/core/session-termination.js +403 -0
  184. package/dist/core/session-termination.js.map +1 -0
  185. package/dist/core/settings-manager.d.ts +22 -0
  186. package/dist/core/settings-manager.d.ts.map +1 -1
  187. package/dist/core/settings-manager.js +37 -5
  188. package/dist/core/settings-manager.js.map +1 -1
  189. package/dist/core/system-prompt.d.ts.map +1 -1
  190. package/dist/core/system-prompt.js +1 -1
  191. package/dist/core/system-prompt.js.map +1 -1
  192. package/dist/core/verified-bash-adapter.d.ts +36 -0
  193. package/dist/core/verified-bash-adapter.d.ts.map +1 -0
  194. package/dist/core/verified-bash-adapter.js +90 -0
  195. package/dist/core/verified-bash-adapter.js.map +1 -0
  196. package/dist/guardrails/command-redaction.d.ts +32 -0
  197. package/dist/guardrails/command-redaction.d.ts.map +1 -0
  198. package/dist/guardrails/command-redaction.js +776 -0
  199. package/dist/guardrails/command-redaction.js.map +1 -0
  200. package/dist/guardrails/evidence-attestation.d.ts +31 -0
  201. package/dist/guardrails/evidence-attestation.d.ts.map +1 -0
  202. package/dist/guardrails/evidence-attestation.js +178 -0
  203. package/dist/guardrails/evidence-attestation.js.map +1 -0
  204. package/dist/guardrails/evidence-receipt-store.d.ts +33 -0
  205. package/dist/guardrails/evidence-receipt-store.d.ts.map +1 -0
  206. package/dist/guardrails/evidence-receipt-store.js +446 -0
  207. package/dist/guardrails/evidence-receipt-store.js.map +1 -0
  208. package/dist/guardrails/evidence-receipt.d.ts +58 -0
  209. package/dist/guardrails/evidence-receipt.d.ts.map +1 -0
  210. package/dist/guardrails/evidence-receipt.js +389 -0
  211. package/dist/guardrails/evidence-receipt.js.map +1 -0
  212. package/dist/guardrails/evidence-system.d.ts +39 -15
  213. package/dist/guardrails/evidence-system.d.ts.map +1 -1
  214. package/dist/guardrails/evidence-system.js +255 -97
  215. package/dist/guardrails/evidence-system.js.map +1 -1
  216. package/dist/guardrails/replay-ledger-io.d.ts +6 -0
  217. package/dist/guardrails/replay-ledger-io.d.ts.map +1 -0
  218. package/dist/guardrails/replay-ledger-io.js +42 -0
  219. package/dist/guardrails/replay-ledger-io.js.map +1 -0
  220. package/dist/guardrails/replay-ledger-lock-owner.d.ts +32 -0
  221. package/dist/guardrails/replay-ledger-lock-owner.d.ts.map +1 -0
  222. package/dist/guardrails/replay-ledger-lock-owner.js +138 -0
  223. package/dist/guardrails/replay-ledger-lock-owner.js.map +1 -0
  224. package/dist/guardrails/replay-ledger-lock.d.ts +24 -0
  225. package/dist/guardrails/replay-ledger-lock.d.ts.map +1 -0
  226. package/dist/guardrails/replay-ledger-lock.js +135 -0
  227. package/dist/guardrails/replay-ledger-lock.js.map +1 -0
  228. package/dist/guardrails/replay-ledger-mutation-gate.d.ts +24 -0
  229. package/dist/guardrails/replay-ledger-mutation-gate.d.ts.map +1 -0
  230. package/dist/guardrails/replay-ledger-mutation-gate.js +205 -0
  231. package/dist/guardrails/replay-ledger-mutation-gate.js.map +1 -0
  232. package/dist/guardrails/replay-ledger-quarantine.d.ts +2 -0
  233. package/dist/guardrails/replay-ledger-quarantine.d.ts.map +1 -0
  234. package/dist/guardrails/replay-ledger-quarantine.js +19 -0
  235. package/dist/guardrails/replay-ledger-quarantine.js.map +1 -0
  236. package/dist/guardrails/replay-ledger-store.d.ts +32 -0
  237. package/dist/guardrails/replay-ledger-store.d.ts.map +1 -0
  238. package/dist/guardrails/replay-ledger-store.js +211 -0
  239. package/dist/guardrails/replay-ledger-store.js.map +1 -0
  240. package/dist/guardrails/shell-command-name-glob.d.ts +3 -0
  241. package/dist/guardrails/shell-command-name-glob.d.ts.map +1 -0
  242. package/dist/guardrails/shell-command-name-glob.js +233 -0
  243. package/dist/guardrails/shell-command-name-glob.js.map +1 -0
  244. package/dist/guardrails/shell-command-option.d.ts +7 -0
  245. package/dist/guardrails/shell-command-option.d.ts.map +1 -0
  246. package/dist/guardrails/shell-command-option.js +24 -0
  247. package/dist/guardrails/shell-command-option.js.map +1 -0
  248. package/dist/guardrails/shell-command-tokenizer.d.ts +29 -0
  249. package/dist/guardrails/shell-command-tokenizer.d.ts.map +1 -0
  250. package/dist/guardrails/shell-command-tokenizer.js +145 -0
  251. package/dist/guardrails/shell-command-tokenizer.js.map +1 -0
  252. package/dist/guardrails/shell-command-wrapper.d.ts +18 -0
  253. package/dist/guardrails/shell-command-wrapper.d.ts.map +1 -0
  254. package/dist/guardrails/shell-command-wrapper.js +42 -0
  255. package/dist/guardrails/shell-command-wrapper.js.map +1 -0
  256. package/dist/guardrails/verified-executor.d.ts +65 -0
  257. package/dist/guardrails/verified-executor.d.ts.map +1 -0
  258. package/dist/guardrails/verified-executor.js +171 -0
  259. package/dist/guardrails/verified-executor.js.map +1 -0
  260. package/dist/guardrails/workspace-fingerprint.d.ts +23 -0
  261. package/dist/guardrails/workspace-fingerprint.d.ts.map +1 -0
  262. package/dist/guardrails/workspace-fingerprint.js +634 -0
  263. package/dist/guardrails/workspace-fingerprint.js.map +1 -0
  264. package/dist/index.d.ts +15 -3
  265. package/dist/index.d.ts.map +1 -1
  266. package/dist/index.js +13 -1
  267. package/dist/index.js.map +1 -1
  268. package/dist/main.d.ts.map +1 -1
  269. package/dist/main.js +12 -0
  270. package/dist/main.js.map +1 -1
  271. package/dist/modes/interactive/interactive-mode.d.ts +3 -0
  272. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  273. package/dist/modes/interactive/interactive-mode.js +59 -9
  274. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  275. package/dist/modes/print-mode.d.ts.map +1 -1
  276. package/dist/modes/print-mode.js +43 -2
  277. package/dist/modes/print-mode.js.map +1 -1
  278. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  279. package/dist/modes/rpc/rpc-mode.js +23 -5
  280. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  281. package/dist/modes/rpc/rpc-types.d.ts +3 -0
  282. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  283. package/dist/modes/rpc/rpc-types.js.map +1 -1
  284. package/dist/types/evidence.d.ts +211 -1
  285. package/dist/types/evidence.d.ts.map +1 -1
  286. package/dist/types/evidence.js.map +1 -1
  287. package/dist/verify-ci.d.ts +3 -0
  288. package/dist/verify-ci.d.ts.map +1 -0
  289. package/dist/verify-ci.js +30 -0
  290. package/dist/verify-ci.js.map +1 -0
  291. package/docs/compaction.md +38 -4
  292. package/docs/extensions.md +2 -0
  293. package/docs/sdk.md +238 -1
  294. package/docs/settings.md +50 -2
  295. package/docs/usage.md +38 -0
  296. package/examples/extensions/custom-provider-anthropic/package-lock.json +5 -5
  297. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  298. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  299. package/examples/extensions/gondolin/package-lock.json +2 -2
  300. package/examples/extensions/gondolin/package.json +1 -1
  301. package/examples/extensions/sandbox/package-lock.json +2 -2
  302. package/examples/extensions/sandbox/package.json +1 -1
  303. package/examples/extensions/with-deps/package-lock.json +4 -4
  304. package/examples/extensions/with-deps/package.json +1 -1
  305. package/npm-shrinkwrap.json +12 -12
  306. package/package.json +4 -4
@@ -0,0 +1,494 @@
1
+ import { createHash, randomUUID } from "node:crypto";
2
+ import { closeSync, existsSync, fstatSync, fsyncSync, lstatSync, openSync, readFileSync, realpathSync, renameSync, statSync, } from "node:fs";
3
+ import { dirname, resolve } from "node:path";
4
+ import lockfile from "proper-lockfile";
5
+ import { atomicRewriteFileSync } from "../core/atomic-session-file.js";
6
+ import { validateCompactionEnvelope } from "../core/compaction/transaction.js";
7
+ import { GENESIS_HASH, inspectRunJournal, RUN_JOURNAL_SCHEMA_VERSION, serializeRunJournalLine, serializeRunJournalMaterial, } from "../core/run-journal.js";
8
+ import { RunJournalStore, writeQuarantineBytesDurably } from "../core/run-journal-store.js";
9
+ import { planSessionDoctor, } from "../core/session-doctor-plan.js";
10
+ import { inspectSessionIntegrity } from "../core/session-integrity.js";
11
+ import { SessionManager } from "../core/session-manager.js";
12
+ import { decideSessionPathAccess, } from "../core/session-path-policy.js";
13
+ import { classifySessionTermination } from "../core/session-termination.js";
14
+ import { validateEvidenceReceipt } from "../guardrails/evidence-receipt.js";
15
+ import { ReplayLedgerManager } from "../guardrails/evidence-system.js";
16
+ import { resolvePath } from "../utils/paths.js";
17
+ const USAGE = "Usage: omk session doctor [--session <path|id>] [--repair [--dry-run]]";
18
+ function parseArgs(args) {
19
+ if (args[0] !== "session" || args[1] !== "doctor")
20
+ return { kind: "absent" };
21
+ let session;
22
+ let repair = false;
23
+ let dryRun = false;
24
+ for (let index = 2; index < args.length; index += 1) {
25
+ const arg = args[index];
26
+ if (arg === "--help" || arg === "-h")
27
+ return { kind: "help" };
28
+ if (arg === "--repair") {
29
+ repair = true;
30
+ continue;
31
+ }
32
+ if (arg === "--dry-run") {
33
+ dryRun = true;
34
+ continue;
35
+ }
36
+ if (arg === "--session") {
37
+ const value = args[index + 1];
38
+ if (!value || value.startsWith("--"))
39
+ return { kind: "error", message: "--session requires a value" };
40
+ session = value;
41
+ index += 1;
42
+ continue;
43
+ }
44
+ return { kind: "error", message: "unexpected session doctor argument" };
45
+ }
46
+ if (dryRun && !repair)
47
+ return { kind: "error", message: "--dry-run requires --repair" };
48
+ return { kind: "ok", session, mode: repair ? (dryRun ? "repair_dry_run" : "repair") : "inspect" };
49
+ }
50
+ function sha256(bytes) {
51
+ return createHash("sha256").update(bytes).digest("hex");
52
+ }
53
+ async function resolveSession(argument, cwd, sessionDir) {
54
+ if (argument && (argument.includes("/") || argument.includes("\\") || argument.endsWith(".jsonl"))) {
55
+ const path = resolvePath(argument, cwd);
56
+ return existsSync(path) ? path : null;
57
+ }
58
+ const local = await SessionManager.list(cwd, sessionDir);
59
+ if (argument) {
60
+ const localMatches = local.filter((session) => session.id === argument || session.id.startsWith(argument));
61
+ if (localMatches.length === 1)
62
+ return localMatches[0].path;
63
+ const all = await SessionManager.listAll(sessionDir);
64
+ const globalMatches = all.filter((session) => session.id === argument || session.id.startsWith(argument));
65
+ return globalMatches.length === 1 ? globalMatches[0].path : null;
66
+ }
67
+ return local[0]?.path ?? null;
68
+ }
69
+ function pathStat(stat) {
70
+ return {
71
+ dev: String(stat.dev),
72
+ ino: String(stat.ino),
73
+ nlink: stat.nlink,
74
+ size: stat.size,
75
+ mtime: Math.max(0, Math.trunc(stat.mtimeMs)),
76
+ regular: stat.isFile(),
77
+ owner: String(stat.uid),
78
+ };
79
+ }
80
+ function pathObservation(target) {
81
+ const root = dirname(target);
82
+ const rootReal = realpathSync(root);
83
+ const targetReal = realpathSync(target);
84
+ const rootLstat = lstatSync(root);
85
+ const targetLstat = lstatSync(target);
86
+ const chain = [
87
+ { lexical: root, realpath: rootReal, linkKind: rootLstat.isSymbolicLink() ? "symlink" : "none" },
88
+ { lexical: target, realpath: targetReal, linkKind: targetLstat.isSymbolicLink() ? "symlink" : "none" },
89
+ ];
90
+ const before = statSync(target);
91
+ const fd = openSync(target, "r");
92
+ let opened;
93
+ try {
94
+ opened = fstatSync(fd);
95
+ }
96
+ finally {
97
+ closeSync(fd);
98
+ }
99
+ const after = statSync(target);
100
+ const owner = typeof process.getuid === "function" ? process.getuid() : before.uid;
101
+ const lockExists = existsSync(`${target}.lock`);
102
+ return {
103
+ platform: process.platform === "win32" ? "win32" : "posix",
104
+ root,
105
+ target,
106
+ identity: { owner: String(owner) },
107
+ evidence: {
108
+ schemaVersion: 1,
109
+ platform: process.platform === "win32" ? "win32" : "posix",
110
+ trustedRootLexical: root,
111
+ trustedRootRealpath: rootReal,
112
+ target: { lexical: target, realpath: targetReal },
113
+ chain,
114
+ statBefore: pathStat(before),
115
+ statAfter: pathStat(after),
116
+ opened: { dev: String(opened.dev), ino: String(opened.ino) },
117
+ },
118
+ lock: lockExists
119
+ ? { state: "unknown", sameHost: false, pidDefinitelyAbsent: false, holderPid: null }
120
+ : { state: "absent", sameHost: true, pidDefinitelyAbsent: true, holderPid: null },
121
+ };
122
+ }
123
+ function normalizedChecks(report, sessionPath) {
124
+ const checks = [];
125
+ const compactions = report.entries.filter((entry) => entry.type === "compaction");
126
+ let compactionStatus = "ok";
127
+ for (const entry of compactions) {
128
+ const details = entry.details;
129
+ if (typeof details !== "object" || details === null || !("compactionEnvelope" in details)) {
130
+ compactionStatus = "missing";
131
+ break;
132
+ }
133
+ try {
134
+ const envelope = validateCompactionEnvelope(details.compactionEnvelope);
135
+ const summarySha256 = createHash("sha256").update(entry.summary, "utf8").digest("hex");
136
+ if (envelope.source.sessionId !== report.header?.id ||
137
+ envelope.summary !== entry.summary ||
138
+ envelope.summarySha256 !== summarySha256 ||
139
+ envelope.source.activeLeafId !== entry.parentId) {
140
+ compactionStatus = "invalid";
141
+ break;
142
+ }
143
+ }
144
+ catch {
145
+ compactionStatus = "invalid";
146
+ break;
147
+ }
148
+ }
149
+ checks.push({ artifact: "compaction_envelope", id: "compaction", status: compactionStatus });
150
+ const replayPath = `${sessionPath}.replay.jsonl`;
151
+ let replayStatus = "ok";
152
+ if (existsSync(replayPath)) {
153
+ try {
154
+ const ledger = new ReplayLedgerManager(report.header?.id ?? "unknown", replayPath);
155
+ if (ledger.getEvents().some((event) => event.goalId !== report.header?.id))
156
+ replayStatus = "invalid";
157
+ }
158
+ catch {
159
+ replayStatus = "invalid";
160
+ }
161
+ }
162
+ checks.push({ artifact: "evidence_link", id: "replay-ledger", status: replayStatus });
163
+ let receiptStatus = "ok";
164
+ for (const entry of report.entries) {
165
+ if (entry.type !== "custom" || entry.customType !== "evidence_receipt")
166
+ continue;
167
+ try {
168
+ validateEvidenceReceipt(entry.data);
169
+ }
170
+ catch {
171
+ receiptStatus = "invalid";
172
+ break;
173
+ }
174
+ }
175
+ checks.push({ artifact: "evidence_link", id: "evidence-receipts", status: receiptStatus });
176
+ let workspaceStatus = "invalid";
177
+ try {
178
+ workspaceStatus = report.header && statSync(report.header.cwd).isDirectory() ? "ok" : "missing";
179
+ }
180
+ catch {
181
+ workspaceStatus = "missing";
182
+ }
183
+ checks.push({ artifact: "workspace", id: "workspace", status: workspaceStatus });
184
+ const hasProviderModel = report.entries.some((entry) => entry.type === "model_change");
185
+ checks.push({
186
+ artifact: "provider_model",
187
+ id: "active-provider-model",
188
+ status: hasProviderModel ? "ok" : "missing",
189
+ });
190
+ return Object.freeze(checks);
191
+ }
192
+ function makeRecoveryRecord(report, sessionId, timestamp) {
193
+ if (report.openRunId === null)
194
+ return undefined;
195
+ const last = report.records.at(-1);
196
+ const termination = classifySessionTermination({
197
+ sessionId,
198
+ runId: report.openRunId,
199
+ timestamp,
200
+ source: "inferred_on_resume",
201
+ message: "Previous process exited without closing the run; recovered by session doctor.",
202
+ cause: { area: "process", code: "crash" },
203
+ sideEffects: "possible",
204
+ });
205
+ const material = {
206
+ schemaVersion: RUN_JOURNAL_SCHEMA_VERSION,
207
+ seq: (last?.seq ?? -1) + 1,
208
+ event: "run_recovered",
209
+ runId: report.openRunId,
210
+ sessionId,
211
+ sessionRevision: last?.sessionRevision ?? 0,
212
+ timestamp,
213
+ prevHash: last?.hash ?? GENESIS_HASH,
214
+ termination,
215
+ };
216
+ return Object.freeze({
217
+ ...material,
218
+ hash: RunJournalStore.sha256(new TextEncoder().encode(serializeRunJournalMaterial(material))),
219
+ });
220
+ }
221
+ function hardSessionDamage(report) {
222
+ return report.findings.some((finding) => finding.reason !== "trailing_fragment" && finding.reason !== "transcript_missing_result");
223
+ }
224
+ function hardJournalDamage(report) {
225
+ return (report?.findings.some((finding) => finding.code !== "trailing_fragment" && finding.code !== "run_unclosed") ??
226
+ false);
227
+ }
228
+ function parsePrefixEntries(bytes) {
229
+ const text = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
230
+ return text
231
+ .split("\n")
232
+ .filter((line) => line.length > 0)
233
+ .map((line) => JSON.parse(line));
234
+ }
235
+ function applySessionActions(sessionPath, repairId, report, actions, preconditionSha256, now) {
236
+ const sessionActions = actions.filter((action) => action.kind === "quarantine_session_trailing_fragment" || action.kind === "append_synthetic_tool_result");
237
+ if (sessionActions.length === 0)
238
+ return 0;
239
+ const release = lockfile.lockSync(sessionPath, { realpath: false });
240
+ try {
241
+ const current = new Uint8Array(readFileSync(sessionPath));
242
+ if (sha256(current) !== preconditionSha256)
243
+ throw new Error("precondition_changed");
244
+ const prefix = current.subarray(0, report.completePrefix.byteCount);
245
+ if (report.trailingFragment) {
246
+ writeQuarantineBytesDurably(`${sessionPath}.quarantine-${repairId}`, current.subarray(prefix.byteLength));
247
+ }
248
+ const records = parsePrefixEntries(prefix);
249
+ let parentId = report.activeLeafId;
250
+ for (const action of sessionActions) {
251
+ if (action.kind !== "append_synthetic_tool_result")
252
+ continue;
253
+ let id = `doctor-${repairId.slice(0, 20)}-${action.sequence}`;
254
+ while (records.some((record) => record.id === id))
255
+ id = `${id}-x`;
256
+ records.push({
257
+ type: "message",
258
+ id,
259
+ parentId,
260
+ timestamp: new Date(now.getTime() + action.sequence).toISOString(),
261
+ message: action.message,
262
+ });
263
+ parentId = id;
264
+ }
265
+ atomicRewriteFileSync(sessionPath, `${records.map((record) => JSON.stringify(record)).join("\n")}\n`);
266
+ return sessionActions.length;
267
+ }
268
+ finally {
269
+ release();
270
+ }
271
+ }
272
+ function applyJournalActions(journalPath, repairId, report, actions, preconditionSha256) {
273
+ const journalActions = actions.filter((action) => action.kind === "quarantine_journal_trailing_fragment" || action.kind === "recover_run");
274
+ if (journalActions.length === 0)
275
+ return 0;
276
+ const release = lockfile.lockSync(journalPath, { realpath: false });
277
+ try {
278
+ const current = new Uint8Array(readFileSync(journalPath));
279
+ if (sha256(current) !== preconditionSha256)
280
+ throw new Error("precondition_changed");
281
+ const prefix = current.subarray(0, report.completePrefix.byteCount);
282
+ if (report.trailingByteCount > 0) {
283
+ writeQuarantineBytesDurably(`${journalPath}.quarantine-${repairId}`, current.subarray(prefix.byteLength));
284
+ }
285
+ const recovery = journalActions.find((action) => action.kind === "recover_run");
286
+ const suffix = recovery
287
+ ? new TextEncoder().encode(`${serializeRunJournalLine(recovery.terminalRecord)}\n`)
288
+ : null;
289
+ const output = suffix ? Buffer.concat([Buffer.from(prefix), Buffer.from(suffix)]) : prefix;
290
+ atomicRewriteFileSync(journalPath, output);
291
+ return journalActions.length;
292
+ }
293
+ finally {
294
+ release();
295
+ }
296
+ }
297
+ function applyCompactionActions(sidecarPath, repairId, actions, preconditionSha256) {
298
+ const abandon = actions.find((action) => action.kind === "abandon_stale_compaction");
299
+ if (!abandon)
300
+ return 0;
301
+ const release = lockfile.lockSync(sidecarPath, { realpath: false });
302
+ try {
303
+ if (sha256(readFileSync(sidecarPath)) !== preconditionSha256)
304
+ throw new Error("precondition_changed");
305
+ renameSync(sidecarPath, `${sidecarPath}.abandoned-${repairId}`);
306
+ if (process.platform !== "win32") {
307
+ const dirFd = openSync(dirname(sidecarPath), "r");
308
+ try {
309
+ fsyncSync(dirFd);
310
+ }
311
+ finally {
312
+ closeSync(dirFd);
313
+ }
314
+ }
315
+ return 1;
316
+ }
317
+ finally {
318
+ release();
319
+ }
320
+ }
321
+ function refusedResult(base, errorCode) {
322
+ return {
323
+ ...base,
324
+ status: "refused",
325
+ exitCode: 2,
326
+ appliedActions: 0,
327
+ ...(errorCode ? { errorCode } : {}),
328
+ };
329
+ }
330
+ export async function runSessionDoctorCli(args, overrides = {}) {
331
+ const parsed = parseArgs(args);
332
+ if (parsed.kind === "absent")
333
+ return { handled: false, exitCode: 0 };
334
+ const writeLine = overrides.writeLine ?? ((line) => console.log(line));
335
+ if (parsed.kind === "help") {
336
+ writeLine(USAGE);
337
+ return { handled: true, exitCode: 0 };
338
+ }
339
+ if (parsed.kind === "error") {
340
+ writeLine(JSON.stringify({ status: "refused", error: parsed.message, usage: USAGE }));
341
+ return { handled: true, exitCode: 2 };
342
+ }
343
+ const cwd = resolve(overrides.cwd ?? process.cwd());
344
+ if (parsed.session === undefined) {
345
+ const sessions = await SessionManager.listAll(overrides.sessionDir);
346
+ const paths = [...new Set(sessions.map((session) => session.path))];
347
+ const nestedArgs = ["session", "doctor"];
348
+ if (parsed.mode !== "inspect")
349
+ nestedArgs.push("--repair");
350
+ if (parsed.mode === "repair_dry_run")
351
+ nestedArgs.push("--dry-run");
352
+ const results = [];
353
+ let exitCode = 0;
354
+ for (const path of paths) {
355
+ const outcome = await runSessionDoctorCli([...nestedArgs, "--session", path], {
356
+ ...overrides,
357
+ writeLine: () => { },
358
+ });
359
+ exitCode = Math.max(exitCode, outcome.exitCode);
360
+ if (outcome.result)
361
+ results.push(outcome.result);
362
+ }
363
+ const batch = {
364
+ schemaVersion: 1,
365
+ command: "session_doctor",
366
+ mode: parsed.mode,
367
+ scope: "all",
368
+ status: exitCode === 2 ? "refused" : exitCode === 1 ? "issues" : "healthy",
369
+ exitCode,
370
+ sessionCount: paths.length,
371
+ appliedActions: results.reduce((total, result) => total + result.appliedActions, 0),
372
+ sessions: results,
373
+ };
374
+ writeLine(JSON.stringify(batch, null, 2));
375
+ return { handled: true, exitCode };
376
+ }
377
+ const sessionPath = await resolveSession(parsed.session, cwd, overrides.sessionDir);
378
+ if (!sessionPath) {
379
+ writeLine(JSON.stringify({ status: "refused", error: "session_not_found", usage: USAGE }));
380
+ return { handled: true, exitCode: 2 };
381
+ }
382
+ const now = overrides.now?.() ?? new Date();
383
+ const repairId = randomUUID();
384
+ const sessionBytes = new Uint8Array(readFileSync(sessionPath));
385
+ const preconditionSha256 = sha256(sessionBytes);
386
+ const report = inspectSessionIntegrity(sessionBytes);
387
+ const sessionId = report.header?.id ?? "unknown-session";
388
+ const checks = normalizedChecks(report, sessionPath);
389
+ const compactionPath = `${sessionPath}.compaction-transaction.json`;
390
+ const compactionBytes = existsSync(compactionPath) ? new Uint8Array(readFileSync(compactionPath)) : null;
391
+ let compaction;
392
+ let compactionInvalid = false;
393
+ if (compactionBytes) {
394
+ try {
395
+ compaction = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(compactionBytes));
396
+ }
397
+ catch {
398
+ compactionInvalid = true;
399
+ }
400
+ }
401
+ const compactionPathAuthorized = compactionBytes === null ||
402
+ decideSessionPathAccess({
403
+ ...pathObservation(compactionPath),
404
+ intent: parsed.mode === "inspect" ? "inspect_content" : parsed.mode === "repair" ? "repair" : "repair_dry_run",
405
+ }).status === "authorized";
406
+ const journalPath = `${sessionPath}.runjournal`;
407
+ const journalBytes = existsSync(journalPath) ? new Uint8Array(readFileSync(journalPath)) : null;
408
+ const journalReport = journalBytes ? inspectRunJournal(journalBytes, RunJournalStore.sha256) : null;
409
+ const terminalRecord = journalReport ? makeRecoveryRecord(journalReport, sessionId, now.toISOString()) : undefined;
410
+ const plan = planSessionDoctor({
411
+ mode: parsed.mode,
412
+ sessionId,
413
+ repairId,
414
+ timestamp: now.getTime(),
415
+ report,
416
+ ...(compaction ? { compaction } : {}),
417
+ ...(journalBytes
418
+ ? {
419
+ journal: {
420
+ bytes: journalBytes,
421
+ hashFn: RunJournalStore.sha256,
422
+ ...(terminalRecord ? { terminalRecord } : {}),
423
+ },
424
+ }
425
+ : {}),
426
+ paths: {
427
+ session: pathObservation(sessionPath),
428
+ ...(journalBytes ? { journal: pathObservation(journalPath) } : {}),
429
+ },
430
+ normalizedChecks: checks,
431
+ });
432
+ const base = {
433
+ schemaVersion: 1,
434
+ command: "session_doctor",
435
+ mode: parsed.mode,
436
+ sessionId,
437
+ sessionPath,
438
+ repairId,
439
+ findings: plan.findings,
440
+ actions: plan.actions,
441
+ normalizedChecks: checks,
442
+ preconditionSha256,
443
+ };
444
+ if (hardSessionDamage(report) ||
445
+ hardJournalDamage(journalReport) ||
446
+ compactionInvalid ||
447
+ !compactionPathAuthorized ||
448
+ plan.status === "refused") {
449
+ const result = refusedResult(base);
450
+ writeLine(JSON.stringify(result, null, 2));
451
+ return { handled: true, exitCode: result.exitCode, result };
452
+ }
453
+ if (parsed.mode !== "repair") {
454
+ const result = {
455
+ ...base,
456
+ status: plan.status,
457
+ exitCode: plan.exitCode,
458
+ appliedActions: 0,
459
+ };
460
+ writeLine(JSON.stringify(result, null, 2));
461
+ return { handled: true, exitCode: result.exitCode, result };
462
+ }
463
+ overrides.beforeExecute?.();
464
+ let appliedActions = 0;
465
+ try {
466
+ appliedActions += applySessionActions(sessionPath, repairId, report, plan.actions, preconditionSha256, now);
467
+ if (journalBytes && journalReport) {
468
+ appliedActions += applyJournalActions(journalPath, repairId, journalReport, plan.actions, sha256(journalBytes));
469
+ }
470
+ if (compactionBytes) {
471
+ appliedActions += applyCompactionActions(compactionPath, repairId, plan.actions, sha256(compactionBytes));
472
+ }
473
+ }
474
+ catch (error) {
475
+ const code = error instanceof Error && error.message === "precondition_changed" ? "precondition_changed" : "repair_failed";
476
+ const result = refusedResult(base, code);
477
+ writeLine(JSON.stringify(result, null, 2));
478
+ return { handled: true, exitCode: result.exitCode, result };
479
+ }
480
+ const finalSession = inspectSessionIntegrity(readFileSync(sessionPath));
481
+ const finalJournal = existsSync(journalPath)
482
+ ? inspectRunJournal(readFileSync(journalPath), RunJournalStore.sha256)
483
+ : null;
484
+ const healthy = finalSession.ok && (finalJournal?.ok ?? true);
485
+ const result = {
486
+ ...base,
487
+ status: healthy ? "healthy" : "issues",
488
+ exitCode: healthy ? 0 : 1,
489
+ appliedActions,
490
+ };
491
+ writeLine(JSON.stringify(result, null, 2));
492
+ return { handled: true, exitCode: result.exitCode, result };
493
+ }
494
+ //# sourceMappingURL=session-doctor-cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-doctor-cli.js","sourceRoot":"","sources":["../../src/commands/session-doctor-cli.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash, randomUUID } from \"node:crypto\";\nimport {\n\tcloseSync,\n\texistsSync,\n\tfstatSync,\n\tfsyncSync,\n\tlstatSync,\n\topenSync,\n\treadFileSync,\n\trealpathSync,\n\trenameSync,\n\ttype Stats,\n\tstatSync,\n} from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport lockfile from \"proper-lockfile\";\nimport { atomicRewriteFileSync } from \"../core/atomic-session-file.ts\";\nimport { type DecideCompactionCommitInput, validateCompactionEnvelope } from \"../core/compaction/transaction.ts\";\nimport {\n\tGENESIS_HASH,\n\tinspectRunJournal,\n\tRUN_JOURNAL_SCHEMA_VERSION,\n\ttype RunJournalReport,\n\ttype RunJournalTerminalRecord,\n\tserializeRunJournalLine,\n\tserializeRunJournalMaterial,\n} from \"../core/run-journal.ts\";\nimport { RunJournalStore, writeQuarantineBytesDurably } from \"../core/run-journal-store.ts\";\nimport {\n\tplanSessionDoctor,\n\ttype SessionDoctorAction,\n\ttype SessionDoctorMode,\n\ttype SessionDoctorNormalizedCheck,\n\ttype SessionDoctorPlan,\n} from \"../core/session-doctor-plan.ts\";\nimport { inspectSessionIntegrity, type SessionIntegrityReport } from \"../core/session-integrity.ts\";\nimport { SessionManager } from \"../core/session-manager.ts\";\nimport {\n\tdecideSessionPathAccess,\n\ttype SessionPathAccessInput,\n\ttype SessionPathChainEntry,\n\ttype SessionPathStat,\n} from \"../core/session-path-policy.ts\";\nimport { classifySessionTermination } from \"../core/session-termination.ts\";\nimport { validateEvidenceReceipt } from \"../guardrails/evidence-receipt.ts\";\nimport { ReplayLedgerManager } from \"../guardrails/evidence-system.ts\";\nimport { resolvePath } from \"../utils/paths.ts\";\n\nconst USAGE = \"Usage: omk session doctor [--session <path|id>] [--repair [--dry-run]]\";\n\nexport interface SessionDoctorCliOverrides {\n\treadonly cwd?: string;\n\treadonly sessionDir?: string;\n\treadonly now?: () => Date;\n\treadonly writeLine?: (line: string) => void;\n\t/** Test seam invoked after planning and before the repair CAS lock. */\n\treadonly beforeExecute?: () => void;\n}\n\nexport interface SessionDoctorCliResult {\n\treadonly schemaVersion: 1;\n\treadonly command: \"session_doctor\";\n\treadonly mode: SessionDoctorMode;\n\treadonly sessionId: string;\n\treadonly sessionPath: string;\n\treadonly repairId: string;\n\treadonly status: \"healthy\" | \"issues\" | \"refused\";\n\treadonly exitCode: 0 | 1 | 2;\n\treadonly findings: SessionDoctorPlan[\"findings\"];\n\treadonly actions: SessionDoctorPlan[\"actions\"];\n\treadonly normalizedChecks: readonly SessionDoctorNormalizedCheck[];\n\treadonly appliedActions: number;\n\treadonly preconditionSha256: string;\n\treadonly errorCode?: \"precondition_changed\" | \"repair_failed\";\n}\n\nexport interface SessionDoctorCliBatchResult {\n\treadonly schemaVersion: 1;\n\treadonly command: \"session_doctor\";\n\treadonly mode: SessionDoctorMode;\n\treadonly scope: \"all\";\n\treadonly status: \"healthy\" | \"issues\" | \"refused\";\n\treadonly exitCode: 0 | 1 | 2;\n\treadonly sessionCount: number;\n\treadonly appliedActions: number;\n\treadonly sessions: readonly SessionDoctorCliResult[];\n}\n\nexport interface SessionDoctorCliOutcome {\n\treadonly handled: boolean;\n\treadonly exitCode: number;\n\treadonly result?: SessionDoctorCliResult;\n}\n\ntype ParseOutcome =\n\t| { readonly kind: \"absent\" }\n\t| { readonly kind: \"help\" }\n\t| { readonly kind: \"error\"; readonly message: string }\n\t| {\n\t\t\treadonly kind: \"ok\";\n\t\t\treadonly session?: string;\n\t\t\treadonly mode: SessionDoctorMode;\n\t };\n\nfunction parseArgs(args: readonly string[]): ParseOutcome {\n\tif (args[0] !== \"session\" || args[1] !== \"doctor\") return { kind: \"absent\" };\n\tlet session: string | undefined;\n\tlet repair = false;\n\tlet dryRun = false;\n\tfor (let index = 2; index < args.length; index += 1) {\n\t\tconst arg = args[index];\n\t\tif (arg === \"--help\" || arg === \"-h\") return { kind: \"help\" };\n\t\tif (arg === \"--repair\") {\n\t\t\trepair = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (arg === \"--dry-run\") {\n\t\t\tdryRun = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (arg === \"--session\") {\n\t\t\tconst value = args[index + 1];\n\t\t\tif (!value || value.startsWith(\"--\")) return { kind: \"error\", message: \"--session requires a value\" };\n\t\t\tsession = value;\n\t\t\tindex += 1;\n\t\t\tcontinue;\n\t\t}\n\t\treturn { kind: \"error\", message: \"unexpected session doctor argument\" };\n\t}\n\tif (dryRun && !repair) return { kind: \"error\", message: \"--dry-run requires --repair\" };\n\treturn { kind: \"ok\", session, mode: repair ? (dryRun ? \"repair_dry_run\" : \"repair\") : \"inspect\" };\n}\n\nfunction sha256(bytes: Uint8Array): string {\n\treturn createHash(\"sha256\").update(bytes).digest(\"hex\");\n}\n\nasync function resolveSession(\n\targument: string | undefined,\n\tcwd: string,\n\tsessionDir: string | undefined,\n): Promise<string | null> {\n\tif (argument && (argument.includes(\"/\") || argument.includes(\"\\\\\") || argument.endsWith(\".jsonl\"))) {\n\t\tconst path = resolvePath(argument, cwd);\n\t\treturn existsSync(path) ? path : null;\n\t}\n\tconst local = await SessionManager.list(cwd, sessionDir);\n\tif (argument) {\n\t\tconst localMatches = local.filter((session) => session.id === argument || session.id.startsWith(argument));\n\t\tif (localMatches.length === 1) return localMatches[0].path;\n\t\tconst all = await SessionManager.listAll(sessionDir);\n\t\tconst globalMatches = all.filter((session) => session.id === argument || session.id.startsWith(argument));\n\t\treturn globalMatches.length === 1 ? globalMatches[0].path : null;\n\t}\n\treturn local[0]?.path ?? null;\n}\n\nfunction pathStat(stat: Stats): SessionPathStat {\n\treturn {\n\t\tdev: String(stat.dev),\n\t\tino: String(stat.ino),\n\t\tnlink: stat.nlink,\n\t\tsize: stat.size,\n\t\tmtime: Math.max(0, Math.trunc(stat.mtimeMs)),\n\t\tregular: stat.isFile(),\n\t\towner: String(stat.uid),\n\t};\n}\n\nfunction pathObservation(target: string): Omit<SessionPathAccessInput, \"intent\"> {\n\tconst root = dirname(target);\n\tconst rootReal = realpathSync(root);\n\tconst targetReal = realpathSync(target);\n\tconst rootLstat = lstatSync(root);\n\tconst targetLstat = lstatSync(target);\n\tconst chain: SessionPathChainEntry[] = [\n\t\t{ lexical: root, realpath: rootReal, linkKind: rootLstat.isSymbolicLink() ? \"symlink\" : \"none\" },\n\t\t{ lexical: target, realpath: targetReal, linkKind: targetLstat.isSymbolicLink() ? \"symlink\" : \"none\" },\n\t];\n\tconst before = statSync(target);\n\tconst fd = openSync(target, \"r\");\n\tlet opened: Stats;\n\ttry {\n\t\topened = fstatSync(fd);\n\t} finally {\n\t\tcloseSync(fd);\n\t}\n\tconst after = statSync(target);\n\tconst owner = typeof process.getuid === \"function\" ? process.getuid() : before.uid;\n\tconst lockExists = existsSync(`${target}.lock`);\n\treturn {\n\t\tplatform: process.platform === \"win32\" ? \"win32\" : \"posix\",\n\t\troot,\n\t\ttarget,\n\t\tidentity: { owner: String(owner) },\n\t\tevidence: {\n\t\t\tschemaVersion: 1,\n\t\t\tplatform: process.platform === \"win32\" ? \"win32\" : \"posix\",\n\t\t\ttrustedRootLexical: root,\n\t\t\ttrustedRootRealpath: rootReal,\n\t\t\ttarget: { lexical: target, realpath: targetReal },\n\t\t\tchain,\n\t\t\tstatBefore: pathStat(before),\n\t\t\tstatAfter: pathStat(after),\n\t\t\topened: { dev: String(opened.dev), ino: String(opened.ino) },\n\t\t},\n\t\tlock: lockExists\n\t\t\t? { state: \"unknown\", sameHost: false, pidDefinitelyAbsent: false, holderPid: null }\n\t\t\t: { state: \"absent\", sameHost: true, pidDefinitelyAbsent: true, holderPid: null },\n\t};\n}\n\nfunction normalizedChecks(\n\treport: SessionIntegrityReport,\n\tsessionPath: string,\n): readonly SessionDoctorNormalizedCheck[] {\n\tconst checks: SessionDoctorNormalizedCheck[] = [];\n\tconst compactions = report.entries.filter((entry) => entry.type === \"compaction\");\n\tlet compactionStatus: SessionDoctorNormalizedCheck[\"status\"] = \"ok\";\n\tfor (const entry of compactions) {\n\t\tconst details = entry.details;\n\t\tif (typeof details !== \"object\" || details === null || !(\"compactionEnvelope\" in details)) {\n\t\t\tcompactionStatus = \"missing\";\n\t\t\tbreak;\n\t\t}\n\t\ttry {\n\t\t\tconst envelope = validateCompactionEnvelope((details as { compactionEnvelope: unknown }).compactionEnvelope);\n\t\t\tconst summarySha256 = createHash(\"sha256\").update(entry.summary, \"utf8\").digest(\"hex\");\n\t\t\tif (\n\t\t\t\tenvelope.source.sessionId !== report.header?.id ||\n\t\t\t\tenvelope.summary !== entry.summary ||\n\t\t\t\tenvelope.summarySha256 !== summarySha256 ||\n\t\t\t\tenvelope.source.activeLeafId !== entry.parentId\n\t\t\t) {\n\t\t\t\tcompactionStatus = \"invalid\";\n\t\t\t\tbreak;\n\t\t\t}\n\t\t} catch {\n\t\t\tcompactionStatus = \"invalid\";\n\t\t\tbreak;\n\t\t}\n\t}\n\tchecks.push({ artifact: \"compaction_envelope\", id: \"compaction\", status: compactionStatus });\n\n\tconst replayPath = `${sessionPath}.replay.jsonl`;\n\tlet replayStatus: SessionDoctorNormalizedCheck[\"status\"] = \"ok\";\n\tif (existsSync(replayPath)) {\n\t\ttry {\n\t\t\tconst ledger = new ReplayLedgerManager(report.header?.id ?? \"unknown\", replayPath);\n\t\t\tif (ledger.getEvents().some((event) => event.goalId !== report.header?.id)) replayStatus = \"invalid\";\n\t\t} catch {\n\t\t\treplayStatus = \"invalid\";\n\t\t}\n\t}\n\tchecks.push({ artifact: \"evidence_link\", id: \"replay-ledger\", status: replayStatus });\n\n\tlet receiptStatus: SessionDoctorNormalizedCheck[\"status\"] = \"ok\";\n\tfor (const entry of report.entries) {\n\t\tif (entry.type !== \"custom\" || entry.customType !== \"evidence_receipt\") continue;\n\t\ttry {\n\t\t\tvalidateEvidenceReceipt(entry.data);\n\t\t} catch {\n\t\t\treceiptStatus = \"invalid\";\n\t\t\tbreak;\n\t\t}\n\t}\n\tchecks.push({ artifact: \"evidence_link\", id: \"evidence-receipts\", status: receiptStatus });\n\n\tlet workspaceStatus: SessionDoctorNormalizedCheck[\"status\"] = \"invalid\";\n\ttry {\n\t\tworkspaceStatus = report.header && statSync(report.header.cwd).isDirectory() ? \"ok\" : \"missing\";\n\t} catch {\n\t\tworkspaceStatus = \"missing\";\n\t}\n\tchecks.push({ artifact: \"workspace\", id: \"workspace\", status: workspaceStatus });\n\n\tconst hasProviderModel = report.entries.some((entry) => entry.type === \"model_change\");\n\tchecks.push({\n\t\tartifact: \"provider_model\",\n\t\tid: \"active-provider-model\",\n\t\tstatus: hasProviderModel ? \"ok\" : \"missing\",\n\t});\n\treturn Object.freeze(checks);\n}\n\nfunction makeRecoveryRecord(\n\treport: RunJournalReport,\n\tsessionId: string,\n\ttimestamp: string,\n): RunJournalTerminalRecord | undefined {\n\tif (report.openRunId === null) return undefined;\n\tconst last = report.records.at(-1);\n\tconst termination = classifySessionTermination({\n\t\tsessionId,\n\t\trunId: report.openRunId,\n\t\ttimestamp,\n\t\tsource: \"inferred_on_resume\",\n\t\tmessage: \"Previous process exited without closing the run; recovered by session doctor.\",\n\t\tcause: { area: \"process\", code: \"crash\" },\n\t\tsideEffects: \"possible\",\n\t});\n\tconst material: Omit<RunJournalTerminalRecord, \"hash\"> = {\n\t\tschemaVersion: RUN_JOURNAL_SCHEMA_VERSION,\n\t\tseq: (last?.seq ?? -1) + 1,\n\t\tevent: \"run_recovered\",\n\t\trunId: report.openRunId,\n\t\tsessionId,\n\t\tsessionRevision: last?.sessionRevision ?? 0,\n\t\ttimestamp,\n\t\tprevHash: last?.hash ?? GENESIS_HASH,\n\t\ttermination,\n\t};\n\treturn Object.freeze({\n\t\t...material,\n\t\thash: RunJournalStore.sha256(new TextEncoder().encode(serializeRunJournalMaterial(material))),\n\t});\n}\n\nfunction hardSessionDamage(report: SessionIntegrityReport): boolean {\n\treturn report.findings.some(\n\t\t(finding) => finding.reason !== \"trailing_fragment\" && finding.reason !== \"transcript_missing_result\",\n\t);\n}\n\nfunction hardJournalDamage(report: RunJournalReport | null): boolean {\n\treturn (\n\t\treport?.findings.some((finding) => finding.code !== \"trailing_fragment\" && finding.code !== \"run_unclosed\") ??\n\t\tfalse\n\t);\n}\n\nfunction parsePrefixEntries(bytes: Uint8Array): Array<Record<string, unknown>> {\n\tconst text = new TextDecoder(\"utf-8\", { fatal: true }).decode(bytes);\n\treturn text\n\t\t.split(\"\\n\")\n\t\t.filter((line) => line.length > 0)\n\t\t.map((line) => JSON.parse(line) as Record<string, unknown>);\n}\n\nfunction applySessionActions(\n\tsessionPath: string,\n\trepairId: string,\n\treport: SessionIntegrityReport,\n\tactions: readonly SessionDoctorAction[],\n\tpreconditionSha256: string,\n\tnow: Date,\n): number {\n\tconst sessionActions = actions.filter(\n\t\t(action) =>\n\t\t\taction.kind === \"quarantine_session_trailing_fragment\" || action.kind === \"append_synthetic_tool_result\",\n\t);\n\tif (sessionActions.length === 0) return 0;\n\tconst release = lockfile.lockSync(sessionPath, { realpath: false });\n\ttry {\n\t\tconst current = new Uint8Array(readFileSync(sessionPath));\n\t\tif (sha256(current) !== preconditionSha256) throw new Error(\"precondition_changed\");\n\t\tconst prefix = current.subarray(0, report.completePrefix.byteCount);\n\t\tif (report.trailingFragment) {\n\t\t\twriteQuarantineBytesDurably(`${sessionPath}.quarantine-${repairId}`, current.subarray(prefix.byteLength));\n\t\t}\n\t\tconst records = parsePrefixEntries(prefix);\n\t\tlet parentId = report.activeLeafId;\n\t\tfor (const action of sessionActions) {\n\t\t\tif (action.kind !== \"append_synthetic_tool_result\") continue;\n\t\t\tlet id = `doctor-${repairId.slice(0, 20)}-${action.sequence}`;\n\t\t\twhile (records.some((record) => record.id === id)) id = `${id}-x`;\n\t\t\trecords.push({\n\t\t\t\ttype: \"message\",\n\t\t\t\tid,\n\t\t\t\tparentId,\n\t\t\t\ttimestamp: new Date(now.getTime() + action.sequence).toISOString(),\n\t\t\t\tmessage: action.message,\n\t\t\t});\n\t\t\tparentId = id;\n\t\t}\n\t\tatomicRewriteFileSync(sessionPath, `${records.map((record) => JSON.stringify(record)).join(\"\\n\")}\\n`);\n\t\treturn sessionActions.length;\n\t} finally {\n\t\trelease();\n\t}\n}\n\nfunction applyJournalActions(\n\tjournalPath: string,\n\trepairId: string,\n\treport: RunJournalReport,\n\tactions: readonly SessionDoctorAction[],\n\tpreconditionSha256: string,\n): number {\n\tconst journalActions = actions.filter(\n\t\t(action) => action.kind === \"quarantine_journal_trailing_fragment\" || action.kind === \"recover_run\",\n\t);\n\tif (journalActions.length === 0) return 0;\n\tconst release = lockfile.lockSync(journalPath, { realpath: false });\n\ttry {\n\t\tconst current = new Uint8Array(readFileSync(journalPath));\n\t\tif (sha256(current) !== preconditionSha256) throw new Error(\"precondition_changed\");\n\t\tconst prefix = current.subarray(0, report.completePrefix.byteCount);\n\t\tif (report.trailingByteCount > 0) {\n\t\t\twriteQuarantineBytesDurably(`${journalPath}.quarantine-${repairId}`, current.subarray(prefix.byteLength));\n\t\t}\n\t\tconst recovery = journalActions.find(\n\t\t\t(action): action is Extract<SessionDoctorAction, { kind: \"recover_run\" }> => action.kind === \"recover_run\",\n\t\t);\n\t\tconst suffix = recovery\n\t\t\t? new TextEncoder().encode(`${serializeRunJournalLine(recovery.terminalRecord)}\\n`)\n\t\t\t: null;\n\t\tconst output = suffix ? Buffer.concat([Buffer.from(prefix), Buffer.from(suffix)]) : prefix;\n\t\tatomicRewriteFileSync(journalPath, output);\n\t\treturn journalActions.length;\n\t} finally {\n\t\trelease();\n\t}\n}\n\nfunction applyCompactionActions(\n\tsidecarPath: string,\n\trepairId: string,\n\tactions: readonly SessionDoctorAction[],\n\tpreconditionSha256: string,\n): number {\n\tconst abandon = actions.find((action) => action.kind === \"abandon_stale_compaction\");\n\tif (!abandon) return 0;\n\tconst release = lockfile.lockSync(sidecarPath, { realpath: false });\n\ttry {\n\t\tif (sha256(readFileSync(sidecarPath)) !== preconditionSha256) throw new Error(\"precondition_changed\");\n\t\trenameSync(sidecarPath, `${sidecarPath}.abandoned-${repairId}`);\n\t\tif (process.platform !== \"win32\") {\n\t\t\tconst dirFd = openSync(dirname(sidecarPath), \"r\");\n\t\t\ttry {\n\t\t\t\tfsyncSync(dirFd);\n\t\t\t} finally {\n\t\t\t\tcloseSync(dirFd);\n\t\t\t}\n\t\t}\n\t\treturn 1;\n\t} finally {\n\t\trelease();\n\t}\n}\n\nfunction refusedResult(\n\tbase: Omit<SessionDoctorCliResult, \"status\" | \"exitCode\" | \"appliedActions\">,\n\terrorCode?: SessionDoctorCliResult[\"errorCode\"],\n): SessionDoctorCliResult {\n\treturn {\n\t\t...base,\n\t\tstatus: \"refused\",\n\t\texitCode: 2,\n\t\tappliedActions: 0,\n\t\t...(errorCode ? { errorCode } : {}),\n\t};\n}\n\nexport async function runSessionDoctorCli(\n\targs: readonly string[],\n\toverrides: SessionDoctorCliOverrides = {},\n): Promise<SessionDoctorCliOutcome> {\n\tconst parsed = parseArgs(args);\n\tif (parsed.kind === \"absent\") return { handled: false, exitCode: 0 };\n\tconst writeLine = overrides.writeLine ?? ((line: string) => console.log(line));\n\tif (parsed.kind === \"help\") {\n\t\twriteLine(USAGE);\n\t\treturn { handled: true, exitCode: 0 };\n\t}\n\tif (parsed.kind === \"error\") {\n\t\twriteLine(JSON.stringify({ status: \"refused\", error: parsed.message, usage: USAGE }));\n\t\treturn { handled: true, exitCode: 2 };\n\t}\n\n\tconst cwd = resolve(overrides.cwd ?? process.cwd());\n\tif (parsed.session === undefined) {\n\t\tconst sessions = await SessionManager.listAll(overrides.sessionDir);\n\t\tconst paths = [...new Set(sessions.map((session) => session.path))];\n\t\tconst nestedArgs = [\"session\", \"doctor\"];\n\t\tif (parsed.mode !== \"inspect\") nestedArgs.push(\"--repair\");\n\t\tif (parsed.mode === \"repair_dry_run\") nestedArgs.push(\"--dry-run\");\n\t\tconst results: SessionDoctorCliResult[] = [];\n\t\tlet exitCode: 0 | 1 | 2 = 0;\n\t\tfor (const path of paths) {\n\t\t\tconst outcome = await runSessionDoctorCli([...nestedArgs, \"--session\", path], {\n\t\t\t\t...overrides,\n\t\t\t\twriteLine: () => {},\n\t\t\t});\n\t\t\texitCode = Math.max(exitCode, outcome.exitCode) as 0 | 1 | 2;\n\t\t\tif (outcome.result) results.push(outcome.result);\n\t\t}\n\t\tconst batch: SessionDoctorCliBatchResult = {\n\t\t\tschemaVersion: 1,\n\t\t\tcommand: \"session_doctor\",\n\t\t\tmode: parsed.mode,\n\t\t\tscope: \"all\",\n\t\t\tstatus: exitCode === 2 ? \"refused\" : exitCode === 1 ? \"issues\" : \"healthy\",\n\t\t\texitCode,\n\t\t\tsessionCount: paths.length,\n\t\t\tappliedActions: results.reduce((total, result) => total + result.appliedActions, 0),\n\t\t\tsessions: results,\n\t\t};\n\t\twriteLine(JSON.stringify(batch, null, 2));\n\t\treturn { handled: true, exitCode };\n\t}\n\tconst sessionPath = await resolveSession(parsed.session, cwd, overrides.sessionDir);\n\tif (!sessionPath) {\n\t\twriteLine(JSON.stringify({ status: \"refused\", error: \"session_not_found\", usage: USAGE }));\n\t\treturn { handled: true, exitCode: 2 };\n\t}\n\tconst now = overrides.now?.() ?? new Date();\n\tconst repairId = randomUUID();\n\tconst sessionBytes = new Uint8Array(readFileSync(sessionPath));\n\tconst preconditionSha256 = sha256(sessionBytes);\n\tconst report = inspectSessionIntegrity(sessionBytes);\n\tconst sessionId = report.header?.id ?? \"unknown-session\";\n\tconst checks = normalizedChecks(report, sessionPath);\n\tconst compactionPath = `${sessionPath}.compaction-transaction.json`;\n\tconst compactionBytes = existsSync(compactionPath) ? new Uint8Array(readFileSync(compactionPath)) : null;\n\tlet compaction: DecideCompactionCommitInput | undefined;\n\tlet compactionInvalid = false;\n\tif (compactionBytes) {\n\t\ttry {\n\t\t\tcompaction = JSON.parse(\n\t\t\t\tnew TextDecoder(\"utf-8\", { fatal: true }).decode(compactionBytes),\n\t\t\t) as DecideCompactionCommitInput;\n\t\t} catch {\n\t\t\tcompactionInvalid = true;\n\t\t}\n\t}\n\tconst compactionPathAuthorized =\n\t\tcompactionBytes === null ||\n\t\tdecideSessionPathAccess({\n\t\t\t...pathObservation(compactionPath),\n\t\t\tintent: parsed.mode === \"inspect\" ? \"inspect_content\" : parsed.mode === \"repair\" ? \"repair\" : \"repair_dry_run\",\n\t\t}).status === \"authorized\";\n\tconst journalPath = `${sessionPath}.runjournal`;\n\tconst journalBytes = existsSync(journalPath) ? new Uint8Array(readFileSync(journalPath)) : null;\n\tconst journalReport = journalBytes ? inspectRunJournal(journalBytes, RunJournalStore.sha256) : null;\n\tconst terminalRecord = journalReport ? makeRecoveryRecord(journalReport, sessionId, now.toISOString()) : undefined;\n\tconst plan = planSessionDoctor({\n\t\tmode: parsed.mode,\n\t\tsessionId,\n\t\trepairId,\n\t\ttimestamp: now.getTime(),\n\t\treport,\n\t\t...(compaction ? { compaction } : {}),\n\t\t...(journalBytes\n\t\t\t? {\n\t\t\t\t\tjournal: {\n\t\t\t\t\t\tbytes: journalBytes,\n\t\t\t\t\t\thashFn: RunJournalStore.sha256,\n\t\t\t\t\t\t...(terminalRecord ? { terminalRecord } : {}),\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t: {}),\n\t\tpaths: {\n\t\t\tsession: pathObservation(sessionPath),\n\t\t\t...(journalBytes ? { journal: pathObservation(journalPath) } : {}),\n\t\t},\n\t\tnormalizedChecks: checks,\n\t});\n\tconst base = {\n\t\tschemaVersion: 1 as const,\n\t\tcommand: \"session_doctor\" as const,\n\t\tmode: parsed.mode,\n\t\tsessionId,\n\t\tsessionPath,\n\t\trepairId,\n\t\tfindings: plan.findings,\n\t\tactions: plan.actions,\n\t\tnormalizedChecks: checks,\n\t\tpreconditionSha256,\n\t};\n\n\tif (\n\t\thardSessionDamage(report) ||\n\t\thardJournalDamage(journalReport) ||\n\t\tcompactionInvalid ||\n\t\t!compactionPathAuthorized ||\n\t\tplan.status === \"refused\"\n\t) {\n\t\tconst result = refusedResult(base);\n\t\twriteLine(JSON.stringify(result, null, 2));\n\t\treturn { handled: true, exitCode: result.exitCode, result };\n\t}\n\tif (parsed.mode !== \"repair\") {\n\t\tconst result: SessionDoctorCliResult = {\n\t\t\t...base,\n\t\t\tstatus: plan.status,\n\t\t\texitCode: plan.exitCode,\n\t\t\tappliedActions: 0,\n\t\t};\n\t\twriteLine(JSON.stringify(result, null, 2));\n\t\treturn { handled: true, exitCode: result.exitCode, result };\n\t}\n\n\toverrides.beforeExecute?.();\n\tlet appliedActions = 0;\n\ttry {\n\t\tappliedActions += applySessionActions(sessionPath, repairId, report, plan.actions, preconditionSha256, now);\n\t\tif (journalBytes && journalReport) {\n\t\t\tappliedActions += applyJournalActions(\n\t\t\t\tjournalPath,\n\t\t\t\trepairId,\n\t\t\t\tjournalReport,\n\t\t\t\tplan.actions,\n\t\t\t\tsha256(journalBytes),\n\t\t\t);\n\t\t}\n\t\tif (compactionBytes) {\n\t\t\tappliedActions += applyCompactionActions(compactionPath, repairId, plan.actions, sha256(compactionBytes));\n\t\t}\n\t} catch (error) {\n\t\tconst code =\n\t\t\terror instanceof Error && error.message === \"precondition_changed\" ? \"precondition_changed\" : \"repair_failed\";\n\t\tconst result = refusedResult(base, code);\n\t\twriteLine(JSON.stringify(result, null, 2));\n\t\treturn { handled: true, exitCode: result.exitCode, result };\n\t}\n\n\tconst finalSession = inspectSessionIntegrity(readFileSync(sessionPath));\n\tconst finalJournal = existsSync(journalPath)\n\t\t? inspectRunJournal(readFileSync(journalPath), RunJournalStore.sha256)\n\t\t: null;\n\tconst healthy = finalSession.ok && (finalJournal?.ok ?? true);\n\tconst result: SessionDoctorCliResult = {\n\t\t...base,\n\t\tstatus: healthy ? \"healthy\" : \"issues\",\n\t\texitCode: healthy ? 0 : 1,\n\t\tappliedActions,\n\t};\n\twriteLine(JSON.stringify(result, null, 2));\n\treturn { handled: true, exitCode: result.exitCode, result };\n}\n"]}
@@ -0,0 +1,21 @@
1
+ import type { EvidenceReceipt, MergeGateResult, WorkspaceScope } from "../types/evidence.ts";
2
+ export interface VerifiedCiCommandRequest {
3
+ readonly evidenceDir: string;
4
+ readonly goalId: string;
5
+ readonly claim: string;
6
+ readonly script: string;
7
+ readonly cwd: string;
8
+ readonly timeoutMs: number | null;
9
+ readonly workspaceScope: WorkspaceScope;
10
+ readonly shellPath?: string;
11
+ }
12
+ export interface VerifiedCiCommandResult {
13
+ readonly exitCode: 0 | 1;
14
+ readonly gate: MergeGateResult;
15
+ readonly receipt: EvidenceReceipt;
16
+ readonly receiptPath: string;
17
+ readonly reportPath: string;
18
+ }
19
+ /** Execute one first-party CI verifier through the local receipt-bound bash path. */
20
+ export declare function runVerifiedCiCommand(request: VerifiedCiCommandRequest): Promise<VerifiedCiCommandResult>;
21
+ //# sourceMappingURL=verify-ci.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify-ci.d.ts","sourceRoot":"","sources":["../../src/commands/verify-ci.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,eAAe,EAAyB,eAAe,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AASpH,MAAM,WAAW,wBAAwB;IACxC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IACxC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,uBAAuB;IACvC,QAAQ,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAClC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC5B;AAED,qFAAqF;AACrF,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CA0D9G","sourcesContent":["import { join } from \"node:path\";\nimport { executeVerifiedLocalBash } from \"../core/verified-bash-adapter.ts\";\nimport { EvidenceReceiptStore } from \"../guardrails/evidence-receipt-store.ts\";\nimport {\n\tEvidenceGate,\n\tReplayLedgerManager,\n\tTaskContractBuilder,\n\tVerifyReporterV2,\n} from \"../guardrails/evidence-system.ts\";\nimport { VerifiedEvidenceExecutor } from \"../guardrails/verified-executor.ts\";\nimport type { EvidenceReceipt, EvidenceReceiptStatus, MergeGateResult, WorkspaceScope } from \"../types/evidence.ts\";\n\nconst PASSED_RECEIPT_STATUS = {\n\tpassed: true,\n\tfailed: false,\n\ttimeout: false,\n\taborted: false,\n} as const satisfies Record<EvidenceReceiptStatus, boolean>;\n\nexport interface VerifiedCiCommandRequest {\n\treadonly evidenceDir: string;\n\treadonly goalId: string;\n\treadonly claim: string;\n\treadonly script: string;\n\treadonly cwd: string;\n\treadonly timeoutMs: number | null;\n\treadonly workspaceScope: WorkspaceScope;\n\treadonly shellPath?: string;\n}\n\nexport interface VerifiedCiCommandResult {\n\treadonly exitCode: 0 | 1;\n\treadonly gate: MergeGateResult;\n\treadonly receipt: EvidenceReceipt;\n\treadonly receiptPath: string;\n\treadonly reportPath: string;\n}\n\n/** Execute one first-party CI verifier through the local receipt-bound bash path. */\nexport async function runVerifiedCiCommand(request: VerifiedCiCommandRequest): Promise<VerifiedCiCommandResult> {\n\tconst executor = new VerifiedEvidenceExecutor({\n\t\tstore: new EvidenceReceiptStore(join(request.evidenceDir, \"receipts\")),\n\t\tledger: new ReplayLedgerManager(request.goalId, join(request.evidenceDir, \"ledger\", \"events.jsonl\")),\n\t});\n\tconst execution = await executeVerifiedLocalBash({\n\t\tevidenceExecutor: executor,\n\t\tgoalId: request.goalId,\n\t\tlaneId: \"ci-runner\",\n\t\tclaim: request.claim,\n\t\tscript: request.script,\n\t\tcwd: request.cwd,\n\t\ttimeoutMs: request.timeoutMs,\n\t\tworkspaceScope: request.workspaceScope,\n\t\texecutor: \"ci-runner\",\n\t\t...(request.shellPath !== undefined ? { shellPath: request.shellPath } : {}),\n\t});\n\tconst passed = PASSED_RECEIPT_STATUS[execution.receipt.core.status];\n\t// Persist only the receipt's redacted command representation; the original\n\t// script may carry inline secrets and must never reach contract or report.\n\tconst persistedCommand = execution.receipt.core.command;\n\tconst verificationCommand =\n\t\tpersistedCommand.kind === \"shell\"\n\t\t\t? persistedCommand.script\n\t\t\t: [persistedCommand.executable, ...persistedCommand.argv].join(\" \");\n\tconst contract = new TaskContractBuilder(request.goalId)\n\t\t.setClaim(request.claim)\n\t\t.addRequiredEvidence({\n\t\t\tclaim: request.claim,\n\t\t\tcategory: \"release\",\n\t\t\tverificationCommand,\n\t\t\treceiptId: execution.evidenceMetadata.receiptId,\n\t\t\treceiptSchemaVersion: 3,\n\t\t\treceiptCommandSha256: execution.evidenceMetadata.receiptCommandSha256,\n\t\t\t...(execution.evidenceMetadata.receiptLaneId !== undefined\n\t\t\t\t? { receiptLaneId: execution.evidenceMetadata.receiptLaneId }\n\t\t\t\t: {}),\n\t\t})\n\t\t.updateEvidenceStatus(request.claim, passed ? \"satisfied\" : \"failed\")\n\t\t.setFinalRisk(\n\t\t\t\"Receipt freshness covers the selected workspace scope (git dirty state or artifact set) plus ledger-sequenced workspace mutations.\",\n\t\t)\n\t\t.setVerdict(passed ? \"pass\" : \"fail\")\n\t\t.build();\n\t// The gate options wire recapture and the workspace-mutation freshness source to\n\t// this command's own ReplayLedger, so a mutation recorded after the receipt blocks.\n\tconst gate = new EvidenceGate({ receiptMode: \"strict\", ...executor.createGateOptions() }).check(contract);\n\tconst reportPath = new VerifyReporterV2({ outputDir: request.evidenceDir, goalId: request.goalId }).write(\n\t\tcontract,\n\t\tgate,\n\t);\n\treturn {\n\t\texitCode: gate.status === \"open\" ? 0 : 1,\n\t\tgate,\n\t\treceipt: execution.receipt,\n\t\treceiptPath: execution.receiptPath,\n\t\treportPath,\n\t};\n}\n"]}