gentle-pi 4.3.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.
- package/README.md +8 -5
- package/assets/agents/gentle-ai-worker.md +1 -1
- package/assets/design-canvas/canvas.css +648 -0
- package/assets/design-canvas/canvas.js +1497 -0
- package/assets/design-canvas/index.html +88 -0
- package/assets/design-canvas/inspector.js +290 -0
- package/assets/orchestrator-delegation-reference.md +2 -2
- package/assets/orchestrator-verification.md +1 -1
- package/assets/orchestrator.md +2 -2
- package/bin/engram-guard +1 -1
- package/bin/gentle-shell.mjs +101 -151
- package/docs/bundled-install.md +47 -42
- package/docs/delegated-verification.md +6 -0
- package/docs/gentle-agents-activity.md +5 -1
- package/docs/gentle-music.md +61 -0
- package/docs/gentle-shell.md +77 -7
- package/docs/install-wizard.md +30 -6
- package/docs/permission-modes.md +7 -2
- package/docs/readme-reference.md +19 -15
- package/docs/session-profile-format.md +26 -0
- package/docs/voice.md +259 -0
- package/docs/yolo-mode.md +17 -2
- package/extensions/ask-user-choice.ts +4 -1
- package/extensions/gentle-agents.ts +173 -38
- package/extensions/gentle-ai.ts +214 -69
- package/extensions/gentle-design.ts +158 -0
- package/extensions/gentle-music.ts +289 -0
- package/extensions/gentle-shell.ts +332 -73
- package/extensions/gentle-voice.ts +11 -0
- package/extensions/session-scratch.ts +41 -22
- package/extensions/skill-registry.ts +63 -8
- package/lib/agent-profiles.ts +26 -0
- package/lib/agents-config.ts +35 -0
- package/lib/agents-protocol.ts +57 -1
- package/lib/agents-runner.ts +52 -3
- package/lib/agents-session-transport.ts +101 -6
- package/lib/agents-widget.ts +14 -1
- package/lib/auto-permission-memory.ts +48 -18
- package/lib/auto-permission-runtime.ts +21 -6
- package/lib/clipboard-image.ts +147 -0
- package/lib/command-palette-catalog.ts +2 -0
- package/lib/commit-slice-signal.ts +1 -1
- package/lib/context-backstop.ts +36 -0
- package/lib/design-canvas-server.ts +947 -0
- package/lib/design-comments.ts +437 -0
- package/lib/design-handoffs.ts +313 -0
- package/lib/design-open-browser.ts +58 -0
- package/lib/design-sources.ts +120 -0
- package/lib/external-editor.ts +31 -0
- package/lib/gentle-design.ts +513 -0
- package/lib/gentle-shell-bundled.ts +123 -49
- package/lib/gentle-shell-launcher.ts +9 -4
- package/lib/gentle-shell-startup-update.ts +61 -9
- package/lib/gentle-shell-uninstall.ts +33 -1
- package/lib/image-attachments.ts +150 -0
- package/lib/inprocess-reviewer.ts +33 -2
- package/lib/nan-provider.ts +3 -0
- package/lib/native-review-cli.ts +11 -4
- package/lib/notification-audio-native.ts +149 -13
- package/lib/notification-audio.ts +4 -0
- package/lib/notification-pulse-worker.ts +82 -18
- package/lib/notification-service.ts +5 -1
- package/lib/orchestrator-presence.ts +78 -8
- package/lib/orchestrator-scope.ts +10 -0
- package/lib/orchestrator-state.ts +11 -3
- package/lib/permission-mode-policy.ts +2 -2
- package/lib/review-host-relay.ts +11 -2
- package/lib/review-reminder-receipt.ts +24 -1
- package/lib/session-profile-append-controller.ts +713 -0
- package/lib/session-profile-disk-reader.ts +182 -0
- package/lib/session-profile-persistence.ts +15 -7
- package/lib/session-scratch.ts +52 -3
- package/lib/session-worktree-registry.ts +7 -0
- package/lib/shell-bar.ts +4 -3
- package/lib/shell-changes.ts +81 -5
- package/lib/shell-prompt.ts +4 -4
- package/lib/shell-sidebar-layout.ts +26 -6
- package/lib/shell-todo.ts +1 -1
- package/lib/verifier-admission.ts +5 -4
- package/lib/vim-editor-adapter.ts +11 -8
- package/lib/voice-artifacts.ts +188 -0
- package/lib/voice-command.ts +576 -0
- package/lib/voice-install.ts +455 -0
- package/lib/voice-platform.ts +99 -0
- package/lib/voice-push-to-talk.ts +262 -0
- package/lib/voice-session.ts +460 -0
- package/lib/voice-settings.ts +50 -0
- package/lib/voice-ui.ts +158 -0
- package/lib/yolo-session-policy.ts +58 -22
- package/package.json +1 -1
- package/runtime/gentle-shell-bundled.mjs +122 -48
- package/runtime/gentle-shell-launcher.mjs +9 -4
- package/runtime/gentle-shell-startup-update.mjs +61 -9
- package/runtime/gentle-shell-uninstall.mjs +33 -1
- package/runtime/native-review-cli.mjs +11 -4
- package/scripts/bundled-engram-migration.mjs +0 -6
- package/scripts/gentle-ai-installer.mjs +10 -10
- package/scripts/installer-downloads.mjs +7 -7
- package/scripts/installer-preflight.mjs +5 -3
- package/scripts/installer-windows.mjs +37 -7
- package/scripts/main-channel.mjs +91 -17
- package/scripts/pi-update.mjs +34 -6
- package/scripts/verify-package-files.mjs +26 -2
- package/scripts/voice-worker.cjs +476 -0
- package/skills/design/SKILL.md +110 -0
- package/tests/agent-profiles.test.ts +24 -0
- package/tests/agents-config.test.ts +61 -0
- package/tests/agents-fake-child.ts +8 -1
- package/tests/agents-protocol.test.ts +32 -0
- package/tests/agents-runner.test.ts +226 -5
- package/tests/agents-session-transport.test.ts +53 -3
- package/tests/ask-user-choice.test.ts +30 -0
- package/tests/auto-mode.test.ts +17 -0
- package/tests/auto-permission-memory-diagnostics.test.ts +56 -0
- package/tests/auto-permission-runtime.test.ts +85 -1
- package/tests/autonomous-guard.test.ts +20 -0
- package/tests/bundled-install.test.ts +3 -3
- package/tests/clipboard-image.test.ts +114 -0
- package/tests/command-palette.test.ts +1 -1
- package/tests/context-backstop.test.ts +70 -4
- package/tests/delegate-for-reason-contract.test.ts +2 -1
- package/tests/design-canvas-assets.test.ts +710 -0
- package/tests/design-canvas-server.test.ts +1096 -0
- package/tests/design-comments.test.ts +201 -0
- package/tests/design-handoffs.test.ts +282 -0
- package/tests/design-open-browser.test.ts +70 -0
- package/tests/design-sources.test.ts +132 -0
- package/tests/engram-safety.test.ts +132 -57
- package/tests/external-editor.test.ts +84 -0
- package/tests/fixtures/primary-session-prompt/gentleman.golden.md +3 -3
- package/tests/gentle-agents.test.ts +365 -20
- package/tests/gentle-ai-binary.test.ts +1 -1
- package/tests/gentle-ai-installer.test.ts +51 -51
- package/tests/gentle-ai.test.ts +292 -13
- package/tests/gentle-design.test.ts +1313 -0
- package/tests/gentle-music.test.ts +335 -0
- package/tests/gentle-shell-bundled.test.ts +301 -248
- package/tests/gentle-shell-launcher.test.ts +28 -2
- package/tests/gentle-shell-startup-update.test.ts +77 -1
- package/tests/gentle-shell-uninstall.test.ts +59 -0
- package/tests/gentle-shell.test.ts +183 -8
- package/tests/gentle-todo.test.ts +11 -0
- package/tests/image-attachments.test.ts +119 -0
- package/tests/image-paste-chips.test.ts +236 -0
- package/tests/inprocess-reviewer.test.ts +55 -2
- package/tests/installer-bundles.test.ts +12 -6
- package/tests/installer-posix-bootstrap.test.ts +8 -8
- package/tests/installer-preflight.test.ts +16 -0
- package/tests/installer-server.test.ts +2 -2
- package/tests/installer-windows-bootstrap.test.ts +61 -3
- package/tests/installer-windows-diagnostics.test.ts +111 -0
- package/tests/main-channel-upgrade.test.ts +232 -2
- package/tests/main-channel.test.ts +140 -21
- package/tests/nan-provider.test.ts +36 -0
- package/tests/native-review-capability-contract.test.ts +11 -4
- package/tests/native-review-parity.test.ts +1 -1
- package/tests/notification-audio-native.test.ts +128 -9
- package/tests/notification-customize.test.ts +17 -5
- package/tests/odd-routing-canonical-ratchet.test.ts +2 -1
- package/tests/orchestrator-budget.test.ts +5 -2
- package/tests/orchestrator-presence.test.ts +100 -2
- package/tests/orchestrator-rdd-ownership.test.ts +2 -2
- package/tests/orchestrator-scope.test.ts +14 -0
- package/tests/orchestrator-state.test.ts +29 -0
- package/tests/package-files.test.ts +34 -0
- package/tests/package-manifest.test.ts +6 -6
- package/tests/permission-mode-policy.test.ts +10 -1
- package/tests/pi-update.test.ts +99 -4
- package/tests/rdd-aware-verification-contract.test.ts +1 -1
- package/tests/review-host-relay-routing.test.ts +88 -1
- package/tests/review-host-relay.test.ts +9 -2
- package/tests/review-json-arguments.test.ts +20 -3
- package/tests/review-loadout-rdd-off-sdk.test.ts +23 -2
- package/tests/review-relay-transport-agent.test.ts +26 -0
- package/tests/review-reminder-receipt.test.ts +31 -1
- package/tests/session-changes.test.ts +2 -1
- package/tests/session-profile-append-controller-fork.test.ts +458 -0
- package/tests/session-profile-append-controller-pi.test.ts +290 -0
- package/tests/session-profile-append-controller.test.ts +731 -0
- package/tests/session-profile-disk-reader-pi.test.ts +183 -0
- package/tests/session-profile-disk-reader.test.ts +311 -0
- package/tests/session-scratch.test.ts +68 -2
- package/tests/session-worktree-registry.test.ts +13 -1
- package/tests/shell-bar.test.ts +14 -2
- package/tests/shell-changes.test.ts +148 -1
- package/tests/shell-prompt.test.ts +3 -3
- package/tests/shell-render-cache.test.ts +134 -1
- package/tests/shell-sidebar-layout.test.ts +50 -0
- package/tests/short-check-routing-contract.test.ts +1 -1
- package/tests/skill-collision-prefixes.test.ts +3 -1
- package/tests/skill-registry-watcher.test.ts +17 -5
- package/tests/skill-registry.test.ts +47 -3
- package/tests/task-size-routing-contract.test.ts +1 -1
- package/tests/test-strength-contract.test.ts +1 -1
- package/tests/verifier-admission.test.ts +18 -1
- package/tests/voice-command.test.ts +773 -0
- package/tests/voice-install.test.ts +323 -0
- package/tests/voice-platform.test.ts +176 -0
- package/tests/voice-push-to-talk.test.ts +444 -0
- package/tests/voice-session.test.ts +434 -0
- package/tests/voice-settings.test.ts +49 -0
- package/tests/voice-ui.test.ts +97 -0
- package/tests/voice-worker.test.ts +445 -0
- package/tests/weak-model-economy-prompt.test.ts +32 -0
- package/tests/windows-hidden-processes.test.ts +25 -2
- package/tests/yolo-customize.test.ts +5 -1
- package/tests/yolo-mode.test.ts +1 -1
- package/tests/yolo-session-policy-capture.test.ts +104 -0
package/docs/permission-modes.md
CHANGED
|
@@ -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
|
package/docs/readme-reference.md
CHANGED
|
@@ -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.
|
|
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,7 +218,7 @@ 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.
|
|
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
|
|
|
@@ -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
|
|
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
|
|
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.
|
|
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
|
|
|
@@ -378,7 +378,7 @@ Tradeoff: `--link` shares one credential store with pi; `import-pi` duplicates i
|
|
|
378
378
|
|
|
379
379
|
`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
380
|
|
|
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.
|
|
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 (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
382
|
|
|
383
383
|
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
384
|
|
|
@@ -386,9 +386,9 @@ Prefix-bundled installations keep their existing `gentle-shell upgrade` route fo
|
|
|
386
386
|
|
|
387
387
|
### `setup` subcommand
|
|
388
388
|
|
|
389
|
-
**Bundled Engram safety:**
|
|
389
|
+
**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
390
|
|
|
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 (
|
|
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 (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
392
|
|
|
393
393
|
`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
394
|
|
|
@@ -438,7 +438,7 @@ If none resolve, `gentle-shell` exits 1 naming all three options. Once a runtime
|
|
|
438
438
|
| `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
439
|
| `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
440
|
| `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`
|
|
441
|
+
| `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
442
|
|
|
443
443
|
### Loading the package
|
|
444
444
|
|
|
@@ -657,7 +657,7 @@ Synthetic tests prove the observer's behavior, not the cause of issue #213. A ne
|
|
|
657
657
|
```text
|
|
658
658
|
/gentle:status Check package assets and global model config.
|
|
659
659
|
/gentle:doctor Run read-only diagnostics for assets, config, tools, guards, and Herdr setup.
|
|
660
|
-
/gentle:models Assign global model/effort routing
|
|
660
|
+
/gentle:models Assign global agent model/effort routing and choose a profile orchestrator.
|
|
661
661
|
/gentle:profiles Create, switch, and manage global agent-model profiles.
|
|
662
662
|
/gentle:persona Switch between gentleman and neutral persona modes.
|
|
663
663
|
/gentle:background-subagents Show or set the managed background-subagents policy, with its deciding source.
|
|
@@ -721,7 +721,7 @@ parent git/status + clarify → one worker writes authorized fixes → focused v
|
|
|
721
721
|
|
|
722
722
|
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
723
|
|
|
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
|
|
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 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
725
|
|
|
726
726
|
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
727
|
|
|
@@ -810,7 +810,7 @@ flowchart TD
|
|
|
810
810
|
|
|
811
811
|
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
812
|
|
|
813
|
-
For the source checkout, native contract pairing is exact: this adapter resolves only the integrity-verified package-local Gentle AI v4.
|
|
813
|
+
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
814
|
|
|
815
815
|
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
816
|
|
|
@@ -820,7 +820,7 @@ Candidate views materialize tracked Git symlinks from their frozen blobs even wh
|
|
|
820
820
|
|
|
821
821
|
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
822
|
|
|
823
|
-
Once the source checkout's pinned gentle-ai runtime (currently v4.
|
|
823
|
+
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
824
|
|
|
825
825
|
### FINALIZE wrapper input
|
|
826
826
|
|
|
@@ -1037,7 +1037,9 @@ Startup and reload materialize saved non-empty routing, but never treat a saved
|
|
|
1037
1037
|
|
|
1038
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.
|
|
1039
1039
|
|
|
1040
|
-
|
|
1040
|
+
The `orchestrator` row selects the model and thinking effort that `u` will store in the current profile. Its initial choice is the target profile's saved entry, or **leave untouched** if that profile has no orchestrator key. Without an existing target profile, it uses the live session model and effort, falling back to `settings.json` when no live model exists; changing the row never switches the live session. Choose **leave untouched** in its model picker, or press `i` on the row, to store no `orchestrator` key—even when replacing a profile that previously carried one. Select a model before editing effort. **Set all agents** never changes this row.
|
|
1041
|
+
|
|
1042
|
+
Press `u` to save global agent routing like `ctrl+s`, then snapshot that routing and the explicit orchestrator choice into the current profile. `ctrl+s` saves only agent routing: it neither updates a profile nor applies the chosen orchestrator. Both keys leave orchestrator defaults and the live model/effort unchanged; applying a profile with no orchestrator key preserves both. Custom-model, export and restore reopens retain the choice; exports/restores remain saved-agent-routing operations. `/gentle:profiles` `s` remains unchanged: it captures the live session model/effort 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`.
|
|
1041
1043
|
|
|
1042
1044
|
Config shape (per agent):
|
|
1043
1045
|
|
|
@@ -1080,7 +1082,7 @@ Profiles are named, switchable snapshots of the global agent-model routing from
|
|
|
1080
1082
|
| `pgup`/`pgdn`, `ctrl+j`/`ctrl+k` | Scroll the detail pane by a page. |
|
|
1081
1083
|
| `esc` | Close. |
|
|
1082
1084
|
|
|
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.
|
|
1085
|
+
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. 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.
|
|
1084
1086
|
|
|
1085
1087
|
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.
|
|
1086
1088
|
|
|
@@ -1249,6 +1251,8 @@ With the policy `on`, `subagent_run` defaults to `mode: "background"` at the run
|
|
|
1249
1251
|
|
|
1250
1252
|
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
1253
|
|
|
1254
|
+
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).
|
|
1255
|
+
|
|
1252
1256
|
```text
|
|
1253
1257
|
/gentle:background-subagents Report the effective policy, the deciding source, and the resolved capability.
|
|
1254
1258
|
/gentle:background-subagents enable Write "on" to the global file.
|
|
@@ -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.
|
package/docs/voice.md
ADDED
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
# Optional local voice dictation
|
|
2
|
+
|
|
3
|
+
Voice dictation is optional. It transcribes speech locally with NVIDIA Parakeet
|
|
4
|
+
through sherpa-onnx, with no API key and no cloud inference. Everything happens
|
|
5
|
+
from `/gentle:voice`; nothing described here runs at startup.
|
|
6
|
+
|
|
7
|
+
## Quick path
|
|
8
|
+
|
|
9
|
+
1. Run `/gentle:voice` and choose **Download voice dictation**. The
|
|
10
|
+
confirmation lists each component, its size, the destination directory,
|
|
11
|
+
the licenses and the platform limitations. Esc during the download cancels it.
|
|
12
|
+
2. Run `/gentle:voice` again and choose **Start dictation**. Speak, then press
|
|
13
|
+
Enter to stop. Esc cancels at any point.
|
|
14
|
+
3. The transcript is pasted into the editor draft at the cursor. It is never
|
|
15
|
+
sent automatically. Pi collapses pastes over 1,000 characters or 10 lines into
|
|
16
|
+
a `[paste #N …]` marker; the full text is retained and expanded when you submit.
|
|
17
|
+
Long transcripts are therefore not displayed as editable text in the draft.
|
|
18
|
+
4. Or hold Space in the editor: push-to-talk is turned on by a successful
|
|
19
|
+
download. See [Push-to-talk](#push-to-talk-hold-space).
|
|
20
|
+
|
|
21
|
+
## The command
|
|
22
|
+
|
|
23
|
+
| Topic | Behavior |
|
|
24
|
+
|-------|----------|
|
|
25
|
+
| Menu | Built-in select and confirm dialogs. **Show status and notices** reports the target, both components, limitations and licenses. **Disable push-to-talk (hold Space)** appears while it is on; **Enable push-to-talk (hold Space)** appears only when voice is installed. |
|
|
26
|
+
| Download | Only after the confirmation; runtime first, then the model. A cancelled download keeps components that already finished. |
|
|
27
|
+
| Dictation | A compact overlay shows preparing, recording, transcribing. Enter stops recording; the overlay stays until the transcript is ready. |
|
|
28
|
+
| Recording limit | After 2 minutes recording stops by itself, and the transcript is pasted without a key press. |
|
|
29
|
+
| Insertion | The recognized text goes through Pi's editor paste pipeline, which may collapse long text into a paste marker. A blank result pastes nothing. |
|
|
30
|
+
| One at a time | A second `/gentle:voice` while a download or dictation runs is refused with a notice. A Space hold during either one types spaces as usual. |
|
|
31
|
+
| Cancel and shutdown | Esc, reload or session shutdown aborts the download or cancels the session. A transcript that arrives afterwards is dropped. |
|
|
32
|
+
| Where it runs | Interactive TUI parent sessions only. RPC, print, JSON and delegated child sessions refuse it. No model-callable tool exists. |
|
|
33
|
+
| Errors | Fixed messages with the action to take, such as installing ALSA or the Visual C++ runtime. Gentle AI never runs those installers. |
|
|
34
|
+
|
|
35
|
+
The command is tested with fake dialogs, downloads and sessions only. No real
|
|
36
|
+
download, native load or microphone recording has been exercised through it.
|
|
37
|
+
|
|
38
|
+
## Push-to-talk (hold Space)
|
|
39
|
+
|
|
40
|
+
Hold Space in the editor to record; release it to stop. The transcript is
|
|
41
|
+
pasted at the cursor and never sent. Esc cancels while recording or
|
|
42
|
+
transcribing. A one-line footer status shows preparing, recording and
|
|
43
|
+
transcribing; no overlay opens, so the editor keeps the focus.
|
|
44
|
+
|
|
45
|
+
| Topic | Behavior |
|
|
46
|
+
|-------|----------|
|
|
47
|
+
| Toggle | Stored as `voice-settings.json` (`gentle-pi.voice-settings/v1`) in the Gentle AI config home. A successful download turns it on; the `/gentle:voice` menu turns it off and on, effective immediately. A missing or malformed file means off. |
|
|
48
|
+
| When it is armed | Only with the toggle on, in an interactive TUI parent session. Delegated child sessions, RPC, print and JSON modes never arm it. Reload or shutdown disarms it and cancels a running dictation. |
|
|
49
|
+
| Startup | Reads the toggle file only. No voice files are checked, nothing is downloaded or loaded, and no worker starts. |
|
|
50
|
+
| First hold | Checks that the runtime and model are installed; the spaces keep typing meanwhile. If voice is not installed, a notice points to `/gentle:voice` and push-to-talk stays off for the session; the saved choice is kept. |
|
|
51
|
+
| One at a time | A hold while a download or dictation runs types spaces normally. |
|
|
52
|
+
|
|
53
|
+
### How a hold is recognized
|
|
54
|
+
|
|
55
|
+
With Pi's keyboard mode, terminals report Space as plain text and never report
|
|
56
|
+
its release, so push-to-talk relies on the operating system's key auto-repeat.
|
|
57
|
+
Pi lets an extension drop or replace a key as it arrives, but not type one
|
|
58
|
+
later, so every space reaches the editor unchanged:
|
|
59
|
+
|
|
60
|
+
- **Typing:** a tap, several spaces, an indent or Space then a letter are
|
|
61
|
+
typed exactly as without push-to-talk, with no delay.
|
|
62
|
+
- **Hold:** auto-repeat has a long initial delay followed by short, regular
|
|
63
|
+
repeats; typing does not. A hold needs a first gap of 180 to 1000 ms (macOS
|
|
64
|
+
allows at least about 225 ms, X11 defaults to 660 ms), then three repeats
|
|
65
|
+
each at most 250 ms apart and regular (the slowest at most 1.6 times the
|
|
66
|
+
fastest), with the first gap at least 1.5 times the slowest repeat. Each
|
|
67
|
+
space must have added exactly one space to the draft. The following repeats
|
|
68
|
+
are turned into Backspace, through the editor's normal key path, until the
|
|
69
|
+
spaces the hold typed are removed; when the hold followed a word, one space
|
|
70
|
+
stays as the separator before the transcript. Later repeats are dropped.
|
|
71
|
+
While recording starts, those spaces can be seen briefly.
|
|
72
|
+
- **Release:** no repeat for 2.5 times the observed repeat interval, between
|
|
73
|
+
150 and 400 ms. The decision waits until input already queued is handled, so
|
|
74
|
+
a repeat delayed by a busy moment is not taken for a release.
|
|
75
|
+
- **Guards:** only single-space input counts. Pastes, escape sequences and
|
|
76
|
+
multi-character input pass through and end the attempt. If the draft changes
|
|
77
|
+
in any other way, for example Vim NORMAL mode where Space only moves the
|
|
78
|
+
cursor, autocomplete, or another key, the hold is not confirmed, or erasing
|
|
79
|
+
stops, and nothing else is removed. Spaces that were in the draft before the
|
|
80
|
+
hold are never removed.
|
|
81
|
+
|
|
82
|
+
Limitations: the timing depends on the keyboard repeat settings. An initial
|
|
83
|
+
repeat delay under 180 ms or over 1000 ms, or a repeat interval over 250 ms,
|
|
84
|
+
prevents a hold from being recognized. Five or more spaces typed with a pause
|
|
85
|
+
and then a very even fast rhythm could still look like a hold. Whether a space
|
|
86
|
+
precedes the hold is judged as if typing at the end of the draft; in the
|
|
87
|
+
middle of existing spaces the separator may be missing. Esc pressed while
|
|
88
|
+
repeats are still arriving, and a release right as the hold is confirmed, can
|
|
89
|
+
leave a stray space. Recording starts once the hold is confirmed and the
|
|
90
|
+
microphone is open; the model is verified while you speak (see below). A hold
|
|
91
|
+
while a dialog or overlay has the focus does not change the draft and is
|
|
92
|
+
ignored. Push-to-talk is tested with fake terminals, editors and sessions
|
|
93
|
+
only.
|
|
94
|
+
|
|
95
|
+
## What gets downloaded
|
|
96
|
+
|
|
97
|
+
All versions, sizes and digests are pinned in `lib/voice-artifacts.ts`.
|
|
98
|
+
|
|
99
|
+
| Component | Source | Size | Verified by |
|
|
100
|
+
|-----------|--------|------|-------------|
|
|
101
|
+
| `sherpa-onnx-node@1.13.8` | npm registry | 12 KB | `dist.integrity` (SHA-512) |
|
|
102
|
+
| `sherpa-onnx-<platform>-<arch>@1.13.8` | npm registry | 9–14 MB | `dist.integrity` (SHA-512) |
|
|
103
|
+
| `node-cpal@1.0.0` (microphone capture) | npm registry | 7.7 MB | `dist.integrity` (SHA-512) |
|
|
104
|
+
| Parakeet TDT 0.6B v3, int8 | Hugging Face, commit `2bda32ec70b0` | about 670 MB | per-file size and SHA-256 |
|
|
105
|
+
|
|
106
|
+
The model is the sherpa-onnx export
|
|
107
|
+
`csukuangfj/sherpa-onnx-nemo-parakeet-tdt-0.6b-v3-int8`: `encoder.int8.onnx`,
|
|
108
|
+
`decoder.int8.onnx`, `joiner.int8.onnx` and `tokens.txt`.
|
|
109
|
+
|
|
110
|
+
## Where it is stored
|
|
111
|
+
|
|
112
|
+
Everything lives in `<Gentle AI config home>/voice` (by default
|
|
113
|
+
`~/.pi/gentle-ai/voice`; see `gentlePiConfigHome()`):
|
|
114
|
+
|
|
115
|
+
```text
|
|
116
|
+
voice/
|
|
117
|
+
runtime/sherpa-onnx-1.13.8-node-cpal-1.0.0-<target>/node_modules/
|
|
118
|
+
sherpa-onnx-node/
|
|
119
|
+
sherpa-onnx-<platform>-<arch>/
|
|
120
|
+
node-cpal/
|
|
121
|
+
models/parakeet-tdt-0.6b-v3-int8-2bda32ec70b0/
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
The platform package sits next to `sherpa-onnx-node` because its loader resolves
|
|
125
|
+
`../sherpa-onnx-<platform>-<arch>/sherpa-onnx.node`. node-cpal loads
|
|
126
|
+
`bin/<platform>-<arch>/index.node` from its own directory. The runtime directory
|
|
127
|
+
names both native versions, so a runtime installed with other pins is never
|
|
128
|
+
reported as the current one.
|
|
129
|
+
|
|
130
|
+
## How an install stays safe
|
|
131
|
+
|
|
132
|
+
- **Explicit only.** Importing the voice modules performs no filesystem or
|
|
133
|
+
network access. Status checks never create the voice directory.
|
|
134
|
+
- **Streamed and bounded.** Each file is hashed while it streams to disk and is
|
|
135
|
+
cut off as soon as it exceeds its pinned size. A wrong length or digest fails
|
|
136
|
+
the install.
|
|
137
|
+
- **Pinned redirects.** npm tarballs are fetched without redirects. Hugging Face
|
|
138
|
+
redirects are followed only over HTTPS to the paths observed for this revision:
|
|
139
|
+
`huggingface.co/api/resolve-cache/...` and `us.aws.cdn.hf.co/xet-bridge-us/...`.
|
|
140
|
+
Any other host, including other CDN regions, is refused.
|
|
141
|
+
- **Cancellable and time-bounded.** An install can be aborted. It also stops
|
|
142
|
+
when no data arrives for 60 seconds, or when it runs past 20 minutes for the
|
|
143
|
+
runtime or 2 hours for the model.
|
|
144
|
+
- **Checked archives.** Every tarball is validated before anything is
|
|
145
|
+
extracted. Only regular files under `package/` are accepted, within the
|
|
146
|
+
registry's file count and unpacked size. Links, directories, traversal,
|
|
147
|
+
duplicates and Windows device names are refused. No package script runs, and
|
|
148
|
+
no downloaded code is loaded during installation.
|
|
149
|
+
- **Atomic publication.** Work happens in a private `.staging-*` directory. The
|
|
150
|
+
install marker is written last, and one rename publishes the component. A
|
|
151
|
+
failure or cancellation removes only that staging directory. An existing
|
|
152
|
+
installation is never partially overwritten: a valid one is kept as is, and an
|
|
153
|
+
invalid one is replaced only by a complete, verified copy.
|
|
154
|
+
|
|
155
|
+
## Dictation session
|
|
156
|
+
|
|
157
|
+
`lib/voice-session.ts` records one dictation and returns its text. It never
|
|
158
|
+
submits the text or touches the editor; the caller decides what to do with it.
|
|
159
|
+
|
|
160
|
+
- **Separate process.** `start()` runs `scripts/voice-worker.cjs` with the same
|
|
161
|
+
Node executable, from the runtime directory, with no shell. Microphone
|
|
162
|
+
capture, the model load and the decode all happen in that process, so a
|
|
163
|
+
native crash or a long decode cannot freeze Gentle AI. Importing the module or
|
|
164
|
+
creating a session does nothing until `start()`.
|
|
165
|
+
- **Checked before loading.** `start()` first requires both components to be
|
|
166
|
+
reported installed. The worker then checks the files again before it loads
|
|
167
|
+
the native code that uses them: every entry in the runtime and model
|
|
168
|
+
directories must be a plain directory or regular file, owned by the current
|
|
169
|
+
user and not writable by everyone (ownership and modes are not checked on
|
|
170
|
+
Windows). Each required runtime file must be present, and each model file
|
|
171
|
+
must match its pinned size and SHA-256. The digests are recomputed on every
|
|
172
|
+
session, which reads the whole model (about 670 MB). Directories above the
|
|
173
|
+
voice home are not checked. These checks catch broken or swapped installs;
|
|
174
|
+
they cannot stop someone with the same user account from replacing the files,
|
|
175
|
+
which is the same as running code as that user.
|
|
176
|
+
- **Order.** So that the first words are recorded, the worker validates the
|
|
177
|
+
runtime files, loads node-cpal and opens the microphone, then reports
|
|
178
|
+
`recording` and verifies the model digests while recording, reading each
|
|
179
|
+
file in chunks so capture keeps running. sherpa-onnx and the model are loaded
|
|
180
|
+
only after every digest matched and recording stopped, because that load is
|
|
181
|
+
synchronous and would stall capture. A mismatch found while recording closes
|
|
182
|
+
the microphone at once and reports the model as invalid; one found after stop
|
|
183
|
+
is reported instead of a transcript. Cancel stops the verification and loads
|
|
184
|
+
nothing. The tradeoff: the recognizer load (about 0.85 seconds measured on an
|
|
185
|
+
Apple Silicon Mac) now happens after stop, so a transcript takes that much
|
|
186
|
+
longer to arrive, and any verification still running when you stop is
|
|
187
|
+
awaited too.
|
|
188
|
+
- **Lifecycle.** A session is used once: `start()` resolves when recording
|
|
189
|
+
begins, `stop()` resolves with `{ text, truncated }`, and `cancel()` (or
|
|
190
|
+
`dispose()`) discards everything, including a transcript that arrives late.
|
|
191
|
+
`start()` resolves while the worker keeps recording; `stop()`, `cancel()` and
|
|
192
|
+
a failed `start()` settle only after the worker has exited. A worker that does
|
|
193
|
+
not exit within 2 seconds of finishing or being cancelled is killed. If the parent
|
|
194
|
+
disappears, the worker sees its input close and stops capturing.
|
|
195
|
+
- **Bounds.** Recording stops by itself after 120 seconds, and the worker then
|
|
196
|
+
transcribes what it has (`truncated: true`). Starting (runtime checks and
|
|
197
|
+
opening the microphone) and transcribing (the rest of the model
|
|
198
|
+
verification, the model load and the decode) each have a 120-second limit. Audio is kept in memory
|
|
199
|
+
only up to the recording limit. All of these are options.
|
|
200
|
+
- **Audio.** The worker opens the default input device through node-cpal,
|
|
201
|
+
preferring 32-bit float samples and otherwise using the device's default
|
|
202
|
+
integer or float format. It mixes all channels down to mono and resamples to
|
|
203
|
+
16 kHz in JavaScript (averaging when downsampling, linear interpolation when
|
|
204
|
+
upsampling). No SoX or FFmpeg is used. Less than 0.1 seconds of audio is
|
|
205
|
+
reported as empty, and a blank transcript as no speech.
|
|
206
|
+
- **Errors.** The worker reports a fixed code only, and the session turns it
|
|
207
|
+
into a fixed message. Native error text, file paths and environment values
|
|
208
|
+
are never included, and the worker's stderr is discarded.
|
|
209
|
+
- **Environment.** The worker gets only home, temp, locale and audio-session
|
|
210
|
+
variables (`HOME`, `USERPROFILE`, `SystemRoot`, `windir`, `TEMP`, `TMP`,
|
|
211
|
+
`TMPDIR`, `XDG_RUNTIME_DIR`, `PULSE_SERVER`, `PULSE_COOKIE`, `LANG`, `LC_ALL`,
|
|
212
|
+
`LC_CTYPE`). Credentials, `PATH`, `NODE_OPTIONS` and loader variables are
|
|
213
|
+
dropped.
|
|
214
|
+
- **Protocol.** JSON lines with schema `gentle.voice/v1`. The parent sends
|
|
215
|
+
`start` (with paths computed from the pinned manifests), then `stop` or
|
|
216
|
+
`cancel`. The worker answers `recording`, `transcribing`, and one final
|
|
217
|
+
`result` or `error`. Any other message, an unknown field, more than 16 lines
|
|
218
|
+
or a line over 64 KB stops the worker.
|
|
219
|
+
|
|
220
|
+
The session has been tested only with scripted fake workers and with the real
|
|
221
|
+
worker driving fake capture and recognizer modules. It has not loaded the real
|
|
222
|
+
native modules, opened a real microphone or transcribed real speech.
|
|
223
|
+
|
|
224
|
+
## Platform support
|
|
225
|
+
|
|
226
|
+
All five targets get the pinned runtime and a `node-cpal@1.0.0` capture binary
|
|
227
|
+
built for their architecture (checked from the binary headers, not by loading).
|
|
228
|
+
|
|
229
|
+
| Target | Prerequisites (not checked before loading) |
|
|
230
|
+
|--------|--------------------------------------------|
|
|
231
|
+
| macOS arm64 | macOS 11 or newer |
|
|
232
|
+
| macOS x64 | macOS 10.12 or newer |
|
|
233
|
+
| Linux x64, glibc 2.34+ | ALSA `libasound.so.2` |
|
|
234
|
+
| Linux arm64, glibc 2.34+ | ALSA `libasound.so.2` |
|
|
235
|
+
| Windows x64 | Microsoft Visual C++ runtime (`vcruntime140.dll`) |
|
|
236
|
+
|
|
237
|
+
node-cpal requires Node 22 or newer, and a dictation session refuses to start
|
|
238
|
+
on an older Node. Gentle AI never downloads or installs the Visual C++ runtime;
|
|
239
|
+
a missing runtime is expected to surface as a runtime load failure, which has
|
|
240
|
+
not been observed on hardware. `/gentle:voice` then names the runtime to install.
|
|
241
|
+
|
|
242
|
+
None of these targets has been verified on real hardware yet: native loading,
|
|
243
|
+
library paths and microphone capture have not been executed. Linux with a glibc
|
|
244
|
+
older than 2.34 is unsupported and the diagnosis names the version found.
|
|
245
|
+
Windows ARM64 has no native sherpa-onnx package and is unsupported. musl Linux
|
|
246
|
+
is unsupported. WSL is reported as unproven.
|
|
247
|
+
|
|
248
|
+
## Licenses and attribution
|
|
249
|
+
|
|
250
|
+
- **Model:** Parakeet TDT 0.6B v3 by NVIDIA, licensed under CC-BY-4.0. The int8
|
|
251
|
+
sherpa-onnx export is by csukuangfj. The export repository has no license file
|
|
252
|
+
of its own; its license is taken from the upstream NVIDIA model.
|
|
253
|
+
- **Runtime:** sherpa-onnx, Apache-2.0. The npm tarballs ship no LICENSE or
|
|
254
|
+
NOTICE file. The platform packages bundle onnxruntime (MIT) without its
|
|
255
|
+
license text.
|
|
256
|
+
- **Capture:** node-cpal 1.0.0, ISC. The tarball ships no LICENSE or NOTICE file. Its prebuilt
|
|
257
|
+
binaries link Rust crates whose notices are not included.
|
|
258
|
+
|
|
259
|
+
These gaps are unresolved and are listed in `VOICE_NOTICES`.
|
package/docs/yolo-mode.md
CHANGED
|
@@ -9,12 +9,27 @@ Use `/gentle:yolo enable` in the interactive primary Pi TUI to stop repeated per
|
|
|
9
9
|
| `/gentle:yolo enable` | Select YOLO for this live session and workspace/clone. |
|
|
10
10
|
| `/gentle:yolo disable` | Select Normal immediately and clear the YOLO indicators; saved defaults stay unchanged. |
|
|
11
11
|
| `/gentle:yolo status` | Show the current state without activating. |
|
|
12
|
-
| `/gentle:yolo` | Open a menu titled **🚀 Gentle YOLO 🔥 —
|
|
12
|
+
| `/gentle:yolo` | Open a menu titled **🚀 Gentle YOLO 🔥 — standing permission (current: ON\|OFF)** with `enable`, `disable` and `status`. Cancelling changes nothing. Without an interactive menu UI it behaves like `status`. |
|
|
13
13
|
|
|
14
14
|
Invalid arguments leave state unchanged.
|
|
15
15
|
|
|
16
16
|
The Session command palette also includes YOLO. Interactive selection requires an eligible primary TUI, live session identity and identifiable workspace. Outside Git, the canonical workspace directory supplies identity. There is no model-callable activation tool. `/gentle:mode default yolo` optionally saves a trusted user-global default for new primary sessions; `/gentle:mode default normal` removes that elevated default. Neither command changes the current mode.
|
|
17
17
|
|
|
18
|
+
## Super Yolo
|
|
19
|
+
|
|
20
|
+
**💥 Super Yolo removes every permission prompt; the only line left is private material.** Select it with `/gentle:mode super-yolo` or save it for new sessions with `/gentle:mode default super-yolo`.
|
|
21
|
+
|
|
22
|
+
While it is active:
|
|
23
|
+
|
|
24
|
+
- Every shell-guard confirmation is waived, data loss included: recursive `rm`, SQL drops, ordinary pushes, rebases, forced branch deletion, `npm publish` and configured guardrail `confirm`/`block` rules all run without dialogs. Code-level hard denies stay blocked (`git reset --hard`, forced clean, force push); see below.
|
|
25
|
+
- The Auto classifier does not run.
|
|
26
|
+
- The **sensitive-path guard stays hard-blocked**: `read`, `write` and `edit` of `.env` files, `.ssh`, keychains, `*.pem/*.key/*.p12/*.pfx`, `secrets/` directories and cloud credential files are refused in every mode, Super Yolo included.
|
|
27
|
+
- Code-level catastrophic denies remain: `rm -rf /`, `rm -rf ~`, `--no-preserve-root`, `git reset --hard`, forced clean and force push are blocked without a dialog.
|
|
28
|
+
- `ask_user` tools, provider consent, maintenance/recovery authorization and opaque-token decisions are never automatically answered.
|
|
29
|
+
- The `/gentle:yolo` toggle shows **ON** while Super Yolo is active and turning it off returns to Normal. Children never inherit Super Yolo; their bounded delegation and child guards are unchanged.
|
|
30
|
+
|
|
31
|
+
Super Yolo is deliberate maximum autonomy for a workspace you accept the consequences of. The shell recognition remains lexical, not a sandbox: unrecognized script forms, custom tools and prompt injection can still reach destructive effects, and OS-level isolation remains your real containment boundary.
|
|
32
|
+
|
|
18
33
|
## Configuration menu path
|
|
19
34
|
|
|
20
35
|
1. Open `/gentle:customize` → **Editor**.
|
|
@@ -23,7 +38,7 @@ The Session command palette also includes YOLO. Interactive selection requires a
|
|
|
23
38
|
|
|
24
39
|
Navigation, the read-only preview and Escape never grant permission. The preview reminds you that ordinary scoped commits/push/PR are covered, destructive confirmations remain, review consent is unchanged and reload resets the live grant. **UNAVAILABLE** means the live primary owner or eligible session/workspace cannot be used; selecting it cannot activate YOLO.
|
|
25
40
|
|
|
26
|
-
The live YOLO toggle does not save preferences. The separate **Default permissions** rows can save Normal, Auto or
|
|
41
|
+
The live YOLO toggle does not save preferences. The separate **Default permissions** rows can save Normal, Auto, YOLO or Super Yolo in the dedicated user-global permission store, never a repository preference or visual profile. **Session permissions** selects the current mode without changing that default. Closing the menu removes its observers and cancels unfinished menu activation; it does not revoke an already completed activation. Reload or session replacement invalidates old menu callbacks and resets the live permission.
|
|
27
42
|
|
|
28
43
|
## What activation authorizes
|
|
29
44
|
|
|
@@ -326,7 +326,10 @@ export default function askUserChoice(pi: ExtensionAPI): void {
|
|
|
326
326
|
if (details?.selection) {
|
|
327
327
|
return new Text(theme.fg("success", `✓ ${details.selection.index}. ${details.selection.label}`), 0, 0);
|
|
328
328
|
}
|
|
329
|
-
if (details?.customResponse !== undefined)
|
|
329
|
+
if (details?.customResponse !== undefined) {
|
|
330
|
+
const text = details.customResponse.trim();
|
|
331
|
+
return new Text(theme.fg("success", text ? `✓ Custom response — ${details.customResponse}` : "✓ Custom response"), 0, 0);
|
|
332
|
+
}
|
|
330
333
|
return new Text(theme.fg("warning", "Cancelled"), 0, 0);
|
|
331
334
|
},
|
|
332
335
|
});
|