looply-cli 0.0.0-stage → 0.3.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 (793) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +137 -3
  3. package/dist/.src-hash +1 -0
  4. package/dist/acceptance-observe.d.ts +108 -0
  5. package/dist/acceptance-observe.d.ts.map +1 -0
  6. package/dist/acceptance-observe.js +152 -0
  7. package/dist/acceptance-observe.js.map +1 -0
  8. package/dist/agent-cmd.d.ts +131 -0
  9. package/dist/agent-cmd.d.ts.map +1 -0
  10. package/dist/agent-cmd.js +154 -0
  11. package/dist/agent-cmd.js.map +1 -0
  12. package/dist/agent-contained.d.ts +114 -0
  13. package/dist/agent-contained.d.ts.map +1 -0
  14. package/dist/agent-contained.js +292 -0
  15. package/dist/agent-contained.js.map +1 -0
  16. package/dist/agent-driver.d.ts +130 -0
  17. package/dist/agent-driver.d.ts.map +1 -0
  18. package/dist/agent-driver.js +170 -0
  19. package/dist/agent-driver.js.map +1 -0
  20. package/dist/agent-envelope.d.ts +94 -0
  21. package/dist/agent-envelope.d.ts.map +1 -0
  22. package/dist/agent-envelope.js +214 -0
  23. package/dist/agent-envelope.js.map +1 -0
  24. package/dist/agent-exec.d.ts +182 -0
  25. package/dist/agent-exec.d.ts.map +1 -0
  26. package/dist/agent-exec.js +125 -0
  27. package/dist/agent-exec.js.map +1 -0
  28. package/dist/agent-runtime.d.ts +23 -0
  29. package/dist/agent-runtime.d.ts.map +1 -0
  30. package/dist/agent-runtime.js +143 -0
  31. package/dist/agent-runtime.js.map +1 -0
  32. package/dist/approval-gate-read.d.ts +66 -0
  33. package/dist/approval-gate-read.d.ts.map +1 -0
  34. package/dist/approval-gate-read.js +138 -0
  35. package/dist/approval-gate-read.js.map +1 -0
  36. package/dist/approval-resolution.d.ts +87 -0
  37. package/dist/approval-resolution.d.ts.map +1 -0
  38. package/dist/approval-resolution.js +100 -0
  39. package/dist/approval-resolution.js.map +1 -0
  40. package/dist/approval-resumes.d.ts +102 -0
  41. package/dist/approval-resumes.d.ts.map +1 -0
  42. package/dist/approval-resumes.js +167 -0
  43. package/dist/approval-resumes.js.map +1 -0
  44. package/dist/ask-brain.d.ts +167 -0
  45. package/dist/ask-brain.d.ts.map +1 -0
  46. package/dist/ask-brain.js +355 -0
  47. package/dist/ask-brain.js.map +1 -0
  48. package/dist/autonomy-authority.d.ts +80 -0
  49. package/dist/autonomy-authority.d.ts.map +1 -0
  50. package/dist/autonomy-authority.js +82 -0
  51. package/dist/autonomy-authority.js.map +1 -0
  52. package/dist/autonomy-controller.d.ts +321 -0
  53. package/dist/autonomy-controller.d.ts.map +1 -0
  54. package/dist/autonomy-controller.js +517 -0
  55. package/dist/autonomy-controller.js.map +1 -0
  56. package/dist/autonomy-store.d.ts +327 -0
  57. package/dist/autonomy-store.d.ts.map +1 -0
  58. package/dist/autonomy-store.js +581 -0
  59. package/dist/autonomy-store.js.map +1 -0
  60. package/dist/autonomy-tick.d.ts +257 -0
  61. package/dist/autonomy-tick.d.ts.map +1 -0
  62. package/dist/autonomy-tick.js +616 -0
  63. package/dist/autonomy-tick.js.map +1 -0
  64. package/dist/bin.d.ts +3 -0
  65. package/dist/bin.d.ts.map +1 -0
  66. package/dist/bin.js +2727 -0
  67. package/dist/bin.js.map +1 -0
  68. package/dist/brain-advice.d.ts +21 -0
  69. package/dist/brain-advice.d.ts.map +1 -0
  70. package/dist/brain-advice.js +51 -0
  71. package/dist/brain-advice.js.map +1 -0
  72. package/dist/candidate-replay-runtime.d.ts +125 -0
  73. package/dist/candidate-replay-runtime.d.ts.map +1 -0
  74. package/dist/candidate-replay-runtime.js +188 -0
  75. package/dist/candidate-replay-runtime.js.map +1 -0
  76. package/dist/checkout-carry.d.ts +76 -0
  77. package/dist/checkout-carry.d.ts.map +1 -0
  78. package/dist/checkout-carry.js +125 -0
  79. package/dist/checkout-carry.js.map +1 -0
  80. package/dist/citation-readers.d.ts +26 -0
  81. package/dist/citation-readers.d.ts.map +1 -0
  82. package/dist/citation-readers.js +102 -0
  83. package/dist/citation-readers.js.map +1 -0
  84. package/dist/command-receipts.d.ts +79 -0
  85. package/dist/command-receipts.d.ts.map +1 -0
  86. package/dist/command-receipts.js +143 -0
  87. package/dist/command-receipts.js.map +1 -0
  88. package/dist/command-runner.d.ts +32 -0
  89. package/dist/command-runner.d.ts.map +1 -0
  90. package/dist/command-runner.js +108 -0
  91. package/dist/command-runner.js.map +1 -0
  92. package/dist/compatible-sets.d.ts +67 -0
  93. package/dist/compatible-sets.d.ts.map +1 -0
  94. package/dist/compatible-sets.js +81 -0
  95. package/dist/compatible-sets.js.map +1 -0
  96. package/dist/compile-check.d.ts +31 -0
  97. package/dist/compile-check.d.ts.map +1 -0
  98. package/dist/compile-check.js +34 -0
  99. package/dist/compile-check.js.map +1 -0
  100. package/dist/compile-store.d.ts +16 -0
  101. package/dist/compile-store.d.ts.map +1 -0
  102. package/dist/compile-store.js +21 -0
  103. package/dist/compile-store.js.map +1 -0
  104. package/dist/completion.d.ts +106 -0
  105. package/dist/completion.d.ts.map +1 -0
  106. package/dist/completion.js +131 -0
  107. package/dist/completion.js.map +1 -0
  108. package/dist/config.d.ts +549 -0
  109. package/dist/config.d.ts.map +1 -0
  110. package/dist/config.js +763 -0
  111. package/dist/config.js.map +1 -0
  112. package/dist/control-file.d.ts +142 -0
  113. package/dist/control-file.d.ts.map +1 -0
  114. package/dist/control-file.js +144 -0
  115. package/dist/control-file.js.map +1 -0
  116. package/dist/coordinator-state.d.ts +131 -0
  117. package/dist/coordinator-state.d.ts.map +1 -0
  118. package/dist/coordinator-state.js +380 -0
  119. package/dist/coordinator-state.js.map +1 -0
  120. package/dist/coordinator.d.ts +95 -0
  121. package/dist/coordinator.d.ts.map +1 -0
  122. package/dist/coordinator.js +97 -0
  123. package/dist/coordinator.js.map +1 -0
  124. package/dist/cursor-store.d.ts +53 -0
  125. package/dist/cursor-store.d.ts.map +1 -0
  126. package/dist/cursor-store.js +98 -0
  127. package/dist/cursor-store.js.map +1 -0
  128. package/dist/daemon-cmd.d.ts +239 -0
  129. package/dist/daemon-cmd.d.ts.map +1 -0
  130. package/dist/daemon-cmd.js +1751 -0
  131. package/dist/daemon-cmd.js.map +1 -0
  132. package/dist/daemon-lock.d.ts +140 -0
  133. package/dist/daemon-lock.d.ts.map +1 -0
  134. package/dist/daemon-lock.js +352 -0
  135. package/dist/daemon-lock.js.map +1 -0
  136. package/dist/daemon-recovery.d.ts +78 -0
  137. package/dist/daemon-recovery.d.ts.map +1 -0
  138. package/dist/daemon-recovery.js +161 -0
  139. package/dist/daemon-recovery.js.map +1 -0
  140. package/dist/daemon.d.ts +368 -0
  141. package/dist/daemon.d.ts.map +1 -0
  142. package/dist/daemon.js +601 -0
  143. package/dist/daemon.js.map +1 -0
  144. package/dist/declared-response-shape.d.ts +93 -0
  145. package/dist/declared-response-shape.d.ts.map +1 -0
  146. package/dist/declared-response-shape.js +200 -0
  147. package/dist/declared-response-shape.js.map +1 -0
  148. package/dist/declared-surfaces.d.ts +16 -0
  149. package/dist/declared-surfaces.d.ts.map +1 -0
  150. package/dist/declared-surfaces.js +19 -0
  151. package/dist/declared-surfaces.js.map +1 -0
  152. package/dist/depends-review.d.ts +113 -0
  153. package/dist/depends-review.d.ts.map +1 -0
  154. package/dist/depends-review.js +110 -0
  155. package/dist/depends-review.js.map +1 -0
  156. package/dist/doctor.d.ts +91 -0
  157. package/dist/doctor.d.ts.map +1 -0
  158. package/dist/doctor.js +71 -0
  159. package/dist/doctor.js.map +1 -0
  160. package/dist/edge-approval.d.ts +105 -0
  161. package/dist/edge-approval.d.ts.map +1 -0
  162. package/dist/edge-approval.js +100 -0
  163. package/dist/edge-approval.js.map +1 -0
  164. package/dist/evidence-cache.d.ts +45 -0
  165. package/dist/evidence-cache.d.ts.map +1 -0
  166. package/dist/evidence-cache.js +90 -0
  167. package/dist/evidence-cache.js.map +1 -0
  168. package/dist/evidence-cmd.d.ts +133 -0
  169. package/dist/evidence-cmd.d.ts.map +1 -0
  170. package/dist/evidence-cmd.js +347 -0
  171. package/dist/evidence-cmd.js.map +1 -0
  172. package/dist/evidence-facts.d.ts +40 -0
  173. package/dist/evidence-facts.d.ts.map +1 -0
  174. package/dist/evidence-facts.js +114 -0
  175. package/dist/evidence-facts.js.map +1 -0
  176. package/dist/exclusive-lock.d.ts +52 -0
  177. package/dist/exclusive-lock.d.ts.map +1 -0
  178. package/dist/exclusive-lock.js +150 -0
  179. package/dist/exclusive-lock.js.map +1 -0
  180. package/dist/exec-domains.d.ts +140 -0
  181. package/dist/exec-domains.d.ts.map +1 -0
  182. package/dist/exec-domains.js +287 -0
  183. package/dist/exec-domains.js.map +1 -0
  184. package/dist/exemption-store.d.ts +197 -0
  185. package/dist/exemption-store.d.ts.map +1 -0
  186. package/dist/exemption-store.js +266 -0
  187. package/dist/exemption-store.js.map +1 -0
  188. package/dist/explicit-start-gate.d.ts +96 -0
  189. package/dist/explicit-start-gate.d.ts.map +1 -0
  190. package/dist/explicit-start-gate.js +103 -0
  191. package/dist/explicit-start-gate.js.map +1 -0
  192. package/dist/fs-trouble.d.ts +70 -0
  193. package/dist/fs-trouble.d.ts.map +1 -0
  194. package/dist/fs-trouble.js +98 -0
  195. package/dist/fs-trouble.js.map +1 -0
  196. package/dist/gate.d.ts +278 -0
  197. package/dist/gate.d.ts.map +1 -0
  198. package/dist/gate.js +278 -0
  199. package/dist/gate.js.map +1 -0
  200. package/dist/git-driver.d.ts +519 -0
  201. package/dist/git-driver.d.ts.map +1 -0
  202. package/dist/git-driver.js +900 -0
  203. package/dist/git-driver.js.map +1 -0
  204. package/dist/git-push-executor.d.ts +41 -0
  205. package/dist/git-push-executor.d.ts.map +1 -0
  206. package/dist/git-push-executor.js +142 -0
  207. package/dist/git-push-executor.js.map +1 -0
  208. package/dist/glob.d.ts +26 -0
  209. package/dist/glob.d.ts.map +1 -0
  210. package/dist/glob.js +93 -0
  211. package/dist/glob.js.map +1 -0
  212. package/dist/goal-adaptive.d.ts +295 -0
  213. package/dist/goal-adaptive.d.ts.map +1 -0
  214. package/dist/goal-adaptive.js +393 -0
  215. package/dist/goal-adaptive.js.map +1 -0
  216. package/dist/goal-compile.d.ts +342 -0
  217. package/dist/goal-compile.d.ts.map +1 -0
  218. package/dist/goal-compile.js +444 -0
  219. package/dist/goal-compile.js.map +1 -0
  220. package/dist/goal-depends-executor.d.ts +55 -0
  221. package/dist/goal-depends-executor.d.ts.map +1 -0
  222. package/dist/goal-depends-executor.js +202 -0
  223. package/dist/goal-depends-executor.js.map +1 -0
  224. package/dist/goal-execution-evidence.d.ts +135 -0
  225. package/dist/goal-execution-evidence.d.ts.map +1 -0
  226. package/dist/goal-execution-evidence.js +159 -0
  227. package/dist/goal-execution-evidence.js.map +1 -0
  228. package/dist/goal-gap.d.ts +140 -0
  229. package/dist/goal-gap.d.ts.map +1 -0
  230. package/dist/goal-gap.js +197 -0
  231. package/dist/goal-gap.js.map +1 -0
  232. package/dist/goal-met-target.d.ts +98 -0
  233. package/dist/goal-met-target.d.ts.map +1 -0
  234. package/dist/goal-met-target.js +92 -0
  235. package/dist/goal-met-target.js.map +1 -0
  236. package/dist/goal-ownership.d.ts +416 -0
  237. package/dist/goal-ownership.d.ts.map +1 -0
  238. package/dist/goal-ownership.js +576 -0
  239. package/dist/goal-ownership.js.map +1 -0
  240. package/dist/goal-runs.d.ts +82 -0
  241. package/dist/goal-runs.d.ts.map +1 -0
  242. package/dist/goal-runs.js +120 -0
  243. package/dist/goal-runs.js.map +1 -0
  244. package/dist/goal-store.d.ts +146 -0
  245. package/dist/goal-store.d.ts.map +1 -0
  246. package/dist/goal-store.js +294 -0
  247. package/dist/goal-store.js.map +1 -0
  248. package/dist/goal-view.d.ts +156 -0
  249. package/dist/goal-view.d.ts.map +1 -0
  250. package/dist/goal-view.js +499 -0
  251. package/dist/goal-view.js.map +1 -0
  252. package/dist/governed-approvals.d.ts +152 -0
  253. package/dist/governed-approvals.d.ts.map +1 -0
  254. package/dist/governed-approvals.js +246 -0
  255. package/dist/governed-approvals.js.map +1 -0
  256. package/dist/governed-broker.d.ts +169 -0
  257. package/dist/governed-broker.d.ts.map +1 -0
  258. package/dist/governed-broker.js +196 -0
  259. package/dist/governed-broker.js.map +1 -0
  260. package/dist/governed-run.d.ts +220 -0
  261. package/dist/governed-run.d.ts.map +1 -0
  262. package/dist/governed-run.js +406 -0
  263. package/dist/governed-run.js.map +1 -0
  264. package/dist/grant-reconcile.d.ts +63 -0
  265. package/dist/grant-reconcile.d.ts.map +1 -0
  266. package/dist/grant-reconcile.js +121 -0
  267. package/dist/grant-reconcile.js.map +1 -0
  268. package/dist/index-for-head.d.ts +56 -0
  269. package/dist/index-for-head.d.ts.map +1 -0
  270. package/dist/index-for-head.js +103 -0
  271. package/dist/index-for-head.js.map +1 -0
  272. package/dist/index.d.ts +39 -0
  273. package/dist/index.d.ts.map +1 -0
  274. package/dist/index.js +55 -0
  275. package/dist/index.js.map +1 -0
  276. package/dist/init-detect.d.ts +39 -0
  277. package/dist/init-detect.d.ts.map +1 -0
  278. package/dist/init-detect.js +188 -0
  279. package/dist/init-detect.js.map +1 -0
  280. package/dist/integration-deps.d.ts +62 -0
  281. package/dist/integration-deps.d.ts.map +1 -0
  282. package/dist/integration-deps.js +251 -0
  283. package/dist/integration-deps.js.map +1 -0
  284. package/dist/integration-runtime.d.ts +458 -0
  285. package/dist/integration-runtime.d.ts.map +1 -0
  286. package/dist/integration-runtime.js +681 -0
  287. package/dist/integration-runtime.js.map +1 -0
  288. package/dist/integration.d.ts +45 -0
  289. package/dist/integration.d.ts.map +1 -0
  290. package/dist/integration.js +87 -0
  291. package/dist/integration.js.map +1 -0
  292. package/dist/integrator.d.ts +84 -0
  293. package/dist/integrator.d.ts.map +1 -0
  294. package/dist/integrator.js +193 -0
  295. package/dist/integrator.js.map +1 -0
  296. package/dist/lane-claims.d.ts +174 -0
  297. package/dist/lane-claims.d.ts.map +1 -0
  298. package/dist/lane-claims.js +218 -0
  299. package/dist/lane-claims.js.map +1 -0
  300. package/dist/lane-coverage.d.ts +87 -0
  301. package/dist/lane-coverage.d.ts.map +1 -0
  302. package/dist/lane-coverage.js +129 -0
  303. package/dist/lane-coverage.js.map +1 -0
  304. package/dist/ledger-replay.d.ts +115 -0
  305. package/dist/ledger-replay.d.ts.map +1 -0
  306. package/dist/ledger-replay.js +155 -0
  307. package/dist/ledger-replay.js.map +1 -0
  308. package/dist/ledger-store.d.ts +68 -0
  309. package/dist/ledger-store.d.ts.map +1 -0
  310. package/dist/ledger-store.js +111 -0
  311. package/dist/ledger-store.js.map +1 -0
  312. package/dist/loop-safety-observer.d.ts +132 -0
  313. package/dist/loop-safety-observer.d.ts.map +1 -0
  314. package/dist/loop-safety-observer.js +76 -0
  315. package/dist/loop-safety-observer.js.map +1 -0
  316. package/dist/loop-safety-store.d.ts +339 -0
  317. package/dist/loop-safety-store.d.ts.map +1 -0
  318. package/dist/loop-safety-store.js +800 -0
  319. package/dist/loop-safety-store.js.map +1 -0
  320. package/dist/machine-store.d.ts +54 -0
  321. package/dist/machine-store.d.ts.map +1 -0
  322. package/dist/machine-store.js +149 -0
  323. package/dist/machine-store.js.map +1 -0
  324. package/dist/mcp-main.d.ts +2 -0
  325. package/dist/mcp-main.d.ts.map +1 -0
  326. package/dist/mcp-main.js +116 -0
  327. package/dist/mcp-main.js.map +1 -0
  328. package/dist/mcp-server.d.ts +72 -0
  329. package/dist/mcp-server.d.ts.map +1 -0
  330. package/dist/mcp-server.js +259 -0
  331. package/dist/mcp-server.js.map +1 -0
  332. package/dist/model-routing.d.ts +75 -0
  333. package/dist/model-routing.d.ts.map +1 -0
  334. package/dist/model-routing.js +108 -0
  335. package/dist/model-routing.js.map +1 -0
  336. package/dist/model-transport.d.ts +188 -0
  337. package/dist/model-transport.d.ts.map +1 -0
  338. package/dist/model-transport.js +625 -0
  339. package/dist/model-transport.js.map +1 -0
  340. package/dist/notify-cadence.d.ts +55 -0
  341. package/dist/notify-cadence.d.ts.map +1 -0
  342. package/dist/notify-cadence.js +68 -0
  343. package/dist/notify-cadence.js.map +1 -0
  344. package/dist/notify-channel.d.ts +69 -0
  345. package/dist/notify-channel.d.ts.map +1 -0
  346. package/dist/notify-channel.js +151 -0
  347. package/dist/notify-channel.js.map +1 -0
  348. package/dist/notify.d.ts +71 -0
  349. package/dist/notify.d.ts.map +1 -0
  350. package/dist/notify.js +125 -0
  351. package/dist/notify.js.map +1 -0
  352. package/dist/observation-inventory.d.ts +65 -0
  353. package/dist/observation-inventory.d.ts.map +1 -0
  354. package/dist/observation-inventory.js +139 -0
  355. package/dist/observation-inventory.js.map +1 -0
  356. package/dist/owned-children.d.ts +45 -0
  357. package/dist/owned-children.d.ts.map +1 -0
  358. package/dist/owned-children.js +64 -0
  359. package/dist/owned-children.js.map +1 -0
  360. package/dist/packet-for-goal.d.ts +19 -0
  361. package/dist/packet-for-goal.d.ts.map +1 -0
  362. package/dist/packet-for-goal.js +32 -0
  363. package/dist/packet-for-goal.js.map +1 -0
  364. package/dist/pair-cmd.d.ts +85 -0
  365. package/dist/pair-cmd.d.ts.map +1 -0
  366. package/dist/pair-cmd.js +205 -0
  367. package/dist/pair-cmd.js.map +1 -0
  368. package/dist/partial-asker.d.ts +96 -0
  369. package/dist/partial-asker.d.ts.map +1 -0
  370. package/dist/partial-asker.js +117 -0
  371. package/dist/partial-asker.js.map +1 -0
  372. package/dist/pdf-text-lines.d.ts +17 -0
  373. package/dist/pdf-text-lines.d.ts.map +1 -0
  374. package/dist/pdf-text-lines.js +70 -0
  375. package/dist/pdf-text-lines.js.map +1 -0
  376. package/dist/pdf-text-worker.d.ts +2 -0
  377. package/dist/pdf-text-worker.d.ts.map +1 -0
  378. package/dist/pdf-text-worker.js +81 -0
  379. package/dist/pdf-text-worker.js.map +1 -0
  380. package/dist/pdf-text.d.ts +56 -0
  381. package/dist/pdf-text.d.ts.map +1 -0
  382. package/dist/pdf-text.js +64 -0
  383. package/dist/pdf-text.js.map +1 -0
  384. package/dist/pending-action.d.ts +154 -0
  385. package/dist/pending-action.d.ts.map +1 -0
  386. package/dist/pending-action.js +148 -0
  387. package/dist/pending-action.js.map +1 -0
  388. package/dist/preemptor.d.ts +40 -0
  389. package/dist/preemptor.d.ts.map +1 -0
  390. package/dist/preemptor.js +49 -0
  391. package/dist/preemptor.js.map +1 -0
  392. package/dist/programme-mode.d.ts +29 -0
  393. package/dist/programme-mode.d.ts.map +1 -0
  394. package/dist/programme-mode.js +50 -0
  395. package/dist/programme-mode.js.map +1 -0
  396. package/dist/progress-view.d.ts +14 -0
  397. package/dist/progress-view.d.ts.map +1 -0
  398. package/dist/progress-view.js +114 -0
  399. package/dist/progress-view.js.map +1 -0
  400. package/dist/project-graph-builder.d.ts +81 -0
  401. package/dist/project-graph-builder.d.ts.map +1 -0
  402. package/dist/project-graph-builder.js +246 -0
  403. package/dist/project-graph-builder.js.map +1 -0
  404. package/dist/project-graph-runtime.d.ts +86 -0
  405. package/dist/project-graph-runtime.d.ts.map +1 -0
  406. package/dist/project-graph-runtime.js +112 -0
  407. package/dist/project-graph-runtime.js.map +1 -0
  408. package/dist/project-index-builder.d.ts +96 -0
  409. package/dist/project-index-builder.d.ts.map +1 -0
  410. package/dist/project-index-builder.js +298 -0
  411. package/dist/project-index-builder.js.map +1 -0
  412. package/dist/project-index-facts.d.ts +51 -0
  413. package/dist/project-index-facts.d.ts.map +1 -0
  414. package/dist/project-index-facts.js +117 -0
  415. package/dist/project-index-facts.js.map +1 -0
  416. package/dist/project-index-store.d.ts +97 -0
  417. package/dist/project-index-store.d.ts.map +1 -0
  418. package/dist/project-index-store.js +140 -0
  419. package/dist/project-index-store.js.map +1 -0
  420. package/dist/project-memory-store.d.ts +127 -0
  421. package/dist/project-memory-store.d.ts.map +1 -0
  422. package/dist/project-memory-store.js +302 -0
  423. package/dist/project-memory-store.js.map +1 -0
  424. package/dist/proposal-store.d.ts +14 -0
  425. package/dist/proposal-store.d.ts.map +1 -0
  426. package/dist/proposal-store.js +19 -0
  427. package/dist/proposal-store.js.map +1 -0
  428. package/dist/prover.d.ts +80 -0
  429. package/dist/prover.d.ts.map +1 -0
  430. package/dist/prover.js +137 -0
  431. package/dist/prover.js.map +1 -0
  432. package/dist/provider-identity-store.d.ts +34 -0
  433. package/dist/provider-identity-store.d.ts.map +1 -0
  434. package/dist/provider-identity-store.js +72 -0
  435. package/dist/provider-identity-store.js.map +1 -0
  436. package/dist/provider-identity.d.ts +104 -0
  437. package/dist/provider-identity.d.ts.map +1 -0
  438. package/dist/provider-identity.js +167 -0
  439. package/dist/provider-identity.js.map +1 -0
  440. package/dist/provider-limit.d.ts +79 -0
  441. package/dist/provider-limit.d.ts.map +1 -0
  442. package/dist/provider-limit.js +148 -0
  443. package/dist/provider-limit.js.map +1 -0
  444. package/dist/provider-preflight.d.ts +171 -0
  445. package/dist/provider-preflight.d.ts.map +1 -0
  446. package/dist/provider-preflight.js +395 -0
  447. package/dist/provider-preflight.js.map +1 -0
  448. package/dist/provider-state.d.ts +120 -0
  449. package/dist/provider-state.d.ts.map +1 -0
  450. package/dist/provider-state.js +182 -0
  451. package/dist/provider-state.js.map +1 -0
  452. package/dist/providers.d.ts +132 -0
  453. package/dist/providers.d.ts.map +1 -0
  454. package/dist/providers.js +161 -0
  455. package/dist/providers.js.map +1 -0
  456. package/dist/publication-recorder.d.ts +117 -0
  457. package/dist/publication-recorder.d.ts.map +1 -0
  458. package/dist/publication-recorder.js +124 -0
  459. package/dist/publication-recorder.js.map +1 -0
  460. package/dist/pursuit-delivery.d.ts +24 -0
  461. package/dist/pursuit-delivery.d.ts.map +1 -0
  462. package/dist/pursuit-delivery.js +38 -0
  463. package/dist/pursuit-delivery.js.map +1 -0
  464. package/dist/queue-store.d.ts +132 -0
  465. package/dist/queue-store.d.ts.map +1 -0
  466. package/dist/queue-store.js +185 -0
  467. package/dist/queue-store.js.map +1 -0
  468. package/dist/queue-summary.d.ts +14 -0
  469. package/dist/queue-summary.d.ts.map +1 -0
  470. package/dist/queue-summary.js +82 -0
  471. package/dist/queue-summary.js.map +1 -0
  472. package/dist/queue-view.d.ts +20 -0
  473. package/dist/queue-view.d.ts.map +1 -0
  474. package/dist/queue-view.js +163 -0
  475. package/dist/queue-view.js.map +1 -0
  476. package/dist/queue-write-lease.d.ts +106 -0
  477. package/dist/queue-write-lease.d.ts.map +1 -0
  478. package/dist/queue-write-lease.js +282 -0
  479. package/dist/queue-write-lease.js.map +1 -0
  480. package/dist/rails-home.d.ts +162 -0
  481. package/dist/rails-home.d.ts.map +1 -0
  482. package/dist/rails-home.js +452 -0
  483. package/dist/rails-home.js.map +1 -0
  484. package/dist/rails-migrations.d.ts +75 -0
  485. package/dist/rails-migrations.d.ts.map +1 -0
  486. package/dist/rails-migrations.js +199 -0
  487. package/dist/rails-migrations.js.map +1 -0
  488. package/dist/rails-stores.d.ts +49 -0
  489. package/dist/rails-stores.d.ts.map +1 -0
  490. package/dist/rails-stores.js +100 -0
  491. package/dist/rails-stores.js.map +1 -0
  492. package/dist/reaper.d.ts +69 -0
  493. package/dist/reaper.d.ts.map +1 -0
  494. package/dist/reaper.js +152 -0
  495. package/dist/reaper.js.map +1 -0
  496. package/dist/record-store.d.ts +36 -0
  497. package/dist/record-store.d.ts.map +1 -0
  498. package/dist/record-store.js +78 -0
  499. package/dist/record-store.js.map +1 -0
  500. package/dist/recovery-io.d.ts +50 -0
  501. package/dist/recovery-io.d.ts.map +1 -0
  502. package/dist/recovery-io.js +122 -0
  503. package/dist/recovery-io.js.map +1 -0
  504. package/dist/recovery.d.ts +146 -0
  505. package/dist/recovery.d.ts.map +1 -0
  506. package/dist/recovery.js +110 -0
  507. package/dist/recovery.js.map +1 -0
  508. package/dist/redraw.d.ts +34 -0
  509. package/dist/redraw.d.ts.map +1 -0
  510. package/dist/redraw.js +62 -0
  511. package/dist/redraw.js.map +1 -0
  512. package/dist/rejected-evidence.d.ts +255 -0
  513. package/dist/rejected-evidence.d.ts.map +1 -0
  514. package/dist/rejected-evidence.js +324 -0
  515. package/dist/rejected-evidence.js.map +1 -0
  516. package/dist/report-cmd.d.ts +32 -0
  517. package/dist/report-cmd.d.ts.map +1 -0
  518. package/dist/report-cmd.js +201 -0
  519. package/dist/report-cmd.js.map +1 -0
  520. package/dist/repos-cmd.d.ts +80 -0
  521. package/dist/repos-cmd.d.ts.map +1 -0
  522. package/dist/repos-cmd.js +240 -0
  523. package/dist/repos-cmd.js.map +1 -0
  524. package/dist/request-body-shape.d.ts +93 -0
  525. package/dist/request-body-shape.d.ts.map +1 -0
  526. package/dist/request-body-shape.js +407 -0
  527. package/dist/request-body-shape.js.map +1 -0
  528. package/dist/requirement-claims.d.ts +89 -0
  529. package/dist/requirement-claims.d.ts.map +1 -0
  530. package/dist/requirement-claims.js +92 -0
  531. package/dist/requirement-claims.js.map +1 -0
  532. package/dist/retention-apply-runtime.d.ts +105 -0
  533. package/dist/retention-apply-runtime.d.ts.map +1 -0
  534. package/dist/retention-apply-runtime.js +269 -0
  535. package/dist/retention-apply-runtime.js.map +1 -0
  536. package/dist/reverify.d.ts +41 -0
  537. package/dist/reverify.d.ts.map +1 -0
  538. package/dist/reverify.js +69 -0
  539. package/dist/reverify.js.map +1 -0
  540. package/dist/round-records.d.ts +65 -0
  541. package/dist/round-records.d.ts.map +1 -0
  542. package/dist/round-records.js +61 -0
  543. package/dist/round-records.js.map +1 -0
  544. package/dist/round-runner.d.ts +924 -0
  545. package/dist/round-runner.d.ts.map +1 -0
  546. package/dist/round-runner.js +1693 -0
  547. package/dist/round-runner.js.map +1 -0
  548. package/dist/run-approval.d.ts +180 -0
  549. package/dist/run-approval.d.ts.map +1 -0
  550. package/dist/run-approval.js +199 -0
  551. package/dist/run-approval.js.map +1 -0
  552. package/dist/run-cmd.d.ts +359 -0
  553. package/dist/run-cmd.d.ts.map +1 -0
  554. package/dist/run-cmd.js +4418 -0
  555. package/dist/run-cmd.js.map +1 -0
  556. package/dist/run-delivery.d.ts +71 -0
  557. package/dist/run-delivery.d.ts.map +1 -0
  558. package/dist/run-delivery.js +104 -0
  559. package/dist/run-delivery.js.map +1 -0
  560. package/dist/run-ended.d.ts +75 -0
  561. package/dist/run-ended.d.ts.map +1 -0
  562. package/dist/run-ended.js +27 -0
  563. package/dist/run-ended.js.map +1 -0
  564. package/dist/run-ending-locator.d.ts +125 -0
  565. package/dist/run-ending-locator.d.ts.map +1 -0
  566. package/dist/run-ending-locator.js +133 -0
  567. package/dist/run-ending-locator.js.map +1 -0
  568. package/dist/run-launcher.d.ts +459 -0
  569. package/dist/run-launcher.d.ts.map +1 -0
  570. package/dist/run-launcher.js +652 -0
  571. package/dist/run-launcher.js.map +1 -0
  572. package/dist/run-lease.d.ts +208 -0
  573. package/dist/run-lease.d.ts.map +1 -0
  574. package/dist/run-lease.js +301 -0
  575. package/dist/run-lease.js.map +1 -0
  576. package/dist/run-refusal-marks.d.ts +189 -0
  577. package/dist/run-refusal-marks.d.ts.map +1 -0
  578. package/dist/run-refusal-marks.js +249 -0
  579. package/dist/run-refusal-marks.js.map +1 -0
  580. package/dist/run-start-marks.d.ts +153 -0
  581. package/dist/run-start-marks.d.ts.map +1 -0
  582. package/dist/run-start-marks.js +269 -0
  583. package/dist/run-start-marks.js.map +1 -0
  584. package/dist/scan-cmd.d.ts +14 -0
  585. package/dist/scan-cmd.d.ts.map +1 -0
  586. package/dist/scan-cmd.js +270 -0
  587. package/dist/scan-cmd.js.map +1 -0
  588. package/dist/scan-events.d.ts +50 -0
  589. package/dist/scan-events.d.ts.map +1 -0
  590. package/dist/scan-events.js +91 -0
  591. package/dist/scan-events.js.map +1 -0
  592. package/dist/scan.d.ts +191 -0
  593. package/dist/scan.d.ts.map +1 -0
  594. package/dist/scan.js +417 -0
  595. package/dist/scan.js.map +1 -0
  596. package/dist/scope-rule.d.ts +148 -0
  597. package/dist/scope-rule.d.ts.map +1 -0
  598. package/dist/scope-rule.js +121 -0
  599. package/dist/scope-rule.js.map +1 -0
  600. package/dist/self-repo-id.d.ts +18 -0
  601. package/dist/self-repo-id.d.ts.map +1 -0
  602. package/dist/self-repo-id.js +70 -0
  603. package/dist/self-repo-id.js.map +1 -0
  604. package/dist/serve-cmd.d.ts +115 -0
  605. package/dist/serve-cmd.d.ts.map +1 -0
  606. package/dist/serve-cmd.js +505 -0
  607. package/dist/serve-cmd.js.map +1 -0
  608. package/dist/serve.d.ts +167 -0
  609. package/dist/serve.d.ts.map +1 -0
  610. package/dist/serve.js +336 -0
  611. package/dist/serve.js.map +1 -0
  612. package/dist/server-client.d.ts +766 -0
  613. package/dist/server-client.d.ts.map +1 -0
  614. package/dist/server-client.js +475 -0
  615. package/dist/server-client.js.map +1 -0
  616. package/dist/session-adapter-runtime.d.ts +195 -0
  617. package/dist/session-adapter-runtime.d.ts.map +1 -0
  618. package/dist/session-adapter-runtime.js +373 -0
  619. package/dist/session-adapter-runtime.js.map +1 -0
  620. package/dist/session-checkpoint-runtime.d.ts +62 -0
  621. package/dist/session-checkpoint-runtime.d.ts.map +1 -0
  622. package/dist/session-checkpoint-runtime.js +268 -0
  623. package/dist/session-checkpoint-runtime.js.map +1 -0
  624. package/dist/session-control-transport.d.ts +106 -0
  625. package/dist/session-control-transport.d.ts.map +1 -0
  626. package/dist/session-control-transport.js +232 -0
  627. package/dist/session-control-transport.js.map +1 -0
  628. package/dist/session-observation-store.d.ts +98 -0
  629. package/dist/session-observation-store.d.ts.map +1 -0
  630. package/dist/session-observation-store.js +155 -0
  631. package/dist/session-observation-store.js.map +1 -0
  632. package/dist/session-observe-runtime.d.ts +123 -0
  633. package/dist/session-observe-runtime.d.ts.map +1 -0
  634. package/dist/session-observe-runtime.js +317 -0
  635. package/dist/session-observe-runtime.js.map +1 -0
  636. package/dist/session-store.d.ts +98 -0
  637. package/dist/session-store.d.ts.map +1 -0
  638. package/dist/session-store.js +116 -0
  639. package/dist/session-store.js.map +1 -0
  640. package/dist/sessions-cmd.d.ts +202 -0
  641. package/dist/sessions-cmd.d.ts.map +1 -0
  642. package/dist/sessions-cmd.js +609 -0
  643. package/dist/sessions-cmd.js.map +1 -0
  644. package/dist/settings-overlay.d.ts +53 -0
  645. package/dist/settings-overlay.d.ts.map +1 -0
  646. package/dist/settings-overlay.js +175 -0
  647. package/dist/settings-overlay.js.map +1 -0
  648. package/dist/setup-prompt.d.ts +34 -0
  649. package/dist/setup-prompt.d.ts.map +1 -0
  650. package/dist/setup-prompt.js +92 -0
  651. package/dist/setup-prompt.js.map +1 -0
  652. package/dist/setup.d.ts +103 -0
  653. package/dist/setup.d.ts.map +1 -0
  654. package/dist/setup.js +283 -0
  655. package/dist/setup.js.map +1 -0
  656. package/dist/shared-grants.d.ts +164 -0
  657. package/dist/shared-grants.d.ts.map +1 -0
  658. package/dist/shared-grants.js +242 -0
  659. package/dist/shared-grants.js.map +1 -0
  660. package/dist/signals.d.ts +55 -0
  661. package/dist/signals.d.ts.map +1 -0
  662. package/dist/signals.js +85 -0
  663. package/dist/signals.js.map +1 -0
  664. package/dist/source-cmd.d.ts +201 -0
  665. package/dist/source-cmd.d.ts.map +1 -0
  666. package/dist/source-cmd.js +684 -0
  667. package/dist/source-cmd.js.map +1 -0
  668. package/dist/source-verdict.d.ts +99 -0
  669. package/dist/source-verdict.d.ts.map +1 -0
  670. package/dist/source-verdict.js +182 -0
  671. package/dist/source-verdict.js.map +1 -0
  672. package/dist/spend-ledger.d.ts +350 -0
  673. package/dist/spend-ledger.d.ts.map +1 -0
  674. package/dist/spend-ledger.js +546 -0
  675. package/dist/spend-ledger.js.map +1 -0
  676. package/dist/stale-run-sweep.d.ts +79 -0
  677. package/dist/stale-run-sweep.d.ts.map +1 -0
  678. package/dist/stale-run-sweep.js +116 -0
  679. package/dist/stale-run-sweep.js.map +1 -0
  680. package/dist/start-attempts.d.ts +385 -0
  681. package/dist/start-attempts.d.ts.map +1 -0
  682. package/dist/start-attempts.js +613 -0
  683. package/dist/start-attempts.js.map +1 -0
  684. package/dist/status-cmd.d.ts +28 -0
  685. package/dist/status-cmd.d.ts.map +1 -0
  686. package/dist/status-cmd.js +116 -0
  687. package/dist/status-cmd.js.map +1 -0
  688. package/dist/stop-follow-up.d.ts +107 -0
  689. package/dist/stop-follow-up.d.ts.map +1 -0
  690. package/dist/stop-follow-up.js +172 -0
  691. package/dist/stop-follow-up.js.map +1 -0
  692. package/dist/surface-lease.d.ts +118 -0
  693. package/dist/surface-lease.d.ts.map +1 -0
  694. package/dist/surface-lease.js +485 -0
  695. package/dist/surface-lease.js.map +1 -0
  696. package/dist/sync.d.ts +54 -0
  697. package/dist/sync.d.ts.map +1 -0
  698. package/dist/sync.js +93 -0
  699. package/dist/sync.js.map +1 -0
  700. package/dist/syncing-ledger.d.ts +45 -0
  701. package/dist/syncing-ledger.d.ts.map +1 -0
  702. package/dist/syncing-ledger.js +53 -0
  703. package/dist/syncing-ledger.js.map +1 -0
  704. package/dist/temp-fixtures.d.ts +68 -0
  705. package/dist/temp-fixtures.d.ts.map +1 -0
  706. package/dist/temp-fixtures.js +38 -0
  707. package/dist/temp-fixtures.js.map +1 -0
  708. package/dist/token-window.d.ts +84 -0
  709. package/dist/token-window.d.ts.map +1 -0
  710. package/dist/token-window.js +143 -0
  711. package/dist/token-window.js.map +1 -0
  712. package/dist/tool-bridge.d.ts +177 -0
  713. package/dist/tool-bridge.d.ts.map +1 -0
  714. package/dist/tool-bridge.js +329 -0
  715. package/dist/tool-bridge.js.map +1 -0
  716. package/dist/tool-call-record.d.ts +197 -0
  717. package/dist/tool-call-record.d.ts.map +1 -0
  718. package/dist/tool-call-record.js +276 -0
  719. package/dist/tool-call-record.js.map +1 -0
  720. package/dist/tool-protocol.d.ts +135 -0
  721. package/dist/tool-protocol.d.ts.map +1 -0
  722. package/dist/tool-protocol.js +104 -0
  723. package/dist/tool-protocol.js.map +1 -0
  724. package/dist/tool-worker.d.ts +3 -0
  725. package/dist/tool-worker.d.ts.map +1 -0
  726. package/dist/tool-worker.js +478 -0
  727. package/dist/tool-worker.js.map +1 -0
  728. package/dist/toolchain-mirror.d.ts +86 -0
  729. package/dist/toolchain-mirror.d.ts.map +1 -0
  730. package/dist/toolchain-mirror.js +307 -0
  731. package/dist/toolchain-mirror.js.map +1 -0
  732. package/dist/trusted-git.d.ts +243 -0
  733. package/dist/trusted-git.d.ts.map +1 -0
  734. package/dist/trusted-git.js +920 -0
  735. package/dist/trusted-git.js.map +1 -0
  736. package/dist/ui.d.ts +76 -0
  737. package/dist/ui.d.ts.map +1 -0
  738. package/dist/ui.js +118 -0
  739. package/dist/ui.js.map +1 -0
  740. package/dist/untrusted-exec.d.ts +275 -0
  741. package/dist/untrusted-exec.d.ts.map +1 -0
  742. package/dist/untrusted-exec.js +479 -0
  743. package/dist/untrusted-exec.js.map +1 -0
  744. package/dist/untrusted-gate.d.ts +73 -0
  745. package/dist/untrusted-gate.d.ts.map +1 -0
  746. package/dist/untrusted-gate.js +226 -0
  747. package/dist/untrusted-gate.js.map +1 -0
  748. package/dist/uploader.d.ts +153 -0
  749. package/dist/uploader.d.ts.map +1 -0
  750. package/dist/uploader.js +204 -0
  751. package/dist/uploader.js.map +1 -0
  752. package/dist/verifier.d.ts +66 -0
  753. package/dist/verifier.d.ts.map +1 -0
  754. package/dist/verifier.js +170 -0
  755. package/dist/verifier.js.map +1 -0
  756. package/dist/verify-apply.d.ts +26 -0
  757. package/dist/verify-apply.d.ts.map +1 -0
  758. package/dist/verify-apply.js +36 -0
  759. package/dist/verify-apply.js.map +1 -0
  760. package/dist/verify-cmd.d.ts +44 -0
  761. package/dist/verify-cmd.d.ts.map +1 -0
  762. package/dist/verify-cmd.js +125 -0
  763. package/dist/verify-cmd.js.map +1 -0
  764. package/dist/verify-pass.d.ts +73 -0
  765. package/dist/verify-pass.d.ts.map +1 -0
  766. package/dist/verify-pass.js +103 -0
  767. package/dist/verify-pass.js.map +1 -0
  768. package/dist/welcome.d.ts +43 -0
  769. package/dist/welcome.d.ts.map +1 -0
  770. package/dist/welcome.js +116 -0
  771. package/dist/welcome.js.map +1 -0
  772. package/dist/workspace-provisioner.d.ts +65 -0
  773. package/dist/workspace-provisioner.d.ts.map +1 -0
  774. package/dist/workspace-provisioner.js +66 -0
  775. package/dist/workspace-provisioner.js.map +1 -0
  776. package/dist/workspace-quarantine.d.ts +64 -0
  777. package/dist/workspace-quarantine.d.ts.map +1 -0
  778. package/dist/workspace-quarantine.js +156 -0
  779. package/dist/workspace-quarantine.js.map +1 -0
  780. package/dist/workspace-residue-sweep.d.ts +113 -0
  781. package/dist/workspace-residue-sweep.d.ts.map +1 -0
  782. package/dist/workspace-residue-sweep.js +158 -0
  783. package/dist/workspace-residue-sweep.js.map +1 -0
  784. package/dist/workspace.d.ts +639 -0
  785. package/dist/workspace.d.ts.map +1 -0
  786. package/dist/workspace.js +2026 -0
  787. package/dist/workspace.js.map +1 -0
  788. package/package.json +52 -4
  789. package/win/CredProbe.cs +64 -0
  790. package/win/FakeClaude.cs +56 -0
  791. package/win/HandleProbe.cs +116 -0
  792. package/win/TokenProbe.cs +53 -0
  793. package/win/appcontainer.ps1 +500 -0
package/dist/config.js ADDED
@@ -0,0 +1,763 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ConfigError = exports.DEFAULTS = exports.PUBLISH_POLICIES = void 0;
4
+ exports.mayPublish = mayPublish;
5
+ exports.parseConfig = parseConfig;
6
+ exports.configWarnings = configWarnings;
7
+ const yaml_1 = require("yaml");
8
+ const core_1 = require("@looply/core");
9
+ const agent_exec_1 = require("./agent-exec");
10
+ const model_routing_1 = require("./model-routing");
11
+ const integration_1 = require("./integration");
12
+ exports.PUBLISH_POLICIES = ['never', 'on-approval', 'manual'];
13
+ /**
14
+ * May Looply itself publish, under this policy?
15
+ *
16
+ * ONE PREDICATE, so that no caller has to remember that `manual` means "not
17
+ * Looply". Two call sites reasoning about the enum separately is how one of
18
+ * them eventually treats an unfamiliar value as permission.
19
+ */
20
+ function mayPublish(policy) {
21
+ return policy === 'on-approval';
22
+ }
23
+ exports.DEFAULTS = {
24
+ run: { minHours: 4, maxRounds: 400, cooldownS: 5, carryIntoCheckouts: [], maxConcurrentRuns: 1, perRoundSafety: false, surfaces: false, integration: false, brain: false },
25
+ machine: {
26
+ maxWorkspaces: 1,
27
+ maxAgentsInFlight: 1,
28
+ coordinator: false,
29
+ provisionWorkspaces: false,
30
+ preemption: false,
31
+ reapProvisioned: false,
32
+ idleCheckoutMinutes: 60,
33
+ integrate: false,
34
+ },
35
+ publish: { policy: 'never' },
36
+ rails: { exemptions: 'ask', prodEnvFiles: ['.env'] },
37
+ queue: { topupThreshold: 5, topupSize: 10, maxSameShape: 3 },
38
+ proof: { enabled: true, onPartial: 'ask', askWindowMin: 20 },
39
+ notify: { channel: 'sms', everyMin: 30 },
40
+ agent: agent_exec_1.DEFAULT_AGENT,
41
+ };
42
+ class ConfigError extends Error {
43
+ key;
44
+ constructor(key, message) {
45
+ super(`config: ${key} — ${message}`);
46
+ this.key = key;
47
+ this.name = 'ConfigError';
48
+ }
49
+ }
50
+ exports.ConfigError = ConfigError;
51
+ const isObj = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
52
+ function str(o, key, path, fallback) {
53
+ const v = o[key];
54
+ if (v === undefined) {
55
+ if (fallback !== undefined)
56
+ return fallback;
57
+ throw new ConfigError(`${path}.${key}`, 'is required');
58
+ }
59
+ if (typeof v !== 'string' || !v.trim())
60
+ throw new ConfigError(`${path}.${key}`, 'must be a non-empty string');
61
+ return v;
62
+ }
63
+ function num(o, key, path, fallback, min = 0) {
64
+ const v = o[key];
65
+ if (v === undefined)
66
+ return fallback;
67
+ if (typeof v !== 'number' || !Number.isFinite(v))
68
+ throw new ConfigError(`${path}.${key}`, 'must be a number');
69
+ if (v < min)
70
+ throw new ConfigError(`${path}.${key}`, `must be >= ${min}`);
71
+ return v;
72
+ }
73
+ function bool(o, key, path, fallback) {
74
+ const v = o[key];
75
+ if (v === undefined)
76
+ return fallback;
77
+ if (typeof v !== 'boolean')
78
+ throw new ConfigError(`${path}.${key}`, 'must be true or false');
79
+ return v;
80
+ }
81
+ function strList(o, key, path, fallback = []) {
82
+ const v = o[key];
83
+ if (v === undefined)
84
+ return fallback;
85
+ if (!Array.isArray(v) || v.some((x) => typeof x !== 'string')) {
86
+ throw new ConfigError(`${path}.${key}`, 'must be a list of strings');
87
+ }
88
+ return v;
89
+ }
90
+ /**
91
+ * `agent.models` and `agent.effort`, or nothing at all.
92
+ *
93
+ * ⚠️ REFUSED HERE, NOT AT ROUND ONE. A model id with a space in it, a role
94
+ * nobody has, or a Fable model named for an agent: each is the kind of mistake
95
+ * that should stop a run before it starts, not after the first model call has
96
+ * been paid for — the same reasoning `provider` is checked on. The rule itself
97
+ * lives in `model-routing.ts` so `looply doctor` can name the same key.
98
+ */
99
+ function roleModelsOf(agent) {
100
+ const out = {};
101
+ const raw = agent['models'];
102
+ if (raw !== undefined) {
103
+ if (!isObj(raw))
104
+ throw new ConfigError('agent.models', 'must be a map of role to model id');
105
+ const models = {};
106
+ for (const [key, value] of Object.entries(raw)) {
107
+ if (typeof value !== 'string')
108
+ throw new ConfigError(`agent.models.${key}`, 'must be a model id');
109
+ models[key] = value;
110
+ }
111
+ const verdict = (0, model_routing_1.checkRoleModels)(models);
112
+ if (!verdict.ok)
113
+ throw new ConfigError(verdict.key, verdict.because);
114
+ out.models = models;
115
+ }
116
+ if (agent['effort'] !== undefined) {
117
+ out.effort = oneOf(agent, 'effort', 'agent', model_routing_1.EFFORT_LEVELS, 'high');
118
+ }
119
+ return out;
120
+ }
121
+ function oneOf(o, key, path, allowed, fallback) {
122
+ const v = o[key];
123
+ if (v === undefined)
124
+ return fallback;
125
+ if (typeof v !== 'string' || !allowed.includes(v)) {
126
+ throw new ConfigError(`${path}.${key}`, `must be one of ${allowed.join(' | ')}`);
127
+ }
128
+ return v;
129
+ }
130
+ /**
131
+ * Read the human decisions, refusing anything malformed rather than guessing.
132
+ *
133
+ * An absent block is an empty list — a project that has recorded no decisions
134
+ * is the ordinary case, not an error. A malformed ENTRY is dropped rather than
135
+ * failing the whole config: a person editing YAML by hand should not lose their
136
+ * ability to run because one entry is half-written, and the entries that are
137
+ * well-formed still mean what they say.
138
+ */
139
+ function parseDecisions(raw) {
140
+ if (!Array.isArray(raw))
141
+ return [];
142
+ const out = [];
143
+ for (const entry of raw) {
144
+ if (!isObj(entry))
145
+ continue;
146
+ const subject = entry['subject'];
147
+ const decision = entry['decision'];
148
+ if (typeof subject !== 'string' || typeof decision !== 'string')
149
+ continue;
150
+ if (subject.trim() === '' || decision.trim() === '')
151
+ continue;
152
+ out.push({ subject: subject.trim(), decision: decision.trim() });
153
+ }
154
+ return out;
155
+ }
156
+ function parseGates(raw) {
157
+ if (raw === undefined)
158
+ throw new ConfigError('gates', 'is required — a run with no checks proves nothing');
159
+ if (!Array.isArray(raw) || raw.length === 0) {
160
+ throw new ConfigError('gates', 'must be a non-empty list');
161
+ }
162
+ const seen = new Set();
163
+ return raw.map((entry, i) => {
164
+ const path = `gates[${i}]`;
165
+ if (!isObj(entry))
166
+ throw new ConfigError(path, 'must be an object');
167
+ const name = str(entry, 'name', path);
168
+ if (seen.has(name))
169
+ throw new ConfigError(path, `duplicate step name ${JSON.stringify(name)}`);
170
+ seen.add(name);
171
+ const step = { name, run: str(entry, 'run', path) };
172
+ const timeoutS = num(entry, 'timeout_s', path, 0, 1);
173
+ if (timeoutS)
174
+ step.timeoutS = timeoutS;
175
+ if (entry['when'] !== undefined)
176
+ step.when = str(entry, 'when', path);
177
+ if (bool(entry, 'required', path, false))
178
+ step.required = true;
179
+ return step;
180
+ });
181
+ }
182
+ const PREDICATE_KEYS = ['equals', 'one_of', 'at_least', 'known'];
183
+ /**
184
+ * `machine.programme.acceptance` and its probes.
185
+ *
186
+ * Every refusal names the exact key, the same way the limits block does.
187
+ */
188
+ function parseAcceptance(raw, probesRaw) {
189
+ const A = 'machine.programme.acceptance';
190
+ const PR = 'machine.programme.acceptance_probes';
191
+ const probes = [];
192
+ if (probesRaw !== undefined) {
193
+ if (!Array.isArray(probesRaw))
194
+ throw new ConfigError(PR, 'must be a list of { fact, run }');
195
+ probesRaw.forEach((entry, i) => {
196
+ if (!isObj(entry))
197
+ throw new ConfigError(`${PR}[${i}]`, 'must be { fact, run }');
198
+ const fact = entry['fact'];
199
+ const run = entry['run'];
200
+ if (typeof fact !== 'string' || !(0, core_1.isAcceptanceFact)(fact) || !fact.startsWith('probe.')) {
201
+ throw new ConfigError(`${PR}[${i}].fact`, 'must be a probe fact named probe.<lower-case-name>');
202
+ }
203
+ if (typeof run !== 'string' || run.trim() === '') {
204
+ throw new ConfigError(`${PR}[${i}].run`, 'is required — a probe with no command reads nothing');
205
+ }
206
+ if (probes.some((p) => p.fact === fact))
207
+ throw new ConfigError(`${PR}[${i}].fact`, `is declared twice: ${fact}`);
208
+ probes.push({ fact, run: run.trim() });
209
+ });
210
+ }
211
+ if (raw === undefined) {
212
+ if (probes.length > 0) {
213
+ throw new ConfigError(`${PR}[0].fact`, `reads ${probes[0]?.fact} and nothing requires it — declare it under acceptance, or remove the probe`);
214
+ }
215
+ return {};
216
+ }
217
+ if (!isObj(raw))
218
+ throw new ConfigError(A, 'must be a block of fact -> predicate');
219
+ const acceptance = {};
220
+ for (const fact of Object.keys(raw).sort()) {
221
+ if (!(0, core_1.isAcceptanceFact)(fact)) {
222
+ throw new ConfigError(`${A}.${fact}`, `is not a verification-environment fact (${core_1.ACCEPTANCE_FACTS.join(', ')}, or probe.<name>)`);
223
+ }
224
+ const spec = raw[fact];
225
+ if (!isObj(spec))
226
+ throw new ConfigError(`${A}.${fact}`, `must be one of { ${PREDICATE_KEYS.join(' | ')} }`);
227
+ const given = PREDICATE_KEYS.filter((k) => spec[k] !== undefined);
228
+ if (given.length !== 1) {
229
+ throw new ConfigError(`${A}.${fact}`, `needs exactly one of ${PREDICATE_KEYS.join(', ')} — found ${given.length === 0 ? 'none' : given.join(' and ')}`);
230
+ }
231
+ const key = given[0];
232
+ if (key === 'known') {
233
+ if (spec['known'] !== true)
234
+ throw new ConfigError(`${A}.${fact}.known`, 'must be true — it means "any value, but it must be readable"');
235
+ acceptance[fact] = { kind: 'known' };
236
+ }
237
+ else if (key === 'equals') {
238
+ const v = spec['equals'];
239
+ if (typeof v !== 'string' || v.trim() === '')
240
+ throw new ConfigError(`${A}.${fact}.equals`, 'must be a non-empty string');
241
+ acceptance[fact] = { kind: 'equals', value: v.trim() };
242
+ }
243
+ else if (key === 'one_of') {
244
+ const v = spec['one_of'];
245
+ if (!Array.isArray(v) || v.length === 0 || v.some((x) => typeof x !== 'string' || x.trim() === '')) {
246
+ throw new ConfigError(`${A}.${fact}.one_of`, 'must be a non-empty list of non-empty strings');
247
+ }
248
+ acceptance[fact] = { kind: 'one-of', values: v.map((x) => x.trim()) };
249
+ }
250
+ else {
251
+ const v = spec['at_least'];
252
+ if (typeof v !== 'string' || !/[0-9]/.test(v)) {
253
+ throw new ConfigError(`${A}.${fact}.at_least`, 'must be a string containing a version, e.g. node@20.11.0 — the compare is dotted-numeric');
254
+ }
255
+ acceptance[fact] = { kind: 'at-least', version: v.trim() };
256
+ }
257
+ }
258
+ /**
259
+ * 🔴 THE PAIRING, BOTH WAYS. Checked after both halves parse, so the message
260
+ * names the fact rather than the first structural problem it met.
261
+ */
262
+ for (const fact of Object.keys(acceptance)) {
263
+ if (fact.startsWith('probe.') && !probes.some((p) => p.fact === fact)) {
264
+ throw new ConfigError(`${A}.${fact}`, `requires ${fact} and nothing reads it — add a probe under acceptance_probes, or remove the requirement`);
265
+ }
266
+ }
267
+ for (const p of probes) {
268
+ if (acceptance[p.fact] === undefined) {
269
+ throw new ConfigError(`${PR}`, `reads ${p.fact} and nothing requires it — declare it under acceptance, or remove the probe`);
270
+ }
271
+ }
272
+ return {
273
+ ...(Object.keys(acceptance).length === 0 ? {} : { acceptance }),
274
+ ...(probes.length === 0 ? {} : { acceptanceProbes: probes }),
275
+ };
276
+ }
277
+ const PROGRAMME_LIMIT_KEYS = ['max_workspaces', 'max_agents_in_flight', 'starts_per_grant', 'window_minutes', 'integration_ref'];
278
+ /**
279
+ * `machine.programme` as a block: `{ on: true, limits: { … } }`. Refused whole
280
+ * when `on` is not true, a limit is missing or out of range, the ref is not the
281
+ * lane's, or a key is not part of it — each refusal names the exact key.
282
+ * Absent, or a boolean, is not a block (slice 1 or nothing).
283
+ */
284
+ function parseProgrammeBlock(raw) {
285
+ if (raw === undefined || typeof raw === 'boolean')
286
+ return null;
287
+ if (!isObj(raw))
288
+ throw new ConfigError('machine.programme', 'must be true, false, or a block { on, limits }');
289
+ const extra = Object.keys(raw).filter((k) => k !== 'on' && k !== 'limits' && k !== 'acceptance' && k !== 'acceptance_probes');
290
+ if (extra.length > 0) {
291
+ throw new ConfigError(`machine.programme.${extra.sort()[0]}`, 'is not part of programme mode (on, limits, acceptance, acceptance_probes)');
292
+ }
293
+ if (raw['on'] !== true) {
294
+ throw new ConfigError('machine.programme.on', 'must be true — a block declares programme mode on; leave the block out to keep manual defaults');
295
+ }
296
+ if (!isObj(raw['limits'])) {
297
+ throw new ConfigError('machine.programme.limits', `is required — programme mode needs its limits declared (${PROGRAMME_LIMIT_KEYS.join(', ')})`);
298
+ }
299
+ const limits = raw['limits'];
300
+ const P = 'machine.programme.limits';
301
+ for (const key of PROGRAMME_LIMIT_KEYS) {
302
+ if (limits[key] === undefined)
303
+ throw new ConfigError(`${P}.${key}`, 'is required — programme mode needs every limit declared');
304
+ }
305
+ const stray = Object.keys(limits).filter((k) => !PROGRAMME_LIMIT_KEYS.includes(k));
306
+ if (stray.length > 0)
307
+ throw new ConfigError(`${P}.${stray.sort()[0]}`, `is not a programme limit (${PROGRAMME_LIMIT_KEYS.join(', ')})`);
308
+ const startsPerGrant = num(limits, 'starts_per_grant', P, 1, 1);
309
+ if (startsPerGrant > core_1.MAX_AUTONOMOUS_STARTS)
310
+ throw new ConfigError(`${P}.starts_per_grant`, `must be <= ${core_1.MAX_AUTONOMOUS_STARTS}`);
311
+ const integrationRef = str(limits, 'integration_ref', P);
312
+ if (integrationRef !== integration_1.INTEGRATION_BRANCH) {
313
+ throw new ConfigError(`${P}.integration_ref`, `must be ${integration_1.INTEGRATION_BRANCH} — the lane integrates there and takes no other ref yet`);
314
+ }
315
+ return {
316
+ limits: {
317
+ maxWorkspaces: num(limits, 'max_workspaces', P, 1, 1),
318
+ maxAgentsInFlight: num(limits, 'max_agents_in_flight', P, 1, 1),
319
+ startsPerGrant,
320
+ windowMinutes: num(limits, 'window_minutes', P, 1, 1),
321
+ integrationRef,
322
+ },
323
+ ...parseAcceptance(raw['acceptance'], raw['acceptance_probes']),
324
+ };
325
+ }
326
+ /** A knob the umbrella declares: set there only; a copy beside the block must agree. */
327
+ function declaredOr(o, key, declared, fallback) {
328
+ if (declared === undefined)
329
+ return num(o, key, 'machine', fallback, 1);
330
+ if (o[key] !== undefined && o[key] !== declared) {
331
+ throw new ConfigError(`machine.${key}`, 'is declared in machine.programme.limits — set it there only');
332
+ }
333
+ return declared;
334
+ }
335
+ function parseConfig(text) {
336
+ let raw;
337
+ try {
338
+ raw = (0, yaml_1.parse)(text);
339
+ }
340
+ catch (e) {
341
+ throw new ConfigError('<root>', `is not valid YAML: ${e.message}`);
342
+ }
343
+ if (!isObj(raw))
344
+ throw new ConfigError('<root>', 'must be a mapping');
345
+ const project = isObj(raw['project']) ? raw['project'] : undefined;
346
+ if (!project)
347
+ throw new ConfigError('project', 'is required');
348
+ const run = isObj(raw['run']) ? raw['run'] : {};
349
+ const rails = isObj(raw['rails']) ? raw['rails'] : {};
350
+ const machine = isObj(raw['machine']) ? raw['machine'] : {};
351
+ const scope = isObj(raw['scope']) ? raw['scope'] : {};
352
+ const queue = isObj(raw['queue']) ? raw['queue'] : {};
353
+ const proof = isObj(raw['proof']) ? raw['proof'] : {};
354
+ const notify = isObj(raw['notify']) ? raw['notify'] : {};
355
+ const publish = isObj(raw['publish']) ? raw['publish'] : {};
356
+ const agent = isObj(raw['agent']) ? raw['agent'] : {};
357
+ const server = isObj(raw['server']) ? raw['server'] : undefined;
358
+ const repos = Array.isArray(raw['repos']) ? raw['repos'] : undefined;
359
+ const sessions = isObj(raw['sessions']) ? raw['sessions'] : undefined;
360
+ const crossRepoNeeds = Array.isArray(raw['cross_repo_needs']) ? raw['cross_repo_needs'] : undefined;
361
+ // M6-10: the umbrella, read first — while it is on, every face defaults to on and the limits feed their knobs.
362
+ const umbrella = parseProgrammeBlock(machine['programme']);
363
+ const under = umbrella !== null;
364
+ const cfg = {
365
+ project: { name: str(project, 'name', 'project') },
366
+ run: {
367
+ minHours: num(run, 'min_hours', 'run', exports.DEFAULTS.run.minHours, 0),
368
+ maxRounds: num(run, 'max_rounds', 'run', exports.DEFAULTS.run.maxRounds, 1),
369
+ cooldownS: num(run, 'cooldown_s', 'run', exports.DEFAULTS.run.cooldownS, 0),
370
+ carryIntoCheckouts: strList(run, 'carry_into_checkouts', 'run'),
371
+ maxConcurrentRuns: num(run, 'max_concurrent_runs', 'run', exports.DEFAULTS.run.maxConcurrentRuns, 1),
372
+ perRoundSafety: bool(run, 'per_round_safety', 'run', false),
373
+ surfaces: bool(run, 'surfaces', 'run', false),
374
+ integration: bool(run, 'integration', 'run', under),
375
+ brain: bool(run, 'brain', 'run', under),
376
+ },
377
+ machine: {
378
+ maxWorkspaces: declaredOr(machine, 'max_workspaces', umbrella?.limits.maxWorkspaces, exports.DEFAULTS.machine.maxWorkspaces),
379
+ maxAgentsInFlight: declaredOr(machine, 'max_agents_in_flight', umbrella?.limits.maxAgentsInFlight, exports.DEFAULTS.machine.maxAgentsInFlight),
380
+ coordinator: bool(machine, 'coordinator', 'machine', under ? true : exports.DEFAULTS.machine.coordinator),
381
+ provisionWorkspaces: bool(machine, 'provision_workspaces', 'machine', under),
382
+ preemption: bool(machine, 'preemption', 'machine', under),
383
+ reapProvisioned: bool(machine, 'reap_provisioned', 'machine', under),
384
+ idleCheckoutMinutes: num(machine, 'idle_checkout_minutes', 'machine', 60, 0),
385
+ integrate: bool(machine, 'integrate', 'machine', under),
386
+ programme: under ? true : bool(machine, 'programme', 'machine', false),
387
+ ...(umbrella === null ? {} : { programmeMode: umbrella }),
388
+ /**
389
+ * ⚠️ ALL OR NOTHING, AND ONLY WHEN THE BLOCK IS PRESENT. A half-specified
390
+ * envelope is worse than none: three ceilings written and one defaulted
391
+ * to something the person never chose is a limit they did not agree to,
392
+ * on a mechanism whose whole job is to stop the machine. The numbers that
393
+ * ARE defaulted here are defaulted only once somebody has written the
394
+ * block, which is the moment they have asked to be bounded.
395
+ */
396
+ ...(isObj(machine['envelope'])
397
+ ? {
398
+ envelope: (() => {
399
+ const env = machine['envelope'];
400
+ const windowMinutes = num(env, 'window_minutes', 'machine.envelope', 60, 1);
401
+ const wallMinutes = num(env, 'max_wall_clock_minutes', 'machine.envelope', 8 * 60, 1);
402
+ const maxUsd = env['max_usd'];
403
+ return {
404
+ maxConcurrentRuns: num(env, 'max_concurrent_runs', 'machine.envelope', 1, 1),
405
+ maxStartsPerWindow: num(env, 'max_starts_per_window', 'machine.envelope', 20, 1),
406
+ windowMs: windowMinutes * 60_000,
407
+ maxWallClockMs: wallMinutes * 60_000,
408
+ ...(maxUsd === undefined
409
+ ? {}
410
+ : {
411
+ maxUsd: num(env, 'max_usd', 'machine.envelope', 0, 0),
412
+ /**
413
+ * 🔴 ABSENT MEANS ABSENT. IT USED TO MEAN ZERO,
414
+ * WHICH MEANT THE CEILING DID NOTHING.
415
+ *
416
+ * MEASURED: `max_usd: 25` with no estimate, sixteen
417
+ * starts — SIXTEEN ADMITTED. Each reservation held $0,
418
+ * so every start re-read a machine that intended to
419
+ * spend nothing and every one of them passed. The
420
+ * warning below has always said such a project would
421
+ * refuse; the parser quietly disagreed with it.
422
+ *
423
+ * Undefined makes an unpriced start unmeasurable, which
424
+ * `withinEnvelope` refuses — the behaviour the warning
425
+ * describes, and the one a person who wrote a dollar
426
+ * ceiling asked for.
427
+ */
428
+ ...(env['estimate_usd_per_start'] === undefined
429
+ ? {}
430
+ : {
431
+ estimateUsdPerStart: num(env, 'estimate_usd_per_start', 'machine.envelope', 0, 0),
432
+ }),
433
+ }),
434
+ };
435
+ })(),
436
+ }
437
+ : {}),
438
+ },
439
+ gates: parseGates(raw['gates']),
440
+ decisions: parseDecisions(raw['decisions']),
441
+ rails: {
442
+ forbiddenPaths: strList(rails, 'forbidden_paths', 'rails'),
443
+ prodPatterns: strList(rails, 'prod_patterns', 'rails'),
444
+ prodEnvFiles: strList(rails, 'prod_env_files', 'rails', exports.DEFAULTS.rails.prodEnvFiles),
445
+ exemptions: oneOf(rails, 'exemptions', 'rails', ['ask', 'never'], exports.DEFAULTS.rails.exemptions),
446
+ },
447
+ scope: {
448
+ free: strList(scope, 'free', 'scope'),
449
+ additive: strList(scope, 'additive', 'scope'),
450
+ // The presence of the BLOCK, not of either list: `scope: {}` is a
451
+ // declaration, and so is one naming only `additive`.
452
+ declared: isObj(raw['scope']),
453
+ },
454
+ queue: {
455
+ topupThreshold: num(queue, 'topup_threshold', 'queue', exports.DEFAULTS.queue.topupThreshold, 0),
456
+ topupSize: num(queue, 'topup_size', 'queue', exports.DEFAULTS.queue.topupSize, 1),
457
+ maxSameShape: num(queue, 'max_same_shape', 'queue', exports.DEFAULTS.queue.maxSameShape, 1),
458
+ },
459
+ proof: {
460
+ enabled: bool(proof, 'enabled', 'proof', exports.DEFAULTS.proof.enabled),
461
+ onPartial: oneOf(proof, 'on_partial', 'proof', ['ask', 'keep', 'discard'], exports.DEFAULTS.proof.onPartial),
462
+ /**
463
+ * 🔴 HOW LONG A ROUND WAITS FOR THE ANSWER, and it is the same number
464
+ * written on the question's deadline. §6.C asks to *"keep independent
465
+ * work moving"*; a round is the loop's only thread, so waiting IS the
466
+ * cost. A minimum of one minute rather than zero: a window of zero is a
467
+ * question asked and abandoned in the same breath.
468
+ */
469
+ askWindowMin: num(proof, 'ask_window_min', 'proof', exports.DEFAULTS.proof.askWindowMin, 1),
470
+ },
471
+ notify: {
472
+ channel: str(notify, 'channel', 'notify', exports.DEFAULTS.notify.channel),
473
+ everyMin: num(notify, 'every_min', 'notify', exports.DEFAULTS.notify.everyMin, 0),
474
+ },
475
+ // ABSENT MEANS `never`. A config that says nothing about publishing has not
476
+ // granted anything, and a value this build does not recognise throws like
477
+ // every other enum here — which is stricter than defaulting, because the
478
+ // run refuses to start at all rather than starting with a guess.
479
+ publish: {
480
+ policy: oneOf(publish, 'policy', 'publish', exports.PUBLISH_POLICIES, exports.DEFAULTS.publish.policy),
481
+ },
482
+ agent: {
483
+ command: str(agent, 'command', 'agent', exports.DEFAULTS.agent.command),
484
+ // Deliberately allowed to be empty: an agent with no such flag should be
485
+ // startable without inventing one for it.
486
+ outputFormatFlag: agent['output_format_flag'] === ''
487
+ ? ''
488
+ : str(agent, 'output_format_flag', 'agent', exports.DEFAULTS.agent.outputFormatFlag),
489
+ /**
490
+ * An absolute path to the built-in provider's executable, for an
491
+ * installation that is not beside node. Absent means "find the package",
492
+ * which is the ordinary case. Validated at launch, not here: this
493
+ * function parses a file and must not touch the filesystem.
494
+ */
495
+ ...(typeof agent['executable'] === 'string' && agent['executable'] !== ''
496
+ ? { executable: str(agent, 'executable', 'agent', '') }
497
+ : {}),
498
+ // Where a configured agent's runtime lives, for containment to grant.
499
+ // Absent for the built-in provider, which finds its own package.
500
+ runtime: strList(agent, 'runtime', 'agent'),
501
+ // Names only. The value comes from the daemon's environment, so a key
502
+ // never has to be written into a config file to reach the agent.
503
+ env: strList(agent, 'env', 'agent'),
504
+ /**
505
+ * The arguments that turn a CONFIGURED provider's own tools off.
506
+ *
507
+ * 🔴 REQUIRED FOR A CONFIGURED PROVIDER, AND THE TRANSPORT REFUSES
508
+ * WITHOUT IT. The built-in provider is mediated by flags looply knows;
509
+ * for anything else looply cannot guess, and a guessed flag that silently
510
+ * does nothing reads exactly like one that works. Empty here means the
511
+ * launch is refused rather than run unmediated.
512
+ */
513
+ noHostTools: strList(agent, 'no_host_tools', 'agent'),
514
+ /**
515
+ * Which model each role runs, and how hard. Built-in provider only; see
516
+ * `model-routing.ts` for the rule that keeps a Fable model on the brain.
517
+ * Absent keys are absent from the spec, so a file that says nothing
518
+ * produces the invocation it always did.
519
+ */
520
+ ...roleModelsOf(agent),
521
+ /**
522
+ * WHICH AGENT KEYS THE FILE ACTUALLY CONTAINED.
523
+ *
524
+ * 🔴 WITHOUT THIS, A PRESET COULD NEVER WIN. `resolveProvider` treated a
525
+ * present `command` as "the person wrote one" — but `command` always has
526
+ * a value, because THIS function defaults it to Claude's. So the
527
+ * truthiness test was true for every project on earth, the preset's
528
+ * command was overridden every time, and somebody who wrote
529
+ * `provider: codex` got Claude while being shown a warning about codex
530
+ * that reads as confirmation.
531
+ *
532
+ * ⚠️ THE KEYS, NOT THE VALUES. "Absent" and "written, and equal to the
533
+ * default" are different statements and only one of them should lose to
534
+ * a preset. A person who explicitly writes Claude's command line beside
535
+ * `provider: codex` is saying something, even if it is a mistake, and it
536
+ * is not this function's place to discard it silently.
537
+ */
538
+ declared: Object.keys(agent).filter((k) => agent[k] !== undefined),
539
+ },
540
+ };
541
+ // ⚠️ VALIDATED HERE, NOT AT ROUND 1. A misspelled provider name is the kind
542
+ // of mistake that should stop a run before it starts, not after the first
543
+ // model call has been spent finding out.
544
+ const providerName = agent['provider'];
545
+ if (providerName !== undefined && providerName !== '') {
546
+ cfg.provider = str(agent, 'provider', 'agent');
547
+ }
548
+ const id = project['id'];
549
+ if (id !== undefined)
550
+ cfg.project.id = str(project, 'id', 'project');
551
+ const to = notify['to'];
552
+ if (to !== undefined)
553
+ cfg.notify.to = str(notify, 'to', 'notify');
554
+ if (server) {
555
+ cfg.server = { url: str(server, 'url', 'server') };
556
+ if (server['machine_token_file'] !== undefined) {
557
+ cfg.server.machineTokenFile = str(server, 'machine_token_file', 'server');
558
+ }
559
+ }
560
+ /**
561
+ * Validated strictly at load, like everything else here: a cross-repo mistake
562
+ * found at hour three of a run has already cost the night.
563
+ */
564
+ if (repos !== undefined) {
565
+ const seen = new Set();
566
+ cfg.repos = repos.map((entry, i) => {
567
+ const at = `repos[${i}]`;
568
+ if (!isObj(entry))
569
+ throw new ConfigError(at, 'must be an object with id and path');
570
+ const id = str(entry, 'id', at);
571
+ if (!/^[A-Za-z0-9._-]+$/.test(id)) {
572
+ throw new ConfigError(`${at}.id`, 'must be letters, digits, dot, dash or underscore - it is an identity, not a path');
573
+ }
574
+ if (seen.has(id))
575
+ throw new ConfigError(`${at}.id`, `${id} is declared twice`);
576
+ seen.add(id);
577
+ return { id, path: str(entry, 'path', at) };
578
+ });
579
+ }
580
+ if (sessions !== undefined) {
581
+ const out = {};
582
+ if (sessions['repo'] !== undefined)
583
+ out.repo = str(sessions, 'repo', 'sessions');
584
+ if (sessions['budget_owner'] !== undefined)
585
+ out.budgetOwner = str(sessions, 'budget_owner', 'sessions');
586
+ // ⚠️ The PRESENCE of the key is the grant, so an explicitly empty list is a
587
+ // grant of nothing rather than no grant at all — the same distinction
588
+ // `scope.declared` draws two fields up.
589
+ if (sessions['scope'] !== undefined)
590
+ out.scope = strList(sessions, 'scope', 'sessions');
591
+ cfg.sessions = out;
592
+ }
593
+ if (crossRepoNeeds !== undefined) {
594
+ cfg.crossRepoNeeds = crossRepoNeeds.map((entry, i) => {
595
+ const at = `cross_repo_needs[${i}]`;
596
+ if (!isObj(entry))
597
+ throw new ConfigError(at, 'must be an object with repo and what');
598
+ // ⚠️ `repo` is NOT checked against `repos:` here. That is
599
+ // `crossRepoBlockedBy`'s answer — `undeclared` — and making it a load
600
+ // error instead would refuse a config whose only fault is that the two
601
+ // lists are being edited in either order.
602
+ return { repo: str(entry, 'repo', at), what: str(entry, 'what', at) };
603
+ });
604
+ }
605
+ // M6-10: the umbrella's window is the envelope's; declared once, in the limits.
606
+ if (umbrella !== null && cfg.machine !== undefined) {
607
+ const windowMs = umbrella.limits.windowMinutes * 60_000;
608
+ if (cfg.machine.envelope !== undefined) {
609
+ if (cfg.machine.envelope.windowMs !== windowMs) {
610
+ throw new ConfigError('machine.envelope.window_minutes', 'is declared in machine.programme.limits — set it there only');
611
+ }
612
+ }
613
+ else {
614
+ /**
615
+ * 🔴 THE OWNER'S `max_agents_in_flight` IS THE RUN CEILING OF THE ENVELOPE
616
+ * LOOPLY WRITES FOR THEM — it used to be a hard-coded 1.
617
+ *
618
+ * Nobody declared that 1: the owner declares their limits in the block,
619
+ * and this envelope exists only because the block implies one. So a
620
+ * programme declared "2 agents in flight", the coordinator placed two
621
+ * goals in two checkouts, and the autonomy tick then refused the second
622
+ * Start on every cadence — "1 run(s) are in flight and the envelope
623
+ * allows 1 (maxConcurrentRuns)" — while the run that raced past it
624
+ * refused itself with the same sentence. MEASURED live (LIVE-2). An
625
+ * envelope the owner writes themselves is theirs and is untouched above.
626
+ */
627
+ cfg.machine = {
628
+ ...cfg.machine,
629
+ envelope: {
630
+ maxConcurrentRuns: umbrella.limits.maxAgentsInFlight,
631
+ maxStartsPerWindow: 20,
632
+ windowMs,
633
+ maxWallClockMs: 8 * 60 * 60_000,
634
+ },
635
+ };
636
+ }
637
+ }
638
+ return cfg;
639
+ }
640
+ /**
641
+ * Warnings that do not block a run but that a user should see before starting one.
642
+ * Silence here was how the previous harness shipped 166 commits whose trailer
643
+ * named a check that had never run.
644
+ */
645
+ function configWarnings(cfg) {
646
+ const warnings = [];
647
+ if (!cfg.rails.forbiddenPaths.length) {
648
+ warnings.push('rails.forbidden_paths is empty — nothing in this repo is off limits');
649
+ }
650
+ if (!cfg.gates.some((g) => g.required)) {
651
+ warnings.push('no gate step is marked required — a green gate proves less than you think');
652
+ }
653
+ if (!cfg.proof.enabled) {
654
+ warnings.push('proof.enabled is false — rounds will commit on a green build alone');
655
+ }
656
+ /**
657
+ * M6-20 / §6.C: WHO CAN BE ASKED, AND WHAT HAPPENS IF NOBODY ANSWERS.
658
+ *
659
+ * 🔴 THE ORIGINAL WARNING WAS TRUE FOR A YEAR. `on_partial: ask` was the
660
+ * default, no CLI code produced a question, and a run answered its own with
661
+ * `discard` (the audit's F-03). It also said what it was waiting for —
662
+ * *"Making it really ask is a change to the round protocol and the owner's
663
+ * decision"* — and `OWNER_CHARTER.md` §6.C is that decision, so a paired
664
+ * machine now raises a real question and waits `ask_window_min` for it.
665
+ *
666
+ * ⚠️ AN UNPAIRED ONE STILL CANNOT, AND THAT IS WHY BOTH HALVES ARE NAMED.
667
+ * `parseConfig` is pure and cannot read the pairing, so guessing which half
668
+ * a reader is in would make this warning wrong for somebody.
669
+ */
670
+ if (cfg.proof.enabled && cfg.proof.onPartial === 'ask') {
671
+ warnings.push(`proof.on_partial is "ask": a paired machine raises a question and waits ${cfg.proof.askWindowMin} ` +
672
+ 'minutes for an answer on your phone; an unpaired one has nobody to ask and discards, saying so on ' +
673
+ 'the run\'s feed and on the item. Set it to "keep" or "discard" to decide without being asked');
674
+ }
675
+ if (cfg.notify.everyMin === 0) {
676
+ warnings.push('notify.every_min is 0 — this run will report nothing, including when it finishes');
677
+ }
678
+ /**
679
+ * 🔴 THE ONE BREAKING CHANGE IN THIS PROJECT'S HISTORY, SAID OUT LOUD AT
680
+ * LAST — IT USED TO ANNOUNCE ITSELF AT ROUND 1 OF AN OVERNIGHT RUN.
681
+ *
682
+ * Phase 6 made `agent.no_host_tools` REQUIRED of any configured provider,
683
+ * and the refusal lives in the transport: the first model call fails with a
684
+ * sentence naming the field. Nothing before that said anything — not
685
+ * `parseConfig`, not `looply doctor`, not `looply doctor --provider`, which
686
+ * returned PASS on exactly the configuration where every model call is
687
+ * refused.
688
+ *
689
+ * MEASURED by the cycle that found it: a config with no `provider:` line at
690
+ * all, just `agent: command: mycli exec`, parses clean, warns about nothing,
691
+ * passes doctor, and is refused at the first model call. That is EVERY
692
+ * project that ever set `agent.command` — not only the ones using a preset —
693
+ * and for each of them looply looked healthy right up to the moment it spent
694
+ * their evening finding out.
695
+ *
696
+ * ⚠️ THE REQUIREMENT ITSELF IS RIGHT AND IS NOT SOFTENED HERE. Looply cannot
697
+ * guess the flag that turns an unknown binary's tools off, and a guessed
698
+ * flag that silently does nothing reads exactly like one that works. What
699
+ * changes is WHEN a person is told: at the moment they can still fix it,
700
+ * rather than after the first model call has been spent.
701
+ */
702
+ /**
703
+ * 🔴 A DOLLAR CEILING WITH NOTHING TO ESTIMATE AGAINST REFUSES EVERY START.
704
+ *
705
+ * Not a hypothetical: admission writes its own reservation first, reads the
706
+ * window back, and an unpriced reservation makes that window unmeasurable —
707
+ * which `withinEnvelope` refuses on, correctly. So a person who writes
708
+ * `max_usd` and nothing else gets a machine that never starts anything, with
709
+ * the only explanation a sentence in a daemon log at 3am.
710
+ */
711
+ /**
712
+ * 🔴 THE CEILINGS THAT DISAGREE — AND THIS SENTENCE IS WHAT THE COORDINATOR
713
+ * END-TO-END PROOF COST AN HOUR TO LEARN.
714
+ *
715
+ * A project set `machine.max_workspaces: 2`; the scheduler correctly placed
716
+ * two goals in two checkouts; and exactly ONE run ever registered. The second
717
+ * was refused by `run.max_concurrent_runs`, which defaults to 1, AFTER a
718
+ * workspace had been cut, a goal placed and a process spawned. Neither number
719
+ * was wrong and nothing anywhere said they disagreed.
720
+ *
721
+ * ⚠️ IT NAMES THE BINDING CEILING RATHER THAN GUESSING AN INTENT. Looply does
722
+ * not raise anybody's limit for them — that is their decision — it only
723
+ * refuses to let the disagreement stay invisible.
724
+ */
725
+ const trouble = (0, core_1.concurrencyTrouble)({
726
+ workspaces: cfg.machine?.maxWorkspaces,
727
+ runs: cfg.run.maxConcurrentRuns,
728
+ agents: cfg.machine?.maxAgentsInFlight,
729
+ });
730
+ if (trouble !== null)
731
+ warnings.push(trouble);
732
+ const envelope = cfg.machine?.envelope;
733
+ if (envelope?.maxUsd !== undefined && !((envelope.estimateUsdPerStart ?? 0) > 0)) {
734
+ warnings.push('machine.envelope.max_usd is set but estimate_usd_per_start is not — every autonomous start ' +
735
+ 'will be REFUSED, because admission cannot show an unpriced start is under a dollar ceiling. ' +
736
+ 'Set estimate_usd_per_start to what you expect one run to cost');
737
+ }
738
+ /**
739
+ * 🔴 A `provider:` PRESET IS A CONFIGURED COMMAND TOO — AND THIS TEST COULD NOT
740
+ * SEE ONE, SO `looply doctor` PASSED A PROJECT WHOSE EVERY MODEL CALL REFUSES.
741
+ *
742
+ * `agent.command` still holds the DEFAULT at parse time when a preset is
743
+ * named: `resolveProvider` substitutes the preset's command later, at run
744
+ * time. So `configured` was false, no warning was pushed, doctor printed none
745
+ * and exited 0 — and the first model call of the first run was refused by a
746
+ * message naming the very field doctor had just declined to mention.
747
+ *
748
+ * MEASURED: a config of `agent:
749
+ provider: "codex"` and nothing else —
750
+ * `looply doctor` exit 0, no mention of `no_host_tools`.
751
+ */
752
+ const configured = cfg.agent.command !== exports.DEFAULTS.agent.command ||
753
+ (cfg.provider !== undefined && cfg.provider !== '');
754
+ if (configured && (cfg.agent.noHostTools?.length ?? 0) === 0) {
755
+ warnings.push('agent.no_host_tools is not set, and this project configures its own agent command ' +
756
+ '(directly, or through a provider preset) — ' +
757
+ 'every model call will be REFUSED until it is. Looply gives a model no host tools and ' +
758
+ 'cannot guess the argument that turns an unknown binary\'s own tools off; set it to those ' +
759
+ 'arguments (for example `no_host_tools: ["--no-tools"]`)');
760
+ }
761
+ return warnings;
762
+ }
763
+ //# sourceMappingURL=config.js.map