@pellux/goodvibes-agent 1.1.7 → 1.2.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 (255) hide show
  1. package/CHANGELOG.md +170 -0
  2. package/README.md +46 -30
  3. package/dist/package/{ast-grep-napi.linux-x64-gnu-mkk8xwww.node → ast-grep-napi.linux-x64-gnu-swtppvy9.node} +0 -0
  4. package/dist/package/{ast-grep-napi.linux-x64-musl-ryqtgdv6.node → ast-grep-napi.linux-x64-musl-ttfcdtap.node} +0 -0
  5. package/dist/package/main.js +132577 -91483
  6. package/docs/README.md +14 -7
  7. package/docs/channels-remote-and-api.md +8 -5
  8. package/docs/connected-host.md +14 -12
  9. package/docs/getting-started.md +56 -30
  10. package/docs/knowledge-artifacts-and-multimodal.md +7 -5
  11. package/docs/project-planning.md +2 -2
  12. package/docs/providers-and-routing.md +11 -3
  13. package/docs/tools-and-commands.md +114 -45
  14. package/docs/voice-and-live-tts.md +3 -1
  15. package/package.json +3 -2
  16. package/release/release-notes.md +130 -5
  17. package/release/release-readiness.json +120 -90
  18. package/src/agent/assistant-cockpit.ts +247 -0
  19. package/src/agent/autonomy-schedule-format.ts +96 -0
  20. package/src/agent/autonomy-schedule.ts +514 -0
  21. package/src/agent/channel-delivery-receipts.ts +292 -0
  22. package/src/agent/competitive-feature-inventory.ts +296 -0
  23. package/src/agent/document-registry-types.ts +106 -0
  24. package/src/agent/document-registry.ts +734 -0
  25. package/src/agent/harness-control.ts +2 -2
  26. package/src/agent/memory-prompt.ts +2 -2
  27. package/src/agent/operator-actions.ts +50 -6
  28. package/src/agent/persona-registry.ts +8 -0
  29. package/src/agent/project-context-files.ts +273 -0
  30. package/src/agent/prompt-context-receipts.ts +502 -0
  31. package/src/agent/reminder-schedule-format.ts +16 -2
  32. package/src/agent/research-run-registry.ts +582 -0
  33. package/src/agent/research-source-registry.ts +441 -0
  34. package/src/agent/routine-registry.ts +19 -3
  35. package/src/agent/routine-schedule-format.ts +27 -2
  36. package/src/agent/runtime-profile-starters.ts +7 -0
  37. package/src/agent/runtime-profile.ts +106 -4
  38. package/src/agent/schedule-edit-format.ts +129 -0
  39. package/src/agent/schedule-edit.ts +496 -0
  40. package/src/agent/schedule-next-routes.ts +42 -0
  41. package/src/agent/setup-wizard-checkpoint.ts +140 -0
  42. package/src/agent/setup-wizard.ts +447 -0
  43. package/src/agent/skill-registry-types.ts +102 -0
  44. package/src/agent/skill-registry.ts +81 -107
  45. package/src/agent/vibe-confirmation-routes.ts +62 -0
  46. package/src/agent/vibe-file.ts +285 -0
  47. package/src/cli/agent-knowledge-command.ts +45 -2
  48. package/src/cli/help.ts +3 -0
  49. package/src/cli/profiles-command.ts +25 -11
  50. package/src/config/agent-settings-policy.ts +1 -18
  51. package/src/input/agent-workspace-activation.ts +53 -0
  52. package/src/input/agent-workspace-artifact-browser-editor.ts +494 -0
  53. package/src/input/agent-workspace-artifact-metadata.ts +17 -0
  54. package/src/input/agent-workspace-basic-command-editors.ts +5 -1
  55. package/src/input/agent-workspace-categories.ts +153 -155
  56. package/src/input/agent-workspace-channel-triage.ts +481 -0
  57. package/src/input/agent-workspace-channels.ts +263 -0
  58. package/src/input/agent-workspace-command-editor.ts +152 -0
  59. package/src/input/agent-workspace-context-snapshot.ts +349 -0
  60. package/src/input/agent-workspace-delegation-editor-submission.ts +8 -0
  61. package/src/input/agent-workspace-document-editor.ts +502 -0
  62. package/src/input/agent-workspace-document-ops-editor.ts +523 -0
  63. package/src/input/agent-workspace-host-category.ts +1 -1
  64. package/src/input/agent-workspace-local-library-snapshot.ts +167 -0
  65. package/src/input/agent-workspace-model-compare-editor.ts +376 -0
  66. package/src/input/agent-workspace-model-compare-prompt-submission.ts +552 -0
  67. package/src/input/agent-workspace-model-compare-types.ts +82 -0
  68. package/src/input/agent-workspace-model-compare-utils.ts +35 -0
  69. package/src/input/agent-workspace-onboarding-categories.ts +141 -0
  70. package/src/input/agent-workspace-operations-command-editor-submission.ts +53 -0
  71. package/src/input/agent-workspace-operations-command-editors.ts +22 -0
  72. package/src/input/agent-workspace-research-report-editor.ts +212 -0
  73. package/src/input/agent-workspace-research-run-editor.ts +144 -0
  74. package/src/input/agent-workspace-research-source-editor.ts +167 -0
  75. package/src/input/agent-workspace-review-packet-snapshot.ts +593 -0
  76. package/src/input/agent-workspace-review-packet-utils.ts +265 -0
  77. package/src/input/agent-workspace-settings.ts +262 -30
  78. package/src/input/agent-workspace-setup-checkpoint-action.ts +127 -0
  79. package/src/input/agent-workspace-setup-snapshot.ts +198 -0
  80. package/src/input/agent-workspace-setup.ts +34 -1
  81. package/src/input/agent-workspace-snapshot.ts +162 -147
  82. package/src/input/agent-workspace-types.ts +287 -2
  83. package/src/input/agent-workspace.ts +18 -0
  84. package/src/input/command-registry.ts +9 -2
  85. package/src/input/commands/agent-runtime-profile-runtime.ts +28 -13
  86. package/src/input/commands/channels-runtime.ts +102 -114
  87. package/src/input/commands/delegation-runtime.ts +87 -24
  88. package/src/input/commands/knowledge-browser-flags.ts +12 -0
  89. package/src/input/commands/knowledge.ts +28 -14
  90. package/src/input/commands/operator-actions-runtime.ts +6 -3
  91. package/src/input/commands/schedule-runtime.ts +71 -14
  92. package/src/input/commands/session-content.ts +2 -2
  93. package/src/input/commands/shell-core.ts +2 -0
  94. package/src/input/commands/vibe-runtime.ts +140 -0
  95. package/src/input/commands.ts +2 -0
  96. package/src/input/connected-host-routes.ts +123 -0
  97. package/src/input/settings-modal-types.ts +14 -0
  98. package/src/main.ts +15 -15
  99. package/src/panels/qr-panel.ts +2 -2
  100. package/src/renderer/agent-workspace-context-lines.ts +686 -0
  101. package/src/renderer/agent-workspace.ts +30 -419
  102. package/src/renderer/settings-modal-helpers.ts +12 -0
  103. package/src/renderer/settings-modal.ts +12 -0
  104. package/src/runtime/bootstrap-command-context.ts +11 -1
  105. package/src/runtime/bootstrap-command-parts.ts +14 -3
  106. package/src/runtime/bootstrap-core.ts +39 -1
  107. package/src/runtime/bootstrap-shell.ts +6 -0
  108. package/src/runtime/bootstrap.ts +113 -30
  109. package/src/runtime/connected-host-auth.ts +3 -2
  110. package/src/runtime/execution-ledger.ts +231 -0
  111. package/src/runtime/services.ts +88 -10
  112. package/src/runtime/tool-permission-safety.ts +199 -5
  113. package/src/shell/session-continuity-hints.ts +39 -0
  114. package/src/tools/agent-artifacts-tool.ts +606 -0
  115. package/src/tools/agent-audit-tool.ts +155 -0
  116. package/src/tools/agent-autonomy-schedule-tool.ts +238 -0
  117. package/src/tools/agent-autonomy-tool.ts +140 -0
  118. package/src/tools/agent-channel-send-tool.ts +24 -2
  119. package/src/tools/agent-channels-tool.ts +140 -0
  120. package/src/tools/agent-computer-tool.ts +168 -0
  121. package/src/tools/agent-context-policy.ts +137 -7
  122. package/src/tools/agent-context-tool.ts +143 -0
  123. package/src/tools/agent-delegation-tool.ts +128 -0
  124. package/src/tools/agent-device-tool.ts +240 -0
  125. package/src/tools/agent-documents-tool.ts +684 -0
  126. package/src/tools/agent-execution-tool.ts +230 -0
  127. package/src/tools/agent-harness-agent-orchestration.ts +703 -0
  128. package/src/tools/agent-harness-autonomy-intake.ts +785 -0
  129. package/src/tools/agent-harness-autonomy-live-records.ts +588 -0
  130. package/src/tools/agent-harness-autonomy-queue-types.ts +88 -0
  131. package/src/tools/agent-harness-autonomy-queue.ts +560 -0
  132. package/src/tools/agent-harness-background-processes-types.ts +35 -0
  133. package/src/tools/agent-harness-background-processes.ts +794 -0
  134. package/src/tools/agent-harness-browser-cockpit-route.ts +219 -0
  135. package/src/tools/agent-harness-browser-control.ts +338 -0
  136. package/src/tools/agent-harness-channel-metadata.ts +168 -10
  137. package/src/tools/agent-harness-cli-command-policy.ts +110 -0
  138. package/src/tools/agent-harness-command-catalog.ts +4 -2
  139. package/src/tools/agent-harness-command-runner.ts +42 -0
  140. package/src/tools/agent-harness-connected-host-status.ts +7 -4
  141. package/src/tools/agent-harness-delegation-posture.ts +234 -19
  142. package/src/tools/agent-harness-document-ops-reviewer-readiness.ts +234 -0
  143. package/src/tools/agent-harness-document-ops-types.ts +72 -0
  144. package/src/tools/agent-harness-document-ops.ts +671 -0
  145. package/src/tools/agent-harness-execution-history.ts +489 -0
  146. package/src/tools/agent-harness-execution-posture.ts +382 -0
  147. package/src/tools/agent-harness-file-recovery.ts +135 -0
  148. package/src/tools/agent-harness-keybinding-metadata.ts +16 -12
  149. package/src/tools/agent-harness-learning-curator-common.ts +102 -0
  150. package/src/tools/agent-harness-learning-curator-consolidation.ts +295 -0
  151. package/src/tools/agent-harness-learning-curator-proposals.ts +606 -0
  152. package/src/tools/agent-harness-learning-curator-types.ts +151 -0
  153. package/src/tools/agent-harness-learning-curator.ts +417 -0
  154. package/src/tools/agent-harness-local-model-benchmarks.ts +199 -0
  155. package/src/tools/agent-harness-local-model-cookbook.ts +238 -0
  156. package/src/tools/agent-harness-local-model-endpoints.ts +673 -0
  157. package/src/tools/agent-harness-media-posture.ts +208 -2
  158. package/src/tools/agent-harness-memory-posture.ts +556 -0
  159. package/src/tools/agent-harness-metadata.ts +100 -168
  160. package/src/tools/agent-harness-mode-catalog.ts +84 -33
  161. package/src/tools/agent-harness-model-catalog.ts +162 -0
  162. package/src/tools/agent-harness-model-provider-health.ts +186 -0
  163. package/src/tools/agent-harness-model-readiness.ts +406 -0
  164. package/src/tools/agent-harness-model-routing-types.ts +266 -0
  165. package/src/tools/agent-harness-model-routing-utils.ts +30 -0
  166. package/src/tools/agent-harness-model-routing.ts +137 -190
  167. package/src/tools/agent-harness-operator-methods.ts +115 -133
  168. package/src/tools/agent-harness-pairing-posture.ts +431 -18
  169. package/src/tools/agent-harness-personal-ops-discovery.ts +533 -0
  170. package/src/tools/agent-harness-personal-ops-intake.ts +385 -0
  171. package/src/tools/agent-harness-personal-ops-lanes.ts +204 -0
  172. package/src/tools/agent-harness-personal-ops-records.ts +732 -0
  173. package/src/tools/agent-harness-personal-ops-runner.ts +637 -0
  174. package/src/tools/agent-harness-personal-ops-types.ts +222 -0
  175. package/src/tools/agent-harness-personal-ops.ts +606 -0
  176. package/src/tools/agent-harness-project-context.ts +144 -0
  177. package/src/tools/agent-harness-prompt-context.ts +589 -0
  178. package/src/tools/agent-harness-provider-account-metadata.ts +2 -2
  179. package/src/tools/agent-harness-release-evidence.ts +9 -7
  180. package/src/tools/agent-harness-release-readiness.ts +9 -7
  181. package/src/tools/agent-harness-research-briefing.ts +427 -0
  182. package/src/tools/agent-harness-research-queue.ts +250 -0
  183. package/src/tools/agent-harness-research-runs.ts +295 -0
  184. package/src/tools/agent-harness-research-workflow.ts +322 -0
  185. package/src/tools/agent-harness-security-posture.ts +2 -2
  186. package/src/tools/agent-harness-service-posture.ts +9 -9
  187. package/src/tools/agent-harness-session-metadata.ts +3 -3
  188. package/src/tools/agent-harness-setup-connected-host.ts +501 -0
  189. package/src/tools/agent-harness-setup-describe.ts +557 -0
  190. package/src/tools/agent-harness-setup-handoffs.ts +502 -0
  191. package/src/tools/agent-harness-setup-model-helpers.ts +101 -0
  192. package/src/tools/agent-harness-setup-plan.ts +253 -0
  193. package/src/tools/agent-harness-setup-posture-types.ts +218 -0
  194. package/src/tools/agent-harness-setup-posture-utils.ts +173 -0
  195. package/src/tools/agent-harness-setup-posture.ts +449 -221
  196. package/src/tools/agent-harness-setup-smoke.ts +508 -0
  197. package/src/tools/agent-harness-sudo-posture.ts +114 -0
  198. package/src/tools/agent-harness-tool-schema.ts +120 -7
  199. package/src/tools/agent-harness-tool-types.ts +78 -0
  200. package/src/tools/agent-harness-tool-utils.ts +43 -0
  201. package/src/tools/agent-harness-tool.ts +311 -370
  202. package/src/tools/agent-harness-ui-surface-metadata.ts +76 -69
  203. package/src/tools/agent-harness-ui-surface-types.ts +46 -0
  204. package/src/tools/agent-harness-vibe-health.ts +105 -0
  205. package/src/tools/agent-harness-workspace-action-runner.ts +149 -0
  206. package/src/tools/agent-harness-workspace-actions.ts +114 -8
  207. package/src/tools/agent-harness-workspace-editor-execution.ts +214 -0
  208. package/src/tools/agent-harness-workspace-editor-runner.ts +755 -0
  209. package/src/tools/agent-host-tool.ts +159 -0
  210. package/src/tools/agent-knowledge-ingest-tool.ts +34 -1
  211. package/src/tools/agent-learning-consolidation-core.ts +327 -0
  212. package/src/tools/agent-learning-consolidation-tool.ts +758 -0
  213. package/src/tools/agent-memory-tool.ts +214 -0
  214. package/src/tools/agent-model-compare-export.ts +315 -0
  215. package/src/tools/agent-model-compare-handoff.ts +592 -0
  216. package/src/tools/agent-model-compare-judgment.ts +633 -0
  217. package/src/tools/agent-model-compare-run.ts +722 -0
  218. package/src/tools/agent-model-compare-tool.ts +698 -0
  219. package/src/tools/agent-model-compare-types.ts +191 -0
  220. package/src/tools/agent-model-compare-utils.ts +93 -0
  221. package/src/tools/agent-models-tool.ts +208 -0
  222. package/src/tools/agent-operator-action-tool.ts +1 -1
  223. package/src/tools/agent-operator-method-tool.ts +643 -0
  224. package/src/tools/agent-personal-ops-tool.ts +197 -0
  225. package/src/tools/agent-policy-explanation.ts +415 -0
  226. package/src/tools/agent-research-report-tool.ts +608 -0
  227. package/src/tools/agent-research-runs-tool.ts +434 -0
  228. package/src/tools/agent-research-sources-tool.ts +443 -0
  229. package/src/tools/agent-research-tool.ts +687 -0
  230. package/src/tools/agent-review-packet-presets-core.ts +757 -0
  231. package/src/tools/agent-review-packet-presets-tool.ts +466 -0
  232. package/src/tools/agent-review-packet-share-tool.ts +305 -0
  233. package/src/tools/agent-route-planner-candidates-setup.ts +411 -0
  234. package/src/tools/agent-route-planner-candidates-surfaces.ts +432 -0
  235. package/src/tools/agent-route-planner-candidates-work.ts +251 -0
  236. package/src/tools/agent-route-planner-helpers.ts +667 -0
  237. package/src/tools/agent-route-planner.ts +185 -0
  238. package/src/tools/agent-route-tool.ts +105 -0
  239. package/src/tools/agent-schedule-edit-tool.ts +210 -0
  240. package/src/tools/agent-schedule-tool.ts +282 -0
  241. package/src/tools/agent-security-tool.ts +145 -0
  242. package/src/tools/agent-sessions-tool.ts +122 -0
  243. package/src/tools/agent-settings-import-tool.ts +104 -0
  244. package/src/tools/agent-settings-tool.ts +176 -0
  245. package/src/tools/agent-setup-tool.ts +226 -0
  246. package/src/tools/agent-support-tool.ts +122 -0
  247. package/src/tools/agent-terminal-process-tools.ts +167 -0
  248. package/src/tools/agent-tool-policy-guard-types.ts +77 -0
  249. package/src/tools/agent-tool-policy-guard.ts +106 -85
  250. package/src/tools/agent-vibe-tool.ts +297 -0
  251. package/src/tools/agent-work-plan-tool.ts +265 -6
  252. package/src/tools/agent-workspace-tool.ts +305 -0
  253. package/src/tools/artifact-archive.ts +169 -0
  254. package/src/tools/tool-definition-compaction.ts +36 -0
  255. package/src/version.ts +1 -1
@@ -1,58 +1,17 @@
1
1
  import type { CommandContext } from '../input/command-registry.ts';
2
2
  import { openTtsProviderPicker, openTtsVoicePicker } from '../input/tts-settings-actions.ts';
3
+ import { openExternalUrl } from '@pellux/goodvibes-sdk/platform/utils';
4
+ import { connectedBrowserCockpitRoute } from './agent-harness-browser-cockpit-route.ts';
5
+ import type { AgentHarnessUiSurfaceArgs, UiSurfaceDefinition, UiSurfaceLookup, UiSurfaceResolution } from './agent-harness-ui-surface-types.ts';
6
+ export type { AgentHarnessUiSurfaceArgs } from './agent-harness-ui-surface-types.ts';
3
7
 
4
- type UiSurfaceKind = 'overlay' | 'modal' | 'workspace' | 'picker';
8
+ function agentHarnessModes(...modes: readonly string[]): string { return `agent_harness ${modes.map((mode) => `mode:"${mode}"`).join(', ')}`; }
5
9
 
6
- function agentHarnessModes(...modes: readonly string[]): string {
7
- return `agent_harness ${modes.map((mode) => `mode:"${mode}"`).join(', ')}`;
8
- }
10
+ function settingsActions(...actions: readonly string[]): string { return `settings ${actions.map((action) => `action:"${action}"`).join('|')}`; }
9
11
 
10
- export interface AgentHarnessUiSurfaceArgs {
11
- readonly query?: unknown;
12
- readonly surfaceId?: unknown;
13
- readonly categoryId?: unknown;
14
- readonly category?: unknown;
15
- readonly target?: unknown;
16
- readonly key?: unknown;
17
- readonly prefix?: unknown;
18
- readonly includeParameters?: unknown;
19
- readonly limit?: unknown;
20
- readonly pane?: unknown;
21
- }
12
+ function hostActions(...actions: readonly string[]): string { return `host ${actions.map((action) => `action:"${action}"`).join('|')}`; }
22
13
 
23
- interface UiSurfaceDefinition {
24
- readonly id: string;
25
- readonly label: string;
26
- readonly kind: UiSurfaceKind;
27
- readonly summary: string;
28
- readonly command: string;
29
- readonly preferredModelRoute: string;
30
- readonly parameters?: readonly string[];
31
- readonly available: (context: CommandContext) => boolean;
32
- readonly open: (context: CommandContext, args: AgentHarnessUiSurfaceArgs) => Record<string, unknown> | Promise<Record<string, unknown>>;
33
- }
34
-
35
- interface UiSurfaceLookup {
36
- readonly source: 'surfaceId' | 'target' | 'query';
37
- readonly input: string;
38
- readonly resolvedBy: 'id' | 'case-insensitive-id' | 'label' | 'case-insensitive-label' | 'search';
39
- }
40
-
41
- type UiSurfaceResolution =
42
- | {
43
- readonly status: 'found';
44
- readonly surface: UiSurfaceDefinition;
45
- readonly lookup: UiSurfaceLookup;
46
- }
47
- | {
48
- readonly status: 'ambiguous';
49
- readonly input: string;
50
- readonly candidates: readonly Record<string, unknown>[];
51
- };
52
-
53
- function readString(value: unknown): string {
54
- return typeof value === 'string' ? value.trim() : '';
55
- }
14
+ function readString(value: unknown): string { return typeof value === 'string' ? value.trim() : ''; }
56
15
 
57
16
  function readLimit(value: unknown, fallback: number): number {
58
17
  const parsed = typeof value === 'string' && value.trim() ? Number(value) : value;
@@ -181,6 +140,47 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
181
140
  return opened(surface, { categoryId: categoryId ?? 'default' });
182
141
  },
183
142
  },
143
+ {
144
+ id: 'connected-browser-cockpit',
145
+ label: 'Connected Browser Cockpit',
146
+ kind: 'workspace',
147
+ summary: 'Connected-host browser cockpit/PWA route.',
148
+ command: 'connected host web route',
149
+ preferredModelRoute: `Use ${hostActions('service', 'services', 'status')} or ${settingsActions('list', 'get')} to inspect or repair web readiness; use mode:"open_ui_surface" only to visibly open the configured cockpit URL.`,
150
+ available: (context) => {
151
+ try {
152
+ return context.platform?.configManager?.get?.('web.enabled') === true;
153
+ } catch {
154
+ return false;
155
+ }
156
+ },
157
+ open: async (context) => {
158
+ const surface = findSurfaceById('connected-browser-cockpit')!;
159
+ const route = connectedBrowserCockpitRoute(context);
160
+ if (route.enabled !== true) {
161
+ return {
162
+ status: 'setup_needed',
163
+ surface: surface.id,
164
+ kind: surface.kind,
165
+ route,
166
+ note: 'The connected-host web endpoint is disabled. Inspect service posture or web settings before opening a browser cockpit.',
167
+ };
168
+ }
169
+ const url = typeof route.url === 'string' ? route.url : '';
170
+ const browserOpened = url ? await openExternalUrl(url) : false;
171
+ return browserOpened
172
+ ? opened(surface, { url, route, browserOpened })
173
+ : {
174
+ status: 'open_failed',
175
+ surface: surface.id,
176
+ kind: surface.kind,
177
+ url,
178
+ route,
179
+ browserOpened,
180
+ note: 'The configured browser cockpit URL was resolved, but the external browser opener did not report success.',
181
+ };
182
+ },
183
+ },
184
184
  {
185
185
  id: 'panel-picker',
186
186
  label: 'Panel Picker',
@@ -258,7 +258,7 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
258
258
  kind: 'modal',
259
259
  summary: 'Fullscreen settings workspace for Agent config, secrets, MCP, and tools.',
260
260
  command: '/settings',
261
- preferredModelRoute: `Use ${agentHarnessModes('settings', 'get_setting', 'set_setting', 'reset_setting')} for model operation; use mode:"open_ui_surface" only to visibly navigate.`,
261
+ preferredModelRoute: `Use ${settingsActions('list', 'get', 'set', 'reset', 'import')} for model operation; use mode:"open_ui_surface" only to visibly navigate.`,
262
262
  parameters: ['target', 'key', 'prefix'],
263
263
  available: (context) => typeof context.openSettingsModal === 'function',
264
264
  open: (context, args) => {
@@ -275,7 +275,7 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
275
275
  kind: 'workspace',
276
276
  summary: 'MCP server setup, trust posture, and tool inventory workspace.',
277
277
  command: '/mcp',
278
- preferredModelRoute: `Use ${agentHarnessModes('workspace_actions', 'tools', 'settings')} for model operation.`,
278
+ preferredModelRoute: `Use ${agentHarnessModes('workspace_actions', 'tools')} or ${settingsActions('list', 'get', 'set')} for model operation.`,
279
279
  available: (context) => typeof context.openMcpWorkspace === 'function',
280
280
  open: (context) => openSimpleContextSurface(context, 'mcp-workspace', 'openMcpWorkspace'),
281
281
  },
@@ -285,7 +285,7 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
285
285
  kind: 'picker',
286
286
  summary: 'Interactive model picker for main, helper, tool, and TTS model routes.',
287
287
  command: '/model',
288
- preferredModelRoute: `Use ${agentHarnessModes('settings', 'get_setting', 'set_setting')} for direct provider.model changes, or mode:"run_command" with confirmation when a concrete model id is known.`,
288
+ preferredModelRoute: `Use ${settingsActions('get', 'set')} for direct provider.model changes, or mode:"run_command" with confirmation when a concrete model id is known.`,
289
289
  parameters: ['target'],
290
290
  available: (context) => typeof context.openModelPicker === 'function' || typeof context.openModelPickerWithTarget === 'function',
291
291
  open: (context, args) => {
@@ -306,7 +306,7 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
306
306
  kind: 'picker',
307
307
  summary: 'Interactive provider picker for model route setup.',
308
308
  command: '/provider',
309
- preferredModelRoute: `Use ${agentHarnessModes('settings', 'get_setting', 'set_setting')} for direct provider routing changes, or confirmed mode:"run_command" mirrors for concrete provider changes.`,
309
+ preferredModelRoute: `Use ${settingsActions('get', 'set')} for direct provider routing changes, or confirmed mode:"run_command" mirrors for concrete provider changes.`,
310
310
  parameters: ['target'],
311
311
  available: (context) => typeof context.openProviderPicker === 'function' || typeof context.openProviderModelPickerWithTarget === 'function',
312
312
  open: (context, args) => {
@@ -327,7 +327,7 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
327
327
  kind: 'picker',
328
328
  summary: 'Reasoning-effort selector for models that expose effort levels.',
329
329
  command: '/effort',
330
- preferredModelRoute: `Use ${agentHarnessModes('settings', 'get_setting', 'set_setting')} for provider.reasoningEffort when a concrete level is known, or mode:"run_workspace_action" setup-reasoning-effort with confirmation.`,
330
+ preferredModelRoute: `Use ${settingsActions('get', 'set')} for provider.reasoningEffort when a concrete level is known, or mode:"run_workspace_action" setup-reasoning-effort with confirmation.`,
331
331
  available: (context) => typeof context.openReasoningEffortPicker === 'function',
332
332
  open: (context) => {
333
333
  const surface = findSurfaceById('reasoning-effort-picker')!;
@@ -355,7 +355,7 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
355
355
  kind: 'picker',
356
356
  summary: 'Streaming TTS provider picker from Agent settings.',
357
357
  command: '/config tts.provider',
358
- preferredModelRoute: `Use ${agentHarnessModes('settings', 'get_setting', 'set_setting')} for tts.provider when a concrete provider id is known; use mode:"open_ui_surface" only to visibly navigate.`,
358
+ preferredModelRoute: `Use ${settingsActions('get', 'set')} for tts.provider when a concrete provider id is known; use mode:"open_ui_surface" only to visibly navigate.`,
359
359
  available: (context) => typeof context.openSelection === 'function' && Boolean(context.platform.voiceProviderRegistry),
360
360
  open: (context) => {
361
361
  const surface = findSurfaceById('tts-provider-picker')!;
@@ -370,7 +370,7 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
370
370
  kind: 'picker',
371
371
  summary: 'TTS voice picker for the selected or supplied provider.',
372
372
  command: '/config tts.voice',
373
- preferredModelRoute: `Use ${agentHarnessModes('settings', 'get_setting', 'set_setting', 'reset_setting')} for tts.voice when a concrete voice id is known; use mode:"open_ui_surface" only to visibly navigate.`,
373
+ preferredModelRoute: `Use ${settingsActions('get', 'set', 'reset')} for tts.voice when a concrete voice id is known; use mode:"open_ui_surface" only to visibly navigate.`,
374
374
  parameters: ['target'],
375
375
  available: (context) => typeof context.openSelection === 'function' && Boolean(context.platform.voiceService),
376
376
  open: async (context, args) => {
@@ -613,7 +613,7 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
613
613
  kind: 'workspace',
614
614
  summary: 'Agent workspace entry for first-run and setup review.',
615
615
  command: '/agent',
616
- preferredModelRoute: `Use ${agentHarnessModes('workspace', 'workspace_actions', 'settings')} for concrete setup operation.`,
616
+ preferredModelRoute: `Use ${agentHarnessModes('workspace', 'workspace_actions')} or ${settingsActions('list', 'get', 'set')} for concrete setup operation.`,
617
617
  available: (context) => typeof context.openAgentWorkspace === 'function',
618
618
  open: (context) => {
619
619
  const surface = findSurfaceById('onboarding')!;
@@ -630,7 +630,7 @@ function findSurfaceById(surfaceId: string): UiSurfaceDefinition | undefined {
630
630
 
631
631
  function surfaceMatches(surface: Record<string, unknown>, query: string): boolean {
632
632
  if (!query) return true;
633
- return [
633
+ const haystack = [
634
634
  surface.id,
635
635
  surface.label,
636
636
  surface.kind,
@@ -638,7 +638,11 @@ function surfaceMatches(surface: Record<string, unknown>, query: string): boolea
638
638
  surface.command,
639
639
  surface.modelRoute,
640
640
  surface.preferredModelRoute,
641
- ].map((value) => String(value ?? '')).join('\n').toLowerCase().includes(query.toLowerCase());
641
+ ].map((value) => String(value ?? '')).join('\n').toLowerCase();
642
+ const normalized = query.toLowerCase().trim();
643
+ if (haystack.includes(normalized)) return true;
644
+ const tokens = normalized.split(/[^a-z0-9]+/).filter((token) => token.length > 0);
645
+ return tokens.length > 0 && tokens.every((token) => haystack.includes(token));
642
646
  }
643
647
 
644
648
  function surfaceLookupFromArgs(args: AgentHarnessUiSurfaceArgs): { readonly source: UiSurfaceLookup['source']; readonly input: string } | null {
@@ -664,43 +668,45 @@ function surfaceCandidate(surface: UiSurfaceDefinition): Record<string, unknown>
664
668
 
665
669
  function uiSurfaceModelRoute(surface: UiSurfaceDefinition): string {
666
670
  switch (surface.id) {
671
+ case 'connected-browser-cockpit':
672
+ return 'computer action:"browser|open_browser" or workspace action:"open"';
667
673
  case 'agent-workspace':
668
674
  case 'panel-picker':
669
675
  case 'security-panel':
670
676
  case 'subscription-panel':
671
677
  case 'mcp-workspace':
672
678
  case 'onboarding':
673
- return 'agent_harness mode:"workspace_actions" or mode:"open_ui_surface"';
679
+ return 'workspace action:"actions|open"';
674
680
  case 'knowledge-panel':
675
- return 'agent_knowledge, agent_knowledge_ingest, or workspace_actions';
681
+ return 'agent_knowledge, agent_knowledge_ingest, or workspace action:"actions"';
676
682
  case 'settings':
677
683
  case 'tts-provider-picker':
678
684
  case 'tts-voice-picker':
679
685
  case 'reasoning-effort-picker':
680
- return 'agent_harness mode:"settings" or mode:"open_ui_surface"';
686
+ return 'settings action:"list|get|set" or workspace action:"open"';
681
687
  case 'model-picker':
682
688
  case 'provider-picker':
683
- return 'agent_harness mode:"settings" or mode:"run_command"';
689
+ return 'settings action:"get|set" or workspace action:"run_command"';
684
690
  case 'session-picker':
685
691
  case 'bookmark-modal':
686
692
  case 'context-inspector':
687
693
  case 'slash-command-mode':
688
694
  case 'command-browser':
689
695
  case 'block-actions':
690
- return 'agent_harness mode:"commands" or mode:"run_command"';
696
+ return 'workspace action:"commands|run_command"';
691
697
  case 'process-monitor':
692
698
  case 'live-tail':
693
699
  case 'file-picker':
694
- return 'first-class tools or agent_harness mode:"open_ui_surface"';
700
+ return 'first-class tools or workspace action:"open"';
695
701
  case 'conversation-search':
696
702
  case 'prompt-history-search':
697
- return 'agent_harness mode:"open_ui_surface"';
703
+ return 'workspace action:"open"';
698
704
  case 'help-overlay':
699
- return 'agent_harness mode:"commands" or mode:"shortcuts"';
705
+ return 'workspace action:"commands|shortcuts"';
700
706
  case 'shortcuts-overlay':
701
- return 'agent_harness mode:"shortcuts" or mode:"keybindings"';
707
+ return 'workspace action:"shortcuts|keybindings"';
702
708
  default:
703
- return 'agent_harness mode:"open_ui_surface"';
709
+ return 'workspace action:"open"';
704
710
  }
705
711
  }
706
712
 
@@ -738,6 +744,7 @@ function describeSurface(
738
744
  ...(options.lookup ? { lookup: options.lookup } : {}),
739
745
  modelRoute: uiSurfaceModelRoute(surface),
740
746
  available: surface.available(context),
747
+ ...(surface.id === 'connected-browser-cockpit' ? { cockpit: connectedBrowserCockpitRoute(context, { includeWorkspaceCoverage: options.includeParameters === true }) } : {}),
741
748
  ...(options.includeParameters ? {
742
749
  preferredModelRoute: surface.preferredModelRoute,
743
750
  parameters: surface.parameters ?? [],
@@ -0,0 +1,46 @@
1
+ import type { CommandContext } from '../input/command-registry.ts';
2
+
3
+ export type UiSurfaceKind = 'overlay' | 'modal' | 'workspace' | 'picker';
4
+
5
+ export interface AgentHarnessUiSurfaceArgs {
6
+ readonly query?: unknown;
7
+ readonly surfaceId?: unknown;
8
+ readonly categoryId?: unknown;
9
+ readonly category?: unknown;
10
+ readonly target?: unknown;
11
+ readonly key?: unknown;
12
+ readonly prefix?: unknown;
13
+ readonly includeParameters?: unknown;
14
+ readonly limit?: unknown;
15
+ readonly pane?: unknown;
16
+ }
17
+
18
+ export interface UiSurfaceDefinition {
19
+ readonly id: string;
20
+ readonly label: string;
21
+ readonly kind: UiSurfaceKind;
22
+ readonly summary: string;
23
+ readonly command: string;
24
+ readonly preferredModelRoute: string;
25
+ readonly parameters?: readonly string[];
26
+ readonly available: (context: CommandContext) => boolean;
27
+ readonly open: (context: CommandContext, args: AgentHarnessUiSurfaceArgs) => Record<string, unknown> | Promise<Record<string, unknown>>;
28
+ }
29
+
30
+ export interface UiSurfaceLookup {
31
+ readonly source: 'surfaceId' | 'target' | 'query';
32
+ readonly input: string;
33
+ readonly resolvedBy: 'id' | 'case-insensitive-id' | 'label' | 'case-insensitive-label' | 'search';
34
+ }
35
+
36
+ export type UiSurfaceResolution =
37
+ | {
38
+ readonly status: 'found';
39
+ readonly surface: UiSurfaceDefinition;
40
+ readonly lookup: UiSurfaceLookup;
41
+ }
42
+ | {
43
+ readonly status: 'ambiguous';
44
+ readonly input: string;
45
+ readonly candidates: readonly Record<string, unknown>[];
46
+ };
@@ -0,0 +1,105 @@
1
+ import type { CommandContext } from '../input/command-registry.ts';
2
+ import type { AgentVibeFile, BlockedAgentVibeFile } from '../agent/vibe-file.ts';
3
+ import { discoverVibeFiles } from '../agent/vibe-file.ts';
4
+ import { previewHarnessText } from './agent-harness-text.ts';
5
+
6
+ export interface AgentHarnessVibeHealthFile {
7
+ readonly path: string;
8
+ readonly scope: string;
9
+ readonly truncated?: boolean;
10
+ }
11
+
12
+ export interface AgentHarnessVibeHealthBlockedFile {
13
+ readonly path: string;
14
+ readonly scope: string;
15
+ readonly reason: string;
16
+ }
17
+
18
+ export interface AgentHarnessVibeHealth {
19
+ readonly status: 'ready' | 'check' | 'recommended';
20
+ readonly applied: number;
21
+ readonly blocked: number;
22
+ readonly truncated: number;
23
+ readonly files: readonly AgentHarnessVibeHealthFile[];
24
+ readonly blockedFiles: readonly AgentHarnessVibeHealthBlockedFile[];
25
+ readonly searchedPaths: readonly string[];
26
+ readonly projectInitPath: string;
27
+ readonly globalInitPath: string;
28
+ readonly nextAction: string;
29
+ readonly userRoute: string;
30
+ readonly modelRoute: string;
31
+ readonly signals: readonly string[];
32
+ }
33
+
34
+ function describeVibeFile(file: AgentVibeFile): AgentHarnessVibeHealthFile {
35
+ return {
36
+ path: file.path,
37
+ scope: file.scope,
38
+ ...(file.truncated ? { truncated: true } : {}),
39
+ };
40
+ }
41
+
42
+ function describeBlockedVibeFile(file: BlockedAgentVibeFile): AgentHarnessVibeHealthBlockedFile {
43
+ return {
44
+ path: file.path,
45
+ scope: file.scope,
46
+ reason: previewHarnessText(file.reason, 180),
47
+ };
48
+ }
49
+
50
+ export function agentHarnessVibeHealth(context: CommandContext): AgentHarnessVibeHealth {
51
+ const shellPaths = context.workspace.shellPaths;
52
+ if (!shellPaths) {
53
+ return {
54
+ status: 'recommended',
55
+ applied: 0,
56
+ blocked: 0,
57
+ truncated: 0,
58
+ files: [],
59
+ blockedFiles: [],
60
+ searchedPaths: [],
61
+ projectInitPath: '',
62
+ globalInitPath: '',
63
+ nextAction: 'VIBE.md discovery is unavailable because shell paths are not wired into this runtime.',
64
+ userRoute: 'Agent Workspace -> Local Context -> Personas -> VIBE.md; /vibe status',
65
+ modelRoute: 'vibe action:"status"',
66
+ signals: ['VIBE.md discovery unavailable: shell paths are not wired.'],
67
+ };
68
+ }
69
+ const snapshot = discoverVibeFiles(shellPaths);
70
+ const truncated = snapshot.files.filter((file) => file.truncated);
71
+ const status = snapshot.blocked.length > 0 || truncated.length > 0
72
+ ? 'check'
73
+ : snapshot.files.length > 0
74
+ ? 'ready'
75
+ : 'recommended';
76
+ const nextAction = snapshot.blocked.length > 0
77
+ ? 'Run /vibe status, inspect blocked files, and edit or remove secret-looking content before relying on personality instructions.'
78
+ : truncated.length > 0
79
+ ? 'Run /vibe status and shorten the truncated VIBE.md file if the omitted content matters.'
80
+ : snapshot.files.length > 0
81
+ ? 'Review /vibe status when changing project or global personality instructions.'
82
+ : 'Create a project VIBE.md or import a reviewed persona when the user wants a custom assistant feel.';
83
+ const signals = [
84
+ `applied VIBE.md files: ${snapshot.files.length}`,
85
+ `blocked VIBE.md files: ${snapshot.blocked.length}`,
86
+ `truncated VIBE.md files: ${truncated.length}`,
87
+ ...(snapshot.files.slice(0, 3).map((file) => `${file.scope}: ${file.path}${file.truncated ? ' (truncated)' : ''}`)),
88
+ ...(snapshot.blocked.slice(0, 3).map((file) => `blocked ${file.scope}: ${file.path} - ${previewHarnessText(file.reason, 96)}`)),
89
+ ];
90
+ return {
91
+ status,
92
+ applied: snapshot.files.length,
93
+ blocked: snapshot.blocked.length,
94
+ truncated: truncated.length,
95
+ files: snapshot.files.map(describeVibeFile),
96
+ blockedFiles: snapshot.blocked.map(describeBlockedVibeFile),
97
+ searchedPaths: snapshot.searchedPaths,
98
+ projectInitPath: snapshot.projectInitPath,
99
+ globalInitPath: snapshot.globalInitPath,
100
+ nextAction,
101
+ userRoute: 'Agent Workspace -> Local Context -> Personas -> VIBE.md; /vibe status',
102
+ modelRoute: 'vibe action:"status"',
103
+ signals,
104
+ };
105
+ }
@@ -0,0 +1,149 @@
1
+ import type { AgentHarnessToolArgs, AgentHarnessToolDeps } from './agent-harness-tool-types.ts';
2
+ import { clearSetupCheckpoint, markSetupCheckpoint, setupCheckpointSummary } from './agent-harness-setup-posture.ts';
3
+ import { runLocalWorkspaceAction } from './agent-harness-local-operations.ts';
4
+ import { AGENT_WORKSPACE_CATEGORIES, buildWorkspaceEditorContext, createWorkspaceEditor, describeWorkspaceAction, describeWorkspaceCategory, listWorkspaceActions, resolveWorkspaceActionDetail } from './agent-harness-workspace-actions.ts';
5
+ import { runCommand } from './agent-harness-command-runner.ts';
6
+ import { runWorkspaceEditorAction } from './agent-harness-workspace-editor-runner.ts';
7
+ import { error, output, readString, requireConfirmedAction } from './agent-harness-tool-utils.ts';
8
+ import { importAgentWorkspaceTuiSettings, previewAgentWorkspaceTuiSettingsImport } from '../input/agent-workspace-settings.ts';
9
+ import { writeOnboardingCheckMarker, writeOnboardingCompletionMarker } from '../runtime/onboarding/index.ts';
10
+
11
+ export async function runWorkspaceAction(
12
+ deps: AgentHarnessToolDeps,
13
+ args: AgentHarnessToolArgs,
14
+ ): Promise<{ readonly success: boolean; readonly output?: string; readonly error?: string }> {
15
+ const resolved = resolveWorkspaceActionDetail(args);
16
+ if (resolved?.status === 'ambiguous') return error(`Ambiguous Agent workspace action ${resolved.input}. Candidates: ${JSON.stringify(resolved.candidates)}`);
17
+ if (!resolved) return error('run_workspace_action requires a valid actionId, command, target, or query. Use mode:"workspace_actions" to inspect available actions.');
18
+ const { category, action, lookup } = resolved;
19
+
20
+ if (action.safety === 'blocked') {
21
+ return error(`Workspace action ${action.id} is blocked in Agent: ${action.detail}`);
22
+ }
23
+ if (action.kind === 'guidance') {
24
+ const editorContext = buildWorkspaceEditorContext(deps.commandContext, args);
25
+ return output({
26
+ status: 'guidance',
27
+ action: describeWorkspaceAction(category, action, { includeEditor: true, editorContext, lookup }),
28
+ });
29
+ }
30
+ if (action.kind === 'workspace' && action.targetCategoryId) {
31
+ const target = AGENT_WORKSPACE_CATEGORIES.find((entry) => entry.id === action.targetCategoryId);
32
+ return output({
33
+ status: 'workspace_target',
34
+ action: describeWorkspaceAction(category, action, { lookup }),
35
+ targetCategory: target ? describeWorkspaceCategory(target) : action.targetCategoryId,
36
+ targetActions: target ? target.actions.map((entry) => describeWorkspaceAction(target, entry)).slice(0, 40) : [],
37
+ });
38
+ }
39
+ if (action.kind === 'command' && action.command) {
40
+ if (/<[^>\s]+(?:\s+[^>]*)?>/.test(action.command)) {
41
+ return output({
42
+ status: 'needs_concrete_command',
43
+ action: describeWorkspaceAction(category, action, { lookup }),
44
+ note: 'This workspace action is a command template. Provide concrete values with mode:"run_command" once the exact command is known.',
45
+ });
46
+ }
47
+ return runCommand(deps, { ...args, command: action.command });
48
+ }
49
+ if (action.kind === 'settings-import') {
50
+ const preview = previewAgentWorkspaceTuiSettingsImport(deps.commandContext);
51
+ if (!preview) return error('GoodVibes settings import is unavailable in this runtime.');
52
+ if (args.confirm !== true) {
53
+ return output({
54
+ status: 'confirmation_required',
55
+ action: describeWorkspaceAction(category, action, { lookup }),
56
+ preview,
57
+ next: 'Run with confirm:true and explicitUserRequest after the user asks to import these settings.',
58
+ });
59
+ }
60
+ const explicitUserRequest = readString(args.explicitUserRequest);
61
+ if (!explicitUserRequest) {
62
+ return error('GoodVibes settings import requires explicitUserRequest when confirm is true.');
63
+ }
64
+ const outcome = await importAgentWorkspaceTuiSettings(deps.commandContext);
65
+ return output({
66
+ status: outcome.status,
67
+ action: describeWorkspaceAction(category, action, { lookup }),
68
+ preview,
69
+ actionResult: outcome.result,
70
+ runtimeSnapshot: outcome.runtimeSnapshot,
71
+ policy: {
72
+ effect: 'state',
73
+ confirmation: 'confirmed',
74
+ explicitUserRequest,
75
+ boundary: 'Applied only Agent-owned settings and subscription state from published GoodVibes platform sources; source package stores were not mutated.',
76
+ },
77
+ });
78
+ }
79
+ if (action.kind === 'setup-checkpoint') {
80
+ const operation = action.setupCheckpointOperation ?? 'show';
81
+ if (operation === 'show') {
82
+ return output({
83
+ status: 'checkpoint_inspected',
84
+ action: describeWorkspaceAction(category, action, { lookup }),
85
+ checkpoint: await setupCheckpointSummary(deps.commandContext),
86
+ });
87
+ }
88
+ const confirmationError = requireConfirmedAction(args, operation === 'clear' ? 'Setup wizard checkpoint clear' : 'Setup wizard checkpoint save');
89
+ if (confirmationError) return error(confirmationError);
90
+ const result = operation === 'clear'
91
+ ? clearSetupCheckpoint(deps.commandContext, args)
92
+ : await markSetupCheckpoint(deps.commandContext, args);
93
+ return output({
94
+ status: 'checkpoint_action_completed',
95
+ action: describeWorkspaceAction(category, action, { lookup }),
96
+ result,
97
+ });
98
+ }
99
+ if (action.kind === 'editor' && action.editorKind) {
100
+ const editor = createWorkspaceEditor(action.editorKind, buildWorkspaceEditorContext(deps.commandContext, args));
101
+ if (!editor) return error(`No workspace editor route exists for ${action.editorKind}.`);
102
+ return runWorkspaceEditorAction(deps, action, editor, args);
103
+ }
104
+ if (action.kind === 'local-selection' || action.kind === 'local-operation') {
105
+ return runLocalWorkspaceAction(deps, action, args);
106
+ }
107
+ if (action.kind === 'onboarding-complete') {
108
+ const confirmationError = requireConfirmedAction(args, 'Onboarding completion');
109
+ if (confirmationError) return error(confirmationError);
110
+ const explicitUserRequest = readString(args.explicitUserRequest);
111
+ if (!explicitUserRequest) return error('Onboarding completion requires explicitUserRequest when confirm is true.');
112
+ const shellPaths = deps.commandContext.workspace?.shellPaths;
113
+ if (!shellPaths) return error('Onboarding completion requires Agent shell paths.');
114
+ const marker = { scope: 'user', source: 'wizard', mode: 'new', workspaceRoot: shellPaths.workingDirectory } as const;
115
+ const checkMarker = writeOnboardingCheckMarker(shellPaths, marker);
116
+ const completionMarker = writeOnboardingCompletionMarker(shellPaths, marker);
117
+ return output({
118
+ status: 'onboarding_completed',
119
+ action: describeWorkspaceAction(category, action, { lookup }),
120
+ explicitUserRequest,
121
+ checkMarker: {
122
+ exists: checkMarker.exists,
123
+ path: checkMarker.path,
124
+ updatedAt: checkMarker.payload?.updatedAt ?? null,
125
+ source: checkMarker.payload?.source ?? null,
126
+ mode: checkMarker.payload?.mode ?? null,
127
+ },
128
+ completionMarker: {
129
+ exists: completionMarker.exists,
130
+ path: completionMarker.path,
131
+ updatedAt: completionMarker.payload?.updatedAt ?? null,
132
+ source: completionMarker.payload?.source ?? null,
133
+ mode: completionMarker.payload?.mode ?? null,
134
+ },
135
+ routes: {
136
+ inspectSetup: 'setup action:"status" includeParameters:true',
137
+ },
138
+ policy: {
139
+ effect: 'confirmed-onboarding-marker-write',
140
+ boundary: 'Writes only the user onboarding check and completion markers. It does not mutate provider credentials, connected-host state, channels, schedules, or local behavior.',
141
+ },
142
+ });
143
+ }
144
+ const editorContext = buildWorkspaceEditorContext(deps.commandContext, args);
145
+ return output({
146
+ status: 'no_direct_effect',
147
+ action: describeWorkspaceAction(category, action, { includeEditor: true, editorContext, lookup }),
148
+ });
149
+ }