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
@@ -8,6 +8,52 @@ import { fileURLToPath } from "node:url";
8
8
  import { INSTALLER_VERSION, installGentleAi } from "./gentle-ai-installer.mjs";
9
9
  import { installTuiModeSetting, isPiManagedInstall } from "./install-tui-mode-setting.mjs";
10
10
 
11
+ const FAILURE_CAUSE_DEPTH = 6;
12
+ const FAILURE_OUTPUT_TAIL = 4000;
13
+
14
+ function failureOutputs(error) {
15
+ return ["stderr", "stdout"].map((stream) => [stream, typeof error?.[stream] === "string" ? error[stream].trimEnd() : ""]).filter(([, text]) => text.trim().length > 0);
16
+ }
17
+
18
+ function failureHeadline(error, outputs) {
19
+ const message = error instanceof Error ? error.message : String(error);
20
+ // A child-process error repeats its stderr after the first message line; it is printed below, bounded.
21
+ const text = outputs.length > 0 ? message.split(/\r?\n/)[0] : message;
22
+ const status = [
23
+ ...(typeof error?.code === "string" || typeof error?.code === "number" ? [`code ${error.code}`] : []),
24
+ ...(typeof error?.signal === "string" ? [`signal ${error.signal}`] : []),
25
+ ];
26
+ return `${text}${status.length > 0 ? ` (${status.join(", ")})` : ""}`;
27
+ }
28
+
29
+ /**
30
+ * A failed installation for the postinstall's stderr: the error's message, then its
31
+ * `cause` chain (at most 6 deep) with each code and the last 4000 characters of any
32
+ * stdout/stderr a failed command left on it. When a cause carried output, the last
33
+ * line repeats the deepest one's last output line in `Error:` form, the line the
34
+ * installer wizard's one-line failure detail selects after pnpm's own summary.
35
+ */
36
+ function describeGentleAiInstallFailure(error) {
37
+ const lines = [];
38
+ let rootCause = null;
39
+ let cause = error;
40
+ for (let depth = 0; cause !== undefined && cause !== null && depth <= FAILURE_CAUSE_DEPTH; depth += 1) {
41
+ const outputs = failureOutputs(cause);
42
+ const name = cause instanceof Error && typeof cause.name === "string" && cause.name !== "" ? cause.name : "Error";
43
+ lines.push(depth === 0 ? failureHeadline(cause, outputs) : ` caused by ${name}: ${failureHeadline(cause, outputs)}`);
44
+ for (const [stream, text] of outputs) {
45
+ const tail = text.length > FAILURE_OUTPUT_TAIL ? text.slice(-FAILURE_OUTPUT_TAIL) : text;
46
+ lines.push(` ${stream}${tail === text ? "" : ` (last ${FAILURE_OUTPUT_TAIL} characters)`}:`, ...tail.split(/\r?\n/).map((line) => ` | ${line}`));
47
+ }
48
+ // stderr first: a deeper cause's output replaces a shallower one's.
49
+ if (outputs.length > 0) rootCause = outputs[0][1].split(/\r?\n/).findLast((line) => line.trim().length > 0).trim();
50
+ cause = cause instanceof Error ? cause.cause : undefined;
51
+ }
52
+ if (cause !== undefined && cause !== null) lines.push(" ... further causes omitted");
53
+ if (rootCause !== null) lines.push(` root cause Error: ${rootCause}`);
54
+ return lines.join("\n");
55
+ }
56
+
11
57
  if (process.env.GENTLE_PI_SKIP_GENTLE_AI_INSTALL === "1") {
12
58
  console.warn("GENTLE_PI_SKIP_GENTLE_AI_INSTALL=1: skipped package-local Gentle AI installation; native review operations will fail with package-local-binary-missing until gentle-pi is reinstalled.");
13
59
  } else {
@@ -15,7 +61,8 @@ if (process.env.GENTLE_PI_SKIP_GENTLE_AI_INSTALL === "1") {
15
61
  const result = await installGentleAi();
16
62
  console.log(`Gentle AI v${INSTALLER_VERSION} ${result.installed ? "installed" : "integrity-verified"} at ${result.binaryPath}`);
17
63
  } catch (error) {
18
- console.error(`gentle-pi could not install its package-local Gentle AI v${INSTALLER_VERSION} binary: ${error instanceof Error ? error.message : String(error)}`);
64
+ // The whole cause chain: the failing command's own output is the diagnosis.
65
+ console.error(`gentle-pi could not install its package-local Gentle AI v${INSTALLER_VERSION} binary: ${describeGentleAiInstallFailure(error)}`);
19
66
  process.exitCode = 1;
20
67
  }
21
68
  }
@@ -65,6 +65,15 @@ function sameFile(left, right) {
65
65
  return left && right && left.dev === right.dev && left.ino === right.ino;
66
66
  }
67
67
 
68
+ // A path's lstat against the fstat of the handle just opened on it. On recent
69
+ // Windows, lstat by path reports dev 0 (no volume serial) while fstat reports
70
+ // the volume's (#1258, #2109): there the file index alone identifies it, and a
71
+ // known dev must still match. POSIX keeps the full device and inode check.
72
+ export function sameOpenedFile(pathStat, handleStat, platform = process.platform) {
73
+ if (platform !== "win32" || !pathStat || !handleStat || (pathStat.dev !== 0 && handleStat.dev !== 0)) return Boolean(sameFile(pathStat, handleStat));
74
+ return pathStat.ino === handleStat.ino;
75
+ }
76
+
68
77
  function assertDirectories(paths) {
69
78
  for (const path of paths) {
70
79
  const stat = inspect(path);
@@ -80,7 +89,7 @@ function readSettings(path) {
80
89
  if (!before.isFile() || before.isSymbolicLink()) throw new Error("settings.json must be a regular, non-symlink file");
81
90
  const fd = openSync(path, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0));
82
91
  try {
83
- if (!sameFile(before, fstatSync(fd))) throw new Error("settings.json changed while opening");
92
+ if (!sameOpenedFile(before, fstatSync(fd))) throw new Error("settings.json changed while opening");
84
93
  const text = readFileSync(fd, "utf8");
85
94
  const value = JSON.parse(text.replace(/^\uFEFF/, ""));
86
95
  if (value === null || typeof value !== "object" || Array.isArray(value)) throw new Error("settings.json must contain a JSON object");
@@ -0,0 +1,154 @@
1
+ #!/usr/bin/env node
2
+ // Development preview for the browser installation wizard.
3
+ //
4
+ // Starts the REAL local host (createInstallerServer) with the real assets, but
5
+ // with fake inventories and a fake runner: it never runs host probes, package
6
+ // managers, downloads or installs. Use it to develop and visually check the UI:
7
+ //
8
+ // node scripts/install-wizard-preview.mjs --scenario=terminal --step-ms=600
9
+ //
10
+ // Then open the printed one-time session URL. Not part of the installer entry.
11
+
12
+ import { fileURLToPath, pathToFileURL } from "node:url";
13
+ import { PI_INSTALL_VERSION, planPreflight, requirements } from "./installer-preflight.mjs";
14
+ import { createInstallerServer } from "./installer-server.mjs";
15
+
16
+ const BIN = "/home/you/.local/share/pnpm/bin";
17
+ const baseInventory = Object.freeze({
18
+ platform: "linux",
19
+ arch: "x64",
20
+ node: { available: true, version: "24.21.0", usable: true, persistent: true, npm: true },
21
+ pnpm: { available: true, version: "11.1.1", usable: true, compatible: true, persistent: true },
22
+ pi: { available: false },
23
+ shell: { available: false },
24
+ gentleAi: { available: false },
25
+ go: { available: false },
26
+ globalBin: { available: true, path: BIN, writable: true, onPath: true },
27
+ setup: false,
28
+ });
29
+ // A machine that only has the bootstrap's temporary Node and pnpm, with no pnpm bin on PATH.
30
+ const freshInventory = Object.freeze({
31
+ ...baseInventory,
32
+ node: { available: true, version: "24.21.0", usable: true, persistent: false, npm: false },
33
+ pnpm: { available: true, version: "11.1.1", usable: true, compatible: true, persistent: false },
34
+ globalBin: { ...baseInventory.globalBin, onPath: false },
35
+ });
36
+ // An earlier run installed the pinned stack, but its setup and `pnpm setup` did not finish.
37
+ const recoveryInventory = Object.freeze({
38
+ ...baseInventory,
39
+ pi: { available: true, version: PI_INSTALL_VERSION, usable: true },
40
+ shell: { available: true, version: requirements.shell, usable: true, global: true },
41
+ gentleAi: { available: true, version: requirements.gentleAi, usable: true, compatible: true },
42
+ globalBin: { ...baseInventory.globalBin, onPath: false },
43
+ setup: { available: true, recoverable: true },
44
+ });
45
+ const checks = ["check-npm", "check-global-bin", "check-existing-stack"];
46
+ const install = ["install-global", "verify-global-list", "verify-shell-bin", "verify-gentle-ai", "shell-setup"];
47
+ const persistence = ["persist-node", "persist-package-managers", "verify-persistent-runtime", "check-npm", "configure-npm-prefix"];
48
+
49
+ // Each scenario mirrors the runner's fixed step order for its plan.
50
+ const scenarios = Object.freeze({
51
+ ready: { inventories: [baseInventory], steps: [...checks, ...install], result: { outcome: "ready" } },
52
+ terminal: {
53
+ inventories: [freshInventory],
54
+ steps: ["check-global-bin", "check-existing-stack", ...persistence, ...install, "persist-path"],
55
+ result: { outcome: "terminal-action-required", action: "open-new-terminal", npmPrefix: "configured" },
56
+ },
57
+ blocked: {
58
+ inventories: [baseInventory],
59
+ steps: ["check-npm", "check-global-bin"],
60
+ result: { outcome: "blocked", reason: "existing-stack" },
61
+ },
62
+ failed: {
63
+ inventories: [freshInventory],
64
+ steps: ["check-global-bin", "check-existing-stack", ...persistence],
65
+ result: { outcome: "failed", failedStep: "install-global" },
66
+ },
67
+ // The first plan goes stale before install (the PATH was fixed meanwhile): the host
68
+ // answers 409 plan-changed and the wizard must show the new plan and ask again.
69
+ "plan-changed": { inventories: [freshInventory, baseInventory], steps: [...checks, ...install], result: { outcome: "ready" } },
70
+ recovery: {
71
+ inventories: [recoveryInventory],
72
+ steps: ["check-npm", "check-global-bin", "check-recoverable-stack", ...install.slice(1), "persist-path"],
73
+ result: { outcome: "terminal-action-required", action: "open-new-terminal" },
74
+ },
75
+ preflight: {
76
+ inventories: [{ ...baseInventory, node: { available: true, version: "18.20.0", usable: true, persistent: true, npm: true },
77
+ gentleAi: { available: true, version: "1.0.0", usable: true, compatible: false } }],
78
+ steps: [],
79
+ result: { outcome: "blocked", reason: "preflight-blocked" },
80
+ },
81
+ });
82
+ export const scenarioNames = Object.freeze(Object.keys(scenarios));
83
+
84
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
85
+
86
+ /** Fake collectPlan/runInstall for a scenario; nothing touches the machine. */
87
+ export function previewScenario(name, { stepMs = 600 } = {}) {
88
+ const scenario = scenarios[name];
89
+ if (!scenario) throw new Error(`Unknown scenario "${name}". Use one of: ${scenarioNames.join(", ")}`);
90
+ let collected = 0;
91
+ return {
92
+ collectPlan: async () => {
93
+ const inventory = structuredClone(scenario.inventories[Math.min(collected, scenario.inventories.length - 1)]);
94
+ collected += 1;
95
+ await sleep(Math.min(stepMs, 400));
96
+ return { inventory, plan: planPreflight(inventory) };
97
+ },
98
+ runInstall: async (_request, log) => {
99
+ const completed = [];
100
+ for (const step of scenario.steps) {
101
+ await sleep(stepMs);
102
+ completed.push(step);
103
+ log({ step, status: "done" });
104
+ }
105
+ await sleep(stepMs);
106
+ const { result } = scenario;
107
+ if (result.outcome === "blocked") log({ step: "gate", status: "blocked", reason: result.reason });
108
+ if (result.outcome === "failed") log({ step: result.failedStep, status: "failed" });
109
+ return { ...result, completed };
110
+ },
111
+ };
112
+ }
113
+
114
+ /** Starts the real host on 127.0.0.1 with a fake scenario. Returns { host, url }. */
115
+ export async function startPreview({ scenario = "ready", stepMs = 600, log = console.log } = {}) {
116
+ const fake = previewScenario(scenario, { stepMs });
117
+ const host = createInstallerServer({
118
+ assetsDir: fileURLToPath(new URL("../assets/install-wizard/", import.meta.url)),
119
+ collectPlan: fake.collectPlan,
120
+ runInstall: fake.runInstall,
121
+ });
122
+ const { url } = await host.listen();
123
+ log(`Gentle Shell wizard preview (scenario: ${scenario}). Fake plan and fake installer: nothing is installed.`);
124
+ log(`Open this one-time link (expires in 2 minutes):\n ${url}`);
125
+ return { host, url };
126
+ }
127
+
128
+ function option(args, name, fallback) {
129
+ const found = args.find((arg) => arg.startsWith(`--${name}=`));
130
+ return found === undefined ? fallback : found.slice(name.length + 3);
131
+ }
132
+
133
+ async function main(args) {
134
+ if (args.includes("--help")) {
135
+ console.log(`Usage: node scripts/install-wizard-preview.mjs [--scenario=${scenarioNames.join("|")}] [--step-ms=600]`);
136
+ return;
137
+ }
138
+ const scenario = option(args, "scenario", "ready");
139
+ const stepMs = Number(option(args, "step-ms", "600"));
140
+ if (!scenarioNames.includes(scenario) || !Number.isFinite(stepMs) || stepMs < 0) {
141
+ console.error(`Use --scenario=${scenarioNames.join("|")} and a non-negative --step-ms.`);
142
+ process.exitCode = 2;
143
+ return;
144
+ }
145
+ const { host } = await startPreview({ scenario, stepMs });
146
+ process.once("SIGINT", () => host.close("signal"));
147
+ process.once("SIGTERM", () => host.close("signal"));
148
+ const { reason, outcome } = await host.closed;
149
+ console.log(`Preview closed (${reason}); last outcome: ${outcome?.outcome ?? "none"}.`);
150
+ }
151
+
152
+ if (process.argv[1] !== undefined && import.meta.url === pathToFileURL(process.argv[1]).href) {
153
+ await main(process.argv.slice(2));
154
+ }