gentle-pi 4.0.0 → 4.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +157 -18
- package/assets/agents/gentle-ai-explore.md +11 -4
- package/assets/agents/gentle-ai-verify.md +23 -4
- package/assets/agents/gentle-ai-worker.md +6 -6
- package/assets/install-wizard/index.html +47 -0
- package/assets/install-wizard/wizard.css +1279 -0
- package/assets/install-wizard/wizard.js +951 -0
- package/assets/orchestrator-delegation.md +70 -163
- package/assets/orchestrator-memory.md +11 -4
- package/assets/orchestrator-prompts.md +48 -0
- package/assets/orchestrator-tracking.md +53 -0
- package/assets/orchestrator-verification.md +28 -0
- package/assets/orchestrator-writer.md +38 -0
- package/assets/orchestrator.md +29 -25
- package/assets/sounds/LICENSE.md +52 -0
- package/assets/sounds/attention.wav +0 -0
- package/assets/sounds/error.wav +0 -0
- package/assets/sounds/success.wav +0 -0
- package/bin/engram-guard +9 -0
- package/bin/gentle-shell-install.mjs +302 -0
- package/bin/gentle-shell.mjs +708 -22
- package/contracts/review-provider-contract-mirror/provider-contract.lock.json +7 -7
- package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/bundle/manifest.json +2 -2
- package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/bundle/orchestration/pi.md +16 -4
- package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/generated/provider-capabilities.baseline.json +2 -2
- package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/generated/provider-roles.baseline.json +1 -1
- package/docs/auto-permission-answers.md +25 -0
- package/docs/auto-permission-evidence.md +39 -0
- package/docs/bundled-install.md +399 -0
- package/docs/delegated-verification.md +3 -5
- package/docs/gentle-agents-activity.md +513 -0
- package/docs/gentle-shell-uninstall.md +136 -0
- package/docs/gentle-shell.md +90 -33
- package/docs/install-wizard.md +2040 -0
- package/docs/native-authority-architecture.md +1 -1
- package/docs/permission-modes.md +127 -0
- package/docs/prompt-history.md +1 -1
- package/docs/readme-reference.md +310 -47
- package/docs/render-cache-performance.md +28 -0
- package/docs/session-profile-format.md +39 -0
- package/docs/sound-notifications-proposal.md +191 -0
- package/docs/sound-notifications.md +114 -0
- package/docs/yolo-mode.md +11 -10
- package/extensions/ask-user-choice.ts +4 -0
- package/extensions/ask-user-question.ts +6 -1
- package/extensions/child-context.ts +11 -2
- package/extensions/child-safety.ts +4 -2
- package/extensions/codegraph-tools.ts +18 -5
- package/extensions/gentle-agents.ts +718 -87
- package/extensions/gentle-ai.ts +991 -263
- package/extensions/gentle-herdr-activity.ts +81 -0
- package/extensions/gentle-notifications.ts +104 -0
- package/extensions/gentle-shell.ts +271 -80
- package/extensions/gentle-todo.ts +123 -18
- package/extensions/history/index.ts +11 -6
- package/extensions/pi-pretty.ts +39 -3
- package/extensions/quiet-tools.ts +91 -21
- package/extensions/skill-registry.ts +175 -46
- package/extensions/startup-banner.ts +11 -2
- package/lib/agent-home.ts +10 -1
- package/lib/agent-model-resolution.ts +80 -0
- package/lib/agent-profiles.ts +13 -3
- package/lib/agents-completion-delivery.ts +11 -3
- package/lib/agents-messaging.ts +1 -1
- package/lib/agents-protocol.ts +40 -1
- package/lib/agents-runner.ts +90 -15
- package/lib/auto-permission-answers.ts +133 -0
- package/lib/auto-permission-classifier.ts +459 -0
- package/lib/auto-permission-evidence.ts +88 -0
- package/lib/auto-permission-memory.ts +69 -0
- package/lib/auto-permission-runtime.ts +484 -0
- package/lib/auto-permission-tool-context.ts +61 -0
- package/lib/background-jobs-tools.ts +202 -0
- package/lib/background-jobs.ts +253 -0
- package/lib/background-monitor.ts +154 -0
- package/lib/bounded-writer-admission.ts +83 -10
- package/lib/builtin-codemode-optout.ts +166 -0
- package/lib/card-content-policy.ts +85 -0
- package/lib/child-package-injection.ts +62 -0
- package/lib/codemode-renderer.ts +14 -4
- package/lib/command-palette-catalog.ts +3 -2
- package/lib/context-threshold.ts +26 -0
- package/lib/destructive-command-guard.ts +104 -28
- package/lib/gentle-ai-binary.ts +109 -4
- package/lib/gentle-shell-bundled.ts +535 -0
- package/lib/gentle-shell-launcher.ts +75 -24
- package/lib/gentle-shell-startup-flow.ts +54 -0
- package/lib/gentle-shell-startup-update.ts +92 -0
- package/lib/gentle-shell-uninstall.ts +840 -0
- package/lib/gentle-shell-update-panel.ts +231 -0
- package/lib/herdr-activity.ts +183 -0
- package/lib/inprocess-reviewer.ts +3 -0
- package/lib/jobs-sidebar-state.ts +20 -0
- package/lib/jobs-view.ts +161 -0
- package/lib/model-price-ratio.ts +83 -0
- package/lib/model-routing-authority.ts +6 -1
- package/lib/nan-provider.ts +33 -11
- package/lib/native-review-cli.ts +194 -73
- package/lib/notification-audio-native.ts +162 -0
- package/lib/notification-audio-windows.ts +399 -0
- package/lib/notification-audio.ts +332 -0
- package/lib/notification-customize.ts +241 -0
- package/lib/notification-events.ts +113 -0
- package/lib/notification-policy.ts +148 -0
- package/lib/notification-pulse-client.ts +367 -0
- package/lib/notification-pulse-protocol.ts +305 -0
- package/lib/notification-pulse-stream.ts +213 -0
- package/lib/notification-pulse-worker.ts +66 -0
- package/lib/notification-scheduler.ts +173 -0
- package/lib/notification-service.ts +202 -0
- package/lib/notification-ui.ts +87 -0
- package/lib/odd-phase.ts +1 -1
- package/lib/orchestrator-alias.ts +20 -0
- package/lib/orchestrator-catalog.ts +79 -0
- package/lib/orchestrator-consultation.ts +61 -0
- package/lib/orchestrator-discovery.ts +49 -0
- package/lib/orchestrator-helper-consent.ts +122 -0
- package/lib/orchestrator-helper.ts +167 -0
- package/lib/orchestrator-message-card.ts +105 -0
- package/lib/orchestrator-presence.ts +115 -14
- package/lib/orchestrator-scope.ts +80 -0
- package/lib/orchestrator-state.ts +107 -0
- package/lib/orchestrator-tool-card.ts +280 -0
- package/lib/orchestrator-work-search.ts +218 -0
- package/lib/orchestrator-work.ts +79 -0
- package/lib/permission-mode-policy.ts +59 -0
- package/lib/review-candidate-view-owner.ts +8 -6
- package/lib/review-candidate-view.ts +3 -2
- package/lib/review-compact-contract.ts +2 -2
- package/lib/review-host-relay.ts +7 -2
- package/lib/review-integration-v2.ts +100 -22
- package/lib/review-publication-gate.ts +1 -1
- package/lib/review-risk-assessment.ts +77 -51
- package/lib/review-sidebar-state.ts +2 -1
- package/lib/review-transaction.ts +72 -3
- package/lib/runtime-metrics-children.ts +1 -1
- package/lib/runtime-metrics-native.ts +3 -2
- package/lib/selection-engine.ts +22 -7
- package/lib/session-change-capture.ts +5 -4
- package/lib/session-changes.ts +27 -22
- package/lib/session-profile-binding.ts +83 -0
- package/lib/session-profile-freeze.ts +261 -0
- package/lib/session-profile-persistence.ts +187 -0
- package/lib/session-worktree-registry.ts +74 -8
- package/lib/shell-bar.ts +41 -11
- package/lib/shell-changes-view.ts +40 -13
- package/lib/shell-changes.ts +88 -71
- package/lib/shell-prompt.ts +6 -4
- package/lib/shell-sidebar-layout.ts +5 -1
- package/lib/shell-todo.ts +81 -26
- package/lib/shell-usage.ts +4 -3
- package/lib/status-timing-diagnostics.ts +201 -0
- package/lib/telemetry-trigger.ts +3 -1
- package/lib/vim-editor-adapter.ts +27 -5
- package/lib/visual-customization-policy.ts +20 -9
- package/lib/visual-customize-view.ts +171 -20
- package/lib/writer-surfaces.ts +162 -0
- package/lib/yolo-session-policy.ts +198 -121
- package/package.json +5 -5
- package/runtime/child-package-injection.mjs +63 -0
- package/runtime/gentle-ai-binary.mjs +109 -4
- package/runtime/gentle-shell-bundled.mjs +536 -0
- package/runtime/gentle-shell-launcher.mjs +74 -23
- package/runtime/gentle-shell-startup-flow.mjs +55 -0
- package/runtime/gentle-shell-startup-update.mjs +93 -0
- package/runtime/gentle-shell-uninstall.mjs +841 -0
- package/runtime/gentle-shell-update-panel.mjs +232 -0
- package/runtime/native-review-cli.mjs +191 -70
- package/runtime/review-integration-v2.mjs +100 -22
- package/runtime/review-risk-assessment.mjs +77 -51
- package/runtime/status-timing-diagnostics.mjs +202 -0
- package/runtime/telemetry-trigger.mjs +3 -1
- package/scripts/bootstrap.cmd +255 -0
- package/scripts/bootstrap.sh +168 -0
- package/scripts/build-distribution.mjs +157 -0
- package/scripts/build-installer-bundles.mjs +136 -0
- package/scripts/build-runtime-modules.mjs +7 -0
- package/scripts/bundled-install.mjs +1308 -0
- package/scripts/bundled-wizard.mjs +399 -0
- package/scripts/check-types.mjs +4 -6
- package/scripts/gentle-ai-installer.mjs +79 -32
- package/scripts/install-gentle-ai.mjs +48 -1
- package/scripts/install-tui-mode-setting.mjs +10 -1
- package/scripts/install-wizard-preview.mjs +154 -0
- package/scripts/installer-downloads.mjs +648 -0
- package/scripts/installer-preflight.mjs +387 -0
- package/scripts/installer-probes.mjs +564 -0
- package/scripts/installer-runner.mjs +1102 -0
- package/scripts/installer-server.mjs +881 -0
- package/scripts/installer-windows-artifacts.json +15 -0
- package/scripts/installer-windows.mjs +752 -0
- package/scripts/main-channel.mjs +452 -0
- package/scripts/npm-pack-result.mjs +31 -0
- package/scripts/pi-update.mjs +223 -0
- package/scripts/render-cache-performance-worker.mjs +205 -0
- package/scripts/render-cache-performance.mjs +115 -0
- package/scripts/run-test-suite.mjs +22 -8
- package/scripts/test-installer-acceptance.sh +161 -0
- package/scripts/test-packed-runner.mjs +23 -5
- package/scripts/types-baseline.json +2 -92
- package/scripts/verify-package-files.mjs +82 -18
- package/skills/gentle-ai/SKILL.md +12 -11
- package/tests/agent-home.test.ts +56 -3
- package/tests/agent-model-resolution.test.ts +113 -0
- package/tests/agent-profiles.test.ts +12 -0
- package/tests/agent-risk-escalation.test.ts +123 -0
- package/tests/agents-completion-delivery.test.ts +17 -0
- package/tests/agents-protocol.test.ts +57 -0
- package/tests/agents-queries.test.ts +9 -9
- package/tests/agents-runner-process.test.ts +31 -0
- package/tests/agents-runner.test.ts +89 -4
- package/tests/append-system-prompt-route.test.ts +18 -1
- package/tests/auto-mode-human-answers.test.ts +68 -0
- package/tests/auto-mode-invariants.test.ts +276 -0
- package/tests/auto-mode-sdk.test.ts +84 -0
- package/tests/auto-mode.test.ts +49 -0
- package/tests/auto-permission-answers.test.ts +170 -0
- package/tests/auto-permission-classifier.test.ts +634 -0
- package/tests/auto-permission-compound.test.ts +24 -0
- package/tests/auto-permission-evidence.test.ts +88 -0
- package/tests/auto-permission-memory.test.ts +46 -0
- package/tests/auto-permission-public-regressions.test.ts +111 -0
- package/tests/auto-permission-runtime.test.ts +454 -0
- package/tests/autonomous-guard.test.ts +86 -16
- package/tests/background-cache-warming.test.ts +2 -1
- package/tests/background-jobs.test.ts +227 -0
- package/tests/background-monitor.test.ts +195 -0
- package/tests/background-subagents-default-mode.test.ts +28 -5
- package/tests/bounded-stop-contract.test.ts +85 -0
- package/tests/bounded-writer-admission.test.ts +52 -1
- package/tests/bridge-wake-lifecycle.test.ts +129 -0
- package/tests/bridge-wake-rendering.test.ts +56 -0
- package/tests/build-distribution.test.ts +269 -0
- package/tests/builtin-codemode-optout.test.ts +242 -0
- package/tests/bundled-install.test.ts +1319 -0
- package/tests/bundled-wizard.test.ts +505 -0
- package/tests/card-content-policy.test.ts +68 -0
- package/tests/card-style-policy.test.ts +34 -2
- package/tests/child-codegraph-bootstrap.test.ts +74 -0
- package/tests/child-package-entrypoints.test.ts +65 -0
- package/tests/child-package-injection.test.ts +74 -0
- package/tests/child-safety.test.ts +12 -0
- package/tests/child-web-package.test.ts +224 -0
- package/tests/codegraph-tools.test.ts +35 -0
- package/tests/codemode-rendering.test.ts +107 -2
- package/tests/command-palette.test.ts +5 -5
- package/tests/context-threshold.test.ts +31 -0
- package/tests/delegate-for-reason-contract.test.ts +327 -0
- package/tests/delegated-key-learnings-contract.test.ts +3 -2
- package/tests/devbinary/native-review-parity.devtest.ts +1 -1
- package/tests/devbinary/pi-host-relay.devtest.ts +173 -3
- package/tests/engram-safety.test.ts +316 -0
- package/tests/generic-agent-tools.test.ts +16 -1
- package/tests/gentle-agents.test.ts +1895 -76
- package/tests/gentle-ai-binary-isolation.test.ts +135 -0
- package/tests/gentle-ai-binary.test.ts +19 -2
- package/tests/gentle-ai-child-guards.test.ts +202 -0
- package/tests/gentle-ai-dev-binary-surfacing.test.ts +125 -15
- package/tests/gentle-ai-installer.test.ts +548 -58
- package/tests/gentle-ai-prompt-model-routing.test.ts +123 -0
- package/tests/gentle-ai-renderer.test.ts +6 -6
- package/tests/gentle-ai.test.ts +999 -31
- package/tests/gentle-herdr-activity.test.ts +100 -0
- package/tests/gentle-notifications.test.ts +427 -0
- package/tests/gentle-shell-bin.test.ts +263 -19
- package/tests/gentle-shell-bundled.test.ts +1036 -0
- package/tests/gentle-shell-launcher.test.ts +251 -25
- package/tests/gentle-shell-startup-flow.test.ts +75 -0
- package/tests/gentle-shell-startup-update.test.ts +85 -0
- package/tests/gentle-shell-uninstall.test.ts +978 -0
- package/tests/gentle-shell-update-panel.test.ts +158 -0
- package/tests/gentle-shell.test.ts +611 -100
- package/tests/gentle-todo.test.ts +317 -14
- package/tests/herdr-activity.test.ts +243 -0
- package/tests/history-agent-home.test.ts +81 -0
- package/tests/history-child-guard.test.ts +70 -0
- package/tests/inprocess-reviewer.test.ts +20 -0
- package/tests/install-gentle-ai-failure.test.ts +69 -0
- package/tests/install-tui-mode-setting.test.ts +15 -0
- package/tests/install-wizard.test.ts +1223 -0
- package/tests/installer-bundles.test.ts +122 -0
- package/tests/installer-posix-bootstrap.test.ts +1201 -0
- package/tests/installer-preflight.test.ts +750 -0
- package/tests/installer-probes.test.ts +1106 -0
- package/tests/installer-runner.test.ts +2159 -0
- package/tests/installer-server.test.ts +1567 -0
- package/tests/installer-windows-bootstrap.test.ts +2410 -0
- package/tests/jobs-view.test.ts +160 -0
- package/tests/main-channel-upgrade.test.ts +395 -0
- package/tests/main-channel.test.ts +344 -0
- package/tests/maintainer/provider-relay.maintest.ts +13 -12
- package/tests/model-price-ratio.test.ts +116 -0
- package/tests/model-profiles-preservation.test.ts +153 -0
- package/tests/model-routing-package.test.ts +10 -0
- package/tests/nan-provider-runtime.test.ts +156 -0
- package/tests/nan-provider.test.ts +28 -18
- package/tests/native-binary-gate.test.ts +2 -0
- package/tests/native-review-capability-contract.test.ts +7 -1
- package/tests/native-review-cli.test.ts +236 -1
- package/tests/native-review-consent.test.ts +2 -2
- package/tests/native-review-parity-runtime.test.ts +1 -1
- package/tests/native-review-parity.test.ts +12 -48
- package/tests/native-risk-evidence-parity.test.ts +21 -0
- package/tests/no-self-pause-contract.test.ts +87 -0
- package/tests/notification-audio-native.test.ts +281 -0
- package/tests/notification-audio-windows.test.ts +581 -0
- package/tests/notification-audio.test.ts +548 -0
- package/tests/notification-customize.test.ts +655 -0
- package/tests/notification-events.test.ts +115 -0
- package/tests/notification-policy.test.ts +201 -0
- package/tests/notification-pulse-client.test.ts +356 -0
- package/tests/notification-pulse-protocol.test.ts +213 -0
- package/tests/notification-pulse-stream.test.ts +320 -0
- package/tests/notification-scheduler.test.ts +258 -0
- package/tests/notification-ui.test.ts +157 -0
- package/tests/npm-pack-result.test.ts +41 -0
- package/tests/odd-integration.test.ts +14 -5
- package/tests/odd-routing-canonical-ratchet.test.ts +53 -12
- package/tests/odd-routing-contract.test.ts +80 -23
- package/tests/odd-runtime-delegation-gate.test.ts +4 -1
- package/tests/orchestrator-budget.test.ts +29 -6
- package/tests/orchestrator-catalog.test.ts +146 -0
- package/tests/orchestrator-consultation-sdk.test.ts +614 -0
- package/tests/orchestrator-consultation.test.ts +111 -0
- package/tests/orchestrator-discovery.test.ts +241 -0
- package/tests/orchestrator-helper-consent.test.ts +171 -0
- package/tests/orchestrator-helper.test.ts +297 -0
- package/tests/orchestrator-message-card.test.ts +190 -0
- package/tests/orchestrator-presence.test.ts +23 -0
- package/tests/orchestrator-rdd-ownership.test.ts +6 -5
- package/tests/orchestrator-scope.test.ts +107 -0
- package/tests/orchestrator-state.test.ts +114 -0
- package/tests/orchestrator-status-publication-contract.test.ts +34 -0
- package/tests/orchestrator-tool-card.test.ts +398 -0
- package/tests/orchestrator-work-search.test.ts +318 -0
- package/tests/orchestrator-work.test.ts +147 -0
- package/tests/package-manifest.test.ts +105 -21
- package/tests/packed-runner-owned-path.test.ts +35 -1
- package/tests/parallel-reason-contract.test.ts +21 -0
- package/tests/parallel-writer-admission.test.ts +210 -0
- package/tests/permission-mode-policy.test.ts +194 -0
- package/tests/persona-single-channel.test.ts +4 -12
- package/tests/pi-pretty.test.ts +56 -0
- package/tests/pi-update-launcher.test.ts +87 -0
- package/tests/pi-update.test.ts +186 -0
- package/tests/provider-defect-handoff.test.ts +4 -3
- package/tests/quiet-tool-rendering.test.ts +160 -3
- package/tests/rdd-aware-verification-contract.test.ts +29 -41
- package/tests/rdd-status-line.test.ts +52 -0
- package/tests/render-cache-performance.test.ts +48 -0
- package/tests/review-agent-end-preflight.test.ts +62 -10
- package/tests/review-candidate-view.test.ts +101 -12
- package/tests/review-contract-prompt.test.ts +33 -4
- package/tests/review-controller-native-recovery.test.ts +327 -17
- package/tests/review-controller-native-routing.test.ts +255 -1
- package/tests/review-controller-workspace-root.test.ts +43 -2
- package/tests/review-controller.test.ts +2 -2
- package/tests/review-correction-lifecycle.test.ts +2 -1
- package/tests/review-gate.test.ts +7 -4
- package/tests/review-graph-schema.test.ts +2 -2
- package/tests/review-host-relay-routing.test.ts +5 -3
- package/tests/review-host-relay.test.ts +49 -2
- package/tests/review-integration-v2-forward.test.ts +21 -1
- package/tests/review-json-arguments.test.ts +167 -0
- package/tests/review-last-event-closure.test.ts +157 -8
- package/tests/review-ledger-contract.test.ts +5 -4
- package/tests/review-policy-judgment-day.test.ts +1 -1
- package/tests/review-policy-ordinary.test.ts +2 -2
- package/tests/review-relay-transport-agent.test.ts +66 -1
- package/tests/review-risk-assessment.test.ts +109 -33
- package/tests/review-session-standing-permission-controller.test.ts +16 -17
- package/tests/review-session-standing-permission-ipc.test.ts +6 -5
- package/tests/review-test-fixtures.ts +7 -1
- package/tests/review-transaction.test.ts +18 -1
- package/tests/run-test-suite.test.ts +83 -5
- package/tests/runtime-harness.mjs +42 -15
- package/tests/runtime-metrics-extension.test.ts +1 -1
- package/tests/runtime-metrics-native.test.ts +31 -1
- package/tests/selection-engine.test.ts +65 -5
- package/tests/session-change-capture.test.ts +10 -10
- package/tests/session-changes-shell.test.ts +242 -48
- package/tests/session-changes.test.ts +17 -24
- package/tests/session-profile-binding.test.ts +163 -0
- package/tests/session-profile-freeze.test.ts +394 -0
- package/tests/session-profile-persistence.test.ts +334 -0
- package/tests/session-subject-routing-contract.test.ts +34 -0
- package/tests/session-worktree-registry.test.ts +57 -2
- package/tests/shell-bar.test.ts +40 -0
- package/tests/shell-changes-view.test.ts +85 -34
- package/tests/shell-changes.test.ts +79 -62
- package/tests/shell-render-cache-runtime.test.ts +69 -0
- package/tests/shell-render-cache.test.ts +129 -0
- package/tests/shell-sidebar-layout.test.ts +27 -2
- package/tests/shell-todo.test.ts +132 -11
- package/tests/shell-usage-view.test.ts +1 -1
- package/tests/shell-usage.test.ts +35 -0
- package/tests/short-check-routing-contract.test.ts +49 -0
- package/tests/skill-registry-watcher.test.ts +119 -0
- package/tests/skill-registry.test.ts +311 -5
- package/tests/startup-banner.test.ts +117 -3
- package/tests/startup-home-repo.test.ts +170 -0
- package/tests/status-timing-diagnostics.test.ts +283 -0
- package/tests/support/orchestrator-modules.ts +19 -0
- package/tests/task-size-routing-contract.test.ts +241 -0
- package/tests/telemetry-trigger.test.ts +27 -1
- package/tests/test-strength-contract.test.ts +124 -0
- package/tests/verify-agent-contract.test.ts +90 -0
- package/tests/verify-first-launch-contract.test.ts +139 -0
- package/tests/verify-package-files.test.ts +56 -0
- package/tests/vim-editor-adapter.test.ts +47 -21
- package/tests/visual-customization-policy.test.ts +32 -3
- package/tests/visual-customize-view.test.ts +288 -10
- package/tests/writer-edit-surface-scope.test.ts +59 -2
- package/tests/writer-surfaces.test.ts +199 -0
- package/tests/yolo-customize.test.ts +18 -3
- package/tests/yolo-mode-runtime.test.ts +37 -10
- package/tests/yolo-mode.test.ts +38 -5
- package/tests/yolo-session-policy.test.ts +1 -1
- /package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/bundle/README.md +0 -0
- /package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/bundle/schemas/lens.schema.json +0 -0
- /package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/bundle/schemas/refuter.schema.json +0 -0
- /package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/bundle/schemas/targeted-validator.schema.json +0 -0
- /package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/bundle/vectors/lens.json +0 -0
- /package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/bundle/vectors/refuter.json +0 -0
- /package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/bundle/vectors/targeted-validator.json +0 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# Opt-in Linux clean-machine acceptance for the browser installation wizard.
|
|
3
|
+
# Runs the real bootstrap and wizard inside a disposable debian:bookworm-slim
|
|
4
|
+
# container as a non-root user. Network access happens only inside that
|
|
5
|
+
# container; nothing reads or writes the host HOME. Not part of CI.
|
|
6
|
+
#
|
|
7
|
+
# Usage: sh scripts/test-installer-acceptance.sh [--worktree]
|
|
8
|
+
# default bundle = `git archive HEAD`
|
|
9
|
+
# --worktree bundle = tracked files as they are in the working tree,
|
|
10
|
+
# including uncommitted modifications (untracked files excluded)
|
|
11
|
+
# GENTLE_ACCEPTANCE_KEEP=1 keeps a failed run's container for inspection.
|
|
12
|
+
set -eu
|
|
13
|
+
fail() { printf 'acceptance: %s\n' "$1" >&2; exit 1; }
|
|
14
|
+
note() { printf 'acceptance: %s\n' "$1"; }
|
|
15
|
+
source_mode='head'
|
|
16
|
+
case $# in
|
|
17
|
+
0) ;;
|
|
18
|
+
1) [ "$1" = --worktree ] || fail "unknown argument: $1"; source_mode=worktree;;
|
|
19
|
+
*) fail 'usage: sh scripts/test-installer-acceptance.sh [--worktree]';;
|
|
20
|
+
esac
|
|
21
|
+
image=debian:bookworm-slim
|
|
22
|
+
# Upper bound for the whole installation inside the container.
|
|
23
|
+
install_limit=${GENTLE_ACCEPTANCE_INSTALL_SECONDS:-1500}
|
|
24
|
+
case $install_limit in ''|*[!0-9]*) fail 'GENTLE_ACCEPTANCE_INSTALL_SECONDS must be a whole number';; esac
|
|
25
|
+
command -v docker >/dev/null 2>&1 || fail 'Docker is required; refusing to run anything on the host'
|
|
26
|
+
docker info >/dev/null 2>&1 || fail 'Docker daemon is unavailable; refusing to run anything on the host'
|
|
27
|
+
command -v git >/dev/null 2>&1 || fail 'git is required to package the bundle'
|
|
28
|
+
repo=$(git rev-parse --show-toplevel) || fail 'run from inside the repository'
|
|
29
|
+
started=$(date +%s)
|
|
30
|
+
elapsed() { printf '%ss' "$(( $(date +%s) - started ))"; }
|
|
31
|
+
name=gentle-install-acceptance-$$-$started
|
|
32
|
+
container=
|
|
33
|
+
passed=0
|
|
34
|
+
cleanup() {
|
|
35
|
+
if [ -n "$container" ] && [ "$passed" = 0 ] && [ "${GENTLE_ACCEPTANCE_KEEP:-}" = 1 ]; then
|
|
36
|
+
printf 'acceptance: kept %s; inspect with: docker exec -it -u tester %s bash; remove with: docker rm -f %s\n' "$container" "$container" "$container" >&2
|
|
37
|
+
elif [ -n "$container" ]; then
|
|
38
|
+
docker rm -f "$container" >/dev/null 2>&1 || printf 'acceptance: could not remove container %s\n' "$container" >&2
|
|
39
|
+
fi
|
|
40
|
+
}
|
|
41
|
+
trap cleanup EXIT
|
|
42
|
+
trap 'exit 1' HUP INT TERM
|
|
43
|
+
|
|
44
|
+
note "image $image, bundle from $source_mode"
|
|
45
|
+
docker run -d --name "$name" --pull missing "$image" sleep infinity >/dev/null || fail 'cannot start the container'
|
|
46
|
+
container=$name
|
|
47
|
+
# Clean machine: no Node, npm, pnpm, Pi or Gentle Shell. curl and CA roots are
|
|
48
|
+
# bootstrap prerequisites that a stock Debian desktop already has.
|
|
49
|
+
docker exec "$container" sh -c 'export DEBIAN_FRONTEND=noninteractive
|
|
50
|
+
apt-get update -qq >/dev/null && apt-get install -y -qq --no-install-recommends ca-certificates curl >/dev/null
|
|
51
|
+
useradd --create-home --shell /bin/bash tester
|
|
52
|
+
mkdir /opt/bundle
|
|
53
|
+
for tool in node npm pnpm pi gentle-shell; do if command -v "$tool" >/dev/null; then echo "unexpected $tool" >&2; exit 1; fi; done' \
|
|
54
|
+
|| fail 'container preparation failed'
|
|
55
|
+
# gentle-shell setup makes 2 anonymous GitHub API requests (upstream Gentle AI's
|
|
56
|
+
# latest-engram lookup), limited to 60 per hour per public IP. /rate_limit does
|
|
57
|
+
# not consume quota. Stop early instead of failing deep inside setup.
|
|
58
|
+
quota=$(docker exec "$container" sh -c 'curl -fsS --max-time 20 -H "Accept: application/vnd.github+json" https://api.github.com/rate_limit' | tr -d ' \n') \
|
|
59
|
+
|| fail 'cannot query the GitHub API rate limit from the container'
|
|
60
|
+
rate=$(printf '%s' "$quota" | sed -n 's/.*"rate":{\([^}]*\)}.*/\1/p')
|
|
61
|
+
remaining=$(printf '%s' "$rate" | sed -n 's/.*"remaining":\([0-9]*\).*/\1/p')
|
|
62
|
+
reset=$(printf '%s' "$rate" | sed -n 's/.*"reset":\([0-9]*\).*/\1/p')
|
|
63
|
+
[ -n "$remaining" ] && [ -n "$reset" ] || fail 'unexpected GitHub rate limit response'
|
|
64
|
+
reset_at=$(date -u -d "@$reset" '+%Y-%m-%d %H:%M:%S UTC' 2>/dev/null || date -u -r "$reset" '+%Y-%m-%d %H:%M:%S UTC' 2>/dev/null || printf 'epoch %s' "$reset")
|
|
65
|
+
if [ "$remaining" -lt 5 ]; then
|
|
66
|
+
fail "only $remaining anonymous GitHub API requests remain on this network (setup needs 2); the quota resets at $reset_at. Not starting."
|
|
67
|
+
fi
|
|
68
|
+
note "GitHub API quota: $remaining anonymous requests left (resets at $reset_at)"
|
|
69
|
+
if [ "$source_mode" = head ]; then
|
|
70
|
+
git -C "$repo" archive --format=tar HEAD
|
|
71
|
+
else
|
|
72
|
+
git -C "$repo" ls-files -z | tar -C "$repo" --null -T - -cf -
|
|
73
|
+
fi | docker exec -i "$container" tar --no-same-owner -xf - -C /opt/bundle || fail 'cannot copy the bundle'
|
|
74
|
+
note "prepared in $(elapsed)"
|
|
75
|
+
|
|
76
|
+
bootstrap_started=$(date +%s)
|
|
77
|
+
# A terminal session exports SHELL (the user's login shell); docker exec does
|
|
78
|
+
# not. pnpm setup needs it to pick the profile to edit, and fails with
|
|
79
|
+
# ERR_PNPM_UNKNOWN_SHELL without it.
|
|
80
|
+
docker exec -d -u tester -w /home/tester -e SHELL=/bin/bash "$container" sh -c \
|
|
81
|
+
'sh /opt/bundle/scripts/bootstrap.sh > "$HOME/bootstrap.log" 2>&1; echo $? > "$HOME/bootstrap.status"' \
|
|
82
|
+
|| fail 'cannot start the bootstrap'
|
|
83
|
+
|
|
84
|
+
# Headless browser stand-in: the same requests the wizard page makes.
|
|
85
|
+
driver=$(cat <<'DRIVER'
|
|
86
|
+
set -eu
|
|
87
|
+
log=$HOME/bootstrap.log
|
|
88
|
+
say() { printf 'driver: %s\n' "$1"; }
|
|
89
|
+
stop() { say "$1"; cat "$log" 2>/dev/null || :; exit 1; }
|
|
90
|
+
waited=0
|
|
91
|
+
while :; do
|
|
92
|
+
url=$(grep -o 'http://127\.0\.0\.1:[0-9]*/session?code=[A-Za-z0-9_-]*' "$log" 2>/dev/null | head -n 1) || url=
|
|
93
|
+
[ -z "$url" ] || break
|
|
94
|
+
[ ! -f "$HOME/bootstrap.status" ] || stop 'bootstrap exited before printing the session URL'
|
|
95
|
+
waited=$((waited + 1)); [ "$waited" -lt 600 ] || stop 'no session URL after 600 s'
|
|
96
|
+
sleep 1
|
|
97
|
+
done
|
|
98
|
+
say "session URL after ${waited}s"
|
|
99
|
+
origin=${url%%/session*}
|
|
100
|
+
jar=$HOME/acceptance-cookies
|
|
101
|
+
curl -fsS -c "$jar" -b "$jar" -o /dev/null "$url" || stop 'session redemption failed'
|
|
102
|
+
api() { curl -fsS -b "$jar" -H 'X-Gentle-Install: 1' "$@"; }
|
|
103
|
+
post() { api -X POST -H "Origin: $origin" -H 'Content-Type: application/json' --data "$1" "$origin$2"; }
|
|
104
|
+
plan=$(api "$origin/api/plan") || stop 'plan request failed'
|
|
105
|
+
case $plan in *'"blockers":[]'*) ;; *) stop "plan has blockers: $plan";; esac
|
|
106
|
+
plan_id=$(printf '%s' "$plan" | sed -n 's/.*"planId":"\([^"]*\)".*/\1/p')
|
|
107
|
+
[ -n "$plan_id" ] || stop "plan has no planId: $plan"
|
|
108
|
+
say "plan: $(printf '%s' "$plan" | grep -o '"actions":\[[^]]*\]' | grep -o '"id":"[^"]*"' | cut -d'"' -f4 | tr '\n' ' ')"
|
|
109
|
+
post "{\"planId\":\"$plan_id\",\"consent\":true}" /api/install >/dev/null || stop 'install request rejected'
|
|
110
|
+
seq=0
|
|
111
|
+
polls=0
|
|
112
|
+
while :; do
|
|
113
|
+
progress=$(api "$origin/api/progress?after=$seq") || stop 'progress request failed'
|
|
114
|
+
printf '%s' "$progress" | grep -o '"step":"[^"]*","status":"[^"]*"' | sed 's/"step":"\([^"]*\)","status":"\([^"]*\)"/ step \1: \2/' || :
|
|
115
|
+
last=$(printf '%s' "$progress" | grep -o '"seq":[0-9]*' | tail -n 1 | cut -d: -f2) || last=
|
|
116
|
+
[ -z "$last" ] || seq=$last
|
|
117
|
+
case $progress in *'"running":false'*'"outcome":{'*) break;; esac
|
|
118
|
+
polls=$((polls + 1)); [ "$polls" -lt "$INSTALL_LIMIT" ] || stop "installation still running after $INSTALL_LIMIT s"
|
|
119
|
+
sleep 1
|
|
120
|
+
done
|
|
121
|
+
outcome=$(printf '%s' "$progress" | sed -n 's/.*"outcome":{"outcome":"\([a-z-]*\)".*/\1/p')
|
|
122
|
+
say "outcome: $outcome"
|
|
123
|
+
post '{}' /api/shutdown >/dev/null || stop 'shutdown request rejected'
|
|
124
|
+
waited=0
|
|
125
|
+
until [ -f "$HOME/bootstrap.status" ]; do
|
|
126
|
+
waited=$((waited + 1)); [ "$waited" -lt 60 ] || stop 'bootstrap still running 60 s after shutdown'
|
|
127
|
+
sleep 1
|
|
128
|
+
done
|
|
129
|
+
status=$(cat "$HOME/bootstrap.status")
|
|
130
|
+
say "bootstrap exit status: $status"
|
|
131
|
+
cat "$log"
|
|
132
|
+
case $outcome in ready|terminal-action-required) [ "$status" = 0 ] || exit 1;; *) exit 1;; esac
|
|
133
|
+
DRIVER
|
|
134
|
+
)
|
|
135
|
+
printf '%s\n' "$driver" | docker exec -i -u tester -w /home/tester -e INSTALL_LIMIT="$install_limit" "$container" sh -s \
|
|
136
|
+
|| fail "wizard flow failed after $(elapsed)"
|
|
137
|
+
note "bootstrap and wizard finished in $(( $(date +%s) - bootstrap_started ))s"
|
|
138
|
+
|
|
139
|
+
# A fresh interactive shell must find the persisted stack; the bootstrap tools
|
|
140
|
+
# must be gone. bash -i without a terminal warns about job control; harmless.
|
|
141
|
+
checks=$(cat <<'CHECKS'
|
|
142
|
+
set -eu
|
|
143
|
+
for tool in node npm pnpm gentle-shell; do printf '%s -> %s\n' "$tool" "$(command -v "$tool")"; done
|
|
144
|
+
printf 'node %s, npm %s, pnpm %s\n' "$(node --version)" "$(npm --version)" "$(pnpm --version)"
|
|
145
|
+
gentle-shell --version
|
|
146
|
+
for dir in "$HOME"/.gentle-shell-bootstrap-tools.*; do
|
|
147
|
+
if [ -e "$dir" ] || [ -L "$dir" ]; then echo "bootstrap tools left behind: $dir" >&2; exit 1; fi
|
|
148
|
+
done
|
|
149
|
+
echo 'bootstrap tools removed'
|
|
150
|
+
CHECKS
|
|
151
|
+
)
|
|
152
|
+
docker exec -u tester -w /home/tester "$container" bash -ic "$checks" || fail "fresh-terminal checks failed after $(elapsed)"
|
|
153
|
+
# Informational: pnpm setup edits only ~/.bashrc, which non-interactive login
|
|
154
|
+
# shells skip on Debian (see docs/install-wizard.md).
|
|
155
|
+
if docker exec -u tester -w /home/tester "$container" bash -lc 'command -v gentle-shell' >/dev/null 2>&1; then
|
|
156
|
+
note 'bash -lc resolves gentle-shell'
|
|
157
|
+
else
|
|
158
|
+
note 'bash -lc does not resolve gentle-shell (expected: ~/.profile is not edited)'
|
|
159
|
+
fi
|
|
160
|
+
passed=1
|
|
161
|
+
note "PASS in $(elapsed)"
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import assert from "node:assert/strict";
|
|
4
|
+
import { normalizeNpmPackResult, parseNpmPackResult } from "./npm-pack-result.mjs";
|
|
4
5
|
import { execFileSync, spawn } from "node:child_process";
|
|
5
6
|
import { createHash } from "node:crypto";
|
|
6
7
|
import { existsSync, lstatSync, mkdtempSync, mkdirSync, readFileSync, readdirSync, realpathSync, rmSync, writeFileSync } from "node:fs";
|
|
@@ -599,6 +600,23 @@ function runWindowsStartupTimingProbe(runtimeScript, env, cwd) {
|
|
|
599
600
|
});
|
|
600
601
|
}
|
|
601
602
|
|
|
603
|
+
export function createHookedPackedConsumerManifest(installDirectory, tarball) {
|
|
604
|
+
const ownedTarball = assertOwnedRegularFile(dirname(tarball), basename(tarball));
|
|
605
|
+
const consumer = realpathSync.native(installDirectory);
|
|
606
|
+
const canonicalTarball = realpathSync.native(ownedTarball);
|
|
607
|
+
const filePath = relative(consumer, canonicalTarball);
|
|
608
|
+
if (isAbsolute(filePath)) throw new Error("packed tarball must share the consumer filesystem root");
|
|
609
|
+
const fileSpec = `file:${filePath.split(sep).join("/")}`;
|
|
610
|
+
if (realpathSync.native(resolve(consumer, fileSpec.slice(5))) !== canonicalTarball) throw new Error("script approval does not resolve to the packed tarball");
|
|
611
|
+
// npm 12 matches local dependencies by their resolved file spec, not name.
|
|
612
|
+
// Absolute installs on npm 12 retain an absolute node.resolved; the relative
|
|
613
|
+
// key alone was empirically blocked. Both keys identify this same tarball.
|
|
614
|
+
// Older npm ignores this consumer-only field. No transitive script is approved.
|
|
615
|
+
const absoluteSpec = `file:${canonicalTarball.split(sep).join("/")}`;
|
|
616
|
+
if (realpathSync.native(absoluteSpec.slice(5)) !== canonicalTarball) throw new Error("absolute script approval does not resolve to the packed tarball");
|
|
617
|
+
return { name: "gentle-pi-packed-runner-test", private: true, allowScripts: { [fileSpec]: true, [absoluteSpec]: true } };
|
|
618
|
+
}
|
|
619
|
+
|
|
602
620
|
async function testHookedPackedRunner() {
|
|
603
621
|
const temporary = mkdtempSync(join(tmpdir(), "gentle-pi-packed-runner-"));
|
|
604
622
|
const packDirectory = join(temporary, "pack");
|
|
@@ -615,14 +633,14 @@ async function testHookedPackedRunner() {
|
|
|
615
633
|
mkdirSync(piAgentHome);
|
|
616
634
|
const originalSettings = '{ "tuiMode": "regular", "theme": "packed-fixture" }\n';
|
|
617
635
|
writeFileSync(join(agentHome, "settings.json"), originalSettings);
|
|
618
|
-
const packed =
|
|
636
|
+
const packed = parseNpmPackResult(runNpm(["pack", "--ignore-scripts", "--json", "--pack-destination", packDirectory], {
|
|
619
637
|
cwd: root,
|
|
620
638
|
encoding: "utf8",
|
|
621
639
|
stdio: ["ignore", "pipe", "inherit"],
|
|
622
640
|
}));
|
|
623
641
|
if (packed.length !== 1 || typeof packed[0]?.filename !== "string") throw new Error("npm pack did not return one tarball");
|
|
624
|
-
const tarball =
|
|
625
|
-
writeFileSync(join(installDirectory, "package.json"), JSON.stringify(
|
|
642
|
+
const { tarball } = assertPackResult(packed, packDirectory, newUnhookedReceipt());
|
|
643
|
+
writeFileSync(join(installDirectory, "package.json"), JSON.stringify(createHookedPackedConsumerManifest(installDirectory, tarball)), "utf8");
|
|
626
644
|
runNpm(["install", "--ignore-scripts=false", "--no-audit", "--no-fund", "--package-lock=false", "--omit=dev", "--legacy-peer-deps", tarball], {
|
|
627
645
|
cwd: installDirectory,
|
|
628
646
|
stdio: "inherit",
|
|
@@ -657,6 +675,7 @@ async function testHookedPackedRunner() {
|
|
|
657
675
|
assert.ok(!abandonAuthorization.includes("evidence_records_present"));
|
|
658
676
|
// Accept prerelease pins too: a stable-only pattern here was a second,
|
|
659
677
|
// silent pin that refused the first prerelease version directory.
|
|
678
|
+
if (!existsSync(join(packageRoot, ".gentle-ai"))) throw new Error("packed postinstall did not create .gentle-ai; npm may have blocked lifecycle scripts — check the consumer allowScripts exact tarball approval and installer output");
|
|
660
679
|
const versions = readdirSync(join(packageRoot, ".gentle-ai"), { withFileTypes: true }).filter((entry) => entry.isDirectory() && /^v\d+\.\d+\.\d+(?:-[0-9A-Za-z][0-9A-Za-z.]*)?$/.test(entry.name));
|
|
661
680
|
if (versions.length !== 1) throw new Error("packed install did not contain exactly one package-local Gentle AI version");
|
|
662
681
|
const executable = join(packageRoot, ".gentle-ai", versions[0].name, process.platform === "win32" ? "gentle-ai.exe" : "gentle-ai");
|
|
@@ -801,8 +820,7 @@ export function validateWindowsStartupTimingMachinePaths(delta, operations = { l
|
|
|
801
820
|
|
|
802
821
|
function assertPackResult(packed, packDirectory, receipt) {
|
|
803
822
|
selectUnhookedCheck(receipt, "pack-metadata");
|
|
804
|
-
|
|
805
|
-
const entry = packed[0];
|
|
823
|
+
const [entry] = normalizeNpmPackResult(packed);
|
|
806
824
|
if (entry.name !== "gentle-pi" || typeof entry.filename !== "string" || entry.filename !== basename(entry.filename)) throw new Error("npm pack returned an unsafe package identity");
|
|
807
825
|
if (typeof entry.integrity !== "string" || !/^sha512-[A-Za-z0-9+/]+={0,2}$/.test(entry.integrity)) throw new Error("npm pack did not report a sha512 integrity");
|
|
808
826
|
const tarball = resolve(packDirectory, entry.filename);
|
|
@@ -1,95 +1,5 @@
|
|
|
1
1
|
{
|
|
2
2
|
"note": "Recorded TypeScript diagnostics. Regenerate with `node scripts/check-types.mjs --update` after fixing or deliberately accepting diagnostics. This file may only shrink without a review decision.",
|
|
3
|
-
"total":
|
|
4
|
-
"byFileAndCode": {
|
|
5
|
-
"extensions/codegraph-tools.ts TS2339": 1,
|
|
6
|
-
"extensions/codegraph-tools.ts TS2345": 1,
|
|
7
|
-
"extensions/gentle-agents.ts TS2322": 3,
|
|
8
|
-
"extensions/gentle-ai.ts TS2322": 5,
|
|
9
|
-
"extensions/gentle-ai.ts TS2339": 11,
|
|
10
|
-
"extensions/gentle-ai.ts TS2345": 15,
|
|
11
|
-
"extensions/gentle-ai.ts TS2365": 1,
|
|
12
|
-
"extensions/gentle-ai.ts TS2488": 2,
|
|
13
|
-
"extensions/gentle-ai.ts TS2554": 1,
|
|
14
|
-
"extensions/gentle-ai.ts TS2740": 1,
|
|
15
|
-
"extensions/gentle-shell.ts TS2556": 1,
|
|
16
|
-
"extensions/quiet-tools.ts TS2339": 1,
|
|
17
|
-
"extensions/quiet-tools.ts TS2352": 2,
|
|
18
|
-
"lib/agents-messaging.ts TS2322": 1,
|
|
19
|
-
"lib/native-review-cli.ts TS2304": 6,
|
|
20
|
-
"lib/native-review-cli.ts TS2339": 1,
|
|
21
|
-
"lib/native-review-cli.ts TS2345": 1,
|
|
22
|
-
"lib/review-candidate-view.ts TS2353": 2,
|
|
23
|
-
"lib/review-compact-contract.ts TS2322": 2,
|
|
24
|
-
"lib/review-compact-contract.ts TS2365": 1,
|
|
25
|
-
"lib/review-integration-v2.ts TS2322": 2,
|
|
26
|
-
"lib/review-integration-v2.ts TS2352": 2,
|
|
27
|
-
"lib/review-publication-gate.ts TS2365": 2,
|
|
28
|
-
"lib/review-transaction.ts TS2322": 1,
|
|
29
|
-
"lib/review-transaction.ts TS2345": 1,
|
|
30
|
-
"lib/runtime-metrics-children.ts TS2345": 2,
|
|
31
|
-
"lib/sdd-preflight.ts TS2352": 1,
|
|
32
|
-
"lib/sdd-preflight.ts TS2365": 1,
|
|
33
|
-
"lib/shell-sidebar-layout.ts TS2341": 1,
|
|
34
|
-
"tests/agents-queries.test.ts TS2322": 1,
|
|
35
|
-
"tests/agents-queries.test.ts TS2345": 3,
|
|
36
|
-
"tests/agents-runner-process.test.ts TS2322": 1,
|
|
37
|
-
"tests/devbinary/native-review-parity.devtest.ts TS2339": 1,
|
|
38
|
-
"tests/devbinary/pi-host-relay.devtest.ts TS2339": 3,
|
|
39
|
-
"tests/gentle-ai-binary.test.ts TS2339": 2,
|
|
40
|
-
"tests/gentle-ai-installer.test.ts TS2339": 7,
|
|
41
|
-
"tests/gentle-ai-installer.test.ts TS2556": 1,
|
|
42
|
-
"tests/gentle-ai-renderer.test.ts TS2345": 6,
|
|
43
|
-
"tests/gentle-ai.test.ts TS2339": 1,
|
|
44
|
-
"tests/gentle-ai.test.ts TS2352": 8,
|
|
45
|
-
"tests/gentle-ai.test.ts TS2353": 1,
|
|
46
|
-
"tests/gentle-shell.test.ts TS2352": 1,
|
|
47
|
-
"tests/gentle-shell.test.ts TS2540": 1,
|
|
48
|
-
"tests/gentle-shell.test.ts TS2554": 1,
|
|
49
|
-
"tests/maintainer/provider-relay.maintest.ts TS2339": 17,
|
|
50
|
-
"tests/maintainer/provider-relay.maintest.ts TS2345": 1,
|
|
51
|
-
"tests/maintainer/provider-relay.maintest.ts TS2540": 2,
|
|
52
|
-
"tests/native-binary-gate.test.ts TS2339": 2,
|
|
53
|
-
"tests/native-review-consent.test.ts TS2554": 1,
|
|
54
|
-
"tests/native-review-parity-runtime.test.ts TS2339": 1,
|
|
55
|
-
"tests/quiet-tool-rendering.test.ts TS2339": 1,
|
|
56
|
-
"tests/quiet-tool-rendering.test.ts TS2345": 1,
|
|
57
|
-
"tests/review-agent-end-preflight.test.ts TS2339": 2,
|
|
58
|
-
"tests/review-agent-end-preflight.test.ts TS2345": 1,
|
|
59
|
-
"tests/review-candidate-view.test.ts TS2353": 4,
|
|
60
|
-
"tests/review-candidate-view.test.ts TS2540": 2,
|
|
61
|
-
"tests/review-candidate-view.test.ts TS2554": 2,
|
|
62
|
-
"tests/review-controller-native-recovery.test.ts TS2345": 1,
|
|
63
|
-
"tests/review-controller-native-routing.test.ts TS2339": 2,
|
|
64
|
-
"tests/review-controller-workspace-root.test.ts TS2322": 2,
|
|
65
|
-
"tests/review-correction-lifecycle.test.ts TS2339": 4,
|
|
66
|
-
"tests/review-gate.test.ts TS2322": 5,
|
|
67
|
-
"tests/review-gate.test.ts TS2345": 4,
|
|
68
|
-
"tests/review-gate.test.ts TS2740": 1,
|
|
69
|
-
"tests/review-graph-schema.test.ts TS2352": 2,
|
|
70
|
-
"tests/review-host-relay-routing.test.ts TS2345": 1,
|
|
71
|
-
"tests/review-host-relay-routing.test.ts TS2739": 1,
|
|
72
|
-
"tests/review-integration-v2-forward.test.ts TS2322": 1,
|
|
73
|
-
"tests/review-last-event-closure.test.ts TS2322": 1,
|
|
74
|
-
"tests/review-policy-judgment-day.test.ts TS2345": 1,
|
|
75
|
-
"tests/review-policy-ordinary.test.ts TS2345": 1,
|
|
76
|
-
"tests/review-policy-ordinary.test.ts TS2554": 1,
|
|
77
|
-
"tests/review-risk-assessment.test.ts TS2345": 1,
|
|
78
|
-
"tests/review-risk-assessment.test.ts TS2352": 1,
|
|
79
|
-
"tests/review-session-standing-permission-controller.test.ts TS2339": 1,
|
|
80
|
-
"tests/review-session-standing-permission-controller.test.ts TS2345": 1,
|
|
81
|
-
"tests/review-session-standing-permission-controller.test.ts TS2352": 1,
|
|
82
|
-
"tests/review-session-standing-permission-ipc.test.ts TS2322": 4,
|
|
83
|
-
"tests/review-test-fixtures.ts TS2739": 1,
|
|
84
|
-
"tests/review-transaction.test.ts TS2339": 1,
|
|
85
|
-
"tests/runtime-metrics-extension.test.ts TS2345": 1,
|
|
86
|
-
"tests/sdd-preflight.test.ts TS2352": 1,
|
|
87
|
-
"tests/sdd-preflight.test.ts TS2554": 2,
|
|
88
|
-
"tests/sdd-research-live.test.ts TS2322": 1,
|
|
89
|
-
"tests/shell-sidebar-layout.test.ts TS2339": 1,
|
|
90
|
-
"tests/shell-sidebar-layout.test.ts TS2345": 1,
|
|
91
|
-
"tests/shell-usage-view.test.ts TS2322": 1,
|
|
92
|
-
"tests/skill-registry.test.ts TS2345": 5,
|
|
93
|
-
"tests/writer-edit-surface-scope.test.ts TS2352": 1
|
|
94
|
-
}
|
|
3
|
+
"total": 0,
|
|
4
|
+
"byFileAndCode": {}
|
|
95
5
|
}
|
|
@@ -7,10 +7,56 @@ import { fileURLToPath, pathToFileURL } from "node:url";
|
|
|
7
7
|
|
|
8
8
|
const root = join(fileURLToPath(new URL("..", import.meta.url)));
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
// Browser installation wizard: bootstrap scripts, entry, host and static assets.
|
|
11
|
+
export const installerPaths = Object.freeze([
|
|
12
|
+
"bin/gentle-shell-install.mjs",
|
|
13
|
+
"scripts/installer-server.mjs",
|
|
14
|
+
"scripts/installer-runner.mjs",
|
|
15
|
+
"scripts/installer-preflight.mjs",
|
|
16
|
+
"scripts/installer-probes.mjs",
|
|
17
|
+
"scripts/installer-downloads.mjs",
|
|
18
|
+
"scripts/main-channel.mjs",
|
|
19
|
+
"scripts/installer-windows.mjs",
|
|
20
|
+
"scripts/installer-windows-artifacts.json",
|
|
21
|
+
"scripts/bundled-wizard.mjs",
|
|
22
|
+
"scripts/bundled-install.mjs",
|
|
23
|
+
"scripts/bootstrap.sh",
|
|
24
|
+
"scripts/bootstrap.cmd",
|
|
25
|
+
"assets/install-wizard/index.html",
|
|
26
|
+
"assets/install-wizard/wizard.js",
|
|
27
|
+
"assets/install-wizard/wizard.css",
|
|
28
|
+
]);
|
|
29
|
+
|
|
30
|
+
export const requiredPaths = [
|
|
11
31
|
"bin/gentle-shell.mjs",
|
|
32
|
+
...installerPaths,
|
|
33
|
+
"extensions/gentle-notifications.ts",
|
|
34
|
+
"lib/notification-audio.ts",
|
|
35
|
+
"lib/notification-audio-native.ts",
|
|
36
|
+
"lib/notification-audio-windows.ts",
|
|
37
|
+
"lib/notification-pulse-protocol.ts",
|
|
38
|
+
"lib/notification-pulse-client.ts",
|
|
39
|
+
"lib/notification-pulse-stream.ts",
|
|
40
|
+
"lib/notification-pulse-worker.ts",
|
|
41
|
+
"lib/notification-customize.ts",
|
|
42
|
+
"lib/notification-events.ts",
|
|
43
|
+
"lib/notification-policy.ts",
|
|
44
|
+
"lib/notification-scheduler.ts",
|
|
45
|
+
"lib/notification-service.ts",
|
|
46
|
+
"lib/notification-ui.ts",
|
|
47
|
+
"assets/sounds/success.wav",
|
|
48
|
+
"assets/sounds/error.wav",
|
|
49
|
+
"assets/sounds/attention.wav",
|
|
50
|
+
"assets/sounds/LICENSE.md",
|
|
51
|
+
"docs/sound-notifications.md",
|
|
52
|
+
"docs/sound-notifications-proposal.md",
|
|
53
|
+
"scripts/npm-pack-result.mjs",
|
|
12
54
|
"assets/orchestrator.md",
|
|
13
55
|
"assets/orchestrator-delegation.md",
|
|
56
|
+
"assets/orchestrator-tracking.md",
|
|
57
|
+
"assets/orchestrator-verification.md",
|
|
58
|
+
"assets/orchestrator-writer.md",
|
|
59
|
+
"assets/orchestrator-prompts.md",
|
|
14
60
|
"assets/orchestrator-memory.md",
|
|
15
61
|
"assets/orchestrator-skills.md",
|
|
16
62
|
"assets/agents/gentle-ai-explore.md",
|
|
@@ -36,20 +82,33 @@ const requiredPaths = [
|
|
|
36
82
|
"extensions/gentle-ai.ts",
|
|
37
83
|
"extensions/resume-hint.ts",
|
|
38
84
|
"extensions/skill-registry.ts",
|
|
85
|
+
"lib/child-package-injection.ts",
|
|
39
86
|
"lib/gentle-ai-binary.ts",
|
|
40
87
|
"lib/gentle-shell-launcher.ts",
|
|
88
|
+
"lib/gentle-shell-bundled.ts",
|
|
89
|
+
"lib/gentle-shell-startup-update.ts",
|
|
90
|
+
"lib/gentle-shell-update-panel.ts",
|
|
91
|
+
"lib/gentle-shell-startup-flow.ts",
|
|
41
92
|
"lib/gentle-shell-resume-hint.ts",
|
|
42
93
|
"lib/native-review-cli.ts",
|
|
94
|
+
"lib/status-timing-diagnostics.ts",
|
|
43
95
|
"lib/provider-contract-bundle.ts",
|
|
44
96
|
"lib/review-host-relay.ts",
|
|
45
97
|
"lib/review-integration-v2.ts",
|
|
46
98
|
"lib/review-relay-contract.ts",
|
|
47
99
|
"lib/agent-assets.ts",
|
|
48
100
|
"lib/telemetry-trigger.ts",
|
|
101
|
+
"runtime/child-package-injection.mjs",
|
|
49
102
|
"runtime/gentle-ai-binary.mjs",
|
|
50
103
|
"runtime/gentle-shell-launcher.mjs",
|
|
104
|
+
"runtime/gentle-shell-bundled.mjs",
|
|
105
|
+
"runtime/gentle-shell-startup-update.mjs",
|
|
106
|
+
"runtime/gentle-shell-update-panel.mjs",
|
|
107
|
+
"runtime/gentle-shell-startup-flow.mjs",
|
|
51
108
|
"runtime/gentle-shell-resume-hint.mjs",
|
|
109
|
+
"runtime/gentle-shell-uninstall.mjs",
|
|
52
110
|
"runtime/native-review-cli.mjs",
|
|
111
|
+
"runtime/status-timing-diagnostics.mjs",
|
|
53
112
|
"runtime/review-integration-v2.mjs",
|
|
54
113
|
"runtime/review-risk-assessment.mjs",
|
|
55
114
|
"runtime/review-relay-contract.mjs",
|
|
@@ -72,17 +131,17 @@ const requiredPaths = [
|
|
|
72
131
|
// exact bytes are pinned by the lock-driven scripts/check-provider-contract.mjs
|
|
73
132
|
// drift check, which runs in the same pnpm test flow.
|
|
74
133
|
"contracts/review-provider-contract-mirror/provider-contract.lock.json",
|
|
75
|
-
"contracts/review-provider-contract-mirror/v1.
|
|
76
|
-
"contracts/review-provider-contract-mirror/v1.
|
|
77
|
-
"contracts/review-provider-contract-mirror/v1.
|
|
78
|
-
"contracts/review-provider-contract-mirror/v1.
|
|
79
|
-
"contracts/review-provider-contract-mirror/v1.
|
|
80
|
-
"contracts/review-provider-contract-mirror/v1.
|
|
81
|
-
"contracts/review-provider-contract-mirror/v1.
|
|
82
|
-
"contracts/review-provider-contract-mirror/v1.
|
|
83
|
-
"contracts/review-provider-contract-mirror/v1.
|
|
84
|
-
"contracts/review-provider-contract-mirror/v1.
|
|
85
|
-
"contracts/review-provider-contract-mirror/v1.
|
|
134
|
+
"contracts/review-provider-contract-mirror/v1.3.0/bundle/README.md",
|
|
135
|
+
"contracts/review-provider-contract-mirror/v1.3.0/bundle/manifest.json",
|
|
136
|
+
"contracts/review-provider-contract-mirror/v1.3.0/bundle/orchestration/pi.md",
|
|
137
|
+
"contracts/review-provider-contract-mirror/v1.3.0/bundle/schemas/lens.schema.json",
|
|
138
|
+
"contracts/review-provider-contract-mirror/v1.3.0/bundle/schemas/refuter.schema.json",
|
|
139
|
+
"contracts/review-provider-contract-mirror/v1.3.0/bundle/schemas/targeted-validator.schema.json",
|
|
140
|
+
"contracts/review-provider-contract-mirror/v1.3.0/bundle/vectors/lens.json",
|
|
141
|
+
"contracts/review-provider-contract-mirror/v1.3.0/bundle/vectors/refuter.json",
|
|
142
|
+
"contracts/review-provider-contract-mirror/v1.3.0/bundle/vectors/targeted-validator.json",
|
|
143
|
+
"contracts/review-provider-contract-mirror/v1.3.0/generated/provider-capabilities.baseline.json",
|
|
144
|
+
"contracts/review-provider-contract-mirror/v1.3.0/generated/provider-roles.baseline.json",
|
|
86
145
|
"prompts/skill-creation.md",
|
|
87
146
|
"skills/_shared/review-ledger-contract.md",
|
|
88
147
|
"skills/branch-pr/SKILL.md",
|
|
@@ -173,6 +232,14 @@ const contractHashes = {
|
|
|
173
232
|
|
|
174
233
|
requiredPaths.push(...Object.keys(contractHashes));
|
|
175
234
|
|
|
235
|
+
// Required package-relative paths that are missing or are not regular files.
|
|
236
|
+
export function missingRequiredPaths(packageRoot, paths) {
|
|
237
|
+
return paths.filter((relativePath) => {
|
|
238
|
+
const absolutePath = join(packageRoot, relativePath);
|
|
239
|
+
return !existsSync(absolutePath) || !statSync(absolutePath).isFile();
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
|
|
176
243
|
function listFilesRecursively(directory) {
|
|
177
244
|
return readdirSync(directory, { withFileTypes: true }).flatMap((entry) => {
|
|
178
245
|
const absolutePath = join(directory, entry.name);
|
|
@@ -287,10 +354,7 @@ async function main() {
|
|
|
287
354
|
process.exit(1);
|
|
288
355
|
}
|
|
289
356
|
|
|
290
|
-
const missing = requiredPaths
|
|
291
|
-
const absolutePath = join(root, relativePath);
|
|
292
|
-
return !existsSync(absolutePath) || !statSync(absolutePath).isFile();
|
|
293
|
-
});
|
|
357
|
+
const missing = missingRequiredPaths(root, requiredPaths);
|
|
294
358
|
|
|
295
359
|
if (missing.length > 0) {
|
|
296
360
|
console.error("gentle-pi package is missing required Pi resources:");
|
|
@@ -331,7 +395,7 @@ async function main() {
|
|
|
331
395
|
});
|
|
332
396
|
|
|
333
397
|
if (driftedContracts.length > 0) {
|
|
334
|
-
console.error("gentle-pi packaged review-integration/v1 and review-integration/v2 contract bytes drifted from the pinned v4.
|
|
398
|
+
console.error("gentle-pi packaged review-integration/v1 and review-integration/v2 contract bytes drifted from the pinned v4.1.1 runtime's vendored Gentle AI contract artifacts:");
|
|
335
399
|
for (const drift of driftedContracts) console.error(`- ${drift.relativePath}: expected ${drift.expected}, got ${drift.actual}`);
|
|
336
400
|
process.exit(1);
|
|
337
401
|
}
|
|
@@ -376,7 +440,7 @@ async function main() {
|
|
|
376
440
|
process.exit(1);
|
|
377
441
|
}
|
|
378
442
|
|
|
379
|
-
console.log(`gentle-pi package resource check passed (${requiredPaths.length} files; ${Object.keys(contractHashes).length} exact byte-pinned contract artifacts for the v4.
|
|
443
|
+
console.log(`gentle-pi package resource check passed (${requiredPaths.length} files; ${Object.keys(contractHashes).length} exact byte-pinned contract artifacts for the v4.1.1 runtime).`);
|
|
380
444
|
}
|
|
381
445
|
|
|
382
446
|
const isMainModule = process.argv[1] !== undefined && import.meta.url === pathToFileURL(process.argv[1]).href;
|
|
@@ -14,11 +14,11 @@ When asked who or what you are, answer as el Gentleman: a Pi-specific coding-age
|
|
|
14
14
|
## Compact Rules
|
|
15
15
|
|
|
16
16
|
- Clarify scope, constraints, acceptance criteria, and non-goals before implementation.
|
|
17
|
-
-
|
|
17
|
+
- Size every task by the orchestrator's Task Size section: understood, contained risk, and resumable from the original request plus `git diff`. Counts of files, commands, tests, or fixes never decide it. Track only large work in its task document and mirror.
|
|
18
18
|
- For behavior changes with applicable runnable deterministic tests and a clear expected outcome, use test-first by default: observe RED, GREEN, relevant alternate cases, then REFACTOR and record evidence. Test presence alone does not establish applicability. For passive documentation, non-testable changes, an unavailable runner, or no meaningful RED, state why and run proportionate ordinary functional or structural verification. Never invent RED/GREEN, skip checks, or require a chat/TUI toggle.
|
|
19
19
|
- Keep one parent session responsible for orchestration; child subagents should receive concrete phase work and must not spawn more subagents.
|
|
20
|
-
- Parent-only delegation triggers
|
|
21
|
-
-
|
|
20
|
+
- Parent-only delegation triggers fire one mechanism at a time: an open decision (ask), understanding beyond the evidence budget (explore), high risk (independent verifier), a large task (track), a writer reason (parallel units or context), tooling/worktree incidents, or a parent context past the context backstop.
|
|
21
|
+
- Parallel writers only with disjoint Allowed edit surfaces (runtime-enforced) or isolated worktrees.
|
|
22
22
|
- Forecast review workload before large changes; ask before producing oversized or multi-area diffs.
|
|
23
23
|
- Keep dangerous-command safety independent and authoritative.
|
|
24
24
|
- Never claim persistent memory is available because of el Gentleman itself; memory is provided by separate packages/tools when active.
|
|
@@ -30,23 +30,24 @@ When asked who or what you are, answer as el Gentleman: a Pi-specific coding-age
|
|
|
30
30
|
Use the smallest safe harness:
|
|
31
31
|
|
|
32
32
|
```text
|
|
33
|
-
small
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
small task → inline direct, focused test and suite inline
|
|
34
|
+
understanding is missing → explore, then re-evaluate
|
|
35
|
+
large authorized work → track ODD tasks and implement by work unit
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
-
For
|
|
38
|
+
For large implementation with subagents:
|
|
39
39
|
|
|
40
40
|
```text
|
|
41
|
-
clarify → scout/context-builder when context-heavy →
|
|
41
|
+
clarify → scout/context-builder when context-heavy → inline, or a writer only for a reason → verify
|
|
42
42
|
```
|
|
43
43
|
|
|
44
44
|
Hard delegation triggers:
|
|
45
45
|
|
|
46
|
-
- **Evidence-budget rule**: read inline only when the evidence fits one parallel batch of at most 3 calls, ~10k tokens (grep and line ranges, never whole large files).
|
|
47
|
-
- **
|
|
46
|
+
- **Evidence-budget rule**: read inline only when the evidence fits one parallel batch of at most 3 calls, ~10k tokens (grep and line ranges, never whole large files). When understanding needs more reading or more than ~5 sequential lookups, delegate one explorer that returns a handoff of at most ~2k tokens with `path:line` evidence. Never force delegation for a small targeted question; do not re-read what the handoff covered beyond one spot check.
|
|
47
|
+
- **Writer rule**: a writer only for a reason (parallel units launched together, or context); size and file count never fire it.
|
|
48
|
+
- **Verification rule**: a high-risk change gets an independent verifier; otherwise the change's own focused test and suite run inline.
|
|
48
49
|
- **Incident rule**: after wrong cwd, accidental worktree/repo mutation, merge recovery, confusing test command, or environment workaround, diagnose separately.
|
|
49
|
-
- **Context backstop**: when the parent context passes ~150k tokens, pause and delegate the next bounded unit of work to a non-review subagent. Keep command output bounded (counts, `--stat`, `tail`)
|
|
50
|
+
- **Context backstop**: when the parent context passes ~150k tokens, pause and delegate the next bounded unit of work to a non-review subagent. Keep command output bounded (counts, `--stat`, `tail`).
|
|
50
51
|
|
|
51
52
|
## Review Lens Selection
|
|
52
53
|
|
package/tests/agent-home.test.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
|
-
import { mkdtempSync, rmSync } from "node:fs";
|
|
2
|
+
import { mkdtempSync, realpathSync, rmSync } from "node:fs";
|
|
3
3
|
import { homedir, tmpdir } from "node:os";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import test from "node:test";
|
|
6
|
-
import { gentlePiConfigHome } from "../lib/agent-home.ts";
|
|
6
|
+
import { bundledGentlePiAgentHome, gentlePiConfigHome } from "../lib/agent-home.ts";
|
|
7
|
+
import { setBundledInstallForTesting } from "../lib/gentle-shell-bundled.ts";
|
|
7
8
|
|
|
8
9
|
// The two Pi homes: `~/.pi/agent` holds Pi's own agent definitions and
|
|
9
10
|
// `~/.pi/gentle-ai` holds everything the Gentle AI commands own. Both are resolved
|
|
@@ -15,7 +16,9 @@ function isolatedHome(t: test.TestContext): string {
|
|
|
15
16
|
const home = mkdtempSync(join(tmpdir(), "gentle-pi-config-home-"));
|
|
16
17
|
const previousHome = process.env.HOME;
|
|
17
18
|
const previousUserProfile = process.env.USERPROFILE;
|
|
18
|
-
|
|
19
|
+
const previousConfigHome = process.env.GENTLE_PI_CONFIG_HOME;
|
|
20
|
+
// Clear the higher-priority config override as well as isolating both OS homes.
|
|
21
|
+
delete process.env.GENTLE_PI_CONFIG_HOME;
|
|
19
22
|
process.env.HOME = home;
|
|
20
23
|
process.env.USERPROFILE = home;
|
|
21
24
|
t.after(() => {
|
|
@@ -23,6 +26,8 @@ function isolatedHome(t: test.TestContext): string {
|
|
|
23
26
|
else process.env.HOME = previousHome;
|
|
24
27
|
if (previousUserProfile === undefined) delete process.env.USERPROFILE;
|
|
25
28
|
else process.env.USERPROFILE = previousUserProfile;
|
|
29
|
+
if (previousConfigHome === undefined) delete process.env.GENTLE_PI_CONFIG_HOME;
|
|
30
|
+
else process.env.GENTLE_PI_CONFIG_HOME = previousConfigHome;
|
|
26
31
|
rmSync(home, { recursive: true, force: true });
|
|
27
32
|
});
|
|
28
33
|
return home;
|
|
@@ -41,6 +46,25 @@ test("gentlePiConfigHome honours GENTLE_PI_CONFIG_HOME and otherwise falls back
|
|
|
41
46
|
);
|
|
42
47
|
});
|
|
43
48
|
|
|
49
|
+
test("the isolated home restores defined and undefined config overrides", async (t) => {
|
|
50
|
+
const previousConfigHome = process.env.GENTLE_PI_CONFIG_HOME;
|
|
51
|
+
try {
|
|
52
|
+
for (const inherited of [undefined, "/synthetic-inherited-config"]) {
|
|
53
|
+
if (inherited === undefined) delete process.env.GENTLE_PI_CONFIG_HOME;
|
|
54
|
+
else process.env.GENTLE_PI_CONFIG_HOME = inherited;
|
|
55
|
+
await t.test(`inherited override: ${inherited === undefined ? "unset" : "set"}`, (child) => {
|
|
56
|
+
const home = isolatedHome(child);
|
|
57
|
+
assert.equal(process.env.GENTLE_PI_CONFIG_HOME, undefined);
|
|
58
|
+
assert.equal(gentlePiConfigHome(), join(home, ".pi", "gentle-ai"));
|
|
59
|
+
});
|
|
60
|
+
assert.equal(process.env.GENTLE_PI_CONFIG_HOME, inherited);
|
|
61
|
+
}
|
|
62
|
+
} finally {
|
|
63
|
+
if (previousConfigHome === undefined) delete process.env.GENTLE_PI_CONFIG_HOME;
|
|
64
|
+
else process.env.GENTLE_PI_CONFIG_HOME = previousConfigHome;
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
|
|
44
68
|
test("the config home ignores the Pi agent-home overrides", (t) => {
|
|
45
69
|
const home = isolatedHome(t);
|
|
46
70
|
// PI_CODING_AGENT_DIR and GENTLE_PI_AGENT_HOME move Pi's agent directory only.
|
|
@@ -50,3 +74,32 @@ test("the config home ignores the Pi agent-home overrides", (t) => {
|
|
|
50
74
|
join(home, ".pi", "gentle-ai"),
|
|
51
75
|
);
|
|
52
76
|
});
|
|
77
|
+
|
|
78
|
+
// S9: a bundled Gentle Shell keeps gentle-pi's config inside its prefix. It is
|
|
79
|
+
// derived from this package's bundled install and the launcher's
|
|
80
|
+
// GENTLE_SHELL_PREFIX, never exported (Gentle AI 4.0.0 reads
|
|
81
|
+
// GENTLE_PI_CONFIG_HOME as a parent folder). The testing overlay stands in for
|
|
82
|
+
// this package running from that install.
|
|
83
|
+
function bundledInstall(t: test.TestContext): string {
|
|
84
|
+
const prefix = realpathSync(mkdtempSync(join(tmpdir(), "gentle-pi-bundled-config-")));
|
|
85
|
+
setBundledInstallForTesting({ root: prefix });
|
|
86
|
+
t.after(() => {
|
|
87
|
+
setBundledInstallForTesting(undefined);
|
|
88
|
+
rmSync(prefix, { recursive: true, force: true });
|
|
89
|
+
});
|
|
90
|
+
return prefix;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
test("a bundled install derives the config home inside its prefix and the agent home from Pi's", (t) => {
|
|
94
|
+
isolatedHome(t);
|
|
95
|
+
const prefix = bundledInstall(t);
|
|
96
|
+
const env = { GENTLE_SHELL_PREFIX: prefix, GENTLE_PI_CONFIG_HOME: "/home/ana/.pi/gentle-ai", PI_CODING_AGENT_DIR: "/agent" };
|
|
97
|
+
assert.equal(gentlePiConfigHome(env), join(prefix, "config", "gentle-ai"));
|
|
98
|
+
assert.equal(bundledGentlePiAgentHome(env), "/agent");
|
|
99
|
+
// Another prefix, or none, is not this install: everything stays as before.
|
|
100
|
+
for (const other of [{ GENTLE_PI_CONFIG_HOME: "/custom" }, { GENTLE_SHELL_PREFIX: join(prefix, "other"), GENTLE_PI_CONFIG_HOME: "/custom" }]) {
|
|
101
|
+
assert.equal(gentlePiConfigHome(other), "/custom");
|
|
102
|
+
assert.equal(bundledGentlePiAgentHome({ ...other, PI_CODING_AGENT_DIR: "/agent" }), undefined);
|
|
103
|
+
}
|
|
104
|
+
assert.equal(gentlePiConfigHome({ GENTLE_PI_CONFIG_HOME: "" }), join(homedir(), ".pi", "gentle-ai"));
|
|
105
|
+
});
|