gentle-pi 4.2.0 → 4.4.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 (334) hide show
  1. package/README.md +340 -138
  2. package/assets/agents/gentle-ai-explore.md +1 -0
  3. package/assets/agents/gentle-ai-verify.md +6 -4
  4. package/assets/agents/gentle-ai-worker.md +7 -1
  5. package/assets/design-canvas/canvas.css +648 -0
  6. package/assets/design-canvas/canvas.js +1497 -0
  7. package/assets/design-canvas/index.html +88 -0
  8. package/assets/design-canvas/inspector.js +290 -0
  9. package/assets/orchestrator-delegation-reference.md +163 -0
  10. package/assets/orchestrator-delegation.md +25 -176
  11. package/assets/orchestrator-tracking.md +1 -1
  12. package/assets/orchestrator-verification.md +14 -8
  13. package/assets/orchestrator-writer.md +5 -1
  14. package/assets/orchestrator.md +11 -11
  15. package/bin/engram-guard +1 -1
  16. package/bin/gentle-shell.mjs +237 -139
  17. package/contracts/review-provider-contract-mirror/provider-contract.lock.json +8 -7
  18. package/contracts/review-provider-contract-mirror/{v1.3.0 → v1.4.0}/bundle/README.md +7 -0
  19. package/contracts/review-provider-contract-mirror/{v1.3.0 → v1.4.0}/bundle/manifest.json +11 -2
  20. package/contracts/review-provider-contract-mirror/v1.4.0/bundle/routing/pi.md +92 -0
  21. package/contracts/review-provider-contract-mirror/{v1.3.0 → v1.4.0}/generated/provider-capabilities.baseline.json +8 -1
  22. package/contracts/review-provider-contract-mirror/{v1.3.0 → v1.4.0}/generated/provider-roles.baseline.json +1 -1
  23. package/docs/assets/diagrams/agent-orchestration.svg +54 -15
  24. package/docs/assets/diagrams/gentleman-workflow.svg +69 -11
  25. package/docs/assets/diagrams/measured-routing.svg +49 -0
  26. package/docs/assets/diagrams/native-review.svg +52 -12
  27. package/docs/assets/diagrams/odd-workflow.svg +128 -66
  28. package/docs/assets/diagrams/permission-modes.svg +51 -0
  29. package/docs/assets/features/audio-notifications.png +0 -0
  30. package/docs/assets/features/command-palette.png +0 -0
  31. package/docs/bundled-install.md +65 -30
  32. package/docs/delegated-verification.md +16 -8
  33. package/docs/gentle-agents-activity.md +16 -6
  34. package/docs/gentle-music.md +61 -0
  35. package/docs/gentle-shell-uninstall.md +8 -1
  36. package/docs/gentle-shell.md +80 -9
  37. package/docs/install-wizard.md +37 -6
  38. package/docs/permission-modes.md +8 -3
  39. package/docs/readme-reference.md +120 -28
  40. package/docs/session-profile-format.md +26 -0
  41. package/docs/voice.md +259 -0
  42. package/docs/yolo-mode.md +38 -10
  43. package/extensions/ask-user-choice.ts +4 -1
  44. package/extensions/codegraph-tools.ts +68 -6
  45. package/extensions/gentle-agents.ts +270 -48
  46. package/extensions/gentle-ai.ts +490 -113
  47. package/extensions/gentle-design.ts +158 -0
  48. package/extensions/gentle-herdr-activity.ts +2 -3
  49. package/extensions/gentle-music.ts +289 -0
  50. package/extensions/gentle-shell.ts +359 -85
  51. package/extensions/gentle-todo.ts +43 -9
  52. package/extensions/gentle-voice.ts +11 -0
  53. package/extensions/quiet-tools.ts +1 -1
  54. package/extensions/session-scratch.ts +384 -0
  55. package/extensions/skill-registry.ts +63 -8
  56. package/extensions/startup-banner.ts +2 -3
  57. package/lib/agent-home.ts +8 -3
  58. package/lib/agent-profiles.ts +26 -0
  59. package/lib/agents-config.ts +35 -0
  60. package/lib/agents-protocol.ts +60 -1
  61. package/lib/agents-runner.ts +107 -9
  62. package/lib/agents-session-transport.ts +101 -6
  63. package/lib/agents-view.ts +3 -1
  64. package/lib/agents-widget.ts +14 -1
  65. package/lib/auto-permission-memory.ts +48 -18
  66. package/lib/auto-permission-runtime.ts +21 -6
  67. package/lib/bounded-writer-admission.ts +51 -0
  68. package/lib/clipboard-image.ts +147 -0
  69. package/lib/command-palette-catalog.ts +2 -4
  70. package/lib/commit-slice-signal.ts +100 -0
  71. package/lib/context-backstop.ts +120 -0
  72. package/lib/delivered-test-lint.ts +80 -0
  73. package/lib/design-canvas-server.ts +947 -0
  74. package/lib/design-comments.ts +437 -0
  75. package/lib/design-handoffs.ts +313 -0
  76. package/lib/design-open-browser.ts +58 -0
  77. package/lib/design-sources.ts +120 -0
  78. package/lib/destructive-command-guard.ts +120 -9
  79. package/lib/external-editor.ts +31 -0
  80. package/lib/gauge-theme.ts +146 -0
  81. package/lib/gentle-ai-binary.ts +28 -7
  82. package/lib/gentle-design.ts +513 -0
  83. package/lib/gentle-shell-bundled.ts +146 -36
  84. package/lib/gentle-shell-import-pi.ts +233 -0
  85. package/lib/gentle-shell-launcher.ts +154 -15
  86. package/lib/gentle-shell-startup-update.ts +61 -9
  87. package/lib/gentle-shell-uninstall.ts +51 -2
  88. package/lib/herdr-activity.ts +24 -0
  89. package/lib/image-attachments.ts +150 -0
  90. package/lib/inprocess-reviewer.ts +33 -2
  91. package/lib/nan-provider.ts +3 -0
  92. package/lib/native-review-cli.ts +20 -5
  93. package/lib/notification-audio-native.ts +149 -13
  94. package/lib/notification-audio.ts +4 -0
  95. package/lib/notification-pulse-worker.ts +82 -18
  96. package/lib/notification-service.ts +5 -1
  97. package/lib/orchestrator-discovery.ts +5 -1
  98. package/lib/orchestrator-presence.ts +87 -8
  99. package/lib/orchestrator-scope.ts +31 -3
  100. package/lib/orchestrator-state.ts +11 -3
  101. package/lib/permission-mode-policy.ts +2 -2
  102. package/lib/provider-contract-bundle.ts +99 -53
  103. package/lib/review-candidate-view-owner.ts +29 -19
  104. package/lib/review-candidate-view.ts +36 -2
  105. package/lib/review-host-relay.ts +11 -2
  106. package/lib/review-reminder-receipt.ts +24 -1
  107. package/lib/review-risk-assessment.ts +43 -38
  108. package/lib/review-session-standing-permission.ts +3 -1
  109. package/lib/session-profile-append-controller.ts +713 -0
  110. package/lib/session-profile-disk-reader.ts +182 -0
  111. package/lib/session-profile-freeze.ts +30 -1
  112. package/lib/session-profile-persistence.ts +15 -7
  113. package/lib/session-scratch.ts +523 -0
  114. package/lib/session-worktree-registry.ts +7 -0
  115. package/lib/shell-bar.ts +29 -28
  116. package/lib/shell-changes-view.ts +80 -13
  117. package/lib/shell-changes.ts +81 -5
  118. package/lib/shell-gauge.ts +49 -6
  119. package/lib/shell-prompt.ts +4 -4
  120. package/lib/shell-sidebar-layout.ts +26 -6
  121. package/lib/shell-todo.ts +24 -5
  122. package/lib/shell-usage-view.ts +5 -1
  123. package/lib/shell-usage.ts +7 -7
  124. package/lib/verifier-admission.ts +30 -0
  125. package/lib/vim-editor-adapter.ts +11 -8
  126. package/lib/voice-artifacts.ts +188 -0
  127. package/lib/voice-command.ts +576 -0
  128. package/lib/voice-install.ts +455 -0
  129. package/lib/voice-platform.ts +99 -0
  130. package/lib/voice-push-to-talk.ts +262 -0
  131. package/lib/voice-session.ts +460 -0
  132. package/lib/voice-settings.ts +50 -0
  133. package/lib/voice-ui.ts +158 -0
  134. package/lib/yolo-session-policy.ts +58 -22
  135. package/lib/yolo-temp-scratch.ts +69 -0
  136. package/package.json +1 -2
  137. package/runtime/gentle-ai-binary.mjs +28 -7
  138. package/runtime/gentle-shell-bundled.mjs +145 -35
  139. package/runtime/gentle-shell-import-pi.mjs +234 -0
  140. package/runtime/gentle-shell-launcher.mjs +152 -13
  141. package/runtime/gentle-shell-startup-update.mjs +61 -9
  142. package/runtime/gentle-shell-uninstall.mjs +51 -2
  143. package/runtime/native-review-cli.mjs +19 -4
  144. package/runtime/review-risk-assessment.mjs +43 -38
  145. package/scripts/build-runtime-modules.mjs +1 -0
  146. package/scripts/bundled-engram-migration.mjs +119 -0
  147. package/scripts/gentle-ai-installer.mjs +10 -10
  148. package/scripts/installer-downloads.mjs +7 -7
  149. package/scripts/installer-preflight.mjs +5 -3
  150. package/scripts/installer-server.mjs +14 -4
  151. package/scripts/installer-windows.mjs +37 -7
  152. package/scripts/main-channel.mjs +94 -19
  153. package/scripts/pi-update.mjs +34 -6
  154. package/scripts/run-test-suite.mjs +5 -0
  155. package/scripts/verify-package-files.mjs +43 -13
  156. package/scripts/voice-worker.cjs +476 -0
  157. package/skills/design/SKILL.md +110 -0
  158. package/skills/gentle-ai/SKILL.md +3 -3
  159. package/skills/work-unit-commits/SKILL.md +5 -3
  160. package/tests/agent-profiles.test.ts +24 -0
  161. package/tests/agent-risk-escalation.test.ts +37 -10
  162. package/tests/agents-config.test.ts +61 -0
  163. package/tests/agents-fake-child.ts +8 -1
  164. package/tests/agents-protocol.test.ts +32 -0
  165. package/tests/agents-runner.test.ts +485 -7
  166. package/tests/agents-session-transport.test.ts +53 -3
  167. package/tests/ask-user-choice.test.ts +30 -0
  168. package/tests/auto-mode.test.ts +17 -0
  169. package/tests/auto-permission-memory-diagnostics.test.ts +56 -0
  170. package/tests/auto-permission-runtime.test.ts +85 -1
  171. package/tests/autonomous-guard.test.ts +142 -0
  172. package/tests/bounded-writer-admission.test.ts +11 -3
  173. package/tests/bundled-install.test.ts +3 -3
  174. package/tests/card-content-policy.test.ts +19 -9
  175. package/tests/child-safety.test.ts +39 -0
  176. package/tests/clipboard-image.test.ts +114 -0
  177. package/tests/codegraph-tools.test.ts +123 -2
  178. package/tests/command-palette.test.ts +15 -5
  179. package/tests/commit-slice-signal.test.ts +162 -0
  180. package/tests/context-backstop.test.ts +225 -0
  181. package/tests/delegate-for-reason-contract.test.ts +92 -24
  182. package/tests/delivered-test-lint.test.ts +105 -0
  183. package/tests/design-canvas-assets.test.ts +710 -0
  184. package/tests/design-canvas-server.test.ts +1096 -0
  185. package/tests/design-comments.test.ts +201 -0
  186. package/tests/design-handoffs.test.ts +282 -0
  187. package/tests/design-open-browser.test.ts +70 -0
  188. package/tests/design-sources.test.ts +132 -0
  189. package/tests/destructive-command-guard.test.ts +85 -1
  190. package/tests/engram-safety.test.ts +132 -57
  191. package/tests/external-editor.test.ts +84 -0
  192. package/tests/fixtures/primary-session-prompt/gentleman.golden.md +143 -0
  193. package/tests/fixtures/provider-contract-bundle/v1.4.0/README.md +29 -0
  194. package/tests/fixtures/provider-contract-bundle/v1.4.0/manifest.json +83 -0
  195. package/tests/fixtures/provider-contract-bundle/v1.4.0/orchestration/pi.md +70 -0
  196. package/tests/fixtures/provider-contract-bundle/v1.4.0/routing/pi.md +92 -0
  197. package/tests/fixtures/provider-contract-bundle/v1.4.0/schemas/lens.schema.json +16 -0
  198. package/tests/fixtures/provider-contract-bundle/v1.4.0/schemas/refuter.schema.json +1 -0
  199. package/tests/fixtures/provider-contract-bundle/v1.4.0/schemas/targeted-validator.schema.json +1 -0
  200. package/tests/fixtures/provider-contract-bundle/v1.4.0/vectors/lens.json +1 -0
  201. package/tests/fixtures/provider-contract-bundle/v1.4.0/vectors/refuter.json +1 -0
  202. package/tests/fixtures/provider-contract-bundle/v1.4.0/vectors/targeted-validator.json +1 -0
  203. package/tests/gauge-theme.test.ts +120 -0
  204. package/tests/gentle-agents.test.ts +645 -21
  205. package/tests/gentle-ai-binary.test.ts +1 -1
  206. package/tests/gentle-ai-child-guards.test.ts +61 -0
  207. package/tests/gentle-ai-doctor-herdr.test.ts +94 -0
  208. package/tests/gentle-ai-installer.test.ts +51 -51
  209. package/tests/gentle-ai.test.ts +292 -13
  210. package/tests/gentle-design.test.ts +1313 -0
  211. package/tests/gentle-music.test.ts +335 -0
  212. package/tests/gentle-shell-bin.test.ts +163 -0
  213. package/tests/gentle-shell-bundled.test.ts +392 -176
  214. package/tests/gentle-shell-import-pi.test.ts +262 -0
  215. package/tests/gentle-shell-launcher.test.ts +107 -2
  216. package/tests/gentle-shell-startup-update.test.ts +77 -1
  217. package/tests/gentle-shell-uninstall.test.ts +89 -0
  218. package/tests/gentle-shell.test.ts +225 -17
  219. package/tests/gentle-todo.test.ts +190 -0
  220. package/tests/headless-delivery-question.test.ts +58 -0
  221. package/tests/herdr-activity.test.ts +34 -1
  222. package/tests/image-attachments.test.ts +119 -0
  223. package/tests/image-paste-chips.test.ts +236 -0
  224. package/tests/inprocess-reviewer.test.ts +55 -2
  225. package/tests/installer-bundles.test.ts +12 -6
  226. package/tests/installer-posix-bootstrap.test.ts +8 -8
  227. package/tests/installer-preflight.test.ts +16 -0
  228. package/tests/installer-server.test.ts +10 -2
  229. package/tests/installer-windows-bootstrap.test.ts +94 -7
  230. package/tests/installer-windows-diagnostics.test.ts +111 -0
  231. package/tests/main-channel-upgrade.test.ts +232 -2
  232. package/tests/main-channel.test.ts +140 -21
  233. package/tests/nan-provider.test.ts +36 -0
  234. package/tests/native-review-capability-contract.test.ts +17 -4
  235. package/tests/native-review-parity.test.ts +23 -2
  236. package/tests/no-self-pause-contract.test.ts +5 -2
  237. package/tests/notification-audio-native.test.ts +128 -9
  238. package/tests/notification-customize.test.ts +17 -5
  239. package/tests/odd-integration.test.ts +5 -1
  240. package/tests/odd-routing-canonical-ratchet.test.ts +128 -162
  241. package/tests/odd-routing-contract.test.ts +115 -30
  242. package/tests/orchestrator-budget.test.ts +22 -8
  243. package/tests/orchestrator-discovery.test.ts +29 -0
  244. package/tests/orchestrator-presence.test.ts +100 -2
  245. package/tests/orchestrator-rdd-ownership.test.ts +3 -1
  246. package/tests/orchestrator-scope.test.ts +80 -0
  247. package/tests/orchestrator-state.test.ts +29 -0
  248. package/tests/orchestrator-status-publication-contract.test.ts +12 -8
  249. package/tests/package-files.test.ts +34 -0
  250. package/tests/package-manifest.test.ts +24 -20
  251. package/tests/permission-mode-policy.test.ts +10 -1
  252. package/tests/pi-update-launcher.test.ts +21 -2
  253. package/tests/pi-update.test.ts +99 -4
  254. package/tests/primary-session-prompt.test.ts +101 -0
  255. package/tests/provider-contract-bundle.test.ts +118 -0
  256. package/tests/provider-contract-mirror.test.ts +24 -0
  257. package/tests/quiet-tool-rendering.test.ts +23 -0
  258. package/tests/rdd-aware-verification-contract.test.ts +29 -11
  259. package/tests/rdd-status-line.test.ts +79 -0
  260. package/tests/review-agent-end-preflight.test.ts +6 -0
  261. package/tests/review-candidate-view.test.ts +49 -0
  262. package/tests/review-contract-prompt.test.ts +5 -2
  263. package/tests/review-controller-native-routing.test.ts +14 -1
  264. package/tests/review-controller.test.ts +1 -1
  265. package/tests/review-host-relay-routing.test.ts +147 -3
  266. package/tests/review-host-relay.test.ts +9 -2
  267. package/tests/review-json-arguments.test.ts +20 -3
  268. package/tests/review-loadout-rdd-off-sdk.test.ts +258 -0
  269. package/tests/review-owner-identity.test.ts +132 -0
  270. package/tests/review-relay-transport-agent.test.ts +26 -0
  271. package/tests/review-reminder-receipt.test.ts +31 -1
  272. package/tests/review-risk-assessment.test.ts +163 -76
  273. package/tests/review-session-standing-permission-controller.test.ts +14 -1
  274. package/tests/review-session-standing-permission.test.ts +27 -1
  275. package/tests/run-test-suite.test.ts +15 -0
  276. package/tests/runtime-harness.mjs +16 -6
  277. package/tests/session-changes-shell.test.ts +1 -1
  278. package/tests/session-changes.test.ts +2 -1
  279. package/tests/session-profile-append-controller-fork.test.ts +458 -0
  280. package/tests/session-profile-append-controller-pi.test.ts +290 -0
  281. package/tests/session-profile-append-controller.test.ts +731 -0
  282. package/tests/session-profile-disk-reader-pi.test.ts +183 -0
  283. package/tests/session-profile-disk-reader.test.ts +311 -0
  284. package/tests/session-profile-freeze.test.ts +23 -0
  285. package/tests/session-scratch.test.ts +1011 -0
  286. package/tests/session-subject-routing-contract.test.ts +2 -1
  287. package/tests/session-worktree-registry.test.ts +13 -1
  288. package/tests/shell-bar.test.ts +21 -2
  289. package/tests/shell-changes-view.test.ts +137 -1
  290. package/tests/shell-changes.test.ts +148 -1
  291. package/tests/shell-gauge.test.ts +42 -0
  292. package/tests/shell-prompt.test.ts +3 -3
  293. package/tests/shell-render-cache.test.ts +134 -1
  294. package/tests/shell-sidebar-layout.test.ts +50 -0
  295. package/tests/short-check-routing-contract.test.ts +1 -1
  296. package/tests/skill-collision-prefixes.test.ts +3 -1
  297. package/tests/skill-registry-watcher.test.ts +17 -5
  298. package/tests/skill-registry.test.ts +47 -3
  299. package/tests/small-task-inline-contract.test.ts +37 -0
  300. package/tests/standalone-config-home.test.ts +324 -0
  301. package/tests/startup-banner.test.ts +5 -4
  302. package/tests/startup-home-repo.test.ts +34 -0
  303. package/tests/support/orchestrator-modules.ts +1 -0
  304. package/tests/task-size-routing-contract.test.ts +70 -10
  305. package/tests/test-scratch-contract.test.ts +102 -0
  306. package/tests/test-strength-contract.test.ts +36 -1
  307. package/tests/tool-batching-contract.test.ts +64 -0
  308. package/tests/verification-proportionality.test.ts +46 -0
  309. package/tests/verifier-admission.test.ts +154 -0
  310. package/tests/verify-agent-contract.test.ts +8 -8
  311. package/tests/voice-command.test.ts +773 -0
  312. package/tests/voice-install.test.ts +323 -0
  313. package/tests/voice-platform.test.ts +176 -0
  314. package/tests/voice-push-to-talk.test.ts +444 -0
  315. package/tests/voice-session.test.ts +434 -0
  316. package/tests/voice-settings.test.ts +49 -0
  317. package/tests/voice-ui.test.ts +97 -0
  318. package/tests/voice-worker.test.ts +445 -0
  319. package/tests/weak-model-economy-prompt.test.ts +32 -0
  320. package/tests/windows-hidden-processes.test.ts +30 -2
  321. package/tests/writer-edit-surface-scope.test.ts +3 -0
  322. package/tests/writer-feature-document-admission.test.ts +156 -0
  323. package/tests/yolo-customize.test.ts +5 -1
  324. package/tests/yolo-mode.test.ts +19 -1
  325. package/tests/yolo-session-policy-capture.test.ts +104 -0
  326. package/tests/yolo-temp-scratch.test.ts +71 -0
  327. package/scripts/mirror-odd-routing.mjs +0 -242
  328. /package/contracts/review-provider-contract-mirror/{v1.3.0 → v1.4.0}/bundle/orchestration/pi.md +0 -0
  329. /package/contracts/review-provider-contract-mirror/{v1.3.0 → v1.4.0}/bundle/schemas/lens.schema.json +0 -0
  330. /package/contracts/review-provider-contract-mirror/{v1.3.0 → v1.4.0}/bundle/schemas/refuter.schema.json +0 -0
  331. /package/contracts/review-provider-contract-mirror/{v1.3.0 → v1.4.0}/bundle/schemas/targeted-validator.schema.json +0 -0
  332. /package/contracts/review-provider-contract-mirror/{v1.3.0 → v1.4.0}/bundle/vectors/lens.json +0 -0
  333. /package/contracts/review-provider-contract-mirror/{v1.3.0 → v1.4.0}/bundle/vectors/refuter.json +0 -0
  334. /package/contracts/review-provider-contract-mirror/{v1.3.0 → v1.4.0}/bundle/vectors/targeted-validator.json +0 -0
@@ -0,0 +1,88 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <meta name="referrer" content="no-referrer">
7
+ <title>Gentle Design</title>
8
+ <link rel="stylesheet" href="{{BASE}}assets/canvas.css">
9
+ <script id="gd-config" type="application/json">{{CONFIG}}</script>
10
+ <script src="{{BASE}}assets/canvas.js" defer></script>
11
+ </head>
12
+ <body>
13
+ <header class="gd-bar" role="toolbar" aria-label="Design canvas controls">
14
+ <h1 class="gd-title" id="gd-title">Gentle Design</h1>
15
+ <label class="gd-field" id="gd-design-field">
16
+ <span class="gd-visually-hidden">Design</span>
17
+ <select id="gd-design" aria-label="Design"></select>
18
+ </label>
19
+ <p id="gd-feature" class="gd-feature" hidden></p>
20
+ <div class="gd-group" role="group" aria-label="Zoom">
21
+ <button type="button" id="gd-zoom-out" aria-label="Zoom out">&minus;</button>
22
+ <output id="gd-zoom-level" aria-live="polite" aria-label="Zoom level">100%</output>
23
+ <button type="button" id="gd-zoom-in" aria-label="Zoom in">+</button>
24
+ <button type="button" id="gd-fit">Fit</button>
25
+ </div>
26
+ <p id="gd-nav-mode" class="gd-nav-mode" role="status" aria-live="polite">Navigating</p>
27
+ <button type="button" id="gd-comment" class="gd-toggle" aria-pressed="false">Comment</button>
28
+ <div class="gd-group" role="radiogroup" aria-label="When a comment is sent to the session">
29
+ <label class="gd-radio"><input type="radio" name="gd-send-mode" id="gd-mode-send" value="send"> Send now</label>
30
+ <label class="gd-radio"><input type="radio" name="gd-send-mode" id="gd-mode-collect" value="collect"> Collect</label>
31
+ </div>
32
+ <button type="button" id="gd-send-all" disabled>Send all (0)</button>
33
+ <button type="button" id="gd-panel-toggle" class="gd-toggle" aria-pressed="true" aria-controls="gd-panel">Comments</button>
34
+ <p id="gd-status" class="gd-status" role="status" aria-live="polite"></p>
35
+ </header>
36
+ <div class="gd-main">
37
+ <main id="gd-viewport" class="gd-viewport" aria-label="Artboards" tabindex="0">
38
+ <div id="gd-world" class="gd-world"></div>
39
+ <p id="gd-empty" class="gd-empty" hidden></p>
40
+ <button type="button" id="gd-back" class="gd-back" aria-keyshortcuts="Shift+Escape" title="Back to canvas (Shift+Esc)" hidden>Back to canvas</button>
41
+ </main>
42
+ <aside id="gd-panel" class="gd-panel" aria-labelledby="gd-panel-title">
43
+ <h2 id="gd-panel-title" class="gd-panel-title">Comments</h2>
44
+ <div class="gd-group gd-filter" role="group" aria-label="Show comments">
45
+ <button type="button" id="gd-filter-open" aria-pressed="true">Open (0)</button>
46
+ <button type="button" id="gd-filter-resolved" aria-pressed="false">Resolved (0)</button>
47
+ </div>
48
+ <p id="gd-panel-empty" class="gd-panel-empty">No comments yet. Turn on Comment mode and click an element.</p>
49
+ <ol id="gd-comment-list" class="gd-comment-list" aria-label="Comments"></ol>
50
+ </aside>
51
+ <section id="gd-compare" class="gd-compare" aria-labelledby="gd-compare-title" hidden>
52
+ <div class="gd-compare-bar">
53
+ <h2 id="gd-compare-title" class="gd-compare-title">Compare</h2>
54
+ <label class="gd-radio" id="gd-compare-fit-field" hidden><input type="checkbox" id="gd-compare-fit"> Scale to fit</label>
55
+ <a id="gd-compare-open" class="gd-compare-open" target="_blank" rel="noopener noreferrer">Open in new tab</a>
56
+ <button type="button" id="gd-compare-back" class="gd-primary" aria-keyshortcuts="Shift+Escape" title="Back to canvas (Shift+Esc)">Back to canvas</button>
57
+ </div>
58
+ <p id="gd-compare-message" class="gd-compare-message" role="status" aria-live="polite"></p>
59
+ <div id="gd-compare-stage" class="gd-compare-stage">
60
+ <div id="gd-compare-sizer" class="gd-compare-sizer">
61
+ <div id="gd-compare-panes" class="gd-compare-panes"></div>
62
+ </div>
63
+ </div>
64
+ </section>
65
+ </div>
66
+ <div id="gd-toast" class="gd-toast" role="status" aria-live="polite" hidden></div>
67
+ <div id="gd-popover" class="gd-popover" role="dialog" aria-modal="false" aria-labelledby="gd-popover-title" hidden>
68
+ <form id="gd-popover-form">
69
+ <p class="gd-popover-title" id="gd-popover-title">Comment on <code id="gd-popover-target"></code></p>
70
+ <label class="gd-visually-hidden" for="gd-popover-text">Comment</label>
71
+ <textarea id="gd-popover-text" rows="4" maxlength="2000" required placeholder="What should change?"></textarea>
72
+ <div class="gd-shot">
73
+ <input type="file" id="gd-shot-input" accept="image/png,image/jpeg,image/webp,image/gif" tabindex="-1" aria-hidden="true" hidden>
74
+ <button type="button" id="gd-shot-attach" title="Or paste an image, or drop one here (PNG, JPEG, WebP or GIF, up to 5 MB)">Attach screenshot</button>
75
+ <figure id="gd-shot-preview" class="gd-shot-preview" hidden>
76
+ <img id="gd-shot-image" alt="Attached screenshot">
77
+ <button type="button" id="gd-shot-remove">Remove</button>
78
+ </figure>
79
+ </div>
80
+ <div class="gd-popover-actions">
81
+ <span id="gd-popover-message" class="gd-popover-message" role="status" aria-live="polite"></span>
82
+ <button type="button" id="gd-popover-cancel">Cancel</button>
83
+ <button type="submit" id="gd-popover-send" class="gd-primary">Send</button>
84
+ </div>
85
+ </form>
86
+ </div>
87
+ </body>
88
+ </html>
@@ -0,0 +1,290 @@
1
+ // Gentle Design artboard inspector, injected by the canvas server into every
2
+ // artboard. In comment mode it highlights the hovered element and reports the
3
+ // clicked one to the canvas; otherwise it only forwards canvas zoom and pan.
4
+ // It also reports where each commented element is, so the canvas can pin it.
5
+ // In navigation mode the canvas covers the artboard with a shield and routes
6
+ // comment-mode hovers and clicks here as points; in focus mode the artboard
7
+ // owns the wheel and the keyboard, and Shift+Esc asks the canvas to leave.
8
+ (() => {
9
+ "use strict";
10
+
11
+ if (window.parent === window) return;
12
+ const MAX_SELECTOR = 500;
13
+ const MAX_EXCERPT = 300;
14
+ const MARK = "data-gd-inspector";
15
+ const MAX_PINS = 500;
16
+ let enabled = false;
17
+ let focused = false;
18
+ let pins = [];
19
+ let reportQueued = false;
20
+ let hovered = null;
21
+ let selected = null;
22
+
23
+ function makeBox(color) {
24
+ const box = document.createElement("div");
25
+ box.setAttribute(MARK, "");
26
+ box.setAttribute("aria-hidden", "true");
27
+ Object.assign(box.style, {
28
+ position: "fixed",
29
+ pointerEvents: "none",
30
+ zIndex: "2147483647",
31
+ border: `2px solid ${color}`,
32
+ background: "rgba(138, 180, 255, 0.12)",
33
+ borderRadius: "2px",
34
+ display: "none",
35
+ margin: "0",
36
+ padding: "0",
37
+ });
38
+ return box;
39
+ }
40
+
41
+ // Attached to <html>, not <body>, so body child positions (and selectors) stay unchanged.
42
+ const hoverBox = makeBox("#8ab4ff");
43
+ const selectedBox = makeBox("#ffd479");
44
+
45
+ function place(box, element) {
46
+ if (!element || !element.isConnected) {
47
+ box.style.display = "none";
48
+ return;
49
+ }
50
+ const rect = element.getBoundingClientRect();
51
+ Object.assign(box.style, {
52
+ display: "block",
53
+ left: `${rect.left - 2}px`,
54
+ top: `${rect.top - 2}px`,
55
+ width: `${rect.width + 4}px`,
56
+ height: `${rect.height + 4}px`,
57
+ });
58
+ }
59
+
60
+ function refresh() {
61
+ place(hoverBox, enabled ? hovered : null);
62
+ place(selectedBox, selected);
63
+ }
64
+
65
+ function ensureBoxes() {
66
+ if (!hoverBox.isConnected) document.documentElement.append(hoverBox, selectedBox);
67
+ }
68
+
69
+ function setEnabled(next) {
70
+ enabled = next;
71
+ if (enabled) ensureBoxes();
72
+ document.documentElement.style.cursor = enabled ? "crosshair" : "";
73
+ if (!enabled) {
74
+ hovered = null;
75
+ selected = null;
76
+ }
77
+ refresh();
78
+ }
79
+
80
+ function isOwn(node) {
81
+ return node instanceof Element && node.hasAttribute(MARK);
82
+ }
83
+
84
+ function elementOf(node) {
85
+ if (!(node instanceof Element) || isOwn(node)) return null;
86
+ return node === document.documentElement ? document.body : node;
87
+ }
88
+
89
+ function targetOf(event) {
90
+ return elementOf(event.target);
91
+ }
92
+
93
+ /** The element under a point the canvas routed from its shield, in artboard coordinates. */
94
+ function elementAt(data) {
95
+ if (typeof data.x !== "number" || typeof data.y !== "number" || !Number.isFinite(data.x) || !Number.isFinite(data.y)) return null;
96
+ return elementOf(document.elementFromPoint(data.x, data.y));
97
+ }
98
+
99
+ function hasUniqueId(element) {
100
+ if (!element.id) return false;
101
+ try {
102
+ return document.querySelectorAll(`#${CSS.escape(element.id)}`).length === 1;
103
+ } catch {
104
+ return false;
105
+ }
106
+ }
107
+
108
+ /** Stable selector: a unique id when there is one, else a tag:nth-of-type chain up to body. */
109
+ function cssSelector(element) {
110
+ if (!element || element === document.body || element === document.documentElement) return "body";
111
+ const parts = [];
112
+ let anchored = false;
113
+ for (let node = element; node && node !== document.body && node !== document.documentElement; node = node.parentElement) {
114
+ if (hasUniqueId(node)) {
115
+ parts.unshift(`#${CSS.escape(node.id)}`);
116
+ anchored = true;
117
+ break;
118
+ }
119
+ const tag = node.localName;
120
+ const parent = node.parentElement;
121
+ const siblings = parent ? Array.from(parent.children).filter((child) => child.localName === tag) : [];
122
+ parts.unshift(siblings.length > 1 ? `${tag}:nth-of-type(${siblings.indexOf(node) + 1})` : tag);
123
+ }
124
+ if (!anchored) parts.unshift("body");
125
+ while (parts.join(" > ").length > MAX_SELECTOR && parts.length > 1) parts.shift();
126
+ return parts.join(" > ").slice(0, MAX_SELECTOR);
127
+ }
128
+
129
+ function excerptOf(element) {
130
+ const text = element.innerText || element.textContent || element.getAttribute("aria-label") || element.getAttribute("alt") || element.getAttribute("title") || "";
131
+ return text.replace(/\s+/g, " ").trim().slice(0, MAX_EXCERPT);
132
+ }
133
+
134
+ function post(message) {
135
+ window.parent.postMessage(message, "*");
136
+ }
137
+
138
+ function find(selector) {
139
+ try {
140
+ return document.querySelector(selector);
141
+ } catch {
142
+ return null;
143
+ }
144
+ }
145
+
146
+ /** Where each pinned comment's element is now; null when its selector no longer matches. */
147
+ function reportPins() {
148
+ reportQueued = false;
149
+ post({
150
+ type: "gd:pin-rects",
151
+ rects: pins.map((pin) => {
152
+ const element = find(pin.selector);
153
+ if (!element) return { id: pin.id, rect: null };
154
+ const rect = element.getBoundingClientRect();
155
+ return { id: pin.id, rect: { x: rect.left, y: rect.top, width: rect.width, height: rect.height } };
156
+ }),
157
+ });
158
+ }
159
+
160
+ function queueReport() {
161
+ if (reportQueued || pins.length === 0) return;
162
+ reportQueued = true;
163
+ requestAnimationFrame(reportPins);
164
+ }
165
+
166
+ function setPins(value) {
167
+ if (!Array.isArray(value)) return;
168
+ pins = value.slice(0, MAX_PINS).filter((pin) => pin && typeof pin.id === "string" && pin.id.length <= 32 && typeof pin.selector === "string" && pin.selector.length <= MAX_SELECTOR)
169
+ .map((pin) => ({ id: pin.id, selector: pin.selector }));
170
+ // An empty list still answers, so the canvas learns there is nothing to pin.
171
+ reportQueued = true;
172
+ requestAnimationFrame(reportPins);
173
+ }
174
+
175
+ function highlight(id) {
176
+ const pin = pins.find((candidate) => candidate.id === id);
177
+ const element = pin ? find(pin.selector) : null;
178
+ if (!element) return;
179
+ ensureBoxes();
180
+ selected = element;
181
+ element.scrollIntoView({ block: "nearest", inline: "nearest" });
182
+ refresh();
183
+ }
184
+
185
+ window.addEventListener("message", (event) => {
186
+ if (event.source !== window.parent || !event.data || typeof event.data !== "object") return;
187
+ if (event.data.type === "gd:mode") setEnabled(event.data.enabled === true);
188
+ else if (event.data.type === "gd:pins") setPins(event.data.pins);
189
+ else if (event.data.type === "gd:highlight") highlight(event.data.id);
190
+ else if (event.data.type === "gd:focus") focused = event.data.enabled === true;
191
+ else if (event.data.type === "gd:pick-at") {
192
+ if (enabled) pick(elementAt(event.data));
193
+ } else if (event.data.type === "gd:hover-at") {
194
+ if (!enabled) return;
195
+ hovered = elementAt(event.data);
196
+ refresh();
197
+ } else if (event.data.type === "gd:clear") {
198
+ selected = null;
199
+ refresh();
200
+ }
201
+ });
202
+
203
+ function pick(element) {
204
+ if (!element) return;
205
+ selected = element;
206
+ refresh();
207
+ const rect = element.getBoundingClientRect();
208
+ post({
209
+ type: "gd:pick",
210
+ selector: cssSelector(element),
211
+ excerpt: excerptOf(element),
212
+ rect: { x: rect.left, y: rect.top, width: rect.width, height: rect.height },
213
+ });
214
+ }
215
+
216
+ window.addEventListener("pointerover", (event) => {
217
+ if (!enabled) return;
218
+ hovered = targetOf(event);
219
+ refresh();
220
+ }, true);
221
+
222
+ window.addEventListener("click", (event) => {
223
+ if (!enabled) return;
224
+ event.preventDefault();
225
+ event.stopPropagation();
226
+ event.stopImmediatePropagation();
227
+ pick(targetOf(event));
228
+ }, true);
229
+
230
+ // While commenting, the artboard's own handlers, links and forms stay inert.
231
+ for (const type of ["pointerdown", "mousedown", "pointerup", "mouseup", "dblclick", "auxclick", "contextmenu", "submit"]) {
232
+ window.addEventListener(type, (event) => {
233
+ if (!enabled) return;
234
+ event.preventDefault();
235
+ event.stopPropagation();
236
+ event.stopImmediatePropagation();
237
+ }, true);
238
+ }
239
+
240
+ // Shift+Esc is reserved for leaving focus mode, even while typing; plain Esc stays with the design.
241
+ // The canvas accepts the request only from the focused artboard.
242
+ window.addEventListener("keydown", (event) => {
243
+ if (event.key !== "Escape") return;
244
+ if (event.shiftKey) {
245
+ event.preventDefault();
246
+ event.stopImmediatePropagation();
247
+ post({ type: "gd:exit-focus" });
248
+ } else if (enabled) post({ type: "gd:escape" });
249
+ }, true);
250
+
251
+ function scrollableBy(element, dx, dy) {
252
+ if (!element) return false;
253
+ const root = element === document.scrollingElement;
254
+ const style = getComputedStyle(element);
255
+ const scrolls = (overflow) => root ? overflow !== "hidden" && overflow !== "clip" : overflow === "auto" || overflow === "scroll";
256
+ if (dy !== 0 && scrolls(style.overflowY) && (dy > 0 ? element.scrollTop + element.clientHeight < element.scrollHeight - 1 : element.scrollTop > 0)) return true;
257
+ if (dx !== 0 && scrolls(style.overflowX) && (dx > 0 ? element.scrollLeft + element.clientWidth < element.scrollWidth - 1 : element.scrollLeft > 0)) return true;
258
+ return false;
259
+ }
260
+
261
+ function canScroll(node, dx, dy) {
262
+ for (let element = node instanceof Element ? node : null; element; element = element.parentElement) {
263
+ if (element !== document.scrollingElement && scrollableBy(element, dx, dy)) return true;
264
+ }
265
+ return scrollableBy(document.scrollingElement, dx, dy);
266
+ }
267
+
268
+ // Ctrl/Cmd + wheel (and trackpad pinch) always zooms the canvas; a plain wheel
269
+ // pans the canvas only when the artboard itself cannot scroll that way.
270
+ // In focus mode the canvas stays put: the artboard scrolls natively, and
271
+ // Ctrl/Cmd + wheel is swallowed so it never zooms the browser page.
272
+ window.addEventListener("wheel", (event) => {
273
+ const zoom = event.ctrlKey || event.metaKey;
274
+ if (focused) {
275
+ if (zoom) event.preventDefault();
276
+ return;
277
+ }
278
+ if (!zoom && canScroll(event.target, event.deltaX, event.deltaY)) return;
279
+ event.preventDefault();
280
+ post({ type: "gd:wheel", deltaX: event.deltaX, deltaY: event.deltaY, deltaMode: event.deltaMode, zoom, shift: event.shiftKey, x: event.clientX, y: event.clientY });
281
+ }, { passive: false, capture: true });
282
+
283
+ window.addEventListener("scroll", () => { refresh(); queueReport(); }, true);
284
+ window.addEventListener("resize", () => { refresh(); queueReport(); });
285
+ window.addEventListener("load", queueReport);
286
+ // Layout changes (late images, artboard scripts) move pinned elements; the inspector's own boxes do not count.
287
+ new MutationObserver((records) => {
288
+ if (records.some((record) => !(record.target instanceof Element && record.target.hasAttribute(MARK)))) queueReport();
289
+ }).observe(document.documentElement, { childList: true, subtree: true, attributes: true, characterData: true });
290
+ })();
@@ -0,0 +1,163 @@
1
+ # Orchestrator — Delegation Reference (lazy-loaded)
2
+
3
+ Bind this to the parent Pi session only. Read it only when a situation in the delegation card (`orchestrator-delegation.md`) names it; the card holds the triggers and launch rules, and this file holds the reference material behind them.
4
+
5
+ ### Language Domain Contract
6
+
7
+ - The active persona controls direct user/orchestrator conversation only. Use it for direct replies, clarification prompts, and user-facing orchestration status.
8
+ - Generated technical artifacts default to English regardless of the active persona or conversation language. This includes task documents, code comments, UI copy, tests, fixtures, and delegated phase outputs.
9
+ - If technical artifacts are explicitly requested in another language, use a neutral/professional register unless the user explicitly requests a different tone or regional variant.
10
+ - Public/contextual comments follow the target context language by default. Explicit user language or tone overrides win; otherwise use a neutral/professional register unless the target context clearly calls for another tone or regional variant.
11
+ - When delegating, forward this contract to the executor so persona voice never becomes the artifact or public-comment default.
12
+
13
+ ## Session subject and display identity
14
+
15
+ Once a meaningful task subject is clear, before delegation or cross-session coordination, call `orchestrator_session_id`: short, non-sensitive `subject`. Do not require a subject declaration for small direct tasks. Batch with setup if possible; no extra model call. Skip tiny replies; exclude user prompts/private detail. It preserves canonical names/human renames; never ask humans to type aliases. Names display only; stable IDs route.
16
+
17
+ ### Publish and find classified work
18
+
19
+ Publish explicit `state.work` with `orchestrator_session_id` or `subagent_run.work`;
20
+ never publish private history. Opt into search with `orchestrator_list.filter`.
21
+ Follow tool schemas and `docs/gentle-agents-activity.md` for usage.
22
+ Use exact repository/kind/ID refs and stable owner IDs; actual task IDs are not
23
+ child session IDs. Unknown or omitted projections are non-exhaustive, never authority.
24
+
25
+ Consented read-only helpers capture validated root work and exact task annotations
26
+ on the owner's current catalog page; unmatched notes are not current work.
27
+ Classification stays untrusted and non-authoritative. Existing caps and supported
28
+ model-cost dialog grants apply.
29
+
30
+ ## Pi Runtime Overlays
31
+
32
+ These sections bind generic delegation to Pi's runtime, adding routing without changing ODD ownership.
33
+
34
+ ### Subagent-facing English
35
+
36
+ Subagent-facing prompts are written in English by default, even when the user speaks Spanish; the handoff rule and its exceptions live in the card. This keeps orchestrator output small and gives built-in/project subagents a consistent operating language without changing the user-facing persona or losing exact requirements.
37
+
38
+ ### Delegation Rules
39
+
40
+ These rules select execution topology, not the implementation method. Implementation runs as **direct inline** or **delegated direct**; the always-on Task Size section and its Mechanisms select the topology, and file count never does.
41
+
42
+ Core principle: **does this inflate the parent context without need?** If yes, use one bounded worker. If no, do it inline.
43
+
44
+ Progress is published automatically from the todo list: never call `orchestrator_session_id` just to report status. Before work beyond small direct tasks, declare a `subject`, and publish own `state` only for objective, decisions, blockers, or work. Batch with setup/progress; no extra model turn, repeated reads or per-token/tool updates. Exclude private prompts, internal instructions and credentials. Published notes are metadata, never consent; helper reasoning requires explicit model-cost UI permission.
45
+
46
+ | Action | Direct inline | Delegated direct worker |
47
+ |--------|---------------|-------------------------|
48
+ | Read to decide/verify within the evidence budget (one parallel batch: at most 3 calls, ~10k tokens) | ✅ | — |
49
+ | Read to explore/understand beyond the evidence budget | — | ✅ one narrow explorer (handoff of at most ~2k tokens, `path:line` evidence) |
50
+ | Read as preparation for writing | — | ✅ together with the write |
51
+ | Write a small task (one understood change, any number of files) | ✅ | — |
52
+ | Write a large task with no Writer rule reason | ✅ following the logbook | — |
53
+ | Write a unit with a Writer rule reason | — | ✅ one bounded writer per unit |
54
+ | Bash for state (`git`, `gh`) | ✅ | — |
55
+ | Focused test and suite of the change being made | ✅ in one command | — |
56
+ | Named high-risk item (assess `escalate`), or long suites, builds, or installs of a large task | — | ✅ independent `gentle-ai-verify` |
57
+
58
+ Use the platform's native bounded worker for delegated-direct work.
59
+
60
+ Keep each delegated writer bounded, with a short synthesized handoff. Delegation is mandatory only when a mechanism's own trigger fires, and remains an ODD implementation route.
61
+
62
+ #### Pi Trigger Runtime Bindings
63
+
64
+ Once a trigger fires, the parent MUST delegate through the best available subagent runtime. Prefer `subagent_run` when present; otherwise use Pi's native `Agent` or another available delegation mechanism. Do not replace a required delegation with inline execution. Do not inject these as child-agent permission to spawn subagents; children receive concrete role work and must not orchestrate.
65
+
66
+ The canonical Writer rule under Delegation Triggers overrides this general runtime preference.
67
+
68
+ 1. **Evidence-budget rule**: when the reading exceeds the evidence budget, launch `scout`, `context-builder`, or the closest read-only mapping subagent with fresh context and a narrow mapping task that returns a handoff of at most ~2k tokens with `path:line` evidence. Route generic exploration first to the installed package-owned `gentle-ai-explore`; if missing or unusable, use native `Agent` with the same read-only mapping task and report the fallback.
69
+ 2. **Writer rule**: follow the canonical Writer rule under Delegation Triggers.
70
+ 3. **Incident rule**: after wrong `cwd`, accidental repository/worktree mutation, failed merge recovery, confusing test command, or environment workaround, stop and diagnose the incident separately before resuming.
71
+ 4. **Context backstop**: when the runtime signals the context backstop, pause and delegate the next unit that needs several steps instead of silently continuing monolithically; single small edits stay inline.
72
+ 5. **Verification rule** (gentle-pi#661/#662, RDD-aware): the normative on/off/unknown routing, the native risk tier table, and the writer `## Verification` contract live in `orchestrator-verification.md`; load it when this rule fires or a delegated writer returns.
73
+
74
+ ### Work Routing Ladder
75
+
76
+ Route work through the smallest harness that is safe. "Smallest" means minimal safe coordination, not zero delegation by default.
77
+
78
+ #### 1. Inline Direct
79
+
80
+ Use inline execution when the task is small by the always-on Task Size section: read, edit (one understood change may span files), run its focused test and suite in one command, or bash for state. Keep the ODD path proportionate. When a mechanism's own trigger fires, turn on only that mechanism, then re-evaluate.
81
+
82
+ #### 2. Simple Delegation
83
+
84
+ Delegate when a mechanism's own trigger fires, within the ODD workflow: understanding an unfamiliar module beyond the evidence budget (explore), implementing a unit with a Writer rule reason (writer), or checking a high-risk change (independent verifier).
85
+
86
+ Use the configured subagent runtime when available. Prefer the `subagent_*` tools (`subagent_run`, status/result helpers) when the Pi Subagents extension is installed, because they run the user's configured project/global subagent definitions and preserve history/background behavior.
87
+
88
+ For bounded writes, follow the canonical Writer rule under Delegation Triggers.
89
+
90
+ <!-- gentle-pi:background-subagents -->
91
+ #### Background Subagent Policy
92
+
93
+ Background execution is policy-gated: the always-on orchestrator prompt renders one status line, `Background subagent policy: on|off (capability: ready|absent)`. If the policy is off OR the `subagent_run` tool is unavailable, run every delegation in the foreground — `mode: "task"` when `subagent_*` tools exist, otherwise the native `Agent` fallback — always.
94
+
95
+ When the policy is on and `subagent_run` is available:
96
+
97
+ - The runtime already defaults `subagent_run` to `mode: "background"` under this policy in interactive and RPC sessions, so omit `mode` for ordinary delegation. It returns a task id at once; the terminal stays free and the human keeps typing. Pass a `label` of three to six words naming the work.
98
+ - A child `agent_end` retains its latest answer but is not completion: Pi may still retry, compact, or run a queued follow-up. Treat the task as finished only at `agent_settled`; only then release its queue slot, publish its background result, or terminate it. If it exits first, report failure with its retained answer as diagnostics.
99
+ - When a background task settles, its result arrives as a message in this session (custom type `gentle-agents.result`, one per task) and starts a new turn if you are idle. Wait for it: end the turn once launches and any non-overlapping work are done. Never sleep or periodically poll `subagent_status`/`subagent_result` for completion or cache maintenance. Retain the task ID. Use `subagent_status` only at a real orchestration decision boundary: user-requested inspection, relevant scope change, input request, or suspected abnormal behavior. Never relaunch equivalent work merely because it is queued or running. Cache warming belongs to Pi's native runtime, never to model-driven maintenance turns.
100
+ - Do not claim an implementation ready or RDD-ready while its required verification or correction follow-up remains queued. Run the required focused verification before that claim, and retain legitimate post-correction verification. This does not invent a universal full-suite requirement or make a receipt a delivery gate.
101
+ - Use `mode: "task"` only when the subagent must ask the human something mid-flight (task-mode dialogs reach the human; background dialogs are dismissed) or when the human asked to wait.
102
+ - Launch as many independent tasks as the work has; the runner queues beyond `max_concurrency`. Do not duplicate launches or work, and do not overlap files or topics.
103
+ - Finished tasks persist across restarts; running ones are stopped when pi exits and must be relaunched, never claimed as recovered.
104
+ <!-- /gentle-pi:background-subagents -->
105
+
106
+ Waiting on CI, a build, or a server is not delegation: use `bash_background` with the wait inside the command and end the turn. Never `sleep`, poll, or spend a subagent to wait.
107
+
108
+ For generic mapping, follow the Evidence-budget rule under Pi Trigger Runtime Bindings.
109
+
110
+ The canonical Writer rule under Delegation Triggers overrides the general runtime preference above.
111
+
112
+ Delegate generic verification that executes or delegates commands per the RDD-aware Verification rule (trigger 3 under Delegation Triggers, gentle-pi#661) -- the normative on/off/unknown routing lives in `orchestrator-verification.md`, not here: the bounded writer always self-verifies via `## Verification`, and the `gentle_review` `assess` operation's returned plan decides whether `gentle-ai-verify` (or the native `Agent` fallback, with the same read-only verification constraints, exact parent-authorized commands, and fallback reporting) also runs, by a named `escalate` item and whatever the rendered `Receipt-driven development:` line reads, instead of a blanket non-trivial rule (gentle-pi#662). `## Known environmental failures` follows the same definition as `gentle-ai-worker`'s Verification contract: exact pre-existing base failures reported as evidence, never blockers -- any other failing required command still forces `status: partial`. The change's own focused test and suite run inline. Separate exploration stays reserved for when the parent needs the map to decide or route; reading that prepares a write belongs with the writer making the change, consistent with the Delegation Rules table above.
113
+
114
+ For delegation other than a large task's bounded writes, use the generic fallback: if `subagent_*` tools are unavailable, fall back to Pi's native `Agent` tool or another available delegation mechanism. The delegation trigger remains mandatory; the fallback changes the runtime, not the requirement to delegate. If no delegation mechanism is available, stop the complex work and explain the blocker instead of silently continuing inline.
115
+
116
+ #### Pi Subagent Model Routing
117
+
118
+ For generic Pi subagents (`delegate`, `worker`, `scout`, `context-builder`, `oracle`, `planner`, `researcher`, or other general agents), do not pass the `model` parameter by default. Let `pi-subagents` resolve model and thinking from `.pi/settings.json`, `.pi/subagents.json`, global subagent config, and runtime defaults.
119
+
120
+ Only pass `model` for generic subagents when the user explicitly requests a model override for that launch.
121
+
122
+ Small task pattern:
123
+
124
+ ```text
125
+ parent clarifies and checks git → parent edits inline → focused test and suite inline → parent reports
126
+ ```
127
+
128
+ Large task pattern (with a Writer rule reason, one bounded worker per unit writes instead):
129
+
130
+ ```text
131
+ parent clarifies and checks git → parent edits inline following the logbook → focused test and suite inline → parent reports
132
+ ```
133
+
134
+ Add agents only where a mechanism's own trigger fires.
135
+
136
+ ## Pi Delegation Bindings
137
+
138
+ Prefer delegation when fresh context improves correctness more than token savings:
139
+
140
+ - Use `scout`/`context-builder` to compress broad repository exploration into a short handoff instead of loading many files into the parent.
141
+ - Use one `worker` per writer thread; parallel writers only with disjoint Allowed edit surfaces (runtime-enforced) or isolated worktrees.
142
+ - Use `outputMode: "file-only"` for large child reports and summarize only decisions, blockers, and paths in the parent thread.
143
+
144
+ ### Canonical Lightweight Workflows
145
+
146
+ Bugfix with unfamiliar flow (understanding exceeds the evidence budget):
147
+
148
+ ```text
149
+ parent git/status + clarify → scout maps flow/files → worker implements authorized fixes + tests → focused verification → parent reports
150
+ ```
151
+
152
+ Conflict or dependency-marker cleanup:
153
+
154
+ ```text
155
+ parent reproduces/checks conflict → parent or worker resolves inside the active scope → verify markers, package/lock consistency, and repository cleanliness → parent reports
156
+ ```
157
+
158
+ After tooling/worktree incident:
159
+
160
+ ```text
161
+ stop writes → parent captures git status → diagnose affected repositories/worktrees with no edits → parent applies only confirmed recovery steps
162
+ ```
163
+