@pellux/goodvibes-agent 1.1.6 → 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 (256) hide show
  1. package/CHANGELOG.md +176 -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 +132662 -91399
  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 +43 -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 +287 -0
  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 +267 -10
  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 +110 -89
  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/tools/tool-execution-safety.ts +41 -0
  256. package/src/version.ts +1 -1
@@ -0,0 +1,382 @@
1
+ import type { ToolRegistry } from '@pellux/goodvibes-sdk/platform/tools';
2
+ import type { CommandContext } from '../input/command-registry.ts';
3
+ import { browserControlPosture } from './agent-harness-browser-control.ts';
4
+ import { delegationDecisionCards } from './agent-harness-delegation-posture.ts';
5
+ import { fileRecoveryCatalogStatus } from './agent-harness-file-recovery.ts';
6
+ import { sudoExecutionPosture } from './agent-harness-sudo-posture.ts';
7
+ import { previewHarnessText } from './agent-harness-text.ts';
8
+
9
+ export interface AgentHarnessExecutionArgs {
10
+ readonly executionRouteId?: unknown;
11
+ readonly target?: unknown;
12
+ readonly query?: unknown;
13
+ readonly includeParameters?: unknown;
14
+ readonly limit?: unknown;
15
+ }
16
+
17
+ type ExecutionResolution =
18
+ | { readonly status: 'found'; readonly route: Record<string, unknown> }
19
+ | { readonly status: 'ambiguous'; readonly input: string; readonly candidates: readonly Record<string, unknown>[] }
20
+ | { readonly status: 'missing_lookup'; readonly usage: string };
21
+
22
+ type ExecutionLookupSource = 'executionRouteId' | 'target' | 'query';
23
+ type ExecutionEffect = 'read-only' | 'local-effect' | 'external-read' | 'delegated-work' | 'setup-gap';
24
+ type ExecutionAvailability = 'ready' | 'setup-needed' | 'fallback-only';
25
+
26
+ interface ExecutionSupervisionRoute {
27
+ readonly id: string;
28
+ readonly label: string;
29
+ readonly available: boolean;
30
+ readonly modelRoute: string;
31
+ readonly requiresConfirmation?: boolean;
32
+ }
33
+
34
+ interface ExecutionRoute {
35
+ readonly id: string;
36
+ readonly label: string;
37
+ readonly detail: string;
38
+ readonly userOutcome: string;
39
+ readonly effect: ExecutionEffect;
40
+ readonly preferredWhen: string;
41
+ readonly useInsteadWhen?: string;
42
+ readonly toolNames?: readonly string[];
43
+ readonly anyToolNames?: readonly string[];
44
+ readonly browserMcp?: boolean;
45
+ readonly modelRoute: string;
46
+ readonly recoveryRoute?: string;
47
+ readonly safety: string;
48
+ readonly nextStep: string;
49
+ }
50
+
51
+ function readString(value: unknown): string {
52
+ return typeof value === 'string' ? value.trim() : '';
53
+ }
54
+
55
+ function readLimit(value: unknown, fallback: number): number {
56
+ const parsed = typeof value === 'string' && value.trim() ? Number(value) : value;
57
+ if (typeof parsed !== 'number' || !Number.isFinite(parsed)) return fallback;
58
+ return Math.max(1, Math.min(500, Math.trunc(parsed)));
59
+ }
60
+
61
+ function lookupFromArgs(args: AgentHarnessExecutionArgs): { readonly source: ExecutionLookupSource; readonly input: string } | null {
62
+ const executionRouteId = readString(args.executionRouteId);
63
+ if (executionRouteId) return { source: 'executionRouteId', input: executionRouteId };
64
+ const target = readString(args.target);
65
+ if (target) return { source: 'target', input: target };
66
+ const query = readString(args.query);
67
+ return query ? { source: 'query', input: query } : null;
68
+ }
69
+
70
+ function routeDefinitions(): readonly ExecutionRoute[] {
71
+ return [
72
+ {
73
+ id: 'local-read-search-analyze',
74
+ label: 'Local read, search, and analysis',
75
+ detail: 'Use workspace read/search/inspect/analyze tools to understand files, diffs, logs, and project structure before taking action.',
76
+ userOutcome: 'The user gets direct answers from the current workspace without delegation ceremony.',
77
+ effect: 'read-only',
78
+ preferredWhen: 'The task needs project context, code review, log triage, or file inspection and the current workspace is the target.',
79
+ useInsteadWhen: 'Use delegation only when the user needs a remote workspace, parallel review, or isolated runner.',
80
+ anyToolNames: ['read', 'find', 'inspect', 'analyze'],
81
+ modelRoute: 'read/find/inspect/analyze',
82
+ safety: 'Read-only tools must stay bounded to the current permitted workspace and avoid raw secret disclosure.',
83
+ nextStep: 'Call the narrowest read/search/analyze tool that answers the user request.',
84
+ },
85
+ {
86
+ id: 'local-edit-write',
87
+ label: 'Local file edit and write',
88
+ detail: 'Use local edit/write tools for explicit implementation, fix, patch, or document changes when this Agent workspace is the intended target.',
89
+ userOutcome: 'The user gets the requested change in place without a handoff when local permissions are already sufficient.',
90
+ effect: 'local-effect',
91
+ preferredWhen: 'The user asks to implement, fix, patch, refactor, update docs, or edit files in the current workspace.',
92
+ useInsteadWhen: 'Use delegation for isolated worktrees, remote machines, parallel workers, or work that needs a separate coding UI.',
93
+ anyToolNames: ['edit', 'write'],
94
+ modelRoute: 'edit/write',
95
+ recoveryRoute: 'execution action:"recovery"',
96
+ safety: 'Respect user-owned dirty worktree changes, keep edits scoped, and verify with tests or static checks when feasible.',
97
+ nextStep: 'Use local edit/write tooling, then run targeted verification through the local shell route when appropriate.',
98
+ },
99
+ {
100
+ id: 'local-shell-command',
101
+ label: 'Local shell command',
102
+ detail: 'Run bounded foreground shell commands for discovery, builds, tests, formatting, verification, and explicit user-supervised sudo when the user request and workspace allow it.',
103
+ userOutcome: 'The user sees progress and results from the actual environment without extra routing decisions.',
104
+ effect: 'local-effect',
105
+ preferredWhen: 'The task needs command output, project tests, build checks, package inspection, safe one-off automation, or visible privilege escalation in the current workspace.',
106
+ useInsteadWhen: 'Use execution action:"processes" plus terminal/process for user-approved long-running local commands; use delegation or connected-host tasks for isolation, remote execution, or parallelism.',
107
+ toolNames: ['exec'],
108
+ modelRoute: 'exec',
109
+ safety: 'Use foreground serial commands, avoid destructive operations unless explicitly requested, keep sudo visible and user-supervised, block hidden background sudo prompts, and report verification results clearly.',
110
+ nextStep: 'Call exec for bounded foreground commands, inspect setup_item sudo-execution-posture before escalation, or inspect execution action:"processes" before starting tracked long-running local work.',
111
+ },
112
+ {
113
+ id: 'web-fetch-research',
114
+ label: 'Web and URL evidence',
115
+ detail: 'Use registered web_search or fetch tools for current public information, source inspection, and evidence gathering.',
116
+ userOutcome: 'The user gets sourced current information without pretending local knowledge is fresh.',
117
+ effect: 'external-read',
118
+ preferredWhen: 'The request depends on current, public, or third-party information.',
119
+ useInsteadWhen: 'Use research run/source/report tools when the answer needs a durable research ledger or citation repair.',
120
+ anyToolNames: ['web_search', 'fetch'],
121
+ modelRoute: 'web_search/fetch',
122
+ safety: 'Read-only browsing must use relevant sources, attribution, and source limits; authenticated or mutating web actions need explicit tools.',
123
+ nextStep: 'Call web_search or fetch, then capture durable sources when a longer research workflow is useful.',
124
+ },
125
+ {
126
+ id: 'browser-or-desktop-control',
127
+ label: 'Browser or desktop control',
128
+ detail: 'Use browser, desktop, or computer-control MCP/tooling only when a trusted server or first-class tool is configured.',
129
+ userOutcome: 'The user can automate real UI flows when setup is present, and gets a clear setup gap when it is not.',
130
+ effect: 'setup-gap',
131
+ preferredWhen: 'The user asks for browser navigation, UI testing, screenshots, screen recording, or device/desktop actions.',
132
+ useInsteadWhen: 'Use read-only web tools for research that does not require controlling a live browser or desktop.',
133
+ browserMcp: true,
134
+ modelRoute: 'mcp/browser tools',
135
+ safety: 'Browser and desktop control must use trusted servers, constrained paths/hosts, and visible confirmation for external effects.',
136
+ nextStep: 'Inspect MCP/browser setup, then use the configured browser tool or report the setup blocker.',
137
+ },
138
+ {
139
+ id: 'delegation-isolation-parallel-remote',
140
+ label: 'Delegation, isolation, parallelism, or remote work',
141
+ detail: 'Use GoodVibes TUI/shared-session delegation when the user benefits from isolation, remote execution, separate worktrees, parallel workers, or delegated review.',
142
+ userOutcome: 'The user gets heavier execution routed to the right supervised environment without blocking ordinary local work.',
143
+ effect: 'delegated-work',
144
+ preferredWhen: 'The task needs a remote host, isolated worktree, parallel agent, separate coding UI, or user-requested delegated review.',
145
+ useInsteadWhen: 'Use local read/edit/exec when the current workspace and permissions are sufficient for a normal implementation or verification task.',
146
+ modelRoute: 'delegation action:"status"',
147
+ safety: 'Delegated work submission must preserve the full original ask and remain visible and confirmation-gated.',
148
+ nextStep: 'Inspect delegation action:"status" or action:"route" before submitting a confirmed handoff.',
149
+ },
150
+ ];
151
+ }
152
+
153
+ function safeToolDefinitions(toolRegistry: ToolRegistry): readonly ReturnType<ToolRegistry['getToolDefinitions']>[number][] {
154
+ try {
155
+ return toolRegistry.getToolDefinitions();
156
+ } catch {
157
+ return [];
158
+ }
159
+ }
160
+
161
+ function registeredToolNames(toolRegistry: ToolRegistry): ReadonlySet<string> {
162
+ return new Set(safeToolDefinitions(toolRegistry).map((tool) => tool.name));
163
+ }
164
+
165
+ function routeAvailability(route: ExecutionRoute, context: CommandContext, toolRegistry: ToolRegistry): ExecutionAvailability {
166
+ if (route.id === 'delegation-isolation-parallel-remote') return 'ready';
167
+ if (route.browserMcp) return browserControlPosture(context, toolRegistry).configured ? 'ready' : 'setup-needed';
168
+ const names = registeredToolNames(toolRegistry);
169
+ if (route.toolNames?.every((name) => names.has(name))) return 'ready';
170
+ if (route.anyToolNames?.some((name) => names.has(name))) return 'ready';
171
+ return route.effect === 'read-only' ? 'fallback-only' : 'setup-needed';
172
+ }
173
+
174
+ function availableTools(route: ExecutionRoute, toolRegistry: ToolRegistry): readonly string[] {
175
+ const names = registeredToolNames(toolRegistry);
176
+ return [...(route.toolNames ?? []), ...(route.anyToolNames ?? [])].filter((name) => names.has(name));
177
+ }
178
+
179
+ function routeSearchText(route: ExecutionRoute): string {
180
+ return [
181
+ route.id,
182
+ route.label,
183
+ route.detail,
184
+ route.userOutcome,
185
+ route.effect,
186
+ route.preferredWhen,
187
+ route.useInsteadWhen ?? '',
188
+ route.modelRoute,
189
+ route.recoveryRoute ?? '',
190
+ route.nextStep,
191
+ ...(route.toolNames ?? []),
192
+ ...(route.anyToolNames ?? []),
193
+ ].join('\n').toLowerCase();
194
+ }
195
+
196
+ function describeCandidate(route: ExecutionRoute, context: CommandContext, toolRegistry: ToolRegistry): Record<string, unknown> {
197
+ return {
198
+ executionRouteId: route.id,
199
+ label: route.label,
200
+ effect: route.effect,
201
+ availability: routeAvailability(route, context, toolRegistry),
202
+ modelRoute: route.modelRoute,
203
+ };
204
+ }
205
+
206
+ function toolInspectorAvailable(context: CommandContext): boolean {
207
+ return Boolean(context.workspace.panelManager?.getRegisteredTypes().some((panel) => panel.id === 'tools'));
208
+ }
209
+
210
+ function executionSupervisionRoutes(context: CommandContext, route: ExecutionRoute): readonly ExecutionSupervisionRoute[] {
211
+ const routes: ExecutionSupervisionRoute[] = [];
212
+ if (route.id === 'local-shell-command') {
213
+ routes.push(
214
+ {
215
+ id: 'process-monitor',
216
+ label: 'Runtime Activity Monitor',
217
+ available: typeof context.openProcessModal === 'function',
218
+ modelRoute: 'workspace action:"open" surfaceId:"process-monitor"',
219
+ requiresConfirmation: true,
220
+ },
221
+ {
222
+ id: 'live-tail',
223
+ label: 'Live Process Output',
224
+ available: typeof context.openLiveTail === 'function',
225
+ modelRoute: 'workspace action:"open" surfaceId:"live-tail"',
226
+ requiresConfirmation: true,
227
+ },
228
+ );
229
+ }
230
+ if (route.id === 'local-shell-command' || route.id === 'local-edit-write') {
231
+ routes.push({
232
+ id: 'tool-inspector',
233
+ label: 'Tool Call Inspector',
234
+ available: toolInspectorAvailable(context),
235
+ modelRoute: 'workspace action:"open_panel" panelId:"tools"',
236
+ requiresConfirmation: true,
237
+ });
238
+ }
239
+ return routes;
240
+ }
241
+
242
+ function executionSupervisionSummary(context: CommandContext): Record<string, unknown> {
243
+ return {
244
+ processMonitorAvailable: typeof context.openProcessModal === 'function',
245
+ liveTailAvailable: typeof context.openLiveTail === 'function',
246
+ toolInspectorAvailable: toolInspectorAvailable(context),
247
+ routes: [
248
+ 'workspace action:"open" surfaceId:"process-monitor"',
249
+ 'workspace action:"open" surfaceId:"live-tail"',
250
+ 'workspace action:"open_panel" panelId:"tools"',
251
+ ],
252
+ };
253
+ }
254
+
255
+ function describeRoute(
256
+ route: ExecutionRoute,
257
+ context: CommandContext,
258
+ toolRegistry: ToolRegistry,
259
+ options: { readonly includeParameters?: boolean; readonly lookup?: Record<string, unknown> } = {},
260
+ ): Record<string, unknown> {
261
+ const availability = routeAvailability(route, context, toolRegistry);
262
+ const tools = availableTools(route, toolRegistry);
263
+ const supervisionRoutes = executionSupervisionRoutes(context, route);
264
+ const browserControl = route.browserMcp ? browserControlPosture(context, toolRegistry) : null;
265
+ const delegationCards = route.id === 'delegation-isolation-parallel-remote' ? delegationDecisionCards(context) : null;
266
+ return {
267
+ executionRouteId: route.id,
268
+ label: route.label,
269
+ effect: route.effect,
270
+ availability,
271
+ ...(tools.length > 0 ? { availableTools: tools } : {}),
272
+ ...(supervisionRoutes.length > 0 ? { supervisionRoutes } : {}),
273
+ modelRoute: route.modelRoute,
274
+ ...(route.recoveryRoute ? { recoveryRoute: route.recoveryRoute } : {}),
275
+ preferredWhen: options.includeParameters ? route.preferredWhen : previewHarnessText(route.preferredWhen),
276
+ nextStep: options.includeParameters ? route.nextStep : previewHarnessText(route.nextStep),
277
+ ...(options.includeParameters
278
+ ? {
279
+ detail: route.detail,
280
+ userOutcome: route.userOutcome,
281
+ useInsteadWhen: route.useInsteadWhen ?? null,
282
+ safety: route.safety,
283
+ toolNames: route.toolNames ?? [],
284
+ anyToolNames: route.anyToolNames ?? [],
285
+ browserMcp: route.browserMcp === true,
286
+ ...(browserControl ? { browserControl } : {}),
287
+ ...(delegationCards ? { delegationDecisionCards: delegationCards } : {}),
288
+ modelAccess: {
289
+ inspectPosture: 'execution action:"status"',
290
+ inspectRoute: `execution action:"route" id:"${route.id}"`,
291
+ inspectTools: 'agent_harness mode:"tools"',
292
+ inspectDelegation: 'delegation action:"status"',
293
+ inspectFileRecovery: route.recoveryRoute ?? 'execution action:"recovery"',
294
+ },
295
+ }
296
+ : {}),
297
+ ...(options.lookup ? { lookup: options.lookup } : {}),
298
+ };
299
+ }
300
+
301
+ function matchingRoutes(input: string): readonly ExecutionRoute[] {
302
+ const normalized = input.toLowerCase().trim();
303
+ const all = routeDefinitions();
304
+ if (!normalized) return all;
305
+ return all.filter((route) => routeSearchText(route).includes(normalized));
306
+ }
307
+
308
+ export function executionPostureCatalogStatus(context: CommandContext, toolRegistry: ToolRegistry): Record<string, unknown> {
309
+ const routes = routeDefinitions();
310
+ const statuses = routes.map((route) => routeAvailability(route, context, toolRegistry));
311
+ return {
312
+ modes: ['execution_posture', 'execution_route', 'browser_control_route'],
313
+ routes: routes.length,
314
+ readyRoutes: statuses.filter((status) => status === 'ready').length,
315
+ setupNeededRoutes: statuses.filter((status) => status === 'setup-needed').length,
316
+ readOnly: true,
317
+ };
318
+ }
319
+
320
+ export function executionPostureSummary(context: CommandContext, toolRegistry: ToolRegistry, args: AgentHarnessExecutionArgs): Record<string, unknown> {
321
+ const query = readString(args.query).toLowerCase();
322
+ const includeParameters = args.includeParameters === true;
323
+ const routes = matchingRoutes(query).slice(0, readLimit(args.limit, 100));
324
+ const all = routeDefinitions();
325
+ const browserControl = browserControlPosture(context, toolRegistry);
326
+ const delegationCards = delegationDecisionCards(context);
327
+ return {
328
+ status: 'available',
329
+ summary: {
330
+ localFirstPolicy: 'Use local read/edit/exec when the current workspace and permissions are sufficient.',
331
+ delegationPolicy: 'Use delegation for isolation, parallelism, remote execution, separate worktrees, or user-requested delegated review.',
332
+ browserControl: browserControl.status,
333
+ browserControlSetup: browserControl,
334
+ delegationDecisionCards: delegationCards,
335
+ sudoPosture: sudoExecutionPosture(context),
336
+ executionHistory: 'execution action:"history"',
337
+ backgroundProcesses: 'execution action:"processes"',
338
+ fileRecovery: fileRecoveryCatalogStatus(context),
339
+ supervision: executionSupervisionSummary(context),
340
+ registeredExecutionTools: [...registeredToolNames(toolRegistry)].filter((name) => ['read', 'find', 'inspect', 'analyze', 'edit', 'write', 'exec', 'fetch', 'web_search'].includes(name)).sort(),
341
+ },
342
+ decisionRules: [
343
+ 'Do not delegate ordinary local implementation, fix, review, or verification work when local tools and permissions are sufficient.',
344
+ 'Do delegate when isolation, parallelism, remote execution, a separate worktree, or a requested delegated review improves the user outcome.',
345
+ 'Report setup gaps directly for browser/desktop control instead of pretending browser automation exists.',
346
+ 'Use tracked background processes for approved long-running local commands instead of hidden exec background mode.',
347
+ ],
348
+ routes: routes.map((route) => describeRoute(route, context, toolRegistry, { includeParameters })),
349
+ returned: routes.length,
350
+ total: all.length,
351
+ policy: 'Read-only execution posture. It selects routes and safety boundaries; actual tool calls remain governed by each first-class tool policy.',
352
+ };
353
+ }
354
+
355
+ export function describeHarnessExecutionRoute(context: CommandContext, toolRegistry: ToolRegistry, args: AgentHarnessExecutionArgs): ExecutionResolution {
356
+ const lookup = lookupFromArgs(args);
357
+ if (!lookup) {
358
+ return {
359
+ status: 'missing_lookup',
360
+ usage: 'execution action:"route" requires executionRouteId, target, or query. Use execution action:"status" to inspect execution route ids.',
361
+ };
362
+ }
363
+ const all = routeDefinitions();
364
+ const normalized = lookup.input.toLowerCase();
365
+ const exact = all.find((route) => route.id === lookup.input);
366
+ if (exact) return { status: 'found', route: describeRoute(exact, context, toolRegistry, { includeParameters: true, lookup: { ...lookup, resolvedBy: 'id' } }) };
367
+ const insensitive = all.find((route) => route.id.toLowerCase() === normalized);
368
+ if (insensitive) return { status: 'found', route: describeRoute(insensitive, context, toolRegistry, { includeParameters: true, lookup: { ...lookup, resolvedBy: 'case-insensitive-id' } }) };
369
+ const searched = matchingRoutes(normalized);
370
+ if (searched.length === 1) return { status: 'found', route: describeRoute(searched[0]!, context, toolRegistry, { includeParameters: true, lookup: { ...lookup, resolvedBy: 'search' } }) };
371
+ if (searched.length > 1) {
372
+ return {
373
+ status: 'ambiguous',
374
+ input: lookup.input,
375
+ candidates: searched.slice(0, 8).map((route) => describeCandidate(route, context, toolRegistry)),
376
+ };
377
+ }
378
+ return {
379
+ status: 'missing_lookup',
380
+ usage: `Unknown execution route ${lookup.input}. Use execution action:"status" to list route ids.`,
381
+ };
382
+ }
@@ -0,0 +1,135 @@
1
+ import { isAbsolute, relative } from 'node:path';
2
+ import type { CommandContext } from '../input/command-registry.ts';
3
+
4
+ export interface AgentHarnessFileRecoveryArgs {
5
+ readonly recoveryAction?: unknown;
6
+ readonly actionId?: unknown;
7
+ readonly target?: unknown;
8
+ readonly query?: unknown;
9
+ readonly includeParameters?: unknown;
10
+ }
11
+
12
+ type FileRecoveryAction = 'undo' | 'redo';
13
+
14
+ function readString(value: unknown): string {
15
+ return typeof value === 'string' ? value.trim() : '';
16
+ }
17
+
18
+ function recoveryActionFromArgs(args: AgentHarnessFileRecoveryArgs): FileRecoveryAction | null {
19
+ const input = readString(args.recoveryAction || args.actionId || args.target || args.query).toLowerCase();
20
+ if (input === 'undo' || input === 'file undo' || input === 'undo file') return 'undo';
21
+ if (input === 'redo' || input === 'file redo' || input === 'redo file') return 'redo';
22
+ return null;
23
+ }
24
+
25
+ function workspacePath(context: CommandContext, filePath: string): string {
26
+ const root = context.workspace?.shellPaths?.workingDirectory;
27
+ if (!root) return filePath;
28
+ const rel = relative(root, filePath);
29
+ if (rel === '') return '.';
30
+ if (!rel.startsWith('..') && !isAbsolute(rel)) return rel;
31
+ return '<outside-workspace>';
32
+ }
33
+
34
+ function managerStatus(context: CommandContext): {
35
+ readonly available: boolean;
36
+ readonly undoDepth: number;
37
+ readonly redoDepth: number;
38
+ readonly nextUndo?: Record<string, unknown>;
39
+ } {
40
+ const manager = context.workspace.fileUndoManager;
41
+ if (!manager) return { available: false, undoDepth: 0, redoDepth: 0 };
42
+ const nextUndo = manager.peekUndo();
43
+ return {
44
+ available: true,
45
+ undoDepth: manager.undoDepth(),
46
+ redoDepth: manager.redoDepth(),
47
+ ...(nextUndo ? {
48
+ nextUndo: {
49
+ path: workspacePath(context, nextUndo.path),
50
+ tool: nextUndo.tool,
51
+ timestamp: nextUndo.timestamp,
52
+ },
53
+ } : {}),
54
+ };
55
+ }
56
+
57
+ function recoveryActions(status: ReturnType<typeof managerStatus>): readonly Record<string, unknown>[] {
58
+ return [
59
+ {
60
+ recoveryAction: 'undo',
61
+ label: 'Undo last file edit/write',
62
+ available: status.available && status.undoDepth > 0,
63
+ modelRoute: 'agent_harness mode:"run_file_recovery"',
64
+ requiresConfirmation: true,
65
+ },
66
+ {
67
+ recoveryAction: 'redo',
68
+ label: 'Redo last undone file edit/write',
69
+ available: status.available && status.redoDepth > 0,
70
+ modelRoute: 'agent_harness mode:"run_file_recovery"',
71
+ requiresConfirmation: true,
72
+ },
73
+ ];
74
+ }
75
+
76
+ export function fileRecoveryCatalogStatus(context: CommandContext): Record<string, unknown> {
77
+ const status = managerStatus(context);
78
+ return {
79
+ modes: ['file_recovery', 'run_file_recovery'],
80
+ available: status.available,
81
+ undoDepth: status.undoDepth,
82
+ redoDepth: status.redoDepth,
83
+ readOnly: true,
84
+ };
85
+ }
86
+
87
+ export function fileRecoverySummary(context: CommandContext, args: AgentHarnessFileRecoveryArgs): Record<string, unknown> {
88
+ const status = managerStatus(context);
89
+ return {
90
+ status: status.available ? 'available' : 'unavailable',
91
+ summary: status,
92
+ actions: recoveryActions(status),
93
+ policy: 'Read-only file recovery posture. Recovery content is not exposed; run_file_recovery requires confirm:true and explicitUserRequest.',
94
+ ...(args.includeParameters === true ? {
95
+ modelAccess: {
96
+ inspect: 'execution action:"recovery"',
97
+ undo: 'agent_harness mode:"run_file_recovery" recoveryAction:"undo" confirm:true explicitUserRequest:"..."',
98
+ redo: 'agent_harness mode:"run_file_recovery" recoveryAction:"redo" confirm:true explicitUserRequest:"..."',
99
+ },
100
+ } : {}),
101
+ };
102
+ }
103
+
104
+ export function runFileRecovery(context: CommandContext, args: AgentHarnessFileRecoveryArgs): Record<string, unknown> {
105
+ const manager = context.workspace.fileUndoManager;
106
+ if (!manager) {
107
+ return {
108
+ status: 'unavailable',
109
+ error: 'No file recovery manager is available in this runtime.',
110
+ };
111
+ }
112
+ const action = recoveryActionFromArgs(args);
113
+ if (!action) {
114
+ return {
115
+ status: 'missing_action',
116
+ usage: 'run_file_recovery requires recoveryAction:"undo" or recoveryAction:"redo". Use execution action:"recovery" first to inspect depth.',
117
+ };
118
+ }
119
+ const result = action === 'undo' ? manager.undo() : manager.redo();
120
+ if (!result) {
121
+ return {
122
+ status: 'nothing_to_recover',
123
+ recoveryAction: action,
124
+ summary: managerStatus(context),
125
+ };
126
+ }
127
+ return {
128
+ status: 'applied',
129
+ recoveryAction: action,
130
+ path: workspacePath(context, result.path),
131
+ tool: result.tool,
132
+ summary: managerStatus(context),
133
+ policy: 'File recovery restored file bytes from the local FileUndoManager snapshot without exposing recovered content.',
134
+ };
135
+ }
@@ -250,11 +250,11 @@ function resolveHarnessKeybinding(context: CommandContext, args: HarnessKeybindi
250
250
 
251
251
  function keybindingModelRoute(action: KeyAction): string {
252
252
  const route = keybindingOperationRoute(action);
253
- if (route.preferredMode === 'run_keybinding') return `agent_harness mode:"run_keybinding" actionId:"${action}"`;
254
- if (route.preferredMode === 'open_ui_surface' && route.surfaceId) return `agent_harness mode:"open_ui_surface" surfaceId:"${route.surfaceId}"`;
255
- if (route.preferredMode === 'open_ui_surface') return 'agent_harness mode:"open_ui_surface"';
256
- if (route.preferredMode === 'run_command' && route.command) return `agent_harness mode:"run_command" command:"${route.command}"`;
257
- if (route.preferredMode === 'run_command') return 'agent_harness mode:"run_command"';
253
+ if (route.preferredMode === 'run_keybinding') return `workspace action:"run_keybinding" actionId:"${action}"`;
254
+ if (route.preferredMode === 'open_ui_surface' && route.surfaceId) return `workspace action:"open" surfaceId:"${route.surfaceId}"`;
255
+ if (route.preferredMode === 'open_ui_surface') return 'workspace action:"open"';
256
+ if (route.preferredMode === 'run_command' && route.command) return `workspace action:"run_command" command:"${route.command}"`;
257
+ if (route.preferredMode === 'run_command') return 'workspace action:"run_command"';
258
258
  return 'direct-user-interaction';
259
259
  }
260
260
 
@@ -265,6 +265,10 @@ function keybindingModelAccess(action: KeyAction, operation: KeybindingOperation
265
265
  set: `agent_harness mode:"set_keybinding" actionId:"${action}" combo:{...} confirm:true explicitUserRequest:"..."`,
266
266
  reset: `agent_harness mode:"reset_keybinding" actionId:"${action}" confirm:true explicitUserRequest:"..."`,
267
267
  preferred: keybindingModelRoute(action),
268
+ directInspect: `workspace action:"keybinding" actionId:"${action}"`,
269
+ directRun: operation.supported ? `workspace action:"run_keybinding" actionId:"${action}" confirm:true explicitUserRequest:"..."` : 'not exposed',
270
+ directSet: `workspace action:"set_keybinding" actionId:"${action}" combo:{...} confirm:true explicitUserRequest:"..."`,
271
+ directReset: `workspace action:"reset_keybinding" actionId:"${action}" confirm:true explicitUserRequest:"..."`,
268
272
  };
269
273
  }
270
274
 
@@ -435,12 +439,12 @@ export function totalHarnessShortcuts(context: CommandContext): number {
435
439
  }
436
440
 
437
441
  function fixedShortcutModelRoute(shortcut: Record<string, string>): string {
438
- if (shortcut.key.includes('/shortcuts')) return 'agent_harness mode:"shortcuts"';
439
- if (shortcut.key.includes('/keybindings')) return 'agent_harness mode:"keybindings"';
440
- if (shortcut.key.includes('?') || shortcut.key.includes('F1')) return 'agent_harness mode:"open_ui_surface" surfaceId:"help-overlay"';
441
- if (shortcut.key.includes('F2')) return 'agent_harness mode:"open_ui_surface" surfaceId:"process-monitor"';
442
+ if (shortcut.key.includes('/shortcuts')) return 'workspace action:"shortcuts"';
443
+ if (shortcut.key.includes('/keybindings')) return 'workspace action:"keybindings"';
444
+ if (shortcut.key.includes('?') || shortcut.key.includes('F1')) return 'workspace action:"open" surfaceId:"help-overlay"';
445
+ if (shortcut.key.includes('F2')) return 'workspace action:"open" surfaceId:"process-monitor"';
442
446
  if (shortcut.key.includes('Esc')) return 'direct-user-interaction';
443
- if (shortcut.key.includes('Tab')) return 'agent_harness mode:"commands"';
447
+ if (shortcut.key.includes('Tab')) return 'workspace action:"commands"';
444
448
  if (shortcut.key.includes('Enter')) return 'main conversation';
445
449
  return 'direct-user-interaction';
446
450
  }
@@ -452,8 +456,8 @@ function describeFixedShortcut(shortcut: Record<string, string>): Record<string,
452
456
  userEditable: false,
453
457
  modelRoute: fixedShortcutModelRoute(shortcut),
454
458
  modelAccess: {
455
- inspectShortcuts: 'agent_harness mode:"shortcuts"',
456
- inspectKeybindings: 'agent_harness mode:"keybindings"',
459
+ inspectShortcuts: 'workspace action:"shortcuts"',
460
+ inspectKeybindings: 'workspace action:"keybindings"',
457
461
  preferred: fixedShortcutModelRoute(shortcut),
458
462
  },
459
463
  };