gentle-pi 4.0.0 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (425) hide show
  1. package/README.md +157 -18
  2. package/assets/agents/gentle-ai-explore.md +11 -4
  3. package/assets/agents/gentle-ai-verify.md +23 -4
  4. package/assets/agents/gentle-ai-worker.md +6 -6
  5. package/assets/install-wizard/index.html +47 -0
  6. package/assets/install-wizard/wizard.css +1279 -0
  7. package/assets/install-wizard/wizard.js +951 -0
  8. package/assets/orchestrator-delegation.md +70 -163
  9. package/assets/orchestrator-memory.md +11 -4
  10. package/assets/orchestrator-prompts.md +48 -0
  11. package/assets/orchestrator-tracking.md +53 -0
  12. package/assets/orchestrator-verification.md +28 -0
  13. package/assets/orchestrator-writer.md +38 -0
  14. package/assets/orchestrator.md +29 -25
  15. package/assets/sounds/LICENSE.md +52 -0
  16. package/assets/sounds/attention.wav +0 -0
  17. package/assets/sounds/error.wav +0 -0
  18. package/assets/sounds/success.wav +0 -0
  19. package/bin/engram-guard +9 -0
  20. package/bin/gentle-shell-install.mjs +302 -0
  21. package/bin/gentle-shell.mjs +708 -22
  22. package/contracts/review-provider-contract-mirror/provider-contract.lock.json +7 -7
  23. package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/bundle/manifest.json +2 -2
  24. package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/bundle/orchestration/pi.md +16 -4
  25. package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/generated/provider-capabilities.baseline.json +2 -2
  26. package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/generated/provider-roles.baseline.json +1 -1
  27. package/docs/auto-permission-answers.md +25 -0
  28. package/docs/auto-permission-evidence.md +39 -0
  29. package/docs/bundled-install.md +399 -0
  30. package/docs/delegated-verification.md +3 -5
  31. package/docs/gentle-agents-activity.md +513 -0
  32. package/docs/gentle-shell-uninstall.md +136 -0
  33. package/docs/gentle-shell.md +90 -33
  34. package/docs/install-wizard.md +2040 -0
  35. package/docs/native-authority-architecture.md +1 -1
  36. package/docs/permission-modes.md +127 -0
  37. package/docs/prompt-history.md +1 -1
  38. package/docs/readme-reference.md +310 -47
  39. package/docs/render-cache-performance.md +28 -0
  40. package/docs/session-profile-format.md +39 -0
  41. package/docs/sound-notifications-proposal.md +191 -0
  42. package/docs/sound-notifications.md +114 -0
  43. package/docs/yolo-mode.md +11 -10
  44. package/extensions/ask-user-choice.ts +4 -0
  45. package/extensions/ask-user-question.ts +6 -1
  46. package/extensions/child-context.ts +11 -2
  47. package/extensions/child-safety.ts +4 -2
  48. package/extensions/codegraph-tools.ts +18 -5
  49. package/extensions/gentle-agents.ts +718 -87
  50. package/extensions/gentle-ai.ts +991 -263
  51. package/extensions/gentle-herdr-activity.ts +81 -0
  52. package/extensions/gentle-notifications.ts +104 -0
  53. package/extensions/gentle-shell.ts +271 -80
  54. package/extensions/gentle-todo.ts +123 -18
  55. package/extensions/history/index.ts +11 -6
  56. package/extensions/pi-pretty.ts +39 -3
  57. package/extensions/quiet-tools.ts +91 -21
  58. package/extensions/skill-registry.ts +175 -46
  59. package/extensions/startup-banner.ts +11 -2
  60. package/lib/agent-home.ts +10 -1
  61. package/lib/agent-model-resolution.ts +80 -0
  62. package/lib/agent-profiles.ts +13 -3
  63. package/lib/agents-completion-delivery.ts +11 -3
  64. package/lib/agents-messaging.ts +1 -1
  65. package/lib/agents-protocol.ts +40 -1
  66. package/lib/agents-runner.ts +90 -15
  67. package/lib/auto-permission-answers.ts +133 -0
  68. package/lib/auto-permission-classifier.ts +459 -0
  69. package/lib/auto-permission-evidence.ts +88 -0
  70. package/lib/auto-permission-memory.ts +69 -0
  71. package/lib/auto-permission-runtime.ts +484 -0
  72. package/lib/auto-permission-tool-context.ts +61 -0
  73. package/lib/background-jobs-tools.ts +202 -0
  74. package/lib/background-jobs.ts +253 -0
  75. package/lib/background-monitor.ts +154 -0
  76. package/lib/bounded-writer-admission.ts +83 -10
  77. package/lib/builtin-codemode-optout.ts +166 -0
  78. package/lib/card-content-policy.ts +85 -0
  79. package/lib/child-package-injection.ts +62 -0
  80. package/lib/codemode-renderer.ts +14 -4
  81. package/lib/command-palette-catalog.ts +3 -2
  82. package/lib/context-threshold.ts +26 -0
  83. package/lib/destructive-command-guard.ts +104 -28
  84. package/lib/gentle-ai-binary.ts +109 -4
  85. package/lib/gentle-shell-bundled.ts +535 -0
  86. package/lib/gentle-shell-launcher.ts +75 -24
  87. package/lib/gentle-shell-startup-flow.ts +54 -0
  88. package/lib/gentle-shell-startup-update.ts +92 -0
  89. package/lib/gentle-shell-uninstall.ts +840 -0
  90. package/lib/gentle-shell-update-panel.ts +231 -0
  91. package/lib/herdr-activity.ts +183 -0
  92. package/lib/inprocess-reviewer.ts +3 -0
  93. package/lib/jobs-sidebar-state.ts +20 -0
  94. package/lib/jobs-view.ts +161 -0
  95. package/lib/model-price-ratio.ts +83 -0
  96. package/lib/model-routing-authority.ts +6 -1
  97. package/lib/nan-provider.ts +33 -11
  98. package/lib/native-review-cli.ts +194 -73
  99. package/lib/notification-audio-native.ts +162 -0
  100. package/lib/notification-audio-windows.ts +399 -0
  101. package/lib/notification-audio.ts +332 -0
  102. package/lib/notification-customize.ts +241 -0
  103. package/lib/notification-events.ts +113 -0
  104. package/lib/notification-policy.ts +148 -0
  105. package/lib/notification-pulse-client.ts +367 -0
  106. package/lib/notification-pulse-protocol.ts +305 -0
  107. package/lib/notification-pulse-stream.ts +213 -0
  108. package/lib/notification-pulse-worker.ts +66 -0
  109. package/lib/notification-scheduler.ts +173 -0
  110. package/lib/notification-service.ts +202 -0
  111. package/lib/notification-ui.ts +87 -0
  112. package/lib/odd-phase.ts +1 -1
  113. package/lib/orchestrator-alias.ts +20 -0
  114. package/lib/orchestrator-catalog.ts +79 -0
  115. package/lib/orchestrator-consultation.ts +61 -0
  116. package/lib/orchestrator-discovery.ts +49 -0
  117. package/lib/orchestrator-helper-consent.ts +122 -0
  118. package/lib/orchestrator-helper.ts +167 -0
  119. package/lib/orchestrator-message-card.ts +105 -0
  120. package/lib/orchestrator-presence.ts +115 -14
  121. package/lib/orchestrator-scope.ts +80 -0
  122. package/lib/orchestrator-state.ts +107 -0
  123. package/lib/orchestrator-tool-card.ts +280 -0
  124. package/lib/orchestrator-work-search.ts +218 -0
  125. package/lib/orchestrator-work.ts +79 -0
  126. package/lib/permission-mode-policy.ts +59 -0
  127. package/lib/review-candidate-view-owner.ts +8 -6
  128. package/lib/review-candidate-view.ts +3 -2
  129. package/lib/review-compact-contract.ts +2 -2
  130. package/lib/review-host-relay.ts +7 -2
  131. package/lib/review-integration-v2.ts +100 -22
  132. package/lib/review-publication-gate.ts +1 -1
  133. package/lib/review-risk-assessment.ts +77 -51
  134. package/lib/review-sidebar-state.ts +2 -1
  135. package/lib/review-transaction.ts +72 -3
  136. package/lib/runtime-metrics-children.ts +1 -1
  137. package/lib/runtime-metrics-native.ts +3 -2
  138. package/lib/selection-engine.ts +22 -7
  139. package/lib/session-change-capture.ts +5 -4
  140. package/lib/session-changes.ts +27 -22
  141. package/lib/session-profile-binding.ts +83 -0
  142. package/lib/session-profile-freeze.ts +261 -0
  143. package/lib/session-profile-persistence.ts +187 -0
  144. package/lib/session-worktree-registry.ts +74 -8
  145. package/lib/shell-bar.ts +41 -11
  146. package/lib/shell-changes-view.ts +40 -13
  147. package/lib/shell-changes.ts +88 -71
  148. package/lib/shell-prompt.ts +6 -4
  149. package/lib/shell-sidebar-layout.ts +5 -1
  150. package/lib/shell-todo.ts +81 -26
  151. package/lib/shell-usage.ts +4 -3
  152. package/lib/status-timing-diagnostics.ts +201 -0
  153. package/lib/telemetry-trigger.ts +3 -1
  154. package/lib/vim-editor-adapter.ts +27 -5
  155. package/lib/visual-customization-policy.ts +20 -9
  156. package/lib/visual-customize-view.ts +171 -20
  157. package/lib/writer-surfaces.ts +162 -0
  158. package/lib/yolo-session-policy.ts +198 -121
  159. package/package.json +5 -5
  160. package/runtime/child-package-injection.mjs +63 -0
  161. package/runtime/gentle-ai-binary.mjs +109 -4
  162. package/runtime/gentle-shell-bundled.mjs +536 -0
  163. package/runtime/gentle-shell-launcher.mjs +74 -23
  164. package/runtime/gentle-shell-startup-flow.mjs +55 -0
  165. package/runtime/gentle-shell-startup-update.mjs +93 -0
  166. package/runtime/gentle-shell-uninstall.mjs +841 -0
  167. package/runtime/gentle-shell-update-panel.mjs +232 -0
  168. package/runtime/native-review-cli.mjs +191 -70
  169. package/runtime/review-integration-v2.mjs +100 -22
  170. package/runtime/review-risk-assessment.mjs +77 -51
  171. package/runtime/status-timing-diagnostics.mjs +202 -0
  172. package/runtime/telemetry-trigger.mjs +3 -1
  173. package/scripts/bootstrap.cmd +255 -0
  174. package/scripts/bootstrap.sh +168 -0
  175. package/scripts/build-distribution.mjs +157 -0
  176. package/scripts/build-installer-bundles.mjs +136 -0
  177. package/scripts/build-runtime-modules.mjs +7 -0
  178. package/scripts/bundled-install.mjs +1308 -0
  179. package/scripts/bundled-wizard.mjs +399 -0
  180. package/scripts/check-types.mjs +4 -6
  181. package/scripts/gentle-ai-installer.mjs +79 -32
  182. package/scripts/install-gentle-ai.mjs +48 -1
  183. package/scripts/install-tui-mode-setting.mjs +10 -1
  184. package/scripts/install-wizard-preview.mjs +154 -0
  185. package/scripts/installer-downloads.mjs +648 -0
  186. package/scripts/installer-preflight.mjs +387 -0
  187. package/scripts/installer-probes.mjs +564 -0
  188. package/scripts/installer-runner.mjs +1102 -0
  189. package/scripts/installer-server.mjs +881 -0
  190. package/scripts/installer-windows-artifacts.json +15 -0
  191. package/scripts/installer-windows.mjs +752 -0
  192. package/scripts/main-channel.mjs +452 -0
  193. package/scripts/npm-pack-result.mjs +31 -0
  194. package/scripts/pi-update.mjs +223 -0
  195. package/scripts/render-cache-performance-worker.mjs +205 -0
  196. package/scripts/render-cache-performance.mjs +115 -0
  197. package/scripts/run-test-suite.mjs +22 -8
  198. package/scripts/test-installer-acceptance.sh +161 -0
  199. package/scripts/test-packed-runner.mjs +23 -5
  200. package/scripts/types-baseline.json +2 -92
  201. package/scripts/verify-package-files.mjs +82 -18
  202. package/skills/gentle-ai/SKILL.md +12 -11
  203. package/tests/agent-home.test.ts +56 -3
  204. package/tests/agent-model-resolution.test.ts +113 -0
  205. package/tests/agent-profiles.test.ts +12 -0
  206. package/tests/agent-risk-escalation.test.ts +123 -0
  207. package/tests/agents-completion-delivery.test.ts +17 -0
  208. package/tests/agents-protocol.test.ts +57 -0
  209. package/tests/agents-queries.test.ts +9 -9
  210. package/tests/agents-runner-process.test.ts +31 -0
  211. package/tests/agents-runner.test.ts +89 -4
  212. package/tests/append-system-prompt-route.test.ts +18 -1
  213. package/tests/auto-mode-human-answers.test.ts +68 -0
  214. package/tests/auto-mode-invariants.test.ts +276 -0
  215. package/tests/auto-mode-sdk.test.ts +84 -0
  216. package/tests/auto-mode.test.ts +49 -0
  217. package/tests/auto-permission-answers.test.ts +170 -0
  218. package/tests/auto-permission-classifier.test.ts +634 -0
  219. package/tests/auto-permission-compound.test.ts +24 -0
  220. package/tests/auto-permission-evidence.test.ts +88 -0
  221. package/tests/auto-permission-memory.test.ts +46 -0
  222. package/tests/auto-permission-public-regressions.test.ts +111 -0
  223. package/tests/auto-permission-runtime.test.ts +454 -0
  224. package/tests/autonomous-guard.test.ts +86 -16
  225. package/tests/background-cache-warming.test.ts +2 -1
  226. package/tests/background-jobs.test.ts +227 -0
  227. package/tests/background-monitor.test.ts +195 -0
  228. package/tests/background-subagents-default-mode.test.ts +28 -5
  229. package/tests/bounded-stop-contract.test.ts +85 -0
  230. package/tests/bounded-writer-admission.test.ts +52 -1
  231. package/tests/bridge-wake-lifecycle.test.ts +129 -0
  232. package/tests/bridge-wake-rendering.test.ts +56 -0
  233. package/tests/build-distribution.test.ts +269 -0
  234. package/tests/builtin-codemode-optout.test.ts +242 -0
  235. package/tests/bundled-install.test.ts +1319 -0
  236. package/tests/bundled-wizard.test.ts +505 -0
  237. package/tests/card-content-policy.test.ts +68 -0
  238. package/tests/card-style-policy.test.ts +34 -2
  239. package/tests/child-codegraph-bootstrap.test.ts +74 -0
  240. package/tests/child-package-entrypoints.test.ts +65 -0
  241. package/tests/child-package-injection.test.ts +74 -0
  242. package/tests/child-safety.test.ts +12 -0
  243. package/tests/child-web-package.test.ts +224 -0
  244. package/tests/codegraph-tools.test.ts +35 -0
  245. package/tests/codemode-rendering.test.ts +107 -2
  246. package/tests/command-palette.test.ts +5 -5
  247. package/tests/context-threshold.test.ts +31 -0
  248. package/tests/delegate-for-reason-contract.test.ts +327 -0
  249. package/tests/delegated-key-learnings-contract.test.ts +3 -2
  250. package/tests/devbinary/native-review-parity.devtest.ts +1 -1
  251. package/tests/devbinary/pi-host-relay.devtest.ts +173 -3
  252. package/tests/engram-safety.test.ts +316 -0
  253. package/tests/generic-agent-tools.test.ts +16 -1
  254. package/tests/gentle-agents.test.ts +1895 -76
  255. package/tests/gentle-ai-binary-isolation.test.ts +135 -0
  256. package/tests/gentle-ai-binary.test.ts +19 -2
  257. package/tests/gentle-ai-child-guards.test.ts +202 -0
  258. package/tests/gentle-ai-dev-binary-surfacing.test.ts +125 -15
  259. package/tests/gentle-ai-installer.test.ts +548 -58
  260. package/tests/gentle-ai-prompt-model-routing.test.ts +123 -0
  261. package/tests/gentle-ai-renderer.test.ts +6 -6
  262. package/tests/gentle-ai.test.ts +999 -31
  263. package/tests/gentle-herdr-activity.test.ts +100 -0
  264. package/tests/gentle-notifications.test.ts +427 -0
  265. package/tests/gentle-shell-bin.test.ts +263 -19
  266. package/tests/gentle-shell-bundled.test.ts +1036 -0
  267. package/tests/gentle-shell-launcher.test.ts +251 -25
  268. package/tests/gentle-shell-startup-flow.test.ts +75 -0
  269. package/tests/gentle-shell-startup-update.test.ts +85 -0
  270. package/tests/gentle-shell-uninstall.test.ts +978 -0
  271. package/tests/gentle-shell-update-panel.test.ts +158 -0
  272. package/tests/gentle-shell.test.ts +611 -100
  273. package/tests/gentle-todo.test.ts +317 -14
  274. package/tests/herdr-activity.test.ts +243 -0
  275. package/tests/history-agent-home.test.ts +81 -0
  276. package/tests/history-child-guard.test.ts +70 -0
  277. package/tests/inprocess-reviewer.test.ts +20 -0
  278. package/tests/install-gentle-ai-failure.test.ts +69 -0
  279. package/tests/install-tui-mode-setting.test.ts +15 -0
  280. package/tests/install-wizard.test.ts +1223 -0
  281. package/tests/installer-bundles.test.ts +122 -0
  282. package/tests/installer-posix-bootstrap.test.ts +1201 -0
  283. package/tests/installer-preflight.test.ts +750 -0
  284. package/tests/installer-probes.test.ts +1106 -0
  285. package/tests/installer-runner.test.ts +2159 -0
  286. package/tests/installer-server.test.ts +1567 -0
  287. package/tests/installer-windows-bootstrap.test.ts +2410 -0
  288. package/tests/jobs-view.test.ts +160 -0
  289. package/tests/main-channel-upgrade.test.ts +395 -0
  290. package/tests/main-channel.test.ts +344 -0
  291. package/tests/maintainer/provider-relay.maintest.ts +13 -12
  292. package/tests/model-price-ratio.test.ts +116 -0
  293. package/tests/model-profiles-preservation.test.ts +153 -0
  294. package/tests/model-routing-package.test.ts +10 -0
  295. package/tests/nan-provider-runtime.test.ts +156 -0
  296. package/tests/nan-provider.test.ts +28 -18
  297. package/tests/native-binary-gate.test.ts +2 -0
  298. package/tests/native-review-capability-contract.test.ts +7 -1
  299. package/tests/native-review-cli.test.ts +236 -1
  300. package/tests/native-review-consent.test.ts +2 -2
  301. package/tests/native-review-parity-runtime.test.ts +1 -1
  302. package/tests/native-review-parity.test.ts +12 -48
  303. package/tests/native-risk-evidence-parity.test.ts +21 -0
  304. package/tests/no-self-pause-contract.test.ts +87 -0
  305. package/tests/notification-audio-native.test.ts +281 -0
  306. package/tests/notification-audio-windows.test.ts +581 -0
  307. package/tests/notification-audio.test.ts +548 -0
  308. package/tests/notification-customize.test.ts +655 -0
  309. package/tests/notification-events.test.ts +115 -0
  310. package/tests/notification-policy.test.ts +201 -0
  311. package/tests/notification-pulse-client.test.ts +356 -0
  312. package/tests/notification-pulse-protocol.test.ts +213 -0
  313. package/tests/notification-pulse-stream.test.ts +320 -0
  314. package/tests/notification-scheduler.test.ts +258 -0
  315. package/tests/notification-ui.test.ts +157 -0
  316. package/tests/npm-pack-result.test.ts +41 -0
  317. package/tests/odd-integration.test.ts +14 -5
  318. package/tests/odd-routing-canonical-ratchet.test.ts +53 -12
  319. package/tests/odd-routing-contract.test.ts +80 -23
  320. package/tests/odd-runtime-delegation-gate.test.ts +4 -1
  321. package/tests/orchestrator-budget.test.ts +29 -6
  322. package/tests/orchestrator-catalog.test.ts +146 -0
  323. package/tests/orchestrator-consultation-sdk.test.ts +614 -0
  324. package/tests/orchestrator-consultation.test.ts +111 -0
  325. package/tests/orchestrator-discovery.test.ts +241 -0
  326. package/tests/orchestrator-helper-consent.test.ts +171 -0
  327. package/tests/orchestrator-helper.test.ts +297 -0
  328. package/tests/orchestrator-message-card.test.ts +190 -0
  329. package/tests/orchestrator-presence.test.ts +23 -0
  330. package/tests/orchestrator-rdd-ownership.test.ts +6 -5
  331. package/tests/orchestrator-scope.test.ts +107 -0
  332. package/tests/orchestrator-state.test.ts +114 -0
  333. package/tests/orchestrator-status-publication-contract.test.ts +34 -0
  334. package/tests/orchestrator-tool-card.test.ts +398 -0
  335. package/tests/orchestrator-work-search.test.ts +318 -0
  336. package/tests/orchestrator-work.test.ts +147 -0
  337. package/tests/package-manifest.test.ts +105 -21
  338. package/tests/packed-runner-owned-path.test.ts +35 -1
  339. package/tests/parallel-reason-contract.test.ts +21 -0
  340. package/tests/parallel-writer-admission.test.ts +210 -0
  341. package/tests/permission-mode-policy.test.ts +194 -0
  342. package/tests/persona-single-channel.test.ts +4 -12
  343. package/tests/pi-pretty.test.ts +56 -0
  344. package/tests/pi-update-launcher.test.ts +87 -0
  345. package/tests/pi-update.test.ts +186 -0
  346. package/tests/provider-defect-handoff.test.ts +4 -3
  347. package/tests/quiet-tool-rendering.test.ts +160 -3
  348. package/tests/rdd-aware-verification-contract.test.ts +29 -41
  349. package/tests/rdd-status-line.test.ts +52 -0
  350. package/tests/render-cache-performance.test.ts +48 -0
  351. package/tests/review-agent-end-preflight.test.ts +62 -10
  352. package/tests/review-candidate-view.test.ts +101 -12
  353. package/tests/review-contract-prompt.test.ts +33 -4
  354. package/tests/review-controller-native-recovery.test.ts +327 -17
  355. package/tests/review-controller-native-routing.test.ts +255 -1
  356. package/tests/review-controller-workspace-root.test.ts +43 -2
  357. package/tests/review-controller.test.ts +2 -2
  358. package/tests/review-correction-lifecycle.test.ts +2 -1
  359. package/tests/review-gate.test.ts +7 -4
  360. package/tests/review-graph-schema.test.ts +2 -2
  361. package/tests/review-host-relay-routing.test.ts +5 -3
  362. package/tests/review-host-relay.test.ts +49 -2
  363. package/tests/review-integration-v2-forward.test.ts +21 -1
  364. package/tests/review-json-arguments.test.ts +167 -0
  365. package/tests/review-last-event-closure.test.ts +157 -8
  366. package/tests/review-ledger-contract.test.ts +5 -4
  367. package/tests/review-policy-judgment-day.test.ts +1 -1
  368. package/tests/review-policy-ordinary.test.ts +2 -2
  369. package/tests/review-relay-transport-agent.test.ts +66 -1
  370. package/tests/review-risk-assessment.test.ts +109 -33
  371. package/tests/review-session-standing-permission-controller.test.ts +16 -17
  372. package/tests/review-session-standing-permission-ipc.test.ts +6 -5
  373. package/tests/review-test-fixtures.ts +7 -1
  374. package/tests/review-transaction.test.ts +18 -1
  375. package/tests/run-test-suite.test.ts +83 -5
  376. package/tests/runtime-harness.mjs +42 -15
  377. package/tests/runtime-metrics-extension.test.ts +1 -1
  378. package/tests/runtime-metrics-native.test.ts +31 -1
  379. package/tests/selection-engine.test.ts +65 -5
  380. package/tests/session-change-capture.test.ts +10 -10
  381. package/tests/session-changes-shell.test.ts +242 -48
  382. package/tests/session-changes.test.ts +17 -24
  383. package/tests/session-profile-binding.test.ts +163 -0
  384. package/tests/session-profile-freeze.test.ts +394 -0
  385. package/tests/session-profile-persistence.test.ts +334 -0
  386. package/tests/session-subject-routing-contract.test.ts +34 -0
  387. package/tests/session-worktree-registry.test.ts +57 -2
  388. package/tests/shell-bar.test.ts +40 -0
  389. package/tests/shell-changes-view.test.ts +85 -34
  390. package/tests/shell-changes.test.ts +79 -62
  391. package/tests/shell-render-cache-runtime.test.ts +69 -0
  392. package/tests/shell-render-cache.test.ts +129 -0
  393. package/tests/shell-sidebar-layout.test.ts +27 -2
  394. package/tests/shell-todo.test.ts +132 -11
  395. package/tests/shell-usage-view.test.ts +1 -1
  396. package/tests/shell-usage.test.ts +35 -0
  397. package/tests/short-check-routing-contract.test.ts +49 -0
  398. package/tests/skill-registry-watcher.test.ts +119 -0
  399. package/tests/skill-registry.test.ts +311 -5
  400. package/tests/startup-banner.test.ts +117 -3
  401. package/tests/startup-home-repo.test.ts +170 -0
  402. package/tests/status-timing-diagnostics.test.ts +283 -0
  403. package/tests/support/orchestrator-modules.ts +19 -0
  404. package/tests/task-size-routing-contract.test.ts +241 -0
  405. package/tests/telemetry-trigger.test.ts +27 -1
  406. package/tests/test-strength-contract.test.ts +124 -0
  407. package/tests/verify-agent-contract.test.ts +90 -0
  408. package/tests/verify-first-launch-contract.test.ts +139 -0
  409. package/tests/verify-package-files.test.ts +56 -0
  410. package/tests/vim-editor-adapter.test.ts +47 -21
  411. package/tests/visual-customization-policy.test.ts +32 -3
  412. package/tests/visual-customize-view.test.ts +288 -10
  413. package/tests/writer-edit-surface-scope.test.ts +59 -2
  414. package/tests/writer-surfaces.test.ts +199 -0
  415. package/tests/yolo-customize.test.ts +18 -3
  416. package/tests/yolo-mode-runtime.test.ts +37 -10
  417. package/tests/yolo-mode.test.ts +38 -5
  418. package/tests/yolo-session-policy.test.ts +1 -1
  419. /package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/bundle/README.md +0 -0
  420. /package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/bundle/schemas/lens.schema.json +0 -0
  421. /package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/bundle/schemas/refuter.schema.json +0 -0
  422. /package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/bundle/schemas/targeted-validator.schema.json +0 -0
  423. /package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/bundle/vectors/lens.json +0 -0
  424. /package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/bundle/vectors/refuter.json +0 -0
  425. /package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/bundle/vectors/targeted-validator.json +0 -0
@@ -0,0 +1,53 @@
1
+ # Orchestrator — ODD Tracking (lazy-loaded)
2
+
3
+ Bind this to the parent Pi session only. Load it when a task is large (its resume test fails) or the user asks to track it; small tasks never need it (see `orchestrator.md` Task Size).
4
+
5
+ ### Organic Driven Development (ODD)
6
+
7
+ These instructions apply to all development work. Preserve the existing direct/delegated topology and one parent owner; do not introduce an ODD CLI, specialized agent, or execution harness.
8
+
9
+ #### Authorization and progress
10
+
11
+ Investigation, explanation, review, comparison, and proposal-only requests remain read-only: no writer, apply, or implementation artifacts. Ambiguous or conditional change intent (unclear whether a change is authorized at all) requires one clarification; stop and wait. Hedged delivery wording (the user may stop you, review commits one at a time, or pick the work up later) asks for resumable notes and separate commits, not a stop; complete every authorized task in the current turn unless the user explicitly says to wait. Research findings and automatic execution pace never authorize mutations.
12
+
13
+ Size every task by the always-on Task Size section (`orchestrator.md`); small work creates no durable task artifacts, and counts of files, commands, tests, fixes, or lines never make it large. For large authorized implementation, automatically create the feature document after exploration, without a task or storage permission prompt. Follow `orchestrator-memory.md` for the file and full Engram recovery copy, automatic updates, truthful checkoffs, and resume. Keep the parent responsible for reconciliation; bounded workers receive the document locator, task IDs, linked `S#`, authorized scope and checks, not authority over unrelated tasks; they read the document until `## Log` before edits and report which `S#` they covered. A rejected or resumed handoff is repaired and resent with the same content, never shortened. Reproduce a user-reported failure by running the reported example before deciding it already works; reading code is not reproduction. Close gate: before the final answer, if any tracked task in the feature document or `todo` is still pending, continue it or quote the exact user sentence that orders the stop. One **Needs your decision** result naming the open blockers or missing proof is also a valid stop.
14
+
15
+ Use about 400 authored changed lines per ODD task only as a planning heuristic, counting additions plus deletions. Keep the smallest coherent behavior with its tests and docs. This is not a task acceptance criterion, hard cap, counter-trigger, automatic stop, forced split, or RDD trigger. If the correct clear solution naturally exceeds it, briefly explain why and continue without size-only rework loops. Never delete spaces, blank lines, or comments for cosmetic line savings; never omit tests, minify, add gratuitous abstractions, or split artificially to fit the heuristic. Forward this same advisory-only instruction when delegating tasks to subagents. The delivery budget below reads the accumulated branch, not this per-task heuristic. Existing PR size gates remain unchanged; follow repository policy.
16
+
17
+ #### Research depth without a new phase
18
+
19
+ Recommend optional research only for a named uncertainty. Establish the problem, intended outcome, constraints, and current evidence; inspect relevant code. Adapt depth to uncertainty and consequence: no fixed questionnaire or mandatory rounds. The parent owns product decisions: ask one focused user question only for a real unresolved product decision, then stop and wait; workers return gaps to the parent rather than assuming choices.
20
+
21
+ When the question needs external evidence, use available authorized documentation/web tools and prefer primary sources. Attribute material claims to URLs or code locations; distinguish verified facts, assumptions, contradictions, freshness, and gaps. If tools are unavailable, disclose limitations without inventing access or evidence. If research is declined, continue within authorized scope only where safe without the missing evidence; pause only unsafe decisions dependent on it.
22
+
23
+ Return concise findings, recommendation, tradeoffs, open questions, and implementation implications. Offer a concise proposal only when a real scope or product decision needs it. Neither research nor a proposal is mandatory. Forward these research instructions to an existing fresh general exploration/research worker through the existing delegation mechanism; do not create a specialized agent or create a new workflow. Research remains read-only and requires no new persistence or readiness machinery.
24
+
25
+ Use at most one scoped independent read-only assumption challenge for a high-consequence unproven premise, even in a small security-critical change. Name the premise, evidence, and consequence; do not start a debate loop. Deterministic failures need fixes, not model debate. The native RDD refuter owns native review claims; never duplicate or bypass it with this challenge.
26
+
27
+ Before building, validate any consequential premise whose failure would invalidate the approach. Reuse relevant findings from sibling investigations instead of repeating the same exploration; verify only what is stale or materially different. During iteration, run focused checks for the behavior being changed, then run the applicable full suite at closure. This sequencing guides effort rather than imposing a token counter or skipping required checks.
28
+
29
+ #### Checks and candidate consent
30
+
31
+ For behavior changes with applicable runnable deterministic tests and a clear expected outcome, use test-first by default: observe RED before implementation, GREEN after minimum implementation, relevant alternate cases, then REFACTOR with focused checks still passing. Test or framework presence alone does not establish applicability. For passive documentation, non-testable changes, an unavailable runner, or no meaningful RED, state why and run proportionate ordinary functional or structural verification; never invent RED/GREEN or skip checks. No TUI toggle or per-task chat choice activates this policy. Forward this policy, the applicable exact runner and commands (when available), and any exception rationale on every implementation delegation; refresh on resume. Record observed evidence or the reason for fallback in the feature document.
32
+
33
+ Run applicable functional checks per task; a TODO checkbox never triggers a review cycle. The native review candidate is a work-unit commit or a PR slice, never a TODO checkbox and never the accumulated feature branch, and native review runs at that work-unit commit or PR slice boundary, not every task update. Checklists grant no approval or receipt and never skip an existing delivery gate.
34
+
35
+ #### Signaling the ODD phase to the Gentle prompt
36
+
37
+ When the Gentle Shell prompt is active, its working label is inferred automatically from the primary session's tool activity: read-only tools show `exploring`, edits `implementing`, test/typecheck/lint/build runs and native review `checking`, user questions `deciding`, and `todo` or feature-document edits `planning`. `gentle_odd_phase` refines that label with phases tools cannot show (for example `authorizing`, `researching`, `deciding`, `closing`); an explicit report survives following read-only tool calls, while a stronger inferred phase (`deciding`, `planning`, `implementing`, `checking`) replaces it. Call `gentle_odd_phase` only when the primary session's own ODD phase actually changes, never per tool call, per thought, or on a fixed cadence; call it with `clear` only to leave the current phase before its turn ends. Its bounded vocabulary covers the ODD protocol steps above, not a strict one-to-one mapping: `authorizing` (1), `exploring` (2), `researching`/`deciding` (3), `deciding` again for step 4's classify decision (no dedicated label), `planning` (5), `implementing` (6), `checking`/`closing` (7). This is a best-effort UI label, not a source of truth: with no inferred or reported phase it falls back to a generic working indicator, unknown tools and ambiguous shell commands leave it unchanged, and an invalid token never clears an already-reported phase. Never call it from a subagent or background/child task; it reports only the primary session's own phase.
38
+
39
+ When RDD is enabled, first use native candidate risk assessment through `gentle_review` with `{"operation":"assess"}`; after each work-unit commit, assess it with that same call and `{"baseRef":"<last reviewed boundary>","committedOnly":true}`. Passive/low: silent structural checks, no reviewer or consent ceremony, and the boundary advances. High, or an unavailable or failed assessment: the commit itself is the candidate; start native review on it right away at that base with `gentle_review` `{"operation":"start"}` and the same `baseRef`/`committedOnly: true` input. Medium: defer to the PR slice, the commits accumulated since the last reviewed boundary, bounded by the delivery budget of about 400 authored changed lines, and review at slice close; native review runs only on grant, and a decline continues under ordinary policy. The first boundary is the branch point, and every reviewed boundary becomes the next base. Record per task the assessed tier and outcome: granted, declined, passive, deferred to slice, or unavailable. Do not substitute model judgment, task size, or defect severity for prospective candidate risk; never infer low risk from a failed assessment. Follow the mirrored provider contract and native continuations; this paragraph introduces no lifecycle route. When RDD is disabled, do not start or prompt for RDD; ordinary checks remain. A checklist or assumption challenge never enables RDD, replaces its refuter, or answers consent. Raise a candidate you know is high risk with the assess `escalate` field (`orchestrator-verification.md`); never lower one.
40
+
41
+ Delivery follows work units. At feature-document creation, forecast authored changed lines (additions plus deletions, generated files excluded) from the task list, and keep a running count from work-unit commits. Choose one delivery strategy per feature: `ask-on-risk` (default), `auto-chain`, `single-pr`, or `exception-ok`. When the forecast or the running count exceeds about 400 authored changed lines, apply the chosen strategy before the next commit: `ask-on-risk` asks once using the ordered oversized-delivery menu; `auto-chain` asks only for a missing chain strategy and slices automatically with a cached choice. When a choice is needed on either chaining path, offer exactly these three semantic outcomes in order:
42
+
43
+ 1. **Feature/tracker branch chain** — `chain_strategy=feature-branch-chain`.
44
+ 2. **Verified default/main branch chain** — `chain_strategy=stacked-to-main`; verify the destination's default branch rather than assuming its name.
45
+ 3. **One single PR — least recommended** — `delivery_strategy=single-pr`.
46
+
47
+ Generate the complete user-facing question and every option label, description, and recommendation marker in the active user's conversation language (English for an English user, Spanish for a Spanish user, etc.). Machine strategy tokens remain unchanged and untranslated. These English examples are illustrative and localizable, not mandatory copy.
48
+
49
+ The third choice overrides the pending chaining path: clear the chain choice as inapplicable and suppress later chain prompts. `single-pr` is not a `chain_strategy` token; do not automatically select `exception-ok`. Explain that an oversized single PR increases reviewer load, delays feedback, and couples rollback; least recommended applies only to this oversized menu, not focused ≤400-line single PRs. Follow the destination repository's documented contribution/size policy: `size:exception` is a Gentle-owned repository policy, not a universal label requirement. Never request or add it for generic users unless their destination policy uses it; preserve required maintainer acceptance and protected-label authorization. A single PR needs no tracker, child dependency diagram, or Chain Context. Shape selection does not authorize push, PR creation, merge, or review-mode/consent changes. Cache both choices, and record slice boundaries, which commits each pull request holds, in the feature document when chaining; for single PR, record the whole-PR scope instead. Resolve the `work-unit-commits` and `chained-pr` skills by registry name, never hardcode their paths.
50
+
51
+ ## Delivery strategy
52
+
53
+ Use the ODD delivery strategy and work-unit boundaries under Checks and candidate consent above. Push, PR creation, and merge remain human decisions.
@@ -0,0 +1,28 @@
1
+ # Orchestrator — Verification (lazy-loaded)
2
+
3
+ Bind this to the parent Pi session only. Load it when the Verification rule fires (a high-risk change) or a delegated writer returns; the small path never needs it.
4
+
5
+ ## Verification rule (normative)
6
+
7
+ 5. **Verification rule** (gentle-pi#661/#662, verify-always-rdd-high S1; normative -- referenced, not restated, in the other orchestrator modules): The bounded writer always runs the exact parent-authorized commands under the delegated task's `## Verification` heading, synchronously and in the foreground, and reports each as `<command>: <observed result>` -- see `gentle-ai-worker`'s Verification contract for the exact rules, including how `## Known environmental failures` (exact pre-existing base failures) differs from any other failing required command, which still forces `status: partial`. Those foreground commands are live work, not silence: while a tool call is in flight the runner's stall watchdog uses `tool_stall_timeout_ms` (default 30 minutes) instead of the `stall_timeout_ms` idle budget. After the writer returns, call `gentle_review` with `{"operation":"assess"}` over the writer's diff and follow the returned plan, whatever the `Receipt-driven development:` line reads (`on`, `off`, or `unknown`), instead of judging non-triviality from the task description: the operation resolves the native risk tier and states exactly who verifies next. When the line reads `on`, the native review is an additional outside view of the change; it never replaces or skips the tier's verification, and the tier's verifier runs before review. Pass `nativeReviewOutcome` when the parent already knows it; ASSESS derives `closed` only from the native `candidate.consumed` fact for this exact candidate (gentle-pi#1175), so a caller-supplied `closed` is not authority and, without that fact, resolves to `unknown`; the outcome only explains the plan, never lowers it. The tier table (stated once, here):
8
+
9
+ | Native risk tier | Verification (any RDD state) |
10
+ |---|---|
11
+ | passive | structural readback by the parent; no separate verifier, no tests |
12
+ | medium | writer self-verification stands; a separate `gentle-ai-verify` run is added only when the writer profile is a small model (mini or low effort) |
13
+ | high | writer self-verification plus a separate `gentle-ai-verify` run, always |
14
+ | unknown / assess failed | treated as high |
15
+
16
+ The small-model bias raises the tier by one for verification purposes (medium becomes high); an unknown `Receipt-driven development:` line never lowers a tier below `off`. The parent spot check (re-running one reported command before delivery) stays required in every tier. ASSESS takes the writer profile from the runtime-recorded model and effort of the pending mutations for the root; caller `writerModelId`/`writerEffort` are only a fallback when no runtime evidence exists, and a missing model, a `mini` model token (`gemini` is not mini), or `low` effort keeps the conservative small-model bias. When native reports them, ASSESS also projects `reviewDue`, `reviewDueReason`, `candidate.consumed`, and the native continuation verbatim; relay that continuation unchanged and never rebuild it. A native code review is not a substitute for applicable functional checks: tests, builds, and functional verification such as browser checks for UI changes still run when applicable, and review outcomes never authorize delivery. The change's own focused test and suite run inline; a small task needs no separate verifier unless it is high risk.
17
+
18
+ ## Agent escalation (gentle-shell#1494)
19
+
20
+ When the change touches a Task Size high-risk item and the native tier is passive or medium, pass `"escalate": {"item": <1-6>, "reason": "<one line>"}` in the same assess input: the tool raises the tier to high, keeps the native one as `nativeRisk`, returns `agentEscalation`, and never lowers a tier. Until the installed gentle-ai assess accepts it, the raise binds this verification plan only, not the native review tier.
21
+
22
+ ## Parallel review protocol (gentle-shell#1731)
23
+
24
+ 1. **Self-review**, required by each writer prompt, in its own session before returning: spec sections by reference (#1713), the request's authorized examples, tests, and typecheck; it fixes and continues (one correction per failing check, a second only if the same check still fails, then `partial`), reporting requirement by requirement. Low and medium risk need nothing else.
25
+ 2. **Independent verify per unit**, once, after its final self-review (never per worker cycle or retry), in parallel when several finish together, only when that unit is high risk: its Risk line, `assess` over its actual diff or the worker's own `escalate` (high-risk list in Task Size; small-model bias per the tier table), never inferred from the worker's summary alone. Assess per unit via its work-unit commit (`{"baseRef":"<previous>","committedOnly":true}`) or its own isolated worktree. Same-model inline code over several deliveries of one feature: one verify at the feature's end; smaller-model writer code stays per unit.
26
+ 3. **Seam check**: after parallel units finish, one inline full-suite command (the parent spot check) catches seams between units.
27
+ 4. **Verify handoff**: the whole feature document (every `S#`, never one task), the baseline commit, and the probe command forms (tests, CLI, typecheck) for probes on isolated state in a fresh `mktemp -d` scratch copy, never just "read-only"; `gentle-ai-verify` holds the checklist. Resolve every unmet item before closing; the writer commits its probes as regression tests.
28
+ 5. **One correction**: verify blockers get one correction batch that fixes every reported blocker, then one re-verify limited to those blockers, never a new full sweep. Blockers still open after that stop as one **Needs your decision**. Advisories never start a correction. A second correction runs automatically only when the recheck shows the same blocker still failing; a new finding never earns one. A `partial` or `blocked` writer report gets only this correction, never an extra verify run beyond the risk tier's verifier; partial, blocked, unavailable, or exhausted proof left after it becomes that one **Needs your decision**.
@@ -0,0 +1,38 @@
1
+ # Orchestrator — Writer Handoff (lazy-loaded)
2
+
3
+ Parent Pi session only. Load it when the Writer rule fires or an explicitly activated Judgment Day fix batch is dispatched; small tasks never need it. The Writer rule fires on a named reason (parallel units, the context backstop), never on size alone or a price ratio: a large task without a reason stays inline, following its logbook. Configured per-agent models (`subagents.json` `model_profiles`) still apply to every writer it launches. Each writer prompt requires the self-review of the Parallel review protocol in `orchestrator-verification.md`. A reason holds only when the launch delivers it:
4
+
5
+ - **Parallelism**: with the Background subagent policy on, launch every disjoint unit in the same turn via `subagent_run` with `mode: "background"`, then wait for all completions before the Seam check; serial launches void the reason: if units cannot launch together, work inline.
6
+
7
+ #### Allowed edit surfaces (MANDATORY)
8
+
9
+ The bounded writer refuses to write outside the exact allowed edit surfaces and stops with `status: interaction_required` when they are missing. The parent derives them while planning the delegation; neither the writer nor the human supplies them.
10
+
11
+ Before launching a bounded writer (`gentle-ai-worker`, a user-configured `worker`, or the native `Agent` fallback), derive the allowed edit surface from the delegated task — files the change must touch, plus directories where it authorizes new files — and pass it in the prompt under an `## Allowed edit surfaces` heading, in the exact-path form of `## Skills to load before work`:
12
+
13
+ - exact repository-relative paths or narrow globs, one per line; never `.` and never a bare repository root; paths containing whitespace require whole-entry backticks (for example, ``- `Directory With Spaces/note.md` ``); a list marker alone does not permit whitespace;
14
+ - the section ends only at the next canonical ATX Markdown heading of any level (zero to three leading ASCII spaces, one to six `#`, then an ASCII space); every non-empty line before that heading must be a valid surface entry, so put explanatory prose under a following heading;
15
+ - pre-existing untracked targets the writer may write, listed explicitly;
16
+ - nothing beyond the delegated task — a surface wider than the task is the same defect as no surface at all.
17
+
18
+ If the surface genuinely cannot be derived, do not launch the writer or ask the human to author paths. Derive a candidate set first — the exact paths this task would touch — and present that enumerated list as an approve/decline choice under the Lossless Blocking Prompts rules in `orchestrator-prompts.md`. A free-text question asking which paths or globs to authorize is never a valid escalation: computing it is the parent's job.
19
+
20
+ Relay a writer's `interaction_required` payload about edit surfaces the same way: present its derived candidate paths as the choice, and add or drop paths only on the human's explicit instruction.
21
+
22
+ #### Judgment Day fix dispatch
23
+
24
+ Use `jd-fix-agent` only for an explicitly activated Judgment Day fix batch, never as a lexical or generic-writer fallback. Judgment Day is independent: it neither enables nor replaces ordinary review; a separately requested ordinary review remains independent. A standalone Judgment Day fix requires no graph-v1 or native review lineage. Its dispatch carries this exact runtime-accepted Markdown shape: `## Judgment Day activation` contains only `User explicitly requested Judgment Day.`. Replace the example ID, frozen ledger hash, row data, and surface with controller-authorized values. The correction batch contains only one round (`1 of 2` or `2 of 2`) and one lowercase SHA-256. The exact frozen finding rows are one JSON object per line, use only the canonical row fields, and exactly match the authorized IDs.
25
+
26
+ ```markdown
27
+ ## Judgment Day activation
28
+ User explicitly requested Judgment Day.
29
+ ## Exact authorized severe IDs
30
+ - `JD-A-001`
31
+ ## Judgment Day correction batch
32
+ Round: 1 of 2.
33
+ Frozen ledger SHA-256: `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`
34
+ ## Exact frozen finding rows
35
+ {"id":"JD-A-001","lens":"judgment-day","location":"path/to/authorized-file.ts:1","severity":"CRITICAL","status_at_freeze":"open","evidence_class":"deterministic","evidence_claim":"Concrete user-impact claim supported by the frozen location."}
36
+ ## Allowed edit surfaces
37
+ path/to/authorized-file.ts
38
+ ```
@@ -1,6 +1,6 @@
1
1
  # el Gentleman Orchestrator
2
2
 
3
- Bind this to the parent Pi session only; subagents receive bounded task instructions.
3
+ Bind this to the parent Pi session only; subagents get bounded task instructions.
4
4
 
5
5
  ## Identity Contract
6
6
 
@@ -24,54 +24,57 @@ Public/contextual comments and replies are different from technical artifacts. W
24
24
 
25
25
  Subagent-facing English delegation and quote/UI exceptions: `orchestrator-delegation.md`.
26
26
 
27
- ## Mental Model
27
+ ## Task Size
28
28
 
29
- el Gentleman is an ecosystem configurator and harness layer. After installation, the user should not memorize workflows or manually wire agents. The package should get out of the way:
29
+ A task is **small** when all three hold:
30
30
 
31
- - Small request: do it directly.
32
- - Substantial authorized work: use ODD; track feature progress automatically.
33
- - Parent session orchestrates; phase agents execute.
31
+ 1. **Understood** — outcome, what and where to change known; no product or design decision is open; proven in one bounded read batch (at most 3 calls, ~10k tokens).
32
+ 2. **Contained risk** — no high-risk item below.
33
+ 3. **Resumable from the diff** — resume test: if the session stopped now, someone could finish from the original request and `git diff` alone.
34
34
 
35
- Delegation is not optional once complexity appears. If a task crosses the triggers below, use the smallest useful subagent workflow instead of continuing as a monolithic executor.
35
+ The number of files, commands or tests, fixes, or a requested `todo` list never decides size. A task is **large** only when the resume test fails (several sessions, external waits, separate deliverables, requirements compaction could lose); large tasks get ODD tracking and workers only by the Writer rule, else inline.
36
36
 
37
- ## Work Routing Ladder
37
+ Small path: inline (parent; `bash_background` policy); observe RED inline before the fix; run the focused test and the suite inline, once each. No explore, worker, or verifier; no feature document, mirror, or commits unless the user asks; `todo` optional. It needs no lazy asset.
38
38
 
39
- Route ODD work through the smallest safe harness:
39
+ **High risk**: a mistake would be hard to detect, hard to undo, or reaches beyond the change: (1) data or irreversible effects (migrations, rewriting or deleting stored data, format changes, writing data without validation; not saving new records); (2) security (auth, permissions, credentials, secrets, guards, sandbox); (3) changing or removing contracts others already consume (public API, CLI flags, config formats, exports, mirrored prompts; not adding a flag, command or optional field; requested changes are not; unrequested breaks in shared code are); (4) concurrency; (5) delivery or environment (installers, release, CI, deploy, dependencies); (6) no test would catch a regression in what changes. Count "unclear" as high only when a bounded look cannot tell whether (1)-(5) apply. When RDD is on and native assess returns a tier, that tier wins.
40
40
 
41
- 1. **Inline Direct** — small, mechanical, parent has context (typo, one-file edit, read-only check within the evidence budget, bash for state); stop when it is no longer small.
42
- 2. **Simple Delegation** — exploration → `gentle-ai-explore`; bounded implementation → `gentle-ai-worker`; command-running verification → `gentle-ai-verify`. Try its package role; if missing/unusable, use native `Agent` under the same read-only mapping/verification constraints and report fallback.
41
+ **Risk line**: close every code change, small path or delegated, with `Risk: item N (reason)` or `Risk: none` per the list; any item → Verification rule.
43
42
 
44
- ODD (Default Workflow, harness section above) is mandatory on every request; detail: `orchestrator-delegation.md`, `orchestrator-memory.md`. For behavior changes with applicable runnable deterministic tests and a clear expected outcome, use test-first by default: observed RED, GREEN, then refactor with checks. For passive documentation, non-testable changes, an unavailable runner or no meaningful RED, state why and run proportionate ordinary functional or structural verification instead. Test presence alone is not applicability; no chat or TUI toggle activates this policy.
43
+ ODD (Default Workflow, harness section above) is mandatory on every request, with the harness's applicable test-first policy (RED, GREEN, refactor); detail: `orchestrator-delegation.md`, `orchestrator-memory.md`.
45
44
 
46
45
  ## Delegation Rules
47
46
 
48
47
  Core question: does this inflate parent context without need?
49
48
 
50
- Before launching bounded writer (`gentle-ai-worker` or `worker`), task/context needs nonempty `## Allowed edit surfaces`: narrow repository-relative paths/globs; never `.`, bare repo root, or absolute. Parent derives surfaces, maps unknown targets read-only, shows derived candidates only for genuine scope choices. Do not ask the human to author paths or globs.
49
+ Before launching bounded writer (`gentle-ai-worker` or `worker`), derive nonempty `## Allowed edit surfaces`: narrow repository-relative paths/globs; never `.`, bare repo root, or absolute. Do not ask the human to author paths or globs.
51
50
 
52
- Mandatory Delegation Triggers — once fired, delegate through the best available runtime (prefer `subagent_run`, else native `Agent`):
51
+ ## Mechanisms
53
52
 
54
- 1. **Evidence-budget rule** — read inline only if evidence fits one parallel batch (at most 3 calls, ~10k tokens; grep and line ranges, never whole large files). Larger reads, >~5 sequential lookups, or a long session ahead → one scout/explorer returning at most ~2k tokens with `path:line` evidence; re-read nothing it covered beyond one spot check. Never force delegation for a small targeted question.
55
- 2. **Multi-file write rule** — 2+ non-trivial files touched → delegate one writer.
56
- 3. **Incident rule** — diagnose wrong cwd/worktree/git/tooling incidents separately before resuming work.
57
- 4. **Context backstop** — parent context past ~150k tokens → pause and delegate the next bounded unit of work. Keep command output bounded (counts, `--stat`, `tail`); full suites and builds go to a verifier.
58
- 5. **Verification rule** — executing/delegating verification commands → `gentle-ai-verify`; only a read-only check within the evidence budget stays inline.
53
+ Mandatory Delegation Triggers — each mechanism turns on only by its own trigger and is then mandatory (prefer `subagent_run`; role missing/unusable: native `Agent`, same read-only constraints; report fallback). When it resolves, re-evaluate task size.
59
54
 
60
- {{GENTLE_PI_BACKGROUND_POLICY}}; rules: the background-subagents block in the delegation contract.
55
+ 1. **Ask** — open product or design decision → one focused question; stop and wait.
56
+ 2. **Evidence-budget rule** — understanding needs more than one read batch or >~5 sequential lookups → one `gentle-ai-explore`, handoff at most ~2k tokens with `path:line` evidence; one spot check only; never for reading before an inline write.
57
+ 3. **Verification rule** — high risk → independent `gentle-ai-verify` after the change's own checks (`orchestrator-verification.md`); otherwise checks run inline.
58
+ 4. **Track** — large task → feature document, Engram mirror, `todo`, work-unit commits (`orchestrator-tracking.md`, `orchestrator-memory.md`).
59
+ 5. **Writer rule** — never by file count or a large task alone; only for a reason (`orchestrator-writer.md`): 2+ independent units, disjoint files, each heavier than a subagent start, launched together in background, else inline; Context backstop.
60
+ 6. **Incident rule** — diagnose wrong cwd/worktree/git/tooling incidents separately before resuming.
61
+ 7. **Context backstop** — parent context past ~150k tokens → delegate the next bounded unit. Bound command output (counts, `--stat`, `tail`).
61
62
 
62
- Per-action table, Work Routing Ladder examples, Cost and Context Balance, Canonical Workflows, and the mirrored gentle-ai canon (blocking-prompt relays, language, delegation): `orchestrator-delegation.md`.
63
+ {{GENTLE_PI_BACKGROUND_POLICY}}; rules: delegation background-subagents block.
64
+
65
+ Per-action table, Work Routing Ladder, Canonical Workflows: `orchestrator-delegation.md`; blocking-prompt relays and provider defects: `orchestrator-prompts.md`.
63
66
 
64
67
  ## Memory Contract
65
68
 
66
- When memory is available, the parent selects context and subagents save discoveries before returning. ODD task continuity and memory lifecycle: `orchestrator-memory.md`.
69
+ With memory, the parent selects context; subagents save discoveries before returning. ODD task continuity and memory lifecycle: `orchestrator-memory.md`.
67
70
 
68
71
  ## Skill Registry Protocol
69
72
 
70
- The parent resolves skill paths once per session under `## Skills to load before work`; subagents read those `SKILL.md` files first, or report unavailable paths. Fallback semantics (`paths-injected`/`fallback-registry`/`fallback-path`/`none`): `orchestrator-skills.md`.
73
+ The parent resolves skill paths once per session under `## Skills to load before work`; subagents read those `SKILL.md` files first (`paths-injected`) or report unavailable paths; fallbacks: `orchestrator-skills.md`.
71
74
 
72
75
  ## Intent-Driven Skill Discovery
73
76
 
74
- For skill-shaped requests, treat `<available_skills>` as a discovery aid only, never overriding a concrete ask. Discovery order and intent hints: `orchestrator-skills.md`.
77
+ For skill-shaped requests, `<available_skills>` is a discovery aid only, never overriding a concrete ask. Discovery order and intent hints: `orchestrator-skills.md`.
75
78
 
76
79
  ## Gentle AI RDD ownership
77
80
 
@@ -82,5 +85,6 @@ This package injects the mirrored provider-bundle review execution contract into
82
85
  - An eligible interactive Pi host may resolve `gentle-ai.review-integration.consent/v3` before the envelope reaches the model. Permission: host-owned. If `gentle_review` returns the envelope unresolved, it is still the original provider-owned two-choice contract. Use `ask_user_choice` exactly or relay losslessly and stop. Never add the host action to a decoded or relayed provider envelope.
83
86
  - Never commit unless the user explicitly asks.
84
87
  - Ask before destructive git operations, publishing, or irreversible file changes.
85
- - Keep writes single-threaded unless isolated worktrees are explicitly approved.
88
+ - Parallel writers only with disjoint Allowed edit surfaces (runtime-enforced) or isolated worktrees.
89
+ - Keep session work inside the project root and registered same-clone worktrees; ask before any read or write outside it, naming the absolute path. Grants are per-target, per-session, never blanket: in-project scripts naming outside paths are not standing consent.
86
90
  - Preserve human control: user decisions beat agent momentum.
@@ -0,0 +1,52 @@
1
+ # Original notification tones
2
+
3
+ `success.wav`, `error.wav`, and `attention.wav` are original synthetic sine tones,
4
+ created for Gentle AI in 2026. No recording, sample library, audio API, or third-party
5
+ composition was used. Mono PCM, 16-bit, 22050 Hz; amplitude 4000/32768, short fades.
6
+ No platform listening verification has been performed; these are generated assets,
7
+ not evidence of working playback. Linux/macOS adapters require manual verification;
8
+ Windows playback is intentionally unavailable pending a safe native adapter.
9
+
10
+ ## Reproduction recipe (Python 3 standard library)
11
+
12
+ Run from repository root. This reproduces only the three WAV assets:
13
+
14
+ ```python
15
+ import math, struct, wave
16
+ from pathlib import Path
17
+ root = Path('assets/sounds')
18
+ root.mkdir(parents=True, exist_ok=True)
19
+ for name, frequencies in {'success': (660, 880), 'error': (330, 220), 'attention': (880, 880, 880)}.items():
20
+ samples = []
21
+ for frequency in frequencies:
22
+ count = 2646
23
+ for i in range(count):
24
+ envelope = min(1, i / 220, (count - 1 - i) / 440)
25
+ samples.append(round(4000 * envelope * math.sin(2 * math.pi * frequency * i / 22050)))
26
+ samples.extend([0] * 661)
27
+ with wave.open(str(root / (name + '.wav')), 'wb') as out:
28
+ out.setnchannels(1); out.setsampwidth(2); out.setframerate(22050)
29
+ out.writeframes(struct.pack('<' + 'h' * len(samples), *samples))
30
+ ```
31
+
32
+ ## MIT License
33
+
34
+ Copyright (c) 2026 Gentle AI contributors
35
+
36
+ Permission is hereby granted, free of charge, to any person obtaining a copy
37
+ of this software and associated documentation files (the "Software"), to deal
38
+ in the Software without restriction, including without limitation the rights
39
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
40
+ copies of the Software, and to permit persons to whom the Software is
41
+ furnished to do so, subject to the following conditions:
42
+
43
+ The above copyright notice and this permission notice shall be included in all
44
+ copies or substantial portions of the Software.
45
+
46
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
47
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
48
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
49
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
50
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
51
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
52
+ SOFTWARE.
Binary file
Binary file
Binary file
@@ -0,0 +1,9 @@
1
+ #!/bin/sh
2
+ # Gentle Shell's Engram guard. A bundled Gentle Shell points ENGRAM_BIN here
3
+ # when memory is disabled (unknown store compatibility or a missing bundled
4
+ # core) and the user selected neither ENGRAM_BIN nor ENGRAM_URL. Providers reach
5
+ # local Engram data only by running ENGRAM_BIN, so failing here stops them
6
+ # before any store is opened, created or migrated. It never runs Engram and
7
+ # never reads or writes Engram data; the notice is printed as data, not run.
8
+ printf '%s\n' "${ENGRAM_STARTUP_NOTICE:-Engram memory disabled: Shell could not verify safe store or server reuse. Matching versions or updating alone do not prove compatibility. Reuse requires a server with verified /compatibility evidence or matching Shell-provisioned store identity. Back up existing Engram data before manual changes; do not delete it or bypass the safety check. Shell rechecks on every launch and remains usable without memory.}" >&2
9
+ exit 78
@@ -0,0 +1,302 @@
1
+ #!/usr/bin/env node
2
+ import { spawn as spawnChild } from "node:child_process";
3
+ import * as fsPromises from "node:fs/promises";
4
+ import { tmpdir } from "node:os";
5
+ import { join, posix, resolve, win32 } from "node:path";
6
+ import { fileURLToPath, pathToFileURL } from "node:url";
7
+ import { collectInventory, planPreflight, pnpmGlobalBin, requirements } from "../scripts/installer-preflight.mjs";
8
+ import { createProbes, hostAdapters, userEnvironment } from "../scripts/installer-probes.mjs";
9
+ import { acquireGo } from "../scripts/installer-downloads.mjs";
10
+ import { childEnvironment, goFirstEnvironment, lookPath, packageNativeGentleAi, pnpmInvocation, runStandardInstall, upgradeInvocation } from "../scripts/installer-runner.mjs";
11
+ import { createInstallerServer } from "../scripts/installer-server.mjs";
12
+ import { configHome, mainChannelAdapter, ownerManager, removeGlobalShell, runUpgrade } from "../scripts/main-channel.mjs";
13
+ import { ensureWindowsPnpmHome, windowsWizardEnvironment } from "../scripts/installer-windows.mjs";
14
+ import { pathEntryPlan, prefixLayout, prefixRoot } from "../scripts/bundled-install.mjs";
15
+ import { DISTRIBUTION_RELEASES, bundledGate, bundledPlan, fetchDistribution, migrationGate, runBundledInstall, windowsPathRegistry } from "../scripts/bundled-wizard.mjs";
16
+
17
+ // Browser installation wizard entry, started by the bootstrap with no argv.
18
+ // Thin wiring only: real probes and adapters, the standard or bundled runner
19
+ // and the loopback host. Exit 0 keeps the bootstrap's tools; nonzero removes them.
20
+
21
+ /** Fixed per-platform browser opener for a local file, spawned with shell:false; null when none. */
22
+ export function openerFor(platform, file, env) {
23
+ if (platform === "darwin") return { command: "/usr/bin/open", args: [file] };
24
+ if (platform === "linux") return { command: "xdg-open", args: [file] };
25
+ if (platform === "win32") {
26
+ // Absolute path: Windows would otherwise search the current directory first.
27
+ const systemRoot = env.SystemRoot ?? env.SYSTEMROOT;
28
+ if (typeof systemRoot !== "string" || !win32.isAbsolute(systemRoot)) return null;
29
+ return { command: win32.join(systemRoot, "System32", "rundll32.exe"), args: ["url.dll,FileProtocolHandler", file] };
30
+ }
31
+ return null;
32
+ }
33
+
34
+ function escapeHtml(value) {
35
+ return String(value).replace(/[&<>"']/g, (char) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" })[char]);
36
+ }
37
+
38
+ /** Static page that refreshes to the session URL; no script. */
39
+ export function redirectPage(url) {
40
+ const href = escapeHtml(url);
41
+ return [
42
+ "<!doctype html>",
43
+ '<meta charset="utf-8">',
44
+ '<meta name="referrer" content="no-referrer">',
45
+ `<meta http-equiv="refresh" content="0;url=${href}">`,
46
+ "<title>Gentle Shell installation wizard</title>",
47
+ `<p><a href="${href}">Continue to the Gentle Shell installation wizard</a></p>`,
48
+ "",
49
+ ].join("\n");
50
+ }
51
+
52
+ /**
53
+ * Writes the redirect page into a fresh private directory (0700, file 0600)
54
+ * under tempDir, so the one-time code never appears in the opener's argv.
55
+ * remove() is idempotent and best effort: it deletes the file, then the directory.
56
+ */
57
+ export async function writeRedirect(url, { tempDir = tmpdir(), files = fsPromises } = {}) {
58
+ const dir = await files.mkdtemp(join(tempDir, "gentle-shell-install-"));
59
+ const file = join(dir, "open.html");
60
+ let removed = false;
61
+ const remove = async () => {
62
+ if (removed) return;
63
+ removed = true;
64
+ await files.unlink(file).catch(() => {});
65
+ await files.rmdir(dir).catch(() => {});
66
+ };
67
+ try {
68
+ await files.chmod(dir, 0o700);
69
+ await files.writeFile(file, redirectPage(url), { mode: 0o600, flag: "wx" });
70
+ } catch (error) {
71
+ await remove();
72
+ throw error;
73
+ }
74
+ return { dir, file, remove };
75
+ }
76
+
77
+ /**
78
+ * Opens url through a private redirect file with the fixed opener (shell:false,
79
+ * detached). Returns { file, remove } while the file exists, or null when nothing
80
+ * was opened; a failed opener removes the file. The printed URL stays the fallback.
81
+ */
82
+ export async function openBrowser(url, { platform = process.platform, env = process.env, tempDir = tmpdir(), files = fsPromises,
83
+ spawn = spawnChild } = {}) {
84
+ // Resolve the opener first so no file is written when there is none.
85
+ if (openerFor(platform, "", env) === null) return null;
86
+ let redirect;
87
+ try {
88
+ redirect = await writeRedirect(url, { tempDir, files });
89
+ } catch {
90
+ return null;
91
+ }
92
+ const opener = openerFor(platform, redirect.file, env);
93
+ try {
94
+ const child = spawn(opener.command, opener.args, { shell: false, detached: true, stdio: "ignore", windowsHide: true });
95
+ child.once("error", () => {
96
+ void redirect.remove();
97
+ });
98
+ child.unref();
99
+ } catch {
100
+ await redirect.remove();
101
+ return null;
102
+ }
103
+ return { file: redirect.file, remove: redirect.remove };
104
+ }
105
+
106
+ /** 0 only for a completed installation; blocked, failed or none is 1. */
107
+ export function exitCodeFor(outcome) {
108
+ return ["ready", "terminal-action-required"].includes(outcome?.outcome) ? 0 : 1;
109
+ }
110
+
111
+ /** The runner's environment: the user's real PATH, so a temporary bootstrap npm
112
+ * or node never counts as persistent and globalBin.onPath stays truthful. A
113
+ * POSIX bootstrap pnpm (passed only through PATH) comes first: the bootstrap
114
+ * acquired it because the user's pnpm is absent or incompatible, so the user's
115
+ * is never run. Windows passes pnpm through the GENTLE_INSTALL_PNPM_* handoff.
116
+ */
117
+ export async function runnerEnvironment({ platform, env, fs }) {
118
+ const user = userEnvironment({ platform, env });
119
+ if (platform === "win32") return user;
120
+ const wizard = await pnpmInvocation(env, platform, fs);
121
+ if (wizard === null || wizard.prefix.length > 0 || (await pnpmInvocation(user, platform, fs))?.command === wizard.command) return user;
122
+ const rest = String(user.PATH ?? "").split(posix.delimiter).filter((entry) => entry.length > 0);
123
+ return { ...user, PATH: [posix.dirname(wizard.command), ...rest].join(posix.delimiter) };
124
+ }
125
+
126
+ /** An update's children: with a private Windows PNPM_HOME, the runner children's
127
+ * environment (pnpm's folders, TEMP and TMP inside it); a pinned Go first on PATH.
128
+ */
129
+ export function upgradeEnvironment({ platform, env, pnpmHome, goPath }) {
130
+ const globalBin = platform === "win32" && pnpmHome?.source === "private" ? pnpmGlobalBin({ platform, env }) : null;
131
+ const base = globalBin ? childEnvironment(env, platform, globalBin, { privateHome: true }) : env;
132
+ return goPath ? goFirstEnvironment(base, platform, goPath) : base;
133
+ }
134
+
135
+ /** The wizard host's collectPlan and runInstall. Every plan starts from a fresh
136
+ * preflight. A new release installation whose release publishes the
137
+ * distribution assets gets the bundled plan (bundledGate) and the bundled
138
+ * runner; so does an existing Gentle Shell that a global pnpm or npm owns
139
+ * (migrationGate, S4), whose plan ends by removing that old package with its
140
+ * own manager. Everything else gets planPreflight and the standard runner, unchanged.
141
+ * `distributionBase`, `download` and `inventory` are trusted local overrides
142
+ * for tests and local checks.
143
+ */
144
+ export function wizardHandlers({ platform, arch, env, run, fs, distributionBase = DISTRIBUTION_RELEASES, download, inventory: inventoryFor }) {
145
+ // Windows: the PNPM_HOME decision (S6) is made before any probe, on every
146
+ // preflight. The server re-collects right before an installation, so the
147
+ // installation uses the decision its consented plan was checked against.
148
+ let wizard = { env, pnpmHome: null };
149
+ // The distribution assets the latest bundled plan was made from; the bundled
150
+ // runner checks them against the consented plan's lockfile sha256.
151
+ let distribution = null;
152
+ const decide = () => (wizard = platform === "win32" ? windowsWizardEnvironment({ env }) : { env, pnpmHome: null });
153
+ // The user's own PATH and home (no bootstrap tools) for the bundled install's PATH entry and setup.
154
+ const user = userEnvironment({ platform, env });
155
+ const home = platform === "win32" ? env.USERPROFILE : env.HOME;
156
+ return {
157
+ collectPlan: async (channel) => {
158
+ const { env: wizardEnv, pnpmHome } = decide();
159
+ // Fresh probes every time: createProbes caches its global package listing.
160
+ const inventory = inventoryFor ? await inventoryFor(channel)
161
+ : await collectInventory({ platform, arch, probes: createProbes({ platform, env: wizardEnv, run, fs, pnpmHome }), pnpmHome });
162
+ // Only a new release installation, or one a global pnpm or npm owns, asks whether its release publishes the assets.
163
+ const owned = inventory.shell?.available === true && ["pnpm", "npm"].includes(inventory.shell.owner);
164
+ const assets = channel === "release" && (inventory.shell?.available === false || owned)
165
+ ? await fetchDistribution({ version: requirements.shell, base: distributionBase, ...(download ? { download } : {}) }) : null;
166
+ const manager = migrationGate({ channel, inventory, distribution: assets, version: requirements.shell });
167
+ if (manager || bundledGate({ channel, inventory, distribution: assets, version: requirements.shell })) {
168
+ distribution = assets;
169
+ // The folder the claim will take (Windows may fall back to the profile), from read-only checks.
170
+ const layout = prefixLayout({ platform, env: user, home, root: prefixRoot({ platform, env: user }) });
171
+ return { inventory, plan: bundledPlan({ platform, distribution: assets, layout, path: pathEntryPlan(layout, { platform, env: user, home }),
172
+ ...(manager ? { migrate: { manager, removal: "plan" } } : {}) }) };
173
+ }
174
+ return { inventory, plan: planPreflight(inventory, { channel }) };
175
+ },
176
+ runInstall: async (request, log) => {
177
+ const { env: wizardEnv, pnpmHome } = wizard;
178
+ // npm and pnpm as `gentle-shell upgrade` runs them (a pinned Go first on PATH when given). On
179
+ // Windows they are the bootstrap's handoff and run without cmd.exe.
180
+ const managers = (runnerEnv, goPath) => {
181
+ const upgradeEnv = upgradeEnvironment({ platform, env: runnerEnv, pnpmHome, goPath });
182
+ const invocation = upgradeInvocation({ platform, env: upgradeEnv, run, fs, handoff: true });
183
+ return {
184
+ fetch: globalThis.fetch,
185
+ fs: fsPromises,
186
+ which: (name) => lookPath(name, upgradeEnv, platform, fs),
187
+ ...(invocation ? { invocation } : {}),
188
+ // stderrTail: a failed main build or extraction keeps its bounded stderr as the error's cause.
189
+ run: (command, argv, options = {}) => run(command, argv, { env: options.env ?? upgradeEnv, cwd: options.cwd, deadlineMs: options.deadlineMs ?? 20 * 60_000,
190
+ ...(options.stderrTail === undefined ? {} : { stderrTail: options.stderrTail }) }),
191
+ };
192
+ };
193
+ const runnerContext = async () => {
194
+ const runnerEnv = await runnerEnvironment({ platform, env: wizardEnv, fs });
195
+ return { runnerEnv, ctx: { env: runnerEnv, home: runnerEnv.HOME ?? env.HOME ?? env.USERPROFILE } };
196
+ };
197
+ if (request?.plan?.bundled !== undefined) {
198
+ return runBundledInstall(request, { platform, arch, env: user, home, distribution, log,
199
+ ...(platform === "win32" ? { registry: windowsPathRegistry(env) } : {}),
200
+ // The consented owner, found again now: the old gentle-pi is removed only with the manager that still owns it.
201
+ removeGlobal: async (name) => {
202
+ const located = await createProbes({ platform, env: wizardEnv, run, fs, pnpmHome }).locateShell();
203
+ if (located?.owner !== name) return false;
204
+ const { runnerEnv, ctx } = await runnerContext();
205
+ const adapters = managers(runnerEnv, null);
206
+ const manager = await ownerManager({ ctx, platform, packageRoot: located.root, adapters });
207
+ return manager.name === name && removeGlobalShell(manager, adapters.run);
208
+ } });
209
+ }
210
+ const { runnerEnv, ctx } = await runnerContext();
211
+ return runStandardInstall(request, {
212
+ platform,
213
+ nodePath: process.execPath,
214
+ env: runnerEnv,
215
+ run,
216
+ fs,
217
+ // An existing Gentle Shell: fresh probes find it, `gentle-shell upgrade`'s logic updates it.
218
+ locateShell: () => createProbes({ platform, env: wizardEnv, run, fs, pnpmHome }).locateShell(),
219
+ // An older Pi: fresh probes find it before its update and confirm it afterwards.
220
+ locatePi: () => createProbes({ platform, env: wizardEnv, run, fs, pnpmHome }).locatePi(),
221
+ // Only a plan with a private Windows PNPM_HOME: claimed, then walked again.
222
+ preparePnpmHome: (home) => ensureWindowsPnpmHome(home, runnerEnv),
223
+ // Only a plan that needs Go and found it missing, older or unchecked: verified go.dev
224
+ // bytes under <config home>/tools/go, used by path or child PATH only.
225
+ acquireGo: () => acquireGo({ root: join(configHome(ctx), "tools", "go"), platform, arch }),
226
+ // A pinned Go goes first on the PATH of the upgrade's children only.
227
+ upgradeShell: async ({ channel, packageRoot, currentVersion, goPath }) => (await runUpgrade({
228
+ args: ["--channel", channel],
229
+ ctx,
230
+ platform,
231
+ arch,
232
+ packageRoot,
233
+ currentVersion,
234
+ adapters: managers(runnerEnv, goPath),
235
+ out: () => {},
236
+ })) === 0,
237
+ verifyGentleAi: packageNativeGentleAi,
238
+ // Only a main plan uses it: network access and writes under ~/.pi/gentle-ai.
239
+ mainChannel: mainChannelAdapter({ fs: fsPromises }),
240
+ log,
241
+ });
242
+ },
243
+ };
244
+ }
245
+
246
+ async function main() {
247
+ const { platform, arch, env } = process;
248
+ const { run, fs } = hostAdapters();
249
+ // The redirect file is removed once the code is redeemed, or when the host closes.
250
+ let redeemed = false;
251
+ let redirect = null;
252
+ const host = createInstallerServer({
253
+ onRedeemed: () => {
254
+ redeemed = true;
255
+ void redirect?.remove();
256
+ },
257
+ assetsDir: fileURLToPath(new URL("../assets/install-wizard/", import.meta.url)),
258
+ ...wizardHandlers({ platform, arch, env, run, fs }),
259
+ });
260
+ let started;
261
+ try {
262
+ started = await host.listen();
263
+ } catch {
264
+ console.error("The installation wizard could not start its local server. Nothing was installed.");
265
+ process.exitCode = 1;
266
+ return;
267
+ }
268
+ console.log("Gentle Shell installation wizard");
269
+ console.log(`Open this link in your browser (it works once and expires in 2 minutes):\n ${started.url}`);
270
+ console.log("Press Ctrl+C to stop the wizard.");
271
+
272
+ let signalled = false;
273
+ const stop = () => {
274
+ signalled = true;
275
+ host.close("signal");
276
+ };
277
+ process.once("SIGINT", stop);
278
+ process.once("SIGTERM", stop);
279
+ const opening = openBrowser(started.url).then((opened) => {
280
+ redirect = opened;
281
+ // The printed URL may have been redeemed while the file was being written.
282
+ if (redeemed) void opened?.remove();
283
+ return opened;
284
+ });
285
+ const { reason, outcome } = await host.closed;
286
+ process.off("SIGINT", stop);
287
+ process.off("SIGTERM", stop);
288
+ await (await opening)?.remove();
289
+ const code = exitCodeFor(outcome);
290
+ if (outcome?.guidance) console.log(outcome.guidance);
291
+ else if (reason === "idle") console.log("The wizard closed after 30 minutes without activity. Nothing was installed.");
292
+ else console.log("The wizard closed without installing anything.");
293
+ if (signalled) process.exit(code);
294
+ process.exitCode = code;
295
+ }
296
+
297
+ if (process.argv[1] && import.meta.url === pathToFileURL(resolve(process.argv[1])).href) {
298
+ main().catch(() => {
299
+ console.error("The installation wizard stopped unexpectedly.");
300
+ process.exitCode = 1;
301
+ });
302
+ }