@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
package/src/cli/help.ts
CHANGED
|
@@ -7,7 +7,7 @@ function readJsonVersion(path: string): string | null {
|
|
|
7
7
|
try {
|
|
8
8
|
if (!existsSync(path)) return null;
|
|
9
9
|
const parsed = JSON.parse(readFileSync(path, 'utf-8')) as { name?: unknown; version?: unknown };
|
|
10
|
-
// Only trust OUR package.json
|
|
10
|
+
// Only trust OUR package.json, a compiled single-file binary can resolve
|
|
11
11
|
// this path to a different package.json (a bundled dependency's) that
|
|
12
12
|
// reports a placeholder like "0.0.0". Fall through to the baked VERSION in
|
|
13
13
|
// that case rather than rendering a stray version in `--version`/banners.
|
|
@@ -30,7 +30,7 @@ export function renderGoodVibesVersion(binary = 'goodvibes'): string {
|
|
|
30
30
|
|
|
31
31
|
/**
|
|
32
32
|
* Honest one-line startup identity for the daemon binary, emitted right as it
|
|
33
|
-
* begins serving
|
|
33
|
+
* begins serving, including on a bare (no-arg) systemd launch. It states the
|
|
34
34
|
* RESOLVED version (never a placeholder), the home/host/port it actually bound,
|
|
35
35
|
* and points at the real service-setup command. This replaces the field
|
|
36
36
|
* behavior where a bare launch showed a wrong "v0.0.0" banner and gave an
|
|
@@ -44,7 +44,7 @@ export function renderDaemonStartupBanner(
|
|
|
44
44
|
binary = 'goodvibes-daemon',
|
|
45
45
|
): string {
|
|
46
46
|
return (
|
|
47
|
-
`${binary} ${version} starting
|
|
47
|
+
`${binary} ${version} starting: ` +
|
|
48
48
|
`home=${binding.homeDir} host=${binding.host} port=${binding.port} ` +
|
|
49
49
|
`(manage as a service: ${binary} install-service)`
|
|
50
50
|
);
|
|
@@ -257,12 +257,12 @@ const COMMAND_HELP: Record<string, CommandHelp> = {
|
|
|
257
257
|
},
|
|
258
258
|
hooks: {
|
|
259
259
|
usage: ['hooks validate'],
|
|
260
|
-
summary: 'Validate the configured hooks.json against the hook loader schema
|
|
260
|
+
summary: 'Validate the configured hooks.json against the hook loader schema; per-hook pass/fail with plain reasons, nonzero exit if any hook is invalid.',
|
|
261
261
|
examples: ['hooks validate', 'hooks validate --json'],
|
|
262
262
|
},
|
|
263
263
|
plugin: {
|
|
264
264
|
usage: ['plugin init <name> [directory]', 'plugin validate <path>', 'plugin bundles browse <index-url-or-file>', 'plugin bundles install <ref> --sha256 <pin>', 'plugin bundles list'],
|
|
265
|
-
summary: 'Scaffold a minimal valid plugin (manifest.json + entry file), validate a plugin directory against the plugin loader checks, or browse/install/list SHA-256-pinned capability bundles from a governed marketplace index. Bundle installs are never unpinned
|
|
265
|
+
summary: 'Scaffold a minimal valid plugin (manifest.json + entry file), validate a plugin directory against the plugin loader checks, or browse/install/list SHA-256-pinned capability bundles from a governed marketplace index. Bundle installs are never unpinned; a missing or mismatched --sha256 is refused, not overridable.',
|
|
266
266
|
examples: ['plugin init my-plugin', 'plugin validate .goodvibes/plugins/my-plugin', 'plugin bundles browse ./marketplace-index.json', 'plugin bundles install ./bundle.json --sha256 <64-hex> --yes'],
|
|
267
267
|
},
|
|
268
268
|
};
|
|
@@ -340,7 +340,7 @@ export function renderGoodVibesDaemonHelp(binary = 'goodvibes-daemon'): string {
|
|
|
340
340
|
' service-status Show whether the daemon service is installed / enabled / active',
|
|
341
341
|
' migrate-service Guided migration from an install-script goodvibes-daemon.service unit; prints a plan',
|
|
342
342
|
' unless run with -y/--yes (never auto-migrates)',
|
|
343
|
-
' send [message] Send a message to one of your configured channels
|
|
343
|
+
' send [message] Send a message to one of your configured channels: Telegram, ntfy,',
|
|
344
344
|
' Discord, Slack, Google Chat, Signal, WhatsApp, iMessage, Teams,',
|
|
345
345
|
' BlueBubbles, Mattermost, Matrix or a webhook. Takes the message as',
|
|
346
346
|
' an argument or on stdin, so it composes with other tooling.',
|
package/src/cli/hooks-command.ts
CHANGED
|
@@ -2,10 +2,10 @@ import { buildHooksValidation } from './hooks-report.ts';
|
|
|
2
2
|
import type { CliCommandOutput, CliCommandRuntime } from '@pellux/goodvibes-terminal-shell';
|
|
3
3
|
|
|
4
4
|
// ---------------------------------------------------------------------------
|
|
5
|
-
// `goodvibes hooks validate
|
|
5
|
+
// `goodvibes hooks validate`, validate the user's hooks.json against the
|
|
6
6
|
// hooks loader's REAL schema. The acceptance verdict comes from
|
|
7
7
|
// buildHooksValidation (src/cli/hooks-report.ts), which runs the SDK's own
|
|
8
|
-
// HookDispatcher.loadFromFile and getHookPointContract
|
|
8
|
+
// HookDispatcher.loadFromFile and getHookPointContract, the same machinery
|
|
9
9
|
// `goodvibes doctor hooks` reuses. This command only reads and reports.
|
|
10
10
|
// ---------------------------------------------------------------------------
|
|
11
11
|
|
|
@@ -23,7 +23,7 @@ export async function handleHooksCommand(runtime: CliCommandRuntime): Promise<Cl
|
|
|
23
23
|
const text = [
|
|
24
24
|
'GoodVibes hooks validation',
|
|
25
25
|
` file: ${path}`,
|
|
26
|
-
' no hooks file present
|
|
26
|
+
' no hooks file present: nothing to validate.',
|
|
27
27
|
].join('\n');
|
|
28
28
|
return { output: json ? JSON.stringify({ path, present: false, hooks: [], valid: true }, null, 2) : text, exitCode: 0 };
|
|
29
29
|
}
|
|
@@ -62,7 +62,7 @@ export async function handleHooksCommand(runtime: CliCommandRuntime): Promise<Cl
|
|
|
62
62
|
const detail = c ? ` (contract: ${c.authority}/${c.executionMode})` : '';
|
|
63
63
|
lines.push(` PASS ${label}${detail}`);
|
|
64
64
|
} else {
|
|
65
|
-
lines.push(` FAIL ${label}
|
|
65
|
+
lines.push(` FAIL ${label}: ${check.reason}`);
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
if (chains.declared > 0 || chains.accepted > 0) {
|
package/src/cli/hooks-report.ts
CHANGED
|
@@ -11,7 +11,7 @@ import { summarizeError } from '@pellux/goodvibes-sdk/platform/utils';
|
|
|
11
11
|
// acceptance comes from running the SDK's own HookDispatcher.loadFromFile (the
|
|
12
12
|
// same loader the app uses at startup), and the "is this a real hook event
|
|
13
13
|
// point" verdict comes from the SDK's getHookPointContract. This module only
|
|
14
|
-
// reads and reports
|
|
14
|
+
// reads and reports, it changes no config and fires no hooks.
|
|
15
15
|
// ---------------------------------------------------------------------------
|
|
16
16
|
|
|
17
17
|
/** Per-hook acceptance verdict, keyed to the on-disk position it was declared at. */
|
|
@@ -28,7 +28,7 @@ export interface HookCheck {
|
|
|
28
28
|
|
|
29
29
|
/** The full validation result for one hooks file. */
|
|
30
30
|
export interface HooksValidation {
|
|
31
|
-
/** Absolute path the app resolves `tools.hooksFile` to
|
|
31
|
+
/** Absolute path the app resolves `tools.hooksFile` to, the "from where" of every hook. */
|
|
32
32
|
readonly path: string;
|
|
33
33
|
readonly present: boolean;
|
|
34
34
|
readonly valid: boolean;
|
|
@@ -42,7 +42,7 @@ export interface HooksValidation {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
export const LOADER_FIELD_REASON =
|
|
45
|
-
"the hooks loader skipped this entry
|
|
45
|
+
"the hooks loader skipped this entry; a hook needs a string \"match\" and a \"type\" of command, prompt, agent, http, or ts";
|
|
46
46
|
|
|
47
47
|
/** Build a consumable multiset of the loader-accepted definitions, keyed by pattern. */
|
|
48
48
|
function acceptedMultiset(accepted: Map<string, HookDefinition[]>): Map<string, Map<string, number>> {
|
|
@@ -100,7 +100,7 @@ export function buildHooksValidation(configManager: Pick<ConfigManager, 'get' |
|
|
|
100
100
|
try {
|
|
101
101
|
parsed = JSON.parse(readFileSync(path, 'utf-8'));
|
|
102
102
|
} catch (error) {
|
|
103
|
-
return { path, present: true, valid: false, reason: `hooks.json is not valid JSON
|
|
103
|
+
return { path, present: true, valid: false, reason: `hooks.json is not valid JSON; ${summarizeError(error)}`, topLevelIssues: [], checks: [], chains: { declared: 0, accepted: 0 }, passCount: 0, failCount: 1 };
|
|
104
104
|
}
|
|
105
105
|
|
|
106
106
|
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Launch-time self-update
|
|
2
|
+
* Launch-time self-update, clients land on the newest release at startup so
|
|
3
3
|
* an installed binary never drifts behind. At TUI launch (before any runtime
|
|
4
4
|
* bootstrap or terminal mode change) this runs a quick version check and, when
|
|
5
5
|
* a newer release exists, installs it through the SAME checksum-verified
|
|
6
6
|
* download/verify/swap path `/update apply` and the suite installer use
|
|
7
|
-
* (src/input/commands/update-runtime.ts
|
|
7
|
+
* (src/input/commands/update-runtime.ts, there is deliberately no second
|
|
8
8
|
* updater), then asks the caller to restart onto the new binary.
|
|
9
9
|
*
|
|
10
10
|
* Honesty rules, in both directions:
|
|
11
11
|
* - the check gets a short timeout; when it cannot complete (offline, slow
|
|
12
12
|
* network) the CURRENT version starts with exactly one line saying the
|
|
13
|
-
* check was skipped
|
|
13
|
+
* check was skipped, launch is never held hostage by the network.
|
|
14
14
|
* - a successful update restarts into the new binary and the restarted
|
|
15
15
|
* process prints a receipt naming both versions, so the swap is never
|
|
16
16
|
* silent.
|
|
17
17
|
* - the install gets a budget too, and running out of it is reported for
|
|
18
18
|
* what actually happened rather than assumed. The budget cancels the work
|
|
19
19
|
* through a real AbortSignal, so a download that is still in flight is
|
|
20
|
-
* genuinely stopped and "deferred
|
|
20
|
+
* genuinely stopped and "deferred, will retry next launch" is true. Once
|
|
21
21
|
* the swap has begun it is never interrupted, so that outcome says the
|
|
22
22
|
* binary WAS replaced and asks for a restart instead. The two are told
|
|
23
23
|
* apart by the swap state the install reports back (UpdateSwapProgress),
|
|
@@ -27,12 +27,12 @@
|
|
|
27
27
|
*
|
|
28
28
|
* The feature is a real configurable setting (`update.autoUpdateAtLaunch` in
|
|
29
29
|
* settings.json, read via readUpdateSettings): default ON, off with an
|
|
30
|
-
* explicit false. Only binary installs self-update
|
|
30
|
+
* explicit false. Only binary installs self-update, package-manager and
|
|
31
31
|
* from-source runs are skipped silently because a swap there would fight the
|
|
32
32
|
* package manager (see detectInstallKind).
|
|
33
33
|
*
|
|
34
34
|
* Everything effectful is injectable; tests drive the decision logic with a
|
|
35
|
-
* stubbed fetch, a stubbed apply, and pinned fixture versions
|
|
35
|
+
* stubbed fetch, a stubbed apply, and pinned fixture versions, never the
|
|
36
36
|
* live build VERSION and never the real network.
|
|
37
37
|
*/
|
|
38
38
|
import { spawnSync } from 'node:child_process';
|
|
@@ -61,7 +61,7 @@ export const LAUNCH_UPDATED_FROM_ENV = 'GOODVIBES_LAUNCH_UPDATED_FROM';
|
|
|
61
61
|
/** Default budget for the launch-time version check; user-tunable via update.launchCheckTimeoutMs. */
|
|
62
62
|
export const LAUNCH_UPDATE_CHECK_TIMEOUT_MS = 2500;
|
|
63
63
|
|
|
64
|
-
/** Default budget for the launch-time download+verify+swap; user-tunable via update.applyTimeoutMs. Generous
|
|
64
|
+
/** Default budget for the launch-time download+verify+swap; user-tunable via update.applyTimeoutMs. Generous, a binary download over a slow connection genuinely takes a while, but bounded so launch is never held hostage. */
|
|
65
65
|
export const LAUNCH_APPLY_TIMEOUT_MS = 45_000;
|
|
66
66
|
|
|
67
67
|
export type LaunchAutoUpdateOutcome =
|
|
@@ -144,11 +144,11 @@ export async function runLaunchAutoUpdate(options: RunLaunchAutoUpdateOptions):
|
|
|
144
144
|
check = 'timeout';
|
|
145
145
|
}
|
|
146
146
|
if (check === 'timeout') {
|
|
147
|
-
// Honest about WHY the check was skipped
|
|
147
|
+
// Honest about WHY the check was skipped, a timeout most commonly means
|
|
148
148
|
// the update server could not be reached in time, not necessarily that
|
|
149
149
|
// the whole machine is offline (a slow/flaky connection is just as
|
|
150
150
|
// common), so this no longer overclaims "offline".
|
|
151
|
-
options.print("couldn't reach the update server
|
|
151
|
+
options.print("couldn't reach the update server; check skipped");
|
|
152
152
|
return { action: 'continue', reason: 'check-skipped' };
|
|
153
153
|
}
|
|
154
154
|
if (check.isCurrent) {
|
|
@@ -181,23 +181,23 @@ export async function runLaunchAutoUpdate(options: RunLaunchAutoUpdateOptions):
|
|
|
181
181
|
if (applyResult === 'timeout') {
|
|
182
182
|
if (!progress.begun) {
|
|
183
183
|
// Nothing has been written yet, so the work can genuinely be called
|
|
184
|
-
// off
|
|
184
|
+
// off, cancel the download in flight, then say it was deferred.
|
|
185
185
|
controller.abort();
|
|
186
|
-
options.print('update deferred
|
|
186
|
+
options.print('update deferred: will retry next launch');
|
|
187
187
|
return { action: 'continue', reason: 'update-deferred' };
|
|
188
188
|
}
|
|
189
189
|
// The swap had already started when the budget ran out. A swap is never
|
|
190
|
-
// interrupted, so the binary on disk is the new one
|
|
190
|
+
// interrupted, so the binary on disk is the new one, cancelling here
|
|
191
191
|
// would be a lie in the other direction. Report the replacement and the
|
|
192
192
|
// restart it needs instead of claiming a deferral that did not happen.
|
|
193
193
|
options.print(`updated in background; restart to use v${normalizeVersion(progress.targetTag ?? check.latestTag)}`);
|
|
194
194
|
return { action: 'continue', reason: 'update-in-background' };
|
|
195
195
|
}
|
|
196
|
-
options.print(`auto-update: ${check.latestTag} installed
|
|
196
|
+
options.print(`auto-update: ${check.latestTag} installed; restarting onto the new version`);
|
|
197
197
|
return { action: 'restart', latestTag: check.latestTag };
|
|
198
198
|
} catch (error) {
|
|
199
199
|
options.print(
|
|
200
|
-
`auto-update failed: ${error instanceof Error ? error.message : String(error)}
|
|
200
|
+
`auto-update failed: ${error instanceof Error ? error.message : String(error)}; starting the current version v${normalizeVersion(options.currentVersion)}`,
|
|
201
201
|
);
|
|
202
202
|
return { action: 'continue', reason: 'update-failed' };
|
|
203
203
|
}
|
|
@@ -214,7 +214,7 @@ export interface SelfUpdateAtLaunchParams {
|
|
|
214
214
|
* binary and EXIT THIS PROCESS with the new instance's exit code (this call
|
|
215
215
|
* never returns in that case); otherwise return the honest lines that were
|
|
216
216
|
* printed (receipt / skipped check / failed update) so the caller can
|
|
217
|
-
* re-surface them through the system message router once it exists
|
|
217
|
+
* re-surface them through the system message router once it exists, the
|
|
218
218
|
* stdout copies written here are wiped by the TUI's alternate screen.
|
|
219
219
|
*/
|
|
220
220
|
export async function selfUpdateAtLaunch(params: SelfUpdateAtLaunchParams): Promise<readonly string[]> {
|
|
@@ -262,7 +262,7 @@ export interface HandDaemonOverAtLaunchParams {
|
|
|
262
262
|
* The launch wiring for the old→new daemon handover (src/runtime/daemon-handover.ts).
|
|
263
263
|
*
|
|
264
264
|
* A daemon binary from before the split cannot update itself onto its own
|
|
265
|
-
* release line
|
|
265
|
+
* release line, the releases URL baked into it names this repository, which no
|
|
266
266
|
* longer builds daemons, and pointing it at the daemon's repository instead
|
|
267
267
|
* still fails because its shipped updater insists on downloading the terminal
|
|
268
268
|
* binary beside it, which that repository does not publish. So the terminal
|
|
@@ -300,7 +300,7 @@ export interface RestartOntoUpdatedBinaryOptions {
|
|
|
300
300
|
readonly execPath: string;
|
|
301
301
|
readonly argv: readonly string[];
|
|
302
302
|
readonly env: NodeJS.ProcessEnv;
|
|
303
|
-
/** The version that performed the update
|
|
303
|
+
/** The version that performed the update, the restarted process prints it in its receipt line. */
|
|
304
304
|
readonly fromVersion: string;
|
|
305
305
|
/** Injectable so tests observe the restart instead of spawning a process. */
|
|
306
306
|
readonly spawn?: (execPath: string, argv: readonly string[], env: NodeJS.ProcessEnv) => number | null;
|
|
@@ -315,7 +315,7 @@ export interface ControlPlaneStatusResult {
|
|
|
315
315
|
readonly port: number;
|
|
316
316
|
readonly recognized: boolean;
|
|
317
317
|
readonly posture: ReturnType<typeof classifyBindPosture>;
|
|
318
|
-
/** undefined = NOT PROBED (unrecognized host mode)
|
|
318
|
+
/** undefined = NOT PROBED (unrecognized host mode), a tri-state, never coerced to false. */
|
|
319
319
|
readonly reachable: boolean | undefined;
|
|
320
320
|
readonly auth: ReturnType<typeof readAuthPaths>;
|
|
321
321
|
readonly service: {
|
|
@@ -329,7 +329,7 @@ export interface ControlPlaneStatusResult {
|
|
|
329
329
|
export async function buildControlPlaneStatusResult(runtime: CliCommandRuntime): Promise<ControlPlaneStatusResult> {
|
|
330
330
|
const binding = resolveRuntimeEndpointBinding(runtime.configManager, 'controlPlane');
|
|
331
331
|
const enabled = runtime.configManager.get('controlPlane.enabled');
|
|
332
|
-
// Never TCP-probe the fallback endpoint of an unrecognized hostMode
|
|
332
|
+
// Never TCP-probe the fallback endpoint of an unrecognized hostMode, a
|
|
333
333
|
// probe asserts a binding that does not exist. Not-probed is its own state
|
|
334
334
|
// (undefined), NEVER coerced to a definite false: a daemon launched with
|
|
335
335
|
// flag overrides can be serving healthily regardless of the stored mode.
|
|
@@ -343,7 +343,7 @@ export async function buildControlPlaneStatusResult(runtime: CliCommandRuntime):
|
|
|
343
343
|
restartOnFailure: runtime.configManager.get('service.restartOnFailure'),
|
|
344
344
|
};
|
|
345
345
|
const issues: string[] = [];
|
|
346
|
-
if (!binding.recognized) issues.push(`controlPlane.hostMode '${binding.hostMode}' is not a recognized mode (local|network|custom)
|
|
346
|
+
if (!binding.recognized) issues.push(`controlPlane.hostMode '${binding.hostMode}' is not a recognized mode (local|network|custom); the daemon cannot bind until it is corrected.`);
|
|
347
347
|
if (enabled === true && binding.recognized && !reachable) issues.push(`Control plane is enabled but not reachable on ${binding.host}:${binding.port}.`);
|
|
348
348
|
if (enabled === true && service.enabled !== true) issues.push('Control plane is enabled but service mode is off.');
|
|
349
349
|
if (enabled === true && service.autostart !== true) issues.push('Control plane is enabled but service autostart is off.');
|
|
@@ -408,7 +408,7 @@ export async function renderPairing(runtime: CliCommandRuntime): Promise<string>
|
|
|
408
408
|
const link = result.deepLink ?? result.fragment;
|
|
409
409
|
const qr = renderQrToString(generateQrMatrix(link));
|
|
410
410
|
const lines: string[] = [
|
|
411
|
-
'Scan to pair a device
|
|
411
|
+
'Scan to pair a device; the QR opens the web app already signed in:',
|
|
412
412
|
'',
|
|
413
413
|
` ${link}`,
|
|
414
414
|
` Token name: ${result.token.name} (rename or revoke later in /settings → security → devices)`,
|
|
@@ -417,7 +417,7 @@ export async function renderPairing(runtime: CliCommandRuntime): Promise<string>
|
|
|
417
417
|
lines.push('', 'Offers carried in this pairing (each declinable in the web app):', ...formatPairingOffers(result.offers.map((o) => o.kind)));
|
|
418
418
|
}
|
|
419
419
|
// The labeled browser-capability list and the one honest LAN line both render
|
|
420
|
-
// from the SDK posture the verb returned
|
|
420
|
+
// from the SDK posture the verb returned, never a locally-authored string.
|
|
421
421
|
const capabilities = formatPostureCapabilities(result.posture);
|
|
422
422
|
if (capabilities.length > 0) lines.push('', 'This device will get:', ...capabilities);
|
|
423
423
|
const notice = pairingPostureNotice(result.posture);
|
|
@@ -440,8 +440,8 @@ interface TailscaleGetResult {
|
|
|
440
440
|
/**
|
|
441
441
|
* Read-only tailscale detection for the `gv pair` block: when tailscale is
|
|
442
442
|
* available with a served https MagicDNS URL, name the encrypted path (the
|
|
443
|
-
* interactive one-action serve lives in the pairing modal). Quiet
|
|
444
|
-
* array
|
|
443
|
+
* interactive one-action serve lives in the pairing modal). Quiet, an empty
|
|
444
|
+
* array, when tailscale is absent or the probe fails.
|
|
445
445
|
*/
|
|
446
446
|
async function renderPairingTailscaleLines(services: RuntimeServices): Promise<string[]> {
|
|
447
447
|
try {
|
|
@@ -451,7 +451,7 @@ async function renderPairingTailscaleLines(services: RuntimeServices): Promise<s
|
|
|
451
451
|
})) as TailscaleGetResult;
|
|
452
452
|
if (!ts.available) return [];
|
|
453
453
|
if (ts.httpsUrl) return ['', `Encrypted access (Tailscale): ${ts.httpsUrl}`];
|
|
454
|
-
return ['', 'Tailscale detected
|
|
454
|
+
return ['', 'Tailscale detected: run it as a serve target for encrypted https access (see the pairing modal).'];
|
|
455
455
|
} catch {
|
|
456
456
|
return [];
|
|
457
457
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* management-utils.ts
|
|
2
|
+
* management-utils.ts, shared CLI utility functions.
|
|
3
3
|
*
|
|
4
4
|
* Extracted from management.ts to break the import cycle:
|
|
5
5
|
* management.ts ↔ management-commands.ts
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* for these utilities).
|
|
11
11
|
*
|
|
12
12
|
* No imports from management-commands.ts or surface-command.ts are allowed
|
|
13
|
-
* in this file
|
|
13
|
+
* in this file, that would recreate the cycle.
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
import { existsSync, readFileSync } from 'node:fs';
|
|
@@ -326,7 +326,7 @@ export async function runNonInteractiveAgent(runtime: CliCommandRuntime): Promis
|
|
|
326
326
|
|
|
327
327
|
try {
|
|
328
328
|
// Async pre-turn refresh of the memory-spine recall snapshot (SDK 1.2.0
|
|
329
|
-
// full-detach)
|
|
329
|
+
// full-detach), see the matching comment in main.ts's submitInput.
|
|
330
330
|
await refreshMemoryRecallSnapshot(ctx.services);
|
|
331
331
|
await ctx.orchestrator.handleUserInput(prompt);
|
|
332
332
|
await done;
|
package/src/cli/management.ts
CHANGED
|
@@ -282,7 +282,7 @@ async function renderModels(runtime: CliCommandRuntime): Promise<string> {
|
|
|
282
282
|
].join('\n'));
|
|
283
283
|
}
|
|
284
284
|
if (subOrFilter === 'chain' || subOrFilter === 'chains') {
|
|
285
|
-
// List synthetic model fallback ladders
|
|
285
|
+
// List synthetic model fallback ladders, backend composition for each synthetic model.
|
|
286
286
|
const canonicalModels = services.providerRegistry.getSyntheticCanonicalModels();
|
|
287
287
|
if (canonicalModels.length === 0) {
|
|
288
288
|
return formatJsonOrText(runtime.cli)([], 'No synthetic models found in the current catalog.');
|
|
@@ -14,11 +14,11 @@ import { summarizeError } from '@pellux/goodvibes-sdk/platform/utils';
|
|
|
14
14
|
import type { CliCommandOutput, CliCommandRuntime } from '@pellux/goodvibes-terminal-shell';
|
|
15
15
|
|
|
16
16
|
// ---------------------------------------------------------------------------
|
|
17
|
-
// `goodvibes plugin bundles browse|install|list
|
|
17
|
+
// `goodvibes plugin bundles browse|install|list`, the capability-bundle
|
|
18
18
|
// marketplace surface. Extends the existing plugin-command.ts family with the
|
|
19
19
|
// SDK's SHA-256-pinned bundle distribution (platform/runtime/ecosystem):
|
|
20
20
|
// parseMarketplaceIndex, fetchAndVerifyBundle, planBundleActivation. There is
|
|
21
|
-
// deliberately NO flag that bypasses a pin mismatch
|
|
21
|
+
// deliberately NO flag that bypasses a pin mismatch, `install` either
|
|
22
22
|
// verifies or refuses; `--yes` only confirms an ALREADY-verified activation
|
|
23
23
|
// plan, it never substitutes for the pin.
|
|
24
24
|
// ---------------------------------------------------------------------------
|
|
@@ -59,7 +59,7 @@ function formatJsonOrText(runtime: CliCommandRuntime, value: unknown, text: stri
|
|
|
59
59
|
return runtime.cli.flags.outputFormat === 'json' ? JSON.stringify(value, null, 2) : text;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
/** file:// / bare-path vs http(s)
|
|
62
|
+
/** file:// / bare-path vs http(s)://, the only two source kinds this CLI surface accepts (no git ref flag exists yet). */
|
|
63
63
|
function inferSourceKind(ref: string): 'file' | 'url' {
|
|
64
64
|
return ref.startsWith('http://') || ref.startsWith('https://') ? 'url' : 'file';
|
|
65
65
|
}
|
|
@@ -111,7 +111,7 @@ async function handleBrowse(runtime: CliCommandRuntime, ref: string | undefined)
|
|
|
111
111
|
const lines = [`Marketplace index at '${ref}' (${bundles.length} bundle${bundles.length === 1 ? '' : 's'}):`];
|
|
112
112
|
for (const entry of bundles) {
|
|
113
113
|
lines.push(
|
|
114
|
-
` ${entry.id}
|
|
114
|
+
` ${entry.id}: ${entry.name} v${entry.version} (${entry.kind})`,
|
|
115
115
|
` ${entry.summary}`,
|
|
116
116
|
` capabilities: ${summarizeCapabilities(entry.capabilities)}`,
|
|
117
117
|
` pin: sha256:${entry.source.sha256} (${entry.source.kind}: ${entry.source.location})`,
|
|
@@ -123,7 +123,7 @@ async function handleBrowse(runtime: CliCommandRuntime, ref: string | undefined)
|
|
|
123
123
|
/** Render an activation plan (granted capabilities, withheld/quarantined ones) for confirmation. */
|
|
124
124
|
function renderPlan(plan: BundleActivationPlan, committed: boolean): string {
|
|
125
125
|
const lines = [
|
|
126
|
-
`${committed ? 'Installed' : 'Activation plan (preview
|
|
126
|
+
`${committed ? 'Installed' : 'Activation plan (preview; re-run with --yes to install)'}: ${plan.manifest.id} v${plan.manifest.version} (${plan.manifest.kind})`,
|
|
127
127
|
` trust tier: ${plan.trustTier}`,
|
|
128
128
|
` declared runtime capabilities: ${plan.manifest.capabilities.runtime.join(', ') || 'none'}`,
|
|
129
129
|
` declared tools: ${plan.manifest.capabilities.tools.join(', ') || 'none'}`,
|
|
@@ -134,18 +134,18 @@ function renderPlan(plan: BundleActivationPlan, committed: boolean): string {
|
|
|
134
134
|
];
|
|
135
135
|
if (plan.quarantine.required) {
|
|
136
136
|
lines.push(
|
|
137
|
-
` QUARANTINED: yes
|
|
137
|
+
` QUARANTINED: yes; ${plan.quarantine.reason ?? 'over-reached its trust tier'}`,
|
|
138
138
|
` withheld capabilities: ${plan.quarantine.revokedCapabilities.join(', ')}`,
|
|
139
139
|
);
|
|
140
140
|
} else {
|
|
141
|
-
lines.push(' quarantined: no
|
|
141
|
+
lines.push(' quarantined: no; every declared capability fit the trust tier');
|
|
142
142
|
}
|
|
143
143
|
return lines.join('\n');
|
|
144
144
|
}
|
|
145
145
|
|
|
146
146
|
async function handleInstall(runtime: CliCommandRuntime, ref: string | undefined, sha256: string | undefined): Promise<CliCommandOutput> {
|
|
147
147
|
if (!ref || !sha256) {
|
|
148
|
-
return { output: 'Usage: goodvibes plugin bundles install <ref> --sha256 <pin> (the pin is required
|
|
148
|
+
return { output: 'Usage: goodvibes plugin bundles install <ref> --sha256 <pin> (the pin is required; there is no unpinned install path)', exitCode: 2 };
|
|
149
149
|
}
|
|
150
150
|
const kind = inferSourceKind(ref);
|
|
151
151
|
const source = { kind, location: ref, sha256 } as const;
|
|
@@ -205,10 +205,10 @@ function handleList(runtime: CliCommandRuntime): CliCommandOutput {
|
|
|
205
205
|
const lines = [`Installed capability bundles (${records.length}):`];
|
|
206
206
|
for (const record of records) {
|
|
207
207
|
lines.push(
|
|
208
|
-
` ${record.id}
|
|
208
|
+
` ${record.id}: ${record.name} v${record.version} (${record.kind})`,
|
|
209
209
|
` installedAt: ${new Date(record.installedAt).toISOString()}`,
|
|
210
210
|
` source: ${record.source.kind}:${record.source.location} (sha256:${record.source.sha256})`,
|
|
211
|
-
` quarantined: ${record.quarantine.required ? `yes
|
|
211
|
+
` quarantined: ${record.quarantine.required ? `yes: ${record.quarantine.reason ?? 'over-reached its trust tier'}` : 'no'}`,
|
|
212
212
|
);
|
|
213
213
|
}
|
|
214
214
|
return { output: formatJsonOrText(runtime, records, lines.join('\n')), exitCode: 0 };
|
|
@@ -8,13 +8,13 @@ import type { CliCommandOutput, CliCommandRuntime } from '@pellux/goodvibes-term
|
|
|
8
8
|
import { handlePluginBundlesCommand } from './plugin-bundles-command.ts';
|
|
9
9
|
|
|
10
10
|
// ---------------------------------------------------------------------------
|
|
11
|
-
// `goodvibes plugin init` / `plugin validate
|
|
11
|
+
// `goodvibes plugin init` / `plugin validate`, scaffold and check plugins
|
|
12
12
|
// against the SAME classic loader the running TUI uses (PluginManager wraps
|
|
13
13
|
// discoverPlugins from @pellux/goodvibes-sdk/platform/plugins). The pass/fail
|
|
14
14
|
// verdict is the real loader's acceptance: we run discoverPlugins against the
|
|
15
15
|
// target directory (isolated from the operator's own plugin folders) and check
|
|
16
16
|
// whether it accepts the directory. Reasons for a rejected manifest are sourced
|
|
17
|
-
// from the SDK's validateManifestV2 (string|null) plus observable file facts
|
|
17
|
+
// from the SDK's validateManifestV2 (string|null) plus observable file facts,
|
|
18
18
|
// no second manifest schema is defined here.
|
|
19
19
|
// ---------------------------------------------------------------------------
|
|
20
20
|
|
|
@@ -57,7 +57,7 @@ function validatePluginDirectory(dirPath: string): PluginValidation {
|
|
|
57
57
|
};
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
// Rejected
|
|
60
|
+
// Rejected, explain why, delegating field checks to the SDK validator.
|
|
61
61
|
const reasons: string[] = [];
|
|
62
62
|
if (!existsSync(manifestPath)) {
|
|
63
63
|
reasons.push('manifest.json not found in the plugin directory.');
|
|
@@ -67,14 +67,14 @@ function validatePluginDirectory(dirPath: string): PluginValidation {
|
|
|
67
67
|
try {
|
|
68
68
|
manifest = JSON.parse(readFileSync(manifestPath, 'utf-8'));
|
|
69
69
|
} catch (error) {
|
|
70
|
-
reasons.push(`manifest.json is not valid JSON
|
|
70
|
+
reasons.push(`manifest.json is not valid JSON; ${summarizeError(error)}`);
|
|
71
71
|
return { ok: false, path: resolved, reasons };
|
|
72
72
|
}
|
|
73
73
|
const fieldReason = validateManifestV2(manifest);
|
|
74
74
|
if (fieldReason) {
|
|
75
75
|
reasons.push(fieldReason);
|
|
76
76
|
} else {
|
|
77
|
-
reasons.push('the plugin loader did not accept this directory
|
|
77
|
+
reasons.push('the plugin loader did not accept this directory; if "main" is set it must be a relative path.');
|
|
78
78
|
}
|
|
79
79
|
return { ok: false, path: resolved, reasons };
|
|
80
80
|
}
|
|
@@ -85,7 +85,7 @@ function renderValidation(result: PluginValidation, json: boolean): CliCommandOu
|
|
|
85
85
|
}
|
|
86
86
|
const lines = ['GoodVibes plugin validation', ` path: ${result.path}`];
|
|
87
87
|
if (result.ok) {
|
|
88
|
-
lines.push(` PASS ${result.manifestName} v${result.manifestVersion}
|
|
88
|
+
lines.push(` PASS ${result.manifestName} v${result.manifestVersion}: the plugin loader accepts this directory.`);
|
|
89
89
|
} else {
|
|
90
90
|
lines.push(' FAIL the plugin loader rejects this directory:');
|
|
91
91
|
for (const reason of result.reasons) lines.push(` - ${reason}`);
|
|
@@ -135,7 +135,7 @@ function handlePluginInit(runtime: CliCommandRuntime): CliCommandOutput {
|
|
|
135
135
|
return {
|
|
136
136
|
output: json
|
|
137
137
|
? JSON.stringify({ ok: false, path: targetDir, reason: summarizeError(error) }, null, 2)
|
|
138
|
-
: `Failed to scaffold plugin at ${targetDir}
|
|
138
|
+
: `Failed to scaffold plugin at ${targetDir}; ${summarizeError(error)}`,
|
|
139
139
|
exitCode: 1,
|
|
140
140
|
};
|
|
141
141
|
}
|
|
@@ -152,8 +152,8 @@ function handlePluginInit(runtime: CliCommandRuntime): CliCommandOutput {
|
|
|
152
152
|
`Scaffolded plugin "${name}" at ${targetDir}`,
|
|
153
153
|
' created: manifest.json, index.js',
|
|
154
154
|
validation.ok
|
|
155
|
-
? ' validation: PASS
|
|
156
|
-
: ` validation: FAIL
|
|
155
|
+
? ' validation: PASS; the plugin loader accepts this directory.'
|
|
156
|
+
: ` validation: FAIL; ${validation.reasons.join('; ')}`,
|
|
157
157
|
` next: run "goodvibes plugin validate ${targetDir}" or restart the TUI to load it.`,
|
|
158
158
|
];
|
|
159
159
|
return { output: lines.join('\n'), exitCode: validation.ok ? 0 : 1 };
|
|
@@ -399,7 +399,7 @@ export async function buildCliServicePosture(
|
|
|
399
399
|
binding,
|
|
400
400
|
bindPosture: classifyBindPosture(binding),
|
|
401
401
|
networkFacing: isNetworkFacing(enabled, binding),
|
|
402
|
-
// Never TCP-probe the fallback endpoint of an unrecognized hostMode
|
|
402
|
+
// Never TCP-probe the fallback endpoint of an unrecognized hostMode,
|
|
403
403
|
// a probe asserts a binding that does not exist.
|
|
404
404
|
...(options.probe && enabled && binding.recognized ? { reachable: await probeTcp(binding.host, binding.port) } : {}),
|
|
405
405
|
};
|
package/src/cli/status.ts
CHANGED
|
@@ -25,11 +25,11 @@ export interface CliStatusOptions {
|
|
|
25
25
|
readonly workspace?: CliWorkspaceStatus;
|
|
26
26
|
/** Per-command exec sandbox availability, host-probed by the caller. */
|
|
27
27
|
readonly sandbox?: CliSandboxStatus;
|
|
28
|
-
/** Outbound relay reachability posture (config + feature-flag gate only
|
|
28
|
+
/** Outbound relay reachability posture (config + feature-flag gate only, a one-shot CLI process has no live connection to inspect). */
|
|
29
29
|
readonly relay?: CliRelayStatus;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
/** Config-derived relay posture. No live socket check
|
|
32
|
+
/** Config-derived relay posture. No live socket check, see doctor's other surfaces for the same honesty bar. */
|
|
33
33
|
export interface CliRelayStatus {
|
|
34
34
|
readonly configEnabled: boolean;
|
|
35
35
|
readonly featureEnabled: boolean;
|
|
@@ -138,7 +138,7 @@ export interface CliStatusSnapshot {
|
|
|
138
138
|
/**
|
|
139
139
|
* Per-surface exposure report row: what a network surface binds to, how it
|
|
140
140
|
* authenticates callers, and what cross-origin allowlist (if any) applies.
|
|
141
|
-
* A plain report
|
|
141
|
+
* A plain report, it changes no behavior and writes no config.
|
|
142
142
|
*/
|
|
143
143
|
export interface CliExposureSurface {
|
|
144
144
|
readonly id: RuntimeEndpointId;
|
|
@@ -205,7 +205,7 @@ function renderWorkspaceSection(workspace: CliWorkspaceStatus | null): string[]
|
|
|
205
205
|
];
|
|
206
206
|
}
|
|
207
207
|
|
|
208
|
-
/** The `Exec sandbox:` block
|
|
208
|
+
/** The `Exec sandbox:` block, honest host-probed availability of the per-command boundary. */
|
|
209
209
|
function renderSandboxSection(sandbox: CliSandboxStatus | null): string[] {
|
|
210
210
|
if (!sandbox) return [];
|
|
211
211
|
const active = sandbox.configEnabled && sandbox.featureEnabled && sandbox.available;
|
|
@@ -228,7 +228,7 @@ function renderSandboxSection(sandbox: CliSandboxStatus | null): string[] {
|
|
|
228
228
|
}
|
|
229
229
|
|
|
230
230
|
/**
|
|
231
|
-
* The `Relay:` block
|
|
231
|
+
* The `Relay:` block, config + feature-flag gate only. The live registration
|
|
232
232
|
* state lives in the running daemon's memory and no verb exposes it, so no
|
|
233
233
|
* client reads it: this CLI reports the gate, and `/relay status` in the
|
|
234
234
|
* terminal app reports the same gate plus an honest "not readable here" for the
|
|
@@ -245,7 +245,7 @@ function renderRelaySection(relay: CliRelayStatus | null): string[] {
|
|
|
245
245
|
` url: ${relay.url || '(not set)'}`,
|
|
246
246
|
` rendezvousId: ${relay.rendezvousId || '(not yet minted)'}`,
|
|
247
247
|
` requireStepUpForMutations: ${yesNo(relay.requireStepUpForMutations)}`,
|
|
248
|
-
' Threat model: the relay operator sees only ciphertext and connection metadata
|
|
248
|
+
' Threat model: the relay operator sees only ciphertext and connection metadata; self-host your own relay for full control.',
|
|
249
249
|
'',
|
|
250
250
|
];
|
|
251
251
|
}
|
|
@@ -296,7 +296,7 @@ const EXPOSURE_SURFACES: readonly { readonly id: RuntimeEndpointId; readonly lab
|
|
|
296
296
|
|
|
297
297
|
/**
|
|
298
298
|
* Build the per-surface exposure report (bind address, auth mode, origin
|
|
299
|
-
* allowlist) for every network surface. Pure over the status options
|
|
299
|
+
* allowlist) for every network surface. Pure over the status options, a
|
|
300
300
|
* report only, no behavior change.
|
|
301
301
|
*/
|
|
302
302
|
export function buildCliExposureReport(options: CliStatusOptions): readonly CliExposureSurface[] {
|
|
@@ -343,7 +343,7 @@ export function buildCliDoctorFindings(options: CliStatusOptions): readonly CliD
|
|
|
343
343
|
const findings: CliDoctorFinding[] = [];
|
|
344
344
|
|
|
345
345
|
// An unrecognized hostMode has NO binding the SDK can produce (its bind
|
|
346
|
-
// resolver has no default case
|
|
346
|
+
// resolver has no default case, the daemon throws before binding), so it
|
|
347
347
|
// is surfaced as a doctor finding on every endpoint that carries one,
|
|
348
348
|
// instead of the fallback loopback binding being presented as fact.
|
|
349
349
|
for (const [endpointId, endpointLabel, endpointBinding] of [
|
|
@@ -535,7 +535,7 @@ export function buildCliDoctorFindings(options: CliStatusOptions): readonly CliD
|
|
|
535
535
|
/**
|
|
536
536
|
* The doctor command's exit code. Advisory findings (`severity: 'warning'`)
|
|
537
537
|
* are notes on an otherwise-usable install and must never make a healthy
|
|
538
|
-
* install report failure
|
|
538
|
+
* install report failure, only a must-fix (`severity: 'risk'`) finding
|
|
539
539
|
* exits non-zero. `strict` (for CI) flips warnings to failures too, so a
|
|
540
540
|
* pipeline can require a fully clean report instead of just "usable".
|
|
541
541
|
*/
|
|
@@ -666,7 +666,7 @@ export function renderCliStatus(options: CliStatusOptions): string {
|
|
|
666
666
|
...renderWorkspaceSection(snapshot.workspace),
|
|
667
667
|
...renderSandboxSection(snapshot.sandbox),
|
|
668
668
|
...renderRelaySection(snapshot.relay),
|
|
669
|
-
'Exposure (report only
|
|
669
|
+
'Exposure (report only: no changes made):',
|
|
670
670
|
...snapshot.exposure.flatMap((surface) => [
|
|
671
671
|
` ${surface.label}: ${yesNo(surface.enabled)} · ${surface.reach}${surface.networkFacing ? ' · network-facing' : ''}`,
|
|
672
672
|
` bind: ${surface.bind}`,
|
|
@@ -131,7 +131,7 @@ export async function handleSurfacesCommand(runtime: CliCommandRuntime): Promise
|
|
|
131
131
|
const readinessIssues: string[] = [];
|
|
132
132
|
for (const [endpointLabel, endpointBinding] of [['controlPlane', controlPlane], ['web', web], ['httpListener', httpListener]] as const) {
|
|
133
133
|
if (!endpointBinding.recognized) {
|
|
134
|
-
readinessIssues.push(`${endpointLabel}.hostMode '${endpointBinding.hostMode}' is not a recognized mode (local|network|custom)
|
|
134
|
+
readinessIssues.push(`${endpointLabel}.hostMode '${endpointBinding.hostMode}' is not a recognized mode (local|network|custom); the daemon cannot bind this endpoint until it is corrected.`);
|
|
135
135
|
}
|
|
136
136
|
}
|
|
137
137
|
if (shouldProbeControlPlane && controlPlane.recognized && config.get('controlPlane.enabled') === true && !controlPlaneReachable) {
|
|
@@ -218,7 +218,7 @@ export interface ListenerTestResult {
|
|
|
218
218
|
readonly port: number;
|
|
219
219
|
readonly recognized: boolean;
|
|
220
220
|
readonly posture: ReturnType<typeof classifyBindPosture>;
|
|
221
|
-
/** undefined = NOT PROBED (unrecognized host mode)
|
|
221
|
+
/** undefined = NOT PROBED (unrecognized host mode), a tri-state, never coerced to false. */
|
|
222
222
|
readonly reachable: boolean | undefined;
|
|
223
223
|
readonly service: {
|
|
224
224
|
readonly enabled: unknown;
|
|
@@ -241,7 +241,7 @@ export async function buildListenerTestResult(runtime: CliCommandRuntime): Promi
|
|
|
241
241
|
const enabled = runtime.configManager.get('danger.httpListener');
|
|
242
242
|
const binding = resolveRuntimeEndpointBinding(runtime.configManager, 'httpListener');
|
|
243
243
|
const posture = classifyBindPosture(binding);
|
|
244
|
-
// Not-probed (unrecognized host mode) stays undefined
|
|
244
|
+
// Not-probed (unrecognized host mode) stays undefined, never a definite false.
|
|
245
245
|
const reachable = enabled === true
|
|
246
246
|
? (binding.recognized ? await probeTcp(binding.host, binding.port) : undefined)
|
|
247
247
|
: false;
|
|
@@ -265,7 +265,7 @@ export async function buildListenerTestResult(runtime: CliCommandRuntime): Promi
|
|
|
265
265
|
};
|
|
266
266
|
}).filter((surface) => surface.enabled === true);
|
|
267
267
|
const issues: string[] = [];
|
|
268
|
-
if (!binding.recognized) issues.push(`httpListener.hostMode '${binding.hostMode}' is not a recognized mode (local|network|custom)
|
|
268
|
+
if (!binding.recognized) issues.push(`httpListener.hostMode '${binding.hostMode}' is not a recognized mode (local|network|custom); the daemon cannot bind until it is corrected.`);
|
|
269
269
|
if (enabled !== true) issues.push('HTTP listener is disabled.');
|
|
270
270
|
if (enabled === true && service.enabled !== true) issues.push('HTTP listener is enabled but service mode is off.');
|
|
271
271
|
if (enabled === true && service.autostart !== true) issues.push('HTTP listener is enabled but service autostart is off.');
|