@pellux/goodvibes-agent 0.1.116 → 0.1.117

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 (168) hide show
  1. package/CHANGELOG.md +41 -663
  2. package/README.md +38 -52
  3. package/dist/package/main.js +37826 -35924
  4. package/docs/README.md +5 -4
  5. package/docs/{connected-services.md → connected-host.md} +18 -10
  6. package/docs/getting-started.md +41 -44
  7. package/docs/release-and-publishing.md +6 -4
  8. package/package.json +3 -3
  9. package/src/agent/behavior-discovery-summary.ts +1 -3
  10. package/src/agent/persona-discovery.ts +1 -3
  11. package/src/agent/persona-registry.ts +5 -3
  12. package/src/agent/reminder-schedule-format.ts +6 -6
  13. package/src/agent/reminder-schedule.ts +1 -1
  14. package/src/agent/routine-registry.ts +43 -4
  15. package/src/agent/routine-schedule-format.ts +6 -6
  16. package/src/agent/routine-schedule-promotion.ts +1 -1
  17. package/src/agent/routine-schedule-receipts.ts +1 -1
  18. package/src/agent/runtime-profile-starters.ts +3 -3
  19. package/src/agent/runtime-profile.ts +78 -0
  20. package/src/agent/skill-registry.ts +190 -13
  21. package/src/cli/agent-knowledge-command.ts +2 -2
  22. package/src/cli/agent-knowledge-format.ts +2 -2
  23. package/src/cli/agent-knowledge-runtime.ts +1 -1
  24. package/src/cli/bundle-command.ts +1 -1
  25. package/src/cli/entrypoint.ts +16 -7
  26. package/src/cli/help.ts +26 -19
  27. package/src/cli/local-library-command.ts +75 -21
  28. package/src/cli/management-commands.ts +7 -6
  29. package/src/cli/management.ts +6 -51
  30. package/src/cli/parser.ts +23 -2
  31. package/src/cli/profiles-command.ts +119 -1
  32. package/src/cli/routines-command.ts +139 -11
  33. package/src/cli/service-posture.ts +11 -11
  34. package/src/cli/status.ts +21 -25
  35. package/src/input/agent-workspace-access-command-editor-submission.ts +149 -0
  36. package/src/input/agent-workspace-access-command-editors.ts +170 -0
  37. package/src/input/agent-workspace-activation.ts +2 -1
  38. package/src/input/agent-workspace-basic-command-editor-submission.ts +345 -92
  39. package/src/input/agent-workspace-basic-command-editors.ts +480 -7
  40. package/src/input/agent-workspace-categories.ts +175 -15
  41. package/src/input/agent-workspace-channel-command-editor-submission.ts +49 -0
  42. package/src/input/agent-workspace-channel-command-editors.ts +47 -0
  43. package/src/input/agent-workspace-command-editor.ts +23 -1
  44. package/src/input/agent-workspace-delegation-editor-submission.ts +55 -0
  45. package/src/input/agent-workspace-editors.ts +27 -0
  46. package/src/input/agent-workspace-knowledge-command-editor-submission.ts +132 -0
  47. package/src/input/agent-workspace-knowledge-command-editors.ts +110 -0
  48. package/src/input/agent-workspace-learned-behavior.ts +67 -0
  49. package/src/input/agent-workspace-library-command-editor-submission.ts +50 -0
  50. package/src/input/agent-workspace-library-command-editors.ts +35 -0
  51. package/src/input/agent-workspace-mcp-command-editor-submission.ts +95 -0
  52. package/src/input/agent-workspace-memory-command-editor-submission.ts +232 -0
  53. package/src/input/agent-workspace-memory-command-editors.ts +180 -0
  54. package/src/input/agent-workspace-navigation.ts +45 -0
  55. package/src/input/agent-workspace-notify-editor-submission.ts +107 -0
  56. package/src/input/agent-workspace-operations-command-editor-submission.ts +146 -0
  57. package/src/input/agent-workspace-operations-command-editors.ts +119 -0
  58. package/src/input/agent-workspace-provider-command-editor-submission.ts +155 -0
  59. package/src/input/agent-workspace-provider-command-editors.ts +93 -0
  60. package/src/input/agent-workspace-requirements.ts +11 -0
  61. package/src/input/agent-workspace-secret-editor-submission.ts +153 -0
  62. package/src/input/agent-workspace-session-command-editor-submission.ts +199 -0
  63. package/src/input/agent-workspace-session-command-editors.ts +249 -0
  64. package/src/input/agent-workspace-setup.ts +24 -14
  65. package/src/input/agent-workspace-skill-bundle-command-editor-submission.ts +101 -0
  66. package/src/input/agent-workspace-skill-bundle-command-editors.ts +110 -0
  67. package/src/input/agent-workspace-snapshot.ts +50 -8
  68. package/src/input/agent-workspace-task-command-editor-submission.ts +61 -0
  69. package/src/input/agent-workspace-task-command-editors.ts +47 -0
  70. package/src/input/agent-workspace-types.ts +120 -0
  71. package/src/input/agent-workspace-voice-media.ts +1 -1
  72. package/src/input/agent-workspace-workplan-editor-submission.ts +153 -0
  73. package/src/input/agent-workspace.ts +47 -37
  74. package/src/input/command-registry.ts +1 -1
  75. package/src/input/commands/agent-runtime-profile-runtime.ts +89 -4
  76. package/src/input/commands/agent-skills-runtime.ts +76 -12
  77. package/src/input/commands/agent-workspace-runtime.ts +4 -3
  78. package/src/input/commands/brief-runtime.ts +38 -9
  79. package/src/input/commands/channels-runtime.ts +3 -3
  80. package/src/input/commands/compat-runtime.ts +32 -0
  81. package/src/input/commands/health-runtime.ts +22 -24
  82. package/src/input/commands/knowledge.ts +26 -5
  83. package/src/input/commands/local-provider-runtime.ts +7 -3
  84. package/src/input/commands/local-setup-review.ts +4 -14
  85. package/src/input/commands/mcp-runtime.ts +8 -12
  86. package/src/input/commands/operator-runtime.ts +8 -67
  87. package/src/input/commands/personas-runtime.ts +1 -1
  88. package/src/input/commands/platform-access-runtime.ts +7 -70
  89. package/src/input/commands/policy-dispatch.ts +1 -1
  90. package/src/input/commands/policy.ts +1 -5
  91. package/src/input/commands/product-runtime.ts +2 -2
  92. package/src/input/commands/qrcode-runtime.ts +6 -4
  93. package/src/input/commands/routines-runtime.ts +44 -6
  94. package/src/input/commands/runtime-services.ts +1 -14
  95. package/src/input/commands/security-runtime.ts +3 -8
  96. package/src/input/commands/session-content.ts +1 -1
  97. package/src/input/commands/session-workflow.ts +5 -14
  98. package/src/input/commands/shell-core.ts +8 -2
  99. package/src/input/commands/subscription-runtime.ts +1 -6
  100. package/src/input/commands/support-bundle-runtime.ts +53 -0
  101. package/src/input/commands/tasks-runtime.ts +2 -2
  102. package/src/input/commands.ts +4 -0
  103. package/src/input/feed-context-factory.ts +0 -1
  104. package/src/input/handler-content-actions.ts +0 -25
  105. package/src/input/handler-feed.ts +0 -2
  106. package/src/input/handler-interactions.ts +2 -31
  107. package/src/input/handler-onboarding.ts +29 -12
  108. package/src/input/handler-shortcuts.ts +1 -3
  109. package/src/input/handler.ts +4 -7
  110. package/src/input/keybindings.ts +9 -9
  111. package/src/input/mcp-workspace.ts +90 -26
  112. package/src/input/onboarding/handler-onboarding-routes.ts +3 -1
  113. package/src/input/onboarding/onboarding-wizard-apply.ts +49 -0
  114. package/src/input/onboarding/onboarding-wizard-helpers.ts +1 -1
  115. package/src/input/onboarding/onboarding-wizard-operator-steps.ts +81 -3
  116. package/src/input/onboarding/onboarding-wizard-steps.ts +14 -7
  117. package/src/input/onboarding/onboarding-wizard-types.ts +1 -0
  118. package/src/input/onboarding/onboarding-wizard.ts +19 -2
  119. package/src/input/profile-picker-modal.ts +2 -2
  120. package/src/input/settings-modal-agent-policy.ts +6 -6
  121. package/src/input/settings-modal-subscriptions.ts +3 -3
  122. package/src/input/settings-modal.ts +14 -14
  123. package/src/main.ts +0 -2
  124. package/src/panels/automation-control-panel.ts +3 -3
  125. package/src/panels/builtin/agent.ts +1 -1
  126. package/src/panels/builtin/operations.ts +2 -2
  127. package/src/panels/builtin/session.ts +26 -18
  128. package/src/panels/builtin/shared.ts +6 -6
  129. package/src/panels/project-planning-panel.ts +1 -1
  130. package/src/panels/provider-health-domains.ts +3 -3
  131. package/src/panels/qr-panel.ts +44 -20
  132. package/src/panels/subscription-panel.ts +3 -3
  133. package/src/panels/system-messages-panel.ts +2 -2
  134. package/src/panels/tasks-panel.ts +4 -4
  135. package/src/planning/project-planning-coordinator.ts +2 -2
  136. package/src/renderer/agent-workspace.ts +26 -5
  137. package/src/renderer/block-actions.ts +1 -3
  138. package/src/renderer/help-overlay.ts +13 -8
  139. package/src/renderer/mcp-workspace.ts +32 -13
  140. package/src/renderer/model-picker-overlay.ts +0 -1
  141. package/src/renderer/model-workspace.ts +0 -2
  142. package/src/renderer/onboarding/onboarding-wizard.ts +20 -4
  143. package/src/renderer/panel-picker-overlay.ts +1 -1
  144. package/src/renderer/profile-picker-modal.ts +2 -2
  145. package/src/renderer/settings-modal-helpers.ts +23 -23
  146. package/src/renderer/settings-modal.ts +18 -18
  147. package/src/renderer/system-message.ts +1 -1
  148. package/src/runtime/agent-runtime-events.ts +129 -0
  149. package/src/runtime/bootstrap-command-parts.ts +3 -2
  150. package/src/runtime/bootstrap-core.ts +4 -64
  151. package/src/runtime/bootstrap-shell.ts +42 -4
  152. package/src/runtime/bootstrap.ts +8 -27
  153. package/src/runtime/connected-host-auth.ts +42 -0
  154. package/src/runtime/diagnostics/panels/panel-resources.ts +1 -1
  155. package/src/runtime/index.ts +1 -5
  156. package/src/runtime/onboarding/apply.ts +213 -0
  157. package/src/runtime/onboarding/derivation.ts +5 -5
  158. package/src/runtime/onboarding/snapshot.ts +2 -2
  159. package/src/runtime/onboarding/types.ts +26 -1
  160. package/src/runtime/onboarding/verify.ts +81 -2
  161. package/src/runtime/operator-token-cleanup.ts +2 -2
  162. package/src/runtime/services.ts +27 -12
  163. package/src/shell/service-settings-sync.ts +7 -7
  164. package/src/shell/ui-openers.ts +27 -38
  165. package/src/tools/agent-local-registry-tool.ts +10 -4
  166. package/src/tools/agent-tool-policy-guard.ts +5 -7
  167. package/src/version.ts +1 -1
  168. package/src/cli/package-verification.ts +0 -274
@@ -82,16 +82,22 @@ function selectedDetailLines(workspace: McpWorkspace, width: number): WorkspaceR
82
82
  if (workspace.mode === 'form') {
83
83
  const field = workspace.formFields[workspace.formIndex];
84
84
  lines.push(
85
- workspace.editingServerName ? `Previewing server: ${workspace.editingServerName}` : 'Drafting an MCP server command',
86
- 'Workspace writes/reloads are blocked. Use the generated /mcp add ... --yes command from the prompt.',
85
+ workspace.editingServerName ? `Editing server: ${workspace.editingServerName}` : 'Drafting an MCP server',
86
+ 'Workspace writes require explicit confirmation. Type yes on the Confirm field, then save from here.',
87
87
  field ? `${field.label}: ${field.help}` : '',
88
- 'Project/global config locations are shown for review. This workspace does not write or reload MCP config.',
88
+ 'Project/global config locations are shown for review. The workspace dispatches confirmed MCP changes through the TUI command router.',
89
89
  );
90
90
  } else if (workspace.mode === 'delete-confirm') {
91
91
  lines.push(
92
- `Removal blocked for server: ${workspace.editingServerName ?? '(unknown)'}`,
93
- 'Use /mcp remove <server> --scope <project|global> --yes from the prompt for explicit removal.',
94
- 'Press n or Esc to return.',
92
+ `Remove server: ${workspace.editingServerName ?? '(unknown)'}`,
93
+ 'Press Enter or y to remove through the TUI command router.',
94
+ 'Press n or Esc to return without changing config.',
95
+ );
96
+ } else if (workspace.mode === 'reload-confirm') {
97
+ lines.push(
98
+ 'Reload MCP runtime',
99
+ 'Press Enter or y to reload MCP runtime from the current config through the TUI command router.',
100
+ 'Press n or Esc to return without reloading.',
95
101
  );
96
102
  } else {
97
103
  const selected = workspace.selectedRow;
@@ -200,27 +206,40 @@ function buildDeleteRows(workspace: McpWorkspace, height: number): WorkspaceRow[
200
206
  return rows.slice(0, height);
201
207
  }
202
208
 
209
+ function buildReloadRows(height: number): WorkspaceRow[] {
210
+ const rows: WorkspaceRow[] = [
211
+ { text: `${GLYPHS.navigation.selected} Confirm MCP runtime reload`, selected: true, fg: PALETTE.warn, bold: true },
212
+ { text: ' Cancel and return to MCP server browser', fg: PALETTE.muted },
213
+ ];
214
+ while (rows.length < height) rows.push({ text: '', kind: 'empty' });
215
+ return rows.slice(0, height);
216
+ }
217
+
203
218
  function buildControlRows(workspace: McpWorkspace, width: number, height: number): WorkspaceRow[] {
204
219
  if (workspace.mode === 'form') return buildFormRows(workspace, width, height);
205
220
  if (workspace.mode === 'delete-confirm') return buildDeleteRows(workspace, height);
221
+ if (workspace.mode === 'reload-confirm') return buildReloadRows(height);
206
222
  return buildToolRows(workspace, width, height);
207
223
  }
208
224
 
209
225
  function footerText(workspace: McpWorkspace): string {
210
- if (workspace.mode === 'form') return 'Focus server command preview · Up/Down field · Left/Right cycle · Type edit · Enter show command · Esc back';
211
- if (workspace.mode === 'delete-confirm') return 'Focus remove guidance · n/Esc cancel';
212
- return 'Focus MCP workspace · Up/Down choose · Enter view/action · a draft · d removal command · r reload command · t tools · Esc close';
226
+ if (workspace.mode === 'form') return 'Focus MCP server form · Up/Down field · Left/Right cycle · Type edit · Enter save/cancel · Esc back';
227
+ if (workspace.mode === 'delete-confirm') return 'Focus remove confirmation · Enter/y remove · n/Esc cancel';
228
+ if (workspace.mode === 'reload-confirm') return 'Focus reload confirmation · Enter/y reload · n/Esc cancel';
229
+ return 'Focus MCP workspace · Up/Down choose · Enter view/action · a add · d remove · r reload · t tools · Esc close';
213
230
  }
214
231
 
215
232
  export function renderMcpWorkspace(workspace: McpWorkspace, width: number, height: number): Line[] {
216
233
  const metrics = getFullscreenWorkspaceMetrics({ width, height });
217
234
  const connected = workspace.servers.filter((server) => server.connected).length;
218
- const stateLabel = workspace.mode === 'browse' ? 'Browse' : workspace.mode === 'form' ? 'Command Preview' : 'Remove Guidance';
235
+ const stateLabel = workspace.mode === 'browse' ? 'Browse' : workspace.mode === 'form' ? 'Server Form' : workspace.mode === 'delete-confirm' ? 'Remove Confirm' : 'Reload Confirm';
219
236
  const mainHeader = workspace.mode === 'form'
220
- ? 'MCP server command preview'
237
+ ? 'MCP server form'
221
238
  : workspace.mode === 'delete-confirm'
222
- ? 'MCP remove command'
223
- : `Servers ${connected}/${workspace.servers.length} connected · Tools ${workspace.tools.length}`;
239
+ ? 'MCP remove confirmation'
240
+ : workspace.mode === 'reload-confirm'
241
+ ? 'MCP reload confirmation'
242
+ : `Servers ${connected}/${workspace.servers.length} connected · Tools ${workspace.tools.length}`;
224
243
 
225
244
  return renderFullscreenWorkspace({
226
245
  width,
@@ -240,7 +240,6 @@ export function renderModelPickerOverlay(
240
240
  if (caps.reasoning) capParts.push('Reasoning: \u2713');
241
241
  if (caps.multimodal) capParts.push('Vision: \u2713');
242
242
  if (caps.toolCalling) capParts.push('Tools: \u2713');
243
- if (caps.codeEditing) capParts.push('Code: \u2713');
244
243
  const capText = capParts.join(' ');
245
244
  const capLine = createOverlayContentLine(width, layout, borderFg, DEFAULT_OVERLAY_PALETTE.bodyBg);
246
245
  putRowText(capLine, layout.margin + 2, contentW, fitDisplay(truncateDisplay(capText, contentW), contentW), '244');
@@ -184,7 +184,6 @@ function detailLines(picker: ModelPickerModal, width: number): string[] {
184
184
  caps.reasoning ? 'reasoning' : '',
185
185
  caps.multimodal ? 'vision' : '',
186
186
  caps.toolCalling ? 'tools' : '',
187
- caps.codeEditing ? 'code' : '',
188
187
  ].filter(Boolean).join(', ') || 'standard';
189
188
  lines.push(`Selected: ${modelKey(selected)} | ${selected.displayName} | context ${formatContext(selected.contextWindow)} | ${capText}`);
190
189
  }
@@ -261,7 +260,6 @@ function renderModelRows(picker: ModelPickerModal, lines: Line[], rows: number,
261
260
  caps.reasoning ? 'R' : '-',
262
261
  caps.multimodal ? 'V' : '-',
263
262
  caps.toolCalling ? 'T' : '-',
264
- caps.codeEditing ? 'C' : '-',
265
263
  ].join('');
266
264
  let x = startX + 1;
267
265
  writeText(line, x, 2, padDisplay(marker, 2), { fg: PALETTE.text, bg, bold: selected }); x += 2;
@@ -161,16 +161,28 @@ function fieldHint(
161
161
  const rawValue = wizard.editBuffer.length > 0 ? wizard.editBuffer : field.placeholder;
162
162
  const editingValue = field.kind === 'masked' && wizard.editBuffer.length > 0
163
163
  ? '•'.repeat(Math.min(12, Math.max(4, wizard.editBuffer.length)))
164
- : rawValue;
164
+ : formatEditingValue(rawValue, field.kind === 'text' && field.multiline === true);
165
165
  return `Editing: ${editingValue}█`;
166
166
  }
167
167
 
168
168
  if (selected && field.kind === 'modelPicker') return `${field.hint} Press Enter to open picker.`;
169
- if (selected && field.kind === 'text') return `${field.hint} Press Enter to edit inline.`;
169
+ if (selected && field.kind === 'text') {
170
+ return field.multiline === true
171
+ ? `${field.hint} Press Enter to edit; Ctrl-J inserts a new line.`
172
+ : `${field.hint} Press Enter to edit inline.`;
173
+ }
170
174
  if (selected && field.kind === 'masked') return `${field.hint} Press Enter to edit inline.`;
171
175
  return field.hint;
172
176
  }
173
177
 
178
+ function formatEditingValue(value: string, multiline: boolean): string {
179
+ if (!multiline) return value;
180
+ const lines = value.split(/\r?\n/);
181
+ if (lines.length <= 1) return value;
182
+ const preview = lines[lines.length - 1] ?? '';
183
+ return `${preview} (${lines.length} lines)`;
184
+ }
185
+
174
186
  function fieldRowPrefix(
175
187
  wizard: OnboardingWizardController,
176
188
  field: OnboardingWizardFieldDefinition,
@@ -255,7 +267,9 @@ function renderFieldRow(
255
267
 
256
268
  function footerText(wizard: OnboardingWizardController): string {
257
269
  if (wizard.isEditingTextField()) {
258
- return '[Enter] Save value [Esc] Cancel edit [Backspace] Delete char [Del/Ctrl+U] Clear value';
270
+ return wizard.isEditingMultilineTextField()
271
+ ? '[Enter] Save value [Ctrl-J] New line [Esc] Cancel edit [Backspace] Delete char [Del/Ctrl+U] Clear value'
272
+ : '[Enter] Save value [Esc] Cancel edit [Backspace] Delete char [Del/Ctrl+U] Clear value';
259
273
  }
260
274
 
261
275
  return '[Enter] Toggle/open [Esc] Close [Tab/Shift+Tab] Screen [↑↓] Move [Del/Ctrl+U] Clear input';
@@ -263,7 +277,9 @@ function footerText(wizard: OnboardingWizardController): string {
263
277
 
264
278
  function controlsText(wizard: OnboardingWizardController): string {
265
279
  if (wizard.isEditingTextField()) {
266
- return 'Controls: Enter saves, Esc cancels, Backspace deletes, Del clears.';
280
+ return wizard.isEditingMultilineTextField()
281
+ ? 'Controls: Enter saves, Ctrl-J inserts a line, Esc cancels, Backspace deletes, Del clears.'
282
+ : 'Controls: Enter saves, Esc cancels, Backspace deletes, Del clears.';
267
283
  }
268
284
  return 'Controls: Enter selects, Del clears, Tab moves.';
269
285
  }
@@ -46,7 +46,7 @@ export function renderPanelPickerOverlay(
46
46
 
47
47
  // ── Title bar ──────────────────────────────────────────────────────────────
48
48
  const titleLine = createOverlayBorderLine(width, layout, '┌', '─', '┐', borderFg);
49
- putOverlayText(titleLine, layout.margin + 2, layout.width - 4, 'Open Panel Workspace', { fg: titleFg, bold: true });
49
+ putOverlayText(titleLine, layout.margin + 2, layout.width - 4, 'Deferred Workspace Picker', { fg: titleFg, bold: true });
50
50
  lines.push(titleLine);
51
51
 
52
52
  // ── Search bar (shown when query is non-empty) ──────────────────────────────
@@ -51,7 +51,7 @@ export function renderProfilePickerModal(
51
51
  });
52
52
  sections.push({
53
53
  type: 'text',
54
- content: 'Use /profiles save <name> --yes to save the current settings as a profile.',
54
+ content: 'Use /agent profiles to create and manage isolated Agent profile homes.',
55
55
  style: { fg: '240', dim: true },
56
56
  });
57
57
  } else {
@@ -114,7 +114,7 @@ export function renderProfilePickerModal(
114
114
  margin: boxMargin,
115
115
  targetContentRows,
116
116
  sections,
117
- hints: ['[Up/Down] Navigate', '[Enter] Load', '/profiles save|delete --yes', '[Esc] Close'],
117
+ hints: ['[Up/Down] Navigate', '[Enter] Load', 'Agent profiles: /agent profiles', '[Esc] Close'],
118
118
  },
119
119
  width,
120
120
  );
@@ -83,12 +83,12 @@ export const CATEGORY_LABELS: Record<(typeof SETTINGS_CATEGORIES)[number], strin
83
83
  storage: 'Storage',
84
84
  permissions: 'Permissions',
85
85
  orchestration: 'Orchestration',
86
- wrfc: 'WRFC Delegation',
86
+ wrfc: 'Build Delegation',
87
87
  helper: 'Helper',
88
88
  tts: 'TTS',
89
- service: 'Runtime Install',
90
- controlPlane: 'Runtime API',
91
- httpListener: 'Inbound Events',
89
+ service: 'Connected Host',
90
+ controlPlane: 'Connected API',
91
+ httpListener: 'Inbound Delivery',
92
92
  web: 'Browser Companion',
93
93
  batch: 'Batch',
94
94
  automation: 'Automation',
@@ -108,7 +108,7 @@ export const CATEGORY_LABELS: Record<(typeof SETTINGS_CATEGORIES)[number], strin
108
108
  export const SETTING_LABELS: Partial<Record<string, string>> = {
109
109
  'ui.systemMessages': 'System Message Target',
110
110
  'ui.operationalMessages': 'Operational Message Target',
111
- 'ui.wrfcMessages': 'Delegated WRFC Message Target',
111
+ 'ui.wrfcMessages': 'Delegated Build Message Target',
112
112
  'ui.voiceEnabled': 'Voice Interaction',
113
113
  'behavior.autoCompactThreshold': 'Auto-Compact %',
114
114
  'behavior.staleContextWarnings': 'Context Warnings',
@@ -124,24 +124,24 @@ export const SETTING_LABELS: Partial<Record<string, string>> = {
124
124
  'helper.globalProvider': 'Helper Provider',
125
125
  'helper.globalModel': 'Helper Model',
126
126
  // Runtime API
127
- 'controlPlane.enabled': 'Runtime API Enabled',
128
- 'controlPlane.hostMode': 'Runtime API Host Mode',
129
- 'controlPlane.host': 'Runtime API Host',
130
- 'controlPlane.port': 'Runtime API Port',
131
- 'controlPlane.baseUrl': 'Runtime API Base URL',
132
- 'controlPlane.streamMode': 'Runtime API Stream Mode',
133
- 'controlPlane.allowRemote': 'Runtime API Allow Remote',
134
- 'controlPlane.trustProxy': 'Runtime API Trust Proxy',
135
- 'controlPlane.tls.mode': 'Runtime API TLS Mode',
136
- 'controlPlane.tls.certFile': 'Runtime API TLS Cert',
137
- 'controlPlane.tls.keyFile': 'Runtime API TLS Key',
138
- // Inbound event endpoint
139
- 'httpListener.hostMode': 'HTTP Host Mode',
140
- 'httpListener.host': 'HTTP Host',
141
- 'httpListener.port': 'HTTP Port',
142
- 'httpListener.trustProxy': 'HTTP Trust Proxy',
143
- 'httpListener.tls.mode': 'HTTP TLS Mode',
144
- 'httpListener.tls.certFile': 'HTTP TLS Cert',
127
+ 'controlPlane.enabled': 'Connected API Enabled',
128
+ 'controlPlane.hostMode': 'Connected API Host Mode',
129
+ 'controlPlane.host': 'Connected API Host',
130
+ 'controlPlane.port': 'Connected API Port',
131
+ 'controlPlane.baseUrl': 'Connected API Base URL',
132
+ 'controlPlane.streamMode': 'Connected API Stream Mode',
133
+ 'controlPlane.allowRemote': 'Connected API Allow Remote',
134
+ 'controlPlane.trustProxy': 'Connected API Trust Proxy',
135
+ 'controlPlane.tls.mode': 'Connected API TLS Mode',
136
+ 'controlPlane.tls.certFile': 'Connected API TLS Cert',
137
+ 'controlPlane.tls.keyFile': 'Connected API TLS Key',
138
+ // Inbound delivery endpoint
139
+ 'httpListener.hostMode': 'Inbound Delivery Host Mode',
140
+ 'httpListener.host': 'Inbound Delivery Host',
141
+ 'httpListener.port': 'Inbound Delivery Port',
142
+ 'httpListener.trustProxy': 'Inbound Delivery Trust Proxy',
143
+ 'httpListener.tls.mode': 'Inbound Delivery TLS Mode',
144
+ 'httpListener.tls.certFile': 'Inbound Delivery TLS Cert',
145
145
  // Browser companion
146
146
  'web.enabled': 'Web Enabled',
147
147
  'web.hostMode': 'Web Host Mode',
@@ -7,7 +7,7 @@
7
7
 
8
8
  import type { Line } from '../types/grid.ts';
9
9
  import type { SettingsModal, SettingEntry, FlagEntry, McpEntry, SubscriptionEntry, SettingsCategory } from '../input/settings-modal.ts';
10
- import { isExternalDaemonOwnedSettingKey, SETTINGS_CATEGORIES, SETTINGS_CATEGORY_GROUPS } from '../input/settings-modal.ts';
10
+ import { isExternalHostOwnedSettingKey, SETTINGS_CATEGORIES, SETTINGS_CATEGORY_GROUPS } from '../input/settings-modal.ts';
11
11
  import { getDisplayWidth, wrapText } from '../utils/terminal-width.ts';
12
12
  import { CATEGORY_LABELS, describeUiRouting, formatValue, getSettingLabel, inferSubscriptionRouteReason, valueColor } from './settings-modal-helpers.ts';
13
13
  import { isSecretConfigKey } from '../config/secret-config.ts';
@@ -30,34 +30,34 @@ const CATEGORY_INFO: Record<SettingsCategory, string> = {
30
30
  behavior: 'Day-to-day shell behavior: approval posture, compaction, history, guidance, notifications, stale-context warnings, return context, and Human-in-the-Loop mode.',
31
31
  storage: 'Local storage posture, including secret storage policy and maximum artifact size for Agent Knowledge, artifacts, and document ingestion.',
32
32
  permissions: 'Permission mode and tool-class policy. These settings decide whether the shell prompts before read/write/exec/network/agent actions.',
33
- orchestration: 'Agent orchestration limits and recursion controls.',
34
- wrfc: 'WRFC is external to normal Agent operation. Review these compatibility values only for explicit GoodVibes TUI build delegation.',
33
+ orchestration: 'Hidden compatibility settings. Normal Agent operation stays serial and does not expose local spawn fanout.',
34
+ wrfc: 'Build-review routing is external to normal Agent operation. Review these compatibility values only for explicit delegated build work.',
35
35
  helper: 'Helper model defaults used by helper subsystems when they do not use the main chat route.',
36
36
  tts: 'Text-to-speech provider, voice, and optional spoken-turn LLM overrides.',
37
- service: 'Connected-service installation posture. Agent shows these compatibility keys for inspection only and does not install, start, stop, restart, or autostart anything.',
38
- controlPlane: 'Connected-service API settings. Agent uses these settings for access and does not mutate bind posture.',
39
- httpListener: 'Inbound event endpoint settings owned by connected GoodVibes services. Agent inspects readiness and does not expose endpoints.',
37
+ service: 'Connected-host status posture. Agent inspects these values only and does not install, start, stop, restart, or autostart anything.',
38
+ controlPlane: 'Connected API settings. Agent uses these values for access and does not mutate bind posture.',
39
+ httpListener: 'Inbound delivery endpoint settings owned by the connected GoodVibes host. Agent inspects readiness and does not expose endpoints.',
40
40
  web: 'External browser companion settings. Agent does not own browser hosting or network bind lifecycle.',
41
- batch: 'Batch execution settings reported from connected GoodVibes services. Agent does not own remote queue provisioning.',
41
+ batch: 'Queued execution settings reported from the connected GoodVibes host. Agent does not own remote queue provisioning.',
42
42
  automation: 'Scheduled and automated run settings, concurrency, timeout, catch-up, cooldown, and retention behavior.',
43
43
  watchers: 'File/process watcher heartbeat, polling, and recovery-window behavior.',
44
- runtime: 'Connected-service guardrails such as companion chat limiter and event bus listener caps.',
44
+ runtime: 'Connected-host guardrails such as companion chat limits and event-stream caps.',
45
45
  telemetry: 'Telemetry payload policy.',
46
46
  cache: 'Provider and model cache behavior, TTL, and hit-rate monitoring.',
47
47
  mcp: 'MCP server trust and scope review. Trust changes can expose local files, tools, databases, browsers, or remote automation depending on the server.',
48
48
  surfaces: 'Messaging and notification channel accounts such as Slack, Discord, ntfy, Telegram, chat bridges, and delivery providers.',
49
49
  release: 'Release-channel preference.',
50
- danger: 'High-impact service switches. Agent renders service-owned switches read-only; change them outside Agent.',
50
+ danger: 'High-impact host switches. Agent renders host-owned switches read-only; change them outside Agent.',
51
51
  tools: 'Tool LLM and helper model routing. Empty provider/model values inherit the active chat route unless a specific helper/tool route is set.',
52
52
  flags: 'Feature flags are SDK gates. They are separate from normal config keys because they enable or disable staged behavior.',
53
- network: 'Read-only view of connected GoodVibes API, inbound-event, and browser companion bind posture plus editable Agent network settings.',
53
+ network: 'Read-only view of connected GoodVibes API, inbound delivery, and browser companion bind posture plus editable Agent network settings.',
54
54
  };
55
55
 
56
56
  const ENUM_VALUE_DESCRIPTIONS: Record<string, Record<string, string>> = {
57
57
  'behavior.hitlMode': {
58
58
  quiet: 'Minimize operational interruptions and surface fewer Human-in-the-Loop prompts.',
59
59
  balanced: 'Show important Human-in-the-Loop prompts without turning routine work into noise.',
60
- operator: 'Surface more operational detail for users actively supervising agents, tools, services, and automation.',
60
+ operator: 'Surface more operational detail for users actively supervising agents, tools, connected-host posture, and automation.',
61
61
  },
62
62
  'behavior.guidanceMode': {
63
63
  off: 'Do not add extra guidance beyond direct command output.',
@@ -105,9 +105,9 @@ const ENUM_VALUE_DESCRIPTIONS: Record<string, Record<string, string>> = {
105
105
  both: 'Show operational messages in both panels and the transcript.',
106
106
  },
107
107
  'ui.wrfcMessages': {
108
- panel: 'Show explicit delegated-build WRFC messages in panels only.',
109
- conversation: 'Show explicit delegated-build WRFC messages inline in the transcript.',
110
- both: 'Show explicit delegated-build WRFC messages in both panels and the transcript.',
108
+ panel: 'Show explicit delegated build messages in panels only.',
109
+ conversation: 'Show explicit delegated build messages inline in the transcript.',
110
+ both: 'Show explicit delegated build messages in both panels and the transcript.',
111
111
  },
112
112
  'surfaces.telegram.mode': {
113
113
  webhook: 'Receive Telegram updates through externally hosted delivery.',
@@ -148,7 +148,7 @@ function buildSettingContext(modal: SettingsModal, entry: SettingEntry): string[
148
148
  ];
149
149
 
150
150
  if (entry.locked) lines.push(`Locked: ${entry.lockReason ?? 'This setting is locked by a higher-priority layer.'}`);
151
- if (entry.conflict) lines.push(`Conflict: inspect with /settings and resolve service-owned sync state in the owning host.`);
151
+ if (entry.conflict) lines.push(`Conflict: inspect with /settings and resolve host-owned sync state in the owning host.`);
152
152
 
153
153
  lines.push('', entry.setting.description);
154
154
 
@@ -248,7 +248,7 @@ function buildSubscriptionContext(modal: SettingsModal, entry: SubscriptionEntry
248
248
  ? modal.subscriptionLogoutConfirmationTarget === entry.provider
249
249
  ? `Press Enter again to sign out ${entry.provider}. Move selection or close config to cancel.`
250
250
  : 'Press Enter to review sign-out for this provider session.'
251
- : `Use /subscription login ${entry.provider} start to begin OAuth sign-in for this provider.`;
251
+ : `Open /agent setup and choose Start subscription login for ${entry.provider}.`;
252
252
  return [
253
253
  entry.provider,
254
254
  `State: ${entry.state}`,
@@ -478,8 +478,8 @@ function footerText(modal: SettingsModal): string {
478
478
  if (modal.currentCategory === 'mcp') return 'Focus settings · Up/Down server · Left categories · Tab pane · Enter edit trust · Esc close';
479
479
  if (modal.currentCategory === 'flags') return 'Focus feature flags · Up/Down flag · Left categories · Tab pane · Enter/Space toggle · Esc close';
480
480
  const selected = modal.getSelected();
481
- if (selected && isExternalDaemonOwnedSettingKey(selected.setting.key)) {
482
- return 'Read-only connected-service setting · Change from GoodVibes TUI or the owning host · Esc close';
481
+ if (selected && isExternalHostOwnedSettingKey(selected.setting.key)) {
482
+ return 'Read-only connected-host setting · Change from GoodVibes TUI or the owning host · Esc close';
483
483
  }
484
484
  return 'Focus settings · Up/Down setting · Left categories · Tab pane · Enter/Space edit/toggle · R reset · Esc close';
485
485
  }
@@ -20,7 +20,7 @@ export function classifySystemMessage(content: string): SystemMessageType {
20
20
  if (/FAILED|cascade abort/i.test(content)) return 'error';
21
21
  // Review failed to reach threshold → warning (yellow, retry in progress)
22
22
  if (/spawning a fix agent/i.test(content)) return 'warning';
23
- // All other WRFC messages (started, passed, auto-committed, gate passed, review ok) → info
23
+ // All other explicit delegated review/build messages classify as info.
24
24
  return 'info';
25
25
  }
26
26
 
@@ -0,0 +1,129 @@
1
+ import type { ConfigManager } from '@pellux/goodvibes-sdk/platform/config';
2
+ import type { ConversationFollowUpItem } from '@pellux/goodvibes-sdk/platform/core';
3
+ import type { AgentManager } from '@pellux/goodvibes-sdk/platform/tools';
4
+ import type {
5
+ AgentEvent,
6
+ ProviderEvent,
7
+ RuntimeEventBus,
8
+ } from '@/runtime/index.ts';
9
+ import type { createDomainDispatch } from './store/index.ts';
10
+
11
+ const AGENT_STATUS_INTERVAL_MS = 30_000;
12
+
13
+ export interface AgentRuntimeMessageRouter {
14
+ low(message: string): void;
15
+ high(message: string): void;
16
+ }
17
+
18
+ export interface AgentRuntimeEventBridgeOptions {
19
+ readonly runtimeBus: RuntimeEventBus;
20
+ readonly domainDispatch: ReturnType<typeof createDomainDispatch>;
21
+ readonly getSystemMessageRouter: () => AgentRuntimeMessageRouter | null;
22
+ readonly queueConversationFollowUp?: (item: ConversationFollowUpItem) => void;
23
+ readonly requestRender: () => void;
24
+ readonly configManager: ConfigManager;
25
+ readonly agentManager: AgentManager;
26
+ }
27
+
28
+ function withRouter(
29
+ getSystemMessageRouter: () => AgentRuntimeMessageRouter | null,
30
+ action: (router: AgentRuntimeMessageRouter) => void,
31
+ ): void {
32
+ const router = getSystemMessageRouter();
33
+ if (router) action(router);
34
+ }
35
+
36
+ function formatAgentTask(task: string): string {
37
+ return task.length > 50 ? `${task.slice(0, 50)}...` : task;
38
+ }
39
+
40
+ export function registerAgentRuntimeEvents(options: AgentRuntimeEventBridgeOptions): {
41
+ unsubs: Array<() => void>;
42
+ agentStatusIntervalRef: { value: ReturnType<typeof setInterval> | null };
43
+ } {
44
+ const {
45
+ runtimeBus,
46
+ domainDispatch,
47
+ getSystemMessageRouter,
48
+ queueConversationFollowUp,
49
+ requestRender,
50
+ agentManager,
51
+ } = options;
52
+ const unsubs: Array<() => void> = [];
53
+
54
+ unsubs.push(runtimeBus.onDomain('turn', (env) => {
55
+ domainDispatch.dispatchTurnEvent(env.payload);
56
+ }));
57
+ unsubs.push(runtimeBus.onDomain('agents', (env) => {
58
+ domainDispatch.dispatchAgentEvent(env.payload);
59
+ }));
60
+ unsubs.push(runtimeBus.onDomain('orchestration', (env) => {
61
+ domainDispatch.dispatchOrchestrationEvent(env.payload);
62
+ }));
63
+ unsubs.push(runtimeBus.onDomain('communication', (env) => {
64
+ domainDispatch.dispatchCommunicationEvent(env.payload);
65
+ }));
66
+ unsubs.push(runtimeBus.onDomain('compaction', (env) => {
67
+ domainDispatch.dispatchCompactionEvent(env.payload);
68
+ }));
69
+ unsubs.push(runtimeBus.onDomain('transport', (env) => {
70
+ domainDispatch.dispatchTransportEvent(env.payload);
71
+ }));
72
+
73
+ unsubs.push(runtimeBus.on<Extract<ProviderEvent, { type: 'MODEL_FALLBACK' }>>('MODEL_FALLBACK', ({ payload }) => {
74
+ withRouter(getSystemMessageRouter, (router) => {
75
+ router.high(`[Model] ${payload.from} exhausted across all providers. Automatically falling back to ${payload.to} via ${payload.provider}.`);
76
+ });
77
+ requestRender();
78
+ }));
79
+ unsubs.push(runtimeBus.on<Extract<AgentEvent, { type: 'AGENT_STREAM_DELTA' }>>('AGENT_STREAM_DELTA', () => {
80
+ requestRender();
81
+ }));
82
+ unsubs.push(runtimeBus.on<Extract<AgentEvent, { type: 'AGENT_PROGRESS' }>>('AGENT_PROGRESS', () => {
83
+ requestRender();
84
+ }));
85
+ unsubs.push(runtimeBus.on<Extract<AgentEvent, { type: 'AGENT_COMPLETED' }>>('AGENT_COMPLETED', ({ payload }) => {
86
+ const record = agentManager.getStatus(payload.agentId);
87
+ if (record) {
88
+ const durationSeconds = record.completedAt !== undefined ? Math.round((record.completedAt - record.startedAt) / 1000) : 0;
89
+ const taskSnippet = formatAgentTask(record.task);
90
+ withRouter(getSystemMessageRouter, (router) => {
91
+ router.low(`[Agent task] ${record.template} ${payload.agentId.slice(-8)} completed in ${durationSeconds}s: "${taskSnippet}"`);
92
+ });
93
+ queueConversationFollowUp?.({
94
+ key: `agent:${payload.agentId}:completed`,
95
+ summary: `${record.template} agent ${payload.agentId.slice(-8)} completed "${taskSnippet}" in ${durationSeconds}s after ${record.toolCallCount} tool calls.`,
96
+ });
97
+ }
98
+ requestRender();
99
+ }));
100
+ unsubs.push(runtimeBus.on<Extract<AgentEvent, { type: 'AGENT_FAILED' }>>('AGENT_FAILED', ({ payload }) => {
101
+ const record = agentManager.getStatus(payload.agentId);
102
+ if (record && record.status !== 'cancelled') {
103
+ const durationSeconds = record.completedAt !== undefined ? Math.round((record.completedAt - record.startedAt) / 1000) : 0;
104
+ const taskSnippet = formatAgentTask(record.task);
105
+ withRouter(getSystemMessageRouter, (router) => {
106
+ router.low(`[Agent task] ${record.template} ${payload.agentId.slice(-8)} failed in ${durationSeconds}s: ${payload.error.slice(0, 80)}`);
107
+ });
108
+ queueConversationFollowUp?.({
109
+ key: `agent:${payload.agentId}:failed`,
110
+ summary: `${record.template} agent ${payload.agentId.slice(-8)} failed while working on "${taskSnippet}": ${payload.error.slice(0, 120)}`,
111
+ });
112
+ }
113
+ requestRender();
114
+ }));
115
+
116
+ const agentStatusIntervalRef = { value: null as ReturnType<typeof setInterval> | null };
117
+ agentStatusIntervalRef.value = setInterval(() => {
118
+ const running = agentManager.list().filter((agent) => agent.status === 'running');
119
+ if (running.length === 0) return;
120
+ const lines = running.map((agent) => ` ${agent.id.slice(-8)}: ${agent.progress ?? agent.status}`);
121
+ withRouter(getSystemMessageRouter, (router) => {
122
+ router.low(`[Agent task] ${running.length} running:\n${lines.join('\n')}`);
123
+ });
124
+ requestRender();
125
+ }, AGENT_STATUS_INTERVAL_MS);
126
+ agentStatusIntervalRef.value.unref?.();
127
+
128
+ return { unsubs, agentStatusIntervalRef };
129
+ }
@@ -171,8 +171,9 @@ export function createBootstrapCommandActions(
171
171
  } = options;
172
172
 
173
173
  const showPanel = (panelId: string, pane?: 'top' | 'bottom') => {
174
- panelManager.open(panelId, pane);
175
- panelManager.show();
174
+ void pane;
175
+ panelManager.hide();
176
+ conversation.log(`Panel "${panelId}" is deferred in GoodVibes Agent. Use /agent for the operator workspace.`, { fg: '214' });
176
177
  requestRender();
177
178
  };
178
179
 
@@ -26,12 +26,12 @@ import {
26
26
  } from '@/runtime/index.ts';
27
27
  import { loadBootstrapSystemPrompt, syncConfiguredServices } from '@/runtime/index.ts';
28
28
  import { registerBootstrapHookBridge } from '@/runtime/index.ts';
29
- import { registerBootstrapRuntimeEvents } from '@/runtime/index.ts';
30
29
  import { createRuntimeServices, type RuntimeServices } from './services.ts';
31
30
  import { createUiRuntimeServices, type UiRuntimeServices } from './ui-services.ts';
32
31
  import { installAgentToolPolicyGuard } from '../tools/agent-tool-policy-guard.ts';
33
32
  import { registerAgentLocalRegistryTool } from '../tools/agent-local-registry-tool.ts';
34
33
  import { GOODVIBES_AGENT_SURFACE_ROOT } from '../config/surface.ts';
34
+ import { registerAgentRuntimeEvents } from './agent-runtime-events.ts';
35
35
 
36
36
  export interface BootstrapCoreState {
37
37
  readonly userSessionId: string;
@@ -211,7 +211,6 @@ export async function initializeBootstrapCore(
211
211
  agentManager: services.agentManager,
212
212
  agentMessageBus: services.agentMessageBus,
213
213
  archetypeLoader: services.archetypeLoader,
214
- wrfcController: services.wrfcController,
215
214
  webSearchService: services.webSearchService,
216
215
  channelRegistry: services.channelPlugins,
217
216
  remoteRunnerRegistry: services.remoteRunnerRegistry,
@@ -314,7 +313,7 @@ export async function initializeBootstrapCore(
314
313
  const runtimeSessionIdRef = { value: userSessionId };
315
314
  const systemMessageRouterRef: { value: SystemMessageRouter | null } = { value: null };
316
315
  const conversationFollowUpRef: { value: ((item: ConversationFollowUpItem) => void) | null } = { value: null };
317
- const { unsubs: runtimeUnsubs, agentStatusIntervalRef } = registerBootstrapRuntimeEvents({
316
+ const { unsubs: runtimeUnsubs, agentStatusIntervalRef } = registerAgentRuntimeEvents({
318
317
  runtimeBus,
319
318
  domainDispatch,
320
319
  getSystemMessageRouter: () => systemMessageRouterRef.value,
@@ -322,69 +321,10 @@ export async function initializeBootstrapCore(
322
321
  requestRender,
323
322
  configManager,
324
323
  agentManager: services.agentManager,
325
- wrfcController: services.wrfcController,
326
324
  });
327
325
 
328
- // ── TUI-specific WRFC constraint-propagation event subscriptions (SDK 0.23.0) ──
329
- // These supplement the SDK's registerBootstrapRuntimeEvents which handles the
330
- // core WORKFLOW_REVIEW_COMPLETED / WORKFLOW_CHAIN_CREATED messages.
331
- // The SDK does not surface constraint-specific system messages; the TUI layer
332
- // adds them here so operators can observe constraint enumeration and violations
333
- // in the SystemMessagesPanel and main conversation.
334
- runtimeUnsubs.push(
335
- runtimeBus.on<Extract<import('@/runtime/index.ts').WorkflowEvent, { type: 'WORKFLOW_CONSTRAINTS_ENUMERATED' }>>(
336
- 'WORKFLOW_CONSTRAINTS_ENUMERATED',
337
- ({ payload }) => {
338
- const router = systemMessageRouterRef.value;
339
- if (!router) return;
340
- const count = payload.constraints.length;
341
- if (count > 0) {
342
- router.wrfc(
343
- `[WRFC] Engineer enumerated ${count} constraint${count !== 1 ? 's' : ''} for chain ${payload.chainId.slice(0, 12)}`,
344
- 'low',
345
- );
346
- }
347
- requestRender();
348
- },
349
- ),
350
- );
351
- runtimeUnsubs.push(
352
- runtimeBus.on<Extract<import('@/runtime/index.ts').WorkflowEvent, { type: 'WORKFLOW_FIX_ATTEMPTED' }>>(
353
- 'WORKFLOW_FIX_ATTEMPTED',
354
- ({ payload }) => {
355
- const router = systemMessageRouterRef.value;
356
- if (!router) return;
357
- const targetIds = payload.targetConstraintIds;
358
- if (targetIds && targetIds.length > 0) {
359
- router.wrfc(
360
- `[WRFC] Fix #${payload.attempt} targeting ${targetIds.length} constraint${targetIds.length !== 1 ? 's' : ''} on chain ${payload.chainId.slice(0, 12)}`,
361
- 'low',
362
- );
363
- requestRender();
364
- }
365
- },
366
- ),
367
- );
368
- runtimeUnsubs.push(
369
- runtimeBus.on<Extract<import('@/runtime/index.ts').WorkflowEvent, { type: 'WORKFLOW_REVIEW_COMPLETED' }>>(
370
- 'WORKFLOW_REVIEW_COMPLETED',
371
- ({ payload }) => {
372
- const router = systemMessageRouterRef.value;
373
- if (!router) return;
374
- const unsatisfied = payload.unsatisfiedConstraintIds;
375
- if (!payload.passed && unsatisfied && unsatisfied.length > 0) {
376
- router.wrfc(
377
- `[WRFC] ✗ Chain ${payload.chainId.slice(0, 12)}: ${unsatisfied.length} constraint violation${unsatisfied.length !== 1 ? 's' : ''} forced failure`,
378
- 'high',
379
- );
380
- requestRender();
381
- }
382
- },
383
- ),
384
- );
385
-
386
- // Subscribe to companion main-chat messages received from the daemon's HTTP layer.
387
- // The daemon emits COMPANION_MESSAGE_RECEIVED on the runtime bus when a companion
326
+ // Subscribe to companion main-chat messages received from the connected host's HTTP layer.
327
+ // The connected host emits COMPANION_MESSAGE_RECEIVED on the runtime bus when a companion
388
328
  // POST /api/sessions/:id/messages with kind='message' arrives.
389
329
  //
390
330
  // bootstrap.ts patches orchestratorHandleUserInputRef.value after the Orchestrator