@pellux/goodvibes-tui 2.0.13 → 2.0.15
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/.goodvibes/GOODVIBES.md +1 -1
- package/.goodvibes/agents/reviewer.md +8 -8
- package/.goodvibes/skills/add-provider/SKILL.md +22 -22
- package/CHANGELOG.md +61 -0
- package/README.md +40 -29
- package/docs/README.md +1 -1
- package/docs/foundation-artifacts/README.md +5 -5
- package/docs/foundation-artifacts/operator-contract.json +123 -123
- package/package.json +12 -10
- package/scripts/postinstall.js +3 -3
- package/src/audio/activation-sound.ts +7 -7
- package/src/audio/capture.ts +7 -7
- package/src/audio/onnxruntime-assets.d.ts +1 -1
- package/src/audio/player.ts +4 -4
- package/src/audio/spoken-turn-wiring.ts +4 -4
- package/src/audio/voice-capture-wiring.ts +5 -5
- package/src/audio/voice-input-session.ts +3 -3
- package/src/audio/wake-inference.ts +13 -8
- package/src/audio/wake-runtime.ts +10 -10
- package/src/cli/completions/generate.ts +2 -2
- package/src/cli/doctor.ts +13 -13
- package/src/cli/ensure-goodvibes-gitignore.ts +3 -3
- package/src/cli/entrypoint.ts +3 -3
- package/src/cli/help.ts +6 -6
- package/src/cli/hooks-command.ts +4 -4
- package/src/cli/hooks-report.ts +4 -4
- package/src/cli/launch-auto-update.ts +17 -17
- package/src/cli/management-commands.ts +8 -8
- package/src/cli/management-utils.ts +3 -3
- package/src/cli/management.ts +1 -1
- package/src/cli/plugin-bundles-command.ts +10 -10
- package/src/cli/plugin-command.ts +9 -9
- package/src/cli/service-posture.ts +1 -1
- package/src/cli/status.ts +10 -10
- package/src/cli/surface-command.ts +4 -4
- package/src/cli/tui-startup.ts +23 -23
- package/src/config/run-daemon-config-migration.ts +3 -3
- package/src/config/secret-config.ts +10 -10
- package/src/config/surface.ts +1 -1
- package/src/config/tui-extension-settings.ts +8 -8
- package/src/core/active-model-identity.ts +7 -7
- package/src/core/approval-alert.ts +5 -5
- package/src/core/bookmark-navigation.ts +3 -3
- package/src/core/budget-breach-notifier.ts +6 -6
- package/src/core/compaction-receipt.ts +8 -8
- package/src/core/composer-state.ts +2 -2
- package/src/core/context-usage.ts +1 -1
- package/src/core/conversation-compaction-render.ts +3 -3
- package/src/core/conversation-event-navigation.ts +2 -2
- package/src/core/conversation-fold.ts +9 -9
- package/src/core/conversation-line-cache.ts +14 -14
- package/src/core/conversation-render-context.ts +6 -6
- package/src/core/conversation-rendering.ts +27 -30
- package/src/core/conversation-search-expansion.ts +6 -6
- package/src/core/conversation-splash-state.ts +3 -3
- package/src/core/conversation-turn-structure.ts +13 -13
- package/src/core/conversation-types.ts +3 -3
- package/src/core/conversation-user-receipts.ts +5 -5
- package/src/core/conversation.ts +17 -17
- package/src/core/format-user-error.ts +5 -5
- package/src/core/long-task-notifier.ts +9 -9
- package/src/core/memory-diagnostics-gateway.ts +8 -8
- package/src/core/memory-provenance.ts +5 -5
- package/src/core/model-routing-chip.ts +3 -3
- package/src/core/pairing-tailscale-gateway.ts +3 -3
- package/src/core/permission-mode.ts +5 -5
- package/src/core/power-chip-source.ts +3 -3
- package/src/core/power-status.ts +8 -8
- package/src/core/rewind-receipt.ts +6 -6
- package/src/core/session-resume-core.ts +8 -8
- package/src/core/stream-event-wiring.ts +36 -36
- package/src/core/stream-stall-watchdog.ts +4 -4
- package/src/core/system-message-noise.ts +7 -7
- package/src/core/system-message-router.ts +10 -10
- package/src/core/terminal-notifier.ts +5 -5
- package/src/core/turn-budget-outcome.ts +5 -5
- package/src/core/turn-cancellation.ts +3 -3
- package/src/core/turn-event-wiring.ts +16 -16
- package/src/core/voice-capture-status.ts +2 -2
- package/src/core/voice-provision-gateway.ts +12 -12
- package/src/core/voice-provision-status.ts +19 -19
- package/src/core/voice-stt-gateway.ts +6 -6
- package/src/core/wake-provision-runner.ts +7 -7
- package/src/core/wake-provision-status.ts +17 -17
- package/src/core/workstream-notification.ts +8 -8
- package/src/export/gist-uploader.ts +7 -7
- package/src/input/autocomplete.ts +3 -3
- package/src/input/bookmark-modal.ts +1 -1
- package/src/input/command-args-hint.ts +2 -2
- package/src/input/command-reference.ts +9 -9
- package/src/input/command-registry.ts +32 -32
- package/src/input/commands/acp-runtime.ts +6 -6
- package/src/input/commands/calendar-runtime.ts +9 -9
- package/src/input/commands/channel-pairing.ts +11 -11
- package/src/input/commands/channel-runtime.ts +1 -1
- package/src/input/commands/checkin-runtime.ts +4 -4
- package/src/input/commands/checkpoint-runtime.ts +4 -4
- package/src/input/commands/ci-runtime.ts +4 -4
- package/src/input/commands/cluster-runtime.ts +3 -3
- package/src/input/commands/codebase-runtime.ts +16 -16
- package/src/input/commands/config.ts +6 -6
- package/src/input/commands/connection-status.ts +12 -12
- package/src/input/commands/context-window.ts +2 -2
- package/src/input/commands/cost-attribution-format.ts +4 -4
- package/src/input/commands/cost-runtime.ts +2 -2
- package/src/input/commands/devices-runtime.ts +7 -7
- package/src/input/commands/diff-runtime.ts +2 -2
- package/src/input/commands/editor-runtime.ts +1 -1
- package/src/input/commands/eval.ts +4 -4
- package/src/input/commands/experience-runtime.ts +1 -1
- package/src/input/commands/git-runtime.ts +3 -3
- package/src/input/commands/graph-runtime.ts +3 -3
- package/src/input/commands/guidance-runtime.ts +1 -1
- package/src/input/commands/health-metrics-format.ts +2 -2
- package/src/input/commands/health-runtime.ts +8 -8
- package/src/input/commands/hosted-runtime.ts +13 -13
- package/src/input/commands/image-runtime.ts +6 -6
- package/src/input/commands/intelligence-runtime.ts +2 -2
- package/src/input/commands/local-auth-runtime.ts +3 -3
- package/src/input/commands/local-provider-runtime.ts +3 -3
- package/src/input/commands/local-runtime.ts +7 -7
- package/src/input/commands/mail-runtime.ts +9 -9
- package/src/input/commands/mcp-runtime.ts +1 -1
- package/src/input/commands/memory.ts +13 -13
- package/src/input/commands/notify-runtime.ts +1 -1
- package/src/input/commands/operator-panel-runtime.ts +8 -8
- package/src/input/commands/operator-rpc.ts +3 -3
- package/src/input/commands/operator-runtime.ts +3 -3
- package/src/input/commands/palette-runtime.ts +1 -1
- package/src/input/commands/payment-card-intake.ts +17 -17
- package/src/input/commands/permissions-provenance.ts +7 -7
- package/src/input/commands/permissions-runtime.ts +1 -1
- package/src/input/commands/planning-runtime.ts +9 -9
- package/src/input/commands/platform-services-runtime.ts +2 -2
- package/src/input/commands/policy-dispatch.ts +6 -6
- package/src/input/commands/power-runtime.ts +6 -6
- package/src/input/commands/principals-runtime.ts +3 -3
- package/src/input/commands/product-runtime.ts +3 -3
- package/src/input/commands/profile-render.ts +13 -13
- package/src/input/commands/profile-runtime.ts +13 -13
- package/src/input/commands/profile-types.ts +13 -13
- package/src/input/commands/provider-accounts-runtime.ts +5 -5
- package/src/input/commands/provider.ts +10 -10
- package/src/input/commands/qrcode-runtime.ts +3 -3
- package/src/input/commands/queue-runtime.ts +6 -6
- package/src/input/commands/recall-files-config.ts +4 -4
- package/src/input/commands/recall-files-git.ts +3 -3
- package/src/input/commands/recall-files.ts +12 -12
- package/src/input/commands/recall-query.ts +3 -3
- package/src/input/commands/recall-review.ts +3 -3
- package/src/input/commands/recall-shared.ts +1 -1
- package/src/input/commands/relay-runtime.ts +5 -5
- package/src/input/commands/remote-runtime.ts +3 -3
- package/src/input/commands/review-runtime.ts +8 -8
- package/src/input/commands/rewind-runtime.ts +21 -21
- package/src/input/commands/runtime-services.ts +1 -2
- package/src/input/commands/schedule-nl.ts +2 -2
- package/src/input/commands/schedule-runtime.ts +2 -2
- package/src/input/commands/secret-runtime.ts +3 -3
- package/src/input/commands/session-content.ts +7 -7
- package/src/input/commands/session-picker-filter.ts +3 -3
- package/src/input/commands/session-workflow.ts +10 -10
- package/src/input/commands/session.ts +15 -15
- package/src/input/commands/settings-sync-runtime.ts +2 -2
- package/src/input/commands/share-runtime.ts +4 -4
- package/src/input/commands/shell-core.ts +11 -11
- package/src/input/commands/tasks-runtime.ts +4 -4
- package/src/input/commands/test-runtime.ts +6 -6
- package/src/input/commands/tts-runtime.ts +4 -4
- package/src/input/commands/update-runtime.ts +27 -27
- package/src/input/commands/websearch-runtime.ts +2 -2
- package/src/input/commands/work-plan-runtime.ts +2 -2
- package/src/input/commands/workstream-attempt-dependents.ts +4 -4
- package/src/input/commands/workstream-attempts.ts +16 -16
- package/src/input/commands/workstream-runtime.ts +36 -36
- package/src/input/commands/worktree-runtime.ts +6 -6
- package/src/input/composer-capture.ts +5 -5
- package/src/input/concealed-input.ts +2 -2
- package/src/input/config-modal-types.ts +16 -16
- package/src/input/config-modal.ts +30 -30
- package/src/input/daemon-owned-settings-descriptions.ts +4 -4
- package/src/input/delete-key-policy.ts +1 -1
- package/src/input/exec-env-scrub-config.ts +7 -7
- package/src/input/feature-unit-layout.ts +5 -5
- package/src/input/feed-context-factory.ts +38 -38
- package/src/input/file-picker.ts +1 -1
- package/src/input/handler-command-route.ts +2 -2
- package/src/input/handler-content-actions.ts +8 -8
- package/src/input/handler-feed-routes.ts +13 -13
- package/src/input/handler-feed.ts +31 -31
- package/src/input/handler-interactions.ts +2 -2
- package/src/input/handler-modal-routes.ts +13 -13
- package/src/input/handler-modal-stack.ts +1 -1
- package/src/input/handler-modal-token-routes.ts +1 -1
- package/src/input/handler-onboarding-daemon-adopt.ts +6 -6
- package/src/input/handler-picker-routes.ts +7 -7
- package/src/input/handler-prompt-buffer.ts +1 -1
- package/src/input/handler-shortcuts.ts +12 -12
- package/src/input/handler-types.ts +3 -3
- package/src/input/handler-ui-state.ts +1 -1
- package/src/input/handler.ts +9 -9
- package/src/input/input-history.ts +1 -1
- package/src/input/keybindings.ts +13 -13
- package/src/input/kill-ring.ts +7 -11
- package/src/input/model-picker-filter.ts +3 -3
- package/src/input/model-picker-items.ts +5 -5
- package/src/input/model-picker-types.ts +2 -2
- package/src/input/model-picker.ts +18 -18
- package/src/input/onboarding/onboarding-feature-units.ts +9 -13
- package/src/input/onboarding/onboarding-provider-key-fields.ts +3 -3
- package/src/input/onboarding/onboarding-runtime-status.ts +3 -3
- package/src/input/onboarding/onboarding-wizard-apply.ts +6 -6
- package/src/input/onboarding/onboarding-wizard-cloudflare-step.ts +1 -1
- package/src/input/onboarding/onboarding-wizard-constants.ts +1 -1
- package/src/input/onboarding/onboarding-wizard-external-surfaces.ts +4 -4
- package/src/input/onboarding/onboarding-wizard-network-adopt.ts +6 -6
- package/src/input/onboarding/onboarding-wizard-steps.ts +2 -2
- package/src/input/panel-integration-actions.ts +3 -3
- package/src/input/panel-mouse-geometry.ts +1 -1
- package/src/input/panel-paste-flood-guard.ts +9 -9
- package/src/input/payments-config.ts +15 -15
- package/src/input/profile-picker-modal.ts +1 -1
- package/src/input/provider-key-intake.ts +9 -9
- package/src/input/relay-settings-descriptions.ts +3 -3
- package/src/input/sandbox-exec-config.ts +9 -9
- package/src/input/search.ts +18 -18
- package/src/input/selection-modal-queue.ts +10 -10
- package/src/input/selection-modal.ts +2 -2
- package/src/input/session-picker-modal.ts +7 -7
- package/src/input/settings-modal-activation.ts +1 -1
- package/src/input/settings-modal-adjustment.ts +2 -2
- package/src/input/settings-modal-commit.ts +6 -6
- package/src/input/settings-modal-connections.ts +2 -2
- package/src/input/settings-modal-data.ts +29 -29
- package/src/input/settings-modal-mutations.ts +7 -7
- package/src/input/settings-modal-reset.ts +3 -3
- package/src/input/settings-modal-search.ts +6 -6
- package/src/input/settings-modal-secrets.ts +3 -3
- package/src/input/settings-modal-types.ts +16 -16
- package/src/input/settings-modal.ts +4 -4
- package/src/input/voice-local-settings.ts +3 -3
- package/src/input/worktree-setup-config.ts +8 -8
- package/src/main.ts +15 -15
- package/src/panels/agent-inspector-shared.ts +5 -5
- package/src/panels/base-panel.ts +3 -3
- package/src/panels/builtin/agent.ts +3 -3
- package/src/panels/builtin/development.ts +4 -4
- package/src/panels/builtin/knowledge.ts +1 -1
- package/src/panels/builtin/operations.ts +12 -12
- package/src/panels/builtin/session.ts +8 -8
- package/src/panels/builtin/shared.ts +6 -6
- package/src/panels/builtin-modals.ts +8 -8
- package/src/panels/confirm-state.ts +5 -5
- package/src/panels/cost-tracker-panel.ts +22 -22
- package/src/panels/diff-panel.ts +20 -20
- package/src/panels/diff-review-model.ts +5 -5
- package/src/panels/diff-review-panel.ts +5 -5
- package/src/panels/eval-registry.ts +2 -2
- package/src/panels/expandable-list-panel.ts +5 -5
- package/src/panels/fleet-acts.ts +20 -20
- package/src/panels/fleet-deep-link.ts +5 -5
- package/src/panels/fleet-gateway.ts +12 -12
- package/src/panels/fleet-observed-render.ts +11 -11
- package/src/panels/fleet-panel-format.ts +14 -14
- package/src/panels/fleet-panel-worktree-detail.ts +8 -8
- package/src/panels/fleet-panel.ts +34 -34
- package/src/panels/fleet-read-model.ts +49 -49
- package/src/panels/fleet-spawn.ts +15 -15
- package/src/panels/fleet-steer.ts +7 -7
- package/src/panels/fleet-stop.ts +5 -5
- package/src/panels/fleet-tabs.ts +14 -14
- package/src/panels/fleet-transcript.ts +26 -26
- package/src/panels/git-panel.ts +8 -8
- package/src/panels/hosted-session-feed.ts +13 -13
- package/src/panels/hosted-session-panel.ts +7 -7
- package/src/panels/index.ts +1 -1
- package/src/panels/local-auth-panel.ts +15 -15
- package/src/panels/memory-consolidation-gateway.ts +8 -8
- package/src/panels/modals/devices-modal.ts +8 -8
- package/src/panels/modals/hooks-modal.ts +1 -1
- package/src/panels/modals/keybindings-modal.ts +5 -5
- package/src/panels/modals/knowledge-modal.ts +2 -2
- package/src/panels/modals/local-auth-modal.ts +4 -4
- package/src/panels/modals/marketplace-modal.ts +3 -3
- package/src/panels/modals/memory-modal.ts +19 -19
- package/src/panels/modals/modal-surface-helpers.ts +1 -1
- package/src/panels/modals/modal-theme.ts +3 -3
- package/src/panels/modals/pairing-modal.ts +19 -19
- package/src/panels/modals/planning-modal.ts +4 -4
- package/src/panels/modals/plugins-modal.ts +1 -1
- package/src/panels/modals/policy-modal.ts +4 -4
- package/src/panels/modals/provider-health-modal.ts +1 -1
- package/src/panels/modals/remote-modal.ts +1 -1
- package/src/panels/modals/sandbox-modal.ts +2 -2
- package/src/panels/modals/security-modal.ts +4 -4
- package/src/panels/modals/services-modal.ts +1 -1
- package/src/panels/modals/work-plan-modal.ts +4 -4
- package/src/panels/notifications-feed.ts +6 -6
- package/src/panels/notifications-panel.ts +6 -6
- package/src/panels/panel-confirm-overlay.ts +4 -4
- package/src/panels/panel-manager.ts +13 -13
- package/src/panels/plugins-panel.ts +6 -6
- package/src/panels/polish-core.ts +2 -2
- package/src/panels/polish-tables.ts +2 -2
- package/src/panels/polish.ts +1 -1
- package/src/panels/project-planning-answer-actions.ts +3 -3
- package/src/panels/scrollable-list-panel.ts +15 -15
- package/src/panels/search-focus.ts +1 -1
- package/src/panels/session-maintenance.ts +1 -1
- package/src/panels/skills-panel.ts +3 -3
- package/src/panels/token-budget-panel.ts +11 -11
- package/src/panels/types.ts +14 -14
- package/src/panels/workstream-graph-render.ts +5 -5
- package/src/panels/wrfc-panel-format.ts +1 -1
- package/src/permissions/broker-approval-card.ts +13 -13
- package/src/permissions/hunk-selection.ts +13 -13
- package/src/permissions/prompt.ts +22 -22
- package/src/permissions/sandbox-exec-gate.ts +5 -5
- package/src/providers/provider-classification.ts +1 -1
- package/src/providers/reasoning-effort-surface.ts +12 -12
- package/src/renderer/ansi-sanitize.ts +5 -6
- package/src/renderer/autocomplete-overlay.ts +5 -5
- package/src/renderer/block-actions-overlay.ts +1 -1
- package/src/renderer/bookmark-modal.ts +1 -1
- package/src/renderer/code-block.ts +2 -2
- package/src/renderer/compaction-history-modal.ts +4 -4
- package/src/renderer/compaction-preview.ts +5 -5
- package/src/renderer/compaction-quality.ts +5 -5
- package/src/renderer/composer-fragments.ts +6 -6
- package/src/renderer/compositor.ts +9 -9
- package/src/renderer/config-modal.ts +3 -3
- package/src/renderer/context-inspector.ts +1 -1
- package/src/renderer/context-status-hint.ts +10 -10
- package/src/renderer/conversation-layout.ts +2 -2
- package/src/renderer/conversation-overlays.ts +2 -2
- package/src/renderer/conversation-surface.ts +6 -6
- package/src/renderer/diff.ts +4 -4
- package/src/renderer/fleet-tab-strip.ts +2 -2
- package/src/renderer/footer-tips.ts +4 -4
- package/src/renderer/fullscreen-primitives.ts +1 -1
- package/src/renderer/git-status.ts +5 -5
- package/src/renderer/header-line.ts +5 -5
- package/src/renderer/help-overlay.ts +5 -5
- package/src/renderer/hint-grammar.ts +2 -2
- package/src/renderer/layout.ts +1 -1
- package/src/renderer/markdown-inline.ts +3 -3
- package/src/renderer/markdown-table.ts +7 -7
- package/src/renderer/modal-factory.ts +3 -3
- package/src/renderer/model-picker-overlay.ts +2 -2
- package/src/renderer/model-workspace.ts +7 -7
- package/src/renderer/onboarding/onboarding-wizard.ts +1 -1
- package/src/renderer/overlay-box.ts +1 -1
- package/src/renderer/panel-composite.ts +5 -5
- package/src/renderer/panel-workspace-bar.ts +1 -1
- package/src/renderer/process-indicator.ts +8 -8
- package/src/renderer/profile-picker-modal.ts +3 -3
- package/src/renderer/prompt-content-width.ts +1 -1
- package/src/renderer/search-overlay.ts +3 -3
- package/src/renderer/selection-modal-overlay.ts +6 -6
- package/src/renderer/semantic-diff.ts +6 -7
- package/src/renderer/session-picker-modal.ts +24 -24
- package/src/renderer/settings-modal-connections.ts +3 -3
- package/src/renderer/settings-modal-helpers.ts +16 -16
- package/src/renderer/settings-modal.ts +10 -10
- package/src/renderer/shell-surface.ts +8 -8
- package/src/renderer/status-glyphs.ts +6 -6
- package/src/renderer/syntax-highlighter.ts +2 -3
- package/src/renderer/system-message.ts +3 -3
- package/src/renderer/tab-strip.ts +2 -2
- package/src/renderer/term-caps.ts +12 -12
- package/src/renderer/terminal-bg-probe.ts +10 -10
- package/src/renderer/terminal-escapes.ts +1 -1
- package/src/renderer/theme-mode-config.ts +3 -3
- package/src/renderer/theme.ts +34 -34
- package/src/renderer/thinking.ts +1 -1
- package/src/renderer/tool-call.ts +5 -5
- package/src/renderer/tool-result-expanded-lines.ts +3 -3
- package/src/renderer/tool-result-summary.ts +6 -6
- package/src/renderer/turn-injection.ts +9 -9
- package/src/renderer/ui-factory.ts +33 -33
- package/src/renderer/ui-primitives.ts +4 -4
- package/src/runtime/bootstrap-command-parts.ts +3 -3
- package/src/runtime/bootstrap-core.ts +21 -21
- package/src/runtime/bootstrap-hook-bridge.ts +8 -8
- package/src/runtime/bootstrap-shell.ts +9 -9
- package/src/runtime/bootstrap.ts +16 -16
- package/src/runtime/client/approval-updates.ts +3 -3
- package/src/runtime/client/build-floors.ts +7 -7
- package/src/runtime/client/daemon-attach-handshake.ts +5 -5
- package/src/runtime/client/fleet-union.ts +7 -7
- package/src/runtime/client/host-service-status.ts +2 -2
- package/src/runtime/client/hosted-exit.ts +4 -4
- package/src/runtime/client/hosted-roster.ts +4 -4
- package/src/runtime/client/hosted-session-stream.ts +5 -5
- package/src/runtime/client/hosted-sessions.ts +8 -8
- package/src/runtime/client/operator-endpoint.ts +14 -14
- package/src/runtime/client/spine-adoption.ts +8 -8
- package/src/runtime/context-accounting-source.ts +4 -4
- package/src/runtime/context.ts +2 -2
- package/src/runtime/conversation-rewind-port.ts +6 -6
- package/src/runtime/credential-composition.ts +2 -2
- package/src/runtime/daemon-attach-notices.ts +6 -6
- package/src/runtime/diagnostics/panels/index.ts +1 -1
- package/src/runtime/diagnostics/panels/ops.ts +2 -2
- package/src/runtime/disposal-wiring.ts +6 -6
- package/src/runtime/index.ts +11 -11
- package/src/runtime/install-self-check-startup.ts +4 -4
- package/src/runtime/install-self-check.ts +6 -6
- package/src/runtime/interaction-seams.ts +4 -4
- package/src/runtime/knowledge-services.ts +2 -2
- package/src/runtime/legacy-daemon-migration.ts +37 -37
- package/src/runtime/legacy-daemon-reconcile.ts +30 -30
- package/src/runtime/memory-governance-services.ts +3 -3
- package/src/runtime/memory-spine-transport.ts +3 -3
- package/src/runtime/notification-dispatch.ts +4 -4
- package/src/runtime/onboarding/apply.ts +1 -1
- package/src/runtime/onboarding/derivation.ts +1 -1
- package/src/runtime/onboarding/fast-path.ts +7 -7
- package/src/runtime/onboarding/progress.ts +2 -2
- package/src/runtime/onboarding/provider-key-capture.ts +4 -4
- package/src/runtime/onboarding/snapshot.ts +2 -2
- package/src/runtime/onboarding/state.ts +4 -4
- package/src/runtime/onboarding/types.ts +4 -4
- package/src/runtime/orchestrator-core-services.ts +5 -5
- package/src/runtime/path-shadow-startup.ts +3 -3
- package/src/runtime/perf/panel-contracts.ts +1 -1
- package/src/runtime/power-keepawake-remote.ts +6 -6
- package/src/runtime/process-lifecycle.ts +14 -14
- package/src/runtime/provider-fallback.ts +3 -3
- package/src/runtime/recovery-autosave.ts +3 -3
- package/src/runtime/recovery-decisions.ts +19 -19
- package/src/runtime/recovery-offer-wiring.ts +4 -4
- package/src/runtime/recovery-prompt.ts +20 -20
- package/src/runtime/relay-reachability-bridge.ts +3 -3
- package/src/runtime/release-artifacts.ts +1 -1
- package/src/runtime/resume-notice.ts +20 -20
- package/src/runtime/runtime-services-types.ts +20 -20
- package/src/runtime/services.ts +20 -20
- package/src/runtime/session-continuity-hints.ts +1 -1
- package/src/runtime/session-inbound-inputs.ts +12 -12
- package/src/runtime/session-resume-liveness-confirm.ts +4 -4
- package/src/runtime/session-spine-transport.ts +3 -3
- package/src/runtime/store/domains/panels.ts +2 -2
- package/src/runtime/store/domains/ui-perf.ts +2 -2
- package/src/runtime/store/index.ts +1 -1
- package/src/runtime/store/selectors/index.ts +1 -1
- package/src/runtime/store/state.ts +2 -2
- package/src/runtime/ui-services.ts +3 -3
- package/src/runtime/workspace-checkpointing.ts +3 -3
- package/src/runtime/wrfc-persistence.ts +15 -15
- package/src/scripts/process-messages.ts +1 -1
- package/src/shell/blocking-input.ts +9 -9
- package/src/shell/recovery-input-helpers.ts +2 -2
- package/src/shell/retry-affordance.ts +9 -9
- package/src/shell/ui-openers.ts +14 -14
- package/src/shell/voice-capture-shell.ts +3 -3
- package/src/tools/wrfc-agent-guard.ts +4 -4
- package/src/utils/browser.ts +2 -2
- package/src/utils/format-duration.ts +3 -3
- package/src/utils/format-number.ts +2 -2
- package/src/utils/splash-lines.ts +4 -4
- package/src/utils/terminal-width.ts +6 -6
- package/src/verification/verification-ledger.ts +25 -25
- package/src/version.ts +3 -3
|
@@ -6,14 +6,14 @@
|
|
|
6
6
|
*
|
|
7
7
|
* NAMING, load-bearing: this module's identifiers say "legacy" because the
|
|
8
8
|
* engine migrates AWAY from the `goodvibes-daemon.service` unit name toward
|
|
9
|
-
* the runtime-managed unit
|
|
9
|
+
* the runtime-managed unit, but that same name is what the suite installer
|
|
10
10
|
* (goodvibes-daemon scripts/install.sh)
|
|
11
11
|
* actively creates for curl-installed hosts TODAY. It is a parallel,
|
|
12
12
|
* first-class install path, not an obsolete one. User-facing copy therefore
|
|
13
13
|
* describes it as "the install-script unit" and never labels it legacy or
|
|
14
14
|
* implies it should be removed unless the user is explicitly migrating.
|
|
15
15
|
*
|
|
16
|
-
* This lives under `src/runtime
|
|
16
|
+
* This lives under `src/runtime/`, not `src/daemon/`, specifically so the
|
|
17
17
|
* `input` layer can consume it directly: the architecture gate's
|
|
18
18
|
* `input-no-entrypoints` rule forbids `src/input/**` from importing
|
|
19
19
|
* `src/daemon/**` (input must stay a pure event-handling layer, never
|
|
@@ -34,11 +34,11 @@
|
|
|
34
34
|
* - ADOPT-OR-WARN, NEVER KILL. If the legacy unit file is simply absent but
|
|
35
35
|
* something is already listening on the configured host:port (this dev
|
|
36
36
|
* host's real case: a manually `nohup`'d daemon with no unit at all),
|
|
37
|
-
* that is an unidentified process, not a managed unit
|
|
37
|
+
* that is an unidentified process, not a managed unit, nothing to stop
|
|
38
38
|
* or disable, and this module never attempts to kill it.
|
|
39
39
|
* - Every action (legacy stop/disable, unit-file removal, daemon-reload)
|
|
40
40
|
* goes through the injectable `actionRunner`/`legacyUnitFileRemove` seams
|
|
41
|
-
* tests use
|
|
41
|
+
* tests use, no code path here bypasses them, so the migration is
|
|
42
42
|
* exercised deterministically via fakes and never touches a real running
|
|
43
43
|
* service in tests.
|
|
44
44
|
*/
|
|
@@ -52,7 +52,7 @@ import { PlatformServiceManager, type ManagedServiceStatus } from '@pellux/goodv
|
|
|
52
52
|
import { summarizeError } from '@pellux/goodvibes-sdk/platform/utils';
|
|
53
53
|
import { runDaemonConfigMigration } from '../config/run-daemon-config-migration.ts';
|
|
54
54
|
|
|
55
|
-
/** Structurally derived from `PlatformServiceManager`'s own constructor
|
|
55
|
+
/** Structurally derived from `PlatformServiceManager`'s own constructor, the
|
|
56
56
|
* SDK's public `platform/daemon` entry point only re-exports the class and
|
|
57
57
|
* `ManagedServiceStatus`, not the options/definition/action-runner interfaces
|
|
58
58
|
* by name, so we pull their shapes off the class itself rather than reaching
|
|
@@ -62,7 +62,7 @@ type ManagedServiceDefinition = NonNullable<ManagedServiceManagerOptions['defini
|
|
|
62
62
|
export type ManagedServiceActionRunner = NonNullable<ManagedServiceManagerOptions['actionRunner']>;
|
|
63
63
|
type ManagedServiceActionResult = ReturnType<ManagedServiceActionRunner>;
|
|
64
64
|
|
|
65
|
-
// The one unit name/description this tool manages
|
|
65
|
+
// The one unit name/description this tool manages, shared by the daemon CLI
|
|
66
66
|
// (`goodvibes-daemon install-service|uninstall-service|service-status|migrate-service`)
|
|
67
67
|
// and the TUI onboarding UX, so both build the EXACT same service definition.
|
|
68
68
|
// `service.serviceName`/nothing-set config default is 'goodvibes'
|
|
@@ -74,7 +74,7 @@ export const MANAGED_SERVICE_DESCRIPTION = 'GoodVibes daemon (shared session bro
|
|
|
74
74
|
|
|
75
75
|
/**
|
|
76
76
|
* Follow-up: resolve the unit name the SDK's `PlatformServiceManager`
|
|
77
|
-
* would actually manage, from config alone
|
|
77
|
+
* would actually manage, from config alone, for callers that need the
|
|
78
78
|
* honest display name BEFORE any manager/status exists (the onboarding
|
|
79
79
|
* wizard's detection banner resolves this at snapshot-collection time and
|
|
80
80
|
* carries it on `OnboardingLegacyDaemonSnapshot.trackedServiceName`).
|
|
@@ -97,7 +97,7 @@ export interface BuildManagedDaemonServiceManagerParams {
|
|
|
97
97
|
readonly homeDir: string;
|
|
98
98
|
readonly host: string;
|
|
99
99
|
readonly port: number;
|
|
100
|
-
/** Defaults to `homeDir
|
|
100
|
+
/** Defaults to `homeDir`, overridable so tests can scope both to one tempdir. */
|
|
101
101
|
readonly workingDirectory?: string | undefined;
|
|
102
102
|
/** Injected in tests; a real `ConfigManager` rooted at `homeDir` otherwise. */
|
|
103
103
|
readonly configManager?: ConfigManager | undefined;
|
|
@@ -106,12 +106,12 @@ export interface BuildManagedDaemonServiceManagerParams {
|
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
/**
|
|
109
|
-
* Build the ONE `PlatformServiceManager` this tool manages
|
|
109
|
+
* Build the ONE `PlatformServiceManager` this tool manages, the single
|
|
110
110
|
* source of truth for the unit's definition (`ExecStart` command/args,
|
|
111
111
|
* name, description). Both `src/daemon/service-commands.ts` (the CLI) and
|
|
112
112
|
* `src/input/handler-onboarding-daemon-adopt.ts` (the onboarding guided UX)
|
|
113
113
|
* call this so a migration triggered from either surface installs the
|
|
114
|
-
* identical unit
|
|
114
|
+
* identical unit, no risk of the two consumers drifting apart.
|
|
115
115
|
*/
|
|
116
116
|
export function buildManagedDaemonServiceManager(params: BuildManagedDaemonServiceManagerParams): PlatformServiceManager {
|
|
117
117
|
const workingDirectory = params.workingDirectory ?? params.homeDir;
|
|
@@ -127,7 +127,7 @@ export function buildManagedDaemonServiceManager(params: BuildManagedDaemonServi
|
|
|
127
127
|
// already configured for hostMode=network / a non-default port) keeps its
|
|
128
128
|
// endpoint without a unit rewrite. Baking endpoint values here is what
|
|
129
129
|
// silently re-pinned custom-configured hosts back to the values current at
|
|
130
|
-
// install time. The suite installer writes the same shape
|
|
130
|
+
// install time. The suite installer writes the same shape, the two paths
|
|
131
131
|
// must produce the identical running daemon (see the installer parity test).
|
|
132
132
|
// `params.host`/`params.port` remain inputs because the migration engine
|
|
133
133
|
// still needs them for its read-only port-liveness probe.
|
|
@@ -136,15 +136,15 @@ export function buildManagedDaemonServiceManager(params: BuildManagedDaemonServi
|
|
|
136
136
|
description: MANAGED_SERVICE_DESCRIPTION,
|
|
137
137
|
workingDirectory,
|
|
138
138
|
command: params.binaryPath,
|
|
139
|
-
// `--daemon-home` names the daemon's own STATE directory
|
|
140
|
-
// operator-tokens.json, auth-users.json and daemon-settings.json
|
|
139
|
+
// `--daemon-home` names the daemon's own STATE directory, the one holding
|
|
140
|
+
// operator-tokens.json, auth-users.json and daemon-settings.json, which is
|
|
141
141
|
// `<home>/.goodvibes/daemon`. This baked the USER HOME, so a serviced
|
|
142
142
|
// daemon filed its identity a level above where every reader in this
|
|
143
143
|
// repository looks: the SDK's platform/config goodvibes-home resolves the flag AS the state
|
|
144
144
|
// directory, cli/service-posture.ts already writes the state directory into
|
|
145
145
|
// GOODVIBES_DAEMON_HOME for the unit it installs, and runtime/bootstrap.ts
|
|
146
146
|
// reads the companion token from the state directory. On a normal machine
|
|
147
|
-
// the mismatch is invisible from the outside
|
|
147
|
+
// the mismatch is invisible from the outside, the daemon simply mints a
|
|
148
148
|
// second operator-tokens.json in the home directory and the client keeps
|
|
149
149
|
// reading the empty one under .goodvibes/daemon.
|
|
150
150
|
args: ['--daemon-home', join(params.homeDir, '.goodvibes', 'daemon')],
|
|
@@ -234,7 +234,7 @@ export interface DetectLegacyUnitInput {
|
|
|
234
234
|
/**
|
|
235
235
|
* Read-only detection: does a legacy `goodvibes-daemon.service` unit file
|
|
236
236
|
* exist, and if so, is it currently active? Never stops, disables, or
|
|
237
|
-
* modifies anything
|
|
237
|
+
* modifies anything, a file-existence check plus a read-only
|
|
238
238
|
* `systemctl --user is-active` query through the injected actionRunner.
|
|
239
239
|
*/
|
|
240
240
|
export function detectLegacyUnit(input: DetectLegacyUnitInput): LegacyUnitInfo {
|
|
@@ -251,8 +251,8 @@ export function detectLegacyUnit(input: DetectLegacyUnitInput): LegacyUnitInfo {
|
|
|
251
251
|
/**
|
|
252
252
|
* The unit name `PlatformServiceManager` is ACTUALLY about to mutate can
|
|
253
253
|
* differ from `MANAGED_SERVICE_NAME` / `definitionOverride.name`. The SDK's
|
|
254
|
-
* internal `resolveServiceName()
|
|
255
|
-
* `status()` alike to compute the unit file PATH
|
|
254
|
+
* internal `resolveServiceName()`, used by `install()`, `uninstall()`, and
|
|
255
|
+
* `status()` alike to compute the unit file PATH, resolves from the
|
|
256
256
|
* `service.serviceName` CONFIG key first, falling back to the
|
|
257
257
|
* `defaultServiceName` this module passes only when that key is unset. It
|
|
258
258
|
* never consults `definitionOverride.name` for the path. So if a host's
|
|
@@ -281,11 +281,11 @@ export function resolveManagedUnitName(status: ManagedServiceStatus): string {
|
|
|
281
281
|
return basename(status.path).replace(/\.(service|plist)$/, '');
|
|
282
282
|
}
|
|
283
283
|
|
|
284
|
-
/** Honest one-line disclosure of the install-script unit's presence/state plus a manual migration hint
|
|
284
|
+
/** Honest one-line disclosure of the install-script unit's presence/state plus a manual migration hint, never auto-acted-on. */
|
|
285
285
|
export function legacyUnitNote(legacy: LegacyUnitInfo, trackedServiceName: string): string {
|
|
286
286
|
const stateWord = legacy.active ? 'installed and RUNNING' : 'installed (not currently active)';
|
|
287
287
|
return (
|
|
288
|
-
`note: a separate service named ${LEGACY_SERVICE_UNIT_NAME}.service is ${stateWord} at ${legacy.path}
|
|
288
|
+
`note: a separate service named ${LEGACY_SERVICE_UNIT_NAME}.service is ${stateWord} at ${legacy.path}; ` +
|
|
289
289
|
`that unit name is managed by the goodvibes install script (older installs used it too), while this tool manages ` +
|
|
290
290
|
`${trackedServiceName}.service and will not touch the other unit automatically. Keep whichever one you use; running ` +
|
|
291
291
|
`both would start two daemons competing for the same port. To retire the install-script unit in favor of this ` +
|
|
@@ -297,7 +297,7 @@ export function legacyUnitNote(legacy: LegacyUnitInfo, trackedServiceName: strin
|
|
|
297
297
|
* Hard ceiling on every systemctl invocation made through a DEFAULT action
|
|
298
298
|
* runner in this module. The reconcile below runs on the daemon's own startup
|
|
299
299
|
* path, and `spawnSync` without a timeout blocks the single JS event loop for
|
|
300
|
-
* as long as the child runs
|
|
300
|
+
* as long as the child runs, a wedged user D-Bus (a real incident class on
|
|
301
301
|
* this host) would freeze an already-listening daemon indefinitely. A timed-out
|
|
302
302
|
* call reports `status: null`, which every status check in this module treats
|
|
303
303
|
* as failure, so a wedge degrades to an honest refusal instead of a hang.
|
|
@@ -321,7 +321,7 @@ export function parseMainPid(result: { status?: number | null; stdout?: string |
|
|
|
321
321
|
* Read-only, best-effort TCP connect probe used ONLY by the legacy-absent
|
|
322
322
|
* branch to tell "nothing is listening on this port" apart from "an
|
|
323
323
|
* unmanaged process (e.g. a manual `nohup`) already owns it." Never used to
|
|
324
|
-
* identify or act on that process
|
|
324
|
+
* identify or act on that process, a positive result only produces a
|
|
325
325
|
* warning, never a kill. Tests always inject a fake `portProbe`; this default
|
|
326
326
|
* is never exercised against a real host in this repo's test suite.
|
|
327
327
|
*/
|
|
@@ -344,11 +344,11 @@ export function defaultPortProbe(host: string, port: number, timeoutMs = 750): P
|
|
|
344
344
|
export interface RunLegacyDaemonMigrationParams {
|
|
345
345
|
readonly host: string;
|
|
346
346
|
readonly port: number;
|
|
347
|
-
/** The unit name this tool manages (e.g. 'goodvibes')
|
|
347
|
+
/** The unit name this tool manages (e.g. 'goodvibes'), distinct from LEGACY_SERVICE_UNIT_NAME. */
|
|
348
348
|
readonly trackedServiceName: string;
|
|
349
349
|
/**
|
|
350
350
|
* Explicit consent to actually execute the migration. Without it, the
|
|
351
|
-
* result is a printed plan only
|
|
351
|
+
* result is a printed plan only, never auto-migrate.
|
|
352
352
|
*/
|
|
353
353
|
readonly confirmMigration?: boolean | undefined;
|
|
354
354
|
/** Injectable port-liveness check for the legacy-absent branch. Defaults to `defaultPortProbe`. */
|
|
@@ -364,7 +364,7 @@ export interface RunLegacyDaemonMigrationParams {
|
|
|
364
364
|
* legacy unit. Called immediately before the two mutation calls
|
|
365
365
|
* (`manager.install()`, and `manager.uninstall()` on the failed-health
|
|
366
366
|
* rollback path) that would otherwise write to or remove that path. This is
|
|
367
|
-
* an internal invariant check, not a normal user-facing error path
|
|
367
|
+
* an internal invariant check, not a normal user-facing error path, the
|
|
368
368
|
* pre-flight collision check in `runLegacyDaemonMigration` already returns
|
|
369
369
|
* before either call site is reached whenever this would trip, so tripping
|
|
370
370
|
* here means that earlier check regressed, not that the user did anything
|
|
@@ -374,7 +374,7 @@ function assertUnitIsNotLegacy(status: ManagedServiceStatus, legacy: LegacyUnitI
|
|
|
374
374
|
if (status.path === legacy.path || resolveManagedUnitName(status) === LEGACY_SERVICE_UNIT_NAME) {
|
|
375
375
|
throw new Error(
|
|
376
376
|
`refusing to ${action}: the resolved managed unit (${resolveManagedUnitName(status)} at ${status.path}) is the ` +
|
|
377
|
-
`install-script ${LEGACY_SERVICE_UNIT_NAME}.service unit
|
|
377
|
+
`install-script ${LEGACY_SERVICE_UNIT_NAME}.service unit: this should already have been caught by the pre-flight ` +
|
|
378
378
|
'collision check in runLegacyDaemonMigration',
|
|
379
379
|
);
|
|
380
380
|
}
|
|
@@ -399,7 +399,7 @@ export async function runLegacyDaemonMigration(
|
|
|
399
399
|
): Promise<LegacyDaemonMigrationResult> {
|
|
400
400
|
const { trackedServiceName } = params;
|
|
401
401
|
// Computed once, up front, and reused for every branch below (this is the
|
|
402
|
-
// exact same single call each branch made individually before
|
|
402
|
+
// exact same single call each branch made individually before, see the
|
|
403
403
|
// fix note on `resolveManagedUnitName` for why the name/path it reports
|
|
404
404
|
// can differ from `trackedServiceName`).
|
|
405
405
|
const currentStatus = manager.status();
|
|
@@ -416,9 +416,9 @@ export async function runLegacyDaemonMigration(
|
|
|
416
416
|
`migrate-service: no install-script ${LEGACY_SERVICE_UNIT_NAME}.service unit was found, but something is already ` +
|
|
417
417
|
`listening on ${params.host}:${params.port}.`,
|
|
418
418
|
"That looks like a process this tool doesn't manage (for example, a manually-started `nohup` daemon) rather " +
|
|
419
|
-
'than a systemd unit
|
|
419
|
+
'than a systemd unit: there is nothing here to stop or disable, and this tool will not attempt to kill an ' +
|
|
420
420
|
'unrecognized process.',
|
|
421
|
-
'Stop that process yourself (or point this TUI at it instead
|
|
421
|
+
'Stop that process yourself (or point this TUI at it instead; see the onboarding "connect to an existing ' +
|
|
422
422
|
'daemon" option), then re-run migrate-service or install-service once the port is free.',
|
|
423
423
|
],
|
|
424
424
|
status: currentStatus,
|
|
@@ -429,7 +429,7 @@ export async function runLegacyDaemonMigration(
|
|
|
429
429
|
exitCode: 0,
|
|
430
430
|
lines: [
|
|
431
431
|
`migrate-service: no install-script ${LEGACY_SERVICE_UNIT_NAME}.service unit was found and ${params.host}:${params.port} ` +
|
|
432
|
-
'is free
|
|
432
|
+
'is free: there is nothing to migrate.',
|
|
433
433
|
`Run install-service to set up the managed ${resolvedUnitName}.service directly.`,
|
|
434
434
|
],
|
|
435
435
|
status: currentStatus,
|
|
@@ -443,7 +443,7 @@ export async function runLegacyDaemonMigration(
|
|
|
443
443
|
lines: [
|
|
444
444
|
`migrate-service: this host's detected service platform is '${currentStatus.platform}', not systemd, but a ` +
|
|
445
445
|
`unit file with the install-script name exists at ${legacy.path}.`,
|
|
446
|
-
'That unit is systemd-specific and this tool only knows how to migrate a systemd unit today
|
|
446
|
+
'That unit is systemd-specific and this tool only knows how to migrate a systemd unit today; ' +
|
|
447
447
|
'nothing was changed.',
|
|
448
448
|
],
|
|
449
449
|
status: currentStatus,
|
|
@@ -453,7 +453,7 @@ export async function runLegacyDaemonMigration(
|
|
|
453
453
|
// Before any mutation, confirm the unit PlatformServiceManager is
|
|
454
454
|
// actually about to install/uninstall isn't the legacy unit itself. This
|
|
455
455
|
// happens when the host's `service.serviceName` config key is set to the
|
|
456
|
-
// legacy unit's own name
|
|
456
|
+
// legacy unit's own name, see `resolveManagedUnitName`'s doc comment for
|
|
457
457
|
// why the SDK resolves mutation paths from that config key rather than
|
|
458
458
|
// from the definition this engine passes. Without this check, `install()`
|
|
459
459
|
// below would overwrite the legacy unit file, a failed-health rollback
|
|
@@ -483,12 +483,12 @@ export async function runLegacyDaemonMigration(
|
|
|
483
483
|
exitCode: 0,
|
|
484
484
|
lines: [
|
|
485
485
|
legacyUnitNote(legacy, resolvedUnitName),
|
|
486
|
-
'migrate-service (dry run
|
|
486
|
+
'migrate-service (dry run: re-run with confirmation to execute): this would',
|
|
487
487
|
` 1. install and start the new ${resolvedUnitName}.service unit`,
|
|
488
488
|
' 2. verify it comes up healthy (a fresh, honest systemd is-active check)',
|
|
489
489
|
` 3. only if that succeeds, stop, disable, and remove the install-script ${LEGACY_SERVICE_UNIT_NAME}.service unit ` +
|
|
490
490
|
'and run `systemctl --user daemon-reload`',
|
|
491
|
-
'Nothing has been changed. Nothing is migrated automatically
|
|
491
|
+
'Nothing has been changed. Nothing is migrated automatically: re-run with explicit confirmation ' +
|
|
492
492
|
"(the CLI's -y/--yes flag) to execute this plan.",
|
|
493
493
|
],
|
|
494
494
|
status: currentStatus,
|
|
@@ -498,7 +498,7 @@ export async function runLegacyDaemonMigration(
|
|
|
498
498
|
// Consented: new-up-then-old-down. The legacy unit is not touched until the
|
|
499
499
|
// new unit is verified healthy.
|
|
500
500
|
// Belt-and-braces: the collision check above already returns before
|
|
501
|
-
// reaching here whenever the resolved unit is the legacy one
|
|
501
|
+
// reaching here whenever the resolved unit is the legacy one, this
|
|
502
502
|
// re-asserts the same invariant right at the mutation site so a future
|
|
503
503
|
// change to the check above can never silently reopen the hole.
|
|
504
504
|
assertUnitIsNotLegacy(currentStatus, legacy, 'install the new unit');
|
|
@@ -521,7 +521,7 @@ export async function runLegacyDaemonMigration(
|
|
|
521
521
|
assertUnitIsNotLegacy(installed, legacy, 'roll back (uninstall) the new unit');
|
|
522
522
|
const rollback = manager.uninstall();
|
|
523
523
|
const rollbackNote = rollback.actionError
|
|
524
|
-
? `rolling back the new unit ALSO hit an error (${rollback.actionError})
|
|
524
|
+
? `rolling back the new unit ALSO hit an error (${rollback.actionError}): remove ${installed.path} by hand.`
|
|
525
525
|
: 'the newly-written unit has been rolled back (removed).';
|
|
526
526
|
return {
|
|
527
527
|
ok: false,
|
|
@@ -536,7 +536,7 @@ export async function runLegacyDaemonMigration(
|
|
|
536
536
|
};
|
|
537
537
|
}
|
|
538
538
|
|
|
539
|
-
// New unit verified healthy
|
|
539
|
+
// New unit verified healthy, now, and only now, retire the legacy unit.
|
|
540
540
|
const run: ManagedServiceActionRunner = params.actionRunner ?? defaultActionRunner(SYSTEMCTL_TIMEOUT_MS);
|
|
541
541
|
const stopResult = run('systemctl', ['--user', 'stop', `${LEGACY_SERVICE_UNIT_NAME}.service`]);
|
|
542
542
|
const disableResult = run('systemctl', ['--user', 'disable', `${LEGACY_SERVICE_UNIT_NAME}.service`]);
|
|
@@ -563,7 +563,7 @@ export async function runLegacyDaemonMigration(
|
|
|
563
563
|
);
|
|
564
564
|
}
|
|
565
565
|
if (removeError) {
|
|
566
|
-
lines.push(`note: could not remove the install-script unit file at ${legacy.path}: ${removeError}
|
|
566
|
+
lines.push(`note: could not remove the install-script unit file at ${legacy.path}: ${removeError}; remove it by hand.`);
|
|
567
567
|
} else {
|
|
568
568
|
lines.push(`the install-script ${LEGACY_SERVICE_UNIT_NAME}.service unit has been stopped, disabled, and removed.`);
|
|
569
569
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The unattended startup reconcile for the redundant install-script
|
|
3
|
-
* `goodvibes-daemon.service` unit
|
|
3
|
+
* `goodvibes-daemon.service` unit, split out of `legacy-daemon-migration.ts`
|
|
4
4
|
* (which owns the shared unit definition, detection, and the CONSENTED
|
|
5
5
|
* `migrate-service` engine) so each module stays within the architecture
|
|
6
6
|
* gate's file-size cap. Same layer (`src/runtime/`), same injectable-seam
|
|
@@ -24,8 +24,8 @@ type ManagedServiceActionResult = ReturnType<ManagedServiceActionRunner>;
|
|
|
24
24
|
/**
|
|
25
25
|
* The exact marker string the suite installer writes into every unit it
|
|
26
26
|
* creates (as a `# managed by goodvibes install.sh` comment). The reconcile
|
|
27
|
-
* check below keys on it to tell an installer-created legacy unit
|
|
28
|
-
* auto-retire
|
|
27
|
+
* check below keys on it to tell an installer-created legacy unit, safe to
|
|
28
|
+
* auto-retire, apart from a hand-written one that must only ever be reported.
|
|
29
29
|
* Kept in lockstep with `INSTALLER_MARKER` in the suite installer
|
|
30
30
|
* (goodvibes-daemon scripts/install.sh).
|
|
31
31
|
*/
|
|
@@ -36,7 +36,7 @@ export const INSTALLER_UNIT_MARKER = 'managed by goodvibes install.sh';
|
|
|
36
36
|
/**
|
|
37
37
|
* CUMULATIVE ceiling on the reconcile's whole boot-path pass. Per-call
|
|
38
38
|
* timeouts alone still allow ~5 sequential slow-but-completing calls to stack
|
|
39
|
-
* up (a degraded
|
|
39
|
+
* up (a degraded, not wedged, user bus), blocking the already-listening
|
|
40
40
|
* daemon's event loop for tens of seconds. One overall deadline covers the
|
|
41
41
|
* pass: once it is exceeded, every remaining call is skipped (reported as
|
|
42
42
|
* `status: null`, which the guards treat as unknown → refusal) and the result
|
|
@@ -49,7 +49,7 @@ export const RECONCILE_DEADLINE_MS = 8_000;
|
|
|
49
49
|
/**
|
|
50
50
|
* Wrap a runner with the reconcile's cumulative deadline: calls after the
|
|
51
51
|
* deadline are skipped outright; calls near it get only the remaining budget
|
|
52
|
-
* as their per-call timeout (default runner only
|
|
52
|
+
* as their per-call timeout (default runner only, injected runners are test
|
|
53
53
|
* fakes that answer instantly).
|
|
54
54
|
*/
|
|
55
55
|
function makeDeadlineBoundRunner(
|
|
@@ -63,7 +63,7 @@ function makeDeadlineBoundRunner(
|
|
|
63
63
|
const remaining = deadlineMs - (Date.now() - startedAt);
|
|
64
64
|
if (remaining <= 0) {
|
|
65
65
|
hit = true;
|
|
66
|
-
return { status: null, stdout: '', stderr: 'reconcile time budget exceeded
|
|
66
|
+
return { status: null, stdout: '', stderr: 'reconcile time budget exceeded: call skipped' } as ManagedServiceActionResult;
|
|
67
67
|
}
|
|
68
68
|
if (injected) return injected(command, args);
|
|
69
69
|
return defaultActionRunner(Math.min(perCallTimeoutMs, remaining))(command, args);
|
|
@@ -168,7 +168,7 @@ function defaultReadOwnCgroup(): string {
|
|
|
168
168
|
* This runs on daemon startup (no user invocation needed) and, guard-railed:
|
|
169
169
|
* - Only acts when the canonical unit is CONFIRMED serving: `is-active`
|
|
170
170
|
* reports active AND its MainPID resolves to a live process. `is-active`
|
|
171
|
-
* alone is not proof
|
|
171
|
+
* alone is not proof, a Type=simple unit reports active from fork onward,
|
|
172
172
|
* including the pre-bind window of a daemon that is about to crash-loop.
|
|
173
173
|
* - NEVER acts from inside the legacy unit itself: if this process IS the
|
|
174
174
|
* legacy unit's MainPID, or /proc/self/cgroup names the legacy unit,
|
|
@@ -176,20 +176,20 @@ function defaultReadOwnCgroup(): string {
|
|
|
176
176
|
* code (mid-boot, from inside a blocking spawnSync). Refuses instead.
|
|
177
177
|
* - NEVER stops a RUNNING legacy daemon: if the legacy unit's MainPID is a
|
|
178
178
|
* live process, it may be the daemon serving the endpoint clients are
|
|
179
|
-
* configured to reach (the wrong-port two-daemon state)
|
|
179
|
+
* configured to reach (the wrong-port two-daemon state), the unattended
|
|
180
180
|
* path only retires enabled-but-NOT-running legacy units; a running one
|
|
181
181
|
* gets a notice pointing at the consented migrate-service.
|
|
182
182
|
* - Requires the CONFIGURED endpoint (the one clients resolve from
|
|
183
|
-
* settings.json, no runtime overrides) to be answering before retiring
|
|
183
|
+
* settings.json, no runtime overrides) to be answering before retiring,
|
|
184
184
|
* a canonical daemon alive on some other port proves nothing about the
|
|
185
185
|
* endpoint clients use.
|
|
186
186
|
* - AUTO-RETIRES only an installer-MARKER-managed legacy unit, and only
|
|
187
187
|
* removes its unit file AFTER `disable --now` reports success. A NONZERO
|
|
188
188
|
* exit leaves everything in place and says so; a TIMED-OUT disable
|
|
189
|
-
* (status null) has an UNKNOWN outcome
|
|
189
|
+
* (status null) has an UNKNOWN outcome, the enablement state is
|
|
190
190
|
* re-inspected before anything is printed, and the receipt states what
|
|
191
191
|
* was actually confirmed, never a blanket claim.
|
|
192
|
-
* - A hand-written legacy unit (no marker) is never touched
|
|
192
|
+
* - A hand-written legacy unit (no marker) is never touched, a one-line
|
|
193
193
|
* actionable notice. An UNREADABLE unit file is reported as unreadable,
|
|
194
194
|
* never misdiagnosed as hand-written.
|
|
195
195
|
* - The whole pass shares ONE cumulative time budget (RECONCILE_DEADLINE_MS)
|
|
@@ -215,11 +215,11 @@ export async function reconcileRedundantLegacyUnit(
|
|
|
215
215
|
const legacyUnit = `${LEGACY_SERVICE_UNIT_NAME}.service`;
|
|
216
216
|
const deadlineNote = (): string[] =>
|
|
217
217
|
deadlineHit()
|
|
218
|
-
? ['note: the reconcile hit its overall time budget
|
|
218
|
+
? ['note: the reconcile hit its overall time budget; remaining checks were skipped; it will re-run at the next daemon start.']
|
|
219
219
|
: [];
|
|
220
220
|
|
|
221
221
|
// Guard 1: the canonical unit must report active. (A timed-out, skipped, or
|
|
222
|
-
// failed probe
|
|
222
|
+
// failed probe, e.g. a wedged user bus, lands here too and refuses.)
|
|
223
223
|
const probe = run(systemctl, ['--user', 'is-active', canonicalUnit]);
|
|
224
224
|
const canonicalActive = (probe.status ?? 1) === 0 && (probe.stdout ?? '').trim() === 'active';
|
|
225
225
|
if (!canonicalActive) {
|
|
@@ -227,7 +227,7 @@ export async function reconcileRedundantLegacyUnit(
|
|
|
227
227
|
action: 'noop',
|
|
228
228
|
reason: 'canonical-not-active',
|
|
229
229
|
lines: [
|
|
230
|
-
`legacy-unit reconcile: a ${legacyUnit} unit file exists at ${path} but ${canonicalUnit} is not confirmably active
|
|
230
|
+
`legacy-unit reconcile: a ${legacyUnit} unit file exists at ${path} but ${canonicalUnit} is not confirmably active; ` +
|
|
231
231
|
'left untouched (it may be the only daemon).',
|
|
232
232
|
...deadlineNote(),
|
|
233
233
|
],
|
|
@@ -244,7 +244,7 @@ export async function reconcileRedundantLegacyUnit(
|
|
|
244
244
|
action: 'noop',
|
|
245
245
|
reason: 'canonical-mainpid-not-alive',
|
|
246
246
|
lines: [
|
|
247
|
-
`legacy-unit reconcile: ${canonicalUnit} reports active but its MainPID could not be confirmed alive
|
|
247
|
+
`legacy-unit reconcile: ${canonicalUnit} reports active but its MainPID could not be confirmed alive; ` +
|
|
248
248
|
`left the ${legacyUnit} unit untouched.`,
|
|
249
249
|
...deadlineNote(),
|
|
250
250
|
],
|
|
@@ -257,7 +257,7 @@ export async function reconcileRedundantLegacyUnit(
|
|
|
257
257
|
//
|
|
258
258
|
// The legacy MainPID probe is TRI-STATE, exactly like guards 1-2: a reply
|
|
259
259
|
// whose status is non-zero or null (bus flap, timeout, skipped-by-deadline)
|
|
260
|
-
// does NOT mean "MainPID=0, unit affirmatively stopped"
|
|
260
|
+
// does NOT mean "MainPID=0, unit affirmatively stopped", reading it that
|
|
261
261
|
// way let one transient systemctl failure on exactly this call authorize
|
|
262
262
|
// `disable --now` against a LIVE legacy daemon (and guard 5 cannot catch
|
|
263
263
|
// it: in the wrong-port state the legacy daemon itself answers the
|
|
@@ -272,7 +272,7 @@ export async function reconcileRedundantLegacyUnit(
|
|
|
272
272
|
action: 'noop',
|
|
273
273
|
reason: 'self-supervised-by-legacy',
|
|
274
274
|
lines: [
|
|
275
|
-
`legacy-unit reconcile: this daemon appears to be running UNDER ${legacyUnit} itself
|
|
275
|
+
`legacy-unit reconcile: this daemon appears to be running UNDER ${legacyUnit} itself; refusing to disable ` +
|
|
276
276
|
`the unit supervising the current process. Migrate from the canonical side instead: goodvibes-daemon migrate-service`,
|
|
277
277
|
],
|
|
278
278
|
};
|
|
@@ -283,14 +283,14 @@ export async function reconcileRedundantLegacyUnit(
|
|
|
283
283
|
reason: 'legacy-state-unknown',
|
|
284
284
|
lines: [
|
|
285
285
|
`legacy-unit reconcile: could not determine whether ${legacyUnit} has a running daemon (the MainPID query ` +
|
|
286
|
-
'failed or timed out)
|
|
286
|
+
'failed or timed out): refusing to act on a guess; it will be re-checked at the next daemon start.',
|
|
287
287
|
...deadlineNote(),
|
|
288
288
|
],
|
|
289
289
|
};
|
|
290
290
|
}
|
|
291
291
|
|
|
292
292
|
// Guard 4: never stop a RUNNING legacy daemon from the unattended path. A
|
|
293
|
-
// live legacy MainPID means a second daemon is actually serving something
|
|
293
|
+
// live legacy MainPID means a second daemon is actually serving something,
|
|
294
294
|
// possibly the endpoint clients resolve from settings.json (the wrong-port
|
|
295
295
|
// two-daemon state). Retiring an enabled-but-idle unit needs no --now kill;
|
|
296
296
|
// stopping a serving one needs consent. (A KNOWN reply of MainPID=0 is the
|
|
@@ -300,7 +300,7 @@ export async function reconcileRedundantLegacyUnit(
|
|
|
300
300
|
action: 'noop',
|
|
301
301
|
reason: 'legacy-running',
|
|
302
302
|
lines: [
|
|
303
|
-
`legacy-unit reconcile: ${legacyUnit} has a live main process (pid ${legacyPid})
|
|
303
|
+
`legacy-unit reconcile: ${legacyUnit} has a live main process (pid ${legacyPid}); a second daemon is ` +
|
|
304
304
|
'actually running, and it may be the one serving the endpoint your clients are configured to reach. ' +
|
|
305
305
|
'Refusing to stop it unattended; migrate deliberately with: goodvibes-daemon migrate-service',
|
|
306
306
|
],
|
|
@@ -309,7 +309,7 @@ export async function reconcileRedundantLegacyUnit(
|
|
|
309
309
|
|
|
310
310
|
// Guard 5: the endpoint clients resolve from settings.json must be answered
|
|
311
311
|
// before anything is retired. The canonical daemon being alive proves only
|
|
312
|
-
// that A daemon runs
|
|
312
|
+
// that A daemon runs, not that the configured endpoint is served (its unit
|
|
313
313
|
// may pin different launch args).
|
|
314
314
|
if (input.configuredEndpoint) {
|
|
315
315
|
const endpointProbe = input.endpointProbe ?? defaultPortProbe;
|
|
@@ -320,7 +320,7 @@ export async function reconcileRedundantLegacyUnit(
|
|
|
320
320
|
reason: 'configured-endpoint-unserved',
|
|
321
321
|
lines: [
|
|
322
322
|
`legacy-unit reconcile: nothing is answering on the CONFIGURED endpoint ` +
|
|
323
|
-
`${input.configuredEndpoint.host}:${input.configuredEndpoint.port}
|
|
323
|
+
`${input.configuredEndpoint.host}:${input.configuredEndpoint.port}; the canonical daemon is alive but not ` +
|
|
324
324
|
`provably serving what clients resolve from settings. Left the ${legacyUnit} unit untouched; check the ` +
|
|
325
325
|
"canonical unit's launch arguments against the controlPlane settings.",
|
|
326
326
|
],
|
|
@@ -346,7 +346,7 @@ export async function reconcileRedundantLegacyUnit(
|
|
|
346
346
|
reason: 'marker-unreadable',
|
|
347
347
|
lines: [
|
|
348
348
|
`note: ${canonicalUnit} is active and a separate ${legacyUnit} exists at ${path}, but its unit file could not ` +
|
|
349
|
-
`be read (${readError})
|
|
349
|
+
`be read (${readError}): left untouched. Inspect it yourself; if it is redundant, retire it with: ` +
|
|
350
350
|
`systemctl --user disable --now ${legacyUnit} && rm ${path} && systemctl --user daemon-reload`,
|
|
351
351
|
],
|
|
352
352
|
};
|
|
@@ -366,14 +366,14 @@ export async function reconcileRedundantLegacyUnit(
|
|
|
366
366
|
}
|
|
367
367
|
|
|
368
368
|
// Installer-marker-managed and redundant: disable first, and only remove the
|
|
369
|
-
// unit file if the disable actually succeeded
|
|
369
|
+
// unit file if the disable actually succeeded, otherwise the enablement
|
|
370
370
|
// symlink dangles at a deleted file and this tool can never repair it (the
|
|
371
371
|
// next pass no-ops at the file-exists check).
|
|
372
372
|
const disableResult = run(systemctl, ['--user', 'disable', '--now', legacyUnit]);
|
|
373
373
|
const disableStatus = disableResult.status ?? 1;
|
|
374
374
|
if (disableStatus !== 0) {
|
|
375
375
|
if (disableResult.status === null) {
|
|
376
|
-
// TIMED OUT: the outcome is UNKNOWN, not failed
|
|
376
|
+
// TIMED OUT: the outcome is UNKNOWN, not failed, `disable --now`
|
|
377
377
|
// removes the enablement symlinks synchronously BEFORE waiting on the
|
|
378
378
|
// stop job, so the disable may well have taken effect even though the
|
|
379
379
|
// client was killed. Re-inspect instead of printing a blanket denial.
|
|
@@ -394,11 +394,11 @@ export async function reconcileRedundantLegacyUnit(
|
|
|
394
394
|
run(systemctl, ['--user', 'daemon-reload']);
|
|
395
395
|
const lines = [
|
|
396
396
|
`reconciled: the disable command timed out waiting on the stop job, but re-inspection confirms the ` +
|
|
397
|
-
`installer-managed ${legacyUnit} is no longer enabled${removeErrorAfterTimeout ? '' :
|
|
397
|
+
`installer-managed ${legacyUnit} is no longer enabled${removeErrorAfterTimeout ? '' : `; its unit file was removed (${path})`}. ` +
|
|
398
398
|
'Its stop may still be completing.',
|
|
399
399
|
];
|
|
400
400
|
if (removeErrorAfterTimeout) {
|
|
401
|
-
lines.push(`note: could not remove ${path}: ${removeErrorAfterTimeout}
|
|
401
|
+
lines.push(`note: could not remove ${path}: ${removeErrorAfterTimeout}; remove it by hand.`);
|
|
402
402
|
}
|
|
403
403
|
lines.push(...deadlineNote());
|
|
404
404
|
return { action: 'removed', reason: 'retired', lines };
|
|
@@ -407,7 +407,7 @@ export async function reconcileRedundantLegacyUnit(
|
|
|
407
407
|
action: 'failed',
|
|
408
408
|
reason: 'disable-timeout',
|
|
409
409
|
lines: [
|
|
410
|
-
`legacy-unit reconcile: the disable of ${legacyUnit} timed out and its outcome is UNKNOWN
|
|
410
|
+
`legacy-unit reconcile: the disable of ${legacyUnit} timed out and its outcome is UNKNOWN; the enablement ` +
|
|
411
411
|
`state could not be re-confirmed. This tool removed nothing; the unit file at ${path} was left in place ` +
|
|
412
412
|
'and will be re-checked at the next daemon start.',
|
|
413
413
|
`Verify it yourself: systemctl --user is-enabled ${legacyUnit}`,
|
|
@@ -421,7 +421,7 @@ export async function reconcileRedundantLegacyUnit(
|
|
|
421
421
|
reason: 'disable-failed',
|
|
422
422
|
lines: [
|
|
423
423
|
`legacy-unit reconcile: the disable of the redundant installer-managed ${legacyUnit} reported failure ` +
|
|
424
|
-
`(${detail})
|
|
424
|
+
`(${detail}): this tool removed nothing; the unit file at ${path} was left in place.`,
|
|
425
425
|
`Verify its state and retire it yourself: systemctl --user is-enabled ${legacyUnit} ; ` +
|
|
426
426
|
`systemctl --user disable --now ${legacyUnit} && rm ${path} && systemctl --user daemon-reload`,
|
|
427
427
|
],
|
|
@@ -442,7 +442,7 @@ export async function reconcileRedundantLegacyUnit(
|
|
|
442
442
|
`was disabled${removeError ? '' : ` and removed (${path})`}.`,
|
|
443
443
|
];
|
|
444
444
|
if (removeError) {
|
|
445
|
-
lines.push(`note: could not remove ${path}: ${removeError}
|
|
445
|
+
lines.push(`note: could not remove ${path}: ${removeError}; remove it by hand.`);
|
|
446
446
|
}
|
|
447
447
|
lines.push(...deadlineNote());
|
|
448
448
|
return { action: 'removed', reason: 'retired', lines };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// ---------------------------------------------------------------------------
|
|
2
|
-
// memory-governance-services.ts
|
|
2
|
+
// memory-governance-services.ts, the daemon-composition tail that constructs
|
|
3
3
|
// and starts the SDK's MemoryGovernor with the TUI fork's REAL cache adapters.
|
|
4
4
|
//
|
|
5
5
|
// Mirrors the SDK's own createRuntimeServices: the CacheRegistry, PauseController
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
// controller before the governor exists); this helper is the TAIL step that
|
|
9
9
|
// hands them to wireDaemonMemoryGovernance with the fork's knowledge stores +
|
|
10
10
|
// shared session broker as the real, reclaiming cache adapters, and starts the
|
|
11
|
-
// governor. It is default ON
|
|
11
|
+
// governor. It is default ON, the governor is a safety feature the owner
|
|
12
12
|
// confirmed starts by default (wireDaemonMemoryGovernance starts it unless a
|
|
13
13
|
// caller opts out), so every daemon composition defends its own footprint.
|
|
14
14
|
//
|
|
@@ -50,7 +50,7 @@ export interface MemoryGovernanceServices {
|
|
|
50
50
|
/**
|
|
51
51
|
* Construct + start the MemoryGovernor with the standard KNOWN cache adapters
|
|
52
52
|
* (knowledge-store + session-union), reading the memory.* config domain. The
|
|
53
|
-
* governor starts by default
|
|
53
|
+
* governor starts by default, it is a safety feature.
|
|
54
54
|
*/
|
|
55
55
|
export function wireMemoryGovernance(deps: MemoryGovernanceServicesDeps): MemoryGovernanceServices {
|
|
56
56
|
const { configManager } = deps;
|
|
@@ -18,9 +18,9 @@
|
|
|
18
18
|
* to a divergent local copy.
|
|
19
19
|
*
|
|
20
20
|
* The SDK's `rest-transport.ts` (`platform/runtime/memory-spine`) adopted
|
|
21
|
-
* this file's version as the superset
|
|
21
|
+
* this file's version as the superset, same routes,
|
|
22
22
|
* same discriminator functions, same honesty contract, same transport-http
|
|
23
|
-
* primitives
|
|
23
|
+
* primitives, so this file now just delegates. `MemorySpineWireOptions`
|
|
24
24
|
* (`{baseUrl, authToken, fetchImpl?}`) is the same shape the SDK's
|
|
25
25
|
* `MemorySpineRestTransportOptions` takes, so there is nothing to adapt: this
|
|
26
26
|
* export is a direct pass-through, kept as this file's own named symbol only
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
* Retired in the same hoist: `syncMemorySpineToHostStatus` and
|
|
31
31
|
* `MemorySpineActiveRef`. Memory-spine activation is now folded into the
|
|
32
32
|
* SDK's `createSpineAdoptionSync` (see `src/runtime/client/spine-adoption.ts`)
|
|
33
|
-
|
|
33
|
+
*, `spine-adoption.ts` supplies `memoryTransport` in the connect bundle
|
|
34
34
|
* instead of calling a separate sync function on the daemon-status signal.
|
|
35
35
|
* Confirmed zero non-test callers remained (only
|
|
36
36
|
* `src/test/runtime/memory-spine-daemon-integration.test.ts` still exercised
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Notification dispatch
|
|
2
|
+
* Notification dispatch, the production wiring that finally gives the
|
|
3
3
|
* panel_only notification target a live producer.
|
|
4
4
|
*
|
|
5
5
|
* The SDK's NotificationRouter decides where each domain notification goes
|
|
@@ -28,7 +28,7 @@ export interface NotificationDispatcher {
|
|
|
28
28
|
/**
|
|
29
29
|
* The runtime event domains whose events surface as operational notifications.
|
|
30
30
|
* Deliberately a curated set of user-relevant, completion/attention-shaped
|
|
31
|
-
* domains
|
|
31
|
+
* domains, not every domain, so the panel reflects meaningful operational
|
|
32
32
|
* activity rather than raw event churn. The router's per-domain verbosity and
|
|
33
33
|
* burst/batch policies still collapse floods within these.
|
|
34
34
|
*/
|
|
@@ -48,7 +48,7 @@ export function humanizeEventType(type: string): string {
|
|
|
48
48
|
return words.map((word, index) => (index === 0 ? word[0]!.toUpperCase() + word.slice(1) : word)).join(' ');
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
/** Derive a notification severity from an event type
|
|
51
|
+
/** Derive a notification severity from an event type, errors/failures warn, the rest are informational. */
|
|
52
52
|
export function levelForEventType(type: string): Notification['level'] {
|
|
53
53
|
const upper = type.toUpperCase();
|
|
54
54
|
if (/(FAILED|ERROR|CRASH|DENIED|BLOCKED)/.test(upper)) return 'warning';
|
|
@@ -91,7 +91,7 @@ export function createNotificationDispatcher(
|
|
|
91
91
|
* attention line. The MemoryGovernor emits this on the 'ops' domain when the
|
|
92
92
|
* pressure tier changes or the leak tripwire fires; that domain also carries
|
|
93
93
|
* high-churn audit/metric events, so it is deliberately NOT in
|
|
94
|
-
* NOTIFICATION_BRIDGE_DOMAINS
|
|
94
|
+
* NOTIFICATION_BRIDGE_DOMAINS, this targeted bridge lifts only the
|
|
95
95
|
* memory-pressure event into notices (critical at the critical tier / on a
|
|
96
96
|
* tripwire, warning at high), leaving the rest of the ops churn out of the
|
|
97
97
|
* feed. Returns an unsubscribe function.
|
|
@@ -139,7 +139,7 @@ function validateConfigValue(operation: Extract<OnboardingApplyOperation, { kind
|
|
|
139
139
|
|
|
140
140
|
// Feature enablement arrives as plain domain settings writes (e.g.
|
|
141
141
|
// sandbox.enabled, controlPlane.gateway), validated by the schema path below
|
|
142
|
-
// like any other key
|
|
142
|
+
// like any other key, there is no separate enablement namespace.
|
|
143
143
|
const schema = CONFIG_SCHEMA.find((entry) => entry.key === operation.key);
|
|
144
144
|
if (!schema) {
|
|
145
145
|
const defaultValue = operation.key.split('.').reduce<unknown>((cursor, part) => (
|
|
@@ -269,7 +269,7 @@ function describeLocalTuiOnly(snapshot: OnboardingSnapshotState): string {
|
|
|
269
269
|
// GoodVibes surfaces on this machine. Turn it off in Settings > daemon if you
|
|
270
270
|
// want none at all.
|
|
271
271
|
if (!hasAnyServerEnabled(snapshot)) {
|
|
272
|
-
return 'Use GoodVibes only in this terminal. No browser access, HTTP listener, external app surface, or network setup. A loopback-only background daemon still runs by default so sessions here stay visible to other GoodVibes surfaces on this machine
|
|
272
|
+
return 'Use GoodVibes only in this terminal. No browser access, HTTP listener, external app surface, or network setup. A loopback-only background daemon still runs by default so sessions here stay visible to other GoodVibes surfaces on this machine; turn it off in Settings > daemon if you want none at all.';
|
|
273
273
|
}
|
|
274
274
|
|
|
275
275
|
return 'Turn off browser access, HTTP listeners, external app surfaces, and network setup. The loopback-only background daemon keeps running by default for cross-surface visibility unless you turn it off in Settings > daemon.';
|