gentle-pi 2.4.0 → 2.6.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 (227) hide show
  1. package/README.md +292 -25
  2. package/assets/agents/gentle-ai-worker.md +13 -0
  3. package/assets/agents/jd-fix-agent.md +18 -0
  4. package/assets/agents/jd-judge-a.md +1 -1
  5. package/assets/agents/jd-judge-b.md +1 -1
  6. package/assets/agents/sdd-apply.md +7 -5
  7. package/assets/agents/sdd-archive.md +5 -3
  8. package/assets/agents/sdd-design.md +4 -0
  9. package/assets/agents/sdd-explore.md +4 -0
  10. package/assets/agents/sdd-init.md +4 -0
  11. package/assets/agents/sdd-onboard.md +4 -0
  12. package/assets/agents/sdd-proposal.md +4 -0
  13. package/assets/agents/sdd-remediate.md +37 -0
  14. package/assets/agents/sdd-research.md +26 -3
  15. package/assets/agents/sdd-spec.md +4 -0
  16. package/assets/agents/sdd-status.md +9 -75
  17. package/assets/agents/sdd-sync.md +4 -0
  18. package/assets/agents/sdd-tasks.md +4 -0
  19. package/assets/agents/sdd-verify.md +5 -3
  20. package/assets/chains/sdd-full.chain.md +4 -0
  21. package/assets/chains/sdd-plan.chain.md +4 -0
  22. package/assets/chains/sdd-verify.chain.md +4 -0
  23. package/assets/migrations/managed-assets-v2.5.0.json +7 -0
  24. package/assets/orchestrator-delegation.md +39 -11
  25. package/assets/orchestrator.md +5 -5
  26. package/assets/sdd-orchestrator-workflow.md +54 -21
  27. package/assets/support/sdd-status-contract.md +34 -90
  28. package/contracts/telemetry/runtime-aggregate-v1.schema.json +65 -0
  29. package/docs/delegated-verification.md +25 -0
  30. package/docs/telemetry.md +94 -0
  31. package/docs/windows-startup-console-visibility.md +18 -0
  32. package/extensions/ask-user-choice.ts +159 -25
  33. package/extensions/codegraph-tools.ts +95 -5
  34. package/extensions/gentle-agents.ts +1337 -0
  35. package/extensions/gentle-ai.ts +2916 -386
  36. package/extensions/gentle-shell.ts +650 -0
  37. package/extensions/gentle-todo.ts +234 -0
  38. package/extensions/quiet-tools.ts +2 -1
  39. package/extensions/runtime-metrics.ts +130 -0
  40. package/extensions/sdd-init.ts +2 -2
  41. package/extensions/startup-banner.ts +52 -75
  42. package/lib/agent-profiles.ts +550 -0
  43. package/lib/agents-completion-delivery.ts +72 -0
  44. package/lib/agents-config.ts +315 -0
  45. package/lib/agents-history.ts +88 -0
  46. package/lib/agents-messaging.ts +187 -0
  47. package/lib/agents-protocol.ts +501 -0
  48. package/lib/agents-runner.ts +1012 -0
  49. package/lib/agents-thread-view.ts +57 -0
  50. package/lib/agents-transcript.ts +87 -0
  51. package/lib/agents-view-layout.ts +40 -0
  52. package/lib/agents-view.ts +914 -0
  53. package/lib/agents-widget.ts +241 -0
  54. package/lib/gentle-ai-binary.ts +3 -1
  55. package/lib/gentle-ai-renderer.ts +143 -25
  56. package/lib/native-choice-list.ts +194 -0
  57. package/lib/native-fullscreen-interaction.ts +47 -0
  58. package/lib/native-pointer-region.ts +164 -0
  59. package/lib/native-review-cli.ts +371 -13
  60. package/lib/orchestrator-presence.ts +337 -0
  61. package/lib/profiles-orchestrator.ts +203 -0
  62. package/lib/review-candidate-view-owner.ts +427 -0
  63. package/lib/review-candidate-view.ts +150 -48
  64. package/lib/review-consent-component.ts +247 -0
  65. package/lib/review-consent-ui.ts +110 -0
  66. package/lib/review-host-relay.ts +28 -0
  67. package/lib/review-integration-v2.ts +243 -11
  68. package/lib/review-last-event-controller.ts +8 -4
  69. package/lib/review-relay-contract.ts +11 -0
  70. package/lib/review-reminder-receipt.ts +74 -0
  71. package/lib/review-repository.ts +2 -2
  72. package/lib/review-risk-assessment.ts +339 -0
  73. package/lib/review-session-standing-permission-ipc.ts +309 -0
  74. package/lib/review-session-standing-permission.ts +240 -0
  75. package/lib/runtime-metrics-children.ts +199 -0
  76. package/lib/runtime-metrics-delivery.ts +68 -0
  77. package/lib/runtime-metrics-native.ts +166 -0
  78. package/lib/runtime-metrics-pi-identity.ts +113 -0
  79. package/lib/runtime-metrics-policy.ts +51 -0
  80. package/lib/runtime-metrics.ts +255 -0
  81. package/lib/sdd-preflight.ts +362 -81
  82. package/lib/sdd-research-capabilities.ts +228 -0
  83. package/lib/sdd-status.ts +29 -7
  84. package/lib/session-worktree-registry.ts +118 -0
  85. package/lib/shell-bar.ts +184 -0
  86. package/lib/shell-card.ts +133 -0
  87. package/lib/shell-changes-view.ts +530 -0
  88. package/lib/shell-changes.ts +290 -0
  89. package/lib/shell-gauge.ts +40 -0
  90. package/lib/shell-prompt.ts +115 -0
  91. package/lib/shell-sidebar-banner.ts +11 -0
  92. package/lib/shell-sidebar-layout.ts +213 -0
  93. package/lib/shell-sidebar.ts +41 -0
  94. package/lib/shell-todo.ts +297 -0
  95. package/lib/shell-usage-view.ts +76 -0
  96. package/lib/shell-usage.ts +246 -0
  97. package/lib/telemetry-trigger.ts +153 -0
  98. package/package.json +8 -5
  99. package/runtime/gentle-ai-binary.mjs +3 -1
  100. package/runtime/native-review-cli.mjs +370 -12
  101. package/runtime/review-integration-v2.mjs +243 -11
  102. package/runtime/review-relay-contract.mjs +11 -0
  103. package/runtime/review-risk-assessment.mjs +340 -0
  104. package/runtime/telemetry-trigger.mjs +154 -0
  105. package/scripts/build-runtime-modules.mjs +11 -1
  106. package/scripts/check-types.mjs +125 -0
  107. package/scripts/gentle-ai-installer.mjs +10 -10
  108. package/scripts/install-gentle-ai.mjs +12 -0
  109. package/scripts/install-tui-mode-setting.mjs +114 -0
  110. package/scripts/test-packed-runner.mjs +38 -2
  111. package/scripts/types-baseline.json +99 -0
  112. package/scripts/verify-package-files.mjs +8 -2
  113. package/skills/_shared/review-ledger-contract.md +20 -2
  114. package/skills/issue-creation/SKILL.md +3 -3
  115. package/skills/judgment-day/SKILL.md +17 -3
  116. package/skills/judgment-day/references/prompts-and-formats.md +14 -3
  117. package/tests/agent-profiles.test.ts +722 -0
  118. package/tests/agents-completion-delivery.test.ts +94 -0
  119. package/tests/agents-config.test.ts +205 -0
  120. package/tests/agents-fake-child.ts +66 -0
  121. package/tests/agents-grouping.test.ts +179 -0
  122. package/tests/agents-history.test.ts +54 -0
  123. package/tests/agents-integration.test.ts +100 -0
  124. package/tests/agents-messaging.test.ts +94 -0
  125. package/tests/agents-protocol.test.ts +198 -0
  126. package/tests/agents-queries.test.ts +190 -0
  127. package/tests/agents-responsive.test.ts +43 -0
  128. package/tests/agents-runner-process.test.ts +111 -0
  129. package/tests/agents-runner.test.ts +959 -0
  130. package/tests/agents-thread-view.test.ts +45 -0
  131. package/tests/agents-transcript.test.ts +30 -0
  132. package/tests/agents-view.test.ts +685 -0
  133. package/tests/agents-widget.test.ts +141 -0
  134. package/tests/artifact-language.test.ts +25 -2
  135. package/tests/ask-user-choice.test.ts +325 -5
  136. package/tests/asset-installation-runtime.test.ts +108 -0
  137. package/tests/autonomous-guard.test.ts +116 -1
  138. package/tests/codegraph-tools.test.ts +112 -2
  139. package/tests/delegated-key-learnings-contract.test.ts +1 -1
  140. package/tests/devbinary/native-review-parity.devtest.ts +110 -0
  141. package/tests/feature-request-form.test.ts +67 -0
  142. package/tests/fixtures/agents-messaging-child.mjs +5 -0
  143. package/tests/fixtures/agents-process-child.mjs +23 -0
  144. package/tests/fixtures/runtime-metrics-native-batches.json +6 -0
  145. package/tests/gentle-agents.test.ts +2168 -0
  146. package/tests/gentle-ai-binary.test.ts +7 -2
  147. package/tests/gentle-ai-installer.test.ts +47 -47
  148. package/tests/gentle-ai-renderer.test.ts +103 -0
  149. package/tests/gentle-ai.test.ts +971 -15
  150. package/tests/gentle-card-text.ts +35 -0
  151. package/tests/gentle-shell.test.ts +818 -0
  152. package/tests/gentle-todo.test.ts +226 -0
  153. package/tests/install-tui-mode-setting.test.ts +324 -0
  154. package/tests/issue-creation-skill.test.ts +22 -0
  155. package/tests/model-routing-authority.test.ts +12 -0
  156. package/tests/native-choice-list.test.ts +202 -0
  157. package/tests/native-fullscreen-interaction.test.ts +125 -0
  158. package/tests/native-pointer-region.test.ts +245 -0
  159. package/tests/native-review-capability-contract.test.ts +27 -1
  160. package/tests/native-review-cli.test.ts +317 -3
  161. package/tests/native-review-consent.test.ts +91 -0
  162. package/tests/native-review-parity-runtime.test.ts +8 -2
  163. package/tests/native-review-parity.test.ts +43 -29
  164. package/tests/native-sdd-attempt-authority.test.ts +7 -2
  165. package/tests/orchestrator-budget.test.ts +69 -0
  166. package/tests/orchestrator-presence.test.ts +389 -0
  167. package/tests/orchestrator-rdd-ownership.test.ts +9 -0
  168. package/tests/package-manifest.test.ts +243 -7
  169. package/tests/profiles-orchestrator.test.ts +208 -0
  170. package/tests/quiet-tool-rendering.test.ts +97 -37
  171. package/tests/rdd-aware-verification-contract.test.ts +226 -0
  172. package/tests/rdd-status-line.test.ts +286 -0
  173. package/tests/review-agent-end-preflight.test.ts +332 -24
  174. package/tests/review-candidate-view.test.ts +751 -7
  175. package/tests/review-consent-ui.test.ts +352 -0
  176. package/tests/review-contract-prompt.test.ts +17 -0
  177. package/tests/review-controller-native-recovery.test.ts +29 -4
  178. package/tests/review-controller-native-routing.test.ts +884 -7
  179. package/tests/review-controller-workspace-root.test.ts +45 -2
  180. package/tests/review-controller.test.ts +26 -1
  181. package/tests/review-host-relay-restart-parity.test.ts +142 -1
  182. package/tests/review-host-relay-routing.test.ts +384 -8
  183. package/tests/review-host-relay.test.ts +29 -0
  184. package/tests/review-integration-v2-forward.test.ts +44 -0
  185. package/tests/review-integration-v2.test.ts +276 -0
  186. package/tests/review-last-event-closure.test.ts +112 -3
  187. package/tests/review-ledger-contract.test.ts +61 -6
  188. package/tests/review-relay-contract.test.ts +26 -0
  189. package/tests/review-reminder-receipt.test.ts +62 -0
  190. package/tests/review-repository.test.ts +28 -1
  191. package/tests/review-risk-assessment.test.ts +626 -0
  192. package/tests/review-session-standing-permission-controller.test.ts +656 -0
  193. package/tests/review-session-standing-permission-ipc.test.ts +233 -0
  194. package/tests/review-session-standing-permission-runtime.test.ts +212 -0
  195. package/tests/review-session-standing-permission.test.ts +156 -0
  196. package/tests/runtime-harness.mjs +447 -39
  197. package/tests/runtime-metrics-children.test.ts +206 -0
  198. package/tests/runtime-metrics-delivery.test.ts +85 -0
  199. package/tests/runtime-metrics-extension.test.ts +187 -0
  200. package/tests/runtime-metrics-native.test.ts +209 -0
  201. package/tests/runtime-metrics-pi-identity.test.ts +113 -0
  202. package/tests/runtime-metrics-policy.test.ts +62 -0
  203. package/tests/runtime-metrics.test.ts +184 -0
  204. package/tests/sdd-agent-tools.test.ts +10 -1
  205. package/tests/sdd-execution-routing-contract.test.ts +28 -0
  206. package/tests/sdd-managed-runtime-settlement.test.ts +331 -0
  207. package/tests/sdd-native-managed-uptake.test.ts +253 -0
  208. package/tests/sdd-planning-routing-contract.test.ts +45 -0
  209. package/tests/sdd-preflight.test.ts +252 -8
  210. package/tests/sdd-research-capabilities.test.ts +256 -0
  211. package/tests/sdd-research-live.test.ts +241 -0
  212. package/tests/sdd-selection-transport.test.ts +504 -0
  213. package/tests/sdd-status.test.ts +51 -0
  214. package/tests/session-worktree-registry.test.ts +135 -0
  215. package/tests/shell-bar.test.ts +176 -0
  216. package/tests/shell-card.test.ts +139 -0
  217. package/tests/shell-changes-view.test.ts +609 -0
  218. package/tests/shell-changes.test.ts +350 -0
  219. package/tests/shell-prompt.test.ts +140 -0
  220. package/tests/shell-sidebar-banner.test.ts +23 -0
  221. package/tests/shell-sidebar-layout.test.ts +387 -0
  222. package/tests/shell-sidebar.test.ts +50 -0
  223. package/tests/shell-todo.test.ts +259 -0
  224. package/tests/shell-usage-view.test.ts +62 -0
  225. package/tests/shell-usage.test.ts +197 -0
  226. package/tests/startup-banner.test.ts +126 -0
  227. package/tests/telemetry-trigger.test.ts +351 -0
@@ -0,0 +1,153 @@
1
+ import { spawn as nodeSpawn } from "node:child_process";
2
+
3
+ // gentle-ai#4309 owns anonymous usage telemetry end to end: install and
4
+ // heartbeat events, the notice, every kill switch, and the wire contract.
5
+ // gentle-pi#677 only nudges the local binary once per process, best-effort,
6
+ // and never surfaces the outcome to the user. This module is the pure,
7
+ // testable core of that nudge (`shouldTriggerTelemetry`,
8
+ // `spawnTelemetryTrigger`) plus the decode helper the foreground
9
+ // `/gentle:telemetry` slash command uses to relay `<op> --json` output
10
+ // (`decodeTelemetryTriggerDecision`).
11
+
12
+ export const TELEMETRY_TRIGGER_KILL_TIMEOUT_MS = 3_000;
13
+
14
+ export const TELEMETRY_TRIGGER_CONTRACT = "gentle-ai.telemetry-trigger/v1";
15
+
16
+ export const TELEMETRY_TRIGGER_DECISIONS = [
17
+ "enrolled",
18
+ "sent_install",
19
+ "sent_heartbeat",
20
+ "rate_limited",
21
+ "backoff",
22
+ "disabled",
23
+ ] as const;
24
+ export type TelemetryTriggerDecision = (typeof TELEMETRY_TRIGGER_DECISIONS)[number];
25
+
26
+ export interface TelemetryTriggerDecisionV1 {
27
+ schema: typeof TELEMETRY_TRIGGER_CONTRACT;
28
+ decision: TelemetryTriggerDecision;
29
+ source: string;
30
+ }
31
+
32
+ /**
33
+ * Decodes `gentle-ai telemetry trigger --json` stdout. An older binary
34
+ * without the verb prints `unknown telemetry command` and exits non-zero, so
35
+ * its stdout never parses as JSON here; that -- along with malformed JSON, a
36
+ * mismatched schema, an unrecognized decision, or a missing/non-string
37
+ * source -- means "nothing to do" and returns undefined rather than
38
+ * throwing.
39
+ */
40
+ export function decodeTelemetryTriggerDecision(stdout: string): TelemetryTriggerDecisionV1 | undefined {
41
+ let parsed: unknown;
42
+ try {
43
+ parsed = JSON.parse(stdout);
44
+ } catch {
45
+ return undefined;
46
+ }
47
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return undefined;
48
+ const record = parsed as Record<string, unknown>;
49
+ if (record.schema !== TELEMETRY_TRIGGER_CONTRACT) return undefined;
50
+ if (typeof record.decision !== "string") return undefined;
51
+ if (!(TELEMETRY_TRIGGER_DECISIONS as readonly string[]).includes(record.decision)) return undefined;
52
+ if (typeof record.source !== "string" || record.source.length === 0) return undefined;
53
+ return {
54
+ schema: TELEMETRY_TRIGGER_CONTRACT,
55
+ decision: record.decision as TelemetryTriggerDecision,
56
+ source: record.source,
57
+ };
58
+ }
59
+
60
+ export type TelemetryKillSwitchReason = "do-not-track" | "telemetry-disabled" | "ci";
61
+
62
+ function telemetryKillSwitchReason(env: Readonly<Record<string, string | undefined>>): TelemetryKillSwitchReason | undefined {
63
+ if (env.DO_NOT_TRACK === "1") return "do-not-track";
64
+ if (env.GENTLE_AI_TELEMETRY === "0") return "telemetry-disabled";
65
+ if (env.CI === "true") return "ci";
66
+ return undefined;
67
+ }
68
+
69
+ /**
70
+ * True unless one of Gentle Pi's own kill switches is set
71
+ * (`DO_NOT_TRACK=1`, `GENTLE_AI_TELEMETRY=0`, or `CI=true`). The binary
72
+ * enforces its own opt-out and rate limiting independently; this predicate
73
+ * only decides whether Gentle Pi spawns the trigger at all.
74
+ */
75
+ export function shouldTriggerTelemetry(env: Readonly<Record<string, string | undefined>>): boolean {
76
+ return telemetryKillSwitchReason(env) === undefined;
77
+ }
78
+
79
+ // A minimal structural subset of node:child_process's ChildProcess, mirroring
80
+ // the ChildLike/Spawn seam already used by lib/agents-runner.ts: narrow
81
+ // enough that tests can stub it without touching a real process.
82
+ export interface TelemetryTriggerChildLike {
83
+ unref(): unknown;
84
+ kill(signal?: NodeJS.Signals | number): boolean;
85
+ on(event: "error", listener: (error: Error) => void): unknown;
86
+ }
87
+
88
+ export interface TelemetryTriggerSpawnOptions {
89
+ cwd: string;
90
+ env: NodeJS.ProcessEnv;
91
+ detached: boolean;
92
+ windowsHide: boolean;
93
+ stdio: "ignore";
94
+ }
95
+
96
+ export type TelemetryTriggerSpawn = (
97
+ command: string,
98
+ args: readonly string[],
99
+ options: TelemetryTriggerSpawnOptions,
100
+ ) => TelemetryTriggerChildLike;
101
+
102
+ export interface SpawnTelemetryTriggerOptions {
103
+ executable: string;
104
+ cwd: string;
105
+ env: NodeJS.ProcessEnv;
106
+ spawn?: TelemetryTriggerSpawn;
107
+ }
108
+
109
+ export type TelemetryTriggerReason = "spawned" | "spawn-error" | TelemetryKillSwitchReason;
110
+
111
+ export interface TelemetryTriggerResult {
112
+ spawned: boolean;
113
+ reason: TelemetryTriggerReason;
114
+ }
115
+
116
+ /**
117
+ * Nudges `<executable> telemetry trigger --json`, detached and
118
+ * fire-and-forget. Never throws, never awaits the child's exit, and never
119
+ * blocks session start: a missing binary, an old binary without the verb, or
120
+ * a spawn failure all just report `{ spawned: false, ... }`. A 3 s timer
121
+ * kills a runaway child; the timer is unref'd so it can never keep the host
122
+ * process alive on its own, matching the detached child's own `unref()`.
123
+ */
124
+ export function spawnTelemetryTrigger(options: SpawnTelemetryTriggerOptions): TelemetryTriggerResult {
125
+ const killSwitch = telemetryKillSwitchReason(options.env);
126
+ if (killSwitch !== undefined) return { spawned: false, reason: killSwitch };
127
+ const spawnImpl = options.spawn ?? (nodeSpawn as unknown as TelemetryTriggerSpawn);
128
+ try {
129
+ const child = spawnImpl(options.executable, ["telemetry", "trigger", "--json"], {
130
+ cwd: options.cwd,
131
+ env: options.env,
132
+ detached: true,
133
+ windowsHide: true,
134
+ stdio: "ignore",
135
+ });
136
+ child.on("error", () => {
137
+ // Fire-and-forget: a spawn-time or runtime child error never surfaces
138
+ // to the caller and never affects session start.
139
+ });
140
+ const killTimer = setTimeout(() => {
141
+ try {
142
+ child.kill();
143
+ } catch {
144
+ // Best effort only; the child may already have exited.
145
+ }
146
+ }, TELEMETRY_TRIGGER_KILL_TIMEOUT_MS);
147
+ killTimer.unref?.();
148
+ child.unref();
149
+ return { spawned: true, reason: "spawned" };
150
+ } catch {
151
+ return { spawned: false, reason: "spawn-error" };
152
+ }
153
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gentle-pi",
3
- "version": "2.4.0",
3
+ "version": "2.6.0",
4
4
  "description": "Turn Pi into el Gentleman: a senior-architect development harness with SDD/OpenSpec, subagents, strict TDD evidence, review guardrails, and skill discovery.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -48,7 +48,8 @@
48
48
  "check:runtime-modules": "node scripts/build-runtime-modules.mjs --check",
49
49
  "test:packed-package": "node scripts/test-packed-runner.mjs",
50
50
  "prepack": "pnpm test && pnpm run check:runtime-modules && node scripts/verify-package-files.mjs",
51
- "prepublishOnly": "pnpm test && pnpm run check:runtime-modules && node scripts/verify-package-files.mjs && pnpm run test:packed-package"
51
+ "prepublishOnly": "pnpm test && pnpm run check:runtime-modules && node scripts/verify-package-files.mjs && pnpm run test:packed-package",
52
+ "typecheck": "node scripts/check-types.mjs"
52
53
  },
53
54
  "pi": {
54
55
  "image": "https://cdn.jsdelivr.net/npm/gentle-pi/assets/gentle-logo-only.png",
@@ -66,11 +67,11 @@
66
67
  ]
67
68
  },
68
69
  "dependencies": {
69
- "@earendil-works/pi-tui": "*",
70
+ "@earendil-works/pi-tui": "0.85.1",
70
71
  "@heyhuynhgiabuu/pi-pretty": "0.6.14"
71
72
  },
72
73
  "peerDependencies": {
73
- "@earendil-works/pi-coding-agent": "*",
74
+ "@earendil-works/pi-coding-agent": ">=0.85.1",
74
75
  "typebox": "*"
75
76
  },
76
77
  "peerDependenciesMeta": {
@@ -79,7 +80,9 @@
79
80
  }
80
81
  },
81
82
  "devDependencies": {
82
- "@earendil-works/pi-coding-agent": "*"
83
+ "@earendil-works/pi-coding-agent": "0.85.1",
84
+ "@types/node": "^24.13.3",
85
+ "typescript": "^5.9.3"
83
86
  },
84
87
  "packageManager": "pnpm@11.1.1"
85
88
  }
@@ -17,6 +17,8 @@ import {
17
17
  import { fileURLToPath } from "node:url";
18
18
 
19
19
  export const GENTLE_AI_BINARY_MISSING_CODE = "package-local-binary-missing";
20
+ export const GENTLE_AI_INSTALL_RECOVERY_COMMAND = "node scripts/install-gentle-ai.mjs";
21
+ export const GENTLE_AI_INSTALL_RECOVERY_INSTRUCTIONS = `If GENTLE_PI_SKIP_GENTLE_AI_INSTALL is set, remove or unset it before changing to the installed gentle-pi package directory and running \`${GENTLE_AI_INSTALL_RECOVERY_COMMAND}\`.`;
20
22
  // Derived from the one authoritative pinned version in
21
23
  // scripts/gentle-ai-installer.mjs rather than repeating the literal here, so
22
24
  // the two can never independently drift apart the way they once did.
@@ -26,7 +28,7 @@ export class PackageLocalGentleAiBinaryMissingError extends Error {
26
28
  code = GENTLE_AI_BINARY_MISSING_CODE;
27
29
  constructor(path ) {
28
30
  super(
29
- `${GENTLE_AI_BINARY_MISSING_CODE}: Gentle AI v${GENTLE_AI_VERSION} is not installed at ${path}. Reinstall gentle-pi, or use GENTLE_PI_SKIP_GENTLE_AI_INSTALL=1 only for development/offline installs.`,
31
+ `${GENTLE_AI_BINARY_MISSING_CODE}: Gentle AI v${GENTLE_AI_VERSION} is not installed at ${path}. ${GENTLE_AI_INSTALL_RECOVERY_INSTRUCTIONS} A missing binary can result from skipped lifecycle scripts, but does not prove install lifecycle scripts were disabled.`,
30
32
  );
31
33
  this.name = "PackageLocalGentleAiBinaryMissingError";
32
34
  }