@pellux/goodvibes-tui 2.0.21 → 2.1.1
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/CHANGELOG.md +65 -1
- package/README.md +30 -29
- package/docs/README.md +8 -5
- package/docs/foundation-artifacts/operator-contract.json +1 -1
- package/package.json +28 -19
- package/src/cli/management.ts +5 -2
- package/src/cli/tui-startup.ts +34 -39
- package/src/core/agent-view-render.ts +157 -0
- package/src/core/approval-alert.ts +49 -11
- package/src/core/bookmark-navigation.ts +7 -1
- package/src/core/budget-breach-notifier.ts +27 -8
- package/src/core/compaction-receipt.ts +1 -1
- package/src/core/context-usage.ts +1 -1
- package/src/core/conversation-compaction-render.ts +3 -3
- package/src/core/conversation-display-only.ts +86 -0
- package/src/core/conversation-event-navigation.ts +27 -0
- package/src/core/conversation-line-cache.ts +216 -447
- package/src/core/conversation-render-context.ts +20 -27
- package/src/core/conversation-rendering.ts +157 -575
- package/src/core/conversation-splash-state.ts +6 -1
- package/src/core/conversation-types.ts +35 -0
- package/src/core/conversation-usage.ts +12 -0
- package/src/core/conversation.ts +130 -131
- package/src/core/long-task-notifier.ts +100 -31
- package/src/core/notices.ts +75 -0
- package/src/core/pairing-tailscale-gateway.ts +1 -1
- package/src/core/process-output-log.ts +143 -0
- package/src/core/rewind-receipt.ts +1 -1
- package/src/core/session-focus.ts +190 -0
- package/src/core/session-resume-core.ts +23 -81
- package/src/core/stream-event-wiring.ts +31 -5
- package/src/core/system-message-noise.ts +2 -2
- package/src/core/system-message-router.ts +16 -18
- package/src/core/turn-event-wiring.ts +272 -33
- package/src/core/work-tree-focus.ts +290 -0
- package/src/core/work-tree-fold-store.ts +143 -0
- package/src/core/work-tree-model.ts +799 -0
- package/src/core/work-tree-render.ts +384 -0
- package/src/core/work-tree-sources.ts +184 -0
- package/src/core/work-tree-wiring.ts +176 -0
- package/src/core/workstream-notification.ts +36 -6
- package/src/core/wrfc-notice-titles.ts +37 -0
- package/src/input/agents-modal-text.ts +119 -0
- package/src/input/agents-modal.ts +699 -0
- package/src/input/bookmark-modal.ts +33 -9
- package/src/input/changes-git.ts +251 -0
- package/src/input/changes-modal.ts +629 -0
- package/src/input/changes-model.ts +125 -0
- package/src/input/command-palette-types.ts +41 -0
- package/src/input/command-palette.ts +272 -0
- package/src/input/command-reference.ts +2 -2
- package/src/input/command-registry.ts +77 -35
- package/src/input/commands/acp-runtime.ts +19 -9
- package/src/input/commands/channel-runtime.ts +2 -2
- package/src/input/commands/ci-runtime.ts +1 -1
- package/src/input/commands/codebase-runtime.ts +1 -1
- package/src/input/commands/config.ts +7 -1
- package/src/input/commands/context-window.ts +25 -19
- package/src/input/commands/control-room-runtime.ts +18 -18
- package/src/input/commands/conversation-runtime.ts +0 -1
- package/src/input/commands/cost-runtime.ts +29 -20
- package/src/input/commands/diff-runtime.ts +35 -181
- package/src/input/commands/eval.ts +1 -1
- package/src/input/commands/experience-runtime.ts +3 -7
- package/src/input/commands/fresh-conversation.ts +86 -0
- package/src/input/commands/git-runtime.ts +5 -22
- package/src/input/commands/graph-runtime.ts +1 -1
- package/src/input/commands/guidance-runtime.ts +1 -1
- package/src/input/commands/health-runtime.ts +8 -9
- package/src/input/commands/hooks-runtime.ts +2 -2
- package/src/input/commands/hosted-runtime.ts +3 -3
- package/src/input/commands/incident-runtime.ts +3 -3
- package/src/input/commands/intelligence-runtime.ts +6 -9
- package/src/input/commands/knowledge.ts +2 -2
- package/src/input/commands/legacy-panel-command.ts +57 -0
- package/src/input/commands/local-auth-runtime.ts +8 -9
- package/src/input/commands/local-provider-runtime.ts +7 -4
- package/src/input/commands/local-runtime.ts +12 -15
- package/src/input/commands/local-setup-review.ts +1 -1
- package/src/input/commands/local-setup.ts +13 -19
- package/src/input/commands/memory.ts +1 -1
- package/src/input/commands/notify-runtime.ts +9 -0
- package/src/input/commands/operator-runtime.ts +10 -12
- package/src/input/commands/permissions-provenance.ts +3 -3
- package/src/input/commands/planning-runtime.ts +7 -7
- package/src/input/commands/platform-sandbox-runtime.ts +2 -2
- package/src/input/commands/platform-services-runtime.ts +1 -1
- package/src/input/commands/policy-dispatch.ts +2 -2
- package/src/input/commands/policy.ts +3 -3
- package/src/input/commands/provider.ts +1 -1
- package/src/input/commands/remote-runtime.ts +1 -1
- package/src/input/commands/review-runtime.ts +39 -94
- package/src/input/commands/rewind-runtime.ts +81 -108
- package/src/input/commands/runtime-services.ts +15 -17
- package/src/input/commands/services-runtime.ts +2 -2
- package/src/input/commands/session-content.ts +21 -5
- package/src/input/commands/session-workflow.ts +13 -38
- package/src/input/commands/settings-sync-runtime.ts +2 -2
- package/src/input/commands/shell-core.ts +19 -4
- package/src/input/commands/skills-runtime.ts +2 -2
- package/src/input/commands/status-runtime.ts +13 -0
- package/src/input/commands/subscription-runtime.ts +1 -1
- package/src/input/commands/tasks-runtime.ts +2 -8
- package/src/input/commands/work-plan-runtime.ts +4 -4
- package/src/input/commands/workstream-attempts.ts +24 -47
- package/src/input/commands/workstream-runtime.ts +2 -2
- package/src/input/commands/worktree-runtime.ts +3 -3
- package/src/input/commands.ts +3 -1
- package/src/input/composer-editor.ts +44 -0
- package/src/input/concealed-input.ts +1 -1
- package/src/input/config-modal-types.ts +20 -8
- package/src/input/config-modal.ts +106 -105
- package/src/input/confirm-dialog-types.ts +28 -0
- package/src/input/confirm-dialog.ts +70 -0
- package/src/input/delete-key-policy.ts +3 -3
- package/src/input/feed-context-factory.ts +15 -16
- package/src/input/handler-command-route.ts +7 -42
- package/src/input/handler-content-actions.ts +16 -15
- package/src/input/handler-feed-routes.ts +26 -211
- package/src/input/handler-feed.ts +68 -95
- package/src/input/handler-interactions.ts +5 -3
- package/src/input/handler-modal-routes.ts +215 -216
- package/src/input/handler-modal-stack.ts +81 -11
- package/src/input/handler-modal-token-routes.ts +4 -0
- package/src/input/handler-onboarding.ts +0 -1
- package/src/input/handler-picker-routes.ts +65 -107
- package/src/input/handler-session-view-route.ts +149 -0
- package/src/input/handler-shortcuts.ts +16 -154
- package/src/input/handler-types.ts +4 -2
- package/src/input/handler-ui-state.ts +45 -15
- package/src/input/handler-work-tree-route.ts +123 -0
- package/src/input/handler.ts +25 -70
- package/src/input/keybindings.ts +16 -71
- package/src/input/masked-entry-modal.ts +117 -0
- package/src/input/mcp-workspace.ts +48 -17
- package/src/input/model-picker-filter.ts +8 -0
- package/src/input/model-picker-open.ts +99 -0
- package/src/input/model-picker-types.ts +1 -1
- package/src/input/model-picker.ts +92 -9
- package/src/input/notifications-modal.ts +123 -0
- package/src/input/overlay-filter.ts +26 -0
- package/src/input/profile-picker-modal.ts +37 -8
- package/src/input/search.ts +3 -3
- package/src/input/selection-modal-queue.ts +2 -0
- package/src/input/selection-modal.ts +28 -16
- package/src/input/session-picker-modal.ts +33 -8
- package/src/input/settings-modal-activation.ts +7 -2
- package/src/input/settings-modal-data.ts +11 -6
- package/src/input/settings-modal-types.ts +1 -1
- package/src/input/settings-modal.ts +20 -20
- package/src/input/submission-intent.ts +1 -1
- package/src/input/submission-router.ts +4 -9
- package/src/input/surface-modal-host.ts +110 -0
- package/src/input/theme-settings-actions.ts +82 -0
- package/src/input/usage-modal.ts +183 -0
- package/src/input/views.ts +97 -0
- package/src/main.ts +175 -165
- package/src/permissions/hunk-selection.ts +1 -1
- package/src/permissions/prompt-card.ts +511 -0
- package/src/permissions/prompt.ts +59 -622
- package/src/renderer/agents-modal.ts +310 -0
- package/src/renderer/autocomplete-overlay.ts +42 -220
- package/src/renderer/back-to-bottom.ts +80 -0
- package/src/renderer/block-actions-overlay.ts +30 -48
- package/src/renderer/bookmark-modal.ts +48 -79
- package/src/renderer/changes-modal.ts +325 -0
- package/src/renderer/code-block.ts +184 -106
- package/src/renderer/command-palette.ts +93 -0
- package/src/renderer/composer-fragments.ts +4 -4
- package/src/renderer/composer.ts +146 -0
- package/src/renderer/compositor.ts +26 -160
- package/src/renderer/config-modal.ts +185 -81
- package/src/renderer/confirm-dialog.ts +50 -0
- package/src/renderer/context-inspector.ts +116 -154
- package/src/renderer/context-status-hint.ts +4 -4
- package/src/renderer/conversation-layout.ts +20 -0
- package/src/renderer/conversation-overlays.ts +94 -84
- package/src/renderer/conversation-surface.ts +19 -38
- package/src/renderer/diff-tint.ts +98 -0
- package/src/renderer/file-picker-overlay.ts +63 -90
- package/src/renderer/footer-targets.ts +38 -0
- package/src/renderer/git-status.ts +3 -4
- package/src/renderer/header-line.ts +140 -117
- package/src/renderer/help-overlay.ts +133 -219
- package/src/renderer/history-search-overlay.ts +15 -12
- package/src/renderer/lane-graph/bead.ts +800 -0
- package/src/renderer/lane-graph/glyphs.ts +134 -0
- package/src/renderer/lane-graph/layout.ts +248 -0
- package/src/renderer/lane-graph/paint.ts +537 -0
- package/src/renderer/lane-graph/semantic-memo.ts +77 -0
- package/src/renderer/layout-engine.ts +2 -57
- package/src/renderer/layout.ts +7 -13
- package/src/renderer/markdown-inline.ts +2 -1
- package/src/renderer/markdown-table.ts +17 -12
- package/src/renderer/markdown.ts +92 -34
- package/src/renderer/masked-entry-modal.ts +78 -0
- package/src/renderer/mcp-workspace.ts +166 -203
- package/src/renderer/model-workspace.ts +381 -436
- package/src/renderer/notifications-modal.ts +116 -0
- package/src/renderer/onboarding/onboarding-wizard.ts +178 -588
- package/src/renderer/process-view.ts +192 -0
- package/src/renderer/profile-picker-modal.ts +58 -110
- package/src/renderer/search-overlay.ts +6 -3
- package/src/renderer/selection-modal-overlay.ts +87 -327
- package/src/renderer/semantic-diff.ts +2 -2
- package/src/renderer/session-chips.ts +102 -0
- package/src/renderer/session-picker-modal.ts +177 -297
- package/src/renderer/settings-modal-connections.ts +14 -23
- package/src/renderer/settings-modal-context.ts +367 -0
- package/src/renderer/settings-modal-helpers.ts +6 -11
- package/src/renderer/settings-modal.ts +322 -726
- package/src/renderer/shell-surface.ts +277 -175
- package/src/renderer/shortcuts-overlay.ts +217 -0
- package/src/renderer/status-line.ts +475 -0
- package/src/renderer/surface-compose.ts +174 -0
- package/src/renderer/surface-kit-extra.ts +303 -0
- package/src/renderer/surface-kit-list.ts +366 -0
- package/src/renderer/surface-kit-parts.ts +360 -0
- package/src/renderer/surface-kit.ts +568 -0
- package/src/renderer/syntax-highlighter.ts +280 -197
- package/src/renderer/syntax-theme.ts +51 -0
- package/src/renderer/system-message.ts +0 -1
- package/src/renderer/term-caps.ts +42 -1
- package/src/renderer/terminal-bg-probe.ts +116 -19
- package/src/renderer/terminal-palette-probe.ts +322 -0
- package/src/renderer/terminal-palette-reader.ts +183 -0
- package/src/renderer/terminal-palette.ts +58 -0
- package/src/renderer/theme-mode-config.ts +16 -1
- package/src/renderer/theme.ts +234 -207
- package/src/renderer/thinking.ts +0 -1
- package/src/renderer/throbber.ts +188 -0
- package/src/renderer/toast-center.ts +119 -0
- package/src/renderer/ui-factory.ts +39 -602
- package/src/renderer/ui-primitives.ts +8 -25
- package/src/renderer/usage-modal.ts +353 -0
- package/src/renderer/user-message.ts +58 -0
- package/src/renderer/voice-capture-chip.ts +53 -0
- package/src/runtime/bootstrap-command-context.ts +0 -5
- package/src/runtime/bootstrap-command-parts.ts +38 -89
- package/src/runtime/bootstrap-core.ts +13 -15
- package/src/runtime/bootstrap-hook-bridge.ts +12 -21
- package/src/runtime/bootstrap-notifier-sync.ts +17 -1
- package/src/runtime/bootstrap-shell.ts +16 -50
- package/src/runtime/bootstrap.ts +14 -14
- package/src/runtime/client/fleet-union.ts +5 -5
- package/src/runtime/client/hosted-exit.ts +2 -2
- package/src/runtime/client/hosted-sessions.ts +1 -1
- package/src/runtime/client/spine-adoption.ts +1 -1
- package/src/runtime/context-accounting-source.ts +5 -4
- package/src/runtime/index.ts +1 -0
- package/src/runtime/notification-dispatch.ts +102 -29
- package/src/runtime/recovery-offer-wiring.ts +4 -1
- package/src/runtime/recovery-prompt.ts +31 -15
- package/src/runtime/runtime-services-types.ts +10 -6
- package/src/runtime/services.ts +17 -12
- package/src/runtime/session-continuity-hints.ts +2 -5
- package/src/runtime/session-inbound-inputs.ts +1 -1
- package/src/runtime/session-resume-liveness-confirm.ts +14 -2
- package/src/runtime/startup-typeahead-gate.ts +103 -0
- package/src/runtime/store/domains/domain-read-matrix.ts +0 -1
- package/src/runtime/store/domains/index.ts +0 -8
- package/src/runtime/store/selectors/index.ts +0 -28
- package/src/runtime/store/state.ts +0 -8
- package/src/runtime/ui-services.ts +4 -6
- package/src/runtime/usage-tracker.ts +348 -0
- package/src/runtime/wrfc-persistence.ts +4 -4
- package/src/shell/blocking-input.ts +92 -2
- package/src/shell/recovery-input-helpers.ts +1 -1
- package/src/shell/session-views.ts +539 -0
- package/src/shell/status-report.ts +86 -0
- package/src/shell/transcript-scroll.ts +68 -0
- package/src/shell/ui-openers.ts +84 -172
- package/src/shell/view-openers.ts +205 -0
- package/src/tools/wrfc-agent-guard.ts +22 -2
- package/src/utils/format-duration.ts +4 -8
- package/src/utils/splash-lines.ts +9 -1
- package/src/utils/terminal-width.ts +56 -0
- package/src/verification/live-verifier.ts +0 -10
- package/src/version.ts +1 -1
- package/src/{panels → views}/agent-inspector-shared.ts +2 -2
- package/src/{panels → views}/builtin-modals.ts +22 -21
- package/src/views/builtin-views.ts +135 -0
- package/src/{panels → views}/confirm-state.ts +9 -9
- package/src/{panels → views}/diff-review-model.ts +10 -3
- package/src/{panels → views}/eval-registry.ts +1 -1
- package/src/{panels → views}/fleet-acts.ts +49 -85
- package/src/{panels/fleet-panel-format.ts → views/fleet-format.ts} +40 -40
- package/src/{panels → views}/fleet-gateway.ts +5 -5
- package/src/{panels → views}/fleet-observed-render.ts +16 -16
- package/src/{panels → views}/fleet-read-model.ts +9 -9
- package/src/{panels/fleet-tabs.ts → views/fleet-session-tabs.ts} +13 -13
- package/src/{panels → views}/fleet-spawn.ts +33 -49
- package/src/{panels → views}/fleet-steer.ts +12 -12
- package/src/{panels → views}/fleet-stop.ts +4 -4
- package/src/{panels → views}/fleet-transcript.ts +26 -27
- package/src/{panels/fleet-panel-worktree-detail.ts → views/fleet-worktree-detail.ts} +7 -7
- package/src/{panels → views}/hosted-session-feed.ts +6 -6
- package/src/views/modal-surface-registry.ts +41 -0
- package/src/{panels → views}/modals/devices-modal.ts +2 -2
- package/src/{panels → views}/modals/hooks-modal.ts +13 -13
- package/src/{panels → views}/modals/keybindings-modal.ts +19 -27
- package/src/{panels → views}/modals/knowledge-modal.ts +6 -5
- package/src/{panels → views}/modals/local-auth-modal.ts +22 -21
- package/src/{panels → views}/modals/marketplace-modal.ts +11 -11
- package/src/{panels → views}/modals/memory-modal.ts +8 -8
- package/src/{panels → views}/modals/modal-surface-helpers.ts +15 -5
- package/src/{panels → views}/modals/pairing-modal.ts +9 -9
- package/src/{panels → views}/modals/planning-modal.ts +15 -20
- package/src/{panels → views}/modals/plugins-modal.ts +6 -6
- package/src/{panels → views}/modals/policy-modal.ts +13 -5
- package/src/{panels → views}/modals/provider-health-modal.ts +4 -4
- package/src/{panels → views}/modals/remote-modal.ts +3 -3
- package/src/{panels → views}/modals/sandbox-modal.ts +4 -4
- package/src/{panels → views}/modals/security-modal.ts +22 -16
- package/src/{panels → views}/modals/services-modal.ts +3 -3
- package/src/{panels → views}/modals/settings-sync-modal.ts +4 -4
- package/src/{panels → views}/modals/skills-modal.ts +9 -9
- package/src/{panels → views}/modals/subscription-modal.ts +3 -3
- package/src/{panels → views}/modals/work-plan-modal.ts +10 -13
- package/src/views/notifications-feed.ts +314 -0
- package/src/{panels → views}/polish-core.ts +38 -36
- package/src/{panels → views}/polish-tables.ts +35 -26
- package/src/{panels → views}/polish.ts +101 -95
- package/src/{panels → views}/project-planning-answer-actions.ts +3 -3
- package/src/{panels → views}/provider-health-routes.ts +14 -14
- package/src/{panels → views}/search-focus.ts +8 -8
- package/src/{panels → views}/session-maintenance.ts +11 -11
- package/src/views/skills-discovery.ts +159 -0
- package/src/views/view-deps.ts +80 -0
- package/src/views/view-panel-adapter.ts +53 -0
- package/src/{panels → views}/workstream-graph-render.ts +1 -1
- package/src/core/conversation-fold.ts +0 -101
- package/src/core/conversation-turn-structure.ts +0 -464
- package/src/core/conversation-user-receipts.ts +0 -42
- package/src/input/commands/operator-panel-runtime.ts +0 -186
- package/src/input/panel-integration-actions.ts +0 -33
- package/src/input/panel-mouse-geometry.ts +0 -97
- package/src/input/panel-paste-flood-guard.ts +0 -86
- package/src/panels/base-panel.ts +0 -301
- package/src/panels/builtin/agent.ts +0 -27
- package/src/panels/builtin/development.ts +0 -92
- package/src/panels/builtin/knowledge.ts +0 -12
- package/src/panels/builtin/operations.ts +0 -177
- package/src/panels/builtin/session.ts +0 -81
- package/src/panels/builtin/shared.ts +0 -357
- package/src/panels/builtin-panels.ts +0 -28
- package/src/panels/cost-tracker-panel.ts +0 -746
- package/src/panels/diff-panel.ts +0 -797
- package/src/panels/diff-review-panel.ts +0 -395
- package/src/panels/expandable-list-panel.ts +0 -189
- package/src/panels/fleet-deep-link.ts +0 -31
- package/src/panels/fleet-panel.ts +0 -799
- package/src/panels/git-panel.ts +0 -800
- package/src/panels/hosted-session-panel.ts +0 -221
- package/src/panels/index.ts +0 -21
- package/src/panels/local-auth-panel.ts +0 -478
- package/src/panels/notifications-feed.ts +0 -127
- package/src/panels/notifications-panel.ts +0 -160
- package/src/panels/panel-confirm-overlay.ts +0 -72
- package/src/panels/panel-manager.ts +0 -791
- package/src/panels/plugins-panel.ts +0 -371
- package/src/panels/scrollable-list-panel.ts +0 -498
- package/src/panels/skills-panel.ts +0 -454
- package/src/panels/token-budget-panel.ts +0 -688
- package/src/panels/types.ts +0 -191
- package/src/panels/wrfc-panel-format.ts +0 -133
- package/src/renderer/diff-view.ts +0 -134
- package/src/renderer/fleet-tab-strip.ts +0 -56
- package/src/renderer/footer-tips.ts +0 -53
- package/src/renderer/fullscreen-primitives.ts +0 -146
- package/src/renderer/fullscreen-workspace.ts +0 -194
- package/src/renderer/hint-grammar.ts +0 -52
- package/src/renderer/modal-factory.ts +0 -480
- package/src/renderer/overlay-box.ts +0 -154
- package/src/renderer/overlay-viewport.ts +0 -104
- package/src/renderer/panel-composite.ts +0 -145
- package/src/renderer/panel-workspace-bar.ts +0 -54
- package/src/renderer/process-indicator.ts +0 -163
- package/src/renderer/tab-strip.ts +0 -222
- package/src/renderer/text-layout.ts +0 -31
- package/src/renderer/tool-call.ts +0 -276
- package/src/renderer/tool-result-expanded-lines.ts +0 -48
- package/src/renderer/tool-result-summary.ts +0 -219
- package/src/runtime/diagnostics/panels/index.ts +0 -21
- package/src/runtime/diagnostics/panels/ops.ts +0 -156
- package/src/runtime/perf/panel-contracts.ts +0 -32
- package/src/runtime/store/domains/panels.ts +0 -117
- package/src/verification/verification-ledger.ts +0 -707
- /package/src/{panels → views}/memory-consolidation-gateway.ts +0 -0
- /package/src/{panels → views}/modals/modal-theme.ts +0 -0
- /package/src/{panels → views}/provider-health-domains.ts +0 -0
|
@@ -1,707 +0,0 @@
|
|
|
1
|
-
import { readFileSync, readdirSync } from 'node:fs';
|
|
2
|
-
import { join } from 'node:path';
|
|
3
|
-
import { CONFIG_SCHEMA } from '@pellux/goodvibes-sdk/platform/config';
|
|
4
|
-
import { FEATURE_SETTINGS } from '@pellux/goodvibes-sdk/platform/runtime/state';
|
|
5
|
-
import { featureEnablementWrite, GOODVIBES_CLI_CATALOG } from '@pellux/goodvibes-terminal-shell';
|
|
6
|
-
import { CommandRegistry } from '../input/command-registry.ts';
|
|
7
|
-
import { registerBuiltinCommands } from '../input/commands.ts';
|
|
8
|
-
|
|
9
|
-
export interface VerificationLedgerArea {
|
|
10
|
-
readonly area: string;
|
|
11
|
-
readonly total: number;
|
|
12
|
-
readonly localSignalVerified: number;
|
|
13
|
-
readonly localBehaviorVerified: number;
|
|
14
|
-
readonly externalOutcomeRequired: number;
|
|
15
|
-
readonly notes: string;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export interface VerificationLedger {
|
|
19
|
-
readonly generatedAt: string;
|
|
20
|
-
readonly areas: readonly VerificationLedgerArea[];
|
|
21
|
-
readonly totals: {
|
|
22
|
-
readonly total: number;
|
|
23
|
-
readonly localSignalVerified: number;
|
|
24
|
-
readonly localBehaviorVerified: number;
|
|
25
|
-
readonly externalOutcomeRequired: number;
|
|
26
|
-
readonly localSignalPercent: number;
|
|
27
|
-
readonly localBehaviorPercent: number;
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Baseline count of `Settings schema and persistence` items with real local
|
|
33
|
-
* behavior verification, as measured when this ledger was first authored. New
|
|
34
|
-
* schema keys added since then are accounted for explicitly (see
|
|
35
|
-
* FEATURE_KNOB_LOCAL_SETTINGS) rather than folded into this number, so the
|
|
36
|
-
* baseline stays an auditable fixed point.
|
|
37
|
-
*/
|
|
38
|
-
const SETTINGS_BEHAVIOR_BASELINE = 184;
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Config keys promoted into CONFIG_SCHEMA for the flag-gated feature knobs
|
|
42
|
-
* (SDK commit f5c4af31, "config: add schema keys for flag-gated feature
|
|
43
|
-
* knobs"). Adding these 28 keys raised the settings inventory `total` without a
|
|
44
|
-
* matching rise in behavior-verified coverage, which dropped
|
|
45
|
-
* `localBehaviorPercent` below its floor. Each key is a local, non-external
|
|
46
|
-
* setting whose full persistence behavior, schema default, set → write →
|
|
47
|
-
* reload round-trip, and reset-to-default, is exercised by
|
|
48
|
-
* `src/test/verification/feature-knob-settings-persistence.test.ts`. They are
|
|
49
|
-
* therefore genuinely behavior-verified locally and counted as such here.
|
|
50
|
-
*/
|
|
51
|
-
/**
|
|
52
|
-
* The daemon's own mailbox and calendar keys (`surfaces.email.*`,
|
|
53
|
-
* `surfaces.calendar.*`), promoted into CONFIG_SCHEMA so the settings modal,
|
|
54
|
-
* which renders from that schema, can actually show them. Before, the
|
|
55
|
-
* daemon's handlers named these keys in their own error messages
|
|
56
|
-
* ("Set surfaces.calendar.caldavUrl and surfaces.calendar.caldavUser") while
|
|
57
|
-
* the UI that told an operator to set them could not display one of them.
|
|
58
|
-
*
|
|
59
|
-
* Declaring 25 keys raised the settings inventory `total` with no matching
|
|
60
|
-
* behavior coverage, which dropped `localBehaviorPercent` below its floor,
|
|
61
|
-
* the same arrival shape as the two lists above.
|
|
62
|
-
*
|
|
63
|
-
* THIS CONSTANT IS NOT A DIAL. Every key below is counted because
|
|
64
|
-
* `src/test/verification/daemon-mailbox-settings-persistence.test.ts` runs the
|
|
65
|
-
* same four-part persistence contract the other counted sets are counted for:
|
|
66
|
-
* schema default exposure, `set()` through the key's own validator to disk,
|
|
67
|
-
* reload into a fresh ConfigManager with read-back equality, and
|
|
68
|
-
* reset-to-default that also survives reload. That test also asserts this list
|
|
69
|
-
* is exactly the `surfaces.email.*` + `surfaces.calendar.*` schema key set and
|
|
70
|
-
* overlaps neither other counted set, so nothing is double-counted and nothing
|
|
71
|
-
* drifts in uncounted.
|
|
72
|
-
*
|
|
73
|
-
* PER-KEY EVIDENCE. All 42 are read by a LIVE consumer, which is why they were
|
|
74
|
-
* declared at all: the SDK's mail and calendar gateway compositions
|
|
75
|
-
* (platform/email/surface-config.ts and platform/calendar/caldav-gateway-config.ts)
|
|
76
|
-
* resolve every one of them when the daemon serves `email.*` and `calendar.*`,
|
|
77
|
-
* and the `surfaces.email.inbound.*` block is read by the daemon's inbound mail
|
|
78
|
-
* reader, the poller/IDLE path that makes incoming mail visible at all.
|
|
79
|
-
* The five password keys (email.password, email.imapPassword,
|
|
80
|
-
* email.imap.password, email.smtp.password, calendar.caldavPassword)
|
|
81
|
-
* additionally resolve through the daemon secret tier rather than from config,
|
|
82
|
-
* and carry no secret value in config themselves. That is now enforced on the
|
|
83
|
-
* write side too: all five are in `config/secret-config.ts`'s
|
|
84
|
-
* SECRET_CONFIG_KEYS, so the settings modal and `/config set` route an entered
|
|
85
|
-
* value into the secret store and leave only a `goodvibes://` reference in
|
|
86
|
-
* config, rather than writing the password itself into a settings file.
|
|
87
|
-
*/
|
|
88
|
-
export const DAEMON_MAILBOX_LOCAL_SETTINGS = [
|
|
89
|
-
'surfaces.email.host',
|
|
90
|
-
'surfaces.email.user',
|
|
91
|
-
'surfaces.email.username',
|
|
92
|
-
'surfaces.email.from',
|
|
93
|
-
'surfaces.email.password',
|
|
94
|
-
'surfaces.email.imapHost',
|
|
95
|
-
'surfaces.email.imapPort',
|
|
96
|
-
'surfaces.email.imapUser',
|
|
97
|
-
'surfaces.email.imapPassword',
|
|
98
|
-
'surfaces.email.imap.host',
|
|
99
|
-
'surfaces.email.imap.port',
|
|
100
|
-
'surfaces.email.imap.user',
|
|
101
|
-
'surfaces.email.imap.password',
|
|
102
|
-
'surfaces.email.imap.secure',
|
|
103
|
-
'surfaces.email.imap.mailbox',
|
|
104
|
-
'surfaces.email.imap.draftsMailbox',
|
|
105
|
-
'surfaces.email.smtp.host',
|
|
106
|
-
'surfaces.email.smtp.port',
|
|
107
|
-
'surfaces.email.smtp.password',
|
|
108
|
-
'surfaces.email.smtp.secure',
|
|
109
|
-
// Inbound mail, the poller/IDLE reader the daemon runs to actually READ mail,
|
|
110
|
-
// which arrived with the platform runtime. These are counted for exactly the
|
|
111
|
-
// reason the keys above are: the same four-part persistence contract runs over
|
|
112
|
-
// every one of them in
|
|
113
|
-
// src/test/verification/daemon-mailbox-settings-persistence.test.ts, and the
|
|
114
|
-
// list is asserted there to be the complete surfaces.email.*/surfaces.calendar.*
|
|
115
|
-
// schema set. Arriving uncounted is what dropped localBehaviorPercent through
|
|
116
|
-
// its floor when the schema grew.
|
|
117
|
-
'surfaces.email.inbound.enabled',
|
|
118
|
-
'surfaces.email.inbound.accounts',
|
|
119
|
-
'surfaces.email.inbound.source',
|
|
120
|
-
'surfaces.email.inbound.gmailPollSecondsExpecting',
|
|
121
|
-
'surfaces.email.inbound.gmailPollSecondsIdle',
|
|
122
|
-
'surfaces.email.inbound.mode',
|
|
123
|
-
'surfaces.email.inbound.pollIntervalSeconds',
|
|
124
|
-
'surfaces.email.inbound.idleReissueMinutes',
|
|
125
|
-
'surfaces.email.inbound.reconnect.maxBackoffSeconds',
|
|
126
|
-
'surfaces.email.inbound.notice.route',
|
|
127
|
-
'surfaces.email.inbound.notice.mode',
|
|
128
|
-
'surfaces.email.inbound.expectationWindowMinutes',
|
|
129
|
-
'surfaces.email.inbound.dedupTtlMinutes',
|
|
130
|
-
'surfaces.email.inbound.retentionDays',
|
|
131
|
-
'surfaces.email.inbound.maxRecords',
|
|
132
|
-
'surfaces.email.inbound.capabilityRecheckMinutes',
|
|
133
|
-
'surfaces.email.inbound.onInsufficientCapability',
|
|
134
|
-
'surfaces.calendar.caldavUrl',
|
|
135
|
-
'surfaces.calendar.caldavUser',
|
|
136
|
-
'surfaces.calendar.caldavPassword',
|
|
137
|
-
'surfaces.calendar.defaultCalendarId',
|
|
138
|
-
'surfaces.calendar.calendars',
|
|
139
|
-
] as const;
|
|
140
|
-
|
|
141
|
-
export const FEATURE_KNOB_LOCAL_SETTINGS = [
|
|
142
|
-
'provider.optimizerMode',
|
|
143
|
-
'provider.optimizerPinnedModel',
|
|
144
|
-
'permissions.divergenceThreshold',
|
|
145
|
-
'permissions.maxDivergenceRecords',
|
|
146
|
-
'tools.overflowSpillBackend',
|
|
147
|
-
'notifications.burstWindowMs',
|
|
148
|
-
'notifications.burstThreshold',
|
|
149
|
-
'notifications.burstCooldownMs',
|
|
150
|
-
'fetch.sanitizeMode',
|
|
151
|
-
'fetch.trustedHosts',
|
|
152
|
-
'fetch.blockedHosts',
|
|
153
|
-
'security.tokenAudit.rotationCadenceDays',
|
|
154
|
-
'security.tokenAudit.rotationWarningDays',
|
|
155
|
-
'security.tokenAudit.managed',
|
|
156
|
-
'integrations.delivery.maxRetries',
|
|
157
|
-
'integrations.delivery.initialDelayMs',
|
|
158
|
-
'integrations.delivery.maxDelayMs',
|
|
159
|
-
'integrations.delivery.maxDlqSize',
|
|
160
|
-
'integrations.delivery.sloEnforced',
|
|
161
|
-
'policy.bundleSource',
|
|
162
|
-
'policy.bundlePath',
|
|
163
|
-
'agents.passiveInjection.budgetTokens',
|
|
164
|
-
'agents.passiveInjection.relevanceFloor',
|
|
165
|
-
'agents.passiveInjection.codeLimit',
|
|
166
|
-
'agents.contextCompactThreshold',
|
|
167
|
-
'runtime.toolBudget.maxMs',
|
|
168
|
-
'runtime.toolBudget.maxTokens',
|
|
169
|
-
'runtime.toolBudget.maxCostUsd',
|
|
170
|
-
] as const;
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* Config keys added by the paired-device and trigger-family domains in SDK
|
|
174
|
-
* 1.14.0. Like FEATURE_KNOB_LOCAL_SETTINGS above, these arrived as new
|
|
175
|
-
* CONFIG_SCHEMA entries that raised the settings inventory `total` with no
|
|
176
|
-
* matching behavior coverage, dropping `localBehaviorPercent` below its floor.
|
|
177
|
-
*
|
|
178
|
-
* THIS CONSTANT IS NOT A DIAL. Each key below is counted because a test that
|
|
179
|
-
* exercises it was actually written:
|
|
180
|
-
* `src/test/verification/device-and-trigger-settings-persistence.test.ts` runs,
|
|
181
|
-
* for every key in this list, the same four-part persistence contract the
|
|
182
|
-
* feature-knob keys are counted for, schema default exposure, `set()` through
|
|
183
|
-
* the key's own validator to disk, reload into a fresh ConfigManager with
|
|
184
|
-
* read-back equality, and reset-to-default that also survives reload. That test
|
|
185
|
-
* additionally asserts this list is exactly the non-enablement key set of both
|
|
186
|
-
* domains and overlaps neither of the other counted sets, so nothing here is
|
|
187
|
-
* double-counted and nothing drifts in uncounted.
|
|
188
|
-
*
|
|
189
|
-
* PER-KEY EVIDENCE, what is verified, and how live the key is TODAY.
|
|
190
|
-
* "persistence" below means the four-part contract above; the second column
|
|
191
|
-
* records whether anything in this tree (TUI or the pinned SDK) reads the key,
|
|
192
|
-
* audited by tracing each key to its consumers.
|
|
193
|
-
*
|
|
194
|
-
* watchers.triggers.backoffLadderMs persistence · live (trigger supervisor retry ladder)
|
|
195
|
-
* watchers.triggers.breakerStrikes persistence · live (strike breaker)
|
|
196
|
-
* watchers.triggers.defaultCheckIntervalMs persistence · live (condition-check scheduler)
|
|
197
|
-
* watchers.triggers.probeTimeoutMs persistence · live (probe execution)
|
|
198
|
-
* watchers.triggers.maxConcurrentChecks persistence · live (check concurrency cap)
|
|
199
|
-
* watchers.triggers.observationRingSize persistence · live (observation ring)
|
|
200
|
-
* watchers.triggers.runHistoryLimit persistence · live (run history retention)
|
|
201
|
-
* watchers.triggers.runHistoryTtlHours persistence · live (run history sweep)
|
|
202
|
-
* watchers.triggers.eventLogLimit persistence · live (event log retention)
|
|
203
|
-
* watchers.triggers.eventLogTtlHours persistence · live (event log sweep)
|
|
204
|
-
* watchers.triggers.sweepIntervalMs persistence · live (housekeeping cadence)
|
|
205
|
-
* watchers.triggers.supervisionTickMs persistence · live (supervision loop tick)
|
|
206
|
-
* watchers.triggers.streamQueueLimit persistence · live (stream watcher queue)
|
|
207
|
-
* watchers.triggers.streamBatchLines persistence · live (stream batching)
|
|
208
|
-
* watchers.triggers.streamBatchIntervalMs persistence · live (stream batching)
|
|
209
|
-
* watchers.triggers.onExitMaxDurationMs persistence · live (on-exit trigger duration cap)
|
|
210
|
-
* watchers.triggers.onExitStdin persistence · live (on-exit stdin posture)
|
|
211
|
-
* watchers.triggers.outputTailBytes persistence · live (captured output tail)
|
|
212
|
-
* device.capabilities.allowAlwaysOffer persistence · behavior (durable-grant offer by sensitivity)
|
|
213
|
-
* device.capabilities.requestTimeoutSeconds persistence · behavior (dispatch, wire payload and prompt deadline)
|
|
214
|
-
* device.location.precision persistence · behavior (precise fix refused / never granted)
|
|
215
|
-
* device.clipboard.readMode persistence · behavior (clipboard read refused / never granted)
|
|
216
|
-
* device.capture.retentionHours persistence · behavior (capture TTL, swept off disk at expiry)
|
|
217
|
-
* device.capture.maxArtifacts persistence · behavior (capture count cap at the sweep)
|
|
218
|
-
* device.capture.sweepIntervalMinutes persistence · behavior (period of the sweep that reaps)
|
|
219
|
-
* device.grants.expiryDays persistence · behavior (grant TTL, then asks again)
|
|
220
|
-
* device.grants.maxPerNode persistence · behavior (per-node grant cap at the sweep)
|
|
221
|
-
* device.grants.auditRetentionDays persistence · behavior (grant ledger retention)
|
|
222
|
-
* device.nodes.maxPaired persistence · live (enforced at the pairing path)
|
|
223
|
-
*
|
|
224
|
-
* On `device.nodes.maxPaired`: the SDK enforces it where a device pairs,
|
|
225
|
-
* PairingTokenManager.mint refuses a NEW node at the cap with
|
|
226
|
-
* PairingLimitReachedError (code DEVICE_NODES_MAX_PAIRED, carrying the setting
|
|
227
|
-
* name, the cap and the live count), mapped to HTTP 409 by the pairing and
|
|
228
|
-
* pairing-handoff routes. An already-paired node supersedes its own record
|
|
229
|
-
* instead of being refused, migration mints off the legacy shared token are
|
|
230
|
-
* deliberately exempt, lowering the cap unpairs nobody, and a non-positive or
|
|
231
|
-
* non-finite value reads as no cap so a broken setting cannot lock the owner
|
|
232
|
-
* out. The cap is read per mint, so a change applies without a restart. What is
|
|
233
|
-
* counted HERE is still only the persistence contract this repo's test
|
|
234
|
-
* exercises, the enforcement itself is SDK-side and SDK-tested, and is recorded
|
|
235
|
-
* in this column so the "how live is it" audit stays accurate, not to claim
|
|
236
|
-
* coverage this repo did not write.
|
|
237
|
-
*
|
|
238
|
-
* On the other ten `device.*` rows: they are live now. This app composes the
|
|
239
|
-
* platform's device posture runtime (src/runtime/device-posture-composition.ts)
|
|
240
|
-
* on the same distributed runtime phones pair onto and the same approval broker
|
|
241
|
-
* every other confirmation rides, registers the `phone` tool on it, and binds the
|
|
242
|
-
* devices.* verbs to it, so each of these keys is read, per request and per
|
|
243
|
-
* sweep, by the DeviceCapabilityService / DeviceGrantStore /
|
|
244
|
-
* DeviceCaptureArtifactStore / DeviceHousekeeper that serve them. They were dark
|
|
245
|
-
* before that: the policy struct carried matching defaults and named the keys in
|
|
246
|
-
* its refusal messages, but nothing mapped configuration into it in either tree.
|
|
247
|
-
* The mapping now lives in the SDK, so every daemon host honours it rather than
|
|
248
|
-
* only whichever consumer had written its own.
|
|
249
|
-
*
|
|
250
|
-
* The second column above is upgraded to "behavior" on the strength of
|
|
251
|
-
* `src/test/verification/device-posture-behavior.test.ts`, which drives THIS
|
|
252
|
-
* app's composition with a real ConfigManager over a temp home and the platform's
|
|
253
|
-
* real stores, stubs only the peer transport and the approval bridge, and asserts
|
|
254
|
-
* per key at two values that the observable outcome differs, refusal code, how
|
|
255
|
-
* authority was established, what reached the transport, what the prompt was
|
|
256
|
-
* given, and what survives on disk after a sweep. It also invokes the `phone`
|
|
257
|
-
* tool and the devices.* verbs off the composed runtime graph, because a mapping
|
|
258
|
-
* nothing composes is the same defect in a different place.
|
|
259
|
-
*
|
|
260
|
-
* STILL NOT COUNTED, FOR A DIFFERENT REASON NOW: the 24 non-enablement
|
|
261
|
-
* `voice.wake.*` keys from the same release. When this list was written they were
|
|
262
|
-
* excluded because nothing captured audio at all. That is no longer true, this
|
|
263
|
-
* terminal opens a recorder subprocess (src/audio/capture.ts), runs the SDK
|
|
264
|
-
* detector over it through onnxruntime-web (src/audio/wake-inference.ts), and
|
|
265
|
-
* hands both a confirmed wake's utterance and a push-to-talk recording to the
|
|
266
|
-
* daemon's `voice.stt` verb. Every one of those rows is read by
|
|
267
|
-
* resolveWakeRuntimeSettings and reaches this surface's runtime.
|
|
268
|
-
*
|
|
269
|
-
* They stay out of the NUMERATOR here because this constant counts exactly one
|
|
270
|
-
* thing, keys whose four-part PERSISTENCE contract is exercised by
|
|
271
|
-
* device-and-trigger-settings-persistence.test.ts, and that test does not cover
|
|
272
|
-
* them. The behaviour they now drive is covered instead by the capture and wake
|
|
273
|
-
* tests under src/test/audio/, which assert the frame path, the detection
|
|
274
|
-
* chain, the disabled-means-no-capture rule, the supervisor's restart and latch,
|
|
275
|
-
* and the recorder argv. Counting them in both places would double-count; adding
|
|
276
|
-
* them here without writing their persistence round-trip would overclaim. So the
|
|
277
|
-
* number this list raises coverage by is unchanged, and the reason it excludes
|
|
278
|
-
* them is recorded above rather than left reading as "the feature does nothing".
|
|
279
|
-
*
|
|
280
|
-
* Every wake row is now in force on this surface, with one condition stated at
|
|
281
|
-
* every surfacing: `voice.wake.vadThreshold` above 0 needs the speech gate's own
|
|
282
|
-
* pinned artifact provisioned (`/voice wake setup` fetches it with the models),
|
|
283
|
-
* and until it is, startup BLOCKS with that reason rather than scoring frames
|
|
284
|
-
* ungated behind a row that says they are screened. `voice.wake.noiseSuppression:
|
|
285
|
-
* speex` runs here: the filter is a WebAssembly module the SDK carries, applied
|
|
286
|
-
* by the wrapper the listener and the push-to-talk session put around this
|
|
287
|
-
* surface's capture opener.
|
|
288
|
-
*/
|
|
289
|
-
export const DEVICE_AND_TRIGGER_LOCAL_SETTINGS = [
|
|
290
|
-
'watchers.triggers.backoffLadderMs',
|
|
291
|
-
'watchers.triggers.breakerStrikes',
|
|
292
|
-
'watchers.triggers.defaultCheckIntervalMs',
|
|
293
|
-
'watchers.triggers.probeTimeoutMs',
|
|
294
|
-
'watchers.triggers.maxConcurrentChecks',
|
|
295
|
-
'watchers.triggers.observationRingSize',
|
|
296
|
-
'watchers.triggers.runHistoryLimit',
|
|
297
|
-
'watchers.triggers.runHistoryTtlHours',
|
|
298
|
-
'watchers.triggers.eventLogLimit',
|
|
299
|
-
'watchers.triggers.eventLogTtlHours',
|
|
300
|
-
'watchers.triggers.sweepIntervalMs',
|
|
301
|
-
'watchers.triggers.supervisionTickMs',
|
|
302
|
-
'watchers.triggers.streamQueueLimit',
|
|
303
|
-
'watchers.triggers.streamBatchLines',
|
|
304
|
-
'watchers.triggers.streamBatchIntervalMs',
|
|
305
|
-
'watchers.triggers.onExitMaxDurationMs',
|
|
306
|
-
'watchers.triggers.onExitStdin',
|
|
307
|
-
'watchers.triggers.outputTailBytes',
|
|
308
|
-
'device.capabilities.allowAlwaysOffer',
|
|
309
|
-
'device.capabilities.requestTimeoutSeconds',
|
|
310
|
-
'device.location.precision',
|
|
311
|
-
'device.clipboard.readMode',
|
|
312
|
-
'device.capture.retentionHours',
|
|
313
|
-
'device.capture.maxArtifacts',
|
|
314
|
-
'device.capture.sweepIntervalMinutes',
|
|
315
|
-
'device.grants.expiryDays',
|
|
316
|
-
'device.grants.maxPerNode',
|
|
317
|
-
'device.grants.auditRetentionDays',
|
|
318
|
-
'device.nodes.maxPaired',
|
|
319
|
-
] as const;
|
|
320
|
-
|
|
321
|
-
/**
|
|
322
|
-
* Every feature's enablement settings key whose on/off writes round-trip
|
|
323
|
-
* through a REAL on-disk ConfigManager in
|
|
324
|
-
* `src/test/verification/../input/settings-modal-flag-persistence.test.ts`
|
|
325
|
-
* ("every feature with an off position round-trips both directions"). These
|
|
326
|
-
* are first-class schema keys under the dissolved feature model, so they are
|
|
327
|
-
* genuinely behavior-verified locally. Keys already counted in the
|
|
328
|
-
* feature-knob list are excluded to keep the sum honest.
|
|
329
|
-
*/
|
|
330
|
-
const ENABLEMENT_KEYS_BEHAVIOR_VERIFIED = new Set(
|
|
331
|
-
FEATURE_SETTINGS
|
|
332
|
-
.filter((feature) => featureEnablementWrite(feature.id, true) !== null && featureEnablementWrite(feature.id, false) !== null)
|
|
333
|
-
.map((feature) => feature.enablement.key)
|
|
334
|
-
.filter((key) => !(FEATURE_KNOB_LOCAL_SETTINGS as readonly string[]).includes(key)),
|
|
335
|
-
).size;
|
|
336
|
-
|
|
337
|
-
/** Settings with real local behavior verification: the authored baseline plus the persistence-tested feature-knob, device/trigger, and enablement keys. */
|
|
338
|
-
/**
|
|
339
|
-
* Config keys added by the LAN group-key layer: the automatic group-key
|
|
340
|
-
* rotation interval, the dual-generation acceptance window around a rotation,
|
|
341
|
-
* the discovery beacon interval, and the roster gossip interval.
|
|
342
|
-
*
|
|
343
|
-
* THIS CONSTANT IS NOT A DIAL, for the same reason as the two above. Each key
|
|
344
|
-
* is counted because a test that exercises it was actually written:
|
|
345
|
-
* `src/test/verification/cluster-group-settings-persistence.test.ts` runs the
|
|
346
|
-
* same four-part persistence contract, schema default exposure, `set()`
|
|
347
|
-
* through the key's own validator to disk, reload into a fresh ConfigManager
|
|
348
|
-
* with read-back equality, and reset-to-default that survives reload.
|
|
349
|
-
*
|
|
350
|
-
* PER-KEY EVIDENCE. All four have a LIVE consumer in this build, which is more
|
|
351
|
-
* than several of the keys counted above can claim:
|
|
352
|
-
* cluster.keyRotationHours , read by resolveClusterGroupSettings and
|
|
353
|
-
* compared against the current key's age in
|
|
354
|
-
* the group runtime's rotation check.
|
|
355
|
-
* cluster.keyRotationGraceMinutes, sets how long the previous generation
|
|
356
|
-
* stays accepted after a scheduled
|
|
357
|
-
* rotation; drives the keyring's accepted
|
|
358
|
-
* generation set.
|
|
359
|
-
* cluster.beaconSeconds , the discovery beacon timer interval, and
|
|
360
|
-
* the basis of the "recently heard from"
|
|
361
|
-
* window that decides which member mints a
|
|
362
|
-
* rotation.
|
|
363
|
-
* cluster.rosterGossipSeconds , how often the member list is shared.
|
|
364
|
-
*
|
|
365
|
-
* `cluster.enabled` is NOT here: it is a feature enablement key and the ledger
|
|
366
|
-
* counts those in its own set.
|
|
367
|
-
*/
|
|
368
|
-
export const CLUSTER_GROUP_LOCAL_SETTINGS = [
|
|
369
|
-
'cluster.keyRotationHours',
|
|
370
|
-
'cluster.keyRotationGraceMinutes',
|
|
371
|
-
'cluster.beaconSeconds',
|
|
372
|
-
'cluster.rosterGossipSeconds',
|
|
373
|
-
] as const;
|
|
374
|
-
|
|
375
|
-
/**
|
|
376
|
-
* Config keys for the daemon's payment capability: the master switch, which
|
|
377
|
-
* card to use by default, the settlement currency, CVV handling, the six
|
|
378
|
-
* budget knobs, the shipping-tier preference, the fourteen billing/shipping
|
|
379
|
-
* address sub-fields, the two approval/veto windows, and the notify-channel
|
|
380
|
-
* list. Card MATERIAL (number, expiry, CVV, cardholder name) is intentionally
|
|
381
|
-
* NOT here, see the SDK's schema-domain-payments.ts header and this repo's
|
|
382
|
-
* own input/payments-config.ts: that material lives write-only in the daemon
|
|
383
|
-
* secret store, never in CONFIG_SCHEMA, so there is nothing for a persistence
|
|
384
|
-
* contract to count.
|
|
385
|
-
*
|
|
386
|
-
* THIS CONSTANT IS NOT A DIAL, for the same reason as the sets above. Every
|
|
387
|
-
* key below is counted because
|
|
388
|
-
* `src/test/verification/payments-settings-persistence.test.ts` runs the same
|
|
389
|
-
* four-part persistence contract the other counted sets are counted for:
|
|
390
|
-
* schema default exposure, `set()` through the key's own validator to disk,
|
|
391
|
-
* reload into a fresh ConfigManager with read-back equality, and
|
|
392
|
-
* reset-to-default that also survives reload. That test also asserts this
|
|
393
|
-
* list is exactly the CONFIG_SCHEMA's `payments.*` key set, so a future SDK
|
|
394
|
-
* addition under this domain is caught (fails the inventory-integrity test)
|
|
395
|
-
* rather than silently uncounted.
|
|
396
|
-
*
|
|
397
|
-
* PER-KEY EVIDENCE. All 28 are read by the daemon's own payment capability
|
|
398
|
-
* (platform/payments, platform/control-plane/routes/payments.ts): the budget
|
|
399
|
-
* keys size the daily/overage/tolerance pools, the window keys size the
|
|
400
|
-
* veto/approval timers, cvvHandling and shipping.preferredTier select the
|
|
401
|
-
* enum behaviors `platform/payments` documents, and the address sub-fields
|
|
402
|
-
* are read directly by the daemon's shipping-address-required refusal and the
|
|
403
|
-
* card-issuer address-verification path. `enabled` and `defaultCardId` gate
|
|
404
|
-
* and select, respectively, whether/which card a purchase uses.
|
|
405
|
-
*/
|
|
406
|
-
export const PAYMENTS_LOCAL_SETTINGS = [
|
|
407
|
-
'payments.enabled',
|
|
408
|
-
'payments.defaultCardId',
|
|
409
|
-
'payments.currency',
|
|
410
|
-
'payments.cvvHandling',
|
|
411
|
-
'payments.budget.dailyItem',
|
|
412
|
-
'payments.budget.dailyOverage',
|
|
413
|
-
'payments.budget.perPurchaseCeilingEnabled',
|
|
414
|
-
'payments.budget.perPurchaseCeiling',
|
|
415
|
-
'payments.budget.overageToleranceEnabled',
|
|
416
|
-
'payments.budget.overageToleranceDailyAllowance',
|
|
417
|
-
'payments.shipping.preferredTier',
|
|
418
|
-
'payments.billingAddress.name',
|
|
419
|
-
'payments.billingAddress.line1',
|
|
420
|
-
'payments.billingAddress.line2',
|
|
421
|
-
'payments.billingAddress.city',
|
|
422
|
-
'payments.billingAddress.region',
|
|
423
|
-
'payments.billingAddress.postalCode',
|
|
424
|
-
'payments.billingAddress.country',
|
|
425
|
-
'payments.shippingAddress.name',
|
|
426
|
-
'payments.shippingAddress.line1',
|
|
427
|
-
'payments.shippingAddress.line2',
|
|
428
|
-
'payments.shippingAddress.city',
|
|
429
|
-
'payments.shippingAddress.region',
|
|
430
|
-
'payments.shippingAddress.postalCode',
|
|
431
|
-
'payments.shippingAddress.country',
|
|
432
|
-
'payments.windows.vetoMinutes',
|
|
433
|
-
'payments.windows.approvalMinutes',
|
|
434
|
-
'payments.majorRetailersAdditional',
|
|
435
|
-
'payments.majorRetailersExcluded',
|
|
436
|
-
'payments.ebayMinSellerFeedbackCount',
|
|
437
|
-
'payments.ebayMinSellerPositivePercent',
|
|
438
|
-
'payments.notifyChannels',
|
|
439
|
-
] as const;
|
|
440
|
-
|
|
441
|
-
/**
|
|
442
|
-
* Connector settings, the daemon's Google-backed mail/calendar keys plus the
|
|
443
|
-
* connected-host dial switch and the hosted-turn routing switch, declared as
|
|
444
|
-
* described schema rows by platform runtime 2.0.8 (before that the connector
|
|
445
|
-
* keys were cast onto the live config invisibly and the settings surface
|
|
446
|
-
* answered "Unknown setting" for keys the daemon really reads). Counted for
|
|
447
|
-
* exactly the reason DAEMON_MAILBOX_LOCAL_SETTINGS is: the same four-part
|
|
448
|
-
* persistence contract runs over every one of them in
|
|
449
|
-
* src/test/verification/connector-settings-persistence.test.ts, and that test
|
|
450
|
-
* asserts this list is the complete schema set for the email, calendar and
|
|
451
|
-
* google prefixes
|
|
452
|
-
* plus the two switches. Arriving uncounted is what dropped
|
|
453
|
-
* localBehaviorPercent through its floor when the schema grew. The three
|
|
454
|
-
* secret-valued keys hold goodvibes://secrets/ references, never values,
|
|
455
|
-
* same note as the mailbox passwords above.
|
|
456
|
-
*/
|
|
457
|
-
export const CONNECTOR_LOCAL_SETTINGS = [
|
|
458
|
-
'email.enabled',
|
|
459
|
-
'email.imapHost',
|
|
460
|
-
'email.imapPort',
|
|
461
|
-
'email.imapSecurity',
|
|
462
|
-
'email.smtpHost',
|
|
463
|
-
'email.smtpPort',
|
|
464
|
-
'email.smtpSecurity',
|
|
465
|
-
'email.username',
|
|
466
|
-
'email.passwordRef',
|
|
467
|
-
'email.smtpPasswordRef',
|
|
468
|
-
'email.fromAddress',
|
|
469
|
-
'email.mailbox',
|
|
470
|
-
'email.draftsMailbox',
|
|
471
|
-
'calendar.google.clientId',
|
|
472
|
-
'calendar.google.clientSecretRef',
|
|
473
|
-
'calendar.google.icsUrl',
|
|
474
|
-
'calendar.microsoft.clientId',
|
|
475
|
-
'calendar.microsoft.clientSecretRef',
|
|
476
|
-
'google.oauth.projectId',
|
|
477
|
-
'google.oauth.publishingStatus',
|
|
478
|
-
'google.oauth.refreshToken',
|
|
479
|
-
'google.credentials.migratedFrom',
|
|
480
|
-
'daemon.connectedHost.enabled',
|
|
481
|
-
'hostedSessions.routeConversationTurns',
|
|
482
|
-
] as const;
|
|
483
|
-
|
|
484
|
-
const SETTINGS_BEHAVIOR_VERIFIED = SETTINGS_BEHAVIOR_BASELINE
|
|
485
|
-
+ FEATURE_KNOB_LOCAL_SETTINGS.length
|
|
486
|
-
+ DEVICE_AND_TRIGGER_LOCAL_SETTINGS.length
|
|
487
|
-
+ CLUSTER_GROUP_LOCAL_SETTINGS.length
|
|
488
|
-
+ DAEMON_MAILBOX_LOCAL_SETTINGS.length
|
|
489
|
-
+ PAYMENTS_LOCAL_SETTINGS.length
|
|
490
|
-
+ CONNECTOR_LOCAL_SETTINGS.length
|
|
491
|
-
+ ENABLEMENT_KEYS_BEHAVIOR_VERIFIED;
|
|
492
|
-
|
|
493
|
-
const EXTERNAL_SLASH_COMMANDS = new Set([
|
|
494
|
-
'auth',
|
|
495
|
-
'bridge',
|
|
496
|
-
'cloudflare',
|
|
497
|
-
'health',
|
|
498
|
-
'listener',
|
|
499
|
-
'login',
|
|
500
|
-
'logout',
|
|
501
|
-
'mcp',
|
|
502
|
-
'notify',
|
|
503
|
-
'pair',
|
|
504
|
-
'qrcode',
|
|
505
|
-
'remote',
|
|
506
|
-
'remote-env',
|
|
507
|
-
'remote-setup',
|
|
508
|
-
'runner-pool',
|
|
509
|
-
'scan',
|
|
510
|
-
'secrets',
|
|
511
|
-
'services',
|
|
512
|
-
'subscription',
|
|
513
|
-
'teleport',
|
|
514
|
-
'tts',
|
|
515
|
-
'tunnel',
|
|
516
|
-
'voice',
|
|
517
|
-
]);
|
|
518
|
-
|
|
519
|
-
const EXTERNAL_CLI_COMMANDS = new Set([
|
|
520
|
-
'bridge',
|
|
521
|
-
'listener',
|
|
522
|
-
'pair',
|
|
523
|
-
'remote',
|
|
524
|
-
'run',
|
|
525
|
-
'serve',
|
|
526
|
-
'service',
|
|
527
|
-
'tui',
|
|
528
|
-
'web',
|
|
529
|
-
]);
|
|
530
|
-
|
|
531
|
-
const ONBOARDING_CAPABILITIES = [
|
|
532
|
-
'local-tui-only',
|
|
533
|
-
'browser-access',
|
|
534
|
-
'network-access',
|
|
535
|
-
'webhook-events',
|
|
536
|
-
'external-integrations',
|
|
537
|
-
'cloudflare-batch',
|
|
538
|
-
] as const;
|
|
539
|
-
|
|
540
|
-
const EXTERNAL_SURFACES = [
|
|
541
|
-
'bluebubbles',
|
|
542
|
-
'discord',
|
|
543
|
-
'googleChat',
|
|
544
|
-
'homeassistant',
|
|
545
|
-
'imessage',
|
|
546
|
-
'matrix',
|
|
547
|
-
'mattermost',
|
|
548
|
-
'msteams',
|
|
549
|
-
'ntfy',
|
|
550
|
-
'signal',
|
|
551
|
-
'slack',
|
|
552
|
-
'telegram',
|
|
553
|
-
'webhook',
|
|
554
|
-
'whatsapp',
|
|
555
|
-
] as const;
|
|
556
|
-
|
|
557
|
-
function percent(numerator: number, denominator: number): number {
|
|
558
|
-
return denominator === 0 ? 0 : Math.round((numerator / denominator) * 1000) / 10;
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
function listSlashCommands(): string[] {
|
|
562
|
-
const registry = new CommandRegistry();
|
|
563
|
-
registerBuiltinCommands(registry);
|
|
564
|
-
return registry.getAll().map((command) => command.name);
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
function countBuiltinPanels(root: string): number {
|
|
568
|
-
const builtinDir = join(root, 'src', 'panels', 'builtin');
|
|
569
|
-
let count = 0;
|
|
570
|
-
for (const file of readdirSync(builtinDir)) {
|
|
571
|
-
if (!file.endsWith('.ts')) continue;
|
|
572
|
-
const text = readFileSync(join(builtinDir, file), 'utf8');
|
|
573
|
-
count += [...text.matchAll(/registerType\(\s*\{\s*id:\s*['"][^'"]+['"]/g)].length;
|
|
574
|
-
}
|
|
575
|
-
return count;
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
/**
|
|
579
|
-
* The CLI command words this terminal actually accepts, read off the catalog
|
|
580
|
-
* the parser is driven by rather than scraped out of a source file, the
|
|
581
|
-
* ledger counts what ships, and a catalog entry IS what ships.
|
|
582
|
-
*/
|
|
583
|
-
function listCliCommands(): string[] {
|
|
584
|
-
return GOODVIBES_CLI_CATALOG.commands
|
|
585
|
-
.map((spec) => spec.name as string)
|
|
586
|
-
.filter((command) => command !== 'unknown');
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
export function buildVerificationLedger(root: string): VerificationLedger {
|
|
590
|
-
const slashCommandNames = listSlashCommands();
|
|
591
|
-
const cliCommandNames = listCliCommands();
|
|
592
|
-
const slashCommands = slashCommandNames.length;
|
|
593
|
-
const panels = countBuiltinPanels(root);
|
|
594
|
-
const cliCommands = cliCommandNames.length;
|
|
595
|
-
const featureFlags = FEATURE_SETTINGS.length;
|
|
596
|
-
const settings = CONFIG_SCHEMA.length;
|
|
597
|
-
const externalSlashCommands = slashCommandNames.filter((command) => EXTERNAL_SLASH_COMMANDS.has(command)).length;
|
|
598
|
-
const externalCliCommands = cliCommandNames.filter((command) => EXTERNAL_CLI_COMMANDS.has(command)).length;
|
|
599
|
-
|
|
600
|
-
const areas: VerificationLedgerArea[] = [
|
|
601
|
-
{
|
|
602
|
-
area: 'Settings schema and persistence',
|
|
603
|
-
total: settings,
|
|
604
|
-
localSignalVerified: settings,
|
|
605
|
-
localBehaviorVerified: SETTINGS_BEHAVIOR_VERIFIED,
|
|
606
|
-
externalOutcomeRequired: settings - SETTINGS_BEHAVIOR_VERIFIED,
|
|
607
|
-
notes: 'Every schema setting can be validated for schema/default/load/write/location; external side effects remain separate.',
|
|
608
|
-
},
|
|
609
|
-
{
|
|
610
|
-
area: 'Feature flags',
|
|
611
|
-
total: featureFlags,
|
|
612
|
-
localSignalVerified: featureFlags,
|
|
613
|
-
localBehaviorVerified: featureFlags - 4,
|
|
614
|
-
externalOutcomeRequired: 4,
|
|
615
|
-
notes: 'All flags can be loaded/toggled; a small surface/service subset still requires live external behavior.',
|
|
616
|
-
},
|
|
617
|
-
{
|
|
618
|
-
area: 'Slash commands',
|
|
619
|
-
total: slashCommands,
|
|
620
|
-
localSignalVerified: slashCommands,
|
|
621
|
-
localBehaviorVerified: slashCommands - externalSlashCommands,
|
|
622
|
-
externalOutcomeRequired: externalSlashCommands,
|
|
623
|
-
notes: 'Every command can be routed and invoked with a fake context; external/provider/device commands need live outcome checks.',
|
|
624
|
-
},
|
|
625
|
-
{
|
|
626
|
-
area: 'Built-in panels',
|
|
627
|
-
total: panels,
|
|
628
|
-
localSignalVerified: panels,
|
|
629
|
-
localBehaviorVerified: panels,
|
|
630
|
-
externalOutcomeRequired: 0,
|
|
631
|
-
notes: 'Panels can be rendered and input-tested against fake read models and real cached state.',
|
|
632
|
-
},
|
|
633
|
-
{
|
|
634
|
-
area: 'Top-level CLI commands',
|
|
635
|
-
total: cliCommands,
|
|
636
|
-
localSignalVerified: cliCommands,
|
|
637
|
-
localBehaviorVerified: cliCommands - externalCliCommands,
|
|
638
|
-
externalOutcomeRequired: externalCliCommands,
|
|
639
|
-
notes: 'Parser/help/status/package behavior is local; long-running TUI/service/remote flows require process or external checks.',
|
|
640
|
-
},
|
|
641
|
-
{
|
|
642
|
-
area: 'External surfaces',
|
|
643
|
-
total: EXTERNAL_SURFACES.length,
|
|
644
|
-
localSignalVerified: EXTERNAL_SURFACES.length,
|
|
645
|
-
localBehaviorVerified: 2,
|
|
646
|
-
externalOutcomeRequired: EXTERNAL_SURFACES.length - 2,
|
|
647
|
-
notes: 'Config/readiness can be local for all surfaces; real message delivery is external for most surfaces.',
|
|
648
|
-
},
|
|
649
|
-
{
|
|
650
|
-
area: 'Onboarding capability bundles',
|
|
651
|
-
total: ONBOARDING_CAPABILITIES.length,
|
|
652
|
-
localSignalVerified: ONBOARDING_CAPABILITIES.length,
|
|
653
|
-
localBehaviorVerified: 5,
|
|
654
|
-
externalOutcomeRequired: 1,
|
|
655
|
-
notes: 'Wizard state derivation/apply can be local; Cloudflare provisioning remains external.',
|
|
656
|
-
},
|
|
657
|
-
];
|
|
658
|
-
|
|
659
|
-
const total = areas.reduce((sum, area) => sum + area.total, 0);
|
|
660
|
-
const localSignalVerified = areas.reduce((sum, area) => sum + area.localSignalVerified, 0);
|
|
661
|
-
const localBehaviorVerified = areas.reduce((sum, area) => sum + area.localBehaviorVerified, 0);
|
|
662
|
-
const externalOutcomeRequired = areas.reduce((sum, area) => sum + area.externalOutcomeRequired, 0);
|
|
663
|
-
|
|
664
|
-
return {
|
|
665
|
-
generatedAt: new Date().toISOString(),
|
|
666
|
-
areas,
|
|
667
|
-
totals: {
|
|
668
|
-
total,
|
|
669
|
-
localSignalVerified,
|
|
670
|
-
localBehaviorVerified,
|
|
671
|
-
externalOutcomeRequired,
|
|
672
|
-
localSignalPercent: percent(localSignalVerified, total),
|
|
673
|
-
localBehaviorPercent: percent(localBehaviorVerified, total),
|
|
674
|
-
},
|
|
675
|
-
};
|
|
676
|
-
}
|
|
677
|
-
|
|
678
|
-
export function renderVerificationLedgerMarkdown(ledger: VerificationLedger): string {
|
|
679
|
-
const lines = [
|
|
680
|
-
'# GoodVibes Verification Ledger',
|
|
681
|
-
'',
|
|
682
|
-
`Generated: ${ledger.generatedAt}`,
|
|
683
|
-
'',
|
|
684
|
-
'| Area | Total | Local verification signal | Local behavior | External outcome required | Notes |',
|
|
685
|
-
'|---|---:|---:|---:|---:|---|',
|
|
686
|
-
...ledger.areas.map((area) => [
|
|
687
|
-
`| ${area.area}`,
|
|
688
|
-
area.total,
|
|
689
|
-
area.localSignalVerified,
|
|
690
|
-
area.localBehaviorVerified,
|
|
691
|
-
area.externalOutcomeRequired,
|
|
692
|
-
area.notes,
|
|
693
|
-
].join(' | ') + ' |'),
|
|
694
|
-
'',
|
|
695
|
-
'## Totals',
|
|
696
|
-
'',
|
|
697
|
-
`- Total inventory items: ${ledger.totals.total}`,
|
|
698
|
-
`- Local verification signal: ${ledger.totals.localSignalVerified} (${ledger.totals.localSignalPercent}%)`,
|
|
699
|
-
`- Local behavior verified: ${ledger.totals.localBehaviorVerified} (${ledger.totals.localBehaviorPercent}%)`,
|
|
700
|
-
`- External outcome required: ${ledger.totals.externalOutcomeRequired}`,
|
|
701
|
-
'',
|
|
702
|
-
'Local verification signal means the item can be exercised through schema, routing, persistence, render, readiness, daemon, CLI, or real-state checks without relying on an external SaaS/device outcome.',
|
|
703
|
-
'Local behavior verified means the behavior can be completed locally with in-process, CLI, daemon, tmux, or real persisted state.',
|
|
704
|
-
'',
|
|
705
|
-
];
|
|
706
|
-
return `${lines.join('\n')}\n`;
|
|
707
|
-
}
|