@the-open-engine/zeroshot 6.38.0 → 6.39.0

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 (381) hide show
  1. package/cli/event-copy.js +8 -7
  2. package/cli/event-copy.ts +12 -0
  3. package/cli/index.js +7 -31
  4. package/cli/json-export.js +61 -64
  5. package/cli/json-export.ts +112 -0
  6. package/cli/message-formatter-utils.js +68 -56
  7. package/cli/message-formatter-utils.ts +121 -0
  8. package/cli/message-formatters-normal.js +124 -259
  9. package/cli/message-formatters-normal.ts +250 -0
  10. package/cli/message-formatters-watch.js +81 -84
  11. package/cli/message-formatters-watch.ts +189 -0
  12. package/lib/agent-cli-provider/adapters/codex.d.ts.map +1 -1
  13. package/lib/agent-cli-provider/adapters/codex.js +3 -1
  14. package/lib/agent-cli-provider/adapters/codex.js.map +1 -1
  15. package/lib/cluster/generated/protocol-schema.cjs +1 -1
  16. package/lib/cluster/generated/protocol-schema.mjs +1 -1
  17. package/lib/cluster/generated/protocol.d.cts +8 -0
  18. package/lib/cluster/generated/protocol.d.mts +8 -0
  19. package/lib/cluster/generated/protocol.d.ts +8 -0
  20. package/lib/clusters-registry.d.ts +23 -0
  21. package/lib/clusters-registry.js +17 -29
  22. package/lib/completion.d.ts +12 -0
  23. package/lib/completion.js +84 -94
  24. package/lib/compose-utils.d.ts +32 -0
  25. package/lib/compose-utils.js +57 -72
  26. package/lib/detached-startup.d.ts +83 -0
  27. package/lib/detached-startup.js +231 -302
  28. package/lib/docker-config.d.ts +43 -0
  29. package/lib/docker-config.js +150 -325
  30. package/lib/docker-env-auth.d.ts +17 -0
  31. package/lib/docker-env-auth.js +75 -0
  32. package/lib/git-remote-utils.d.ts +48 -0
  33. package/lib/git-remote-utils.js +147 -213
  34. package/lib/id-detector.d.ts +15 -0
  35. package/lib/id-detector.js +37 -41
  36. package/lib/path-check.d.ts +30 -0
  37. package/lib/path-check.js +42 -45
  38. package/lib/process-liveness.d.ts +16 -0
  39. package/lib/process-liveness.js +19 -12
  40. package/lib/provider-credential-path.d.ts +16 -0
  41. package/lib/provider-credential-path.js +31 -29
  42. package/lib/provider-defaults.d.ts +30 -0
  43. package/lib/provider-defaults.js +47 -42
  44. package/lib/provider-detection.d.ts +11 -0
  45. package/lib/provider-detection.js +91 -54
  46. package/lib/provider-names.d.ts +38 -0
  47. package/lib/provider-names.js +56 -64
  48. package/lib/repo-settings.d.ts +28 -0
  49. package/lib/repo-settings.js +83 -59
  50. package/lib/run-mode.d.ts +21 -0
  51. package/lib/run-mode.js +21 -20
  52. package/lib/run-plan.d.ts +28 -0
  53. package/lib/run-plan.js +17 -16
  54. package/lib/settings/claude-auth.d.ts +35 -0
  55. package/lib/settings/claude-auth.js +30 -47
  56. package/lib/settings-defaults.d.ts +20 -0
  57. package/lib/settings-defaults.js +149 -0
  58. package/lib/settings-error.d.ts +7 -0
  59. package/lib/settings-error.js +8 -0
  60. package/lib/settings-issue-providers.d.ts +10 -0
  61. package/lib/settings-issue-providers.js +12 -0
  62. package/lib/settings-models.d.ts +22 -0
  63. package/lib/settings-models.js +93 -0
  64. package/lib/settings-storage.d.ts +23 -0
  65. package/lib/settings-storage.js +205 -0
  66. package/lib/settings-validation.d.ts +7 -0
  67. package/lib/settings-validation.js +182 -0
  68. package/lib/settings.d.ts +29 -0
  69. package/lib/settings.js +41 -736
  70. package/lib/setup-apply-types.d.ts +66 -0
  71. package/lib/setup-apply-types.js +2 -0
  72. package/lib/setup-apply.d.ts +39 -0
  73. package/lib/setup-apply.js +267 -264
  74. package/lib/setup-journal.d.ts +41 -0
  75. package/lib/setup-journal.js +119 -76
  76. package/lib/setup-plan-types.d.ts +102 -0
  77. package/lib/setup-plan-types.js +2 -0
  78. package/lib/setup-plan.d.ts +30 -0
  79. package/lib/setup-plan.js +300 -324
  80. package/lib/setup-undo.d.ts +44 -0
  81. package/lib/setup-undo.js +61 -74
  82. package/lib/start-cluster-config.d.ts +26 -0
  83. package/lib/start-cluster-config.js +56 -0
  84. package/lib/start-cluster-environment.d.ts +40 -0
  85. package/lib/start-cluster-environment.js +134 -0
  86. package/lib/start-cluster-run-options.d.ts +53 -0
  87. package/lib/start-cluster-run-options.js +147 -0
  88. package/lib/start-cluster.d.ts +64 -0
  89. package/lib/start-cluster.js +98 -454
  90. package/lib/stream-json-parser.d.ts +17 -0
  91. package/lib/stream-json-parser.js +51 -52
  92. package/npm-shrinkwrap.json +2 -2
  93. package/package.json +12 -6
  94. package/scripts/postinstall.js +27 -0
  95. package/scripts/rust-distribution.js +23 -14
  96. package/src/agent/agent-command-proofs-context.js +35 -45
  97. package/src/agent/agent-command-proofs-context.ts +87 -0
  98. package/src/agent/agent-config-settings.js +19 -0
  99. package/src/agent/agent-config-settings.ts +41 -0
  100. package/src/agent/agent-config.js +122 -231
  101. package/src/agent/agent-config.ts +285 -0
  102. package/src/agent/agent-context-builder.js +38 -273
  103. package/src/agent/agent-context-builder.ts +51 -0
  104. package/src/agent/agent-context-environment-sections.js +105 -0
  105. package/src/agent/agent-context-environment-sections.ts +134 -0
  106. package/src/agent/agent-context-packs.js +165 -0
  107. package/src/agent/agent-context-packs.ts +296 -0
  108. package/src/agent/agent-context-prompt-sections.js +100 -0
  109. package/src/agent/agent-context-prompt-sections.ts +148 -0
  110. package/src/agent/agent-context-sections.js +25 -334
  111. package/src/agent/agent-context-sections.ts +36 -0
  112. package/src/agent/agent-context-sources.js +96 -149
  113. package/src/agent/agent-context-sources.ts +253 -0
  114. package/src/agent/agent-context-types.js +2 -0
  115. package/src/agent/agent-context-types.ts +132 -0
  116. package/src/agent/agent-context-validation-sections.js +73 -0
  117. package/src/agent/agent-context-validation-sections.ts +129 -0
  118. package/src/agent/agent-input-injector.js +99 -118
  119. package/src/agent/agent-input-injector.ts +195 -0
  120. package/src/agent/agent-liveness-poll.js +74 -78
  121. package/src/agent/agent-liveness-poll.ts +163 -0
  122. package/src/agent/agent-quality-gate-schema.js +77 -86
  123. package/src/agent/agent-quality-gate-schema.ts +135 -0
  124. package/src/agent/agent-quality-gates-context.js +44 -50
  125. package/src/agent/agent-quality-gates-context.ts +91 -0
  126. package/src/agent/agent-stuck-detector.js +171 -239
  127. package/src/agent/agent-stuck-detector.ts +288 -0
  128. package/src/agent/agent-trigger-evaluator.js +29 -46
  129. package/src/agent/agent-trigger-evaluator.ts +98 -0
  130. package/src/agent/context-metrics.js +110 -141
  131. package/src/agent/context-metrics.ts +261 -0
  132. package/src/agent/context-pack-builder.js +72 -358
  133. package/src/agent/context-pack-builder.ts +105 -0
  134. package/src/agent/context-pack-core.js +70 -0
  135. package/src/agent/context-pack-core.ts +96 -0
  136. package/src/agent/context-pack-selection.js +119 -0
  137. package/src/agent/context-pack-selection.ts +187 -0
  138. package/src/agent/context-pack-truncation.js +139 -0
  139. package/src/agent/context-pack-truncation.ts +208 -0
  140. package/src/agent/context-pack-types.js +2 -0
  141. package/src/agent/context-pack-types.ts +98 -0
  142. package/src/agent/context-replay-policy.js +30 -39
  143. package/src/agent/context-replay-policy.ts +71 -0
  144. package/src/agent/critical-agent-policy.js +6 -10
  145. package/src/agent/critical-agent-policy.ts +20 -0
  146. package/src/agent/guidance-queue.js +74 -87
  147. package/src/agent/guidance-queue.ts +166 -0
  148. package/src/agent/output-extraction-error-detail.js +45 -0
  149. package/src/agent/output-extraction-error-detail.ts +49 -0
  150. package/src/agent/output-extraction-failures.js +125 -0
  151. package/src/agent/output-extraction-failures.ts +149 -0
  152. package/src/agent/output-extraction-json.js +234 -0
  153. package/src/agent/output-extraction-json.ts +235 -0
  154. package/src/agent/output-extraction-pi.js +124 -0
  155. package/src/agent/output-extraction-pi.ts +137 -0
  156. package/src/agent/output-extraction-types.js +2 -0
  157. package/src/agent/output-extraction-types.ts +49 -0
  158. package/src/agent/output-extraction.js +17 -617
  159. package/src/agent/output-extraction.ts +30 -0
  160. package/src/agent/output-reformatter-errors.js +83 -0
  161. package/src/agent/output-reformatter-errors.ts +106 -0
  162. package/src/agent/output-reformatter-types.js +2 -0
  163. package/src/agent/output-reformatter-types.ts +86 -0
  164. package/src/agent/output-reformatter.js +140 -185
  165. package/src/agent/output-reformatter.ts +238 -0
  166. package/src/agent/pi-terminal-lifecycle-types.js +2 -0
  167. package/src/agent/pi-terminal-lifecycle-types.ts +41 -0
  168. package/src/agent/pi-terminal-lifecycle.js +186 -206
  169. package/src/agent/pi-terminal-lifecycle.ts +297 -0
  170. package/src/agent/provider-control-plane.js +22 -21
  171. package/src/agent/provider-control-plane.ts +52 -0
  172. package/src/agent/provider-terminal-failure-types.js +2 -0
  173. package/src/agent/provider-terminal-failure-types.ts +60 -0
  174. package/src/agent/provider-terminal-failure.js +194 -191
  175. package/src/agent/provider-terminal-failure.ts +262 -0
  176. package/src/agent/rate-limit-backoff.js +31 -74
  177. package/src/agent/rate-limit-backoff.ts +71 -0
  178. package/src/agent/schema-utils.js +85 -125
  179. package/src/agent/schema-utils.ts +148 -0
  180. package/src/agent/structured-output-error.js +34 -33
  181. package/src/agent/structured-output-error.ts +105 -0
  182. package/src/agent/validation-platform.js +27 -27
  183. package/src/agent/validation-platform.ts +49 -0
  184. package/src/agent-cli-provider/adapters/codex.ts +3 -1
  185. package/src/attach/attach-client.js +232 -405
  186. package/src/attach/attach-client.ts +300 -0
  187. package/src/attach/attach-server-cleanup.js +43 -0
  188. package/src/attach/attach-server-cleanup.ts +39 -0
  189. package/src/attach/attach-server-clients.js +117 -0
  190. package/src/attach/attach-server-clients.ts +122 -0
  191. package/src/attach/attach-server-events.js +38 -0
  192. package/src/attach/attach-server-events.ts +36 -0
  193. package/src/attach/attach-server-pty.js +45 -0
  194. package/src/attach/attach-server-pty.ts +64 -0
  195. package/src/attach/attach-server-runtime.js +73 -0
  196. package/src/attach/attach-server-runtime.ts +62 -0
  197. package/src/attach/attach-server-socket.js +28 -0
  198. package/src/attach/attach-server-socket.ts +23 -0
  199. package/src/attach/attach-server-types.js +2 -0
  200. package/src/attach/attach-server-types.ts +82 -0
  201. package/src/attach/attach-server.js +106 -523
  202. package/src/attach/attach-server.ts +158 -0
  203. package/src/attach/index.js +18 -35
  204. package/src/attach/index.ts +18 -0
  205. package/src/attach/protocol.js +95 -184
  206. package/src/attach/protocol.ts +181 -0
  207. package/src/attach/ring-buffer.js +76 -102
  208. package/src/attach/ring-buffer.ts +109 -0
  209. package/src/attach/send-input.js +64 -75
  210. package/src/attach/send-input.ts +94 -0
  211. package/src/attach/socket-discovery.js +164 -218
  212. package/src/attach/socket-discovery.ts +230 -0
  213. package/src/attach/socket-paths.js +42 -61
  214. package/src/attach/socket-paths.ts +81 -0
  215. package/src/claude-credentials.js +51 -54
  216. package/src/claude-credentials.ts +89 -0
  217. package/src/cluster/generated/protocol-schema.ts +1 -1
  218. package/src/cluster/generated/protocol.ts +2 -1
  219. package/src/command-proofs.js +110 -141
  220. package/src/command-proofs.ts +216 -0
  221. package/src/config-router.js +81 -73
  222. package/src/config-router.ts +131 -0
  223. package/src/copy-worker.js +53 -29
  224. package/src/copy-worker.ts +75 -0
  225. package/src/darwin-keychain-boundary.js +80 -111
  226. package/src/darwin-keychain-boundary.ts +148 -0
  227. package/src/guidance-topics.js +4 -5
  228. package/src/guidance-topics.ts +10 -0
  229. package/src/input-helpers.js +33 -54
  230. package/src/input-helpers.ts +58 -0
  231. package/src/ledger-sequence.js +45 -48
  232. package/src/ledger-sequence.ts +63 -0
  233. package/src/legacy-lib/clusters-registry.ts +40 -0
  234. package/src/legacy-lib/completion.ts +148 -0
  235. package/src/legacy-lib/compose-utils.ts +102 -0
  236. package/src/legacy-lib/detached-startup.ts +449 -0
  237. package/src/legacy-lib/docker-config.ts +282 -0
  238. package/src/legacy-lib/docker-env-auth.ts +116 -0
  239. package/src/legacy-lib/git-remote-utils.ts +244 -0
  240. package/src/legacy-lib/id-detector.ts +57 -0
  241. package/src/legacy-lib/js-yaml.d.ts +3 -0
  242. package/src/legacy-lib/omelette.d.ts +15 -0
  243. package/src/legacy-lib/path-check.ts +89 -0
  244. package/src/legacy-lib/process-liveness.ts +36 -0
  245. package/src/legacy-lib/provider-credential-path.ts +57 -0
  246. package/src/legacy-lib/provider-defaults.ts +114 -0
  247. package/src/legacy-lib/provider-detection.ts +67 -0
  248. package/src/legacy-lib/provider-names.ts +126 -0
  249. package/src/legacy-lib/repo-settings.ts +88 -0
  250. package/src/legacy-lib/run-mode.ts +58 -0
  251. package/src/legacy-lib/run-plan.ts +49 -0
  252. package/src/legacy-lib/settings/claude-auth.ts +80 -0
  253. package/src/legacy-lib/settings-defaults.ts +212 -0
  254. package/src/legacy-lib/settings-error.ts +8 -0
  255. package/src/legacy-lib/settings-issue-providers.ts +18 -0
  256. package/src/legacy-lib/settings-models.ts +124 -0
  257. package/src/legacy-lib/settings-storage.ts +277 -0
  258. package/src/legacy-lib/settings-validation.ts +220 -0
  259. package/src/legacy-lib/settings.ts +87 -0
  260. package/src/legacy-lib/setup-apply-types.ts +70 -0
  261. package/src/legacy-lib/setup-apply.ts +456 -0
  262. package/src/legacy-lib/setup-journal.ts +185 -0
  263. package/src/legacy-lib/setup-plan-types.ts +96 -0
  264. package/src/legacy-lib/setup-plan.ts +500 -0
  265. package/src/legacy-lib/setup-undo.ts +142 -0
  266. package/src/legacy-lib/start-cluster-config.ts +124 -0
  267. package/src/legacy-lib/start-cluster-environment.ts +165 -0
  268. package/src/legacy-lib/start-cluster-run-options.ts +279 -0
  269. package/src/legacy-lib/start-cluster.ts +237 -0
  270. package/src/legacy-lib/stream-json-parser.ts +88 -0
  271. package/src/message-buffer.js +55 -71
  272. package/src/message-buffer.ts +107 -0
  273. package/src/message-bus-bridge.js +92 -133
  274. package/src/message-bus-bridge.ts +149 -0
  275. package/src/name-generator-shared.js +220 -0
  276. package/src/name-generator-shared.ts +231 -0
  277. package/src/name-generator.js +8 -217
  278. package/src/name-generator.ts +27 -0
  279. package/src/omp-blob-root.js +83 -64
  280. package/src/omp-blob-root.ts +116 -0
  281. package/src/omp-config-overlay.js +65 -38
  282. package/src/omp-config-overlay.ts +110 -0
  283. package/src/omp-execution-fingerprint.js +38 -43
  284. package/src/omp-execution-fingerprint.ts +92 -0
  285. package/src/omp-session-limits.js +10 -15
  286. package/src/omp-session-limits.ts +53 -0
  287. package/src/omp-session-partition.js +2 -2
  288. package/src/omp-session-verifier.js +1 -1
  289. package/src/orchestrator.js +19 -4
  290. package/src/providers/anthropic/index.js +3 -1
  291. package/src/providers/anthropic/index.ts +13 -0
  292. package/src/providers/capabilities.js +19 -27
  293. package/src/providers/capabilities.ts +44 -0
  294. package/src/providers/google/index.js +3 -1
  295. package/src/providers/google/index.ts +13 -0
  296. package/src/providers/openai/index.js +3 -1
  297. package/src/providers/openai/index.ts +13 -0
  298. package/src/providers/opencode/index.js +3 -1
  299. package/src/providers/opencode/index.ts +13 -0
  300. package/src/quality-gates.js +67 -127
  301. package/src/quality-gates.ts +149 -0
  302. package/src/repo-settings-access.js +40 -0
  303. package/src/repo-settings-access.ts +64 -0
  304. package/src/schemas/sub-cluster.js +127 -183
  305. package/src/schemas/sub-cluster.ts +238 -0
  306. package/src/state-snapshot-normalization.js +224 -0
  307. package/src/state-snapshot-normalization.ts +222 -0
  308. package/src/state-snapshot.js +192 -359
  309. package/src/state-snapshot.ts +291 -0
  310. package/src/state-snapshotter.js +118 -130
  311. package/src/state-snapshotter.ts +167 -0
  312. package/src/sub-cluster-wrapper.js +4 -13
  313. package/src/task-run-model-args.js +87 -124
  314. package/src/task-run-model-args.ts +204 -0
  315. package/src/task-runner.js +5 -25
  316. package/src/task-runner.ts +28 -0
  317. package/src/task-startup-error.js +73 -58
  318. package/src/task-startup-error.ts +126 -0
  319. package/src/template-validation/consensus-gate-contracts.js +2 -0
  320. package/src/template-validation/consensus-gate-contracts.ts +70 -0
  321. package/src/template-validation/consensus-gate-scenarios.js +76 -0
  322. package/src/template-validation/consensus-gate-scenarios.ts +130 -0
  323. package/src/template-validation/consensus-gate-stage.js +34 -0
  324. package/src/template-validation/consensus-gate-stage.ts +56 -0
  325. package/src/template-validation/random-topology-contracts.js +2 -0
  326. package/src/template-validation/random-topology-contracts.ts +54 -0
  327. package/src/template-validation/random-topology-dispatch.js +25 -0
  328. package/src/template-validation/random-topology-dispatch.ts +33 -0
  329. package/src/template-validation/random-topology-message-loop.js +53 -0
  330. package/src/template-validation/random-topology-message-loop.ts +73 -0
  331. package/src/template-validation/random-topology-operations.js +79 -0
  332. package/src/template-validation/random-topology-operations.ts +101 -0
  333. package/src/template-validation/random-topology-runtime.js +25 -0
  334. package/src/template-validation/random-topology-runtime.ts +43 -0
  335. package/src/template-validation/random-topology-scenario.js +52 -0
  336. package/src/template-validation/random-topology-scenario.ts +57 -0
  337. package/src/template-validation/random-topology-schema.js +159 -0
  338. package/src/template-validation/random-topology-schema.ts +190 -0
  339. package/src/template-validation/random-topology-state.js +28 -0
  340. package/src/template-validation/random-topology-state.ts +30 -0
  341. package/src/template-validation/random-topology-trigger-evaluation.js +45 -0
  342. package/src/template-validation/random-topology-trigger-evaluation.ts +65 -0
  343. package/src/template-validation/random-topology-trigger.js +75 -0
  344. package/src/template-validation/random-topology-trigger.ts +88 -0
  345. package/src/template-validation/report-formatter.js +40 -46
  346. package/src/template-validation/report-formatter.ts +101 -0
  347. package/src/template-validation/simulate-consensus-gates.js +111 -302
  348. package/src/template-validation/simulate-consensus-gates.ts +196 -0
  349. package/src/template-validation/simulate-random-topology.js +26 -519
  350. package/src/template-validation/simulate-random-topology.ts +57 -0
  351. package/src/template-validation/simulate-two-stage-validation.js +41 -265
  352. package/src/template-validation/simulate-two-stage-validation.ts +55 -0
  353. package/src/template-validation/simulation-agent-runtime.js +25 -0
  354. package/src/template-validation/simulation-agent-runtime.ts +40 -0
  355. package/src/template-validation/simulation-agent.js +29 -0
  356. package/src/template-validation/simulation-agent.ts +73 -0
  357. package/src/template-validation/simulation-runtime.js +34 -0
  358. package/src/template-validation/simulation-runtime.ts +72 -0
  359. package/src/template-validation/two-stage-contracts.js +2 -0
  360. package/src/template-validation/two-stage-contracts.ts +41 -0
  361. package/src/template-validation/two-stage-inputs.js +21 -0
  362. package/src/template-validation/two-stage-inputs.ts +29 -0
  363. package/src/template-validation/two-stage-results.js +30 -0
  364. package/src/template-validation/two-stage-results.ts +40 -0
  365. package/src/template-validation/two-stage-scenario.js +86 -0
  366. package/src/template-validation/two-stage-scenario.ts +120 -0
  367. package/src/worktree-claude-config.js +182 -220
  368. package/src/worktree-claude-config.ts +272 -0
  369. package/src/worktree-tooling-env.js +103 -125
  370. package/src/worktree-tooling-env.ts +142 -0
  371. package/task-lib/completion.js +2 -3
  372. package/task-lib/completion.ts +9 -0
  373. package/task-lib/config.js +1 -4
  374. package/task-lib/config.ts +11 -0
  375. package/task-lib/name-generator.js +4 -226
  376. package/task-lib/name-generator.ts +11 -0
  377. package/task-lib/omp-session-cleanup.js +1 -1
  378. package/task-lib/omp-storage-root.js +8 -12
  379. package/task-lib/omp-storage-root.ts +62 -0
  380. package/task-lib/process-termination.js +143 -166
  381. package/task-lib/process-termination.ts +268 -0
@@ -1,3 +1,4 @@
1
+ "use strict";
1
2
  /**
2
3
  * `zeroshot setup apply` — writes decisions from #A's plan/decision contract
3
4
  * (lib/setup-plan.js) to global settings, repo-local settings, and the undo
@@ -10,311 +11,313 @@
10
11
  * — a settings key nobody reads is dead config, the exact drift the
11
12
  * canonical-path rule (issue #605) forbids.
12
13
  */
13
-
14
+ // These CommonJS paths intentionally resolve beside the emitted module in lib/.
15
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
14
16
  const { resolveDecisionPath, domainFor, isConsumedPath, CONSUMED_PATHS } = require('./setup-plan');
17
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
15
18
  const { validateMountConfig, validateEnvPassthrough } = require('./docker-config');
19
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
16
20
  const { VALID_PROVIDERS } = require('./provider-names');
17
21
  const VALID_LEVELS = Object.freeze(['level1', 'level2', 'level3']);
18
- const {
19
- loadJournal,
20
- saveJournal,
21
- upsertJournalEntry,
22
- getNestedValue,
23
- setNestedValue,
24
- deepEqual,
25
- } = require('./setup-journal');
26
-
22
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
23
+ const setupJournal = require('./setup-journal');
24
+ const { loadJournal, saveJournal, upsertJournalEntry } = setupJournal;
25
+ const { getNestedValue, setNestedValue, deepEqual } = setupJournal;
27
26
  const SECRET_PATTERN = /token|secret|password|api[_-]?key|credential/i;
28
-
27
+ function includesValue(values, value) {
28
+ return values.includes(value);
29
+ }
29
30
  function assertSecretSafePath(targetPath) {
30
- if (SECRET_PATTERN.test(targetPath)) {
31
- throw new Error(`Refusing to write secret-shaped settings path: ${targetPath}`);
32
- }
31
+ if (SECRET_PATTERN.test(targetPath)) {
32
+ throw new Error(`Refusing to write secret-shaped settings path: ${targetPath}`);
33
+ }
33
34
  }
34
-
35
35
  function domainError(decisionId, value) {
36
- return new Error(
37
- `Invalid value for decision "${decisionId}": expected ${domainFor(decisionId)}, got ${JSON.stringify(value)}`
38
- );
36
+ const expected = domainFor(decisionId);
37
+ const received = JSON.stringify(value);
38
+ return new Error(`Invalid value for decision "${decisionId}": expected ${expected}, got ${received}`);
39
39
  }
40
-
41
- // Resolve a submitted decision into the exact value stored at its canonical
42
- // settings path, validating its decision domain before any write occurs.
43
- function convertDecisionValue({ decisionId, value, globalSettings, deps }) {
44
- switch (decisionId) {
45
- case 'defaultProvider':
46
- if (typeof value !== 'string' || !deps.VALID_PROVIDERS.includes(value)) {
47
- throw domainError(decisionId, value);
48
- }
49
- return value;
50
-
51
- case 'defaultIsolation':
52
- if (!['worktree', 'docker', 'none'].includes(value)) throw domainError(decisionId, value);
53
- return value;
54
-
55
- case 'allowLocalNoIsolation':
56
- if (typeof value !== 'boolean') throw domainError(decisionId, value);
57
- return value;
58
-
59
- case 'defaultDelivery':
60
- if (!['none', 'pr', 'ship'].includes(value)) throw domainError(decisionId, value);
61
- return value;
62
-
63
- case 'defaultIssueSource':
64
- if (typeof value !== 'string' || !deps.listIssueProviders().includes(value)) {
65
- throw domainError(decisionId, value);
66
- }
67
- return value;
68
-
69
- case 'prBase':
70
- if (typeof value !== 'string' || value.trim() === '') throw domainError(decisionId, value);
71
- return value;
72
-
73
- case 'dockerMounts': {
74
- const err = validateMountConfig(value);
75
- if (err) throw new Error(`Invalid value for decision "${decisionId}": ${err}`);
76
- return value;
77
- }
78
-
79
- case 'dockerEnvPassthrough': {
80
- const err = validateEnvPassthrough(value);
81
- if (err) throw new Error(`Invalid value for decision "${decisionId}": ${err}`);
82
- return value;
83
- }
84
-
85
- case 'updatePolicy':
86
- if (!['off', 'notify', 'auto'].includes(value)) throw domainError(decisionId, value);
87
- return value;
88
-
89
- default: {
90
- if (!decisionId.startsWith('providerLevel.')) {
40
+ function convertProviderLevelDecision({ decisionId, value, globalSettings, deps, }) {
41
+ if (!decisionId.startsWith('providerLevel.')) {
91
42
  throw new Error(`Unknown decision ID: ${decisionId}`);
92
- }
93
- if (!value || typeof value !== 'object' || Array.isArray(value)) {
43
+ }
44
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
94
45
  throw domainError(decisionId, value);
95
- }
96
- const keys = Object.keys(value).sort();
97
- const expectedKeys = ['defaultLevel', 'maxLevel', 'minLevel'];
98
- if (
99
- keys.length !== expectedKeys.length ||
46
+ }
47
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
48
+ const decisionValue = value;
49
+ // Preserve Array.prototype.sort's default UTF-16 ordering.
50
+ // eslint-disable-next-line sonarjs/no-alphabetical-sort
51
+ const keys = Object.keys(decisionValue).sort();
52
+ const expectedKeys = ['defaultLevel', 'maxLevel', 'minLevel'];
53
+ if (keys.length !== expectedKeys.length ||
100
54
  keys.some((key, index) => key !== expectedKeys[index]) ||
101
- expectedKeys.some((key) => !VALID_LEVELS.includes(value[key]))
102
- ) {
55
+ expectedKeys.some((key) => !includesValue(VALID_LEVELS, decisionValue[key]))) {
56
+ throw domainError(decisionId, value);
57
+ }
58
+ const providerName = decisionId.slice('providerLevel.'.length);
59
+ if (!deps.VALID_PROVIDERS.includes(providerName))
103
60
  throw domainError(decisionId, value);
104
- }
105
- const providerName = decisionId.slice('providerLevel.'.length);
106
- if (!deps.VALID_PROVIDERS.includes(providerName)) throw domainError(decisionId, value);
107
- const rank = (level) => VALID_LEVELS.indexOf(level);
108
- if (
109
- rank(value.minLevel) > rank(value.defaultLevel) ||
110
- rank(value.defaultLevel) > rank(value.maxLevel)
111
- ) {
61
+ const rank = (level) => VALID_LEVELS.findIndex((item) => item === level);
62
+ if (rank(decisionValue.minLevel) > rank(decisionValue.defaultLevel) ||
63
+ rank(decisionValue.defaultLevel) > rank(decisionValue.maxLevel)) {
112
64
  throw domainError(decisionId, value);
113
- }
114
- const existing = getNestedValue(globalSettings, `providerSettings.${providerName}`) || {};
115
- return { ...existing, ...value };
116
65
  }
117
- }
66
+ const existingValue = getNestedValue(globalSettings, `providerSettings.${providerName}`) || {};
67
+ // Both operands have passed the same object-domain checks used by the legacy implementation.
68
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
69
+ const existing = existingValue;
70
+ return { ...existing, ...decisionValue };
71
+ }
72
+ // Resolve a submitted decision into the exact value stored at its canonical
73
+ // settings path, validating its decision domain before any write occurs.
74
+ function convertDecisionValue({ decisionId, value, globalSettings, deps, }) {
75
+ switch (decisionId) {
76
+ case 'defaultProvider':
77
+ if (typeof value !== 'string' || !deps.VALID_PROVIDERS.includes(value)) {
78
+ throw domainError(decisionId, value);
79
+ }
80
+ return value;
81
+ case 'defaultIsolation':
82
+ if (!includesValue(['worktree', 'docker', 'none'], value)) {
83
+ throw domainError(decisionId, value);
84
+ }
85
+ return value;
86
+ case 'allowLocalNoIsolation':
87
+ if (typeof value !== 'boolean')
88
+ throw domainError(decisionId, value);
89
+ return value;
90
+ case 'defaultDelivery':
91
+ if (!includesValue(['none', 'pr', 'ship'], value))
92
+ throw domainError(decisionId, value);
93
+ return value;
94
+ case 'defaultIssueSource':
95
+ if (typeof value !== 'string' || !deps.listIssueProviders().includes(value)) {
96
+ throw domainError(decisionId, value);
97
+ }
98
+ return value;
99
+ case 'prBase':
100
+ if (typeof value !== 'string' || value.trim() === '')
101
+ throw domainError(decisionId, value);
102
+ return value;
103
+ case 'dockerMounts': {
104
+ const err = validateMountConfig(value);
105
+ if (err)
106
+ throw new Error(`Invalid value for decision "${decisionId}": ${err}`);
107
+ return value;
108
+ }
109
+ case 'dockerEnvPassthrough': {
110
+ const err = validateEnvPassthrough(value);
111
+ if (err)
112
+ throw new Error(`Invalid value for decision "${decisionId}": ${err}`);
113
+ return value;
114
+ }
115
+ case 'updatePolicy':
116
+ if (!includesValue(['off', 'notify', 'auto'], value))
117
+ throw domainError(decisionId, value);
118
+ return value;
119
+ default:
120
+ return convertProviderLevelDecision({ decisionId, value, globalSettings, deps });
121
+ }
118
122
  }
119
-
120
123
  function defaultApplyDeps() {
121
- const fs = require('fs');
122
- const { loadSettings, mutateSettings } = require('./settings');
123
- const { readRepoSettings, writeRepoSettings } = require('./repo-settings');
124
- const { checkGhAuth } = require('../src/preflight');
125
- const { listProviders: listIssueProviders } = require('../src/issue-providers');
126
-
127
- return {
128
- readFile: (filePath) => fs.readFileSync(filePath, 'utf8'),
129
- loadSettings,
130
- mutateSettings,
131
- readRepoSettings,
132
- writeRepoSettings,
133
- checkGhAuth,
134
- listIssueProviders,
135
- VALID_PROVIDERS,
136
- now: () => new Date().toISOString(),
137
- };
124
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
125
+ const fs = require('fs');
126
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
127
+ const { loadSettings, mutateSettings } = require('./settings');
128
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
129
+ const { readRepoSettings, writeRepoSettings } = require('./repo-settings');
130
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
131
+ const { checkGhAuth } = require('../src/preflight');
132
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
133
+ const { listProviders: listIssueProviders } = require('../src/issue-providers');
134
+ return {
135
+ readFile: (filePath) => fs.readFileSync(filePath, 'utf8'),
136
+ loadSettings,
137
+ mutateSettings,
138
+ readRepoSettings,
139
+ writeRepoSettings,
140
+ checkGhAuth,
141
+ listIssueProviders,
142
+ VALID_PROVIDERS,
143
+ now: () => new Date().toISOString(),
144
+ };
138
145
  }
139
-
140
146
  // Phase 1: resolve + validate EVERY input decision before any write happens
141
147
  // (fail-closed — a single bad decisionId or out-of-domain value rejects the
142
148
  // whole request, never a partial apply).
143
149
  function resolveAndValidateDecisions(input, globalSettings, deps) {
144
- const resolved = [];
145
- for (const [decisionId, value] of Object.entries(input)) {
146
- const target = resolveDecisionPath(decisionId);
147
- if (!target) {
148
- throw new Error(`Unknown decision ID: ${decisionId}`);
150
+ const resolved = [];
151
+ for (const [decisionId, value] of Object.entries(input)) {
152
+ const target = resolveDecisionPath(decisionId);
153
+ if (!target) {
154
+ throw new Error(`Unknown decision ID: ${decisionId}`);
155
+ }
156
+ assertSecretSafePath(target.path);
157
+ const writeValue = convertDecisionValue({ decisionId, value, globalSettings, deps });
158
+ resolved.push({ decisionId, target, inputValue: value, writeValue });
149
159
  }
150
- assertSecretSafePath(target.path);
151
- const writeValue = convertDecisionValue({ decisionId, value, globalSettings, deps });
152
- resolved.push({ decisionId, target, inputValue: value, writeValue });
153
- }
154
- return resolved;
160
+ return resolved;
155
161
  }
156
-
157
162
  // Decides the outcome for a single resolved decision: a skip (with reason)
158
163
  // or the write to perform. Returns the write descriptor rather than mutating
159
164
  // anything, so the caller controls when settings objects/journal are touched.
160
- function resolveDecisionOutcome(
161
- { decisionId, target, inputValue, writeValue },
162
- { globalSettings, repoSettings, allowRiskyDefaults }
163
- ) {
164
- const settingsObj = target.scope === 'repo' ? repoSettings : globalSettings;
165
- const currentValue = getNestedValue(settingsObj, target.path) ?? null;
166
- const base = { decisionId, from: currentValue, to: writeValue };
167
-
168
- if (decisionId === 'defaultDelivery' && inputValue === 'ship' && !allowRiskyDefaults) {
169
- return { result: { ...base, applied: false, skippedReason: 'requires-explicit-opt-in' } };
170
- }
171
- if (!isConsumedPath(target.scope, target.path)) {
172
- return { result: { ...base, applied: false, skippedReason: 'no-consumer' } };
173
- }
174
- if (deepEqual(currentValue, writeValue)) {
175
- return { result: { ...base, applied: false, skippedReason: 'unchanged' } };
176
- }
177
-
178
- return {
179
- result: { ...base, applied: true },
180
- write: {
181
- settingsObj,
182
- scope: target.scope,
183
- path: target.path,
184
- writeValue,
185
- priorValue: currentValue,
186
- },
187
- };
165
+ function resolveDecisionOutcome(decision, context) {
166
+ const { decisionId, target, inputValue, writeValue } = decision;
167
+ const { globalSettings, repoSettings, allowRiskyDefaults } = context;
168
+ const settingsObj = target.scope === 'repo' ? repoSettings : globalSettings;
169
+ const currentValue = getNestedValue(settingsObj, target.path) ?? null;
170
+ const base = { decisionId, from: currentValue, to: writeValue };
171
+ if (decisionId === 'defaultDelivery' && inputValue === 'ship' && !allowRiskyDefaults) {
172
+ return { result: { ...base, applied: false, skippedReason: 'requires-explicit-opt-in' } };
173
+ }
174
+ if (!isConsumedPath(target.scope, target.path)) {
175
+ return { result: { ...base, applied: false, skippedReason: 'no-consumer' } };
176
+ }
177
+ if (deepEqual(currentValue, writeValue)) {
178
+ return { result: { ...base, applied: false, skippedReason: 'unchanged' } };
179
+ }
180
+ return {
181
+ result: { ...base, applied: true },
182
+ write: {
183
+ settingsObj,
184
+ scope: target.scope,
185
+ path: target.path,
186
+ writeValue,
187
+ priorValue: currentValue,
188
+ },
189
+ };
188
190
  }
189
-
190
191
  // Applies one decision's write to its in-memory settings object and journals
191
192
  // it (deferred persistence — the caller flushes to disk once at the end).
192
- function applyWrite(write, { repoRoot, journal, deps }) {
193
- setNestedValue(write.settingsObj, write.path, write.writeValue);
194
- upsertJournalEntry(journal, {
195
- scope: write.scope,
196
- path: write.path,
197
- repoRoot: write.scope === 'repo' ? repoRoot : null,
198
- priorValue: write.priorValue,
199
- appliedValue: write.writeValue,
200
- appliedAt: deps.now(),
201
- });
202
- return write.scope;
193
+ function applyWrite(write, context) {
194
+ const { repoRoot, journal, deps } = context;
195
+ setNestedValue(write.settingsObj, write.path, write.writeValue);
196
+ upsertJournalEntry(journal, {
197
+ scope: write.scope,
198
+ path: write.path,
199
+ repoRoot: write.scope === 'repo' ? repoRoot : null,
200
+ priorValue: write.priorValue,
201
+ appliedValue: write.writeValue,
202
+ appliedAt: deps.now(),
203
+ });
204
+ return write.scope;
203
205
  }
204
-
205
206
  // Phase 2: resolve each global outcome against the locked, freshly read state.
206
207
  // Repo-local settings remain intentionally outside the global settings lock.
207
- function writeResolvedDecisions(
208
- resolved,
209
- { repoSettings, repoRoot, journal, allowRiskyDefaults, deps }
210
- ) {
211
- const resultsById = new Map();
212
- let repoDirty = false;
213
- let globalDirty = false;
214
- const globalDecisions = resolved.filter((decision) => decision.target.scope === 'global');
215
-
216
- if (globalDecisions.length > 0) {
217
- const globalResults = deps.mutateSettings((freshGlobalSettings) => {
218
- const results = [];
219
- for (const decision of globalDecisions) {
220
- const freshDecision = {
221
- ...decision,
222
- writeValue: convertDecisionValue({
223
- decisionId: decision.decisionId,
224
- value: decision.inputValue,
225
- globalSettings: freshGlobalSettings,
226
- deps,
227
- }),
228
- };
229
- const { result, write } = resolveDecisionOutcome(freshDecision, {
230
- globalSettings: freshGlobalSettings,
231
- repoSettings,
232
- allowRiskyDefaults,
208
+ function writeResolvedDecisions(resolved, context) {
209
+ const { repoSettings, repoRoot, journal, allowRiskyDefaults, deps } = context;
210
+ const resultsById = new Map();
211
+ let repoDirty = false;
212
+ let globalDirty = false;
213
+ const globalDecisions = resolved.filter((decision) => decision.target.scope === 'global');
214
+ if (globalDecisions.length > 0) {
215
+ const globalResults = deps.mutateSettings((freshGlobalSettings) => {
216
+ const results = [];
217
+ for (const decision of globalDecisions) {
218
+ const freshDecision = {
219
+ ...decision,
220
+ writeValue: convertDecisionValue({
221
+ decisionId: decision.decisionId,
222
+ value: decision.inputValue,
223
+ globalSettings: freshGlobalSettings,
224
+ deps,
225
+ }),
226
+ };
227
+ const { result, write } = resolveDecisionOutcome(freshDecision, {
228
+ globalSettings: freshGlobalSettings,
229
+ repoSettings,
230
+ allowRiskyDefaults,
231
+ });
232
+ results.push(result);
233
+ if (write) {
234
+ applyWrite(write, { repoRoot, journal, deps });
235
+ globalDirty = true;
236
+ }
237
+ }
238
+ return results;
233
239
  });
234
- results.push(result);
235
- if (write) {
236
- applyWrite(write, { repoRoot, journal, deps });
237
- globalDirty = true;
238
- }
239
- }
240
- return results;
241
- });
242
- for (const result of globalResults) resultsById.set(result.decisionId, result);
243
- }
244
-
245
- for (const decision of resolved.filter((item) => item.target.scope === 'repo')) {
246
- const { result, write } = resolveDecisionOutcome(decision, {
247
- globalSettings: {},
248
- repoSettings,
249
- allowRiskyDefaults,
240
+ for (const result of globalResults)
241
+ resultsById.set(result.decisionId, result);
242
+ }
243
+ for (const decision of resolved.filter((item) => item.target.scope === 'repo')) {
244
+ const { result, write } = resolveDecisionOutcome(decision, {
245
+ globalSettings: {},
246
+ repoSettings,
247
+ allowRiskyDefaults,
248
+ });
249
+ resultsById.set(result.decisionId, result);
250
+ if (!write)
251
+ continue;
252
+ applyWrite(write, { repoRoot, journal, deps });
253
+ repoDirty = true;
254
+ }
255
+ if (repoDirty)
256
+ deps.writeRepoSettings(repoRoot, repoSettings);
257
+ if (globalDirty || repoDirty)
258
+ saveJournal(journal);
259
+ return resolved.map((decision) => {
260
+ const result = resultsById.get(decision.decisionId);
261
+ if (!result)
262
+ throw new Error(`Missing apply result for decision: ${decision.decisionId}`);
263
+ return result;
250
264
  });
251
- resultsById.set(result.decisionId, result);
252
- if (!write) continue;
253
- applyWrite(write, { repoRoot, journal, deps });
254
- repoDirty = true;
255
- }
256
-
257
- if (repoDirty) deps.writeRepoSettings(repoRoot, repoSettings);
258
- if (globalDirty || repoDirty) saveJournal(journal);
259
- return resolved.map((decision) => resultsById.get(decision.decisionId));
260
265
  }
261
-
262
266
  function assertDecisionObject(decisions, label) {
263
- if (!decisions || typeof decisions !== 'object' || Array.isArray(decisions)) {
264
- throw new Error(`${label} must be a JSON object of { decisionId: value }`);
265
- }
267
+ if (!decisions || typeof decisions !== 'object' || Array.isArray(decisions)) {
268
+ throw new Error(`${label} must be a JSON object of { decisionId: value }`);
269
+ }
266
270
  }
267
-
268
271
  /** Apply an in-memory decision object without temporary files. */
269
- function applyDecisionValues({ decisions, cwd, allowRiskyDefaults = false, deps = {} }) {
270
- assertDecisionObject(decisions, 'Decisions');
271
- const resolvedDeps = { ...defaultApplyDeps(), ...deps };
272
- const globalSettings = resolvedDeps.loadSettings();
273
- const { repoRoot, settings: repoSettingsRaw } = resolvedDeps.readRepoSettings(cwd);
274
- const repoSettings = repoSettingsRaw || {};
275
- const resolved = resolveAndValidateDecisions(decisions, globalSettings, resolvedDeps);
276
- const results = writeResolvedDecisions(resolved, {
277
- repoSettings,
278
- repoRoot,
279
- journal: loadJournal(),
280
- allowRiskyDefaults,
281
- deps: resolvedDeps,
282
- });
283
-
284
- const issueSourceApplied = results.find(
285
- (result) => result.decisionId === 'defaultIssueSource' && result.applied
286
- );
287
- if (issueSourceApplied?.to === 'github') {
288
- const auth = resolvedDeps.checkGhAuth();
289
- if (!auth?.authenticated) console.log('Run: gh auth login');
290
- }
291
- return results;
272
+ function applyDecisionValues({ decisions, cwd, allowRiskyDefaults = false, deps = {}, }) {
273
+ assertDecisionObject(decisions, 'Decisions');
274
+ const resolvedDeps = { ...defaultApplyDeps(), ...deps };
275
+ const globalSettings = resolvedDeps.loadSettings();
276
+ const { repoRoot, settings: repoSettingsRaw } = resolvedDeps.readRepoSettings(cwd);
277
+ const repoSettings = repoSettingsRaw || {};
278
+ const resolved = resolveAndValidateDecisions(decisions, globalSettings, resolvedDeps);
279
+ const results = writeResolvedDecisions(resolved, {
280
+ repoSettings,
281
+ repoRoot,
282
+ journal: loadJournal(),
283
+ allowRiskyDefaults,
284
+ deps: resolvedDeps,
285
+ });
286
+ const issueSourceApplied = results.find((result) => result.decisionId === 'defaultIssueSource' && result.applied);
287
+ if (issueSourceApplied?.to === 'github') {
288
+ const auth = resolvedDeps.checkGhAuth();
289
+ if (!auth?.authenticated)
290
+ console.log('Run: gh auth login');
291
+ }
292
+ return results;
292
293
  }
293
-
294
294
  /** Apply a decisions JSON file through the shared object API. */
295
- function applyDecisions({ decisionsPath, cwd, allowRiskyDefaults = false, deps = {} }) {
296
- const resolvedDeps = { ...defaultApplyDeps(), ...deps };
297
- let decisions;
298
- try {
299
- decisions = JSON.parse(resolvedDeps.readFile(decisionsPath));
300
- } catch (error) {
301
- throw new Error(`Failed to read decisions file "${decisionsPath}": ${error.message}`);
302
- }
303
- assertDecisionObject(decisions, 'Decisions file');
304
- return applyDecisionValues({
305
- decisions,
306
- cwd,
307
- allowRiskyDefaults,
308
- deps: resolvedDeps,
309
- });
295
+ function applyDecisions({ decisionsPath, cwd, allowRiskyDefaults = false, deps = {}, }) {
296
+ const resolvedDeps = { ...defaultApplyDeps(), ...deps };
297
+ let decisions;
298
+ try {
299
+ decisions = JSON.parse(resolvedDeps.readFile(decisionsPath));
300
+ }
301
+ catch (error) {
302
+ const message = typeof error === 'object' && error !== null && 'message' in error
303
+ ? error.message
304
+ : undefined;
305
+ throw new Error(`Failed to read decisions file "${decisionsPath}": ${String(message)}`);
306
+ }
307
+ assertDecisionObject(decisions, 'Decisions file');
308
+ return applyDecisionValues({
309
+ decisions,
310
+ cwd,
311
+ allowRiskyDefaults,
312
+ deps: resolvedDeps,
313
+ });
310
314
  }
311
-
312
315
  module.exports = {
313
- applyDecisions,
314
- applyDecisionValues,
315
- resolveAndValidateDecisions,
316
- writeResolvedDecisions,
317
- assertSecretSafePath,
318
- isConsumedPath,
319
- CONSUMED_PATHS,
316
+ applyDecisions,
317
+ applyDecisionValues,
318
+ resolveAndValidateDecisions,
319
+ writeResolvedDecisions,
320
+ assertSecretSafePath,
321
+ isConsumedPath,
322
+ CONSUMED_PATHS,
320
323
  };
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Undo journal for `zeroshot setup apply` / `zeroshot setup undo`.
3
+ *
4
+ * One journal entry per setting this setup owns: { scope, path, repoRoot,
5
+ * priorValue, appliedValue, appliedAt }. `priorValue: null` means the key
6
+ * did not exist before apply, so undo deletes it rather than restoring it.
7
+ * Shared by lib/setup-apply.js (writer) and lib/setup-undo.js (reader) so the
8
+ * nested-path mutation and equality semantics can't drift between the two.
9
+ */
10
+ interface JournalEntry {
11
+ readonly appliedAt: string;
12
+ readonly appliedValue: unknown;
13
+ readonly path: string;
14
+ readonly priorValue: unknown;
15
+ readonly repoRoot: string | null;
16
+ readonly scope: string;
17
+ readonly [key: string]: unknown;
18
+ }
19
+ interface SetupJournal {
20
+ entries: JournalEntry[];
21
+ version: number;
22
+ [key: string]: unknown;
23
+ }
24
+ declare function getJournalPath(): string;
25
+ declare function loadJournal(): SetupJournal;
26
+ declare function saveJournal(journal: SetupJournal): void;
27
+ declare function upsertJournalEntry(journal: SetupJournal, entry: JournalEntry): void;
28
+ declare function setNestedValue(target: Record<string, unknown>, pathStr: string, value: unknown): void;
29
+ declare function deleteNestedKey(target: Record<string, unknown>, pathStr: string): void;
30
+ declare function deepEqual(left: unknown, right: unknown): boolean;
31
+ declare const _default: {
32
+ getJournalPath: typeof getJournalPath;
33
+ loadJournal: typeof loadJournal;
34
+ saveJournal: typeof saveJournal;
35
+ upsertJournalEntry: typeof upsertJournalEntry;
36
+ getNestedValue: (source: Record<string, unknown>, pathStr: string) => unknown;
37
+ setNestedValue: typeof setNestedValue;
38
+ deleteNestedKey: typeof deleteNestedKey;
39
+ deepEqual: typeof deepEqual;
40
+ };
41
+ export = _default;