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,28 @@
1
+ # Verify render-cache effectiveness without removing animations
2
+
3
+ Use the diagnostic runner to compare two worktrees based on the same commit. It loads both through Pi's native virtual modules, verifies exact editor class identity, and retains quality animation, the Shell editor/header/sidebar, native messages, native tool components and fullscreen frame rendering.
4
+
5
+ ## Run
6
+
7
+ ```bash
8
+ node scripts/render-cache-performance.mjs \
9
+ --baseline-root=<before-worktree> \
10
+ --candidate-root=<fixed-worktree> \
11
+ --pi-root=<installed-pi-package> \
12
+ --output=/tmp/render-cache-performance.json
13
+ ```
14
+
15
+ Default matrix: 100/1,000/5,000 tools × 100/160 columns × float/neon × pulse, scroll, typing, streaming, append, resize and theme. Four fresh-process paired replicas alternate before/after order (AB/BA/AB/BA). `--counts`, `--widths`, `--styles`, `--samples`, `--repetitions` and `--live-ms` override these settings; use small counts and samples for a smoke run. Run serially on an otherwise idle machine.
16
+
17
+ ## Read the evidence
18
+
19
+ - `runs`: raw action-plus-frame wall/CPU times, cold render, construction time, paint/projection counters, visible-screen hashes, memory snapshots and a separate live quality-timer/typing run.
20
+ - `comparisons`: per-replica medians and exploratory p95, speedup and enforced cold/warm output equivalence. All tracked source files, host/native dependency files and instrumentation fingerprints must remain unchanged.
21
+ - Stable cases use 50 measured frames after five warmup frames. Resize/theme deliberately invalidate caches and use at most eight frames; do not treat their tail percentile as statistically robust.
22
+ - Heap/RSS snapshots use explicit GC outside timing, including a job boundary after teardown. They characterize retention for these fixtures, not all transient allocations or proof of absence of leaks.
23
+
24
+ ## Limits
25
+
26
+ Reports must use a new path outside the source/harness/host roots; existing files and symlinks are rejected. Read only reports with a `finished` field after successful process exit: progress writes are not atomic.
27
+
28
+ The transcript is synthetic. Deterministic cases drive the real quality interval callback with controlled time; the separate live run uses real timers and records input-to-frame latency and timer drift. The ANSI sink has no terminal emulator or real terminal-write cost. Model/network latency, other extensions and real session restore/startup are not measured. Private APIs are audited only on Pi and pi-tui 1.1.0 and fail closed on version/editor identity/output mismatches. Preserve raw data and report replicas separately; consecutive frames are correlated, so neither p95 nor a render speedup describes the entire application's latency.
@@ -0,0 +1,39 @@
1
+ # Session profile record format
2
+
3
+ `lib/session-profile-persistence.ts` defines the optional session profile v1
4
+ codec and pure replay contract. Adding this module does not change Enter,
5
+ startup, routing, shared defaults, or live orchestrator behavior.
6
+
7
+ ## Payloads
8
+
9
+ A custom entry uses `customType: "gentle-pi.session-profile/v1"` and one payload:
10
+
11
+ ```json
12
+ {"kind":"bind","origin":"user","name":"work","modelProfiles":{"worker":{"model":"provider/model"},"orchestrator":{"thinking":"high"}}}
13
+ {"kind":"clear"}
14
+ ```
15
+
16
+ The encoder creates only explicit `user` selections. The decoder accepts the
17
+ closed origin set `user`, `local`, `repo`, and `global`; this does not implement
18
+ inherited startup persistence or follow mode. A bound empty snapshot is not a
19
+ clear. Snapshots are detached, known invalid fields reject the whole binding,
20
+ and unknown extra fields carry no routing meaning. Existing route normalization
21
+ supports legacy model strings and `effort`; valid `thinking` takes precedence.
22
+
23
+ ## Replay
24
+
25
+ `replaySessionProfileBranch` requires entries already corroborated on disk,
26
+ ordered oldest to newest on the active branch. Supplying `getBranch()` alone
27
+ does not establish persistence. The newest profile-family entry is terminal:
28
+
29
+ | Result | Meaning |
30
+ | --- | --- |
31
+ | `absent` | No profile-family entry on the supplied branch. |
32
+ | `bound` | A detached, validated binding, including an empty snapshot. |
33
+ | `cleared` | An explicit clear; fallback is a later consumer's decision. |
34
+ | `invalid` | Invalid v1 data; never resurrect an earlier binding. |
35
+ | `unsupported` | Unknown profile-family identifier, regardless of payload. |
36
+
37
+ Replay neither appends nor publishes bindings and never applies a model or
38
+ thinking level. A subsequent disk-reader slice supplies corroboration; this
39
+ codec alone cannot establish it.
@@ -0,0 +1,191 @@
1
+ # Propuesta: notificaciones sonoras nativas
2
+
3
+ **Propuesta histórica aprobada y ejecutada por unidades; ver [estado actual](#estado-actual-sn6).** El texto original debajo conserva las decisiones propuestas, no afirma que sigan sin implementar.
4
+
5
+ Incorporar a gentle-shell notificaciones sonoras configurables para sesión, agente principal y subagentes. El audio estará **desactivado por defecto** y no alterará la ejecución, las decisiones ni los permisos del harness.
6
+
7
+ ## Decisión propuesta
8
+
9
+ Crear una capa independiente de notificaciones: los adaptadores observan eventos reales, una política decide si notificarlos y un backend reproduce el sonido sin bloquear el trabajo. La reproducción pertenece a la sesión interactiva padre, nunca a cada proceso hijo.
10
+
11
+ La primera versión ofrece configuración por origen y transición, sonidos incluidos, archivos propios, prueba de sonido y silencio temporal. No añade notificaciones de escritorio ni un bus de eventos generalista.
12
+
13
+ ## Encaje en la estructura actual
14
+
15
+ | Punto existente | Papel en la propuesta |
16
+ |---|---|
17
+ | `extensions/gentle-shell.ts` | Integrar el acceso a configuración; ya observa eventos de sesión y agente principal. |
18
+ | `extensions/gentle-agents.ts` | Publicar transiciones de tareas vivas, sin reproducir audio directamente. |
19
+ | `lib/agents-protocol.ts` | Fuente del vocabulario de estados de subagentes. No duplicar su máquina de estados. |
20
+ | `lib/agent-home.ts` | Resolver el directorio global con `gentlePiConfigHome()`. |
21
+ | `lib/visual-customization-policy.ts` | Referencia de configuración validada y escritura atómica; no mezclar audio con ajustes visuales. |
22
+
23
+ Archivos nuevos orientativos:
24
+
25
+ - `extensions/gentle-notifications.ts`: ciclo de vida, suscripciones y propietario único del servicio.
26
+ - `lib/notification-policy.ts`: esquema, resolución de configuración, selección de sonido, deduplicación y límites.
27
+ - `lib/notification-audio.ts`: detección de capacidades y reproducción por plataforma.
28
+ - `assets/sounds/`: sonidos breves con licencia redistribuible documentada.
29
+ - Pruebas de política, adaptadores y reproducción bajo `tests/`.
30
+
31
+ La integración usará el mecanismo de eventos existente. Los nuevos eventos internos serán tipados y específicos de notificaciones; no se introducirán dependencias desde los runners hacia audio o UI.
32
+
33
+ ## Qué se puede configurar
34
+
35
+ Se notifican **entradas en estados o eventos de ciclo de vida**, no snapshots ni cada actualización de texto. Sesión, agente principal y subagentes no comparten necesariamente los mismos estados.
36
+
37
+ | Origen | Transiciones/eventos propuestos | Condición |
38
+ |---|---|---|
39
+ | Sesión | `started`, `shutdown` | Inicio interactivo y cierre; el sonido de cierre es de mejor esfuerzo. |
40
+ | Agente principal | `started`, `completed`, `failed`, `cancelled`, `attention` | Derivados de evidencia del runtime, no de etiquetas visuales. |
41
+ | Subagente | `queued`, `running`, `waiting`, `completed`, `failed`, `cancelled`, `timed_out` | Vocabulario actual de `TASK_STATUS`. |
42
+
43
+ `attention` significa una petición explícita de intervención, no estar pensando ni ejecutar una herramienta. `waiting` conservará su significado real en el protocolo de subagentes; no se asumirá que todo tiempo de espera requiere al usuario.
44
+
45
+ **Antes de implementar:** confirmar qué eventos distinguen fallo, cancelación y finalización del agente principal, qué productores representan intervención humana y si `session_start` también cubre cambios de sesión. No interpretar `agent_end` como éxito por sí solo. Si una transición no tiene evidencia fiable, quedará fuera del catálogo inicial y se documentará la limitación.
46
+
47
+ ### Preset recomendado
48
+
49
+ El interruptor general empieza apagado. Al activarlo con el preset recomendado:
50
+
51
+ - Finalización de agente principal o subagente: sonido breve de éxito.
52
+ - Fallo y timeout: sonido de error.
53
+ - Intervención humana explícita: sonido de atención.
54
+ - Inicio, ejecución, cancelación y cierre: silencio.
55
+
56
+ Todos los eventos disponibles pueden asignarse a un sonido o a silencio. El catálogo de la UI mostrará solo eventos realmente soportados.
57
+
58
+ ## Configuración
59
+
60
+ Archivo global propuesto: `<gentlePiConfigHome()>/notifications.json`; por defecto, `~/.pi/gentle-ai/notifications.json`. Se respeta `GENTLE_PI_CONFIG_HOME`.
61
+
62
+ Ejemplo ilustrativo del esquema propuesto, no configuración funcional actual:
63
+
64
+ ```json
65
+ {
66
+ "schema": "gentle-shell.notifications/v1",
67
+ "enabled": false,
68
+ "audio": {
69
+ "backend": "auto",
70
+ "minimumIntervalMs": 1000,
71
+ "coalesceWindowMs": 300,
72
+ "events": {
73
+ "session.started": null,
74
+ "session.shutdown": null,
75
+ "agent.started": null,
76
+ "agent.completed": "builtin:success",
77
+ "agent.failed": "builtin:error",
78
+ "agent.cancelled": null,
79
+ "agent.attention": "builtin:attention",
80
+ "subagent.queued": null,
81
+ "subagent.running": null,
82
+ "subagent.waiting": null,
83
+ "subagent.completed": "builtin:success",
84
+ "subagent.failed": "builtin:error",
85
+ "subagent.cancelled": null,
86
+ "subagent.timed_out": "builtin:error"
87
+ }
88
+ }
89
+ }
90
+ ```
91
+
92
+ Reglas:
93
+
94
+ - `null` significa silencio; un evento omitido también significa silencio. No habilitar sonidos nuevos implícitamente al actualizar.
95
+ - `builtin:<id>` selecciona un sonido incluido; `file:<ruta-absoluta>` selecciona un archivo local validado.
96
+ - Archivo ausente: configuración desactivada sin escribir archivos ni detectar reproductores.
97
+ - Archivo inválido o ilegible: audio desactivado y diagnóstico discreto, una sola vez. La UI no sobrescribe un archivo inválido silenciosamente.
98
+ - Escritura atómica, siguiendo el patrón de configuración existente.
99
+ - Sin configuración por repositorio en v1: un proyecto no puede activar audio ni seleccionar archivos o ejecutables en la máquina del usuario.
100
+ - Silencio temporal en memoria, no persistente. Cambiar de sesión conserva ese silencio mientras viva la misma instancia interactiva; reiniciar el proceso lo elimina.
101
+
102
+ ## Experiencia de usuario
103
+
104
+ Añadir una sección **Notificaciones** al acceso de personalización/configuración existente, separada de los ajustes visuales:
105
+
106
+ 1. Activar/desactivar audio.
107
+ 2. Elegir origen y evento; asignar sonido o silencio.
108
+ 3. Seleccionar sonido incluido o introducir un archivo local.
109
+ 4. Probar el sonido elegido mediante una acción explícita.
110
+ 5. Silenciar/reanudar durante esta instancia interactiva.
111
+ 6. Consultar disponibilidad del backend y restaurar el preset.
112
+
113
+ La prueba es una excepción explícita al interruptor general: el usuario puede preescuchar sin activar notificaciones automáticas. No reproduce eventos pendientes ni cambia configuración por sí sola.
114
+
115
+ No se modifica el resultado de herramientas ni se añaden mensajes al contexto del modelo. No se requiere un comando nuevo en v1.
116
+
117
+ ## Fiabilidad, ruido y seguridad
118
+
119
+ - **Una sola reproducción:** los hijos publican estados; solo el propietario interactivo padre puede reproducir. RPC/headless y procesos de subagentes permanecen silenciosos.
120
+ - **Sin replay:** restaurar tareas o historial establece la referencia inicial, pero no genera sonidos. Desactivar o silenciar descarta pendientes; reactivar no reproduce el pasado.
121
+ - **Identidad:** deduplicar por sesión, tarea/run y transición. Reinicios o ejecuciones nuevas no reutilizan la identidad anterior.
122
+ - **Ráfagas:** agrupar durante 300 ms y reproducir un sonido con prioridad error > atención > éxito > otros. El intervalo mínimo limita la frecuencia global; no acumular una cola que suene después de perder relevancia.
123
+ - **Sin solapamiento:** reproducción serial y cola acotada a un candidato pendiente. Un sonido más prioritario puede sustituir al pendiente, no al que ya se está reproduciendo.
124
+ - **No bloquear:** procesos asíncronos, timeout acotado y limpieza al cerrar. Ningún fallo de audio cambia el estado del agente.
125
+ - **Archivos seguros:** validar archivo regular, formato permitido y tamaño acotado; no aceptar URL, comandos ni expansión de shell. Ejecutar binarios conocidos con argumentos separados, nunca `shell: true`.
126
+ - **Diagnósticos discretos:** backend ausente o fallo de reproducción produce una advertencia local limitada, nunca spam ni contaminación del transcript.
127
+ - **Sin sonido obligatorio:** no usar BEL como fallback automático; puede producir sonido o aviso visual según el terminal y no permite distinguir los eventos.
128
+
129
+ ## Plataformas
130
+
131
+ Proponer adaptadores para Linux, macOS y Windows, con detección perezosa al activar o probar audio. No instalar dependencias del sistema automáticamente.
132
+
133
+ | Entorno | Comportamiento esperado |
134
+ |---|---|
135
+ | Linux | Elegir un reproductor conocido disponible y probar reproducción local. |
136
+ | macOS | Usar reproducción nativa disponible, con el mismo contrato asíncrono. |
137
+ | Windows | Usar un mecanismo nativo sin abrir ventanas de consola auxiliares. |
138
+ | SSH, contenedores o equipos sin audio | Reproducción en la máquina del proceso; no prometer audio en el equipo cliente. Si no hay backend utilizable, informar y seguir. |
139
+
140
+ WAV sería el formato base para sonidos incluidos y archivos propios en v1, evitando una matriz de codecs. El backend exacto de cada plataforma y los límites de tamaño/duración se concretarán tras una prueba técnica; no se considerará soportada una plataforma sin verificación real.
141
+
142
+ ## Alcance y no objetivos
143
+
144
+ **Incluido:** configuración global opt-in, catálogo de transiciones verificables, sonidos incluidos/propios, UI de configuración, prueba, silencio temporal, deduplicación, agrupación y fallos no bloqueantes.
145
+
146
+ **Fuera de v1:** notificaciones de escritorio, voz, URLs de audio, ejecutables configurables, horarios, reglas por agente individual/proyecto, sincronización entre sesiones independientes, detección de foco de ventana y perfiles visuales con audio.
147
+
148
+ Dos sesiones independientes pueden sonar a la vez; la política limita cada instancia, no todos los procesos del equipo.
149
+
150
+ ## Criterios de aceptación y verificación
151
+
152
+ - [ ] Sin archivo de configuración o con `enabled: false`, no hay audio automático, subprocesses de reproducción ni detección de backend.
153
+ - [ ] Cada evento soportado puede configurarse independientemente por origen.
154
+ - [ ] `agent_end` no genera éxito cuando el resultado indica fallo o cancelación.
155
+ - [ ] Una transición duplicada produce como máximo una notificación; una ejecución nueva puede notificar de nuevo.
156
+ - [ ] La restauración de historial y tareas no reproduce sonidos.
157
+ - [ ] Los hijos y sesiones no interactivas nunca reproducen audio.
158
+ - [ ] Silenciar/desactivar limpia pendientes; reanudar no genera replay.
159
+ - [ ] Ráfagas respetan prioridad, intervalo mínimo y ausencia de solapamiento.
160
+ - [ ] Configuración inválida, archivo ausente y reproductor fallido no bloquean ni alteran el trabajo.
161
+ - [ ] Rutas con espacios y caracteres especiales no se interpretan como comandos.
162
+ - [ ] La UI permite configurar, probar y silenciar; la prueba no habilita audio automático.
163
+ - [ ] El cierre limpia procesos y listeners sin prolongar indebidamente la salida.
164
+ - [ ] Se documentan y verifican manualmente las plataformas declaradas como soportadas.
165
+
166
+ Usar tests deterministas con reloj y reproductor inyectados para política y deduplicación; tests de adaptadores para eventos reales, restauración y resultado del agente; tests de configuración y argumentos del backend. Aplicar RED/GREEN a esas conductas durante implementación. Complementar con pruebas manuales de UI, escucha y cierre por plataforma. Esta propuesta documental no requiere RED/GREEN.
167
+
168
+ ## Unidades de implementación propuestas
169
+
170
+ 1. **Contrato y política:** confirmar productores de eventos, esquema, configuración y tests de deduplicación/ráfagas.
171
+ 2. **Audio:** adaptadores, sonidos redistribuibles y tests de fallos, timeout y seguridad.
172
+ 3. **Integración:** propietario padre, eventos de agente/subagentes y pruebas de no replay/headless.
173
+ 4. **Configuración y entrega:** UI, documentación y matriz de verificación manual por plataforma.
174
+
175
+ Cada unidad conservará sus tests junto al código. Estimar el diff antes de implementar y dividir la entrega si el volumen dificulta la revisión.
176
+
177
+ ## Próximo paso
178
+
179
+ Aprobar o ajustar el alcance de v1 y la configuración global. Después, realizar una exploración técnica acotada de productores de estados y reproducción por plataforma antes de fijar el contrato e implementar.
180
+
181
+ ## Estado de ejecución en este worktree
182
+
183
+ **Estado histórico al copiar esta propuesta: ejecución aprobada; implementación todavía no iniciada en aquel turno.**
184
+ El estado inicial y el texto anterior se conservan como propuesta histórica, sin modificar el original de `gentle-shell`. El alcance aprobado, los contratos refinados y las seis unidades futuras se concretan en el [plan ODD](../odd/tasks/sound-notifications.md), que rige la ejecución.
185
+ Esta entrega es solo planificación y copia: sin implementación, review, subagentes ni commits. La elección «Por unidades revisables (recomendado)» autoriza para la ejecución posterior commits LOCALES por unidad con sus tests, no push ni PR.
186
+
187
+ ## Estado actual SN6
188
+
189
+ SN1–SN5 implementados y entregados por el parent; SN5 `c3a20d8e` (548 líneas, contexto confirmado por parent). SN6 añade el panel Notifications desde customize, validación WAV al seleccionar, consentimiento de recuperación estrictamente booleano y documentación de uso. La guía vigente es [sound-notifications.md](sound-notifications.md); el [ODD](../odd/tasks/sound-notifications.md) conserva RED/GREEN y pendientes.
190
+
191
+ No se declara aceptación completa: SN6 espera commit del parent, full checks/verifier y manuales de UI, escucha, reload y quit. Linux/macOS tienen adaptadores implementados **UNVERIFIED manual listening**; Windows permanece unavailable. `session.shutdown` se excluye del catálogo runtime/UI para no demorar el cierre, aunque la propuesta histórica pedía mejor esfuerzo y el esquema conserva la clave. La sección Plataformas anterior es intención histórica, no una afirmación actual de soporte Windows ni verificación física. No hay review, commits ni subagentes en este turno de implementación.
@@ -0,0 +1,114 @@
1
+ # Sound notifications
2
+
3
+ Audio is **off by default**. In a primary Pi terminal, open `/gentle:customize` → **Notifications** (the card header reads **Audio notifications**) and use the controls **directly in the same two-column card**: the global switch, process mute and three independent type groups (**Success**, **Error**, **Attention**) that each own their included tone or a local WAV. Per-event exceptions stay folded behind **Advanced**. Nothing closes the overlay or opens a second menu, and audio preferences stay separate from visual settings, profiles and visual reset. No new command is needed.
4
+
5
+ **Quick answer (Linux/WSLg):** on **plain Linux** the installed package prefers the native WAV backend and needs no external player; it connects to the local PulseAudio/PipeWire-Pulse Unix socket and needs a running server with a default sink. Inside **WSL** the Windows system `SoundPlayer` is preferred instead: the validated WAV snapshot is mapped to the derived `\\wsl.localhost\<distro>\...` UNC path and played by the fixed system host, so no Pulse server or RDP audio dependency is required; it does depend on the default `/mnt/c` automount and the standard `C:\Windows` root and falls back to the trusted Linux CLI before any playback otherwise. **Native Windows** WAV uses the same system `SoundPlayer` through the fixed `C:\Windows\...\powershell.exe` host. A read-only probe succeeded here, but physical audio is not claimed. OGG/FLAC always use the legacy CLI backend on Linux and WSL; native OGG/FLAC codecs are a future phase and Windows OGG/FLAC is unsupported. macOS keeps `afplay` for WAV and FLAC (own CoreAudio phase planned).
6
+
7
+ ## Use the direct controls
8
+
9
+ - **Audio notifications: on / off** toggles the global switch. Highlighting or rendering the row never discovers a player or enables anything.
10
+ - **Audio: unmuted / muted** toggles this process' mute. Mute survives reload and session replacement; restarting Pi clears it. Muting/disabling discards pending events; resuming never replays them.
11
+ - **Success / Error / Attention** are the three basic types. Each shows its human selection — `success tone` / `error tone` / `attention tone`, `silence`, a local WAV basename, or `Custom (varies)` when the type's events diverge. **Enter** cycles that type between `silence → builtin:success → builtin:error → builtin:attention → silence`; on a mixed type Enter applies the recommended tone for that type. **`f`** opens an inline field to assign a literal absolute local WAV to that type, independently of the other types; the field is prefilled with the current path when the type already owns a file. **`p`** explicitly previews the type's selected sound, never an arbitrary one.
12
+ - **Advanced: show/hide per-event exceptions** reveals the per-event rows (`agent.completed`, `context.high`, …) for one-off overrides. They start folded; expanding or collapsing only changes the card view and never writes configuration or reproduces sound. Each per-event row cycles and assigns its own WAV like a type row. **`f`** and **`p`** on any type or per-event row stay inside the same card; in Notifications `p` never opens the visual profiles pane.
13
+
14
+ **Context warning.** When context usage reaches **90%** of the active model's window, Gentle warns once per high episode. The sound is the `context.high` event: turn **Audio notifications** on, expand **Advanced**, and select its sound. A file saved before `context.high` existed stays silent for it, so select a sound on that Advanced row to hear it; its recommended tone is `builtin:attention`. The visual warning is fully independent: the **Sections → Section contextWarning** row in `/gentle:customize` (shown by default) toggles it, and neither toggle changes the other. The episode rearms when usage drops below 90%, after a successful compaction, or in a new session; a canceled or failed compaction does not rearm, and the unknown reading right after a successful compaction never repeats the warning.
15
+
16
+ The inline field and the recovery confirmation render inside the same card. **Escape** cancels the field or confirmation; a second Escape closes the card. If the field, value or `y yes` cannot be shown in full (a resize or a very small terminal), Enter or `y` is refused instead of acting on something invisible. Invalid/unreadable configuration disables automatic audio: saving in that state requires a fresh explicit inline confirmation to replace it, cancel preserves the file and settings, and a failed write does not grant consent to the next attempt. Diagnostics are generic local UI notices, not conversation messages, tools, model context or agent state.
17
+
18
+ ## Supported events and defaults
19
+
20
+ | Origin | Events | Recommended sound |
21
+ | --- | --- | --- |
22
+ | Session | `session.started` | Silence |
23
+ | Main agent | `agent.started`, `agent.cancelled` | Silence |
24
+ | Main agent | `agent.completed` | `builtin:success` |
25
+ | Main agent | `agent.failed` | `builtin:error` |
26
+ | Main agent | `agent.attention` | `builtin:attention` |
27
+ | Context | `context.high` | `builtin:attention` |
28
+ | Subagent | `subagent.queued`, `subagent.running`, `subagent.waiting`, `subagent.cancelled` | Silence |
29
+ | Subagent | `subagent.completed` | `builtin:success` |
30
+ | Subagent | `subagent.failed`, `subagent.timed_out` | `builtin:error` |
31
+
32
+ `session.started` means initial process startup only, once per process, not reload/new/resume/fork. Main outcomes use settled-run evidence; `agent_end` is not success. Attention is an active main-run edge from the existing explicit intervention lifecycle (`herdr:blocked`), not every dialog. Subagent waiting does not imply attention. Restored tasks/history and unchanged snapshots are silent. `context.high` is a local runtime signal from the context-usage probe, never a producer bus event, and fires at most once per high episode.
33
+
34
+ **Shutdown limitation:** `session.shutdown` remains in the schema for compatibility but is excluded from the runtime/UI catalog. Lazy playback cannot reliably finish during immediate cleanup without delaying exit. The historical best-effort proposal is not a promise of a quit sound; shutdown cancels audio instead.
35
+
36
+ ## Global configuration
37
+
38
+ Only `<gentlePiConfigHome()>/notifications.json` is read. It normally resolves to `~/.pi/gentle-ai/notifications.json`; `GENTLE_PI_CONFIG_HOME` overrides the directory. No repository override can activate audio. Missing configuration reads the preset with `enabled: false`, without creating a file. Saved files are strict, not merged with defaults: omitted event keys and `null` both mean silence, including after upgrades.
39
+
40
+ Complete default schema (the shutdown entry is inert):
41
+
42
+ ```json
43
+ {
44
+ "schema": "gentle-shell.notifications/v1",
45
+ "enabled": false,
46
+ "audio": {
47
+ "backend": "auto",
48
+ "minimumIntervalMs": 1000,
49
+ "coalesceWindowMs": 300,
50
+ "events": {
51
+ "session.started": null,
52
+ "session.shutdown": null,
53
+ "agent.started": null,
54
+ "agent.completed": "builtin:success",
55
+ "agent.failed": "builtin:error",
56
+ "agent.cancelled": null,
57
+ "agent.attention": "builtin:attention",
58
+ "context.high": "builtin:attention",
59
+ "subagent.queued": null,
60
+ "subagent.running": null,
61
+ "subagent.waiting": null,
62
+ "subagent.completed": "builtin:success",
63
+ "subagent.failed": "builtin:error",
64
+ "subagent.cancelled": null,
65
+ "subagent.timed_out": "builtin:error"
66
+ }
67
+ }
68
+ }
69
+ ```
70
+
71
+ Unknown keys/schema/events are rejected. `enabled` must be boolean; backend must be `auto`; timing values are integer milliseconds: minimum interval 0–60000, coalesce window 0–2000, inclusive. Zero disables that timing window, not the TTL. Writes use an exclusive 0600 temporary file beside the target followed by atomic rename. Changes apply to the live owner immediately and invalidate stale pending mappings. Direct external edits are read on the next session attachment/reload, not polled in the background. A file saved before `context.high` existed keeps that event silent; selecting a sound on its Advanced row is the only explicit way to enable it.
72
+
73
+ ## Local WAV security
74
+
75
+ Builtins `success`, `error`, `attention` are original synthetic tones under the [MIT license, provenance and reproduction recipe](../assets/sounds/LICENSE.md).
76
+
77
+ Enter a **literal absolute local path** in the file dialog (without the `file:` prefix). JSON references use `file:/absolute/path/my sound.wav`. Spaces and punctuation are literal; no shell interprets them. No URLs, UNC/network or device paths, relative paths, `~`, environment expansion, commands or configurable player executables. Selection and playback both validate; extension alone does not prove format.
78
+
79
+ Allowed content: RIFF/WAVE integer PCM (format 1), mono or stereo, 8/16/24/32-bit, 8000–192000 Hz, nonempty aligned data, coherent chunk bounds/padding and rate metadata; maximum **2 MiB** and **10 seconds**. Compressed/float/extensible WAV is not accepted. The final source must be a readable regular file, not a symlink or FIFO. No-follow/nonblocking descriptor opening, bounded reads and WAV validation fail closed. Intermediate directories are not a sandbox against other same-user filesystem writers.
80
+
81
+ Playback revalidates and snapshots the bytes in a private 0700 temporary directory with an exclusive 0600 file named for the validated format, then selects a backend **after** the format is known: native WAV first on Linux, otherwise the trusted absolute CLI with separate literal argv and `shell:false`. Source changes after selection cannot substitute unchecked playback bytes. A format no available backend supports is rejected before any snapshot or spawn. A native failure after a spawn is never retried through the CLI, so partial audio cannot duplicate. Abort/timeout kills the child/worker; the serial reservation is held until close and cleanup, not merely until kill was requested. Playback timeout is 11000 ms (native bridge + socket + owned Node): the validated 10 s duration limit plus a 1 s termination margin. OS-denied termination/cleanup cannot be guaranteed by mocks.
82
+
83
+ ## Noise and retention
84
+
85
+ Only the primary **TUI** owner plays. Child processes, print/JSON and **all RPC**, including interactive RPC hosts, are silent. The context visual warning shares that owner guard, so it is also primary-TUI only. There is no desktop notification or BEL fallback. Two independent Pi processes can overlap; serialization is per process.
86
+
87
+ Ráfagas coalesce into at most one pending candidate, in event priority order: failed/timed_out > main attention > completed > other. Changing the sound does not change event priority. Equal priority selects the latest sound but keeps the first coalesce deadline. Starts respect the minimum interval. Pending events have a **2000 ms** freshness budget (including slow discovery/validation and minimum-interval waits). That budget pauses only while another sound has actually started playing, so a long WAV does not silently discard the next candidate; it resumes with the remaining budget when playback settles. Already stale incoming events are still rejected. Waiting behind discovery that has not started playback does not pause expiry. There is still only one pending candidate, not a growing queue. Preview remains subject to context, file validation, serialization and timeout.
88
+
89
+ The scheduler keeps a bounded 256-identity FIFO. The owner additionally retains the highest sequence **per producer/run** for the active parent session, across reload, preventing old wire duplicates after FIFO eviction. This map is not size-capped: it costs O(distinct runs) during a long session, is cleared when attaching a different session ID, and disappears on process exit. The actual TaskStore producer increments a store-global sequence on each status change, but current retention is still keyed per run; no producer-wide compaction is claimed here. Muted/off occurrences are consumed, not buffered.
90
+
91
+ ## Runtime backend selection
92
+
93
+ | Format | Plain Linux | WSL (Windows interop) | Native Windows | macOS |
94
+ | --- | --- | --- | --- | --- |
95
+ | WAV | Native Pulse backend (preferred); trusted CLI fallback | Windows `SoundPlayer` through the derived `\\wsl.localhost\<distro>\...` UNC (preferred); trusted Linux CLI fallback | Windows `SoundPlayer` via the fixed `C:\Windows\...\powershell.exe` host | `/usr/bin/afplay` (legacy) |
96
+ | OGG / FLAC | Legacy CLI: first of `/usr/bin/paplay`, `/usr/bin/pw-play`, `/usr/bin/aplay` that supports it | Same trusted Linux CLI | Unsupported | `afplay` supports FLAC; OGG unverified |
97
+
98
+ Capabilities are aggregated, not replaced: a native WAV backend never removes the CLI OGG/FLAC capability. `availability` and `capabilities` discover only on an explicit request, never on import, render, or while audio is off. Selection is pure and IO-free (`createDefaultNotificationBackend`): `win32` and a valid WSL interop environment take the Windows adapter, every other platform keeps the local Pulse bridge, whose target is unavailable on macOS so `afplay` owns playback. On plain Linux the native backend probes the local Unix socket once per discovery and requires a default sink; when it is unavailable the CLI is used, and the probe result is cached until the owner is rebuilt. The WSL route uses only the default `/mnt/c` automount and the standard `C:\Windows` root: a non-standard mount or root, a missing `/run/WSL/*_interop` socket, or a failed read-only probe falls back to the trusted Linux CLI **before** any playback — there is deliberately no automatic Pulse fallback on WSL (a silent Pulse path is avoided) and no arbitrary binary, configurable route or route scheme. Native codecs (OGG/FLAC) are a future phase; own CoreAudio (macOS) and WASAPI (Windows) phases are planned. No system players are installed automatically and no new package dependency is added.
99
+
100
+ ## Platforms and manual verification
101
+
102
+ Physical listening, UI, reload and quit remain **PENDING / UNVERIFIED** on every platform. The Linux/WSLg native path reached a real read-only Pulse `AUTH`/ServerInfo probe with a default sink (not a physical-listen claim); the WSL and native Windows routes use the system `SoundPlayer` for WAV and need no separate WASAPI phase, while Windows OGG/FLAC stays unsupported. macOS still uses `afplay` for WAV and FLAC while its own CoreAudio phase is planned. No physical playback or audible evidence is claimed for any route.
103
+
104
+ No system dependencies are installed automatically. No usable backend produces silence plus a bounded local warning, not an agent failure. SSH and containers play on the process host, not necessarily your client; an executable may exist without a usable device/server. Automated tests use injected clocks/processes and WAV validation; they do **not** establish physical audio or manual TUI correctness.
105
+
106
+ Manual acceptance remains pending for every applicable platform:
107
+
108
+ - [ ] Navigate customize → Notifications in narrow/wide, regular/fullscreen terminals; cancel every inline field and confirmation. Verify Enter, `f` and `p` stay inside the same card and never open another menu.
109
+ - [ ] Assign a valid local WAV with spaces via `f` to one type; confirm the other types keep their own sounds, preview off/muted with `p`, enable, verify live outcomes and independent mappings; verify bad files and consent cancellation preserve bytes.
110
+ - [ ] Mute and reload/change session, then resume without replay; confirm no probe while off unless explicitly requested.
111
+ - [ ] Quit/reload during probe, validation and active playback: no late spawn, overlap, stale write, leaked process or delayed exit.
112
+ - [ ] Listen to builtin/custom tones and exercise missing player, failed player and hanging player on the real host.
113
+
114
+ Implementation progress and automated evidence live in the [ODD task](../odd/tasks/sound-notifications.md). Full closure and manual acceptance are not inferred from the mock suite.
package/docs/yolo-mode.md CHANGED
@@ -1,19 +1,19 @@
1
- # Session-only YOLO permission
1
+ # YOLO permission
2
2
 
3
3
  > 🚀 **Full speed, destructive actions still ask.** YOLO lets the agent implement, commit, push and open PRs within the already authorized task without asking each time, which suits long autonomous runs. Destructive operations still require fresh confirmation.
4
4
 
5
- Use `/gentle:yolo enable` in the interactive primary Pi TUI to stop repeated permission questions for ordinary work **within your already authorized task**. YOLO defaults **OFF**. The active status and a separate editor widget both say **🚀 YOLO ON 🔥 — destructive confirmations remain**, even when Gentle Shell hides its status layout.
5
+ Use `/gentle:yolo enable` in the interactive primary Pi TUI to stop repeated permission questions for ordinary work **within your already authorized task**. YOLO is **OFF** unless you select it or save YOLO as the user-global default. [Normal, Auto and global defaults](permission-modes.md) are managed separately from the live-session toggle. The active status and a separate editor widget both say **🚀 YOLO ON 🔥 — destructive confirmations remain**, even when Gentle Shell hides its status layout.
6
6
 
7
7
  | Command | Effect |
8
8
  | --- | --- |
9
- | `/gentle:yolo enable` | Activate for this live session and Git clone. |
10
- | `/gentle:yolo disable` | Revoke immediately and clear the indicators. |
9
+ | `/gentle:yolo enable` | Select YOLO for this live session and workspace/clone. |
10
+ | `/gentle:yolo disable` | Select Normal immediately and clear the YOLO indicators; saved defaults stay unchanged. |
11
11
  | `/gentle:yolo status` | Show the current state without activating. |
12
12
  | `/gentle:yolo` | Open a menu titled **🚀 Gentle YOLO 🔥 — full speed, destructive actions still ask (current: ON\|OFF)** with `enable`, `disable` and `status`. Cancelling changes nothing. Without an interactive menu UI it behaves like `status`. |
13
13
 
14
14
  Invalid arguments leave state unchanged.
15
15
 
16
- The Session command palette also includes YOLO. Activation fails closed without an identifiable Git clone, interactive TUI or live session identity. There is no YOLO environment variable, persisted configuration or model-callable activation tool.
16
+ The Session command palette also includes YOLO. Interactive selection requires an eligible primary TUI, live session identity and identifiable workspace. Outside Git, the canonical workspace directory supplies identity. There is no model-callable activation tool. `/gentle:mode default yolo` optionally saves a trusted user-global default for new primary sessions; `/gentle:mode default normal` removes that elevated default. Neither command changes the current mode.
17
17
 
18
18
  ## Configuration menu path
19
19
 
@@ -21,15 +21,15 @@ The Session command palette also includes YOLO. Activation fails closed without
21
21
  2. Select **YOLO: OFF · session only**, immediately after the Vim enable/disable rows.
22
22
  3. Press **Enter** or **Space** to toggle the same permission as `/gentle:yolo`. The row updates to **YOLO: ON · session only**; slash changes and revocation also update an open menu.
23
23
 
24
- Navigation, the read-only preview and Escape never grant permission. The preview reminds you that ordinary scoped commits/push/PR are covered, destructive confirmations remain, review consent is unchanged and reload resets the grant. **UNAVAILABLE** means the live primary owner or eligible session/clone cannot be used; selecting it cannot activate YOLO.
24
+ Navigation, the read-only preview and Escape never grant permission. The preview reminds you that ordinary scoped commits/push/PR are covered, destructive confirmations remain, review consent is unchanged and reload resets the live grant. **UNAVAILABLE** means the live primary owner or eligible session/workspace cannot be used; selecting it cannot activate YOLO.
25
25
 
26
- Unlike Vim, this control does not write a global/repository preference, visual profile, prompt-history preference or guardrail setting. Closing the menu removes its observers and cancels unfinished menu activation; it does not revoke an already completed activation. Reload or session replacement invalidates old menu callbacks and resets the permission.
26
+ The live YOLO toggle does not save preferences. The separate **Default permissions** rows can save Normal, Auto or YOLO in the dedicated user-global permission store, never a repository preference or visual profile. **Session permissions** selects the current mode without changing that default. Closing the menu removes its observers and cancels unfinished menu activation; it does not revoke an already completed activation. Reload or session replacement invalidates old menu callbacks and resets the live permission.
27
27
 
28
28
  ## What activation authorizes
29
29
 
30
30
  YOLO supplies standing human permission for ordinary already-scoped implementation, checks, commits, non-force pushes and PR creation. Its active-only system instruction qualifies the default commit/push/PR confirmation clauses; it also tells the primary agent to make ordinary reversible implementation choices without needless interviews.
31
31
 
32
- Only a single plain `git push` can skip the shell guard's routine default confirmation. Simple remote/ref arguments and `-u`/`--set-upstream` are eligible. Compound commands, wrappers, repository-changing options and other push options conservatively retain normal guard behavior. Full command evaluation, including the recognized data-loss guards, runs first. Explicit push confirmations or blocks in either configuration layer remain restrictions, including when legacy persistent autonomy or its environment override would ignore them. YOLO never changes persistent `autonomousMode`.
32
+ The shell guard's routine default confirmation is skipped for reversible delivery only. Every guarded segment of the command is judged on its own, so `git commit -m "..." && git push -u origin feature`, `git push && gh pr create --fill`, `git -C <dir> push origin main` and `git fetch && git rebase origin/main && git push` run without a prompt, while the other segments keep their ordinary guard (`git push && rm -rf data` still asks for the `rm`). A push segment is eligible with plain remote/ref arguments, `src:dst` refspecs with both sides present, and the options `-u`/`--set-upstream`, `-q`/`--quiet`, `-v`/`--verbose`, `--tags`, `--follow-tags`, `--no-verify` and `--porcelain`. A rebase segment is eligible with plain refs, `--onto`, `--continue`, `--abort`, `--skip` and `--autostash`; it is recoverable from the reflog. Anything that deletes or rewrites a remote ref, publishes, or runs arbitrary commands never qualifies: `--delete`/`-d`, `:branch` and `+branch` refspecs, `--mirror`, `--prune`, `--all`, every force spelling (hard-blocked), `--receive-pack`/`--exec`, `--repo`, `-o`, `sudo`, shell wrappers such as `sh -c`, interactive or `--exec` rebases, `git branch -D`, `pi remove` and `npm publish`. Full command evaluation, including the recognized data-loss guards, runs first. Explicit push or rebase confirmations or blocks in either configuration layer remain restrictions, including when legacy persistent autonomy or its environment override would ignore them. YOLO never changes persistent `autonomousMode`.
33
33
 
34
34
  ## What still requires a decision
35
35
 
@@ -42,9 +42,9 @@ Children retain only their bounded delegated scope. They cannot activate or inhe
42
42
 
43
43
  ## Lifetime and limits
44
44
 
45
- Permission is in memory in the extension instance, bound to the exact live SessionManager, session ID and canonical Git common-directory identity. Sibling worktrees in one clone may retain it; an unrelated clone or session identity cannot. Scope loss revokes rather than hiding permission until you return.
45
+ Live permission is held in the extension instance, bound to the exact live SessionManager, session ID and canonical Git common-directory identity, or canonical workspace directory outside Git. Sibling worktrees in one clone may retain it; an unrelated workspace or session identity cannot. Scope loss revokes rather than hiding permission until you return.
46
46
 
47
- New, resumed, forked or replaced sessions, shutdown/quit, **reload** and process restart reset YOLO to OFF. Re-activate explicitly after reload. No session entry restores a grant.
47
+ Shutdown, **reload** and session replacement revoke live grants and callbacks. New primary session instances may apply a saved global YOLO default; they never restore a grant from transcript entries. An explicit Normal selection wins over that default in the current session. To keep both this session and future sessions in Normal, use `/gentle:yolo disable` and `/gentle:mode default normal`.
48
48
 
49
49
  This is permission guidance and shell-guard defense in depth, **not a sandbox or an all-tools safety guarantee**. Detection only covers recognized command forms; scripts, custom tools and prompt injection can bypass semantic guidance. Tools and extensions retain the operating-system permissions of the process. Trusted SDK callers can invoke command handlers and supply interactive contexts; the human command path is not an OS security boundary against those callers. Use OS/container isolation and narrowly scoped credentials when you need an actual containment boundary.
50
50
 
@@ -79,6 +79,7 @@ Children receive the lightweight `child-safety.ts` entry alongside `child-contex
79
79
  ### Detection limitations
80
80
 
81
81
  - This is deterministic lexical recognition, **not** shell or SQL evaluation. Aliases, functions, dynamically assembled commands, variable/command expansion inside quoted payloads, unusual wrapper flags, complex heredocs and deeply nested wrappers can evade recognition. Simple recursive removal of a variable target is guarded, but its expanded target cannot reliably be identified as a hard-deny path.
82
+ - Guarded-command confirmations and hard-denied patterns ignore text that only appears as an argument of a known data command (`grep`, `rg`, `cat`, `echo`, `printf`, `head`, `tail`, `jq`, `sort`, `uniq`, `wc` and similar), including the body of a real heredoc fed to one. Searching a file for a push or printing a reset command does not open a dialog. The exemption applies only when every command in the line is such a data command or an inert one (`cd`, `pwd`, `test`, `mkdir`, `touch`), optionally after plain `VAR=value` assignments or a flagless `env`. Anything else anywhere in the line keeps the full lexical match: any other command or wrapper (`sed`, `sh`, `python`, `awk`, `xargs`, `sudo`, `exec`, `at`, `./script`), command or process substitution, a `<<` that is not an unquoted heredoc, and quoting the tokenizer cannot account for. `sed` is excluded because GNU sed can execute its script.
82
83
  - Scripts, migration files, redirected SQL files, arbitrary interpreter programs (Python/Node/etc.), encoded payloads and remote execution are not inspected. Non-recursive wildcard deletion, file truncation, other database clients and nontrivial tautological SQL predicates are not comprehensively classified. A `WHERE` clause is not proof of bounded impact.
83
84
  - Only `bash` tool calls reach this data-loss boundary, including nested calls dispatched through Pi's tool-event pipeline. Direct process execution, user shell commands, MCP tools and other tools are not covered by these hooks.
84
85
  - The older primary regex safeguards remain authoritative and may be more conservative about text than the shared recognizer. Missing or explicitly overridden child extension paths remove the lightweight boundary; a valid package installation must include the safety entry.
@@ -2,6 +2,7 @@ import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-a
2
2
  import { DynamicBorder } from "@earendil-works/pi-coding-agent";
3
3
  import { Container, Input, isKeyRelease, matchesKey, Text, type KeybindingsManager, type TuiMouseEvent } from "@earendil-works/pi-tui";
4
4
  import { type Static, Type } from "typebox";
5
+ import { captureChoiceAnswer } from "../lib/auto-permission-answers.ts";
5
6
  import { NativeChoiceList } from "../lib/native-choice-list.ts";
6
7
  import { createNativeFullscreenInteraction } from "../lib/native-fullscreen-interaction.ts";
7
8
  import { isInteractiveMode, isInteractiveRpcHost } from "../lib/rpc-host.ts";
@@ -226,6 +227,7 @@ export default function askUserChoice(pi: ExtensionAPI): void {
226
227
  parameters: ChoiceParamsSchema,
227
228
  executionMode: "sequential",
228
229
  async execute(_toolCallId, params: ChoiceParams, _signal, _onUpdate, ctx) {
230
+ const captureAnswer = captureChoiceAnswer(ctx, _toolCallId, params, _signal);
229
231
  if (ctx.mode !== "tui") {
230
232
  if (!isInteractiveRpcHost(ctx.mode, process.env)) {
231
233
  throw new Error("ask_user_choice is unavailable outside the interactive TUI");
@@ -238,6 +240,7 @@ export default function askUserChoice(pi: ExtensionAPI): void {
238
240
  finally {
239
241
  pi.events.emit(ASK_USER_CHOICE_BLOCKED_EVENT, { active: false });
240
242
  }
243
+ captureAnswer(rpcSelection);
241
244
  return choiceToolResult(params, rpcSelection);
242
245
  }
243
246
 
@@ -302,6 +305,7 @@ export default function askUserChoice(pi: ExtensionAPI): void {
302
305
  pi.events.emit(ASK_USER_CHOICE_BLOCKED_EVENT, { active: false });
303
306
  }
304
307
 
308
+ captureAnswer(selection);
305
309
  return choiceToolResult(params, selection);
306
310
  },
307
311
  renderCall(args, theme) {
@@ -1,6 +1,7 @@
1
1
  import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
2
2
  import { DynamicBorder } from "@earendil-works/pi-coding-agent";
3
3
  import { Text } from "@earendil-works/pi-tui";
4
+ import { captureQuestionnaireAnswers } from "../lib/auto-permission-answers.ts";
4
5
  import { createNativeFullscreenInteraction } from "../lib/native-fullscreen-interaction.ts";
5
6
  import { type QuestionData, type QuestionParams, QuestionParamsSchema } from "../lib/questionnaire/schema.ts";
6
7
  import {
@@ -264,11 +265,14 @@ export default function askUserQuestion(pi: ExtensionAPI): void {
264
265
  ): Promise<QuestionnaireToolResult> {
265
266
  const error = validateQuestionnaire(params);
266
267
  if (error) return invalidQuestionnaireResult(error);
268
+ const captureAnswers = captureQuestionnaireAnswers(ctx, _toolCallId, params, _signal);
267
269
  if (ctx.mode !== "tui") {
268
270
  if (!isInteractiveRpcHost(ctx.mode, process.env)) return unavailableResult();
269
271
  try {
270
272
  pi.events.emit(ASK_USER_QUESTION_BLOCKED_EVENT, { active: true });
271
- return await askThroughDialogs(ctx, params);
273
+ const result = await askThroughDialogs(ctx, params);
274
+ if (!result.details.cancelled) captureAnswers(result.details.answers);
275
+ return result;
272
276
  }
273
277
  finally {
274
278
  pi.events.emit(ASK_USER_QUESTION_BLOCKED_EVENT, { active: false });
@@ -307,6 +311,7 @@ export default function askUserQuestion(pi: ExtensionAPI): void {
307
311
  details: { cancelled: true },
308
312
  };
309
313
  }
314
+ captureAnswers(selection.answers);
310
315
  return {
311
316
  content: [{ type: "text", text: answersText(selection.answers) }],
312
317
  details: { answers: selection.answers },
@@ -1,13 +1,22 @@
1
1
  import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
2
  import { filterChildSessionContextFiles, type ContextFileOptions } from "../lib/child-context-files.ts";
3
+ import { REQUESTED_TOOLS_ENV } from "../lib/agents-runner.ts";
4
+ import { registerCodeGraphTool } from "./codegraph-tools.ts";
3
5
 
4
6
  // gentle-shell#1587: delegated children drop the orchestrator-only gentle-ai
5
7
  // managed blocks from their context files. Gentle Agents passes this file to
6
8
  // every child with --extension because children do not load the gentle-pi
7
- // package in the isolated Gentle Shell home. It registers one hook and has no
8
- // other side effects; outside a child session it is a no-op.
9
+ // package in the isolated Gentle Shell home. At startup it also supplies the
10
+ // existing CodeGraph implementation only when explicitly requested and absent
11
+ // (the full package already registers it). Outside a child session it is inert.
9
12
  export function createChildContextExtension(env: NodeJS.ProcessEnv = process.env): (pi: ExtensionAPI) => void {
10
13
  return (pi) => {
14
+ const requested = (env[REQUESTED_TOOLS_ENV] ?? "").split(",").map(name => name.trim());
15
+ if (env.GENTLE_PI_AGENTS_CHILD === "1" && requested.includes("codegraph")) {
16
+ pi.on("session_start", () => {
17
+ if (!pi.getAllTools().some(tool => tool.name === "codegraph")) registerCodeGraphTool(pi);
18
+ });
19
+ }
11
20
  pi.on("before_agent_start", (event) => {
12
21
  if (env.GENTLE_PI_AGENTS_CHILD !== "1") return undefined;
13
22
  // The filtered copies replace contextFiles on the same options object
@@ -1,4 +1,5 @@
1
1
  import type { ExtensionAPI, ToolCallEventResult } from "@earendil-works/pi-coding-agent";
2
+ import { SHELL_COMMAND_TOOLS } from "../lib/background-jobs.ts";
2
3
  import { recognizeDestructiveCommands } from "../lib/destructive-command-guard.ts";
3
4
 
4
5
  export function blockChildDestructiveCommand(command: string): ToolCallEventResult | undefined {
@@ -12,8 +13,9 @@ export function createChildSafetyExtension(env: NodeJS.ProcessEnv = process.env)
12
13
  return (pi) => {
13
14
  if (env.GENTLE_PI_AGENTS_CHILD !== "1") return;
14
15
  pi.on("tool_call", (event) => {
15
- if (event.toolName !== "bash" || typeof event.input.command !== "string") return undefined;
16
- return blockChildDestructiveCommand(event.input.command);
16
+ const command = (event.input as { command?: unknown }).command;
17
+ if (!SHELL_COMMAND_TOOLS.has(event.toolName) || typeof command !== "string") return undefined;
18
+ return blockChildDestructiveCommand(command);
17
19
  });
18
20
  };
19
21
  }