@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,287 @@
1
+ """Token list -> command AST; raises `UnsupportedConstruct` for banned grammar.
2
+
3
+ `parse(tokens) -> CommandList` per windows-shell-workpackages-2026-07-19.md §1.4. Never
4
+ returns a partial/guessed tree: any construct outside the frozen grammar raises
5
+ `UnsupportedConstruct` with the matching catalog id and an actionable message naming the
6
+ construct.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import re
12
+
13
+ from errors import UnsupportedConstruct
14
+ from nodes import (
15
+ AndOr,
16
+ BraceGroup,
17
+ CommandList,
18
+ DQ,
19
+ Lit,
20
+ Pipeline,
21
+ PipelineElement,
22
+ Raw,
23
+ Redirect,
24
+ SimpleCommand,
25
+ Subshell,
26
+ Word,
27
+ )
28
+ from tokens import Token
29
+
30
+ _ASSIGNMENT_RE = re.compile(r"^([A-Za-z_][A-Za-z0-9_]*)=(.*)$", re.DOTALL)
31
+ _EXTGLOB_RE = re.compile(r"[@!?*+]\(")
32
+ _BRACE_EXPANSION_RE = re.compile(r"\{[^{}]*,[^{}]*\}")
33
+
34
+ _JOB_CONTROL_WORDS = {"fg", "bg", "jobs", "wait", "disown"}
35
+ _CONTROL_FLOW_WORDS = {"if", "for", "while", "until", "case", "select"}
36
+ _ARITHMETIC_WORDS = {"let"}
37
+ _UNSUPPORTED_BUILTIN_WORDS = {"eval", "source", ".", "alias", "trap", "set", "shopt", "read", "declare", "local"}
38
+ _NESTED_SHELL_WORDS = {"bash", "sh", "zsh", "fish", "cmd", "powershell", "pwsh", "wsl"}
39
+
40
+
41
+ def _literal_text_from_segments(segments: list) -> str | None:
42
+ parts: list[str] = []
43
+ for seg in segments:
44
+ if isinstance(seg, Lit):
45
+ parts.append(seg.text)
46
+ elif isinstance(seg, Raw):
47
+ parts.append(seg.text)
48
+ elif isinstance(seg, DQ):
49
+ inner = _literal_text_from_segments(seg.segments)
50
+ if inner is None:
51
+ return None
52
+ parts.append(inner)
53
+ else:
54
+ return None
55
+ return "".join(parts)
56
+
57
+
58
+ def _literal_text(word: Word) -> str | None:
59
+ return _literal_text_from_segments(word.segments)
60
+
61
+
62
+ def _check_word_banned_patterns(word: Word) -> None:
63
+ for seg in word.segments:
64
+ if isinstance(seg, Raw):
65
+ if _EXTGLOB_RE.search(seg.text):
66
+ raise UnsupportedConstruct(
67
+ "extended-glob", "Extended glob patterns ('@(...)','!(...)', etc.) are not supported."
68
+ )
69
+ if _BRACE_EXPANSION_RE.search(seg.text):
70
+ raise UnsupportedConstruct(
71
+ "brace-expansion", "Brace expansion ('{a,b,c}') is not supported; list the values explicitly."
72
+ )
73
+
74
+
75
+ def _check_command_word_banned(text: str) -> None:
76
+ if text in _JOB_CONTROL_WORDS:
77
+ raise UnsupportedConstruct("job-control", f"Job control ('{text}') is not supported.")
78
+ if text in _CONTROL_FLOW_WORDS:
79
+ raise UnsupportedConstruct(
80
+ "control-flow", f"Compound control-flow commands ('{text}') are not supported."
81
+ )
82
+ if text in _ARITHMETIC_WORDS:
83
+ raise UnsupportedConstruct("arithmetic-expansion", f"Arithmetic command '{text}' is not supported.")
84
+ if text == "function":
85
+ raise UnsupportedConstruct("function-definition", "Function definitions are not supported.")
86
+ if text == "exec":
87
+ raise UnsupportedConstruct("exec-builtin", "The 'exec' builtin is not supported.")
88
+ if text in _UNSUPPORTED_BUILTIN_WORDS:
89
+ raise UnsupportedConstruct("unsupported-builtin", f"The '{text}' builtin is not supported.")
90
+ if text in _NESTED_SHELL_WORDS:
91
+ raise UnsupportedConstruct(
92
+ "nested-shell", f"Nesting another shell ('{text}') is not supported; run the command directly."
93
+ )
94
+ if text.endswith(".sh") or text.startswith("/bin/"):
95
+ raise UnsupportedConstruct("posix-script", f"Invoking a script/path directly ('{text}') is not supported.")
96
+
97
+
98
+ _REDIRECT_OP_RE = re.compile(r"^(\d*)(.*)$", re.DOTALL)
99
+ _DUP_SUFFIX_RE = re.compile(r"&(\d+)$")
100
+
101
+
102
+ def _is_redirect_op_text(text: str) -> bool:
103
+ return "<" in text or ">" in text
104
+
105
+
106
+ class _Parser:
107
+ def __init__(self, toks: list[Token]) -> None:
108
+ self.toks = toks
109
+ self.i = 0
110
+
111
+ def peek(self) -> Token | None:
112
+ return self.toks[self.i] if self.i < len(self.toks) else None
113
+
114
+ def peek_at(self, offset: int) -> Token | None:
115
+ j = self.i + offset
116
+ return self.toks[j] if j < len(self.toks) else None
117
+
118
+ def advance(self) -> Token:
119
+ tok = self.toks[self.i]
120
+ self.i += 1
121
+ return tok
122
+
123
+ def at_op(self, text: str) -> bool:
124
+ tok = self.peek()
125
+ return tok is not None and tok.kind == "OP" and tok.text == text
126
+
127
+ def _skip_seps(self) -> None:
128
+ while self.at_op(";") or self.at_op("\n"):
129
+ self.advance()
130
+
131
+ def parse_command_list(self, stop_texts: frozenset[str]) -> CommandList:
132
+ entries = []
133
+ separators: list[str] = []
134
+ self._skip_seps()
135
+ while True:
136
+ tok = self.peek()
137
+ if tok is None or (tok.kind == "OP" and tok.text in stop_texts):
138
+ break
139
+ entries.append(self.parse_and_or())
140
+ if self.at_op("&"):
141
+ raise UnsupportedConstruct(
142
+ "job-control", "Background execution ('&') is not supported; run commands synchronously."
143
+ )
144
+ tok = self.peek()
145
+ if tok is None or (tok.kind == "OP" and tok.text in stop_texts):
146
+ break
147
+ if tok.kind == "OP" and tok.text in (";", "\n"):
148
+ separators.append(self.advance().text) # type: ignore[arg-type]
149
+ self._skip_seps()
150
+ continue
151
+ raise UnsupportedConstruct(
152
+ "malformed-syntax", f"Unexpected token in command list: {tok!r}."
153
+ )
154
+ return CommandList(entries=entries, separators=separators)
155
+
156
+ def parse_and_or(self) -> AndOr:
157
+ pipelines = [self.parse_pipeline()]
158
+ operators: list[str] = []
159
+ while self.at_op("&&") or self.at_op("||"):
160
+ operators.append(self.advance().text) # type: ignore[arg-type]
161
+ while self.at_op("\n"):
162
+ self.advance()
163
+ pipelines.append(self.parse_pipeline())
164
+ return AndOr(pipelines=pipelines, operators=operators)
165
+
166
+ def parse_pipeline(self) -> Pipeline:
167
+ negated = False
168
+ tok = self.peek()
169
+ if tok is not None and tok.kind == "WORD" and _literal_text_from_segments(tok.segments or []) == "!":
170
+ negated = True
171
+ self.advance()
172
+ elements: list[PipelineElement] = [self.parse_pipeline_element()]
173
+ while self.at_op("|"):
174
+ self.advance()
175
+ while self.at_op("\n"):
176
+ self.advance()
177
+ elements.append(self.parse_pipeline_element())
178
+ return Pipeline(elements=elements, negated=negated)
179
+
180
+ def parse_pipeline_element(self) -> PipelineElement:
181
+ if self.at_op("("):
182
+ self.advance()
183
+ body = self.parse_command_list(frozenset({")"}))
184
+ if not self.at_op(")"):
185
+ raise UnsupportedConstruct("malformed-syntax", "Unterminated subshell: missing closing ')'.")
186
+ self.advance()
187
+ redirects = self._parse_redirects()
188
+ return Subshell(body=body, redirects=redirects)
189
+ if self.at_op("{"):
190
+ self.advance()
191
+ body = self.parse_command_list(frozenset({"}"}))
192
+ if not self.at_op("}"):
193
+ raise UnsupportedConstruct("malformed-syntax", "Unterminated brace group: missing closing '}'.")
194
+ self.advance()
195
+ redirects = self._parse_redirects()
196
+ return BraceGroup(body=body, redirects=redirects)
197
+ command = self.parse_simple_command()
198
+ if not command.assignments and not command.words and not command.redirects:
199
+ # A fully empty SimpleCommand reached as a pipeline element means a missing
200
+ # command word (e.g. "| foo", "a && ", "a | | b"). Assignment-only (`FOO=1`) and
201
+ # redirect-only (`> file`) commands are valid and never reach here empty.
202
+ raise UnsupportedConstruct(
203
+ "malformed-syntax", "Missing command: a pipeline/list element has no command word."
204
+ )
205
+ return command
206
+
207
+ def _parse_redirects(self) -> list[Redirect]:
208
+ redirects: list[Redirect] = []
209
+ while True:
210
+ tok = self.peek()
211
+ if tok is not None and tok.kind == "OP" and tok.text is not None and _is_redirect_op_text(tok.text):
212
+ redirects.append(self._parse_one_redirect())
213
+ continue
214
+ break
215
+ return redirects
216
+
217
+ def _parse_one_redirect(self) -> Redirect:
218
+ tok = self.advance()
219
+ text = tok.text or ""
220
+ m = _REDIRECT_OP_RE.match(text)
221
+ assert m is not None
222
+ fd_text, _core = m.group(1), m.group(2)
223
+ fd = int(fd_text) if fd_text else None
224
+ dup_match = _DUP_SUFFIX_RE.search(text)
225
+ dup_fd = int(dup_match.group(1)) if dup_match else None
226
+ target: Word | None = None
227
+ if dup_fd is None:
228
+ target_tok = self.peek()
229
+ if target_tok is None or target_tok.kind != "WORD":
230
+ raise UnsupportedConstruct("malformed-syntax", f"Redirect '{text}' is missing its target.")
231
+ self.advance()
232
+ target = Word(segments=target_tok.segments or [])
233
+ return Redirect(op=text, fd=fd, target=target, dup_fd=dup_fd)
234
+
235
+ def parse_simple_command(self) -> SimpleCommand:
236
+ assignments: list[tuple[str, Word]] = []
237
+ words: list[Word] = []
238
+ redirects: list[Redirect] = []
239
+ while True:
240
+ tok = self.peek()
241
+ if tok is None:
242
+ break
243
+ if tok.kind == "OP":
244
+ if tok.text is not None and _is_redirect_op_text(tok.text):
245
+ redirects.append(self._parse_one_redirect())
246
+ continue
247
+ break
248
+ word = Word(segments=tok.segments or [])
249
+ if not words:
250
+ lead = word.segments[0] if word.segments else None
251
+ if isinstance(lead, Raw):
252
+ m = _ASSIGNMENT_RE.match(lead.text)
253
+ if m:
254
+ self.advance()
255
+ name, rest = m.group(1), m.group(2)
256
+ value_segments = ([Raw(text=rest)] if rest else []) + list(word.segments[1:])
257
+ assignments.append((name, Word(segments=value_segments)))
258
+ continue
259
+ _check_word_banned_patterns(word)
260
+ if not words:
261
+ nxt1 = self.peek_at(1)
262
+ nxt2 = self.peek_at(2)
263
+ if (
264
+ nxt1 is not None
265
+ and nxt1.kind == "OP"
266
+ and nxt1.text == "("
267
+ and nxt2 is not None
268
+ and nxt2.kind == "OP"
269
+ and nxt2.text == ")"
270
+ ):
271
+ raise UnsupportedConstruct("function-definition", "Function definitions are not supported.")
272
+ literal = _literal_text(word)
273
+ if literal is not None:
274
+ _check_command_word_banned(literal)
275
+ words.append(word)
276
+ self.advance()
277
+ return SimpleCommand(assignments=assignments, words=words, redirects=redirects)
278
+
279
+
280
+ def parse(tokens: list[Token]) -> CommandList:
281
+ parser = _Parser(tokens)
282
+ result = parser.parse_command_list(frozenset())
283
+ if parser.peek() is not None:
284
+ raise UnsupportedConstruct(
285
+ "malformed-syntax", f"Unexpected trailing token: {parser.peek()!r}."
286
+ )
287
+ return result
@@ -0,0 +1,137 @@
1
+ """External-command spawn: PATHEXT-aware resolution, pipe wiring, deadline-safe kill.
2
+
3
+ Owned by WP-C. Pure stdlib. See windows-shell-workpackages-2026-07-19.md §3 (WP-C spec).
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ import os
9
+ import signal
10
+ import subprocess
11
+ import time
12
+ from typing import BinaryIO
13
+
14
+ from state import ShellState
15
+
16
+ TIMEOUT_EXIT_CODE = 124
17
+
18
+
19
+ def resolve_external(name: str, env: dict[str, str], cwd: str | None = None) -> str | None:
20
+ """Resolve `name` to an absolute path over `env["PATH"]`, honoring PATHEXT on win32.
21
+
22
+ Direct `.exe` (or extension-less on POSIX) targets resolve as-is; `.bat`/`.cmd`
23
+ targets are still resolved to a path (the caller wraps them via `cmd /c`).
24
+
25
+ Thread-safe: pipeline stages may resolve concurrently on threads, so this never
26
+ reads or mutates `os.environ` (which `shutil.which` does internally for PATH).
27
+ Manual resolution only, entirely off the request env passed in.
28
+ """
29
+ path_value = env.get("PATH", "")
30
+ if os.path.isabs(name) or os.sep in name or (os.altsep and os.altsep in name):
31
+ candidate = name if os.path.isabs(name) else os.path.join(cwd or os.getcwd(), name)
32
+ if os.path.isfile(candidate):
33
+ return os.path.abspath(candidate)
34
+ return None
35
+
36
+ path_dirs = [d for d in path_value.split(os.pathsep) if d]
37
+
38
+ if os.name == "nt":
39
+ pathext = env.get("PATHEXT") or ".COM;.EXE;.BAT;.CMD"
40
+ exts = [e for e in pathext.split(os.pathsep) if e]
41
+ has_ext = any(name.lower().endswith(ext.lower()) for ext in exts)
42
+ candidates = [name] if has_ext else [name + ext for ext in exts] + [name]
43
+ for directory in path_dirs:
44
+ for candidate in candidates:
45
+ full = os.path.join(directory, candidate)
46
+ if os.path.isfile(full):
47
+ return full
48
+ return None
49
+
50
+ for directory in path_dirs:
51
+ base_dir = directory if os.path.isabs(directory) else os.path.join(cwd or os.getcwd(), directory)
52
+ full = os.path.join(base_dir, name)
53
+ if os.path.isfile(full) and os.access(full, os.X_OK):
54
+ return full
55
+ return None
56
+
57
+
58
+ def build_argv(resolved_path: str, argv: list[str]) -> list[str]:
59
+ """Wrap `.bat`/`.cmd` targets via `cmd /c`; direct-exec everything else."""
60
+ lower = resolved_path.lower()
61
+ if lower.endswith(".bat") or lower.endswith(".cmd"):
62
+ return ["cmd", "/c", resolved_path, *argv[1:]]
63
+ return [resolved_path, *argv[1:]]
64
+
65
+
66
+ def spawn_external(
67
+ argv: list[str],
68
+ state: ShellState,
69
+ stdin: BinaryIO | int,
70
+ stdout: BinaryIO | int,
71
+ stderr: BinaryIO | int,
72
+ deadline: float | None,
73
+ ) -> "subprocess.Popen[bytes]":
74
+ """Resolve argv[0] and spawn it (no shell) with the given cwd/env/streams.
75
+
76
+ Raises FileNotFoundError if argv[0] does not resolve.
77
+ """
78
+ resolved = resolve_external(argv[0], state.env, state.cwd)
79
+ if resolved is None:
80
+ raise FileNotFoundError(argv[0])
81
+ full_argv = build_argv(resolved, argv)
82
+ kwargs: dict = {}
83
+ if os.name != "nt":
84
+ kwargs["start_new_session"] = True
85
+ else:
86
+ kwargs["creationflags"] = getattr(subprocess, "CREATE_NEW_PROCESS_GROUP", 0)
87
+ return subprocess.Popen(
88
+ full_argv,
89
+ cwd=state.cwd,
90
+ env=dict(state.env),
91
+ stdin=stdin,
92
+ stdout=stdout,
93
+ stderr=stderr,
94
+ **kwargs,
95
+ )
96
+
97
+
98
+ def kill_process_tree(proc: "subprocess.Popen[bytes]") -> None:
99
+ """Best-effort kill of `proc` and its children."""
100
+ if os.name == "nt":
101
+ subprocess.run(
102
+ ["taskkill", "/F", "/T", "/PID", str(proc.pid)],
103
+ stdout=subprocess.DEVNULL,
104
+ stderr=subprocess.DEVNULL,
105
+ check=False,
106
+ )
107
+ else:
108
+ try:
109
+ pgid = os.getpgid(proc.pid)
110
+ os.killpg(pgid, signal.SIGKILL)
111
+ except (ProcessLookupError, PermissionError, OSError):
112
+ try:
113
+ proc.kill()
114
+ except (ProcessLookupError, OSError):
115
+ pass
116
+ try:
117
+ proc.wait(timeout=5)
118
+ except Exception:
119
+ pass
120
+
121
+
122
+ def wait_with_deadline(proc: "subprocess.Popen[bytes]", deadline: float | None) -> int:
123
+ """Wait for `proc`; if `deadline` (a `time.monotonic()` budget) elapses first, kill it.
124
+
125
+ Returns the process exit code, or 124 on deadline breach.
126
+ """
127
+ if deadline is None:
128
+ return proc.wait()
129
+ remaining = deadline - time.monotonic()
130
+ if remaining <= 0:
131
+ kill_process_tree(proc)
132
+ return TIMEOUT_EXIT_CODE
133
+ try:
134
+ return proc.wait(timeout=remaining)
135
+ except subprocess.TimeoutExpired:
136
+ kill_process_tree(proc)
137
+ return TIMEOUT_EXIT_CODE
@@ -0,0 +1,100 @@
1
+ """Shell state: current working directory + environment, and delta computation.
2
+
3
+ Owned by WP-C. Pure stdlib. See windows-shell-workpackages-2026-07-19.md §3 (WP-C spec).
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ import os
9
+ from dataclasses import dataclass, field
10
+
11
+
12
+ class ShellEnvironment(dict[str, str]):
13
+ """Windows-compatible environment mapping while preserving the first key spelling."""
14
+
15
+ def _existing_key(self, key: object) -> str | None:
16
+ if not isinstance(key, str) or os.name != "nt":
17
+ return key if isinstance(key, str) and dict.__contains__(self, key) else None
18
+ folded = key.casefold()
19
+ return next((candidate for candidate in dict.keys(self) if candidate.casefold() == folded), None)
20
+
21
+ def __contains__(self, key: object) -> bool:
22
+ return self._existing_key(key) is not None
23
+
24
+ def __getitem__(self, key: str) -> str:
25
+ existing = self._existing_key(key)
26
+ if existing is None:
27
+ raise KeyError(key)
28
+ return dict.__getitem__(self, existing)
29
+
30
+ def get(self, key: str, default: str | None = None) -> str | None:
31
+ existing = self._existing_key(key)
32
+ return dict.get(self, existing, default) if existing is not None else default
33
+
34
+ def __setitem__(self, key: str, value: str) -> None:
35
+ existing = self._existing_key(key)
36
+ dict.__setitem__(self, existing or key, value)
37
+
38
+ def __delitem__(self, key: str) -> None:
39
+ existing = self._existing_key(key)
40
+ if existing is None:
41
+ raise KeyError(key)
42
+ dict.__delitem__(self, existing)
43
+
44
+ def pop(self, key: str, default=None):
45
+ existing = self._existing_key(key)
46
+ if existing is None:
47
+ return default
48
+ return dict.pop(self, existing)
49
+
50
+ def setdefault(self, key: str, default: str = "") -> str:
51
+ existing = self._existing_key(key)
52
+ if existing is not None:
53
+ return dict.__getitem__(self, existing)
54
+ dict.__setitem__(self, key, default)
55
+ return default
56
+
57
+ def copy(self) -> "ShellEnvironment":
58
+ return ShellEnvironment(self)
59
+
60
+
61
+ @dataclass
62
+ class ShellState:
63
+ """Mutable cwd + env carried through a single engine run."""
64
+
65
+ cwd: str
66
+ env: ShellEnvironment = field(default_factory=ShellEnvironment)
67
+
68
+ def __post_init__(self) -> None:
69
+ if not isinstance(self.env, ShellEnvironment):
70
+ self.env = ShellEnvironment(self.env)
71
+
72
+ def copy(self) -> "ShellState":
73
+ """Return an independent copy (used for subshell isolation)."""
74
+ return ShellState(cwd=self.cwd, env=self.env.copy())
75
+
76
+ def chdir(self, path: str) -> None:
77
+ """Validate `path` exists and is a directory, then update cwd + OLDPWD."""
78
+ target = path if os.path.isabs(path) else os.path.join(self.cwd, path)
79
+ target = os.path.normpath(target)
80
+ if not os.path.isdir(target):
81
+ raise FileNotFoundError(target)
82
+ self.env["OLDPWD"] = self.cwd
83
+ self.cwd = target
84
+
85
+ def setenv(self, name: str, value: str) -> None:
86
+ self.env[name] = value
87
+
88
+ def unsetenv(self, name: str) -> None:
89
+ self.env.pop(name, None)
90
+
91
+ def delta(self, original_env: dict[str, str]) -> dict[str, str | None]:
92
+ """Compute envDelta vs `original_env`: changed/added -> value, removed -> None."""
93
+ result: dict[str, str | None] = {}
94
+ for key, value in self.env.items():
95
+ if key not in original_env or original_env[key] != value:
96
+ result[key] = value
97
+ for key in original_env:
98
+ if key not in self.env:
99
+ result[key] = None
100
+ return result