looply-cli 0.0.0-stage → 0.2.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 (785) 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 +2719 -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/server-client.d.ts +766 -0
  605. package/dist/server-client.d.ts.map +1 -0
  606. package/dist/server-client.js +475 -0
  607. package/dist/server-client.js.map +1 -0
  608. package/dist/session-adapter-runtime.d.ts +195 -0
  609. package/dist/session-adapter-runtime.d.ts.map +1 -0
  610. package/dist/session-adapter-runtime.js +373 -0
  611. package/dist/session-adapter-runtime.js.map +1 -0
  612. package/dist/session-checkpoint-runtime.d.ts +62 -0
  613. package/dist/session-checkpoint-runtime.d.ts.map +1 -0
  614. package/dist/session-checkpoint-runtime.js +268 -0
  615. package/dist/session-checkpoint-runtime.js.map +1 -0
  616. package/dist/session-control-transport.d.ts +106 -0
  617. package/dist/session-control-transport.d.ts.map +1 -0
  618. package/dist/session-control-transport.js +232 -0
  619. package/dist/session-control-transport.js.map +1 -0
  620. package/dist/session-observation-store.d.ts +98 -0
  621. package/dist/session-observation-store.d.ts.map +1 -0
  622. package/dist/session-observation-store.js +155 -0
  623. package/dist/session-observation-store.js.map +1 -0
  624. package/dist/session-observe-runtime.d.ts +123 -0
  625. package/dist/session-observe-runtime.d.ts.map +1 -0
  626. package/dist/session-observe-runtime.js +317 -0
  627. package/dist/session-observe-runtime.js.map +1 -0
  628. package/dist/session-store.d.ts +98 -0
  629. package/dist/session-store.d.ts.map +1 -0
  630. package/dist/session-store.js +116 -0
  631. package/dist/session-store.js.map +1 -0
  632. package/dist/sessions-cmd.d.ts +202 -0
  633. package/dist/sessions-cmd.d.ts.map +1 -0
  634. package/dist/sessions-cmd.js +609 -0
  635. package/dist/sessions-cmd.js.map +1 -0
  636. package/dist/settings-overlay.d.ts +53 -0
  637. package/dist/settings-overlay.d.ts.map +1 -0
  638. package/dist/settings-overlay.js +175 -0
  639. package/dist/settings-overlay.js.map +1 -0
  640. package/dist/setup-prompt.d.ts +34 -0
  641. package/dist/setup-prompt.d.ts.map +1 -0
  642. package/dist/setup-prompt.js +92 -0
  643. package/dist/setup-prompt.js.map +1 -0
  644. package/dist/setup.d.ts +103 -0
  645. package/dist/setup.d.ts.map +1 -0
  646. package/dist/setup.js +283 -0
  647. package/dist/setup.js.map +1 -0
  648. package/dist/shared-grants.d.ts +164 -0
  649. package/dist/shared-grants.d.ts.map +1 -0
  650. package/dist/shared-grants.js +242 -0
  651. package/dist/shared-grants.js.map +1 -0
  652. package/dist/signals.d.ts +55 -0
  653. package/dist/signals.d.ts.map +1 -0
  654. package/dist/signals.js +85 -0
  655. package/dist/signals.js.map +1 -0
  656. package/dist/source-cmd.d.ts +201 -0
  657. package/dist/source-cmd.d.ts.map +1 -0
  658. package/dist/source-cmd.js +684 -0
  659. package/dist/source-cmd.js.map +1 -0
  660. package/dist/source-verdict.d.ts +99 -0
  661. package/dist/source-verdict.d.ts.map +1 -0
  662. package/dist/source-verdict.js +182 -0
  663. package/dist/source-verdict.js.map +1 -0
  664. package/dist/spend-ledger.d.ts +350 -0
  665. package/dist/spend-ledger.d.ts.map +1 -0
  666. package/dist/spend-ledger.js +546 -0
  667. package/dist/spend-ledger.js.map +1 -0
  668. package/dist/stale-run-sweep.d.ts +79 -0
  669. package/dist/stale-run-sweep.d.ts.map +1 -0
  670. package/dist/stale-run-sweep.js +116 -0
  671. package/dist/stale-run-sweep.js.map +1 -0
  672. package/dist/start-attempts.d.ts +385 -0
  673. package/dist/start-attempts.d.ts.map +1 -0
  674. package/dist/start-attempts.js +613 -0
  675. package/dist/start-attempts.js.map +1 -0
  676. package/dist/status-cmd.d.ts +28 -0
  677. package/dist/status-cmd.d.ts.map +1 -0
  678. package/dist/status-cmd.js +116 -0
  679. package/dist/status-cmd.js.map +1 -0
  680. package/dist/stop-follow-up.d.ts +107 -0
  681. package/dist/stop-follow-up.d.ts.map +1 -0
  682. package/dist/stop-follow-up.js +172 -0
  683. package/dist/stop-follow-up.js.map +1 -0
  684. package/dist/surface-lease.d.ts +118 -0
  685. package/dist/surface-lease.d.ts.map +1 -0
  686. package/dist/surface-lease.js +485 -0
  687. package/dist/surface-lease.js.map +1 -0
  688. package/dist/sync.d.ts +54 -0
  689. package/dist/sync.d.ts.map +1 -0
  690. package/dist/sync.js +93 -0
  691. package/dist/sync.js.map +1 -0
  692. package/dist/syncing-ledger.d.ts +45 -0
  693. package/dist/syncing-ledger.d.ts.map +1 -0
  694. package/dist/syncing-ledger.js +53 -0
  695. package/dist/syncing-ledger.js.map +1 -0
  696. package/dist/temp-fixtures.d.ts +68 -0
  697. package/dist/temp-fixtures.d.ts.map +1 -0
  698. package/dist/temp-fixtures.js +38 -0
  699. package/dist/temp-fixtures.js.map +1 -0
  700. package/dist/token-window.d.ts +84 -0
  701. package/dist/token-window.d.ts.map +1 -0
  702. package/dist/token-window.js +143 -0
  703. package/dist/token-window.js.map +1 -0
  704. package/dist/tool-bridge.d.ts +177 -0
  705. package/dist/tool-bridge.d.ts.map +1 -0
  706. package/dist/tool-bridge.js +329 -0
  707. package/dist/tool-bridge.js.map +1 -0
  708. package/dist/tool-call-record.d.ts +197 -0
  709. package/dist/tool-call-record.d.ts.map +1 -0
  710. package/dist/tool-call-record.js +276 -0
  711. package/dist/tool-call-record.js.map +1 -0
  712. package/dist/tool-protocol.d.ts +135 -0
  713. package/dist/tool-protocol.d.ts.map +1 -0
  714. package/dist/tool-protocol.js +104 -0
  715. package/dist/tool-protocol.js.map +1 -0
  716. package/dist/tool-worker.d.ts +3 -0
  717. package/dist/tool-worker.d.ts.map +1 -0
  718. package/dist/tool-worker.js +478 -0
  719. package/dist/tool-worker.js.map +1 -0
  720. package/dist/toolchain-mirror.d.ts +86 -0
  721. package/dist/toolchain-mirror.d.ts.map +1 -0
  722. package/dist/toolchain-mirror.js +307 -0
  723. package/dist/toolchain-mirror.js.map +1 -0
  724. package/dist/trusted-git.d.ts +243 -0
  725. package/dist/trusted-git.d.ts.map +1 -0
  726. package/dist/trusted-git.js +920 -0
  727. package/dist/trusted-git.js.map +1 -0
  728. package/dist/ui.d.ts +76 -0
  729. package/dist/ui.d.ts.map +1 -0
  730. package/dist/ui.js +118 -0
  731. package/dist/ui.js.map +1 -0
  732. package/dist/untrusted-exec.d.ts +275 -0
  733. package/dist/untrusted-exec.d.ts.map +1 -0
  734. package/dist/untrusted-exec.js +479 -0
  735. package/dist/untrusted-exec.js.map +1 -0
  736. package/dist/untrusted-gate.d.ts +73 -0
  737. package/dist/untrusted-gate.d.ts.map +1 -0
  738. package/dist/untrusted-gate.js +226 -0
  739. package/dist/untrusted-gate.js.map +1 -0
  740. package/dist/uploader.d.ts +153 -0
  741. package/dist/uploader.d.ts.map +1 -0
  742. package/dist/uploader.js +204 -0
  743. package/dist/uploader.js.map +1 -0
  744. package/dist/verifier.d.ts +66 -0
  745. package/dist/verifier.d.ts.map +1 -0
  746. package/dist/verifier.js +170 -0
  747. package/dist/verifier.js.map +1 -0
  748. package/dist/verify-apply.d.ts +26 -0
  749. package/dist/verify-apply.d.ts.map +1 -0
  750. package/dist/verify-apply.js +36 -0
  751. package/dist/verify-apply.js.map +1 -0
  752. package/dist/verify-cmd.d.ts +44 -0
  753. package/dist/verify-cmd.d.ts.map +1 -0
  754. package/dist/verify-cmd.js +125 -0
  755. package/dist/verify-cmd.js.map +1 -0
  756. package/dist/verify-pass.d.ts +73 -0
  757. package/dist/verify-pass.d.ts.map +1 -0
  758. package/dist/verify-pass.js +103 -0
  759. package/dist/verify-pass.js.map +1 -0
  760. package/dist/welcome.d.ts +43 -0
  761. package/dist/welcome.d.ts.map +1 -0
  762. package/dist/welcome.js +116 -0
  763. package/dist/welcome.js.map +1 -0
  764. package/dist/workspace-provisioner.d.ts +65 -0
  765. package/dist/workspace-provisioner.d.ts.map +1 -0
  766. package/dist/workspace-provisioner.js +66 -0
  767. package/dist/workspace-provisioner.js.map +1 -0
  768. package/dist/workspace-quarantine.d.ts +64 -0
  769. package/dist/workspace-quarantine.d.ts.map +1 -0
  770. package/dist/workspace-quarantine.js +156 -0
  771. package/dist/workspace-quarantine.js.map +1 -0
  772. package/dist/workspace-residue-sweep.d.ts +113 -0
  773. package/dist/workspace-residue-sweep.d.ts.map +1 -0
  774. package/dist/workspace-residue-sweep.js +158 -0
  775. package/dist/workspace-residue-sweep.js.map +1 -0
  776. package/dist/workspace.d.ts +639 -0
  777. package/dist/workspace.d.ts.map +1 -0
  778. package/dist/workspace.js +2026 -0
  779. package/dist/workspace.js.map +1 -0
  780. package/package.json +54 -6
  781. package/win/CredProbe.cs +64 -0
  782. package/win/FakeClaude.cs +56 -0
  783. package/win/HandleProbe.cs +116 -0
  784. package/win/TokenProbe.cs +53 -0
  785. package/win/appcontainer.ps1 +500 -0
@@ -0,0 +1,920 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.repoConfigTrouble = repoConfigTrouble;
4
+ exports.resolveGitLayout = resolveGitLayout;
5
+ exports.repoConfigPaths = repoConfigPaths;
6
+ exports.repoConfigTroubleAt = repoConfigTroubleAt;
7
+ exports.worktreeMetadata = worktreeMetadata;
8
+ exports.repoRootTroubleAt = repoRootTroubleAt;
9
+ exports.noHooksDir = noHooksDir;
10
+ exports.gitBinary = gitBinary;
11
+ exports.trustedGitArgs = trustedGitArgs;
12
+ exports.trustedGitEnv = trustedGitEnv;
13
+ exports.mainWorktreeRoot = mainWorktreeRoot;
14
+ exports.isCheckoutRoot = isCheckoutRoot;
15
+ exports.repoIdentityPath = repoIdentityPath;
16
+ exports.linkedRepoCommonDir = linkedRepoCommonDir;
17
+ const node_fs_1 = require("node:fs");
18
+ const node_path_1 = require("node:path");
19
+ const node_os_1 = require("node:os");
20
+ /**
21
+ * THE REPOSITORY IS UNTRUSTED INPUT TO A TRUSTED PROCESS.
22
+ *
23
+ * `GitDriver` runs as the daemon. The repository it operates on is written by
24
+ * the coding agent, and git executes programs named by configuration — so a
25
+ * round that writes eight lines into `.git/config` gets arbitrary code running
26
+ * under the daemon's identity, with the daemon's environment and whatever
27
+ * credentials are ambient to the account.
28
+ *
29
+ * This is not hypothetical and it is not only hooks. Measured against the exact
30
+ * verbs `GitDriver` issues, EIGHT mechanisms execute:
31
+ *
32
+ * filter.<any>.clean → `add -A`, `add -N`
33
+ * filter.<any>.smudge → `checkout --`, `reset --hard`
34
+ * diff.<any>.textconv → `diff HEAD`
35
+ * diff.external → `diff HEAD`
36
+ * core.fsmonitor → `status`
37
+ * core.hooksPath / hooks → `commit`
38
+ *
39
+ * Only `core.pager` did not fire, and only because stdio is a pipe rather than
40
+ * a terminal — which is a property of how we spawn, not a property of git.
41
+ *
42
+ * TWO MECHANISMS, BECAUSE ONE IS NOT ENOUGH.
43
+ *
44
+ * `core.hooksPath` has a fixed name, so it can simply be overridden on the
45
+ * command line, where it beats anything the repository says. Filters cannot:
46
+ * `filter.<ANY NAME>.clean` is an unbounded family and no list of `-c`
47
+ * overrides can enumerate it. So the second mechanism is refusal — the config
48
+ * is read as a plain file and the operation is declined before git is invoked
49
+ * at all.
50
+ *
51
+ * SCOPED TO THE REPOSITORY'S OWN CONFIG, deliberately. System and global config
52
+ * belong to the person, not to the round: this machine's system config defines
53
+ * `filter.lfs.clean`, and refusing that would break every repository with Git
54
+ * LFS installed while protecting nothing.
55
+ */
56
+ /**
57
+ * Config keys that can name a program for git to run.
58
+ *
59
+ * Patterns, not names — `filter\..*\.clean` covers a filter called anything at
60
+ * all, which is the whole point. Each entry either fired in the audit or names
61
+ * a documented execution path of the same shape.
62
+ */
63
+ const EXECUTABLE_KEYS = [
64
+ /^filter\..*\.(clean|smudge|process)$/,
65
+ /^diff\..*\.(textconv|command)$/,
66
+ /^diff\.external$/,
67
+ /^merge\..*\.driver$/,
68
+ /^core\.(fsmonitor|hookspath|pager|editor|sshcommand)$/,
69
+ /^sequence\.editor$/,
70
+ /^pager\./,
71
+ /^alias\./,
72
+ // An include pulls in another file wholesale, so it can reintroduce every
73
+ // key above from somewhere this check never looked.
74
+ /^include\.path$/,
75
+ /^includeif\./,
76
+ // `ext::` transports name a command to run. No remote is used today; this is
77
+ // here so that adding one later cannot quietly open the door.
78
+ /^protocol\..*\.command$/,
79
+ /^credential\./,
80
+ ];
81
+ /**
82
+ * Config keys that move the working tree out from under the caller.
83
+ *
84
+ * A DIFFERENT HAZARD FROM THE LIST ABOVE, which is why it is a different list
85
+ * and a different sentence: `core.worktree` names no program, so nothing here
86
+ * gets code execution. It makes `git rev-parse --show-toplevel` — and every
87
+ * verb `GitDriver` issues — operate somewhere the caller never named.
88
+ *
89
+ * ⚠️ MEASURED. With `core.worktree` pointing at a sibling directory,
90
+ * `GitDriver.discard()` ran `reset --hard` and `clean -fd` against that
91
+ * directory: a file holding uncommitted work was overwritten and another was
92
+ * deleted, while `repoRootTroubleAt` — whose whole promise is "the tree is the
93
+ * one the caller named" — returned null, because it compares against the
94
+ * directory holding `.git` and git does not.
95
+ *
96
+ * `GIT_WORK_TREE` and `GIT_DIR` do the same thing from the ENVIRONMENT rather
97
+ * than from the repository's config. They are handled where they belong, in
98
+ * `trustedGitEnv` below, which builds the `GIT_` namespace up instead of
99
+ * inheriting it — a config key is refused, an environment variable is dropped.
100
+ */
101
+ const REDIRECTING_KEYS = [/^core\.worktree$/];
102
+ /**
103
+ * One section header, and whatever follows it ON THE SAME LINE.
104
+ *
105
+ * 🔴 BOTH HALVES WERE EXPLOITABLE, and both were measured rather than imagined.
106
+ *
107
+ * `[filter "ev"] clean = sh evil` git resolves `filter.ev.clean`. The old
108
+ * parser `continue`d after a header and
109
+ * never looked at the rest of the line, so
110
+ * it reported nothing.
111
+ * `[filter "]"]` the old `^\[([^\]]+)\]` stopped at the
112
+ * FIRST `]`, which is inside the quotes.
113
+ * Section became `filter`, the key became
114
+ * `filter.clean`, and no pattern matched.
115
+ *
116
+ * Each produced a marker file on disk through `add -A`. So the closing bracket
117
+ * is now found by a scanner that knows about quoting and backslash escapes, and
118
+ * the remainder of the line is parsed as a variable.
119
+ */
120
+ function parseHeader(line) {
121
+ let inQuote = false;
122
+ let end = -1;
123
+ for (let i = 1; i < line.length; i++) {
124
+ const c = line[i];
125
+ if (inQuote) {
126
+ if (c === '\\') {
127
+ i += 1;
128
+ continue;
129
+ }
130
+ if (c === '"')
131
+ inQuote = false;
132
+ continue;
133
+ }
134
+ if (c === '"') {
135
+ inQuote = true;
136
+ continue;
137
+ }
138
+ if (c === ']') {
139
+ end = i;
140
+ break;
141
+ }
142
+ }
143
+ if (end === -1)
144
+ return null;
145
+ const inner = line.slice(1, end);
146
+ const rest = line.slice(end + 1);
147
+ // `[filter "ev"]`, `[core]`, and the legacy `[filter.ev]` all arrive here. The
148
+ // quoted subsection keeps its case in git but the section and key do not, and
149
+ // every pattern below ignores the subsection's spelling anyway.
150
+ const m = /^\s*([^\s"]+)\s*(?:"((?:[^"\\]|\\.)*)")?\s*$/.exec(inner);
151
+ if (m === null)
152
+ return null;
153
+ const base = m[1].toLowerCase();
154
+ const sub = m[2];
155
+ return {
156
+ section: sub === undefined ? base : `${base}.${sub.replace(/\\(.)/g, '$1')}`,
157
+ rest,
158
+ };
159
+ }
160
+ /**
161
+ * Every `section.subsection.key` this text defines, lowercased as git names it.
162
+ *
163
+ * `malformed` is not a detail: a header this cannot parse is one whose keys
164
+ * cannot be attributed to any section, and silently dropping them is the shape
165
+ * of every hole above. The caller refuses instead.
166
+ */
167
+ function dottedKeys(text) {
168
+ const out = [];
169
+ let section = '';
170
+ let malformed = false;
171
+ for (const raw of text.split(/\r?\n/)) {
172
+ let line = raw.trim();
173
+ if (line.length === 0 || line.startsWith('#') || line.startsWith(';'))
174
+ continue;
175
+ if (line.startsWith('[')) {
176
+ const header = parseHeader(line);
177
+ if (header === null) {
178
+ // Git would reject the file outright. We cannot know what section the
179
+ // lines below belong to, so we must not guess — and must not proceed.
180
+ malformed = true;
181
+ section = '';
182
+ continue;
183
+ }
184
+ section = header.section;
185
+ line = header.rest.trim();
186
+ if (line.length === 0 || line.startsWith('#') || line.startsWith(';'))
187
+ continue;
188
+ }
189
+ if (section.length === 0)
190
+ continue;
191
+ // At most one variable per line: git reads a variable's value to the end of
192
+ // the line, so anything after `=` is the value and never another key.
193
+ const eq = line.indexOf('=');
194
+ const key = (eq === -1 ? line : line.slice(0, eq)).trim().toLowerCase();
195
+ if (key.length === 0)
196
+ continue;
197
+ out.push(`${section}.${key}`);
198
+ }
199
+ return { keys: out, malformed };
200
+ }
201
+ /**
202
+ * The first executable key this config defines, in words, or null if none.
203
+ *
204
+ * Takes the text rather than a path so the rule is testable without a
205
+ * repository, and so the caller decides what an unreadable config means.
206
+ */
207
+ function repoConfigTrouble(text) {
208
+ const { keys, malformed } = dottedKeys(text);
209
+ for (const key of keys) {
210
+ if (EXECUTABLE_KEYS.some((p) => p.test(key))) {
211
+ return `this repository's git config sets ${key}, which names a program for git to run`;
212
+ }
213
+ if (REDIRECTING_KEYS.some((p) => p.test(key))) {
214
+ return `this repository's git config sets ${key}, which points git at a different working tree`;
215
+ }
216
+ }
217
+ if (malformed) {
218
+ return `this repository's git config has a section header this cannot parse, so it could not be checked`;
219
+ }
220
+ return null;
221
+ }
222
+ /** `code` off an fs error without asserting the error's shape. */
223
+ function errCode(e) {
224
+ return typeof e === 'object' && e !== null && 'code' in e ? String(e.code) : 'unknown';
225
+ }
226
+ /**
227
+ * Whether `dir` is really a git directory, by git's own test.
228
+ *
229
+ * 🔴 THE HOLE THIS CLOSES WAS BOTH CHECKS AT ONCE, and it was demonstrated.
230
+ * Accepting any directory *named* `.git` meant that
231
+ *
232
+ * mkdir -p sub/.git # empty, and the agent may create it
233
+ *
234
+ * made `resolveGitLayout(sub)` answer `{root: sub}`. Git ignores such a decoy
235
+ * and keeps walking — `git -C sub rev-parse --absolute-git-dir` still names the
236
+ * real repository above, and `git -C sub config --get filter.ev.clean` still
237
+ * resolved the malicious program. But looply's checks did not:
238
+ * `repoConfigTroubleAt(sub)` returned null, so the config was never examined,
239
+ * and `repoRootTroubleAt(sub)` returned null, so `reset --hard` issued from
240
+ * `sub` reset the whole repository above it and overwrote uncommitted work.
241
+ *
242
+ * So the markers are required, and a directory that lacks them is walked PAST
243
+ * rather than stopped at — which is exactly what git does, and which lands on
244
+ * the real repository whose config then gets read.
245
+ *
246
+ * `commondir` is the linked-worktree case: `<common>/worktrees/<name>` holds
247
+ * `HEAD` and `commondir` but has neither `objects` nor `refs` of its own.
248
+ */
249
+ function looksLikeGitDir(dir) {
250
+ try {
251
+ if (!(0, node_fs_1.statSync)((0, node_path_1.join)(dir, 'HEAD')).isFile())
252
+ return false;
253
+ }
254
+ catch {
255
+ return false;
256
+ }
257
+ if ((0, node_fs_1.existsSync)((0, node_path_1.join)(dir, 'commondir')))
258
+ return true;
259
+ return (0, node_fs_1.existsSync)((0, node_path_1.join)(dir, 'objects')) && (0, node_fs_1.existsSync)((0, node_path_1.join)(dir, 'refs'));
260
+ }
261
+ /** The `gitdir:` line of a linked worktree's `.git` file, resolved against it. */
262
+ function gitdirPointer(text, from) {
263
+ // Git's `read_gitfile_gently` strips trailing NEWLINES, not trailing spaces —
264
+ // so a pointer ending in a space names a directory whose name ends in a space,
265
+ // and trimming it here would resolve to a different one.
266
+ const m = /^gitdir:[ \t]*(.*?)[\r\n]*$/.exec(text.replace(/[\r\n]+$/, ''));
267
+ if (m === null)
268
+ return null;
269
+ const p = m[1];
270
+ if (p.length === 0)
271
+ return null;
272
+ return (0, node_path_1.isAbsolute)(p) ? p : (0, node_path_1.resolve)(from, p);
273
+ }
274
+ /**
275
+ * Find the repository governing `cwd`, the way git does: look for a `.git`
276
+ * entry here, then in each parent, to the filesystem root.
277
+ *
278
+ * WALKING UP IS DELIBERATE. Run from a subdirectory, the old check looked at
279
+ * `<subdir>/.git`, found nothing, and returned "no trouble" — while every git
280
+ * command it was guarding still ran against the repository above. That was a
281
+ * second way to reach the same fail-open, and it did not need a worktree.
282
+ */
283
+ function resolveGitLayout(cwd) {
284
+ const lexical = walkForLayout((0, node_path_1.resolve)(cwd));
285
+ if (lexical.kind !== 'none')
286
+ return lexical;
287
+ /**
288
+ * ⚠️ AND AGAIN PHYSICALLY, because this walk is lexical and git's is not.
289
+ *
290
+ * `dirname` is string arithmetic: it climbs out of a junction or symlink by
291
+ * name and never reaches the directory the link actually points into. Driven
292
+ * with a cwd inside a Windows junction, `git rev-parse --show-toplevel` named
293
+ * the real repository while this answered `none` — and `none` means "no
294
+ * repository here", which is the silent allow. Node reports an unresolved
295
+ * cwd for exactly this case: `process.cwd()` inside a junction returns the
296
+ * junction path under cmd.exe and PowerShell.
297
+ *
298
+ * Only on the `none` path, so the ordinary checkout pays one `resolve` and
299
+ * nothing else.
300
+ */
301
+ const real = realOrResolved(cwd);
302
+ return real === (0, node_path_1.resolve)(cwd) ? lexical : walkForLayout(real);
303
+ }
304
+ function walkForLayout(start) {
305
+ let dir = start;
306
+ for (;;) {
307
+ const dotGit = (0, node_path_1.join)(dir, '.git');
308
+ let st;
309
+ try {
310
+ st = (0, node_fs_1.statSync)(dotGit);
311
+ }
312
+ catch (e) {
313
+ const code = errCode(e);
314
+ // Not here. ENOTDIR means some component of this path is a file rather
315
+ // than a directory, which on Windows usually surfaces as ENOENT anyway;
316
+ // either way the answer is the same as an absence — keep climbing, and
317
+ // let the repository above be found. (An earlier comment here claimed
318
+ // this STOPPED the walk. It never did, and stopping would be wrong.)
319
+ if (code === 'ENOENT' || code === 'ENOTDIR') {
320
+ const up = (0, node_path_1.dirname)(dir);
321
+ if (up === dir)
322
+ return { kind: 'none' };
323
+ dir = up;
324
+ continue;
325
+ }
326
+ // Present but unstattable — a permission wall, not an absence.
327
+ return { kind: 'fault', because: `${dotGit} could not be read (${code})` };
328
+ }
329
+ let gitDir;
330
+ if (st.isDirectory()) {
331
+ if (!looksLikeGitDir(dotGit)) {
332
+ // A directory called `.git` that is not one. Git walks past it; so do
333
+ // we, or the repository that actually governs this cwd is never read.
334
+ const up = (0, node_path_1.dirname)(dir);
335
+ if (up === dir)
336
+ return { kind: 'none' };
337
+ dir = up;
338
+ continue;
339
+ }
340
+ gitDir = dotGit;
341
+ }
342
+ else if (st.isFile()) {
343
+ let text;
344
+ try {
345
+ text = (0, node_fs_1.readFileSync)(dotGit, 'utf8');
346
+ }
347
+ catch (e) {
348
+ return { kind: 'fault', because: `${dotGit} names a git directory but could not be read (${errCode(e)})` };
349
+ }
350
+ const p = gitdirPointer(text, dir);
351
+ if (p === null) {
352
+ return { kind: 'fault', because: `${dotGit} is a file that does not name a git directory` };
353
+ }
354
+ // Normalised so that a forward-slashed pointer and a backslashed
355
+ // `commonDir` cannot become two spellings of one path in a caller that
356
+ // compares them as strings.
357
+ gitDir = (0, node_path_1.normalize)(p);
358
+ }
359
+ else {
360
+ return { kind: 'fault', because: `${dotGit} is neither a file nor a directory` };
361
+ }
362
+ try {
363
+ if (!(0, node_fs_1.statSync)(gitDir).isDirectory()) {
364
+ return { kind: 'fault', because: `${gitDir} is not a git directory` };
365
+ }
366
+ }
367
+ catch (e) {
368
+ return { kind: 'fault', because: `${gitDir} could not be read (${errCode(e)})` };
369
+ }
370
+ // A FAULT HERE, not a walk-past. A `.git` FILE that names something which
371
+ // is not a git directory is corruption or misdirection, not the ordinary
372
+ // "there is no repository in this folder" that a bare directory means.
373
+ if (!looksLikeGitDir(gitDir)) {
374
+ return { kind: 'fault', because: `${gitDir} does not look like a git directory` };
375
+ }
376
+ // `commondir` is absent in an ordinary checkout and present in a linked
377
+ // worktree, where it is usually the relative `../..`.
378
+ let commonDir = gitDir;
379
+ try {
380
+ // `strbuf_rtrim`-style: git strips trailing newlines here, not spaces.
381
+ const raw = (0, node_fs_1.readFileSync)((0, node_path_1.join)(gitDir, 'commondir'), 'utf8').replace(/[\r\n]+$/, '');
382
+ if (raw.length === 0) {
383
+ return { kind: 'fault', because: `${(0, node_path_1.join)(gitDir, 'commondir')} is empty` };
384
+ }
385
+ commonDir = (0, node_path_1.normalize)((0, node_path_1.isAbsolute)(raw) ? raw : (0, node_path_1.resolve)(gitDir, raw));
386
+ }
387
+ catch (e) {
388
+ const code = errCode(e);
389
+ if (code !== 'ENOENT') {
390
+ return { kind: 'fault', because: `${(0, node_path_1.join)(gitDir, 'commondir')} could not be read (${code})` };
391
+ }
392
+ }
393
+ return { kind: 'ok', root: dir, gitDir, commonDir };
394
+ }
395
+ }
396
+ /**
397
+ * Every config file that governs this repository, most-shared first.
398
+ *
399
+ * `config.worktree` is read only when `extensions.worktreeConfig` is set, but
400
+ * it is scanned unconditionally: a file that git might read is a file this
401
+ * check must not skip, and scanning one git ignores costs a refusal nobody
402
+ * could have exploited anyway.
403
+ */
404
+ function repoConfigPaths(layout) {
405
+ const paths = [(0, node_path_1.join)(layout.commonDir, 'config')];
406
+ const perWorktree = (0, node_path_1.join)(layout.gitDir, 'config.worktree');
407
+ if (!paths.includes(perWorktree))
408
+ paths.push(perWorktree);
409
+ return paths;
410
+ }
411
+ /**
412
+ * Judge the config of the repository governing `cwd`, in words, or null.
413
+ *
414
+ * A missing repository is not a fault and neither is a missing config file — a
415
+ * config that does not exist defines nothing. A repository whose metadata or
416
+ * config cannot be READ is a refusal: the whole mechanism is "decline before
417
+ * git runs", and declining is the only answer that stays sound when the file
418
+ * the decision rests on is unavailable.
419
+ */
420
+ function repoConfigTroubleAt(cwd) {
421
+ const layout = resolveGitLayout(cwd);
422
+ if (layout.kind === 'none') {
423
+ // No repository, here or above. Git will produce its own error if one was
424
+ // expected, and there is no config to have been subverted.
425
+ return null;
426
+ }
427
+ if (layout.kind === 'fault') {
428
+ return `this repository's git metadata could not be read, so its config could not be checked — ${layout.because}`;
429
+ }
430
+ for (const path of repoConfigPaths(layout)) {
431
+ let text;
432
+ try {
433
+ text = (0, node_fs_1.readFileSync)(path, 'utf8');
434
+ }
435
+ catch (e) {
436
+ const code = errCode(e);
437
+ if (code === 'ENOENT')
438
+ continue;
439
+ return `this repository's git config at ${path} could not be read (${code}), so it could not be checked`;
440
+ }
441
+ const trouble = repoConfigTrouble(text);
442
+ if (trouble !== null)
443
+ return trouble;
444
+ }
445
+ return null;
446
+ }
447
+ /**
448
+ * The metadata directories of the worktree AT `dir`, or null when `dir` is not
449
+ * itself one.
450
+ *
451
+ * ⚠️ DELIBERATELY NOT THE ENCLOSING REPOSITORY, and the difference is the whole
452
+ * reason this is a separate function. {@link resolveGitLayout} walks up, which
453
+ * is the right answer to "whose config could execute when git runs here" — a
454
+ * command issued in a subdirectory is still governed by the repository above.
455
+ * It is the WRONG answer to "what does this grant own": a directory that merely
456
+ * SITS INSIDE a repository is not that repository's worktree, and protecting an
457
+ * ancestor's metadata would describe a boundary the container does not have.
458
+ *
459
+ * Caught by `agent-contained.spec.ts`, which passes a `projectDir` that is not
460
+ * a repository and pins the protected list at three entries.
461
+ */
462
+ function worktreeMetadata(dir) {
463
+ const layout = resolveGitLayout(dir);
464
+ if (layout.kind !== 'ok')
465
+ return null;
466
+ if (realOrResolved(layout.root) !== realOrResolved(dir))
467
+ return null;
468
+ return { gitDir: layout.gitDir, commonDir: layout.commonDir };
469
+ }
470
+ /** `realpathSync` where it works, the resolved path where it does not. */
471
+ function realOrResolved(p) {
472
+ try {
473
+ return (0, node_fs_1.realpathSync)(p);
474
+ }
475
+ catch {
476
+ return (0, node_path_1.resolve)(p);
477
+ }
478
+ }
479
+ /**
480
+ * Whether `cwd` is the root of the repository it belongs to, in words, or null.
481
+ *
482
+ * THE CHECK THAT NEVER EXISTED. `looply` derives three things from `cwd` — the
483
+ * project identity, `.looply/state`, and the tree every git verb operates on —
484
+ * and nothing established that `cwd` was a repository at all, let alone its
485
+ * root. Started one directory down, the run wrote its state into a subdirectory
486
+ * while committing, discarding and resetting the whole repository above it: a
487
+ * `reset --hard` scoped to a tree the person never named.
488
+ *
489
+ * A worktree layout makes it reachable by accident rather than by mistake,
490
+ * which is why it lands here rather than after the first worktree exists.
491
+ */
492
+ function repoRootTroubleAt(cwd) {
493
+ const layout = resolveGitLayout(cwd);
494
+ if (layout.kind === 'none') {
495
+ // Unchanged from before this check existed: git says what it thinks of a
496
+ // directory that is not a repository, in its own words.
497
+ return null;
498
+ }
499
+ if (layout.kind === 'fault') {
500
+ return `this repository's git metadata could not be read — ${layout.because}`;
501
+ }
502
+ if (realOrResolved(layout.root) !== realOrResolved(cwd)) {
503
+ /**
504
+ * ⚠️ NEVER "run from `<root>` instead", which is what this said first.
505
+ *
506
+ * `<root>` may be nothing to do with the person's project. A plain folder
507
+ * under a dotfiles or monorepo checkout — a very ordinary thing to have on
508
+ * a Desktop — resolves to that enclosing repository, and following the
509
+ * advice would point looply at a tree it may then commit to, discard and
510
+ * `reset --hard`: precisely the harm this refusal exists to prevent.
511
+ *
512
+ * So the two cases are told apart, and only the one that IS a subdirectory
513
+ * of the intended project gets a destination.
514
+ */
515
+ const here = (0, node_path_1.resolve)(cwd);
516
+ if ((0, node_fs_1.existsSync)((0, node_path_1.join)(here, '.git'))) {
517
+ return (`this is not the root of its git repository — ${here} holds git metadata that git does not ` +
518
+ `recognise, while ${layout.root} is the repository that governs it`);
519
+ }
520
+ return (`this is not the root of a git repository — ${here} sits inside ${layout.root}. ` +
521
+ `If ${layout.root} is the project you mean, start looply there; if it is not, ` +
522
+ `initialise a repository here first`);
523
+ }
524
+ return null;
525
+ }
526
+ /**
527
+ * An empty directory to point `core.hooksPath` at.
528
+ *
529
+ * Created rather than merely named: a path that does not exist would also work
530
+ * today, but an empty directory we make is one the repository cannot fill by
531
+ * simply creating what git was told to look for.
532
+ *
533
+ * 🔴 AND IT IS EMPTIED EVERY TIME, WHICH IT WAS NOT.
534
+ *
535
+ * This was one machine-global `%TEMP%\looply-no-hooks`, created once and never
536
+ * looked at again — passed as `core.hooksPath` on EVERY trusted git call of
537
+ * every workspace of every project on the machine. `mkdirSync` is recursive and
538
+ * idempotent, so the first caller made it and every later caller trusted it
539
+ * without ever asking what was inside.
540
+ *
541
+ * `%TEMP%` is world-writable on Windows. Anything that can write there could
542
+ * drop a `pre-commit` into that directory and have it executed by the very
543
+ * mechanism that exists to guarantee no repository hook ever runs — with the
544
+ * daemon's own privileges, uncontained. Not a workspace-isolation problem: a
545
+ * one-line hole in the hook defence itself, which nothing would have noticed
546
+ * because the directory is invisible and the flag reads as already handled.
547
+ *
548
+ * ⚠️ SO IT IS CHECKED, NOT ASSUMED. Anything sitting in it is removed before
549
+ * the path is handed to git. Sweeping is cheap — the directory is empty in
550
+ * every ordinary case — and a sweep that fails still leaves git pointed at a
551
+ * directory whose contents this call has at least tried to control.
552
+ */
553
+ function noHooksDir() {
554
+ const dir = (0, node_path_1.join)((0, node_os_1.tmpdir)(), 'looply-no-hooks');
555
+ try {
556
+ (0, node_fs_1.mkdirSync)(dir, { recursive: true });
557
+ }
558
+ catch {
559
+ // Already there, or a filesystem that will fail the same way when git
560
+ // looks. Either way git finds no hooks, which is the point.
561
+ }
562
+ try {
563
+ for (const name of (0, node_fs_1.readdirSync)(dir)) {
564
+ (0, node_fs_1.rmSync)((0, node_path_1.join)(dir, name), { recursive: true, force: true });
565
+ }
566
+ }
567
+ catch {
568
+ // Unreadable or unwritable. Git will find whatever is there; nothing here
569
+ // can do better, and failing a run over a temp directory would be worse.
570
+ }
571
+ return dir;
572
+ }
573
+ let cachedGitBinary;
574
+ /**
575
+ * The absolute path of the `git` this machine will run, resolved from PATH only.
576
+ *
577
+ * 🔴 A BARE `spawn('git', …, {cwd})` LETS THE REPOSITORY SUPPLY THE BINARY.
578
+ *
579
+ * On Windows the process creation path searches the WORKING DIRECTORY BEFORE
580
+ * PATH. `cwd` here is the project root, and `untrustedGrants` hands the
581
+ * contained agent `{ path: projectDir, write: true }` — so a `git.exe` the agent
582
+ * writes runs OUTSIDE the container, as the daemon, on `status`, `add -A`,
583
+ * `diff HEAD`, `commit`, `reset --hard`, `clean -fd` and `push`. Measured:
584
+ * `spawnSync('git', ['--version'], { cwd: <dir with a planted git.exe> })`
585
+ * executed the plant; the same call from another directory ran real git.
586
+ *
587
+ * That defeats everything else in this file at once — the config check, the
588
+ * root check, the rebuilt `GIT_` namespace, the `GIT_DIR` pin, `core.hooksPath`
589
+ * and `commit.gpgsign=false` — because none of them constrains a program that
590
+ * is not git. `exec-domains.ts` already makes exactly this argument for the
591
+ * runtime mirror ("untrusted code that could replace `node.exe` would be
592
+ * untrusted code choosing what every later gate runs"); it simply had never
593
+ * been applied to git.
594
+ *
595
+ * Resolved once and cached: PATH does not change under a running daemon, and a
596
+ * per-call PATH walk on every git verb would be a needless cost.
597
+ */
598
+ function gitBinary() {
599
+ if (cachedGitBinary !== undefined)
600
+ return cachedGitBinary;
601
+ const win = process.platform === 'win32';
602
+ const exts = win ? (process.env['PATHEXT'] ?? '.EXE').split(';') : [''];
603
+ // PATH ONLY. The cwd is deliberately not searched — it is the thing being
604
+ // defended against.
605
+ for (const dir of (process.env['PATH'] ?? '').split(win ? ';' : ':')) {
606
+ const d = dir.trim().replace(/^"|"$/g, '');
607
+ if (d.length === 0)
608
+ continue;
609
+ for (const ext of exts) {
610
+ const candidate = (0, node_path_1.join)(d, `git${ext.toLowerCase()}`);
611
+ try {
612
+ if ((0, node_fs_1.statSync)(candidate).isFile()) {
613
+ cachedGitBinary = candidate;
614
+ return candidate;
615
+ }
616
+ }
617
+ catch {
618
+ // Not here; keep walking.
619
+ }
620
+ }
621
+ }
622
+ cachedGitBinary = null;
623
+ return null;
624
+ }
625
+ /**
626
+ * Arguments every trusted git invocation carries, before the caller's own.
627
+ *
628
+ * `-c` beats repository config, so this is enforcement rather than a request:
629
+ * the repository cannot override it back.
630
+ */
631
+ function trustedGitArgs() {
632
+ return [
633
+ '-c',
634
+ `core.hooksPath=${noHooksDir()}`,
635
+ /**
636
+ * SIGNING IS NOT AN ATTACK, SO IT IS NOT REFUSED — IT IS TURNED OFF HERE.
637
+ *
638
+ * A person who signs their commits has `commit.gpgsign = true` and a
639
+ * `gpg.program` in their GLOBAL config, and refusing their repository over
640
+ * it would be absurd. But `git commit` then spawns that program under the
641
+ * daemon, which is the same execution this file exists to prevent — and it
642
+ * is not hypothetical: with signing on, `commit` failed with "gpg failed to
643
+ * sign the data" after the named program ran.
644
+ *
645
+ * `-c` is the same scoped override `core.hooksPath` above uses: it applies
646
+ * to this invocation only and mutates nothing of the person's. Verified to
647
+ * beat both a global-config `commit.gpgsign` and one injected through
648
+ * `GIT_CONFIG_COUNT`, in gpg and ssh signing formats alike.
649
+ *
650
+ * `push.gpgSign` is here for a second reason as well as the first: with it
651
+ * set, looply's push FAILS outright — "the receiving end does not support
652
+ * --signed push" — so this is a correctness fix, not only a safety one.
653
+ */
654
+ '-c',
655
+ 'commit.gpgsign=false',
656
+ '-c',
657
+ 'push.gpgSign=false',
658
+ ];
659
+ }
660
+ /**
661
+ * The environment for a trusted git invocation.
662
+ *
663
+ * 🔴 THE `GIT_` NAMESPACE IS THE ENTIRE REDIRECT SURFACE, so it is the one
664
+ * namespace built up rather than inherited — exactly the principle
665
+ * `exec-domains.ts` already states for contained children, applied here to a
666
+ * single prefix instead of a whole environment.
667
+ *
668
+ * Spreading `process.env` handed every one of these to git, and each was
669
+ * demonstrated against looply's own verbs on a clean repository:
670
+ *
671
+ * GIT_DIR, GIT_WORK_TREE, GIT_COMMON_DIR operate on a DIFFERENT repository
672
+ * while both Phase 0 checks — which
673
+ * read the cwd — return null.
674
+ * `GIT_WORK_TREE` alone is the worst:
675
+ * git keeps this repository's gitdir
676
+ * and index and relocates the TREE,
677
+ * which is what turns `discard()`'s
678
+ * `reset --hard` + `clean -fd` into
679
+ * data loss somewhere else.
680
+ * GIT_CONFIG_COUNT/KEY/VALUE, inject config, so
681
+ * GIT_CONFIG_PARAMETERS, `filter.<any>.clean` fires on
682
+ * GIT_CONFIG_GLOBAL, GIT_CONFIG_SYSTEM `status`, `add -A`, `diff HEAD`
683
+ * and `commit`. The repository's own
684
+ * config is clean throughout.
685
+ * GIT_EXTERNAL_DIFF fires on `diff HEAD`.
686
+ * GIT_INDEX_FILE `add -A` writes a foreign index, so
687
+ * the round's own commit carries none
688
+ * of its work. Git EXPORTS this to
689
+ * hooks, so it needs no attacker.
690
+ * GIT_OBJECT_DIRECTORY writes this repository's blobs into
691
+ * a directory somebody else named.
692
+ * GIT_NAMESPACE the push lands at
693
+ * `refs/namespaces/<ns>/...` while
694
+ * `ls-remote` — under the same
695
+ * namespace — reports it present at
696
+ * the real ref. The write and its
697
+ * verification lie consistently.
698
+ * GIT_TRACE, GIT_TRACE2* an arbitrary file create-and-append
699
+ * primitive, as the daemon.
700
+ * GIT_LITERAL_PATHSPECS breaks the `:(exclude).looply`
701
+ * argument — fails closed, but only
702
+ * by luck.
703
+ *
704
+ * ⚠️ THE `GIT_` PREFIX IS DROPPED EXCEPT FOR `AMBIENT_GIT_KEPT` below, and both
705
+ * halves of that are deliberate. PATH, HOME, APPDATA, SSH_AUTH_SOCK,
706
+ * SSH_ASKPASS, GCM_*, LANG and the lowercase proxy variables are the person's
707
+ * machine, not the round's input. Most of what an ordinary setup depends on —
708
+ * the credential helper, LFS filters, identity in a config file — lives in
709
+ * FILES; the exceptions that live in the environment are named in
710
+ * `AMBIENT_GIT_KEPT`, because dropping them broke a CI commit outright. A rule
711
+ * of "refuse if any GIT_* is set" would refuse an ordinary developer session,
712
+ * which already carries `GIT_EDITOR`, `GIT_ASKPASS` and `GIT_TERMINAL_PROMPT`
713
+ * from its surrounding tooling.
714
+ *
715
+ * ⚠️ SO THE HONEST CLAIM IS NARROWER STILL, and the first version of this
716
+ * comment overstated it. Ambient environment cannot redirect a looply git
717
+ * operation, and cannot inject configuration THROUGH THE `GIT_` NAMESPACE. It
718
+ * can still inject configuration by other means: `XDG_CONFIG_HOME` and `HOME`
719
+ * survive verbatim, and git reads `$XDG_CONFIG_HOME/git/config` and
720
+ * `$HOME/.gitconfig`, neither of which `repoConfigPaths` scans. That is
721
+ * deliberate, and it is the same carve-out the header already makes for system
722
+ * and global config: those files are the person's, and refusing them would
723
+ * break every machine with Git LFS. It is also unreachable from repository
724
+ * content — no production file assigns `process.env` — which is the threat this
725
+ * file exists to stop. And it is NOT "the child can name no program":
726
+ * `SSH_ASKPASS` and its relatives survive as ambient machine configuration.
727
+ *
728
+ * ⚠️ AND `GIT_CONFIG_NOSYSTEM` IS DELIBERATELY NOT SET. `exec-domains.ts` sets
729
+ * it for the UNTRUSTED gate on purpose; setting it here would drop the system
730
+ * config that carries `filter.lfs.*` and `credential.helper` — the breakage the
731
+ * header of this file already refuses to cause.
732
+ */
733
+ /**
734
+ * `GIT_` variables that are NOT redirection or injection primitives, and that an
735
+ * ordinary developer or CI system legitimately sets.
736
+ *
737
+ * 🔴 DROPPING THE WHOLE NAMESPACE BROKE COMMITS. `GitDriver.commit` runs a bare
738
+ * `git commit -m` with no `--author`, so with these gone the only identity path
739
+ * is a config file — and a CI runner that supplies identity through the
740
+ * environment gets `Author identity unknown`, exit 128. Measured: the same
741
+ * commit in the same repository succeeded with them and failed without. The
742
+ * resulting `GitError` is thrown outside every try in `runRound`, so it ended
743
+ * the whole run, after the paid model turn and after a passing gate.
744
+ *
745
+ * Each entry earns its place by NOT being able to move the operation: an author
746
+ * name is a string on a commit object. `GIT_SSH_COMMAND` and `GIT_SSH` do name a
747
+ * program, but only for the two network verbs, they are how deploy keys and
748
+ * non-default ports are configured on every CI system, and their config
749
+ * equivalent `core.sshCommand` is already refused when it comes from the
750
+ * REPOSITORY — which is the threat this file is about. Ambient is the person's
751
+ * machine.
752
+ */
753
+ const AMBIENT_GIT_KEPT = [
754
+ /^GIT_(AUTHOR|COMMITTER)_(NAME|EMAIL|DATE)$/i,
755
+ /^GIT_SSH(_COMMAND)?$/i,
756
+ /^GIT_LFS_/i,
757
+ ];
758
+ function trustedGitEnv(base, cwd) {
759
+ /**
760
+ * Built as a plain record and cast once at the end, deliberately.
761
+ * `NodeJS.ProcessEnv` is widened by `expo-modules-core` to REQUIRE `NODE_ENV`
762
+ * under the test tsconfig, so an empty literal of that type does not compile
763
+ * there even though it compiles for this package alone.
764
+ */
765
+ const out = {};
766
+ for (const [k, v] of Object.entries(base)) {
767
+ if (!/^GIT_/i.test(k) || AMBIENT_GIT_KEPT.some((p) => p.test(k)))
768
+ out[k] = v;
769
+ }
770
+ // Never block a daemon on a credential prompt nobody can answer.
771
+ out['GIT_TERMINAL_PROMPT'] = '0';
772
+ /**
773
+ * PINNED, so that the repository this file CHECKED and the repository git
774
+ * OPERATES ON are the same one by construction.
775
+ *
776
+ * Only when the layout resolved: on `fault` the caller's two checks refuse
777
+ * before this matters, and on `none` nothing is pinned so git produces its own
778
+ * error exactly as before. The pair comes from `resolveGitLayout`, which was
779
+ * verified against `git rev-parse --absolute-git-dir --show-toplevel` in both
780
+ * an ordinary checkout and a linked worktree.
781
+ *
782
+ * ⚠️ THIS DISABLES GIT'S OWN DISCOVERY for looply's commands, which is safe
783
+ * only because `repoRootTroubleAt` already guarantees the cwd is the
784
+ * repository root. Relax that check and this becomes load-bearing in a way it
785
+ * is not today.
786
+ */
787
+ if (cwd !== undefined) {
788
+ const layout = resolveGitLayout(cwd);
789
+ if (layout.kind === 'ok') {
790
+ out['GIT_DIR'] = layout.gitDir;
791
+ out['GIT_WORK_TREE'] = layout.root;
792
+ }
793
+ }
794
+ return out;
795
+ }
796
+ /**
797
+ * THE MAIN WORKTREE'S ROOT — the directory a project's shared state belongs to.
798
+ *
799
+ * 🔴 A LINKED WORKTREE IS THE SAME PROJECT, and almost nothing in looply knew
800
+ * that. Project identity, the loop-safety history, the single-use exemption
801
+ * ledger, the human's control file and the ledger the daemon uploads are all
802
+ * derived from the working directory — so running in a worktree silently
803
+ * produced a DIFFERENT project with a fresh safety history, unspent exemptions,
804
+ * a control file nobody writes and events nobody uploads.
805
+ *
806
+ * The main worktree is where the common dir lives: for `<root>/.git` the answer
807
+ * is `<root>`. A linked worktree's common dir is that same `<root>/.git`, so it
808
+ * resolves to the same place — which is the whole point.
809
+ *
810
+ * ⚠️ NULL, NOT A GUESS, when there is no repository or its metadata cannot be
811
+ * read. The caller then keeps whatever it does today, so a non-repository
812
+ * directory behaves exactly as it did before this existed.
813
+ *
814
+ * ⚠️ A BARE OR SEPARATE-GITDIR REPOSITORY HAS NO MAIN WORKTREE ROOT. When the
815
+ * common dir is not named `.git`, this returns null rather than inventing a
816
+ * parent directory that may hold nothing at all.
817
+ */
818
+ function mainWorktreeRoot(cwd) {
819
+ const layout = resolveGitLayout(cwd);
820
+ if (layout.kind !== 'ok')
821
+ return null;
822
+ const common = (0, node_path_1.resolve)(layout.commonDir);
823
+ if ((0, node_path_1.basename)(common).toLowerCase() !== '.git')
824
+ return null;
825
+ return (0, node_path_1.dirname)(common);
826
+ }
827
+ /**
828
+ * WHAT ALL THE WORKTREES OF ONE REPOSITORY SHARE, when no main worktree exists.
829
+ *
830
+ * 🔴 `mainWorktreeRoot` RETURNING NULL WAS TREATED AS "NO SHARING NEEDED", and
831
+ * those are different statements. A repository can have several worktrees and no
832
+ * main one — `git clone --bare` then `git worktree add` twice is the ordinary
833
+ * way to get there — and for those, "no main root" was silently answered by
834
+ * putting the project's state inside each checkout. That is exactly the split
835
+ * the project/execution divide exists to prevent: a fresh loop-safety history
836
+ * per checkout, and one single-use exemption spendable once per checkout.
837
+ *
838
+ * The common dir is the identity every worktree of a repository agrees on, so it
839
+ * is what the shared location is keyed by.
840
+ *
841
+ * ⚠️ SEPARATE-GIT-DIR AND SUBMODULE LAYOUTS DO NOT REACH HERE. Both set
842
+ * `core.worktree`, which `repoConfigTrouble` refuses by name before any of this
843
+ * runs. The case this actually serves is the bare repository with linked
844
+ * worktrees, which nothing refuses and which was silently mis-scoped.
845
+ *
846
+ * ⚠️ NULL FOR AN ORDINARY CHECKOUT — `gitDir === commonDir` — even though one
847
+ * exists. There is a single worktree there, so the execution's own directory IS
848
+ * the project's, and answering anything else would move state that is correct
849
+ * where it sits.
850
+ */
851
+ /**
852
+ * THE PATH THAT IDENTIFIES A REPOSITORY, whichever of its checkouts you are in.
853
+ *
854
+ * 🔴 PROJECT IDENTITY WAS THE CWD, AND A WORKTREE IS NOT A NEW PROJECT. Both
855
+ * `repoPathHash` (the server's project key) and `projectKeyFor` (the project
856
+ * memory key) hashed the directory the command happened to run in. So
857
+ * `looply run --in <workspace>` registered a SECOND project on the server for
858
+ * the same repository, uploaded its events there, and read an empty project
859
+ * memory — while the person watching saw one project stop producing evidence.
860
+ *
861
+ * ⚠️ AN ORDINARY CHECKOUT HASHES TO EXACTLY WHAT IT ALWAYS DID. The main
862
+ * worktree root of a normal repository IS its root, so every existing key,
863
+ * every cached `projects` entry in the machine store and every server-side
864
+ * project survives untouched. Only a linked worktree's answer changes, and it
865
+ * changes from "a project of its own" to "the project it was cut from".
866
+ *
867
+ * ⚠️ AND A NON-REPOSITORY IS UNCHANGED TOO — no layout, no answer, the path
868
+ * comes back as given. Tests that pass invented directories keep working, which
869
+ * is deliberate: this must not require a repository to be callable.
870
+ */
871
+ /**
872
+ * Whether this directory IS a checkout's root — ordinary or linked.
873
+ *
874
+ * `resolveGitLayout` walks up, so every directory inside a repository has a
875
+ * layout. This is the question that separates `<repo>` from `<repo>/packages/a`,
876
+ * and it is the one both the project's identity and the project's state have to
877
+ * agree on or one of them is lying about what a project is.
878
+ */
879
+ function isCheckoutRoot(cwd) {
880
+ const layout = resolveGitLayout(cwd);
881
+ return layout.kind === 'ok' && (0, node_path_1.resolve)(layout.root) === (0, node_path_1.resolve)(cwd);
882
+ }
883
+ function repoIdentityPath(cwd) {
884
+ const here = (0, node_path_1.resolve)(cwd);
885
+ const layout = resolveGitLayout(here);
886
+ if (layout.kind !== 'ok')
887
+ return here;
888
+ /**
889
+ * ⚠️ A SUBDIRECTORY RESOLVES TO ITS REPOSITORY, and that is deliberate — but
890
+ * it was briefly changed to the opposite, so the reasoning is recorded here.
891
+ *
892
+ * `resolveGitLayout` walks up, so `<repo>/packages/a` answers `<repo>`. An
893
+ * adversarial pass called that a compatibility break: two directories that had
894
+ * always been two projects, merged onto one key.
895
+ *
896
+ * MEASURED, AND THE PREMISE IS FALSE. Looply cannot run outside a checkout
897
+ * root — `repoRootTroubleAt` refuses every git verb from a subdirectory, and
898
+ * the config is read from `<cwd>/.looply/config.yaml`, which a subdirectory
899
+ * does not have. So no subdirectory has ever registered a server project,
900
+ * filed a project memory, or held state; there is nothing there to merge.
901
+ *
902
+ * Requiring the root instead broke the one thing subdirectories ARE used for:
903
+ * a person typing `looply stop` or `looply runs` from inside their tree.
904
+ * Those commands are not guarded by the root check, and with the narrowing
905
+ * they addressed `<subdir>/.looply/state` — so the brake silently wrote a file
906
+ * no run would ever read, and reported "no run is going" while one was.
907
+ * Measured on the shipped build before it was reverted.
908
+ */
909
+ return mainWorktreeRoot(here) ?? linkedRepoCommonDir(here) ?? here;
910
+ }
911
+ function linkedRepoCommonDir(cwd) {
912
+ const layout = resolveGitLayout(cwd);
913
+ if (layout.kind !== 'ok')
914
+ return null;
915
+ const common = (0, node_path_1.resolve)(layout.commonDir);
916
+ if ((0, node_path_1.resolve)(layout.gitDir) === common)
917
+ return null;
918
+ return common;
919
+ }
920
+ //# sourceMappingURL=trusted-git.js.map