@pellux/goodvibes-tui 1.13.1 → 1.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/CHANGELOG.md +96 -0
  2. package/README.md +6 -6
  3. package/bin/goodvibes +6 -0
  4. package/bin/goodvibes-daemon +6 -0
  5. package/bin/launcher-support.js +34 -1
  6. package/docs/foundation-artifacts/operator-contract.json +8076 -2047
  7. package/package.json +15 -11
  8. package/scripts/postinstall.js +73 -48
  9. package/src/cli/bundle-command.ts +5 -5
  10. package/src/cli/completion.ts +1 -1
  11. package/src/cli/completions/generate.ts +15 -3
  12. package/src/cli/doctor.ts +385 -0
  13. package/src/cli/entrypoint.ts +72 -1
  14. package/src/cli/help.ts +29 -9
  15. package/src/cli/hooks-command.ts +74 -0
  16. package/src/cli/hooks-report.ts +167 -0
  17. package/src/cli/index.ts +3 -0
  18. package/src/cli/management.ts +13 -1
  19. package/src/cli/parser.ts +10 -2
  20. package/src/cli/plugin-bundles-command.ts +228 -0
  21. package/src/cli/plugin-command.ts +179 -0
  22. package/src/cli/service-posture.ts +10 -0
  23. package/src/cli/status.ts +275 -2
  24. package/src/cli/tui-startup.ts +119 -1
  25. package/src/cli/types.ts +3 -1
  26. package/src/config/index.ts +16 -0
  27. package/src/config/tui-extension-settings.ts +169 -0
  28. package/src/core/approval-alert.ts +15 -2
  29. package/src/core/compaction-receipt.ts +127 -0
  30. package/src/core/model-routing-chip.ts +82 -0
  31. package/src/core/permission-mode.ts +89 -0
  32. package/src/core/rewind-receipt.ts +83 -0
  33. package/src/core/rewind-turn-anchors.ts +160 -0
  34. package/src/core/scriptable-statusline.ts +141 -0
  35. package/src/core/session-auto-titler.ts +110 -0
  36. package/src/core/stream-event-wiring.ts +20 -0
  37. package/src/core/system-message-router.ts +1 -1
  38. package/src/core/terminal-notifier.ts +102 -0
  39. package/src/core/turn-event-wiring.ts +80 -1
  40. package/src/input/command-reference.ts +96 -0
  41. package/src/input/command-registry.ts +25 -0
  42. package/src/input/commands/channel-pairing.ts +245 -0
  43. package/src/input/commands/channel-runtime.ts +152 -6
  44. package/src/input/commands/checkin-runtime.ts +89 -0
  45. package/src/input/commands/checkpoint-runtime.ts +7 -179
  46. package/src/input/commands/ci-runtime.ts +207 -0
  47. package/src/input/commands/cost-attribution-format.ts +52 -0
  48. package/src/input/commands/cost-runtime.ts +44 -4
  49. package/src/input/commands/editor-runtime.ts +22 -0
  50. package/src/input/commands/flags-runtime.ts +328 -0
  51. package/src/input/commands/health-metrics-format.ts +67 -0
  52. package/src/input/commands/health-runtime.ts +55 -1
  53. package/src/input/commands/memory.ts +23 -0
  54. package/src/input/commands/operator-rpc.ts +95 -0
  55. package/src/input/commands/palette-runtime.ts +22 -0
  56. package/src/input/commands/permissions-provenance.ts +264 -0
  57. package/src/input/commands/permissions-runtime.ts +21 -0
  58. package/src/input/commands/planning-runtime.ts +28 -1
  59. package/src/input/commands/platform-access-runtime.ts +2 -97
  60. package/src/input/commands/principals-runtime.ts +212 -0
  61. package/src/input/commands/product-runtime.ts +43 -3
  62. package/src/input/commands/recall-files-config.ts +54 -0
  63. package/src/input/commands/recall-files-git.ts +57 -0
  64. package/src/input/commands/recall-files.ts +185 -0
  65. package/src/input/commands/recall-query.ts +8 -3
  66. package/src/input/commands/recall-review.ts +2 -2
  67. package/src/input/commands/recall-shared.ts +13 -0
  68. package/src/input/commands/relay-runtime.ts +86 -0
  69. package/src/input/commands/review-runtime.ts +160 -0
  70. package/src/input/commands/rewind-runtime.ts +362 -0
  71. package/src/input/commands/schedule-nl.ts +147 -0
  72. package/src/input/commands/schedule-runtime.ts +29 -10
  73. package/src/input/commands/secret-runtime.ts +55 -0
  74. package/src/input/commands/session-content.ts +19 -8
  75. package/src/input/commands/session-workflow.ts +10 -0
  76. package/src/input/commands/update-runtime.ts +363 -0
  77. package/src/input/commands/workstream-attempt-dependents.ts +103 -0
  78. package/src/input/commands/workstream-attempts.ts +244 -0
  79. package/src/input/commands/workstream-runtime.ts +164 -26
  80. package/src/input/commands/worktree-runtime.ts +56 -2
  81. package/src/input/commands.ts +135 -80
  82. package/src/input/composer-capture.ts +67 -0
  83. package/src/input/composer-editor.ts +134 -0
  84. package/src/input/concealed-input.ts +94 -0
  85. package/src/input/exec-env-scrub-config.ts +84 -0
  86. package/src/input/feature-unit-layout.ts +142 -0
  87. package/src/input/feed-context-factory.ts +2 -0
  88. package/src/input/handler-feed-routes.ts +17 -0
  89. package/src/input/handler-feed.ts +3 -0
  90. package/src/input/handler-modal-routes.ts +5 -2
  91. package/src/input/handler-shortcuts.ts +37 -0
  92. package/src/input/handler.ts +24 -2
  93. package/src/input/keybindings.ts +11 -2
  94. package/src/input/onboarding/onboarding-feature-units.ts +536 -0
  95. package/src/input/onboarding/onboarding-wizard-apply.ts +40 -6
  96. package/src/input/onboarding/onboarding-wizard-external-surfaces.ts +324 -629
  97. package/src/input/onboarding/onboarding-wizard-steps.ts +5 -5
  98. package/src/input/onboarding/onboarding-wizard-types.ts +6 -0
  99. package/src/input/relay-settings-descriptions.ts +35 -0
  100. package/src/input/sandbox-exec-config.ts +107 -0
  101. package/src/input/settings-modal-adjustment.ts +4 -7
  102. package/src/input/settings-modal-data.ts +178 -8
  103. package/src/input/settings-modal-mutations.ts +41 -13
  104. package/src/input/settings-modal-types.ts +42 -5
  105. package/src/input/settings-modal.ts +67 -15
  106. package/src/input/submission-router.ts +4 -1
  107. package/src/input/worktree-setup-config.ts +93 -0
  108. package/src/main.ts +43 -43
  109. package/src/panels/builtin/development.ts +14 -0
  110. package/src/panels/diff-review-model.ts +189 -0
  111. package/src/panels/diff-review-panel.ts +395 -0
  112. package/src/panels/fleet-panel-format.ts +114 -2
  113. package/src/panels/fleet-panel.ts +65 -78
  114. package/src/panels/fleet-read-model.ts +91 -11
  115. package/src/panels/fleet-stop.ts +19 -4
  116. package/src/panels/modals/memory-modal.ts +11 -2
  117. package/src/permissions/hunk-selection.ts +86 -5
  118. package/src/permissions/prompt.ts +108 -7
  119. package/src/permissions/sandbox-exec-gate.ts +162 -0
  120. package/src/renderer/settings-modal-helpers.ts +21 -1
  121. package/src/renderer/settings-modal.ts +70 -44
  122. package/src/renderer/shell-surface.ts +23 -1
  123. package/src/renderer/system-message.ts +4 -0
  124. package/src/renderer/tool-result-summary.ts +95 -5
  125. package/src/renderer/ui-factory.ts +22 -0
  126. package/src/runtime/bootstrap-command-context.ts +15 -1
  127. package/src/runtime/bootstrap-command-parts.ts +14 -2
  128. package/src/runtime/bootstrap-core.ts +38 -38
  129. package/src/runtime/bootstrap-notifier-sync.ts +41 -0
  130. package/src/runtime/bootstrap-shell.ts +8 -0
  131. package/src/runtime/bootstrap.ts +21 -23
  132. package/src/runtime/context-accounting-source.ts +103 -0
  133. package/src/runtime/conversation-rewind-port.ts +130 -0
  134. package/src/runtime/fleet-needs-input-push.ts +70 -0
  135. package/src/runtime/install-self-check-startup.ts +36 -0
  136. package/src/runtime/install-self-check.ts +149 -0
  137. package/src/runtime/onboarding/fast-path.ts +93 -0
  138. package/src/runtime/process-lifecycle.ts +32 -24
  139. package/src/runtime/relay-reachability-bridge.ts +53 -0
  140. package/src/runtime/release-artifacts.ts +79 -0
  141. package/src/runtime/services.ts +33 -33
  142. package/src/runtime/trust/workspace-registration.ts +184 -0
  143. package/src/runtime/trust/workspace-trust.ts +202 -0
  144. package/src/runtime/ui-services.ts +2 -1
  145. package/src/runtime/update-check.ts +113 -0
  146. package/src/runtime/workspace-checkpointing.ts +32 -0
  147. package/src/runtime/workstream-attempts-validation.ts +77 -0
  148. package/src/runtime/workstream-draft-edits.ts +95 -0
  149. package/src/runtime/workstream-draft-store.ts +101 -0
  150. package/src/runtime/workstream-draft-types.ts +42 -0
  151. package/src/runtime/workstream-services.ts +70 -39
  152. package/src/shell/blocking-input.ts +29 -0
  153. package/src/shell/ui-openers.ts +65 -0
  154. package/src/verification/verification-ledger.ts +56 -2
  155. package/src/version.ts +1 -1
  156. package/src/input/onboarding/onboarding-wizard-external-surface-extra-specs.ts +0 -130
  157. package/src/runtime/gateway-verbs.ts +0 -47
  158. package/src/runtime/render-scheduler.ts +0 -90
@@ -1,130 +0,0 @@
1
- import type { ExternalSurfaceSpec } from './onboarding-wizard-types.ts';
2
-
3
- export const WEBHOOK_SURFACE_SPEC: ExternalSurfaceSpec = {
4
- id: 'webhook',
5
- enabledFieldId: 'external-services.webhook',
6
- enabledConfigKey: 'surfaces.webhook.enabled',
7
- label: 'Outbound webhook surface',
8
- hint: 'Enable outbound webhook delivery targets.',
9
- defaultEnabled: (snapshot) => snapshot?.config.surfaces.webhook.enabled ?? false,
10
- fields: [
11
- {
12
- id: 'external-services.webhook.default-target',
13
- configKey: 'surfaces.webhook.defaultTarget',
14
- kind: 'text',
15
- label: 'Default webhook target',
16
- hint: 'Fallback URL used for outbound webhook deliveries.',
17
- placeholder: 'https://example.com/goodvibes',
18
- defaultValue: (snapshot) => snapshot?.config.surfaces.webhook.defaultTarget ?? '',
19
- },
20
- {
21
- id: 'external-services.webhook.secret',
22
- configKey: 'surfaces.webhook.secret',
23
- kind: 'masked',
24
- label: 'Webhook signing secret',
25
- hint: 'Secret used to sign outbound webhook payloads.',
26
- placeholder: 'secret',
27
- defaultValue: (snapshot) => snapshot?.config.surfaces.webhook.secret ?? '',
28
- },
29
- {
30
- id: 'external-services.webhook.timeout-ms',
31
- configKey: 'surfaces.webhook.timeoutMs',
32
- kind: 'text',
33
- valueType: 'number',
34
- label: 'Webhook timeout ms',
35
- hint: 'Request timeout for outbound webhook deliveries.',
36
- placeholder: '10000',
37
- defaultNumber: 10000,
38
- min: 1000,
39
- max: 60000,
40
- defaultValue: (snapshot) => String(snapshot?.config.surfaces.webhook.timeoutMs ?? 10000),
41
- },
42
- ],
43
- };
44
-
45
- export const HOME_ASSISTANT_SURFACE_SPEC: ExternalSurfaceSpec = {
46
- id: 'homeassistant',
47
- enabledFieldId: 'external-services.homeassistant',
48
- enabledConfigKey: 'surfaces.homeassistant.enabled',
49
- label: 'Home Assistant surface',
50
- hint: 'Enable the Home Assistant companion surface, daemon callbacks, and event delivery.',
51
- defaultEnabled: (snapshot) => snapshot?.config.surfaces.homeassistant.enabled ?? false,
52
- fields: [
53
- {
54
- id: 'external-services.homeassistant.instance-url',
55
- configKey: 'surfaces.homeassistant.instanceUrl',
56
- kind: 'text',
57
- label: 'Home Assistant URL',
58
- hint: 'Base URL of the Home Assistant instance.',
59
- placeholder: 'http://homeassistant.local:8123',
60
- defaultValue: (snapshot) => snapshot?.config.surfaces.homeassistant.instanceUrl ?? '',
61
- },
62
- {
63
- id: 'external-services.homeassistant.access-token',
64
- configKey: 'surfaces.homeassistant.accessToken',
65
- kind: 'masked',
66
- label: 'Home Assistant access token',
67
- hint: 'Long-lived Home Assistant access token or goodvibes:// secret reference.',
68
- placeholder: 'long-lived access token',
69
- defaultValue: (snapshot) => snapshot?.config.surfaces.homeassistant.accessToken ?? '',
70
- },
71
- {
72
- id: 'external-services.homeassistant.webhook-secret',
73
- configKey: 'surfaces.homeassistant.webhookSecret',
74
- kind: 'masked',
75
- label: 'Home Assistant webhook secret',
76
- hint: 'Shared secret used to verify inbound Home Assistant callbacks.',
77
- placeholder: 'webhook secret',
78
- defaultValue: (snapshot) => snapshot?.config.surfaces.homeassistant.webhookSecret ?? '',
79
- },
80
- {
81
- id: 'external-services.homeassistant.default-conversation-id',
82
- configKey: 'surfaces.homeassistant.defaultConversationId',
83
- kind: 'text',
84
- label: 'Default conversation ID',
85
- hint: 'Default Home Assistant conversation id used for route binding.',
86
- placeholder: 'goodvibes',
87
- defaultValue: (snapshot) => snapshot?.config.surfaces.homeassistant.defaultConversationId ?? 'goodvibes',
88
- },
89
- {
90
- id: 'external-services.homeassistant.remote-session-ttl-ms',
91
- configKey: 'surfaces.homeassistant.remoteSessionTtlMs',
92
- kind: 'text',
93
- valueType: 'number',
94
- label: 'Remote session idle TTL ms',
95
- hint: 'How long an idle Home Assistant remote conversation session remains open before the daemon closes it.',
96
- placeholder: '1200000',
97
- defaultNumber: 1_200_000,
98
- min: 60_000,
99
- max: 86_400_000,
100
- defaultValue: (snapshot) => String(snapshot?.config.surfaces.homeassistant.remoteSessionTtlMs ?? 1_200_000),
101
- },
102
- {
103
- id: 'external-services.homeassistant.device-id',
104
- configKey: 'surfaces.homeassistant.deviceId',
105
- kind: 'text',
106
- label: 'Home Assistant device ID',
107
- hint: 'Stable device identifier exposed by the GoodVibes daemon.',
108
- placeholder: 'goodvibes-daemon',
109
- defaultValue: (snapshot) => snapshot?.config.surfaces.homeassistant.deviceId ?? 'goodvibes-daemon',
110
- },
111
- {
112
- id: 'external-services.homeassistant.device-name',
113
- configKey: 'surfaces.homeassistant.deviceName',
114
- kind: 'text',
115
- label: 'Home Assistant device name',
116
- hint: 'Display name for the GoodVibes daemon device in Home Assistant.',
117
- placeholder: 'GoodVibes Daemon',
118
- defaultValue: (snapshot) => snapshot?.config.surfaces.homeassistant.deviceName ?? 'GoodVibes Daemon',
119
- },
120
- {
121
- id: 'external-services.homeassistant.event-type',
122
- configKey: 'surfaces.homeassistant.eventType',
123
- kind: 'text',
124
- label: 'Home Assistant event type',
125
- hint: 'Event type used for daemon-to-Home Assistant deliveries.',
126
- placeholder: 'goodvibes_message',
127
- defaultValue: (snapshot) => snapshot?.config.surfaces.homeassistant.eventType ?? 'goodvibes_message',
128
- },
129
- ],
130
- };
@@ -1,47 +0,0 @@
1
- /**
2
- * gateway-verbs.ts — attach handlers for every ws-only gateway verb group.
3
- *
4
- * The GatewayMethodCatalog's builtin DESCRIPTORS make fleet.* (including the
5
- * archive verbs), checkpoints.*, sessions.search, and push.* appear in the
6
- * contract, but a descriptor without an attached handler answers
7
- * 501 "Gateway method is not invokable" over both websocket and HTTP invoke.
8
- * createRuntimeServices never called the SDK's registration entry point, so
9
- * every daemon build this package ever vendored shipped exactly that 501 for
10
- * the whole ws-only family (found by the companion app against the 1.13.0
11
- * daemon). This module is the named home for the attachment — mirroring the
12
- * SDK runtime's own composition root (goodvibes-sdk
13
- * platform/runtime/services.ts) — and
14
- * src/test/daemon/gateway-ws-only-invokable.test.ts gates that every ws-only
15
- * verb stays descriptor-present AND handler-attached, with live invokes of
16
- * fleet.snapshot / fleet.archived.list.
17
- */
18
- import {
19
- registerGatewayVerbGroups,
20
- type GatewayMethodCatalog,
21
- type GatewayVerbGroupDeps,
22
- } from '@pellux/goodvibes-sdk/platform/control-plane';
23
- import {
24
- createProcessRegistry,
25
- withFleetArchive,
26
- type ArchivableProcessRegistry,
27
- type ProcessRegistryDeps,
28
- } from '@pellux/goodvibes-sdk/platform/runtime/fleet';
29
-
30
- export function attachWsOnlyGatewayVerbHandlers(
31
- gatewayMethods: GatewayMethodCatalog,
32
- deps: GatewayVerbGroupDeps,
33
- ): void {
34
- registerGatewayVerbGroups(gatewayMethods, deps);
35
- }
36
-
37
- /**
38
- * One shared process registry aggregating the runtime's managers — the Fleet
39
- * panel (panels/fleet-read-model.ts) is its first consumer. Constructed once
40
- * (not per-consumer) so the coalesced tick and the agent-activity side-table
41
- * are shared, not duplicated. Archive-aware: finished agent/swarm subtrees
42
- * can be moved out of the live fleet view into a session-scoped archive (see
43
- * the SDK's fleet/archive.ts).
44
- */
45
- export function createArchivableFleetRegistry(deps: ProcessRegistryDeps): ArchivableProcessRegistry {
46
- return withFleetArchive(createProcessRegistry(deps));
47
- }
@@ -1,90 +0,0 @@
1
- /**
2
- * render-scheduler.ts — same-tick render coalescing for the TUI shell (WO-208).
3
- *
4
- * main.ts fans out its own direct render() calls across turn/stream/input wiring
5
- * (~14 direct invocation contexts). Each one previously ran a full synchronous
6
- * Compositor.composite() the instant it was called. When several fire within a
7
- * single event-loop tick — a streaming burst is the canonical case — only the
8
- * LAST frame is ever visible; the earlier composites are immediately overwritten.
9
- * This scheduler collapses every schedule() call made within one tick into a
10
- * single composite flushed on the microtask queue, so the tick produces exactly
11
- * one frame. That frame is byte-identical to what the last synchronous render()
12
- * would have produced, because the coalesced flush runs after all of the tick's
13
- * synchronous state mutations, reading the same final state the last direct
14
- * render() would have read.
15
- *
16
- * This is deliberately SEPARATE from bootstrap-core's requestRender(), which is a
17
- * cross-tick, 16ms-throttled (~60fps) coalescer for the panel/input/runtime
18
- * fan-out — that one caps repaint RATE across ticks. This one collapses the
19
- * WITHIN-tick burst with no added latency: a microtask flushes at the tail of the
20
- * current tick, before the event loop yields to I/O, so the frame still lands in
21
- * the same turn it was requested in.
22
- *
23
- * flushNow() preserves a synchronous immediate path for callers that genuinely
24
- * need the frame composited before they return. Terminal resize is the known
25
- * case: the resize handler resets the compositor diff and must repaint against
26
- * the new dimensions synchronously rather than waiting for the microtask.
27
- * flushNow() also clears any pending coalesced flush, so a resize (or any
28
- * immediate paint) followed by an already-queued microtask never double-composites.
29
- */
30
-
31
- export interface RenderScheduler {
32
- /**
33
- * Coalesced request: schedule a composite for the current tick. N calls within
34
- * one tick collapse into exactly one composite, flushed on the microtask queue.
35
- */
36
- readonly schedule: () => void;
37
- /**
38
- * Immediate request: run the composite synchronously right now, and cancel any
39
- * pending coalesced flush so the tick still composites only once. Use only where
40
- * a caller genuinely requires synchronous output (terminal resize).
41
- */
42
- readonly flushNow: () => void;
43
- }
44
-
45
- /**
46
- * Build a render scheduler around `renderNow` (the synchronous composite closure).
47
- *
48
- * `scheduleFlush` is the deferral primitive; it defaults to `queueMicrotask` so
49
- * bursts coalesce within the current tick. Tests and benchmarks inject a manual
50
- * queue to flush deterministically.
51
- */
52
- export function createRenderScheduler(
53
- renderNow: () => void,
54
- scheduleFlush: (flush: () => void) => void = queueMicrotask,
55
- /**
56
- * When provided and returning true, every composite path becomes a no-op.
57
- * Wired to process-lifecycle's isTerminalRestored(): once the exit teardown
58
- * has handed the terminal back to the shell, a late frame (async shutdown
59
- * races, stray timers) would paint cursor-positioned content over the
60
- * user's primary screen and strand the next prompt mid-screen.
61
- */
62
- isReleased: () => boolean = () => false,
63
- ): RenderScheduler {
64
- let scheduled = false;
65
-
66
- const flush = (): void => {
67
- // A synchronous flushNow() (or a superseding immediate paint) before this
68
- // microtask ran clears `scheduled`, turning this into a no-op so a single
69
- // tick never composites twice.
70
- if (!scheduled) return;
71
- scheduled = false;
72
- if (isReleased()) return;
73
- renderNow();
74
- };
75
-
76
- const schedule = (): void => {
77
- if (scheduled) return;
78
- scheduled = true;
79
- scheduleFlush(flush);
80
- };
81
-
82
- const flushNow = (): void => {
83
- // Satisfy any pending coalesced flush, then composite synchronously.
84
- scheduled = false;
85
- if (isReleased()) return;
86
- renderNow();
87
- };
88
-
89
- return { schedule, flushNow };
90
- }