gentle-pi 4.3.0 → 4.5.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 (218) hide show
  1. package/README.md +10 -7
  2. package/assets/agents/gentle-ai-worker.md +1 -1
  3. package/assets/design-canvas/canvas.css +648 -0
  4. package/assets/design-canvas/canvas.js +1497 -0
  5. package/assets/design-canvas/index.html +88 -0
  6. package/assets/design-canvas/inspector.js +290 -0
  7. package/assets/orchestrator-delegation-reference.md +2 -2
  8. package/assets/orchestrator-verification.md +1 -1
  9. package/assets/orchestrator.md +2 -2
  10. package/bin/engram-guard +1 -1
  11. package/bin/gentle-shell.mjs +138 -155
  12. package/docs/bundled-install.md +47 -42
  13. package/docs/delegated-verification.md +6 -0
  14. package/docs/gentle-agents-activity.md +5 -1
  15. package/docs/gentle-music.md +82 -0
  16. package/docs/gentle-shell.md +80 -10
  17. package/docs/install-wizard.md +30 -6
  18. package/docs/permission-modes.md +7 -2
  19. package/docs/readme-reference.md +72 -55
  20. package/docs/session-profile-format.md +26 -0
  21. package/docs/voice.md +259 -0
  22. package/docs/yolo-mode.md +17 -2
  23. package/extensions/ask-user-choice.ts +4 -1
  24. package/extensions/gentle-agents.ts +187 -40
  25. package/extensions/gentle-ai.ts +1765 -1185
  26. package/extensions/gentle-design.ts +158 -0
  27. package/extensions/gentle-music.ts +354 -0
  28. package/extensions/gentle-shell.ts +418 -79
  29. package/extensions/gentle-voice.ts +11 -0
  30. package/extensions/session-scratch.ts +41 -22
  31. package/extensions/skill-registry.ts +63 -8
  32. package/lib/agent-profiles.ts +26 -0
  33. package/lib/agents-config.ts +35 -0
  34. package/lib/agents-protocol.ts +57 -1
  35. package/lib/agents-runner.ts +52 -3
  36. package/lib/agents-session-transport.ts +101 -6
  37. package/lib/agents-widget.ts +14 -1
  38. package/lib/auto-permission-memory.ts +48 -18
  39. package/lib/auto-permission-runtime.ts +21 -6
  40. package/lib/clipboard-image.ts +147 -0
  41. package/lib/command-palette-catalog.ts +3 -2
  42. package/lib/commit-slice-signal.ts +1 -1
  43. package/lib/context-backstop.ts +36 -0
  44. package/lib/design-canvas-server.ts +947 -0
  45. package/lib/design-comments.ts +437 -0
  46. package/lib/design-handoffs.ts +313 -0
  47. package/lib/design-open-browser.ts +58 -0
  48. package/lib/design-sources.ts +120 -0
  49. package/lib/external-editor.ts +31 -0
  50. package/lib/gentle-design.ts +513 -0
  51. package/lib/gentle-shell-bundled.ts +141 -57
  52. package/lib/gentle-shell-launcher.ts +11 -4
  53. package/lib/gentle-shell-startup-update.ts +61 -9
  54. package/lib/gentle-shell-uninstall.ts +33 -1
  55. package/lib/image-attachments.ts +150 -0
  56. package/lib/inprocess-reviewer.ts +33 -2
  57. package/lib/jobs-sidebar-state.ts +22 -3
  58. package/lib/jobs-widget.ts +112 -0
  59. package/lib/nan-provider.ts +3 -0
  60. package/lib/native-review-cli.ts +11 -4
  61. package/lib/notification-audio-native.ts +149 -13
  62. package/lib/notification-audio.ts +4 -0
  63. package/lib/notification-pulse-worker.ts +82 -18
  64. package/lib/notification-service.ts +5 -1
  65. package/lib/orchestrator-presence.ts +78 -8
  66. package/lib/orchestrator-scope.ts +10 -0
  67. package/lib/orchestrator-state.ts +11 -3
  68. package/lib/permission-mode-policy.ts +2 -2
  69. package/lib/review-host-relay.ts +11 -2
  70. package/lib/review-reminder-receipt.ts +24 -1
  71. package/lib/session-profile-append-controller.ts +713 -0
  72. package/lib/session-profile-disk-reader.ts +182 -0
  73. package/lib/session-profile-freeze.ts +2 -2
  74. package/lib/session-profile-persistence.ts +15 -7
  75. package/lib/session-scratch.ts +52 -3
  76. package/lib/session-worktree-registry.ts +7 -0
  77. package/lib/shell-bar.ts +6 -7
  78. package/lib/shell-changes.ts +81 -5
  79. package/lib/shell-prompt.ts +4 -4
  80. package/lib/shell-sidebar-layout.ts +27 -7
  81. package/lib/shell-todo.ts +1 -1
  82. package/lib/verifier-admission.ts +5 -4
  83. package/lib/vim-editor-adapter.ts +14 -10
  84. package/lib/voice-artifacts.ts +188 -0
  85. package/lib/voice-command.ts +576 -0
  86. package/lib/voice-install.ts +455 -0
  87. package/lib/voice-platform.ts +99 -0
  88. package/lib/voice-push-to-talk.ts +262 -0
  89. package/lib/voice-session.ts +460 -0
  90. package/lib/voice-settings.ts +50 -0
  91. package/lib/voice-ui.ts +158 -0
  92. package/lib/yolo-session-policy.ts +58 -22
  93. package/package.json +1 -1
  94. package/runtime/gentle-shell-bundled.mjs +140 -56
  95. package/runtime/gentle-shell-launcher.mjs +11 -4
  96. package/runtime/gentle-shell-startup-update.mjs +61 -9
  97. package/runtime/gentle-shell-uninstall.mjs +33 -1
  98. package/runtime/native-review-cli.mjs +11 -4
  99. package/scripts/bundled-engram-migration.mjs +0 -6
  100. package/scripts/bundled-install.mjs +209 -13
  101. package/scripts/gentle-ai-installer.mjs +10 -10
  102. package/scripts/installer-downloads.mjs +31 -7
  103. package/scripts/installer-preflight.mjs +6 -4
  104. package/scripts/installer-windows.mjs +37 -7
  105. package/scripts/main-channel.mjs +91 -17
  106. package/scripts/pi-update.mjs +37 -7
  107. package/scripts/verify-package-files.mjs +26 -2
  108. package/scripts/voice-worker.cjs +476 -0
  109. package/skills/design/SKILL.md +110 -0
  110. package/tests/agent-profiles.test.ts +24 -0
  111. package/tests/agents-config.test.ts +61 -0
  112. package/tests/agents-fake-child.ts +8 -1
  113. package/tests/agents-protocol.test.ts +32 -0
  114. package/tests/agents-runner.test.ts +226 -5
  115. package/tests/agents-session-transport.test.ts +53 -3
  116. package/tests/ask-user-choice.test.ts +30 -0
  117. package/tests/auto-mode.test.ts +17 -0
  118. package/tests/auto-permission-memory-diagnostics.test.ts +56 -0
  119. package/tests/auto-permission-runtime.test.ts +85 -1
  120. package/tests/autonomous-guard.test.ts +20 -0
  121. package/tests/bundled-install.test.ts +276 -5
  122. package/tests/clipboard-image.test.ts +114 -0
  123. package/tests/command-palette.test.ts +4 -4
  124. package/tests/context-backstop.test.ts +70 -4
  125. package/tests/delegate-for-reason-contract.test.ts +2 -1
  126. package/tests/design-canvas-assets.test.ts +710 -0
  127. package/tests/design-canvas-server.test.ts +1096 -0
  128. package/tests/design-comments.test.ts +201 -0
  129. package/tests/design-handoffs.test.ts +282 -0
  130. package/tests/design-open-browser.test.ts +70 -0
  131. package/tests/design-sources.test.ts +132 -0
  132. package/tests/engram-safety.test.ts +132 -57
  133. package/tests/external-editor.test.ts +84 -0
  134. package/tests/fixtures/primary-session-prompt/gentleman.golden.md +3 -3
  135. package/tests/gentle-agents.test.ts +369 -24
  136. package/tests/gentle-ai-binary.test.ts +1 -1
  137. package/tests/gentle-ai-installer.test.ts +51 -51
  138. package/tests/gentle-ai.test.ts +928 -448
  139. package/tests/gentle-design.test.ts +1313 -0
  140. package/tests/gentle-music.test.ts +452 -0
  141. package/tests/gentle-shell-bundled.test.ts +321 -248
  142. package/tests/gentle-shell-launcher.test.ts +29 -2
  143. package/tests/gentle-shell-startup-update.test.ts +77 -1
  144. package/tests/gentle-shell-uninstall.test.ts +59 -0
  145. package/tests/gentle-shell.test.ts +227 -27
  146. package/tests/gentle-todo.test.ts +11 -0
  147. package/tests/image-attachments.test.ts +119 -0
  148. package/tests/image-paste-chips.test.ts +236 -0
  149. package/tests/inprocess-reviewer.test.ts +55 -2
  150. package/tests/installer-bundles.test.ts +12 -6
  151. package/tests/installer-downloads.test.ts +32 -0
  152. package/tests/installer-posix-bootstrap.test.ts +8 -8
  153. package/tests/installer-preflight.test.ts +16 -0
  154. package/tests/installer-server.test.ts +2 -2
  155. package/tests/installer-windows-bootstrap.test.ts +61 -3
  156. package/tests/installer-windows-diagnostics.test.ts +111 -0
  157. package/tests/jobs-widget.test.ts +138 -0
  158. package/tests/main-channel-upgrade.test.ts +232 -2
  159. package/tests/main-channel.test.ts +140 -21
  160. package/tests/model-profiles-preservation.test.ts +2 -2
  161. package/tests/nan-provider.test.ts +36 -0
  162. package/tests/native-review-capability-contract.test.ts +11 -4
  163. package/tests/native-review-parity.test.ts +1 -1
  164. package/tests/notification-audio-native.test.ts +128 -9
  165. package/tests/notification-customize.test.ts +17 -5
  166. package/tests/odd-routing-canonical-ratchet.test.ts +2 -1
  167. package/tests/orchestrator-budget.test.ts +5 -2
  168. package/tests/orchestrator-presence.test.ts +100 -2
  169. package/tests/orchestrator-rdd-ownership.test.ts +2 -2
  170. package/tests/orchestrator-scope.test.ts +14 -0
  171. package/tests/orchestrator-state.test.ts +29 -0
  172. package/tests/package-files.test.ts +34 -0
  173. package/tests/package-manifest.test.ts +6 -6
  174. package/tests/permission-mode-policy.test.ts +10 -1
  175. package/tests/pi-update.test.ts +104 -4
  176. package/tests/rdd-aware-verification-contract.test.ts +1 -1
  177. package/tests/review-host-relay-routing.test.ts +88 -1
  178. package/tests/review-host-relay.test.ts +9 -2
  179. package/tests/review-json-arguments.test.ts +20 -3
  180. package/tests/review-loadout-rdd-off-sdk.test.ts +23 -2
  181. package/tests/review-relay-transport-agent.test.ts +26 -0
  182. package/tests/review-reminder-receipt.test.ts +31 -1
  183. package/tests/runtime-harness.mjs +188 -211
  184. package/tests/session-changes.test.ts +2 -1
  185. package/tests/session-profile-append-controller-fork.test.ts +458 -0
  186. package/tests/session-profile-append-controller-pi.test.ts +290 -0
  187. package/tests/session-profile-append-controller.test.ts +731 -0
  188. package/tests/session-profile-disk-reader-pi.test.ts +183 -0
  189. package/tests/session-profile-disk-reader.test.ts +311 -0
  190. package/tests/session-profile-freeze.test.ts +6 -4
  191. package/tests/session-scratch.test.ts +68 -2
  192. package/tests/session-worktree-registry.test.ts +13 -1
  193. package/tests/shell-bar.test.ts +18 -6
  194. package/tests/shell-changes.test.ts +148 -1
  195. package/tests/shell-prompt.test.ts +3 -3
  196. package/tests/shell-render-cache.test.ts +134 -1
  197. package/tests/shell-sidebar-layout.test.ts +67 -0
  198. package/tests/short-check-routing-contract.test.ts +1 -1
  199. package/tests/skill-collision-prefixes.test.ts +3 -1
  200. package/tests/skill-registry-watcher.test.ts +17 -5
  201. package/tests/skill-registry.test.ts +47 -3
  202. package/tests/task-size-routing-contract.test.ts +1 -1
  203. package/tests/test-strength-contract.test.ts +1 -1
  204. package/tests/verifier-admission.test.ts +18 -1
  205. package/tests/vim-editor-adapter.test.ts +2 -2
  206. package/tests/voice-command.test.ts +773 -0
  207. package/tests/voice-install.test.ts +323 -0
  208. package/tests/voice-platform.test.ts +176 -0
  209. package/tests/voice-push-to-talk.test.ts +444 -0
  210. package/tests/voice-session.test.ts +434 -0
  211. package/tests/voice-settings.test.ts +49 -0
  212. package/tests/voice-ui.test.ts +97 -0
  213. package/tests/voice-worker.test.ts +445 -0
  214. package/tests/weak-model-economy-prompt.test.ts +32 -0
  215. package/tests/windows-hidden-processes.test.ts +25 -2
  216. package/tests/yolo-customize.test.ts +5 -1
  217. package/tests/yolo-mode.test.ts +1 -1
  218. package/tests/yolo-session-policy-capture.test.ts +104 -0
@@ -59,7 +59,7 @@ it lets the window close.
59
59
  Current requirements come from `package.json` and
60
60
  [`gentle-ai-installer.mjs`](../scripts/gentle-ai-installer.mjs): Node ≥22.19.0,
61
61
  Pi ≥1.2.0, pnpm acquisition 11.1.1, Gentle Shell package 4.0.0 and package-local
62
- Gentle AI 4.2.0. Windows native source builds require Go ≥1.25.10 when the
62
+ Gentle AI 4.3.1. Windows native source builds require Go ≥1.25.10 when the
63
63
  required usable native binary is missing. A reusable binary does not require Go.
64
64
  When a build needs Go and the user's Go is missing, older or unchecked, the installer uses
65
65
  its own [pinned Go](#pinned-go) instead of blocking.
@@ -787,9 +787,13 @@ publishes main builds, so main is built on this computer
787
787
  Gentleman-Programming/gentle-ai (GitHub API, raw SHA), runs
788
788
  `go install github.com/gentleman-programming/gentle-ai/v4/cmd/gentle-ai@<sha>`
789
789
  in a sealed Go environment (`GOPROXY=https://proxy.golang.org`,
790
- `GOSUMDB=sum.golang.org`, `GOTOOLCHAIN=local`, `GOFLAGS=-modcacherw`), requires
791
- the binary's version to end in that commit's first 12 characters, keeps it
792
- under `<config home>/main/gentle-ai/<sha>/` and registers it as the
790
+ `GOSUMDB=sum.golang.org`, `GOTOOLCHAIN=local`, `GOFLAGS=-modcacherw`),
791
+ asks Go (`go list -m -json`, same environment) which module version that
792
+ commit is (a release tag such as `v4.2.0`, or a pseudo-version) and requires
793
+ its origin to be that exact commit, requires the binary to embed that module
794
+ version (`go version -m`) and to report it, all in the `.build` work
795
+ folder, and only then moves it to `<config home>/main/gentle-ai/<sha>/`
796
+ (a failed rebuild leaves an already registered build in place) and registers it as the
793
797
  `gentle-pi.dev-binary/v1` override, which never falls back to the pinned
794
798
  binary silently.
795
799
  2. `install-shell-main`: downloads the latest `main` commit's source tarball,
@@ -812,8 +816,28 @@ publishes main builds, so main is built on this computer
812
816
  a version it cannot check) it builds with the pinned Go under
813
817
  `<config home>/tools/go`, downloading and verifying it there with the same
814
818
  `acquireGo` as the wizard when no earlier run published it, and only when
815
- Gentle AI is rebuilt. A failed download stops with `main-requires-tools`
816
- before anything is built; the user's Go is never run for the build.
819
+ Gentle AI is rebuilt. A failed download stops the Gentle AI build with
820
+ `main-requires-tools` before it starts (a main Shell that moved is still
821
+ installed, as below); the user's Go is never run for the build.
822
+ - When the Gentle AI step of `gentle-shell upgrade --channel main` fails (the
823
+ build, its verification, or getting the pinned Go) and the main Shell moved,
824
+ the upgrade still packs and installs that Shell, records no channel, prints
825
+ `Updated Gentle Shell to the latest main (<sha12>); Gentle AI was not updated.`
826
+ and exits 1 with the original error (code and message) followed by
827
+ `; Gentle Shell was updated to main <sha12> but Gentle AI was not: run
828
+ gentle-shell upgrade --channel main to finish`. The retry then rebuilds Gentle
829
+ AI with the new Shell's code, so a fix in the main-channel upgrade path reaches
830
+ an install whose own copy of it is broken; a cause the new Shell does not fix
831
+ (a Go download that keeps failing, for example) still has to be resolved first. Until then Gentle AI stays the
832
+ previously registered main build or the pinned binary: a rejected build is
833
+ never registered. When the Shell install fails as well, its error is reported
834
+ with `; Gentle AI was not updated either (<Gentle AI error>)`. An unexpected
835
+ error that has no main-channel code (a filesystem `EACCES`, for example) is
836
+ reported as `main-upgrade-incomplete` with its own message and the same
837
+ suffix, so neither the retry advice nor either error is lost. When the Shell
838
+ is already current, a failed Gentle AI step fails as before, with nothing
839
+ installed or recorded. The wizard's runner is the one bundled with the
840
+ downloaded installer and does not get this behavior from a newer main.
817
841
  - Trust: Gentle AI source is verified by Go's checksum database; the Gentle Shell
818
842
  source is fetched over TLS from GitHub by exact commit SHA, with no pinned
819
843
  digest. Main builds are development builds.
@@ -53,14 +53,15 @@ Changing the default does **not** change the current session. To return this ses
53
53
  | **Normal** | Existing permission behavior; the default when no valid global preference exists. |
54
54
  | **Auto** | A separate reviewer using the current session model checks eligible actions against live user intent before execution. Local reads are classified too; locality does not exempt an action from explicit restrictions. |
55
55
  | **YOLO** | Standing permission for ordinary already-authorized work and delivery; no Auto classifier. Destructive and independent consent boundaries remain, except recursive removal of the session's own [temp scratch](yolo-mode.md#temp-scratch-removal). [Full YOLO details](yolo-mode.md). |
56
+ | **Super Yolo** | No permission prompts at all, including data-loss confirmations and configured guardrail actions. The only remaining line is the sensitive-path guard: read/write/edit of `.env`, `.ssh`, keychains, `*.pem/*.key/*.p12/*.pfx`, `secrets/` and cloud credential files stays hard-blocked. Code-level catastrophic denies (`rm -rf /`, `--no-preserve-root`, `git reset --hard`, forced clean, force push) also remain. |
56
57
 
57
58
  ## Commands and menu
58
59
 
59
60
  | Command | Effect |
60
61
  | --- | --- |
61
- | `/gentle:mode normal`, `auto`, or `yolo` | Select exactly one mode for the current interactive primary session. |
62
+ | `/gentle:mode normal`, `auto`, `yolo`, or `super-yolo` | Select exactly one mode for the current interactive primary session. |
62
63
  | `/gentle:mode status` or `/gentle:mode` | Show current mode and saved default. |
63
- | `/gentle:mode default normal`, `auto`, or `yolo` | Save the default for new primary sessions, leaving the current mode unchanged. |
64
+ | `/gentle:mode default normal`, `auto`, `yolo`, or `super-yolo` | Save the default for new primary sessions, leaving the current mode unchanged. |
64
65
  | `/gentle:yolo enable`, `disable`, or `status` | Existing shortcut; enable selects YOLO, disable selects Normal. |
65
66
 
66
67
  In `/gentle:customize` → **Editor**, use **Session permissions** to change the current mode, or **Default permissions** to save a future-session preference. The original **YOLO: ON/OFF · session only** row still toggles the live mode; it does not save a default. Browsing, previews, and closing the menu do not grant permission.
@@ -116,6 +117,10 @@ The **Auto checks** status and `gentle-auto-permission` session entries account
116
117
 
117
118
  The dedicated `permission-mode.json` in Gentle Pi's resolved user config home contains a strict versioned preference. Saving uses a private atomic replacement; malformed or unreadable existing preferences fall back to Normal and refuse an overwrite until repaired. Use the human command/menu path rather than asking model tools to edit this authority file.
118
119
 
120
+ Model `write`/`edit` calls keep the config home protected except for the main-channel updater's `dev-binary.json`, `channel.json`, `main/` and `tools/go`. Those destinations select or build executable code, so they still require authorization under the current mode's ordinary checks; Auto classifies them and can deny an update. They are not automatically allowed. Permission preferences, global and project `runtime-guardrails.json`, their parent directories and symlink aliases resolving to them stay blocked even if a classifier would allow the action. Other config-home state, including model routing, persona and privacy preferences, remains protected.
121
+
122
+ Shell recognition remains deliberately conservative: commands mentioning the config home or policy filenames can still be blocked. This change does not relax shell protection, authorize routing around a denial, or turn the hook into a sandbox.
123
+
119
124
  Live mode selection is bound to the SessionManager, session ID and canonical Git clone identity, or the canonical workspace directory outside Git. Session replacement, shutdown and reload revoke live callbacks and pending actions. A newly initialized primary session may select its saved default; this is a new application of the global preference, not restoration of an old session grant. Disable the saved default as well if future sessions must stay Normal.
120
125
 
121
126
  ## Limits
@@ -157,7 +157,7 @@ otherwise `herdr` from `PATH`, without a shell.
157
157
  | **Skill creation workflow** | Provides the `gentle-ai-skill-creator`/`gentle-ai-skill-improver` skills, `/skill-creation` prompt, and packaged style guide for LLM-first skills. |
158
158
  | **Delivery skills** | Includes issue-first PRs, chained PRs, work-unit commits, cognitive docs, comment writing, and Judgment Day review. |
159
159
  | **Bounded native review** | Freezes one candidate, dispatches only controller-selected lenses, and records native authority. Review outcomes are informational; delivery follows ordinary repository policy. |
160
- | **Verified native runtime** | The current source checkout provisions the exact package-local Gentle AI v4.2.0 runtime: signed, SHA-256-pinned release archives on Darwin/Linux and a Go SumDB-verified source build on Windows x64/arm64. It validates package-local integrity and rejects PATH, global, sibling, symlink, and mode fallbacks. |
160
+ | **Verified native runtime** | The current source checkout provisions the exact package-local Gentle AI v4.3.1 runtime: signed, SHA-256-pinned release archives on Darwin/Linux and a Go SumDB-verified source build on Windows x64/arm64. It validates package-local integrity and rejects PATH, global, sibling, symlink, and mode fallbacks. |
161
161
  | **Runtime safety** | Blocks destructive shell commands, asks for confirmation for sensitive operations, and blocks direct read/write/edit access to sensitive paths. Blocks writing a test file that reads git history at a literal commit or points `TMPDIR` inside the working directory (including a relative path such as `.tmp`, `./.tmp`, or `tmp/x`), in the primary session and in subagents. Refuses native review tools (`gentle_review*`) called from inside another tool, such as a codemode script: they run only as direct tool calls. |
162
162
 
163
163
  ## Audio notifications
@@ -218,11 +218,11 @@ This installs the current npm release; select an explicit version if you need a
218
218
 
219
219
  ### Source checkout
220
220
 
221
- This checkout declares `gentle-pi` `4.0.0` with a package-local Gentle AI `v4.2.0` pin. Checkout metadata alone is not proof of npm publication; verify the registry version and its release workflow.
221
+ This checkout declares `gentle-pi` `4.0.0` with a package-local Gentle AI `v4.3.1` pin. Checkout metadata alone is not proof of npm publication; verify the registry version and its release workflow.
222
222
 
223
223
  ### Pi compatibility
224
224
 
225
- The current package requires Pi 1.2.0 or newer and Node >=22.19.0. Development tests resolve Pi through the open `>=1.0.0` development range. The private Vim editor adapter admits only the audited Pi `0.99.1`, `0.99.2`, `1.0.0`, `1.1.0`, and `1.2.0` releases; any other release keeps ordinary prompt editing until its editor is audited. Use the latest Pi release; gentle-pi does not update your installed Pi automatically. Children, including any `GENTLE_PI_AGENTS_PI` override, must emit `agent_settled`: `agent_end` records a run's output but is not completion because retries or queued continuations may follow.
225
+ The current package requires Pi 1.2.0 or newer and Node >=22.19.0. Development tests resolve Pi through the open `>=1.0.0` development range. The private Vim editor adapter admits only the audited Pi `0.99.1`, `0.99.2`, `1.0.0`, `1.1.0`, `1.2.0`, `1.3.0`, and `1.4.0` releases; any other release keeps ordinary prompt editing until its editor is audited. Use the latest Pi release; gentle-pi does not update your installed Pi automatically. Children, including any `GENTLE_PI_AGENTS_PI` override, must emit `agent_settled`: `agent_end` records a run's output but is not completion because retries or queued continuations may follow.
226
226
 
227
227
  The [`v2.6.0` release](https://github.com/Gentleman-Programming/gentle-shell/releases/tag/v2.6.0) added persistent registered worktrees and grouped `/gentle:changes` views; fuller workspace interaction details are in the [Gentle Shell reference](gentle-shell.md). It also adds named atomic `/gentle:profiles`, native review intended-untracked selection and provider continuations, and opt-in custom ask responses. Pi recognizes its global Git-managed package path; subsystems install with explicit recovery guidance when npm lifecycle work was skipped. Windows keeps child consoles hidden and fixes ownership mode; Gentle Todo keeps the next pending task visible when collapsed.
228
228
 
@@ -234,7 +234,7 @@ Project-local installs (`pi install -l`), Git installs outside that exact global
234
234
 
235
235
  Malformed/nonobject JSON, symlink/nonregular settings, unsafe paths, or a busy settings lock fail without replacing settings. The installer coordinates with Pi's cooperative settings lock and uses atomic replacement; it does not guarantee safety against noncooperating writers or malicious concurrent directory replacement. Already-fullscreen settings remain byte-identical. Native installation failure leaves settings untouched; `GENTLE_PI_SKIP_GENTLE_AI_INSTALL=1` skips only native provisioning, not the recognized global fullscreen setting.
236
236
 
237
- ### RDD history and opt-in
237
+ ### RDD history and default
238
238
 
239
239
  Native RDD was introduced in `gentle-pi` `v0.15.0` on 2026-07-10 with bounded review transactions. The current stable release, [`v3.5.1`](https://github.com/Gentleman-Programming/gentle-shell/releases/tag/v3.5.1), includes native RDD:
240
240
 
@@ -243,9 +243,9 @@ Native RDD was introduced in `gentle-pi` `v0.15.0` on 2026-07-10 with bounded re
243
243
  pi install npm:gentle-pi@3.5.1
244
244
  ```
245
245
 
246
- RDD remains opt-in. Enable it only through an explicit user decision with `/gentle:review-mode enable`; `status` lets you inspect the mode without changing it. The `.git/gentle-ai/candidate-views` parent must sit on a filesystem that honors private POSIX modes (or equivalent Windows ACLs); WSL DrvFS mounts without metadata can reject START before lineage creation.
246
+ RDD is optional and on by default (since Gentle AI v4.0.0). Turn it off anytime with `/gentle:review-mode disable` for this clone or `gentle-ai review mode disable` machine-wide; `/gentle:review-mode enable` only clears a clone-local off, and `status` lets you inspect the mode without changing it. The `.git/gentle-ai/candidate-views` parent must sit on a filesystem that honors private POSIX modes (or equivalent Windows ACLs); WSL DrvFS mounts without metadata can reject START before lineage creation.
247
247
 
248
- The source checkout's RDD integration installs Gentle AI only into its private `.gentle-ai/` directory. Darwin and Linux use pinned release assets with asset and executable SHA-256 verification (signed archives for source pin `v4.2.0`; raw prerelease binaries only under a prerelease pin). Windows x64 and arm64 build the exact `v4.2.0` source tag with a local Go 1.25.10+ toolchain, a sealed Go environment, `GOTOOLCHAIN=local`, and `GOSUMDB=sum.golang.org`; it does not download Go automatically (the [installation wizard](install-wizard.md#pinned-go) can put its own pinned Go first on PATH for that build). Go runs in a short private directory under the system temp directory, never inside the package, because a deep pnpm store path pushes Go's working directories past MAX_PATH; a failed build prints its whole cause chain with the failing command's output tail. Windows provenance is Go-toolchain plus SumDB evidence and postinstall tamper detection, **not** Authenticode or protection against a malicious joint binary-and-manifest replacement. Package-private locks coordinate cooperative concurrent or crashed installers; their tombstones fail closed. A malicious same-user process with write access to package-private `node_modules` is outside that protocol because it can already replace package code, binary, or manifest, and portable Node has no pathname-delete CAS. It never uses `PATH` or a global `gentle-ai` installation. For development or offline installs only, set `GENTLE_PI_SKIP_GENTLE_AI_INSTALL=1`; native review operations then fail closed with an actionable `package-local-binary-missing` error. To recover explicitly, if `GENTLE_PI_SKIP_GENTLE_AI_INSTALL` is set, remove or unset it before changing to the installed `gentle-pi` package directory. Then run `node scripts/install-gentle-ai.mjs`. This invokes the package-owned installer without relying on a global binary or npm configuration change. A missing binary can result from skipped lifecycle scripts, but does not prove that lifecycle scripts were disabled.
248
+ The source checkout's RDD integration installs Gentle AI only into its private `.gentle-ai/` directory. Darwin and Linux use pinned release assets with asset and executable SHA-256 verification (signed archives for source pin `v4.3.1`; raw prerelease binaries only under a prerelease pin). Windows x64 and arm64 build the exact `v4.3.1` source tag with a local Go 1.25.10+ toolchain, a sealed Go environment, `GOTOOLCHAIN=local`, and `GOSUMDB=sum.golang.org`; it does not download Go automatically (the [installation wizard](install-wizard.md#pinned-go) can put its own pinned Go first on PATH for that build). Go runs in a short private directory under the system temp directory, never inside the package, because a deep pnpm store path pushes Go's working directories past MAX_PATH; a failed build prints its whole cause chain with the failing command's output tail. Windows provenance is Go-toolchain plus SumDB evidence and postinstall tamper detection, **not** Authenticode or protection against a malicious joint binary-and-manifest replacement. Package-private locks coordinate cooperative concurrent or crashed installers; their tombstones fail closed. A malicious same-user process with write access to package-private `node_modules` is outside that protocol because it can already replace package code, binary, or manifest, and portable Node has no pathname-delete CAS. It never uses `PATH` or a global `gentle-ai` installation. For development or offline installs only, set `GENTLE_PI_SKIP_GENTLE_AI_INSTALL=1`; native review operations then fail closed with an actionable `package-local-binary-missing` error. To recover explicitly, if `GENTLE_PI_SKIP_GENTLE_AI_INSTALL` is set, remove or unset it before changing to the installed `gentle-pi` package directory. Then run `node scripts/install-gentle-ai.mjs`. This invokes the package-owned installer without relying on a global binary or npm configuration change. A missing binary can result from skipped lifecycle scripts, but does not prove that lifecycle scripts were disabled.
249
249
 
250
250
  Recommended companion packages, into the standalone `gentle-shell` home:
251
251
 
@@ -304,6 +304,7 @@ gentle-shell home [link|isolated|<path>]
304
304
  gentle-shell [home selectors] setup [--dry-run]
305
305
  gentle-shell upgrade [--channel release|main]
306
306
  gentle-shell upgrade --rollback
307
+ gentle-shell update [pi|self|--self|--all] --latest
307
308
  gentle-shell self-uninstall [--dry-run] [--yes] [--include-shared]
308
309
  ```
309
310
 
@@ -378,17 +379,17 @@ Tradeoff: `--link` shares one credential store with pi; `import-pi` duplicates i
378
379
 
379
380
  `gentle-shell list` and extension updates follow that same home selection. `gentle-shell update --extensions-only` preserves Pi's extension-only command; `--extensions`, package targets, and model updates also stay with Pi.
380
381
 
381
- `gentle-shell update` updates the selected Pi through its verified npm or pnpm global owner, avoiding Pi's self-update refusal for pnpm v11 linked stores. Ownership requires successful global listing JSON, an exact canonical listed package-root/CLI match, and binding to the selected runtime. An adjacent peer (the launcher's `bundled` runtime) is supplied by the exact listed `gentle-pi` package: that Shell package is reinstalled at its current version so the manager re-resolves the peer, and a separate global Pi is never the target, because updating it leaves the peer a Shell install runs unchanged. A `PATH` or `GENTLE_SHELL_PI` runtime is supplied only by its own listed global Pi package; when that executable is a package-manager shim (pnpm's POSIX shim, a `.cmd`), Shell follows the single `dist/bundle/cli.js` it names, relative to the shim's directory, and refuses shims naming none or several. Pi and Shell are never installed together in a comma group, and unrelated packages are never reinstalled. Merely residing under `PNPM_HOME` proves nothing. Adjacent peers resolve where the package manager places them: nested under the Shell package (npm), beside it in pnpm's linked store, or in the global group's own `node_modules`. npm source/link entries are rejected. pnpm updates additionally require that the actual old global group contains only the target top-level package: aggregated listings may contain other, separate groups, but shared groups are rejected because pnpm can remove the whole old group. Unknown, malformed, failed, or ambiguous ownership refuses before installation; update source checkouts and other unsupported layouts with their supplying package manager.
382
+ `gentle-shell update` updates the selected Pi through its verified npm or pnpm global owner, avoiding Pi's self-update refusal for pnpm v11 linked stores. Ownership requires successful global listing JSON, an exact canonical listed package-root/CLI match, and binding to the selected runtime. An adjacent peer (the launcher's `bundled` runtime) is supplied by the exact listed `gentle-pi` package: that Shell package is reinstalled at its current version so the manager re-resolves the peer (a main-channel `<version>-main.<sha12>` Shell, which is never published, from the tarball `gentle-shell upgrade --channel main` packed under `<config home>/main/packages/` (an absolute `GENTLE_PI_CONFIG_HOME`, else `~/.pi/gentle-ai`; a relative override is refused), refusing without installation when it is missing and naming `gentle-shell upgrade --channel release` then `--channel main` as the rebuild path), and a separate global Pi is never the target, because updating it leaves the peer a Shell install runs unchanged. A `PATH` or `GENTLE_SHELL_PI` runtime is supplied only by its own listed global Pi package; when that executable is a package-manager shim (pnpm's POSIX shim, a `.cmd`), Shell follows the single `dist/bundle/cli.js` it names, relative to the shim's directory, and refuses shims naming none or several. Pi and Shell are never installed together in a comma group, and unrelated packages are never reinstalled. Merely residing under `PNPM_HOME` proves nothing. Adjacent peers resolve where the package manager places them: nested under the Shell package (npm), beside it in pnpm's linked store, or in the global group's own `node_modules`. npm source/link entries are rejected. pnpm updates additionally require that the actual old global group contains only the target top-level package: aggregated listings may contain other, separate groups, but shared groups are rejected because pnpm can remove the whole old group. Unknown, malformed, failed, or ambiguous ownership refuses before installation; update source checkouts and other unsupported layouts with their supplying package manager.
382
383
 
383
384
  After a successful install, Shell reads the supplied Pi version back from a fresh global listing and reports it, naming the previous version when it changed. An unchanged pnpm result also names pnpm's `minimumReleaseAge` setting: pnpm installs only releases older than that age (pnpm 11 defaults to 4320 minutes), so a very recent Pi release is picked up once it is old enough; Shell reports the rule rather than overriding it. Both the listing and the install run from the system temporary directory, so a project's `packageManager` pin in the current directory never changes which pnpm answers. When the version cannot be read back, the output says so and points at `gentle-shell --version`.
384
385
 
385
- Prefix-bundled installations keep their existing `gentle-shell upgrade` route for Pi. `update --all` updates the verified owner before forwarding extension updates; an ownership refusal stops without mutation. Shell's `upgrade` and `self-uninstall` ownership behavior is unchanged.
386
+ Prefix-bundled installations keep their existing `gentle-shell upgrade` route for Pi, or `gentle-shell update --latest` for the newest published Pi without the release's verified lockfile (see [`upgrade`](#upgrade-subcommand-and-channels)). Outside a bundled install `--latest` changes nothing: `update` already installs the latest Pi. `update --all` updates the verified owner before forwarding extension updates; an ownership refusal stops without mutation. Shell's `upgrade` and `self-uninstall` ownership behavior is unchanged.
386
387
 
387
388
  ### `setup` subcommand
388
389
 
389
- **Bundled Engram safety:** a fresh state uses the checksum-pinned Engram 3.4.0: before Pi starts, Shell provisions the new store's identity with that core and records it, so later launches keep using it, and a store Shell did not provision is never adopted. A running server is reused only through Engram's exact `GET /compatibility` ready contract, or when it is Shell's own store with the recorded `/health` instance and the exact bundled core version. Anything else (foreign or unknown data, provenance mismatch, a newer schema in the database header, a token-protected or unknown server) disables memory with an explanation of the missing safety evidence and backup precautions (matching versions or updating alone do not prove compatibility), and Shell points `ENGRAM_BIN` at its own guard (`bin/engram-guard`), which fails before any store access for every gentle-engram from 0.4.1 on, whichever Pi route loaded it. No compatibility is inferred from versions. An explicit `ENGRAM_BIN` or `ENGRAM_URL` is never replaced and bypasses the guard. Every launch also pins `npm:gentle-engram@0.4.2` through Pi's own `install` command and verifies `engram.startupPolicy: 1`; a failed check is reported and Shell still starts. See [bundled startup safety](bundled-install.md#engram-startup-safety) for the full rules and known limits.
390
+ **Bundled Engram safety:** Shell shares the global Engram server on `127.0.0.1:7437`, like other agents' hooks. A running server is reused only through Engram's exact `GET /compatibility` ready contract; when nothing listens, Shell starts the checksum-pinned Engram 3.5.2 core as a detached `engram serve` (Engram's default port and `~/.engram`, no update check, no GitHub tokens) and waits up to 10 seconds for that same contract, so you never start the server yourself. An existing store does not disable memory by itself, whoever created it; only a database header from a newer Engram schema keeps Shell from starting its older core on it. Anything else (a server that does not verify, a token-protected or unknown server, a start that fails or never reports ready) disables memory for that launch with an explanation of the missing safety evidence and backup precautions (matching versions or updating alone do not prove compatibility); Shell never stops or replaces a listening server. Shell always points `ENGRAM_BIN` at its own guard (`bin/engram-guard`), which fails before any store access for every gentle-engram from 0.4.1 on, whichever Pi route loaded it, so memory reaches the store only through the verified server's `ENGRAM_URL`. No compatibility is inferred from versions. An explicit `ENGRAM_BIN` or `ENGRAM_URL` is never replaced and bypasses the guard. Every launch also pins `npm:gentle-engram@0.4.2` through Pi's own `install` command and verifies `engram.startupPolicy: 1`; a failed check is reported and Shell still starts. See [bundled startup safety](bundled-install.md#engram-startup-safety) for the full rules and known limits.
390
391
 
391
- The memory decision never skips or fails bundled setup: it always publishes the verified core, runs Gentle AI and pins the companion, then only selects the Engram environment (core or guard) for setup children and the launched Pi. `--dry-run` installs nothing. Non-bundled setup keeps the existing behavior described below.
392
+ The memory decision never skips or fails bundled setup: it always publishes the verified core, runs Gentle AI and pins the companion, then only selects the Engram environment (the guard as `ENGRAM_BIN`, plus `ENGRAM_URL` when memory is allowed) for setup children and the launched Pi. `--dry-run` installs nothing. Non-bundled setup keeps the existing behavior described below.
392
393
 
393
394
  `gentle-shell setup` provisions the resolved home — the same home selection as any other invocation, `--isolated` by default, or `--link`/`--home <path>` when given before `setup` — with the same companion packages a regular `gentle-ai install --agent pi` installs into a Pi agent home: `npm:gentle-pi`, `npm:gentle-engram`, `npm:@juicesharp/rpiv-ask-user-question`, `npm:pi-web-access`, `npm:pi-btw`, plus running `pi-engram init`. It never touches `~/.pi/agent` unless you pass `--link`.
394
395
 
@@ -438,7 +439,7 @@ If none resolve, `gentle-shell` exits 1 naming all three options. Once a runtime
438
439
  | `GENTLE_SHELL_NO_AUTO_SETUP` | Set to `1` to skip automatic first-run provisioning (see "First run in an isolated or custom home" below). |
439
440
  | `ENGRAM_STARTUP_POLICY` | Bundled startup recomputes `allow` or `disabled` from safety evidence. Explicit empty/invalid values remain disabled; user `allow` does not override unknown data. Standalone provider behavior with the variable absent is unchanged. |
440
441
  | `ENGRAM_STARTUP_NOTICE` | Display-only recovery guidance; never executed. |
441
- | `ENGRAM_BIN`, `ENGRAM_URL`, `ENGRAM_PORT`, `ENGRAM_DATA_DIR`, `ENGRAM_DATABASE_URL` | Explicit selections are not probed by Shell and keep bundled memory disabled. An explicit `ENGRAM_BIN` or `ENGRAM_URL` is never replaced and bypasses the guard (an `ENGRAM_URL` alone still gets the verified core, or the guard, as `ENGRAM_BIN`); without them, bundled Shell sets `ENGRAM_BIN` (core or guard) and, for verified reuse, `ENGRAM_URL`. |
442
+ | `ENGRAM_BIN`, `ENGRAM_URL`, `ENGRAM_PORT`, `ENGRAM_DATA_DIR`, `ENGRAM_DATABASE_URL`, `ENGRAM_SERVER_MODE` | Explicit selections are not probed by Shell and keep bundled memory disabled. An explicit `ENGRAM_BIN` or `ENGRAM_URL` is never replaced and bypasses the guard (an `ENGRAM_URL` alone still gets the verified core, or the guard, as `ENGRAM_BIN`); without them, bundled Shell sets `ENGRAM_BIN` to the guard and, for verified reuse, `ENGRAM_URL`. |
442
443
 
443
444
  ### Loading the package
444
445
 
@@ -555,6 +556,7 @@ every `update` form that updates Pi itself explains that and runs
555
556
  `gentle-shell upgrade` (in a terminal) or names it. Those forms are no target,
556
557
  `--self`, `self` or `pi`, `--all`, and `self` or `pi` with `--extensions`. The
557
558
  extension part of an "all" form, and every package update, still reaches Pi.
559
+ `gentle-shell update --latest` (also with `pi`, `self`, `--self` or `--all`) installs the newest published stable Pi with the active Gentle Shell instead, without the release's verified lockfile: it first warns that Gentle Shell features relying on audited Pi internals (such as the Vim editor) may turn off until a Gentle Shell release verifies that Pi, then verifies and switches to it like `upgrade`, keeping the previous version for `gentle-shell upgrade --rollback`. Afterwards `gentle-shell upgrade` never downgrades that Pi: a release of the same Gentle Shell with an older verified Pi changes nothing, and a newer Gentle Shell release upgrades as usual. When the active Pi is already newer than the published `latest` (the dist-tag moved back), `--latest` changes nothing. Outside a bundled install, `gentle-shell update --latest` is the ordinary managed Pi update, which already installs the newest published Pi.
558
560
  In a bundled install Pi and the agent's commands keep your own environment;
559
561
  Pi installs packages with Gentle Shell's npm through the `npmCommand` setting
560
562
  of its own home. Details: [Bundled install](bundled-install.md#launcher-in-a-bundled-install).
@@ -657,8 +659,7 @@ Synthetic tests prove the observer's behavior, not the cause of issue #213. A ne
657
659
  ```text
658
660
  /gentle:status Check package assets and global model config.
659
661
  /gentle:doctor Run read-only diagnostics for assets, config, tools, guards, and Herdr setup.
660
- /gentle:models Assign global model/effort routing to packaged/custom agents.
661
- /gentle:profiles Create, switch, and manage global agent-model profiles.
662
+ /gentle:profiles Open the models screen on this repository's profile. Subcommands: export <name>, import, publish <name>, export-routing, restore-routing.
662
663
  /gentle:persona Switch between gentleman and neutral persona modes.
663
664
  /gentle:background-subagents Show or set the managed background-subagents policy, with its deciding source.
664
665
  /gentle:review-mode Show or set the receipt-driven development mode (status|enable|disable).
@@ -721,7 +722,7 @@ parent git/status + clarify → one worker writes authorized fixes → focused v
721
722
 
722
723
  A second admission check stops small-task delegation: in the primary session, a `gentle-ai-worker` or `worker` launch is admitted only when its task or context has a line that starts with `Spec: odd/tasks/<feature>.md` and names a task `T<n>` later on that line (for example `, T2, S3` or the delegation card's `(read until "## Log"). Do T2; S3.`), where the document is a regular file under the writer root's `odd/tasks/` after resolving symlinks, or when the parent's measured context reaches the context backstop described below. Otherwise the launch is rejected with an instruction to write the unit inline. Judgment Day fix agents, read-only subagents, and continuations are not affected.
723
724
 
724
- A third admission check keeps the independent verifier for high-risk changes: in the primary session, a `gentle-ai-verify` launch is admitted only when its task or context has a line that starts with `Risk:` (optionally as a list item) and names a Task Size high-risk item first, in the form `Risk: item N` with N from 1 to 6 (several items are allowed, for example `Risk: item 2, item 3 (reason)`), or when it carries a feature-document task line the writer check above accepts, or when the parent's measured context reaches the context backstop. `Risk: none` or no line is rejected with an instruction to run the change's focused test and suite inline, not to retry the launch, and never to add a Risk line or create a feature document only to get a verifier admitted. Subagent children, continuations, writers, Judgment Day agents, native review relays, and read-only explorers are not affected.
725
+ A third admission check keeps the independent verifier for high-risk changes: in the primary session, a `gentle-ai-verify` launch is admitted only when its task or context has a declaration that starts a line (optionally as a list item) or a sentence (after `.`, `!` or `?` and a space) with `Risk:` and names a Task Size high-risk item first, in the form `Risk: item N` with N from 1 to 6 (several items are allowed, for example `Risk: item 2, item 3 (reason)`), or when it carries a feature-document task line the writer check above accepts, or when the parent's measured context reaches the context backstop. `Risk: none`, a mention inside a sentence, or no declaration is rejected with an instruction to run the change's focused test and suite inline, not to retry the launch, and never to add a Risk line or create a feature document only to get a verifier admitted. Subagent children, continuations, writers, Judgment Day agents, native review relays, and read-only explorers are not affected.
725
726
 
726
727
  Every subagent child runs with its own `TMPDIR` (also `TMP` and `TEMP` on Windows): a fresh `gaXXXXXX` directory created under the inherited temp directory (joined to the inherited value as given, never its real path), so scratch the child makes with `mktemp` stays out of the worktree. The runtime removes that directory and everything in it when the child ends, including a failed launch. A quarantined child, whose process exit is unconfirmed, keeps its directory under the system temp directory, because a surviving descendant may still use it; once its exit is proven, including a process group that ends after the child's own exit, the directory is removed and the slot is freed. Each continuation is a new child with a new directory.
727
728
 
@@ -810,7 +811,7 @@ flowchart TD
810
811
 
811
812
  VALIDATE is informational. Commit, push, PR, and release commands follow ordinary repository policy; RDD never authorizes, rewrites, consumes review state for, or blocks them. Dangerous-command safety and destructive-review consent remain independent.
812
813
 
813
- For the source checkout, native contract pairing is exact: this adapter resolves only the integrity-verified package-local Gentle AI v4.2.0 executable, independently hashes it, then negotiates `gentle-ai.review-integration/v2` outside the repository. Capabilities are cached by that executable digest. Every START, target status, FINALIZE, and validate request passes the same contract identifier. Negotiated envelopes decode exactly against the vendored schemas; `recover` routes only the provider-selected `action_disposition`, and optional additions require a future compatible schema/minor that the provider explicitly advertises and the consumer negotiates.
814
+ For the source checkout, native contract pairing is exact: this adapter resolves only the integrity-verified package-local Gentle AI v4.3.1 executable, independently hashes it, then negotiates `gentle-ai.review-integration/v2` outside the repository. Capabilities are cached by that executable digest. Every START, target status, FINALIZE, and validate request passes the same contract identifier. Negotiated envelopes decode exactly against the vendored schemas; `recover` routes only the provider-selected `action_disposition`, and optional additions require a future compatible schema/minor that the provider explicitly advertises and the consumer negotiates.
814
815
 
815
816
  Contract `/v2` replaces the Base64 `candidate_diff` reviewer transport of `/v1` with immutable `base_tree`/`candidate_tree` plus an ordered `changed_path_manifest` and never an inline patch. `gentle-pi` negotiates `/v2` only, with no dual-lane fallback; the cutover landed as one atomic commit against gentle-ai v2.2.2 (tracked by the `migrate-review-integration-v2` change), and the `/v1` schemas stay packaged because the `/v2` schemas `$ref` into their fragments. This provider contract version is unrelated to Pi's own internal "compact-v2" review-authority naming used below — the shared digit is coincidental, not a version pairing.
816
817
 
@@ -820,7 +821,7 @@ Candidate views materialize tracked Git symlinks from their frozen blobs even wh
820
821
 
821
822
  On POSIX, if START rejects a group- or world-accessible `.git/gentle-ai/candidate-views` parent, Pi reports `candidate-owner-parent-privacy` before native START. When a sanitized probe shows the filesystem cannot represent private POSIX modes (for example WSL DrvFS mounts without `metadata`), Pi instead reports `candidate-owner-parent-chmod-ineffective` with guidance to move the Git common directory to a POSIX-metadata filesystem or enable metadata support. Inspect that parent's ownership and permissions and correct them out of band before retrying; Pi does not change them automatically. Other owner-preparation failures retain a generic diagnostic rather than exposing filesystem errors.
822
823
 
823
- Once the source checkout's pinned gentle-ai runtime (currently v4.2.0) has written review authority, rollback MUST preserve every native store and receipt and MUST NOT run a downgraded binary against that repository. Disable the Pi route or roll forward to a compatible authority-aware release instead; deleting authority data or reinstalling an older binary is not a rollback path.
824
+ Once the source checkout's pinned gentle-ai runtime (currently v4.3.1) has written review authority, rollback MUST preserve every native store and receipt and MUST NOT run a downgraded binary against that repository. Disable the Pi route or roll forward to a compatible authority-aware release instead; deleting authority data or reinstalling an older binary is not a rollback path.
824
825
 
825
826
  ### FINALIZE wrapper input
826
827
 
@@ -1006,15 +1007,41 @@ A project can still override the global default with:
1006
1007
  ## Model and effort assignment
1007
1008
 
1008
1009
  ```text
1009
- /gentle:models
1010
+ /gentle:profiles
1011
+ ```
1012
+
1013
+ `/gentle:profiles` opens the models screen on the profile this repository resolves: one table, with your profiles as tabs across the top. It replaces the retired `/gentle:models`, which opened the same screen.
1014
+
1015
+ ```text
1016
+ ╭──────────────────────────────────────────────────────────────────────────────╮
1017
+ │ current ◉★ ▾ before-nan-202609… nan GPT-Max + New │
1018
+ │ ─━━━━━━━━━━━━━━───────────────────────────────────────────────────────────── │
1019
+ │ current Used in this session. Default for new sessions. │
1020
+ │ │
1021
+ │ ▸ Orchestrator openai-codex/gpt-6.1-sol max │
1022
+ │ ────────────────────────────────────────────────────────────── │
1023
+ │ Agent Model ▾ Effort ▾ │
1024
+ │ gentle-ai-explore nan/deepseek-v4-flash high │
1025
+ │ gentle-ai-worker nan/glm5.3-flash high │
1026
+ │ │
1027
+ │ [ Use in this session ] [ Make default ] [ Save ] Saved │
1028
+ ╰──────────────────────────────────────────────────────────────────────────────╯
1010
1029
  ```
1011
1030
 
1012
- The modal discovers:
1031
+ - **Tabs are profiles.** Click a tab or press `←` `→` to show another one; the screen redraws in place. Symbols show where a profile is in effect: `◉` this session, `★` the default for new sessions, `⌂` this repository. Leaving a profile with unsaved changes asks first: **Save and switch**, **Discard**, or **Stay**.
1032
+ - **The table is that profile's routing.** The orchestrator is the first row; agents follow. Click a model or press `enter` to choose from a searchable list (the current one is marked `✓`; **Custom model id…** takes any `provider/model`). Click an effort or press `e` to pick from a single row of levels: only the levels that row's model supports, as its provider's catalog declares them (every level when the row inherits its model or the model is not in the catalog). Pi lands an unsupported level on the nearest supported one at launch, and the table says where: `max → high`. Click `Model ▾` or `Effort ▾`, or move the cursor to that header, to change every agent at once; the orchestrator is never part of that.
1033
+ - **Three buttons decide where it applies.** **Use in this session** (`u`) binds what you see to this Pi session only and switches its orchestrator; nothing shared is written. **Make default** (`d`) makes it the default for new sessions through the guarded global apply (diff confirmation, pin honesty, rollback). **Save** (`s` or `ctrl+s`) writes what you see into the profile. Use and Make default save pending edits first and say so.
1034
+ - **The profile menu**, `▾` on the active tab (`m`), holds **Rename**, **Duplicate**, **Use in this repo** (the clone pin; it reads **Stop using in this repo** when it already applies), and **Delete**. **+ New** (`n`) starts a profile as a copy of the current one, from what is running now, or empty.
1035
+ - Problems the screen will not hide appear under the profile name with `⚠`: a pin file that is not a valid pin or names a profile that does not exist (either way it is ignored), and routing keys no agent matches (ignored at launch), with the agent name it probably meant when there is one.
1036
+ - Edited values are highlighted until saved, and the footer counts them (`● 2 unsaved`). `esc` closes; with unsaved edits the first press warns and the second closes without saving. Every action reports on the line under the footer.
1037
+ - Everything clickable highlights under the pointer, and a click runs one action. Keys: `←→` profile, `↑↓` agent, `enter` model, `e` effort, `s` save, `u` use, `d` default, `n` new, `m` the profile menu, `esc` close.
1038
+
1039
+ The editor discovers:
1013
1040
 
1014
1041
  - project agents in `.pi/subagents/`, `.pi/agents/`, and `.agents/`;
1015
1042
  - user agents in `~/.pi/agent/subagents/`, `~/.pi/agent/agents/`, and `~/.agents/`.
1016
1043
 
1017
- When applying routing, project agents write runtime profiles to `.pi/subagents.json`; global and built-in agents write profiles to `~/.pi/agent/subagents.json`.
1044
+ When **Make default** applies a profile, project agents write runtime profiles to `.pi/subagents.json`; global and built-in agents write profiles to `~/.pi/agent/subagents.json`.
1018
1045
 
1019
1046
  Recommended model/effort shape:
1020
1047
 
@@ -1031,13 +1058,11 @@ Saved globally at:
1031
1058
  ~/.pi/gentle-ai/models.json
1032
1059
  ```
1033
1060
 
1034
- Existing project-local `.pi/gentle-ai/models.json` files are still read as a legacy fallback when no global model config exists, but `/gentle:models` writes the shared global config.
1035
-
1036
- Startup and reload materialize saved non-empty routing, but never treat a saved empty agent entry (`{}`) as permission to delete an existing `subagents.json` model profile or agent frontmatter. This also preserves previously materialized routes and routes whose agent definition is missing. To clear routing, explicitly save an inherit choice in `/gentle:models` or confirm a profile replacement in `/gentle:profiles`. Activation needs no ownership sidecar or lock.
1061
+ Global routing is owned by profiles: edit a profile's routing on the models screen and apply it with **Make default**. Applying writes the shared global config at `~/.pi/gentle-ai/models.json`; existing project-local `.pi/gentle-ai/models.json` files are still read as a legacy fallback when no global model config exists.
1037
1062
 
1038
- Inside `/gentle:models`, press `x` to export the saved routing to `~/.pi/gentle-ai/models.export.json`, or `r` to restore from that file after confirmation. Export uses a versioned envelope and restore writes the normal `models.json` shape before applying routing to agents.
1063
+ Startup and reload materialize saved non-empty routing, but never treat a saved empty agent entry (`{}`) as permission to delete an existing `subagents.json` model profile or agent frontmatter. This also preserves previously materialized routes and routes whose agent definition is missing. To clear routing, make a profile whose entries are inherit the default (or confirm a profile replacement) on the models screen. Activation needs no ownership sidecar or lock.
1039
1064
 
1040
- Press `u` to save global agent routing like `ctrl+s`, then capture that routing plus this session's orchestrator model and thinking level in the current profile. If this session has no model, `u` falls back to the orchestrator defaults in `settings.json`; it never changes those defaults. `/gentle:profiles` `s` follows the same rule for the orchestrator: the live session when available, the `settings.json` defaults otherwise. The panel names the profile `u` targets: the profile this repository pins when a pin wins, otherwise the globally active profile. When no profiles store exists yet, `u` seeds it with a `current` profile the way `/gentle:profiles` does on first open; when the store exists but nothing is active and nothing is pinned, the global save still happens and the panel points you to `/gentle:profiles`.
1065
+ `/gentle:profiles export-routing` writes the saved routing to `~/.pi/gentle-ai/models.export.json`, and `/gentle:profiles restore-routing` restores from that file after confirmation. They carry `-routing` because they move the global `models.json` routing, not a profile: `/gentle:profiles export <name>` and `import` move one profile through `profiles.export.json`. Export uses a versioned envelope and restore writes the normal `models.json` shape before applying routing to agents.
1041
1066
 
1042
1067
  Config shape (per agent):
1043
1068
 
@@ -1061,32 +1086,23 @@ Legacy string entries are still accepted and treated as `model`-only config.
1061
1086
  /gentle:profiles
1062
1087
  ```
1063
1088
 
1064
- Profiles are named, switchable snapshots of the global agent-model routing from `/gentle:models`. The panel fills the terminal, shows the profile list on the left, and a detail pane comparing the selected profile's routing with the currently effective routing, one line per agent in shared columns. Keys:
1089
+ Profiles are named, switchable snapshots of the agent-model routing, including the orchestrator. They are the tabs of the models screen described above; everything about choosing, editing, and applying them happens there.
1065
1090
 
1066
- | Key | Action |
1067
- | ------- | ---------------------------------------------------------------------- |
1068
- | `enter` | Bind the selected profile to this parent session. The panel shows it as `name (session)`; launches from this session resolve the binding ahead of pins and the global default, and a profile with an `orchestrator` entry switches the session you are in to that model right away. Nothing is written: no global routing, no pins, no materialized stores. |
1069
- | `a` | Set as global default (the pre-binding `enter` semantics): writes `models.json`, replaces the routing of every agent, sets the orchestrator when the profile defines one. Inside a pinned repository it stays repository-scoped instead; see **Per-repository pins** below. |
1070
- | `c` | Create a new, empty profile. |
1071
- | `s` | Snapshot the current routing into the selected profile, including the orchestrator the session actually runs (live model and thinking level); falls back to the `settings.json` defaults when no live model exists. Live routing is unchanged. |
1072
- | `d` | Duplicate the selected profile. |
1073
- | `r` | Rename the selected profile (keeps it active if it was active). |
1074
- | `x` | Delete the selected profile (refuses the active profile). |
1075
- | `e` | Export the selected profile to `~/.pi/gentle-ai/profiles.export.json`. |
1076
- | `i` | Import a profile from `~/.pi/gentle-ai/profiles.export.json`. |
1077
- | `p` | Pin the selected profile to this repository: writes the clone-local pin, so this repository's subagent launches use that profile no matter which profile is globally active. Pressing it again on the pinned profile removes the pin. |
1078
- | `P` | Publish or remove the shared repository declaration at `<worktree-root>/.pi/gentle-ai/profile.json`, so the whole team starts from that profile in this repository. |
1079
- | `j`/`k`, wheel | Scroll the detail pane one line at a time (agents-view style). |
1080
- | `pgup`/`pgdn`, `ctrl+j`/`ctrl+k` | Scroll the detail pane by a page. |
1081
- | `esc` | Close. |
1091
+ The file operations are subcommands:
1082
1092
 
1083
- Selecting a profile with Enter does not write `profiles.json`, `models.json`, Pi's global `settings.json`, agent frontmatter, `subagents.json`, or repository pins. Other open sessions keep their own bindings and live orchestrators. The session binding overrides pins and global routing as a complete snapshot, including reviewer routing; omitted roles do not fall back to another profile. The binding lasts in the current process (including `/reload`); resuming in another process requires selecting it again.
1093
+ | Command | Action |
1094
+ | ------------------------------------ | ------ |
1095
+ | `/gentle:profiles export <name>` | Export a profile to `~/.pi/gentle-ai/profiles.export.json`. |
1096
+ | `/gentle:profiles import` | Import the profile in `~/.pi/gentle-ai/profiles.export.json`, asking before it replaces one with the same name. |
1097
+ | `/gentle:profiles publish <name>` | Publish the shared repository declaration at `<worktree-root>/.pi/gentle-ai/profile.json` so the whole team starts from that profile; run it again to remove the declaration. |
1084
1098
 
1085
- Applying a profile with `a` writes `~/.pi/gentle-ai/models.json`, then reconciles agent frontmatter and `subagents.json` the same way `/gentle:models` does. A profile is a complete snapshot: every discoverable agent it omits returns to inherit, so routing materialized by a previous profile, by `/gentle:models`, or by a migration never survives a switch silently. The active profile is persisted so `/gentle:profiles` reopens with the applied profile marked.
1099
+ The binding made by **Use in this session** writes no shared routing: not `models.json`, Pi's global `settings.json`, agent frontmatter, `subagents.json`, or repository pins. When the table has unsaved edits, they are saved to the profile in `profiles.json` first, exactly as **Save** would, and the screen says so; with no pending edits nothing is written at all. Other open sessions keep their own bindings and live orchestrators. The session binding overrides pins and global routing as a complete snapshot, including reviewer routing; omitted roles do not fall back to another profile. The binding lasts in the current process (including `/reload`); resuming in another process requires selecting it again. Re-selecting re-copies the profile definition from `profiles.json`; later edits to `subagents.json` or agent frontmatter never reach a bound session, in that session or through a re-selection.
1086
1100
 
1087
- A profile also carries the orchestrator under the reserved routing key `orchestrator`. Applying a profile with `a` when it defines one writes `defaultProvider`, `defaultModel`, and `defaultThinkingLevel` to Pi's global `settings.json` (preserving every other key; an unreadable `settings.json` aborts that part and is reported instead of being overwritten) and switches the session you are in to that model and thinking level right away, so the orchestrator answers with the profile's model from the next turn. Binding with `enter` skips the settings write and switches only the session you are in: same live move, nothing persisted. When the model is not in Pi's catalog or its provider has no authentication, `a` still records the default for new sessions and the apply note says this session kept its current model, while `enter` simply reports the refusal. Applying or binding a profile without an `orchestrator` entry never moves the orchestrator, and `s` snapshots the orchestrator the session actually runs together with the routing. `orchestrator` is reserved: it is not a subagent name, is never written to `subagents.json`, and is not counted as a role.
1101
+ Outside a pinned repository, **Make default** writes `~/.pi/gentle-ai/models.json`, then reconciles agent frontmatter and `subagents.json` with the shared materialization rules. When a valid pin wins, it only re-pins this clone to the profile and writes none of `models.json`, materialized routing, `settings.json`, or the active marker (see **Per-repository pins**). A profile is a complete snapshot: every discoverable agent it omits returns to inherit, so routing materialized by a previous profile, by an earlier apply, or by a migration never survives a switch silently. The active profile is persisted so `/gentle:profiles` reopens with the applied profile marked.
1088
1102
 
1089
- The panel's current routing, the `current` seed, and `s` all read the routing in effect: `models.json` where it has an entry, and otherwise the `subagents.json` model profile or frontmatter routing the runtime actually resolves for that agent. A sparse `models.json` therefore never hides routing that is still live. When `profiles.json` is missing, the command seeds one profile named `current` captured from that effective routing, marked active only when it has routing entries. Profiles or routing entries dropped by normalization are named in a warning instead of being lost silently.
1103
+ A profile also carries the orchestrator under the reserved routing key `orchestrator`. Outside a pinned repository, **Make default** on a profile that defines one writes `defaultProvider`, `defaultModel`, and `defaultThinkingLevel` to Pi's global `settings.json` (preserving every other key; an unreadable `settings.json` aborts that part and is reported instead of being overwritten) and switches the session you are in to that model and thinking level right away, so the orchestrator answers with the profile's model from the next turn. **Use in this session** skips the settings write and switches only the session you are in: same live move, nothing persisted. When the model is not in Pi's catalog or its provider has no authentication, **Make default** still records the default for new sessions and says this session kept its current model, while **Use in this session** simply reports the refusal. Applying or binding a profile without an `orchestrator` entry never moves the orchestrator, and **+ New › From what's running now** captures the orchestrator the session actually runs together with the routing. `orchestrator` is reserved: it is not a subagent name, is never written to `subagents.json`, and is not counted as a role.
1104
+
1105
+ The `current` seed and **From what's running now** read the routing in effect. A valid local pin or repository declaration wins first: inside a pinned repository they read the pinned profile's routing. **From what's running now** also prefers this session's binding when it has one. Otherwise they read `models.json` where it has an entry, and the `subagents.json` model profile or frontmatter routing the runtime actually resolves for agents it omits. A sparse `models.json` therefore never hides routing that is still live. When `profiles.json` is missing, the command seeds one profile named `current` captured from that effective routing, marked active only when it has routing entries. Profiles or routing entries dropped by normalization are named in a warning instead of being lost silently.
1090
1106
 
1091
1107
  Saved globally at:
1092
1108
 
@@ -1119,7 +1135,7 @@ Store shape:
1119
1135
 
1120
1136
  The `profiles` values use the same per-agent shape as `models.json`. Profile names are slugs of 1-64 ASCII characters (letters, numbers, `.`, `_`, `-`, starting with a letter or number); names outside ASCII are rejected, as are the reserved object keys `__proto__`, `constructor`, and `prototype`. A rename or duplicate onto an existing name is refused, renaming the active profile keeps it active, and deleting the active profile is refused. Export and import use a single-profile envelope (`kind: "gentle-pi.agent_model_profile"`, `version: 1`) at `~/.pi/gentle-ai/profiles.export.json`.
1121
1137
 
1122
- The store is replaced atomically through a sibling temp file and a rename, so an interrupted write cannot leave truncated JSON behind. Explicit global apply with `a` writes `profiles.json` first and then materializes routing; if materialization fails, the previous active marker and the previous routing are restored, and anything that could not be restored is named in the warning.
1138
+ The store is replaced atomically through a sibling temp file and a rename, so an interrupted write cannot leave truncated JSON behind. **Make default** writes `profiles.json` first and then materializes routing; if materialization fails, the previous active marker is restored, and the previous routing is restored when a profile was active before. With no previously active profile there is no routing to restore: `models.json` keeps the new routing and the warning says so. Anything that could not be restored is named in the warning.
1123
1139
 
1124
1140
  ### Per-repository pins
1125
1141
 
@@ -1129,8 +1145,8 @@ Two pin layers exist, and both hold only a profile name:
1129
1145
 
1130
1146
  | Layer | Path | Written by | Git impact |
1131
1147
  | ----- | ---- | ---------- | ---------- |
1132
- | Local pin | `<git-common-dir>/gentle-ai/profile-pin.json` | `p` | Invisible to git; every worktree of the clone shares it. |
1133
- | Repository declaration | `<worktree-root>/.pi/gentle-ai/profile.json` | `P` | An ordinary repository file; commit it to share the pin with the team. |
1148
+ | Local pin | `<git-common-dir>/gentle-ai/profile-pin.json` | Profile menu `▾` › **Use in this repo** | Invisible to git; every worktree of the clone shares it. |
1149
+ | Repository declaration | `<worktree-root>/.pi/gentle-ai/profile.json` | `/gentle:profiles publish <name>` | An ordinary repository file; commit it to share the pin with the team. |
1134
1150
 
1135
1151
  Both use the same shape, and both are a separate artifact from `profiles.json`:
1136
1152
 
@@ -1150,9 +1166,9 @@ or stale pins fall through to the next valid layer. A session shows the profile
1150
1166
  in `follow` mode, appears within about two seconds while the UI session is active. The indicator is
1151
1167
  omitted if no valid profile remains.
1152
1168
 
1153
- For a given working directory the winner is the local pin, then the repository declaration, then the globally active profile. A session resolves these layers once, when it starts, and keeps the result. `p` and `P` are toggles: pressing one on the profile that already holds that layer removes it, and either key pressed outside a Git worktree writes nothing and says so.
1169
+ For a given working directory the winner is the local pin, then the repository declaration, then the globally active profile. A session resolves these layers once, when it starts, and keeps the result. Both are toggles: using one on the profile that already holds that layer removes it (the menu then reads **Stop using in this repo**), and either one outside a Git worktree writes nothing and says so.
1154
1170
 
1155
- In a pinned repository the pinned profile governs subagent launches: the agents it names take its model and effort, and the agents it omits return to inherit (their own definition, then the default model). The globally active profile and writes made through `/gentle:models` do not reach those launches, which `/gentle:models` reports when it runs inside a pinned repository. `a` follows the same boundary: inside a pinned repository it re-pins that repository instead of writing the global routing, so a global apply can never move another repository's routing. `enter` writes nothing at all: it binds the profile to the current session, which outranks the pin for this session's launches. The panel states which layer won, names the file that holds it, and marks the profile with `(pinned)`.
1171
+ In a pinned repository the pinned profile governs subagent launches: the agents it names take its model and effort, and the agents it omits return to inherit (their own definition, then the default model). The default profile does not reach those launches, which `/gentle:profiles` reports when it runs inside a pinned repository. **Make default** follows the same boundary: when a valid pin wins it re-pins this clone (the clone-local pin) instead of writing the global routing; a malformed pin or one naming a missing profile is ignored, and Make default applies globally as it would outside a pinned repository, so it can never move another repository's routing. A committed repository declaration is never rewritten; when one still names another profile, the clone-local pin takes precedence and the screen says so. **Use in this session** writes no pin or shared routing (only pending table edits, saved to the profile first): it binds the profile to the current session, which outranks the pin for this session's launches. The tab of the pinned profile carries `⌂`.
1156
1172
 
1157
1173
  To share a pin, commit the repository declaration. When `.pi/` is ignored, Git cannot re-include a nested file until its parent directories are visible. The panel therefore prints these ordered root `.gitignore` rules, which keep unrelated `.pi` content ignored while making only the declaration committable:
1158
1174
 
@@ -1164,7 +1180,7 @@ To share a pin, commit the repository declaration. When `.pi/` is ignored, Git c
1164
1180
  !.pi/gentle-ai/profile.json
1165
1181
  ```
1166
1182
 
1167
- Renaming the profile that is this repository's local pin rewrites the local pin; a repository declaration is never rewritten behind a commit, and the panel says to press `P` again when it still names the old profile. Deleting a profile is refused while it is the global active profile, this repository's local pin, or this repository's repository declaration. Pins held by other repositories cannot be enumerated from here and are not checked.
1183
+ Renaming the profile that is this repository's local pin rewrites the local pin; a repository declaration is never rewritten behind a commit, and the rename note says to run `/gentle:profiles publish <name>` again when it still names the old profile. Deleting a profile is refused while it is the global active profile, this repository's local pin, or this repository's repository declaration. Pins held by other repositories cannot be enumerated from here and are not checked.
1168
1184
 
1169
1185
  A pin that cannot be honored never blocks work and is never destroyed by a read. Running outside a Git worktree, an unreadable or unparseable pin file, and a pin naming a profile the global store does not have are reported in the panel, and the repository falls back to the globally active profile. A missing pin layer is the ordinary no-pin state and stays silent.
1170
1186
 
@@ -1187,7 +1203,7 @@ A session that never selected a profile resolves the shared defaults once, at st
1187
1203
  **Drift notice.** On each subagent launch, a session with a frozen profile compares it with the current defaults of its own directory, without applying them. When they differ, it shows one line:
1188
1204
 
1189
1205
  ```text
1190
- el Gentleman: the default profile changed to "local" (local), this session keeps "frontier" (local). Press Enter on a profile in /gentle:profiles to adopt it.
1206
+ el Gentleman: the default profile changed to "local" (local), this session keeps "frontier" (local). Open /gentle:profiles and choose Use in this session to adopt one.
1191
1207
  ```
1192
1208
 
1193
1209
  The notice appears once per distinct change: further launches stay quiet until the defaults change again. The same profile reached through another layer is not a change; an edit of the profile's content is. Sessions with a profile selected in the session, `follow` sessions, and subagent children never show it.
@@ -1208,8 +1224,7 @@ The notice appears once per distinct change: further launches stay quiet until t
1208
1224
  | -------------------------------- | ------------------------------------------------------------------- |
1209
1225
  | `/gentle:status` | Shows package assets and global model config status. |
1210
1226
  | `/gentle:doctor` | Runs read-only diagnostics for assets, model/persona config, memory tools, safety guards, and (inside Herdr) the task-summary sidebar setup. |
1211
- | `/gentle:models` | Opens global model + effort assignment UI. Press `x` to export, `r` to restore saved routing, and `u` to save routing and capture the session in the current profile. |
1212
- | `/gentle:profiles` | Opens global agent-model profiles: apply live, create, snapshot, duplicate, rename, delete, export, and import. |
1227
+ | `/gentle:profiles` | Opens the models screen on this repository's profile. `export <name>`, `import`, and `publish <name>` handle profile files and the repository declaration; `export-routing` and `restore-routing` move the saved global routing through `models.export.json`. |
1213
1228
  | `/gentle:commands` | Opens the command palette (default `alt+k`): a curated, grouped menu (Configuration, Session, Diagnostics, Skills) of registered Gentle commands; search and run by label. |
1214
1229
  | `/gentle:persona` | Switches global persona mode, with project override support. |
1215
1230
  | `/gentle:background-subagents` | Shows or sets the managed background-subagents policy (`status\|enable\|disable`), naming the source that decided it. |
@@ -1249,6 +1264,8 @@ With the policy `on`, `subagent_run` defaults to `mode: "background"` at the run
1249
1264
 
1250
1265
  Background delegation is off unless you turn it on. The policy is user-owned: only an explicit `/gentle:background-subagents enable` or `disable` writes it, and Pi automation never toggles it.
1251
1266
 
1267
+ An agent whose explicit `tools` frontmatter includes `bash_background` fails before spawn when the effective background-subagents policy is `off`, in either task or background mode. Admission resolves policy at dispatch using the request's environment and config home, including queued tasks. The error names the policy file, the exact opt-in shape `{"schema":"gentle-pi.background-subagents/v1","policy":"on"}`, and `/gentle:background-subagents enable|disable|status`. Agents without explicit tools are unchanged; the child missing-tools check remains the backstop for other names. Policy `on` passes this admission check only: it does not implement child background tools (future Slices 2–3).
1268
+
1252
1269
  ```text
1253
1270
  /gentle:background-subagents Report the effective policy, the deciding source, and the resolved capability.
1254
1271
  /gentle:background-subagents enable Write "on" to the global file.
@@ -1330,7 +1347,7 @@ The frame labels INSERT, NORMAL, VISUAL (characterwise), or VISUAL LINE (linewis
1330
1347
 
1331
1348
  **Deliberate `/` divergence from Claude Code:** NORMAL `/` hands off to **Pi's native slash commands and skills**, enters INSERT, and inserts `/` at the existing cursor. Pi offers slash completion only at the start of the first line; elsewhere it inserts a literal slash without moving or replacing the draft. There is **no reverse prompt-history search**. Pi's explicit history shortcuts still work, transferring to INSERT first. Unknown NORMAL printable input, encoded text and bracketed paste do not silently insert; application shortcuts can transfer to INSERT before acting.
1332
1349
 
1333
- This is a bounded command subset, not full Claude Code/Vim parity. The private editor adapter supports only the audited Pi coding-agent/TUI `0.99.1`, `0.99.2`, `1.0.0`, `1.1.0`, and `1.2.0` package pairs. The two 0.99 releases have byte-identical editor and undo-stack sources. Pi 1.0.0, 1.1.0 and 1.2.0 are separately audited against the touched state, paste/history, cursor/layout, autocomplete and undo-snapshot contracts. Pi 1.2.0's paired APC fake-cursor markers remain intact so the host can suppress software cursors when hardware cursors are visible; selection inversion and empty-prompt hints support both these markers and legacy SGR cursors. Current bundled and unbundled 1.2.0 tests prove identity, edit/undo, paste, selection, wrapping/scroll and autocomplete behavior, not old/new byte identity. Fabricated metadata tests preserve exact-version admission coverage for the older audited releases. Version metadata must come from a canonical candidate host package root whose actual `CustomEditor` and `Editor` classes match the loaded classes, never from the extension's local metadata or CLI path alone. Unknown versions, mismatched prototypes, or invalid layouts fail closed: a single compatibility warning is shown and the prompt continues with ordinary editing instead of silently entering inert NORMAL mode. Operations that would cross a registered collapsed paste marker, or encounter duplicate occurrences of a registered marker ID, are rejected without editing it. Visual highlighting relies on Pi's render layout and may be omitted if its geometry cannot be validated. No live-terminal proof of every layout or complete parity is claimed.
1350
+ This is a bounded command subset, not full Claude Code/Vim parity. The private editor adapter supports only the audited Pi coding-agent/TUI `0.99.1`, `0.99.2`, `1.0.0`, `1.1.0`, `1.2.0`, `1.3.0`, and `1.4.0` package pairs. The two 0.99 releases have byte-identical editor and undo-stack sources. Pi 1.0.0, 1.1.0 and 1.2.0 are separately audited against the touched state, paste/history, cursor/layout, autocomplete and undo-snapshot contracts. Pi 1.2.0's paired APC fake-cursor markers remain intact so the host can suppress software cursors when hardware cursors are visible; selection inversion and empty-prompt hints support both these markers and legacy SGR cursors. Current bundled and unbundled 1.2.0 tests prove identity, edit/undo, paste, selection, wrapping/scroll and autocomplete behavior, not old/new byte identity. Fabricated metadata tests preserve exact-version admission coverage for the older audited releases. Version metadata must come from a canonical candidate host package root whose actual `CustomEditor` and `Editor` classes match the loaded classes, never from the extension's local metadata or CLI path alone. Unknown versions, mismatched prototypes, or invalid layouts fail closed: a single compatibility warning is shown and the prompt continues with ordinary editing instead of silently entering inert NORMAL mode. Operations that would cross a registered collapsed paste marker, or encounter duplicate occurrences of a registered marker ID, are rejected without editing it. Visual highlighting relies on Pi's render layout and may be omitted if its geometry cannot be validated. No live-terminal proof of every layout or complete parity is claimed.
1334
1351
 
1335
1352
  Startup banner settings remain global in `banner.json` under `GENTLE_PI_CONFIG_HOME` (default `~/.pi/gentle-ai`). Existing `showRose` and `showTextLogo` opt-outs independently control the main startup artwork; both default to enabled. Changes apply on the next session or `/reload`. Color presets are `pink` (default), `cyan`, `yellow`, and `green`. The static sidebar heading is independent of these preferences and follows the active theme.
1336
1353
 
@@ -37,3 +37,29 @@ does not establish persistence. The newest profile-family entry is terminal:
37
37
  Replay neither appends nor publishes bindings and never applies a model or
38
38
  thinking level. A subsequent disk-reader slice supplies corroboration; this
39
39
  codec alone cannot establish it.
40
+
41
+ ## Disk corroboration
42
+
43
+ `readSessionProfileDisk(source)` in `lib/session-profile-disk-reader.ts` is the
44
+ stateless synchronous check that supplies the corroboration replay requires.
45
+ It reads the session's public active branch and its JSONL file, selects the
46
+ newest profile-family entry on the branch (excluding caller-supplied known
47
+ failed append IDs), and admits it only when the record on disk is identical.
48
+ It performs no writes, fallback policy, caching, ancestry repair or fsync, and
49
+ a missing file is conservative: it never restores a profile found only in
50
+ memory.
51
+
52
+ The result is the decoder result plus `entryIndex` and `lineNumber`, or
53
+ `indeterminate` with one reason: `missing-source`, `invalid-candidate-metadata`,
54
+ `unreadable-file`, `source-changed`, `invalid-record`,
55
+ `session-header-mismatch`, `duplicate-id`, `missing-header`,
56
+ `selected-record-missing`, `selected-record-mismatch`, or
57
+ `unserializable-source` (exported as `DiskProfileIndeterminateReason`).
58
+ Reasons never carry record contents.
59
+
60
+ Malformed JSON lines are skipped, matching Pi's session parser, so a file Pi
61
+ opens never becomes permanently indeterminate here; `lineNumber` still counts
62
+ physical lines. A malformed selected record is therefore
63
+ `selected-record-missing`. `missing-header` means no line parsed at all (an
64
+ empty, all-blank or all-malformed file). Pi writes no byte order mark, so a
65
+ BOM-prefixed header line is skipped as malformed like any other.