@caupulican/pi-adaptative 0.81.37 → 0.81.39

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 (451) hide show
  1. package/CHANGELOG.md +91 -0
  2. package/README.md +1 -1
  3. package/dist/bundled-resources/extensions/tmux-agent-manager/README.md +18 -1
  4. package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.d.ts +131 -0
  5. package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.d.ts.map +1 -0
  6. package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.js +196 -0
  7. package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.js.map +1 -0
  8. package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.ts +308 -0
  9. package/dist/bundled-resources/extensions/tmux-agent-manager/index.d.ts +22 -2
  10. package/dist/bundled-resources/extensions/tmux-agent-manager/index.d.ts.map +1 -1
  11. package/dist/bundled-resources/extensions/tmux-agent-manager/index.js +585 -24
  12. package/dist/bundled-resources/extensions/tmux-agent-manager/index.js.map +1 -1
  13. package/dist/bundled-resources/extensions/tmux-agent-manager/index.ts +749 -27
  14. package/dist/bundled-resources/runtimes/pi-shell-engine/commands/__init__.py +43 -0
  15. package/dist/bundled-resources/runtimes/pi-shell-engine/commands/fs.py +270 -0
  16. package/dist/bundled-resources/runtimes/pi-shell-engine/commands/search.py +252 -0
  17. package/dist/bundled-resources/runtimes/pi-shell-engine/commands/strings.py +399 -0
  18. package/dist/bundled-resources/runtimes/pi-shell-engine/commands/text.py +575 -0
  19. package/dist/bundled-resources/runtimes/pi-shell-engine/context.py +52 -0
  20. package/dist/bundled-resources/runtimes/pi-shell-engine/errors.py +49 -0
  21. package/dist/bundled-resources/runtimes/pi-shell-engine/exec.py +734 -0
  22. package/dist/bundled-resources/runtimes/pi-shell-engine/expand.py +238 -0
  23. package/dist/bundled-resources/runtimes/pi-shell-engine/main.py +132 -0
  24. package/dist/bundled-resources/runtimes/pi-shell-engine/nodes.py +116 -0
  25. package/dist/bundled-resources/runtimes/pi-shell-engine/parser.py +287 -0
  26. package/dist/bundled-resources/runtimes/pi-shell-engine/proc.py +137 -0
  27. package/dist/bundled-resources/runtimes/pi-shell-engine/state.py +100 -0
  28. package/dist/bundled-resources/runtimes/pi-shell-engine/tokens.py +579 -0
  29. package/dist/bundled-resources/skills/tool-call-repair/SKILL.md +19 -9
  30. package/dist/bundled-resources/skills/tool-call-repair/references/failure-grammar.md +22 -5
  31. package/dist/bundled-resources/skills/tool-call-repair/references/repair-catalogue.md +5 -5
  32. package/dist/bundled-resources/skills/tool-call-repair/references/text-protocol-grammar.md +28 -7
  33. package/dist/cli/args.d.ts +3 -0
  34. package/dist/cli/args.d.ts.map +1 -1
  35. package/dist/cli/args.js +15 -0
  36. package/dist/cli/args.js.map +1 -1
  37. package/dist/core/agent-paths.d.ts +49 -0
  38. package/dist/core/agent-paths.d.ts.map +1 -0
  39. package/dist/core/agent-paths.js +107 -0
  40. package/dist/core/agent-paths.js.map +1 -0
  41. package/dist/core/agent-session-services.d.ts.map +1 -1
  42. package/dist/core/agent-session-services.js +3 -3
  43. package/dist/core/agent-session-services.js.map +1 -1
  44. package/dist/core/agent-session.d.ts +234 -17
  45. package/dist/core/agent-session.d.ts.map +1 -1
  46. package/dist/core/agent-session.js +484 -62
  47. package/dist/core/agent-session.js.map +1 -1
  48. package/dist/core/autonomy/contracts.d.ts +9 -0
  49. package/dist/core/autonomy/contracts.d.ts.map +1 -1
  50. package/dist/core/autonomy/contracts.js.map +1 -1
  51. package/dist/core/autonomy/lane-tracker.d.ts +10 -1
  52. package/dist/core/autonomy/lane-tracker.d.ts.map +1 -1
  53. package/dist/core/autonomy/lane-tracker.js +5 -1
  54. package/dist/core/autonomy/lane-tracker.js.map +1 -1
  55. package/dist/core/background-lane-controller.d.ts +122 -6
  56. package/dist/core/background-lane-controller.d.ts.map +1 -1
  57. package/dist/core/background-lane-controller.js +447 -90
  58. package/dist/core/background-lane-controller.js.map +1 -1
  59. package/dist/core/bash-execution-controller.d.ts +4 -0
  60. package/dist/core/bash-execution-controller.d.ts.map +1 -1
  61. package/dist/core/bash-execution-controller.js +7 -1
  62. package/dist/core/bash-execution-controller.js.map +1 -1
  63. package/dist/core/compaction-support.d.ts +13 -3
  64. package/dist/core/compaction-support.d.ts.map +1 -1
  65. package/dist/core/compaction-support.js +43 -7
  66. package/dist/core/compaction-support.js.map +1 -1
  67. package/dist/core/context/context-audit.d.ts +33 -1
  68. package/dist/core/context/context-audit.d.ts.map +1 -1
  69. package/dist/core/context/context-audit.js +31 -5
  70. package/dist/core/context/context-audit.js.map +1 -1
  71. package/dist/core/context/sqlite-runtime-index.d.ts.map +1 -1
  72. package/dist/core/context/sqlite-runtime-index.js +13 -7
  73. package/dist/core/context/sqlite-runtime-index.js.map +1 -1
  74. package/dist/core/context-gc.d.ts.map +1 -1
  75. package/dist/core/context-gc.js +16 -1
  76. package/dist/core/context-gc.js.map +1 -1
  77. package/dist/core/context-pipeline.d.ts +26 -4
  78. package/dist/core/context-pipeline.d.ts.map +1 -1
  79. package/dist/core/context-pipeline.js +137 -14
  80. package/dist/core/context-pipeline.js.map +1 -1
  81. package/dist/core/cost-guard.d.ts +19 -3
  82. package/dist/core/cost-guard.d.ts.map +1 -1
  83. package/dist/core/cost-guard.js +18 -3
  84. package/dist/core/cost-guard.js.map +1 -1
  85. package/dist/core/delegation/session-worker-result.d.ts +34 -4
  86. package/dist/core/delegation/session-worker-result.d.ts.map +1 -1
  87. package/dist/core/delegation/session-worker-result.js +64 -4
  88. package/dist/core/delegation/session-worker-result.js.map +1 -1
  89. package/dist/core/delegation/worker-actions.d.ts.map +1 -1
  90. package/dist/core/delegation/worker-actions.js +1 -1
  91. package/dist/core/delegation/worker-actions.js.map +1 -1
  92. package/dist/core/delegation/worker-result.d.ts +42 -1
  93. package/dist/core/delegation/worker-result.d.ts.map +1 -1
  94. package/dist/core/delegation/worker-result.js +68 -0
  95. package/dist/core/delegation/worker-result.js.map +1 -1
  96. package/dist/core/extensions/loader.d.ts.map +1 -1
  97. package/dist/core/extensions/loader.js +23 -7
  98. package/dist/core/extensions/loader.js.map +1 -1
  99. package/dist/core/extensions/runner.d.ts.map +1 -1
  100. package/dist/core/extensions/runner.js +1 -0
  101. package/dist/core/extensions/runner.js.map +1 -1
  102. package/dist/core/extensions/types.d.ts +51 -0
  103. package/dist/core/extensions/types.d.ts.map +1 -1
  104. package/dist/core/extensions/types.js.map +1 -1
  105. package/dist/core/goal-loop-controller.d.ts +17 -1
  106. package/dist/core/goal-loop-controller.d.ts.map +1 -1
  107. package/dist/core/goal-loop-controller.js +79 -11
  108. package/dist/core/goal-loop-controller.js.map +1 -1
  109. package/dist/core/goals/goal-continuation-controller.d.ts +48 -2
  110. package/dist/core/goals/goal-continuation-controller.d.ts.map +1 -1
  111. package/dist/core/goals/goal-continuation-controller.js +77 -0
  112. package/dist/core/goals/goal-continuation-controller.js.map +1 -1
  113. package/dist/core/goals/goal-continuation-defaults.d.ts +39 -0
  114. package/dist/core/goals/goal-continuation-defaults.d.ts.map +1 -1
  115. package/dist/core/goals/goal-continuation-defaults.js +42 -0
  116. package/dist/core/goals/goal-continuation-defaults.js.map +1 -1
  117. package/dist/core/goals/goal-continuation-prompt.d.ts +4 -0
  118. package/dist/core/goals/goal-continuation-prompt.d.ts.map +1 -1
  119. package/dist/core/goals/goal-continuation-prompt.js +51 -10
  120. package/dist/core/goals/goal-continuation-prompt.js.map +1 -1
  121. package/dist/core/goals/goal-runtime-snapshot.d.ts +101 -2
  122. package/dist/core/goals/goal-runtime-snapshot.d.ts.map +1 -1
  123. package/dist/core/goals/goal-runtime-snapshot.js +87 -4
  124. package/dist/core/goals/goal-runtime-snapshot.js.map +1 -1
  125. package/dist/core/goals/goal-state.d.ts +89 -1
  126. package/dist/core/goals/goal-state.d.ts.map +1 -1
  127. package/dist/core/goals/goal-state.js +71 -5
  128. package/dist/core/goals/goal-state.js.map +1 -1
  129. package/dist/core/goals/goal-tool-core.d.ts +56 -2
  130. package/dist/core/goals/goal-tool-core.d.ts.map +1 -1
  131. package/dist/core/goals/goal-tool-core.js +111 -5
  132. package/dist/core/goals/goal-tool-core.js.map +1 -1
  133. package/dist/core/goals/session-goal-state.d.ts +11 -2
  134. package/dist/core/goals/session-goal-state.d.ts.map +1 -1
  135. package/dist/core/goals/session-goal-state.js +32 -17
  136. package/dist/core/goals/session-goal-state.js.map +1 -1
  137. package/dist/core/keybindings.d.ts +10 -0
  138. package/dist/core/keybindings.d.ts.map +1 -1
  139. package/dist/core/keybindings.js +10 -2
  140. package/dist/core/keybindings.js.map +1 -1
  141. package/dist/core/learning/observation-store.d.ts +12 -3
  142. package/dist/core/learning/observation-store.d.ts.map +1 -1
  143. package/dist/core/learning/observation-store.js +30 -15
  144. package/dist/core/learning/observation-store.js.map +1 -1
  145. package/dist/core/learning/skill-curator.d.ts +5 -1
  146. package/dist/core/learning/skill-curator.d.ts.map +1 -1
  147. package/dist/core/learning/skill-curator.js +21 -19
  148. package/dist/core/learning/skill-curator.js.map +1 -1
  149. package/dist/core/local-runtime-controller.d.ts +65 -3
  150. package/dist/core/local-runtime-controller.d.ts.map +1 -1
  151. package/dist/core/local-runtime-controller.js +186 -26
  152. package/dist/core/local-runtime-controller.js.map +1 -1
  153. package/dist/core/memory/providers/file-store.d.ts +1 -1
  154. package/dist/core/memory/providers/file-store.d.ts.map +1 -1
  155. package/dist/core/memory/providers/file-store.js +6 -6
  156. package/dist/core/memory/providers/file-store.js.map +1 -1
  157. package/dist/core/model-capability.d.ts +34 -0
  158. package/dist/core/model-capability.d.ts.map +1 -1
  159. package/dist/core/model-capability.js +42 -1
  160. package/dist/core/model-capability.js.map +1 -1
  161. package/dist/core/model-router/tool-escalation.d.ts +15 -0
  162. package/dist/core/model-router/tool-escalation.d.ts.map +1 -1
  163. package/dist/core/model-router/tool-escalation.js +23 -1
  164. package/dist/core/model-router/tool-escalation.js.map +1 -1
  165. package/dist/core/model-router-controller.d.ts +34 -7
  166. package/dist/core/model-router-controller.d.ts.map +1 -1
  167. package/dist/core/model-router-controller.js +95 -16
  168. package/dist/core/model-router-controller.js.map +1 -1
  169. package/dist/core/models/adaptation-store.d.ts +7 -0
  170. package/dist/core/models/adaptation-store.d.ts.map +1 -1
  171. package/dist/core/models/adaptation-store.js +47 -11
  172. package/dist/core/models/adaptation-store.js.map +1 -1
  173. package/dist/core/models/default-model-suggestions.d.ts.map +1 -1
  174. package/dist/core/models/default-model-suggestions.js +17 -0
  175. package/dist/core/models/default-model-suggestions.js.map +1 -1
  176. package/dist/core/models/fitness-store.d.ts +3 -0
  177. package/dist/core/models/fitness-store.d.ts.map +1 -1
  178. package/dist/core/models/fitness-store.js +11 -2
  179. package/dist/core/models/fitness-store.js.map +1 -1
  180. package/dist/core/models/llamacpp-runtime.d.ts +180 -0
  181. package/dist/core/models/llamacpp-runtime.d.ts.map +1 -0
  182. package/dist/core/models/llamacpp-runtime.js +475 -0
  183. package/dist/core/models/llamacpp-runtime.js.map +1 -0
  184. package/dist/core/models/local-registration.d.ts +40 -0
  185. package/dist/core/models/local-registration.d.ts.map +1 -1
  186. package/dist/core/models/local-registration.js +94 -5
  187. package/dist/core/models/local-registration.js.map +1 -1
  188. package/dist/core/models/local-runtime.d.ts.map +1 -1
  189. package/dist/core/models/local-runtime.js +9 -7
  190. package/dist/core/models/local-runtime.js.map +1 -1
  191. package/dist/core/models/model-ref.d.ts +7 -0
  192. package/dist/core/models/model-ref.d.ts.map +1 -1
  193. package/dist/core/models/model-ref.js +26 -0
  194. package/dist/core/models/model-ref.js.map +1 -1
  195. package/dist/core/models/needle-runtime.d.ts +257 -0
  196. package/dist/core/models/needle-runtime.d.ts.map +1 -0
  197. package/dist/core/models/needle-runtime.js +519 -0
  198. package/dist/core/models/needle-runtime.js.map +1 -0
  199. package/dist/core/models/prism-llamacpp-lifecycle.d.ts +89 -0
  200. package/dist/core/models/prism-llamacpp-lifecycle.d.ts.map +1 -0
  201. package/dist/core/models/prism-llamacpp-lifecycle.js +121 -0
  202. package/dist/core/models/prism-llamacpp-lifecycle.js.map +1 -0
  203. package/dist/core/package-manager.d.ts.map +1 -1
  204. package/dist/core/package-manager.js +11 -10
  205. package/dist/core/package-manager.js.map +1 -1
  206. package/dist/core/process-matrix/codes.d.ts +72 -0
  207. package/dist/core/process-matrix/codes.d.ts.map +1 -0
  208. package/dist/core/process-matrix/codes.js +15 -0
  209. package/dist/core/process-matrix/codes.js.map +1 -0
  210. package/dist/core/process-matrix/runtime.d.ts +63 -0
  211. package/dist/core/process-matrix/runtime.d.ts.map +1 -0
  212. package/dist/core/process-matrix/runtime.js +310 -0
  213. package/dist/core/process-matrix/runtime.js.map +1 -0
  214. package/dist/core/process-matrix/store.d.ts +22 -0
  215. package/dist/core/process-matrix/store.d.ts.map +1 -0
  216. package/dist/core/process-matrix/store.js +80 -0
  217. package/dist/core/process-matrix/store.js.map +1 -0
  218. package/dist/core/process-matrix/supervisor.d.ts +72 -0
  219. package/dist/core/process-matrix/supervisor.d.ts.map +1 -0
  220. package/dist/core/process-matrix/supervisor.js +130 -0
  221. package/dist/core/process-matrix/supervisor.js.map +1 -0
  222. package/dist/core/profile-registry.d.ts +7 -0
  223. package/dist/core/profile-registry.d.ts.map +1 -1
  224. package/dist/core/profile-registry.js +20 -0
  225. package/dist/core/profile-registry.js.map +1 -1
  226. package/dist/core/python-runtime.d.ts.map +1 -1
  227. package/dist/core/python-runtime.js +3 -3
  228. package/dist/core/python-runtime.js.map +1 -1
  229. package/dist/core/reflection-controller.d.ts +29 -5
  230. package/dist/core/reflection-controller.d.ts.map +1 -1
  231. package/dist/core/reflection-controller.js +215 -126
  232. package/dist/core/reflection-controller.js.map +1 -1
  233. package/dist/core/reload-blockers.d.ts +36 -0
  234. package/dist/core/reload-blockers.d.ts.map +1 -1
  235. package/dist/core/reload-blockers.js +44 -0
  236. package/dist/core/reload-blockers.js.map +1 -1
  237. package/dist/core/resource-loader.d.ts.map +1 -1
  238. package/dist/core/resource-loader.js +8 -7
  239. package/dist/core/resource-loader.js.map +1 -1
  240. package/dist/core/runtime-builder.d.ts +58 -5
  241. package/dist/core/runtime-builder.d.ts.map +1 -1
  242. package/dist/core/runtime-builder.js +209 -25
  243. package/dist/core/runtime-builder.js.map +1 -1
  244. package/dist/core/scout-controller.d.ts +6 -0
  245. package/dist/core/scout-controller.d.ts.map +1 -1
  246. package/dist/core/scout-controller.js +66 -52
  247. package/dist/core/scout-controller.js.map +1 -1
  248. package/dist/core/sdk.d.ts.map +1 -1
  249. package/dist/core/sdk.js +3 -3
  250. package/dist/core/sdk.js.map +1 -1
  251. package/dist/core/session-role.d.ts +31 -0
  252. package/dist/core/session-role.d.ts.map +1 -0
  253. package/dist/core/session-role.js +52 -0
  254. package/dist/core/session-role.js.map +1 -0
  255. package/dist/core/settings-manager.d.ts +42 -3
  256. package/dist/core/settings-manager.d.ts.map +1 -1
  257. package/dist/core/settings-manager.js +94 -60
  258. package/dist/core/settings-manager.js.map +1 -1
  259. package/dist/core/system-prompt-builder.d.ts +12 -0
  260. package/dist/core/system-prompt-builder.d.ts.map +1 -1
  261. package/dist/core/system-prompt-builder.js +6 -0
  262. package/dist/core/system-prompt-builder.js.map +1 -1
  263. package/dist/core/system-prompt.d.ts +14 -1
  264. package/dist/core/system-prompt.d.ts.map +1 -1
  265. package/dist/core/system-prompt.js +20 -3
  266. package/dist/core/system-prompt.js.map +1 -1
  267. package/dist/core/tasks/session-task-state.d.ts +11 -2
  268. package/dist/core/tasks/session-task-state.d.ts.map +1 -1
  269. package/dist/core/tasks/session-task-state.js +27 -11
  270. package/dist/core/tasks/session-task-state.js.map +1 -1
  271. package/dist/core/tasks/task-contract-monitor.d.ts +45 -0
  272. package/dist/core/tasks/task-contract-monitor.d.ts.map +1 -0
  273. package/dist/core/tasks/task-contract-monitor.js +56 -0
  274. package/dist/core/tasks/task-contract-monitor.js.map +1 -0
  275. package/dist/core/tasks/task-state.d.ts +8 -0
  276. package/dist/core/tasks/task-state.d.ts.map +1 -1
  277. package/dist/core/tasks/task-state.js +28 -1
  278. package/dist/core/tasks/task-state.js.map +1 -1
  279. package/dist/core/tool-gate-controller.d.ts.map +1 -1
  280. package/dist/core/tool-gate-controller.js +5 -0
  281. package/dist/core/tool-gate-controller.js.map +1 -1
  282. package/dist/core/tool-recovery-log-records.d.ts +7 -0
  283. package/dist/core/tool-recovery-log-records.d.ts.map +1 -1
  284. package/dist/core/tool-recovery-log-records.js +14 -6
  285. package/dist/core/tool-recovery-log-records.js.map +1 -1
  286. package/dist/core/tool-selection/promotion.d.ts +54 -0
  287. package/dist/core/tool-selection/promotion.d.ts.map +1 -0
  288. package/dist/core/tool-selection/promotion.js +81 -0
  289. package/dist/core/tool-selection/promotion.js.map +1 -0
  290. package/dist/core/tool-selection/tool-performance-store.d.ts +37 -0
  291. package/dist/core/tool-selection/tool-performance-store.d.ts.map +1 -1
  292. package/dist/core/tool-selection/tool-performance-store.js +87 -3
  293. package/dist/core/tool-selection/tool-performance-store.js.map +1 -1
  294. package/dist/core/tool-selection/tool-selection-controller.d.ts +45 -0
  295. package/dist/core/tool-selection/tool-selection-controller.d.ts.map +1 -1
  296. package/dist/core/tool-selection/tool-selection-controller.js +96 -0
  297. package/dist/core/tool-selection/tool-selection-controller.js.map +1 -1
  298. package/dist/core/tools/bash.d.ts +18 -0
  299. package/dist/core/tools/bash.d.ts.map +1 -1
  300. package/dist/core/tools/bash.js +97 -18
  301. package/dist/core/tools/bash.js.map +1 -1
  302. package/dist/core/tools/delegate-status.d.ts +14 -0
  303. package/dist/core/tools/delegate-status.d.ts.map +1 -1
  304. package/dist/core/tools/delegate-status.js +82 -7
  305. package/dist/core/tools/delegate-status.js.map +1 -1
  306. package/dist/core/tools/delegate.d.ts.map +1 -1
  307. package/dist/core/tools/delegate.js +25 -8
  308. package/dist/core/tools/delegate.js.map +1 -1
  309. package/dist/core/tools/find.d.ts.map +1 -1
  310. package/dist/core/tools/find.js +52 -44
  311. package/dist/core/tools/find.js.map +1 -1
  312. package/dist/core/tools/goal.d.ts +94 -3
  313. package/dist/core/tools/goal.d.ts.map +1 -1
  314. package/dist/core/tools/goal.js +165 -15
  315. package/dist/core/tools/goal.js.map +1 -1
  316. package/dist/core/tools/grep.d.ts.map +1 -1
  317. package/dist/core/tools/grep.js +5 -4
  318. package/dist/core/tools/grep.js.map +1 -1
  319. package/dist/core/tools/model-fitness.d.ts +7 -0
  320. package/dist/core/tools/model-fitness.d.ts.map +1 -1
  321. package/dist/core/tools/model-fitness.js +2 -2
  322. package/dist/core/tools/model-fitness.js.map +1 -1
  323. package/dist/core/tools/render-utils.d.ts.map +1 -1
  324. package/dist/core/tools/render-utils.js +1 -1
  325. package/dist/core/tools/render-utils.js.map +1 -1
  326. package/dist/core/tools/shell-contract-router.d.ts +6 -1
  327. package/dist/core/tools/shell-contract-router.d.ts.map +1 -1
  328. package/dist/core/tools/shell-contract-router.js +69 -13
  329. package/dist/core/tools/shell-contract-router.js.map +1 -1
  330. package/dist/core/tools/shell-session.d.ts +89 -0
  331. package/dist/core/tools/shell-session.d.ts.map +1 -0
  332. package/dist/core/tools/shell-session.js +432 -0
  333. package/dist/core/tools/shell-session.js.map +1 -0
  334. package/dist/core/tools/task-steps.d.ts +4 -0
  335. package/dist/core/tools/task-steps.d.ts.map +1 -1
  336. package/dist/core/tools/task-steps.js +63 -8
  337. package/dist/core/tools/task-steps.js.map +1 -1
  338. package/dist/core/tools/tmux-dispatch.d.ts +86 -0
  339. package/dist/core/tools/tmux-dispatch.d.ts.map +1 -0
  340. package/dist/core/tools/tmux-dispatch.js +91 -0
  341. package/dist/core/tools/tmux-dispatch.js.map +1 -0
  342. package/dist/core/tools/windows-shell-engine.d.ts +42 -0
  343. package/dist/core/tools/windows-shell-engine.d.ts.map +1 -0
  344. package/dist/core/tools/windows-shell-engine.js +153 -0
  345. package/dist/core/tools/windows-shell-engine.js.map +1 -0
  346. package/dist/core/tools/windows-shell-state.d.ts +40 -0
  347. package/dist/core/tools/windows-shell-state.d.ts.map +1 -0
  348. package/dist/core/tools/windows-shell-state.js +59 -0
  349. package/dist/core/tools/windows-shell-state.js.map +1 -0
  350. package/dist/core/tools/worktree-sync.d.ts +24 -0
  351. package/dist/core/tools/worktree-sync.d.ts.map +1 -0
  352. package/dist/core/tools/worktree-sync.js +338 -0
  353. package/dist/core/tools/worktree-sync.js.map +1 -0
  354. package/dist/core/trust-manager.d.ts +4 -1
  355. package/dist/core/trust-manager.d.ts.map +1 -1
  356. package/dist/core/trust-manager.js +20 -2
  357. package/dist/core/trust-manager.js.map +1 -1
  358. package/dist/core/util/atomic-file.d.ts +55 -0
  359. package/dist/core/util/atomic-file.d.ts.map +1 -0
  360. package/dist/core/util/atomic-file.js +255 -0
  361. package/dist/core/util/atomic-file.js.map +1 -0
  362. package/dist/core/util/minimatch-cache.d.ts +33 -0
  363. package/dist/core/util/minimatch-cache.d.ts.map +1 -0
  364. package/dist/core/util/minimatch-cache.js +0 -0
  365. package/dist/core/util/minimatch-cache.js.map +1 -0
  366. package/dist/core/worktree-sync/codes.d.ts +227 -0
  367. package/dist/core/worktree-sync/codes.d.ts.map +1 -0
  368. package/dist/core/worktree-sync/codes.js +14 -0
  369. package/dist/core/worktree-sync/codes.js.map +1 -0
  370. package/dist/core/worktree-sync/git-engine.d.ts +156 -0
  371. package/dist/core/worktree-sync/git-engine.d.ts.map +1 -0
  372. package/dist/core/worktree-sync/git-engine.js +1191 -0
  373. package/dist/core/worktree-sync/git-engine.js.map +1 -0
  374. package/dist/core/worktree-sync/lane-gate.d.ts +75 -0
  375. package/dist/core/worktree-sync/lane-gate.d.ts.map +1 -0
  376. package/dist/core/worktree-sync/lane-gate.js +360 -0
  377. package/dist/core/worktree-sync/lane-gate.js.map +1 -0
  378. package/dist/core/worktree-sync/runtime.d.ts +47 -0
  379. package/dist/core/worktree-sync/runtime.d.ts.map +1 -0
  380. package/dist/core/worktree-sync/runtime.js +96 -0
  381. package/dist/core/worktree-sync/runtime.js.map +1 -0
  382. package/dist/core/worktree-sync/store.d.ts +69 -0
  383. package/dist/core/worktree-sync/store.d.ts.map +1 -0
  384. package/dist/core/worktree-sync/store.js +247 -0
  385. package/dist/core/worktree-sync/store.js.map +1 -0
  386. package/dist/core/worktree-sync/watcher.d.ts +29 -0
  387. package/dist/core/worktree-sync/watcher.d.ts.map +1 -0
  388. package/dist/core/worktree-sync/watcher.js +93 -0
  389. package/dist/core/worktree-sync/watcher.js.map +1 -0
  390. package/dist/main.d.ts.map +1 -1
  391. package/dist/main.js +94 -0
  392. package/dist/main.js.map +1 -1
  393. package/dist/migrations.d.ts +9 -0
  394. package/dist/migrations.d.ts.map +1 -1
  395. package/dist/migrations.js +38 -0
  396. package/dist/migrations.js.map +1 -1
  397. package/dist/modes/interactive/auto-learn-controller.d.ts +16 -1
  398. package/dist/modes/interactive/auto-learn-controller.d.ts.map +1 -1
  399. package/dist/modes/interactive/auto-learn-controller.js +50 -8
  400. package/dist/modes/interactive/auto-learn-controller.js.map +1 -1
  401. package/dist/modes/interactive/components/profile-resource-editor.d.ts.map +1 -1
  402. package/dist/modes/interactive/components/profile-resource-editor.js +23 -1
  403. package/dist/modes/interactive/components/profile-resource-editor.js.map +1 -1
  404. package/dist/modes/interactive/interactive-mode.d.ts +1 -0
  405. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  406. package/dist/modes/interactive/interactive-mode.js +4 -0
  407. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  408. package/dist/modes/interactive/local-model-commands.d.ts +43 -0
  409. package/dist/modes/interactive/local-model-commands.d.ts.map +1 -1
  410. package/dist/modes/interactive/local-model-commands.js +290 -3
  411. package/dist/modes/interactive/local-model-commands.js.map +1 -1
  412. package/dist/modes/interactive/session-flow-commands.d.ts.map +1 -1
  413. package/dist/modes/interactive/session-flow-commands.js +24 -4
  414. package/dist/modes/interactive/session-flow-commands.js.map +1 -1
  415. package/dist/utils/fs-watch.d.ts +11 -0
  416. package/dist/utils/fs-watch.d.ts.map +1 -1
  417. package/dist/utils/fs-watch.js +20 -2
  418. package/dist/utils/fs-watch.js.map +1 -1
  419. package/dist/utils/highlight-js-languages.d.ts +4 -0
  420. package/dist/utils/highlight-js-languages.d.ts.map +1 -0
  421. package/dist/utils/highlight-js-languages.js +573 -0
  422. package/dist/utils/highlight-js-languages.js.map +1 -0
  423. package/dist/utils/shell.d.ts +7 -1
  424. package/dist/utils/shell.d.ts.map +1 -1
  425. package/dist/utils/shell.js +39 -9
  426. package/dist/utils/shell.js.map +1 -1
  427. package/dist/utils/syntax-highlight.d.ts.map +1 -1
  428. package/dist/utils/syntax-highlight.js +53 -5
  429. package/dist/utils/syntax-highlight.js.map +1 -1
  430. package/dist/utils/tools-manager.d.ts.map +1 -1
  431. package/dist/utils/tools-manager.js +112 -1
  432. package/dist/utils/tools-manager.js.map +1 -1
  433. package/docs/development.md +2 -0
  434. package/docs/packages.md +1 -1
  435. package/docs/process-matrix.md +120 -0
  436. package/docs/settings.md +5 -2
  437. package/docs/tmux-agent-manager.md +85 -2
  438. package/docs/windows.md +52 -3
  439. package/docs/work-directory.md +29 -0
  440. package/docs/worktree-sync.md +250 -0
  441. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  442. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  443. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  444. package/examples/extensions/sandbox/package-lock.json +2 -2
  445. package/examples/extensions/sandbox/package.json +1 -1
  446. package/examples/extensions/with-deps/package-lock.json +2 -2
  447. package/examples/extensions/with-deps/package.json +1 -1
  448. package/npm-shrinkwrap.json +12 -12
  449. package/package.json +10 -4
  450. package/docs/integration-sweep-builder-blueprint-2026-07-09.md +0 -365
  451. package/docs/integration-sweep-resume-2026-07-09.md +0 -407
@@ -0,0 +1,360 @@
1
+ /**
2
+ * Lane gate: G8/G10 enforcement for a LANE-BOUND `pi` session (launched with
3
+ * `PI_WORKTREE_LANE=<key>`). RuntimeBuilder wraps the session's file-mutation tools (edit /
4
+ * write / bash) with {@link WorktreeLaneGate.checkMutation}; a lane that the active policy marks
5
+ * sync_required fails closed with the exact recovery step until it rebases main.
6
+ *
7
+ * Honesty boundary (unchanged from the tmux trust model): this is HARD for pi children -- the
8
+ * wrapper lives under the tool layer, not in the prompt -- and cooperative-only for foreign
9
+ * CLIs, whose backstop is the land CAS (G3): stale work simply cannot land.
10
+ *
11
+ * Determinism: the gate re-derives from git only when the epoch file actually changed (mtime
12
+ * fence) or while blocked; verdicts in between are cached. No polling, no timers.
13
+ */
14
+ import { existsSync, realpathSync, statSync } from "node:fs";
15
+ import { basename, dirname, join, resolve, sep } from "node:path";
16
+ import { deriveLaneFacts, resolveRepoContext } from "./git-engine.js";
17
+ import { readLane } from "./store.js";
18
+ const SYNC_SAFE_GIT_SUBCOMMANDS = new Set([
19
+ "status",
20
+ "diff",
21
+ "log",
22
+ "show",
23
+ "add",
24
+ "commit",
25
+ "stash",
26
+ "rev-parse",
27
+ "ls-files",
28
+ "blame",
29
+ "grep",
30
+ ]);
31
+ const MAIN_MUTATING_GIT_SUBCOMMANDS = new Set(["merge", "rebase", "reset", "commit", "branch", "update-ref", "push"]);
32
+ /**
33
+ * Classify one bash command line for a lane-bound session (G10 + the sync_required allowlist).
34
+ * Tokenization is whitespace-naive by design -- deterministic and reviewable; shell-quoting
35
+ * tricks can evade it, which is the documented cooperative boundary (the land CAS cannot be
36
+ * evaded). Command POSITION still matters: `git` only begins an invocation at the start of the
37
+ * command or immediately after a shell separator (`&&`, `||`, `;`, `|`) -- a bare `git` token
38
+ * elsewhere (e.g. as a plain argument to `echo`) is not an invocation. Rules:
39
+ * - `git push` anywhere: refused (main moves only through the land gate; pushing is owner-only).
40
+ * - `git -C <path>` / `--git-dir` combined with a mutating subcommand: refused (escaping the
41
+ * lane worktree to operate on another checkout, e.g. the hub).
42
+ * - `git branch -f/-M/-D <main>` / `git update-ref refs/heads/<main>`: refused.
43
+ * - Everything else: allowed; a read/commit-shaped git subcommand additionally stays allowed
44
+ * while the lane is sync_required (committing WIP is the prescribed step BEFORE syncing).
45
+ */
46
+ export function classifyLaneBashCommand(command, mainBranch) {
47
+ // This classifier is defense-in-depth, not a shell parser. Refuse compound
48
+ // syntax before any segment can return an allow verdict; otherwise `git
49
+ // status; git push` is approved by the first safe segment.
50
+ if (/[|;&<>$`(){}\n\r]/u.test(command)) {
51
+ return {
52
+ verdict: "main_mutation_refused",
53
+ reason: "compound shell syntax is refused in a lane; use typed worktree_sync actions",
54
+ };
55
+ }
56
+ if (/^\s*["']git["']\s/u.test(command)) {
57
+ return {
58
+ verdict: "main_mutation_refused",
59
+ reason: "quoted command names are refused in a lane; use the typed Git actions",
60
+ };
61
+ }
62
+ const segments = [command];
63
+ let allowedWhenSyncRequired = false;
64
+ for (const segment of segments) {
65
+ const tokens = segment.trim().split(/\s+/).filter(Boolean);
66
+ if (tokens[0] !== "git")
67
+ continue;
68
+ let j = 1;
69
+ let escapesWorktree = false;
70
+ // Skip git global options to find the subcommand; -C/--git-dir mark checkout escape.
71
+ while (j < tokens.length) {
72
+ const token = tokens[j] ?? "";
73
+ if (token === "-C" || token === "--git-dir" || token === "--work-tree") {
74
+ escapesWorktree = true;
75
+ j += 2;
76
+ continue;
77
+ }
78
+ if (token.startsWith("-C") && token !== "-C") {
79
+ escapesWorktree = true;
80
+ j += 1;
81
+ continue;
82
+ }
83
+ if (token.startsWith("--git-dir=") || token.startsWith("--work-tree=")) {
84
+ escapesWorktree = true;
85
+ j += 1;
86
+ continue;
87
+ }
88
+ if (token.startsWith("-")) {
89
+ j += 1;
90
+ continue;
91
+ }
92
+ break;
93
+ }
94
+ const subcommand = tokens[j] ?? "";
95
+ const rest = tokens.slice(j + 1);
96
+ if (subcommand === "push") {
97
+ return {
98
+ verdict: "main_mutation_refused",
99
+ reason: "git push is refused in a lane session; landing is the only integration path and pushing stays an owner action",
100
+ };
101
+ }
102
+ if (escapesWorktree && MAIN_MUTATING_GIT_SUBCOMMANDS.has(subcommand)) {
103
+ return {
104
+ verdict: "main_mutation_refused",
105
+ reason: `git -C/--git-dir with '${subcommand}' escapes the lane worktree; operate only on this lane (G10)`,
106
+ };
107
+ }
108
+ if (subcommand === "branch" &&
109
+ rest.some((token) => /^(?:-f|--force|-M|-m|-D|-d)$/.test(token)) &&
110
+ rest.includes(mainBranch)) {
111
+ return {
112
+ verdict: "main_mutation_refused",
113
+ reason: `git branch may not move/delete '${mainBranch}' from a lane; main moves only through the land gate (G10)`,
114
+ };
115
+ }
116
+ if (subcommand === "update-ref" && rest.some((token) => token === `refs/heads/${mainBranch}`)) {
117
+ return {
118
+ verdict: "main_mutation_refused",
119
+ reason: `git update-ref may not touch refs/heads/${mainBranch} from a lane (G10)`,
120
+ };
121
+ }
122
+ if (SYNC_SAFE_GIT_SUBCOMMANDS.has(subcommand))
123
+ allowedWhenSyncRequired = true;
124
+ }
125
+ return allowedWhenSyncRequired ? { verdict: "allowed_even_when_sync_required" } : { verdict: "allowed" };
126
+ }
127
+ /** Symlink-safe resolution of a path that may not exist yet: realpath the NEAREST EXISTING
128
+ * ancestor, then re-append the not-yet-existing tail literally (a not-yet-created file's own
129
+ * missing final component can never itself be a symlink escape). */
130
+ function resolveSymlinkSafe(targetPath) {
131
+ if (existsSync(targetPath)) {
132
+ try {
133
+ return realpathSync(targetPath);
134
+ }
135
+ catch {
136
+ return targetPath;
137
+ }
138
+ }
139
+ const tail = [basename(targetPath)];
140
+ let ancestor = dirname(targetPath);
141
+ while (!existsSync(ancestor)) {
142
+ const parent = dirname(ancestor);
143
+ if (parent === ancestor)
144
+ break; // reached the filesystem root without finding one
145
+ tail.unshift(basename(ancestor));
146
+ ancestor = parent;
147
+ }
148
+ let realAncestor;
149
+ try {
150
+ realAncestor = realpathSync(ancestor);
151
+ }
152
+ catch {
153
+ realAncestor = ancestor;
154
+ }
155
+ return join(realAncestor, ...tail);
156
+ }
157
+ /** Symlink-safe containment check (G-path): does `targetPath` resolve inside `worktreePath`? */
158
+ export function isPathOutsideLane(targetPath, worktreePath) {
159
+ let realRoot;
160
+ try {
161
+ realRoot = realpathSync(worktreePath);
162
+ }
163
+ catch {
164
+ realRoot = worktreePath;
165
+ }
166
+ const resolvedTarget = resolveSymlinkSafe(targetPath);
167
+ return resolvedTarget !== realRoot && !resolvedTarget.startsWith(realRoot + sep);
168
+ }
169
+ /** Resolve a user-supplied relative lane path and reject symlink/parent escapes. */
170
+ export function resolveLaneMutationPath(worktreePath, candidate) {
171
+ const target = resolve(worktreePath, candidate);
172
+ return isPathOutsideLane(target, worktreePath) ? undefined : target;
173
+ }
174
+ async function changedPaths(deps, cwd, base, ref) {
175
+ const result = await deps.exec("git", ["diff", "--name-only", `${base}..${ref}`, "--"], {
176
+ cwd,
177
+ timeout: 60_000,
178
+ maxBuffer: 1024 * 1024,
179
+ });
180
+ if (result.code !== 0)
181
+ return undefined;
182
+ return new Set(result.stdout
183
+ .split(/\r?\n/u)
184
+ .map((path) => path.trim())
185
+ .filter(Boolean));
186
+ }
187
+ function hardShellCommandAllowed(command, mainBranch, trustedGateCommand) {
188
+ const trimmed = command.trim();
189
+ if (trustedGateCommand && trimmed === trustedGateCommand.trim())
190
+ return true;
191
+ if (!/^git(?:\s|$)/u.test(trimmed))
192
+ return false;
193
+ const verdict = classifyLaneBashCommand(trimmed, mainBranch);
194
+ if (verdict.verdict === "main_mutation_refused")
195
+ return false;
196
+ const tokens = trimmed.split(/\s+/u);
197
+ const subcommand = tokens[1] ?? "";
198
+ if (!SYNC_SAFE_GIT_SUBCOMMANDS.has(subcommand) && subcommand !== "commit")
199
+ return false;
200
+ // Git path operands must not escape the lane checkout. The typed worktree
201
+ // actions are the authoritative route for path-sensitive add/diff operations;
202
+ // this final check prevents the common absolute/parent escape in the shell floor.
203
+ return !tokens.slice(2).some((token) => token.startsWith("/") || token.startsWith("..") || token.includes("/../"));
204
+ }
205
+ /**
206
+ * The G8 gate object RuntimeBuilder holds per lane-bound session. `checkMutation` is called by
207
+ * the wrapped edit/write/bash tools before every mutating execution.
208
+ */
209
+ export class WorktreeLaneGate {
210
+ config;
211
+ _ctx;
212
+ _epochFileMtimeMs;
213
+ _cachedAllowed = false;
214
+ constructor(config) {
215
+ this.config = config;
216
+ }
217
+ async resolveContext() {
218
+ if (this._ctx)
219
+ return this._ctx;
220
+ const ctx = await resolveRepoContext(this.config.engineDeps());
221
+ if ("code" in ctx)
222
+ return undefined;
223
+ this._ctx = ctx;
224
+ return ctx;
225
+ }
226
+ /** Cheap fence: has the epoch file changed since the last allowed verdict? */
227
+ epochChanged(ctx) {
228
+ let mtimeMs;
229
+ try {
230
+ mtimeMs = statSync(ctx.paths.epochFile).mtimeMs;
231
+ }
232
+ catch {
233
+ mtimeMs = undefined;
234
+ }
235
+ if (mtimeMs === this._epochFileMtimeMs)
236
+ return false;
237
+ this._epochFileMtimeMs = mtimeMs;
238
+ return true;
239
+ }
240
+ async checkMutation(toolName, bashCommand, targetPath) {
241
+ const ctx = await this.resolveContext();
242
+ // No repo context (deleted repo, engine failure): fail OPEN for plain tools -- the land
243
+ // CAS still holds -- but the G10 bash rules below never depend on repo state.
244
+ const mainBranch = ctx?.mainBranch ?? "main";
245
+ if (this.config.hardShell && !ctx) {
246
+ return {
247
+ allowed: false,
248
+ code: "lane_state_unavailable",
249
+ message: "worktree-sync: lane state is unavailable; hard worker mutations fail closed",
250
+ };
251
+ }
252
+ if (toolName === "bash" && bashCommand !== undefined) {
253
+ if (this.config.hardShell &&
254
+ !hardShellCommandAllowed(bashCommand, mainBranch, this.config.trustedGateCommand?.())) {
255
+ return {
256
+ allowed: false,
257
+ code: "main_mutation_refused",
258
+ message: "worktree-sync: unrestricted bash is unavailable in a hard worker lane; use typed worktree_sync actions",
259
+ };
260
+ }
261
+ const verdict = classifyLaneBashCommand(bashCommand, mainBranch);
262
+ if (verdict.verdict === "main_mutation_refused") {
263
+ return { allowed: false, code: "main_mutation_refused", message: `worktree-sync: ${verdict.reason}` };
264
+ }
265
+ if (verdict.verdict === "allowed_even_when_sync_required")
266
+ return { allowed: true };
267
+ }
268
+ if (!ctx)
269
+ return { allowed: true };
270
+ // G-path: an edit/write target must resolve INSIDE this lane's worktree (symlink-safe),
271
+ // checked BEFORE the staleness cache so a cached "allowed" verdict never short-circuits past
272
+ // it. No active lane record: existing fail-open stands (mirrors the readLane check below).
273
+ if ((toolName === "edit" || toolName === "write") && targetPath !== undefined) {
274
+ const laneForPath = await readLane(ctx.paths, this.config.laneKey);
275
+ if (laneForPath?.status === "active" && isPathOutsideLane(targetPath, laneForPath.worktreePath)) {
276
+ return {
277
+ allowed: false,
278
+ code: "path_outside_lane",
279
+ message: `worktree-sync: '${targetPath}' resolves outside lane '${this.config.laneKey}' worktree (${laneForPath.worktreePath}); edit/write only inside your lane checkout`,
280
+ };
281
+ }
282
+ }
283
+ // G8: sync_required fails mutations closed. Re-derive only when the epoch moved or while
284
+ // blocked (a successful sync clears the block on the very next check).
285
+ if (this._cachedAllowed && !this.epochChanged(ctx))
286
+ return { allowed: true };
287
+ const deps = this.config.engineDeps();
288
+ const lane = await readLane(ctx.paths, this.config.laneKey);
289
+ if (!lane || lane.status !== "active") {
290
+ if (this.config.hardShell) {
291
+ return {
292
+ allowed: false,
293
+ code: "lane_state_unavailable",
294
+ message: "worktree-sync: hard worker lane registration is missing or inactive; reconcile before mutating",
295
+ };
296
+ }
297
+ this._cachedAllowed = true;
298
+ return { allowed: true };
299
+ }
300
+ // Re-derive main tip: the cached ctx pins the sha from session start.
301
+ const fresh = await resolveRepoContext(deps);
302
+ if ("code" in fresh) {
303
+ if (this.config.hardShell) {
304
+ return {
305
+ allowed: false,
306
+ code: "lane_state_unavailable",
307
+ message: "worktree-sync: Git context is unavailable; hard worker mutation refused",
308
+ };
309
+ }
310
+ this._cachedAllowed = true;
311
+ return { allowed: true };
312
+ }
313
+ this._ctx = fresh;
314
+ const facts = await deriveLaneFacts(deps, fresh, lane);
315
+ if (facts.fresh) {
316
+ this._cachedAllowed = true;
317
+ return { allowed: true };
318
+ }
319
+ const policy = this.config.policy();
320
+ let syncRequired = policy === "on_land_mandatory";
321
+ if (policy === "overlap_mandatory") {
322
+ // Epoch files are notification/diagnostic state only. Derive both sides from the
323
+ // current merge base so an overlap from land N remains enforced after unrelated land N+1.
324
+ const mergeBase = await deps.exec("git", ["merge-base", fresh.mainBranch, lane.branch], {
325
+ cwd: fresh.topLevel,
326
+ timeout: 60_000,
327
+ maxBuffer: 1024 * 1024,
328
+ });
329
+ if (mergeBase.code !== 0 || !mergeBase.stdout.trim()) {
330
+ syncRequired = true;
331
+ }
332
+ else {
333
+ const base = mergeBase.stdout.trim().split(/\s+/u)[0];
334
+ const lanePaths = await changedPaths(deps, fresh.topLevel, base, lane.branch);
335
+ const mainPaths = await changedPaths(deps, fresh.topLevel, base, fresh.mainBranch);
336
+ if (!lanePaths || !mainPaths) {
337
+ syncRequired = true;
338
+ }
339
+ else {
340
+ syncRequired = [...lanePaths].some((path) => mainPaths.has(path));
341
+ }
342
+ }
343
+ }
344
+ if (policy === "land_time_only")
345
+ syncRequired = false;
346
+ if (!syncRequired) {
347
+ this._cachedAllowed = true;
348
+ return { allowed: true };
349
+ }
350
+ this._cachedAllowed = false;
351
+ return {
352
+ allowed: false,
353
+ code: "sync_required",
354
+ message: `worktree-sync: lane '${this.config.laneKey}' must rebase main before further mutations ` +
355
+ `(main moved past this lane). Commit any WIP (git add/commit stay available), then call ` +
356
+ `worktree_sync {"action":"sync"}, resolve conflicts if any, and continue. (sync_required)`,
357
+ };
358
+ }
359
+ }
360
+ //# sourceMappingURL=lane-gate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lane-gate.js","sourceRoot":"","sources":["../../../src/core/worktree-sync/lane-gate.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Lane gate: G8/G10 enforcement for a LANE-BOUND `pi` session (launched with\n * `PI_WORKTREE_LANE=<key>`). RuntimeBuilder wraps the session's file-mutation tools (edit /\n * write / bash) with {@link WorktreeLaneGate.checkMutation}; a lane that the active policy marks\n * sync_required fails closed with the exact recovery step until it rebases main.\n *\n * Honesty boundary (unchanged from the tmux trust model): this is HARD for pi children -- the\n * wrapper lives under the tool layer, not in the prompt -- and cooperative-only for foreign\n * CLIs, whose backstop is the land CAS (G3): stale work simply cannot land.\n *\n * Determinism: the gate re-derives from git only when the epoch file actually changed (mtime\n * fence) or while blocked; verdicts in between are cached. No polling, no timers.\n */\n\nimport { existsSync, realpathSync, statSync } from \"node:fs\";\nimport { basename, dirname, join, resolve, sep } from \"node:path\";\nimport type { WorktreeSyncPolicy } from \"./codes.ts\";\nimport { deriveLaneFacts, type RepoContext, resolveRepoContext, type WorktreeSyncEngineDeps } from \"./git-engine.ts\";\nimport { readLane } from \"./store.ts\";\n\nexport type LaneBashVerdict =\n\t| { verdict: \"allowed\" }\n\t| { verdict: \"allowed_even_when_sync_required\" }\n\t| { verdict: \"main_mutation_refused\"; reason: string };\n\nconst SYNC_SAFE_GIT_SUBCOMMANDS = new Set([\n\t\"status\",\n\t\"diff\",\n\t\"log\",\n\t\"show\",\n\t\"add\",\n\t\"commit\",\n\t\"stash\",\n\t\"rev-parse\",\n\t\"ls-files\",\n\t\"blame\",\n\t\"grep\",\n]);\n\nconst MAIN_MUTATING_GIT_SUBCOMMANDS = new Set([\"merge\", \"rebase\", \"reset\", \"commit\", \"branch\", \"update-ref\", \"push\"]);\n\n/**\n * Classify one bash command line for a lane-bound session (G10 + the sync_required allowlist).\n * Tokenization is whitespace-naive by design -- deterministic and reviewable; shell-quoting\n * tricks can evade it, which is the documented cooperative boundary (the land CAS cannot be\n * evaded). Command POSITION still matters: `git` only begins an invocation at the start of the\n * command or immediately after a shell separator (`&&`, `||`, `;`, `|`) -- a bare `git` token\n * elsewhere (e.g. as a plain argument to `echo`) is not an invocation. Rules:\n * - `git push` anywhere: refused (main moves only through the land gate; pushing is owner-only).\n * - `git -C <path>` / `--git-dir` combined with a mutating subcommand: refused (escaping the\n * lane worktree to operate on another checkout, e.g. the hub).\n * - `git branch -f/-M/-D <main>` / `git update-ref refs/heads/<main>`: refused.\n * - Everything else: allowed; a read/commit-shaped git subcommand additionally stays allowed\n * while the lane is sync_required (committing WIP is the prescribed step BEFORE syncing).\n */\nexport function classifyLaneBashCommand(command: string, mainBranch: string): LaneBashVerdict {\n\t// This classifier is defense-in-depth, not a shell parser. Refuse compound\n\t// syntax before any segment can return an allow verdict; otherwise `git\n\t// status; git push` is approved by the first safe segment.\n\tif (/[|;&<>$`(){}\\n\\r]/u.test(command)) {\n\t\treturn {\n\t\t\tverdict: \"main_mutation_refused\",\n\t\t\treason: \"compound shell syntax is refused in a lane; use typed worktree_sync actions\",\n\t\t};\n\t}\n\tif (/^\\s*[\"']git[\"']\\s/u.test(command)) {\n\t\treturn {\n\t\t\tverdict: \"main_mutation_refused\",\n\t\t\treason: \"quoted command names are refused in a lane; use the typed Git actions\",\n\t\t};\n\t}\n\tconst segments = [command];\n\tlet allowedWhenSyncRequired = false;\n\tfor (const segment of segments) {\n\t\tconst tokens = segment.trim().split(/\\s+/).filter(Boolean);\n\t\tif (tokens[0] !== \"git\") continue;\n\t\tlet j = 1;\n\t\tlet escapesWorktree = false;\n\t\t// Skip git global options to find the subcommand; -C/--git-dir mark checkout escape.\n\t\twhile (j < tokens.length) {\n\t\t\tconst token = tokens[j] ?? \"\";\n\t\t\tif (token === \"-C\" || token === \"--git-dir\" || token === \"--work-tree\") {\n\t\t\t\tescapesWorktree = true;\n\t\t\t\tj += 2;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (token.startsWith(\"-C\") && token !== \"-C\") {\n\t\t\t\tescapesWorktree = true;\n\t\t\t\tj += 1;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (token.startsWith(\"--git-dir=\") || token.startsWith(\"--work-tree=\")) {\n\t\t\t\tescapesWorktree = true;\n\t\t\t\tj += 1;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (token.startsWith(\"-\")) {\n\t\t\t\tj += 1;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tconst subcommand = tokens[j] ?? \"\";\n\t\tconst rest = tokens.slice(j + 1);\n\t\tif (subcommand === \"push\") {\n\t\t\treturn {\n\t\t\t\tverdict: \"main_mutation_refused\",\n\t\t\t\treason:\n\t\t\t\t\t\"git push is refused in a lane session; landing is the only integration path and pushing stays an owner action\",\n\t\t\t};\n\t\t}\n\t\tif (escapesWorktree && MAIN_MUTATING_GIT_SUBCOMMANDS.has(subcommand)) {\n\t\t\treturn {\n\t\t\t\tverdict: \"main_mutation_refused\",\n\t\t\t\treason: `git -C/--git-dir with '${subcommand}' escapes the lane worktree; operate only on this lane (G10)`,\n\t\t\t};\n\t\t}\n\t\tif (\n\t\t\tsubcommand === \"branch\" &&\n\t\t\trest.some((token) => /^(?:-f|--force|-M|-m|-D|-d)$/.test(token)) &&\n\t\t\trest.includes(mainBranch)\n\t\t) {\n\t\t\treturn {\n\t\t\t\tverdict: \"main_mutation_refused\",\n\t\t\t\treason: `git branch may not move/delete '${mainBranch}' from a lane; main moves only through the land gate (G10)`,\n\t\t\t};\n\t\t}\n\t\tif (subcommand === \"update-ref\" && rest.some((token) => token === `refs/heads/${mainBranch}`)) {\n\t\t\treturn {\n\t\t\t\tverdict: \"main_mutation_refused\",\n\t\t\t\treason: `git update-ref may not touch refs/heads/${mainBranch} from a lane (G10)`,\n\t\t\t};\n\t\t}\n\t\tif (SYNC_SAFE_GIT_SUBCOMMANDS.has(subcommand)) allowedWhenSyncRequired = true;\n\t}\n\treturn allowedWhenSyncRequired ? { verdict: \"allowed_even_when_sync_required\" } : { verdict: \"allowed\" };\n}\n\n/** Symlink-safe resolution of a path that may not exist yet: realpath the NEAREST EXISTING\n * ancestor, then re-append the not-yet-existing tail literally (a not-yet-created file's own\n * missing final component can never itself be a symlink escape). */\nfunction resolveSymlinkSafe(targetPath: string): string {\n\tif (existsSync(targetPath)) {\n\t\ttry {\n\t\t\treturn realpathSync(targetPath);\n\t\t} catch {\n\t\t\treturn targetPath;\n\t\t}\n\t}\n\tconst tail: string[] = [basename(targetPath)];\n\tlet ancestor = dirname(targetPath);\n\twhile (!existsSync(ancestor)) {\n\t\tconst parent = dirname(ancestor);\n\t\tif (parent === ancestor) break; // reached the filesystem root without finding one\n\t\ttail.unshift(basename(ancestor));\n\t\tancestor = parent;\n\t}\n\tlet realAncestor: string;\n\ttry {\n\t\trealAncestor = realpathSync(ancestor);\n\t} catch {\n\t\trealAncestor = ancestor;\n\t}\n\treturn join(realAncestor, ...tail);\n}\n\n/** Symlink-safe containment check (G-path): does `targetPath` resolve inside `worktreePath`? */\nexport function isPathOutsideLane(targetPath: string, worktreePath: string): boolean {\n\tlet realRoot: string;\n\ttry {\n\t\trealRoot = realpathSync(worktreePath);\n\t} catch {\n\t\trealRoot = worktreePath;\n\t}\n\tconst resolvedTarget = resolveSymlinkSafe(targetPath);\n\treturn resolvedTarget !== realRoot && !resolvedTarget.startsWith(realRoot + sep);\n}\n\n/** Resolve a user-supplied relative lane path and reject symlink/parent escapes. */\nexport function resolveLaneMutationPath(worktreePath: string, candidate: string): string | undefined {\n\tconst target = resolve(worktreePath, candidate);\n\treturn isPathOutsideLane(target, worktreePath) ? undefined : target;\n}\n\nexport interface WorktreeLaneGateConfig {\n\tlaneKey: string;\n\tengineDeps: () => WorktreeSyncEngineDeps;\n\tpolicy: () => WorktreeSyncPolicy;\n\t/** Worker launches use a hard shell envelope: only lane-safe Git/WIP commands and the owner-configured\n\t * exact gate command may pass through bash. Interactive lane sessions retain the legacy cooperative\n\t * command surface while the typed worktree_sync actions are used for hard worker mutations. */\n\thardShell?: boolean;\n\ttrustedGateCommand?: () => string | undefined;\n}\n\nexport type LaneMutationCheck = { allowed: true } | { allowed: false; code: string; message: string };\n\nasync function changedPaths(\n\tdeps: WorktreeSyncEngineDeps,\n\tcwd: string,\n\tbase: string,\n\tref: string,\n): Promise<Set<string> | undefined> {\n\tconst result = await deps.exec(\"git\", [\"diff\", \"--name-only\", `${base}..${ref}`, \"--\"], {\n\t\tcwd,\n\t\ttimeout: 60_000,\n\t\tmaxBuffer: 1024 * 1024,\n\t});\n\tif (result.code !== 0) return undefined;\n\treturn new Set(\n\t\tresult.stdout\n\t\t\t.split(/\\r?\\n/u)\n\t\t\t.map((path) => path.trim())\n\t\t\t.filter(Boolean),\n\t);\n}\n\nfunction hardShellCommandAllowed(command: string, mainBranch: string, trustedGateCommand?: string): boolean {\n\tconst trimmed = command.trim();\n\tif (trustedGateCommand && trimmed === trustedGateCommand.trim()) return true;\n\tif (!/^git(?:\\s|$)/u.test(trimmed)) return false;\n\tconst verdict = classifyLaneBashCommand(trimmed, mainBranch);\n\tif (verdict.verdict === \"main_mutation_refused\") return false;\n\tconst tokens = trimmed.split(/\\s+/u);\n\tconst subcommand = tokens[1] ?? \"\";\n\tif (!SYNC_SAFE_GIT_SUBCOMMANDS.has(subcommand) && subcommand !== \"commit\") return false;\n\t// Git path operands must not escape the lane checkout. The typed worktree\n\t// actions are the authoritative route for path-sensitive add/diff operations;\n\t// this final check prevents the common absolute/parent escape in the shell floor.\n\treturn !tokens.slice(2).some((token) => token.startsWith(\"/\") || token.startsWith(\"..\") || token.includes(\"/../\"));\n}\n\n/**\n * The G8 gate object RuntimeBuilder holds per lane-bound session. `checkMutation` is called by\n * the wrapped edit/write/bash tools before every mutating execution.\n */\nexport class WorktreeLaneGate {\n\tprivate readonly config: WorktreeLaneGateConfig;\n\tprivate _ctx: RepoContext | undefined;\n\tprivate _epochFileMtimeMs: number | undefined;\n\tprivate _cachedAllowed = false;\n\n\tconstructor(config: WorktreeLaneGateConfig) {\n\t\tthis.config = config;\n\t}\n\n\tprivate async resolveContext(): Promise<RepoContext | undefined> {\n\t\tif (this._ctx) return this._ctx;\n\t\tconst ctx = await resolveRepoContext(this.config.engineDeps());\n\t\tif (\"code\" in ctx) return undefined;\n\t\tthis._ctx = ctx;\n\t\treturn ctx;\n\t}\n\n\t/** Cheap fence: has the epoch file changed since the last allowed verdict? */\n\tprivate epochChanged(ctx: RepoContext): boolean {\n\t\tlet mtimeMs: number | undefined;\n\t\ttry {\n\t\t\tmtimeMs = statSync(ctx.paths.epochFile).mtimeMs;\n\t\t} catch {\n\t\t\tmtimeMs = undefined;\n\t\t}\n\t\tif (mtimeMs === this._epochFileMtimeMs) return false;\n\t\tthis._epochFileMtimeMs = mtimeMs;\n\t\treturn true;\n\t}\n\n\tasync checkMutation(toolName: string, bashCommand?: string, targetPath?: string): Promise<LaneMutationCheck> {\n\t\tconst ctx = await this.resolveContext();\n\t\t// No repo context (deleted repo, engine failure): fail OPEN for plain tools -- the land\n\t\t// CAS still holds -- but the G10 bash rules below never depend on repo state.\n\t\tconst mainBranch = ctx?.mainBranch ?? \"main\";\n\t\tif (this.config.hardShell && !ctx) {\n\t\t\treturn {\n\t\t\t\tallowed: false,\n\t\t\t\tcode: \"lane_state_unavailable\",\n\t\t\t\tmessage: \"worktree-sync: lane state is unavailable; hard worker mutations fail closed\",\n\t\t\t};\n\t\t}\n\n\t\tif (toolName === \"bash\" && bashCommand !== undefined) {\n\t\t\tif (\n\t\t\t\tthis.config.hardShell &&\n\t\t\t\t!hardShellCommandAllowed(bashCommand, mainBranch, this.config.trustedGateCommand?.())\n\t\t\t) {\n\t\t\t\treturn {\n\t\t\t\t\tallowed: false,\n\t\t\t\t\tcode: \"main_mutation_refused\",\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t\"worktree-sync: unrestricted bash is unavailable in a hard worker lane; use typed worktree_sync actions\",\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst verdict = classifyLaneBashCommand(bashCommand, mainBranch);\n\t\t\tif (verdict.verdict === \"main_mutation_refused\") {\n\t\t\t\treturn { allowed: false, code: \"main_mutation_refused\", message: `worktree-sync: ${verdict.reason}` };\n\t\t\t}\n\t\t\tif (verdict.verdict === \"allowed_even_when_sync_required\") return { allowed: true };\n\t\t}\n\t\tif (!ctx) return { allowed: true };\n\n\t\t// G-path: an edit/write target must resolve INSIDE this lane's worktree (symlink-safe),\n\t\t// checked BEFORE the staleness cache so a cached \"allowed\" verdict never short-circuits past\n\t\t// it. No active lane record: existing fail-open stands (mirrors the readLane check below).\n\t\tif ((toolName === \"edit\" || toolName === \"write\") && targetPath !== undefined) {\n\t\t\tconst laneForPath = await readLane(ctx.paths, this.config.laneKey);\n\t\t\tif (laneForPath?.status === \"active\" && isPathOutsideLane(targetPath, laneForPath.worktreePath)) {\n\t\t\t\treturn {\n\t\t\t\t\tallowed: false,\n\t\t\t\t\tcode: \"path_outside_lane\",\n\t\t\t\t\tmessage: `worktree-sync: '${targetPath}' resolves outside lane '${this.config.laneKey}' worktree (${laneForPath.worktreePath}); edit/write only inside your lane checkout`,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\t// G8: sync_required fails mutations closed. Re-derive only when the epoch moved or while\n\t\t// blocked (a successful sync clears the block on the very next check).\n\t\tif (this._cachedAllowed && !this.epochChanged(ctx)) return { allowed: true };\n\n\t\tconst deps = this.config.engineDeps();\n\t\tconst lane = await readLane(ctx.paths, this.config.laneKey);\n\t\tif (!lane || lane.status !== \"active\") {\n\t\t\tif (this.config.hardShell) {\n\t\t\t\treturn {\n\t\t\t\t\tallowed: false,\n\t\t\t\t\tcode: \"lane_state_unavailable\",\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t\"worktree-sync: hard worker lane registration is missing or inactive; reconcile before mutating\",\n\t\t\t\t};\n\t\t\t}\n\t\t\tthis._cachedAllowed = true;\n\t\t\treturn { allowed: true };\n\t\t}\n\t\t// Re-derive main tip: the cached ctx pins the sha from session start.\n\t\tconst fresh = await resolveRepoContext(deps);\n\t\tif (\"code\" in fresh) {\n\t\t\tif (this.config.hardShell) {\n\t\t\t\treturn {\n\t\t\t\t\tallowed: false,\n\t\t\t\t\tcode: \"lane_state_unavailable\",\n\t\t\t\t\tmessage: \"worktree-sync: Git context is unavailable; hard worker mutation refused\",\n\t\t\t\t};\n\t\t\t}\n\t\t\tthis._cachedAllowed = true;\n\t\t\treturn { allowed: true };\n\t\t}\n\t\tthis._ctx = fresh;\n\t\tconst facts = await deriveLaneFacts(deps, fresh, lane);\n\t\tif (facts.fresh) {\n\t\t\tthis._cachedAllowed = true;\n\t\t\treturn { allowed: true };\n\t\t}\n\n\t\tconst policy = this.config.policy();\n\t\tlet syncRequired = policy === \"on_land_mandatory\";\n\t\tif (policy === \"overlap_mandatory\") {\n\t\t\t// Epoch files are notification/diagnostic state only. Derive both sides from the\n\t\t\t// current merge base so an overlap from land N remains enforced after unrelated land N+1.\n\t\t\tconst mergeBase = await deps.exec(\"git\", [\"merge-base\", fresh.mainBranch, lane.branch], {\n\t\t\t\tcwd: fresh.topLevel,\n\t\t\t\ttimeout: 60_000,\n\t\t\t\tmaxBuffer: 1024 * 1024,\n\t\t\t});\n\t\t\tif (mergeBase.code !== 0 || !mergeBase.stdout.trim()) {\n\t\t\t\tsyncRequired = true;\n\t\t\t} else {\n\t\t\t\tconst base = mergeBase.stdout.trim().split(/\\s+/u)[0];\n\t\t\t\tconst lanePaths = await changedPaths(deps, fresh.topLevel, base, lane.branch);\n\t\t\t\tconst mainPaths = await changedPaths(deps, fresh.topLevel, base, fresh.mainBranch);\n\t\t\t\tif (!lanePaths || !mainPaths) {\n\t\t\t\t\tsyncRequired = true;\n\t\t\t\t} else {\n\t\t\t\t\tsyncRequired = [...lanePaths].some((path) => mainPaths.has(path));\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (policy === \"land_time_only\") syncRequired = false;\n\n\t\tif (!syncRequired) {\n\t\t\tthis._cachedAllowed = true;\n\t\t\treturn { allowed: true };\n\t\t}\n\t\tthis._cachedAllowed = false;\n\t\treturn {\n\t\t\tallowed: false,\n\t\t\tcode: \"sync_required\",\n\t\t\tmessage:\n\t\t\t\t`worktree-sync: lane '${this.config.laneKey}' must rebase main before further mutations ` +\n\t\t\t\t`(main moved past this lane). Commit any WIP (git add/commit stay available), then call ` +\n\t\t\t\t`worktree_sync {\"action\":\"sync\"}, resolve conflicts if any, and continue. (sync_required)`,\n\t\t};\n\t}\n}\n"]}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Worktree-sync runtime composition: the pieces main.ts / RuntimeBuilder wire together.
3
+ *
4
+ * The lane binding is an ENVIRONMENT contract: a session launched with `PI_WORKTREE_LANE=<key>`
5
+ * (set by the `--worktree-lane` CLI flag, or directly by any launcher -- tmux panes inherit it
6
+ * from the launch command line) is lane-bound: its file-mutation tools run behind the lane gate
7
+ * (G8/G10) and its epoch watcher injects staleness notices. The env form is deliberate -- it
8
+ * crosses EVERY process boundary (tmux, exec, nested shells) without per-launcher plumbing.
9
+ */
10
+ import type { SettingsManager } from "../settings-manager.ts";
11
+ import { type WorktreeSyncEngineDeps } from "./git-engine.ts";
12
+ export declare const PI_WORKTREE_LANE_ENV = "PI_WORKTREE_LANE";
13
+ /** The lane this process is bound to, from the cross-process env contract. Invalid values are
14
+ * ignored (never a crash on a malformed env). */
15
+ export declare function getBoundWorktreeLaneKey(env?: NodeJS.ProcessEnv): string | undefined;
16
+ export interface WorktreeSyncEngineConfig {
17
+ cwd: string;
18
+ agentDir: string;
19
+ settingsManager: SettingsManager;
20
+ sessionId?: string;
21
+ signal?: AbortSignal;
22
+ }
23
+ /** Build production engine deps from session facts + resolved settings. */
24
+ export declare function buildWorktreeSyncEngineDeps(config: WorktreeSyncEngineConfig): WorktreeSyncEngineDeps;
25
+ export interface WorktreeSyncRuntimeConfig extends WorktreeSyncEngineConfig {
26
+ /** Structural notice injection into the running session (host `sendCustomMessage` seam):
27
+ * "steer" mid-turn, trigger a turn when idle -- the host closure decides the mechanics. */
28
+ notify: (text: string) => void;
29
+ /** Diagnostics sink for startup-reconcile findings (never throws into the session). */
30
+ onDiagnostic?: (message: string) => void;
31
+ }
32
+ export interface WorktreeSyncRuntimeHandle {
33
+ stop(): void;
34
+ }
35
+ /**
36
+ * Start the per-session worktree-sync runtime (main.ts composition root):
37
+ * 1. one startup reconcile pass (registry vs git reality -- orphans marked, lost lanes
38
+ * re-registered, dead owners cleared, provably-stale lock released), and
39
+ * 2. for a LANE-BOUND session, the epoch watcher: a land anywhere on this machine injects a
40
+ * deterministic staleness notice into this session promptly (the pull-guaranteed channel is
41
+ * still the lane gate + turn-start checks -- enforcement never rides on the watcher).
42
+ *
43
+ * No-op when worktree-sync is disabled. Never throws: this runs at session start and a broken
44
+ * repo state must surface as a diagnostic, not a startup crash.
45
+ */
46
+ export declare function startWorktreeSyncRuntime(config: WorktreeSyncRuntimeConfig): Promise<WorktreeSyncRuntimeHandle>;
47
+ //# sourceMappingURL=runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../src/core/worktree-sync/runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAIN,KAAK,sBAAsB,EAC3B,MAAM,iBAAiB,CAAC;AAGzB,eAAO,MAAM,oBAAoB,qBAAqB,CAAC;AAIvD;iDACiD;AACjD,wBAAgB,uBAAuB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,GAAG,SAAS,CAGhG;AAED,MAAM,WAAW,wBAAwB;IACxC,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,eAAe,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,WAAW,CAAC;CACrB;AAED,2EAA2E;AAC3E,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,wBAAwB,GAAG,sBAAsB,CAapG;AAED,MAAM,WAAW,yBAA0B,SAAQ,wBAAwB;IAC1E;+FAC2F;IAC3F,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,uFAAuF;IACvF,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC;AAED,MAAM,WAAW,yBAAyB;IACzC,IAAI,IAAI,IAAI,CAAC;CACb;AAID;;;;;;;;;;GAUG;AACH,wBAAsB,wBAAwB,CAAC,MAAM,EAAE,yBAAyB,GAAG,OAAO,CAAC,yBAAyB,CAAC,CA6CpH","sourcesContent":["/**\n * Worktree-sync runtime composition: the pieces main.ts / RuntimeBuilder wire together.\n *\n * The lane binding is an ENVIRONMENT contract: a session launched with `PI_WORKTREE_LANE=<key>`\n * (set by the `--worktree-lane` CLI flag, or directly by any launcher -- tmux panes inherit it\n * from the launch command line) is lane-bound: its file-mutation tools run behind the lane gate\n * (G8/G10) and its epoch watcher injects staleness notices. The env form is deliberate -- it\n * crosses EVERY process boundary (tmux, exec, nested shells) without per-launcher plumbing.\n */\n\nimport { worktreesDir } from \"../agent-paths.ts\";\nimport type { SettingsManager } from \"../settings-manager.ts\";\nimport {\n\tcreateDefaultWorktreeSyncExec,\n\treconcile,\n\tresolveRepoContext,\n\ttype WorktreeSyncEngineDeps,\n} from \"./git-engine.ts\";\nimport { type EpochWatcherHandle, startEpochWatcher } from \"./watcher.ts\";\n\nexport const PI_WORKTREE_LANE_ENV = \"PI_WORKTREE_LANE\";\n\nconst LANE_KEY_RE = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/;\n\n/** The lane this process is bound to, from the cross-process env contract. Invalid values are\n * ignored (never a crash on a malformed env). */\nexport function getBoundWorktreeLaneKey(env: NodeJS.ProcessEnv = process.env): string | undefined {\n\tconst value = env[PI_WORKTREE_LANE_ENV]?.trim();\n\treturn value && LANE_KEY_RE.test(value) ? value : undefined;\n}\n\nexport interface WorktreeSyncEngineConfig {\n\tcwd: string;\n\tagentDir: string;\n\tsettingsManager: SettingsManager;\n\tsessionId?: string;\n\tsignal?: AbortSignal;\n}\n\n/** Build production engine deps from session facts + resolved settings. */\nexport function buildWorktreeSyncEngineDeps(config: WorktreeSyncEngineConfig): WorktreeSyncEngineDeps {\n\tconst settings = config.settingsManager.getWorktreeSyncSettings();\n\treturn {\n\t\texec: createDefaultWorktreeSyncExec(),\n\t\tcwd: config.cwd,\n\t\tworktreesBaseDir: settings.worktreesRoot ?? worktreesDir(config.agentDir),\n\t\toptions: {\n\t\t\tmaxLanes: settings.maxLanes,\n\t\t\t...(settings.mainBranch !== undefined ? { mainBranchOverride: settings.mainBranch } : {}),\n\t\t},\n\t\t...(config.sessionId !== undefined ? { sessionId: config.sessionId } : {}),\n\t\t...(config.signal !== undefined ? { signal: config.signal } : {}),\n\t};\n}\n\nexport interface WorktreeSyncRuntimeConfig extends WorktreeSyncEngineConfig {\n\t/** Structural notice injection into the running session (host `sendCustomMessage` seam):\n\t * \"steer\" mid-turn, trigger a turn when idle -- the host closure decides the mechanics. */\n\tnotify: (text: string) => void;\n\t/** Diagnostics sink for startup-reconcile findings (never throws into the session). */\n\tonDiagnostic?: (message: string) => void;\n}\n\nexport interface WorktreeSyncRuntimeHandle {\n\tstop(): void;\n}\n\nconst NOOP_HANDLE: WorktreeSyncRuntimeHandle = { stop: () => {} };\n\n/**\n * Start the per-session worktree-sync runtime (main.ts composition root):\n * 1. one startup reconcile pass (registry vs git reality -- orphans marked, lost lanes\n * re-registered, dead owners cleared, provably-stale lock released), and\n * 2. for a LANE-BOUND session, the epoch watcher: a land anywhere on this machine injects a\n * deterministic staleness notice into this session promptly (the pull-guaranteed channel is\n * still the lane gate + turn-start checks -- enforcement never rides on the watcher).\n *\n * No-op when worktree-sync is disabled. Never throws: this runs at session start and a broken\n * repo state must surface as a diagnostic, not a startup crash.\n */\nexport async function startWorktreeSyncRuntime(config: WorktreeSyncRuntimeConfig): Promise<WorktreeSyncRuntimeHandle> {\n\tconst settings = config.settingsManager.getWorktreeSyncSettings();\n\tif (!settings.enabled) return NOOP_HANDLE;\n\tconst deps = buildWorktreeSyncEngineDeps(config);\n\n\ttry {\n\t\tconst reconciled = await reconcile(deps);\n\t\tif (reconciled.code === \"reconciled\") {\n\t\t\tconst findings: string[] = [];\n\t\t\tif (reconciled.orphanedLaneKeys.length > 0)\n\t\t\t\tfindings.push(`orphaned: ${reconciled.orphanedLaneKeys.join(\", \")}`);\n\t\t\tif (reconciled.reRegisteredLaneKeys.length > 0) {\n\t\t\t\tfindings.push(`re-registered: ${reconciled.reRegisteredLaneKeys.join(\", \")}`);\n\t\t\t}\n\t\t\tif (reconciled.staleLockReleased) findings.push(\"released a stale integration lock\");\n\t\t\tif (findings.length > 0) config.onDiagnostic?.(`worktree-sync reconcile: ${findings.join(\"; \")}`);\n\t\t} else if (reconciled.code !== \"not_a_git_repo\" && reconciled.code !== \"default_branch_unresolved\") {\n\t\t\t// Now that the runtime starts in every session, these two codes are benign absence, not a\n\t\t\t// problem to surface: a non-repo cwd, or a repo whose default branch isn't named main/master.\n\t\t\t// Every other refusal still gets a diagnostic.\n\t\t\tconfig.onDiagnostic?.(`worktree-sync reconcile skipped: [${reconciled.code}] ${reconciled.message}`);\n\t\t}\n\t} catch (error) {\n\t\tconfig.onDiagnostic?.(\n\t\t\t`worktree-sync reconcile failed: ${error instanceof Error ? error.message : String(error)}`,\n\t\t);\n\t}\n\n\tconst laneKey = getBoundWorktreeLaneKey();\n\tif (!laneKey) return NOOP_HANDLE;\n\n\tlet watcher: EpochWatcherHandle | undefined;\n\ttry {\n\t\tconst ctx = await resolveRepoContext(deps);\n\t\tif (!(\"code\" in ctx)) {\n\t\t\twatcher = startEpochWatcher({\n\t\t\t\tepochFile: ctx.paths.epochFile,\n\t\t\t\tlaneKey,\n\t\t\t\tnotify: config.notify,\n\t\t\t});\n\t\t}\n\t} catch (error) {\n\t\tconfig.onDiagnostic?.(`worktree-sync watcher failed: ${error instanceof Error ? error.message : String(error)}`);\n\t}\n\treturn { stop: () => watcher?.stop() };\n}\n"]}
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Worktree-sync runtime composition: the pieces main.ts / RuntimeBuilder wire together.
3
+ *
4
+ * The lane binding is an ENVIRONMENT contract: a session launched with `PI_WORKTREE_LANE=<key>`
5
+ * (set by the `--worktree-lane` CLI flag, or directly by any launcher -- tmux panes inherit it
6
+ * from the launch command line) is lane-bound: its file-mutation tools run behind the lane gate
7
+ * (G8/G10) and its epoch watcher injects staleness notices. The env form is deliberate -- it
8
+ * crosses EVERY process boundary (tmux, exec, nested shells) without per-launcher plumbing.
9
+ */
10
+ import { worktreesDir } from "../agent-paths.js";
11
+ import { createDefaultWorktreeSyncExec, reconcile, resolveRepoContext, } from "./git-engine.js";
12
+ import { startEpochWatcher } from "./watcher.js";
13
+ export const PI_WORKTREE_LANE_ENV = "PI_WORKTREE_LANE";
14
+ const LANE_KEY_RE = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/;
15
+ /** The lane this process is bound to, from the cross-process env contract. Invalid values are
16
+ * ignored (never a crash on a malformed env). */
17
+ export function getBoundWorktreeLaneKey(env = process.env) {
18
+ const value = env[PI_WORKTREE_LANE_ENV]?.trim();
19
+ return value && LANE_KEY_RE.test(value) ? value : undefined;
20
+ }
21
+ /** Build production engine deps from session facts + resolved settings. */
22
+ export function buildWorktreeSyncEngineDeps(config) {
23
+ const settings = config.settingsManager.getWorktreeSyncSettings();
24
+ return {
25
+ exec: createDefaultWorktreeSyncExec(),
26
+ cwd: config.cwd,
27
+ worktreesBaseDir: settings.worktreesRoot ?? worktreesDir(config.agentDir),
28
+ options: {
29
+ maxLanes: settings.maxLanes,
30
+ ...(settings.mainBranch !== undefined ? { mainBranchOverride: settings.mainBranch } : {}),
31
+ },
32
+ ...(config.sessionId !== undefined ? { sessionId: config.sessionId } : {}),
33
+ ...(config.signal !== undefined ? { signal: config.signal } : {}),
34
+ };
35
+ }
36
+ const NOOP_HANDLE = { stop: () => { } };
37
+ /**
38
+ * Start the per-session worktree-sync runtime (main.ts composition root):
39
+ * 1. one startup reconcile pass (registry vs git reality -- orphans marked, lost lanes
40
+ * re-registered, dead owners cleared, provably-stale lock released), and
41
+ * 2. for a LANE-BOUND session, the epoch watcher: a land anywhere on this machine injects a
42
+ * deterministic staleness notice into this session promptly (the pull-guaranteed channel is
43
+ * still the lane gate + turn-start checks -- enforcement never rides on the watcher).
44
+ *
45
+ * No-op when worktree-sync is disabled. Never throws: this runs at session start and a broken
46
+ * repo state must surface as a diagnostic, not a startup crash.
47
+ */
48
+ export async function startWorktreeSyncRuntime(config) {
49
+ const settings = config.settingsManager.getWorktreeSyncSettings();
50
+ if (!settings.enabled)
51
+ return NOOP_HANDLE;
52
+ const deps = buildWorktreeSyncEngineDeps(config);
53
+ try {
54
+ const reconciled = await reconcile(deps);
55
+ if (reconciled.code === "reconciled") {
56
+ const findings = [];
57
+ if (reconciled.orphanedLaneKeys.length > 0)
58
+ findings.push(`orphaned: ${reconciled.orphanedLaneKeys.join(", ")}`);
59
+ if (reconciled.reRegisteredLaneKeys.length > 0) {
60
+ findings.push(`re-registered: ${reconciled.reRegisteredLaneKeys.join(", ")}`);
61
+ }
62
+ if (reconciled.staleLockReleased)
63
+ findings.push("released a stale integration lock");
64
+ if (findings.length > 0)
65
+ config.onDiagnostic?.(`worktree-sync reconcile: ${findings.join("; ")}`);
66
+ }
67
+ else if (reconciled.code !== "not_a_git_repo" && reconciled.code !== "default_branch_unresolved") {
68
+ // Now that the runtime starts in every session, these two codes are benign absence, not a
69
+ // problem to surface: a non-repo cwd, or a repo whose default branch isn't named main/master.
70
+ // Every other refusal still gets a diagnostic.
71
+ config.onDiagnostic?.(`worktree-sync reconcile skipped: [${reconciled.code}] ${reconciled.message}`);
72
+ }
73
+ }
74
+ catch (error) {
75
+ config.onDiagnostic?.(`worktree-sync reconcile failed: ${error instanceof Error ? error.message : String(error)}`);
76
+ }
77
+ const laneKey = getBoundWorktreeLaneKey();
78
+ if (!laneKey)
79
+ return NOOP_HANDLE;
80
+ let watcher;
81
+ try {
82
+ const ctx = await resolveRepoContext(deps);
83
+ if (!("code" in ctx)) {
84
+ watcher = startEpochWatcher({
85
+ epochFile: ctx.paths.epochFile,
86
+ laneKey,
87
+ notify: config.notify,
88
+ });
89
+ }
90
+ }
91
+ catch (error) {
92
+ config.onDiagnostic?.(`worktree-sync watcher failed: ${error instanceof Error ? error.message : String(error)}`);
93
+ }
94
+ return { stop: () => watcher?.stop() };
95
+ }
96
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../../src/core/worktree-sync/runtime.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Worktree-sync runtime composition: the pieces main.ts / RuntimeBuilder wire together.\n *\n * The lane binding is an ENVIRONMENT contract: a session launched with `PI_WORKTREE_LANE=<key>`\n * (set by the `--worktree-lane` CLI flag, or directly by any launcher -- tmux panes inherit it\n * from the launch command line) is lane-bound: its file-mutation tools run behind the lane gate\n * (G8/G10) and its epoch watcher injects staleness notices. The env form is deliberate -- it\n * crosses EVERY process boundary (tmux, exec, nested shells) without per-launcher plumbing.\n */\n\nimport { worktreesDir } from \"../agent-paths.ts\";\nimport type { SettingsManager } from \"../settings-manager.ts\";\nimport {\n\tcreateDefaultWorktreeSyncExec,\n\treconcile,\n\tresolveRepoContext,\n\ttype WorktreeSyncEngineDeps,\n} from \"./git-engine.ts\";\nimport { type EpochWatcherHandle, startEpochWatcher } from \"./watcher.ts\";\n\nexport const PI_WORKTREE_LANE_ENV = \"PI_WORKTREE_LANE\";\n\nconst LANE_KEY_RE = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/;\n\n/** The lane this process is bound to, from the cross-process env contract. Invalid values are\n * ignored (never a crash on a malformed env). */\nexport function getBoundWorktreeLaneKey(env: NodeJS.ProcessEnv = process.env): string | undefined {\n\tconst value = env[PI_WORKTREE_LANE_ENV]?.trim();\n\treturn value && LANE_KEY_RE.test(value) ? value : undefined;\n}\n\nexport interface WorktreeSyncEngineConfig {\n\tcwd: string;\n\tagentDir: string;\n\tsettingsManager: SettingsManager;\n\tsessionId?: string;\n\tsignal?: AbortSignal;\n}\n\n/** Build production engine deps from session facts + resolved settings. */\nexport function buildWorktreeSyncEngineDeps(config: WorktreeSyncEngineConfig): WorktreeSyncEngineDeps {\n\tconst settings = config.settingsManager.getWorktreeSyncSettings();\n\treturn {\n\t\texec: createDefaultWorktreeSyncExec(),\n\t\tcwd: config.cwd,\n\t\tworktreesBaseDir: settings.worktreesRoot ?? worktreesDir(config.agentDir),\n\t\toptions: {\n\t\t\tmaxLanes: settings.maxLanes,\n\t\t\t...(settings.mainBranch !== undefined ? { mainBranchOverride: settings.mainBranch } : {}),\n\t\t},\n\t\t...(config.sessionId !== undefined ? { sessionId: config.sessionId } : {}),\n\t\t...(config.signal !== undefined ? { signal: config.signal } : {}),\n\t};\n}\n\nexport interface WorktreeSyncRuntimeConfig extends WorktreeSyncEngineConfig {\n\t/** Structural notice injection into the running session (host `sendCustomMessage` seam):\n\t * \"steer\" mid-turn, trigger a turn when idle -- the host closure decides the mechanics. */\n\tnotify: (text: string) => void;\n\t/** Diagnostics sink for startup-reconcile findings (never throws into the session). */\n\tonDiagnostic?: (message: string) => void;\n}\n\nexport interface WorktreeSyncRuntimeHandle {\n\tstop(): void;\n}\n\nconst NOOP_HANDLE: WorktreeSyncRuntimeHandle = { stop: () => {} };\n\n/**\n * Start the per-session worktree-sync runtime (main.ts composition root):\n * 1. one startup reconcile pass (registry vs git reality -- orphans marked, lost lanes\n * re-registered, dead owners cleared, provably-stale lock released), and\n * 2. for a LANE-BOUND session, the epoch watcher: a land anywhere on this machine injects a\n * deterministic staleness notice into this session promptly (the pull-guaranteed channel is\n * still the lane gate + turn-start checks -- enforcement never rides on the watcher).\n *\n * No-op when worktree-sync is disabled. Never throws: this runs at session start and a broken\n * repo state must surface as a diagnostic, not a startup crash.\n */\nexport async function startWorktreeSyncRuntime(config: WorktreeSyncRuntimeConfig): Promise<WorktreeSyncRuntimeHandle> {\n\tconst settings = config.settingsManager.getWorktreeSyncSettings();\n\tif (!settings.enabled) return NOOP_HANDLE;\n\tconst deps = buildWorktreeSyncEngineDeps(config);\n\n\ttry {\n\t\tconst reconciled = await reconcile(deps);\n\t\tif (reconciled.code === \"reconciled\") {\n\t\t\tconst findings: string[] = [];\n\t\t\tif (reconciled.orphanedLaneKeys.length > 0)\n\t\t\t\tfindings.push(`orphaned: ${reconciled.orphanedLaneKeys.join(\", \")}`);\n\t\t\tif (reconciled.reRegisteredLaneKeys.length > 0) {\n\t\t\t\tfindings.push(`re-registered: ${reconciled.reRegisteredLaneKeys.join(\", \")}`);\n\t\t\t}\n\t\t\tif (reconciled.staleLockReleased) findings.push(\"released a stale integration lock\");\n\t\t\tif (findings.length > 0) config.onDiagnostic?.(`worktree-sync reconcile: ${findings.join(\"; \")}`);\n\t\t} else if (reconciled.code !== \"not_a_git_repo\" && reconciled.code !== \"default_branch_unresolved\") {\n\t\t\t// Now that the runtime starts in every session, these two codes are benign absence, not a\n\t\t\t// problem to surface: a non-repo cwd, or a repo whose default branch isn't named main/master.\n\t\t\t// Every other refusal still gets a diagnostic.\n\t\t\tconfig.onDiagnostic?.(`worktree-sync reconcile skipped: [${reconciled.code}] ${reconciled.message}`);\n\t\t}\n\t} catch (error) {\n\t\tconfig.onDiagnostic?.(\n\t\t\t`worktree-sync reconcile failed: ${error instanceof Error ? error.message : String(error)}`,\n\t\t);\n\t}\n\n\tconst laneKey = getBoundWorktreeLaneKey();\n\tif (!laneKey) return NOOP_HANDLE;\n\n\tlet watcher: EpochWatcherHandle | undefined;\n\ttry {\n\t\tconst ctx = await resolveRepoContext(deps);\n\t\tif (!(\"code\" in ctx)) {\n\t\t\twatcher = startEpochWatcher({\n\t\t\t\tepochFile: ctx.paths.epochFile,\n\t\t\t\tlaneKey,\n\t\t\t\tnotify: config.notify,\n\t\t\t});\n\t\t}\n\t} catch (error) {\n\t\tconfig.onDiagnostic?.(`worktree-sync watcher failed: ${error instanceof Error ? error.message : String(error)}`);\n\t}\n\treturn { stop: () => watcher?.stop() };\n}\n"]}