@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
@@ -5,9 +5,8 @@ import type {
5
5
  AgentWorkspaceLocalEditor,
6
6
  AgentWorkspaceRuntimeSnapshot,
7
7
  } from '../input/agent-workspace.ts';
8
- import { formatAgentRecordReviewState } from '../agent/record-labels.ts';
9
8
  import type { Line } from '../types/grid.ts';
10
- import { truncateDisplay, wrapText } from '../utils/terminal-width.ts';
9
+ import { wrapText } from '../utils/terminal-width.ts';
11
10
  import { GLYPHS } from './ui-primitives.ts';
12
11
  import {
13
12
  getFullscreenWorkspaceMetrics,
@@ -17,7 +16,8 @@ import {
17
16
  WORKSPACE_PALETTE as PALETTE,
18
17
  type WorkspaceRow,
19
18
  } from './fullscreen-workspace.ts';
20
- import { actionResultColor, setupStatusColor, type AgentWorkspaceContextLine as ContextLine } from './agent-workspace-style.ts';
19
+ import { actionResultColor, type AgentWorkspaceContextLine as ContextLine } from './agent-workspace-style.ts';
20
+ import { compactText, reviewerReadinessContextLines, snapshotLines } from './agent-workspace-context-lines.ts';
21
21
 
22
22
  function buildLeftRows(workspace: AgentWorkspace, height: number): WorkspaceRow[] {
23
23
  const rows: WorkspaceRow[] = [];
@@ -59,6 +59,7 @@ function actionCommand(action: AgentWorkspaceAction): string {
59
59
  if (action.kind === 'editor') return action.editorKind ? `edit ${action.editorKind}` : 'edit form';
60
60
  if (action.kind === 'setting') return action.settingKey ? `setting ${action.settingKey}` : 'setting';
61
61
  if (action.kind === 'settings-import') return 'import GoodVibes settings';
62
+ if (action.kind === 'setup-checkpoint') return action.setupCheckpointOperation ? `setup checkpoint ${action.setupCheckpointOperation}` : 'setup checkpoint';
62
63
  if (action.kind === 'model-picker') return action.modelPickerFlow === 'model' ? 'model picker' : 'provider/model picker';
63
64
  if (action.kind === 'settings-modal') return action.settingsTarget ? `settings ${action.settingsTarget}` : 'settings';
64
65
  if (action.kind === 'local-selection') return action.selectionDelta && action.selectionDelta < 0 ? 'select previous' : 'select next';
@@ -67,38 +68,6 @@ function actionCommand(action: AgentWorkspaceAction): string {
67
68
  return action.command ?? '(guidance)';
68
69
  }
69
70
 
70
- function setupCounts(snapshot: AgentWorkspaceRuntimeSnapshot): { ready: number; recommended: number; optional: number; blocked: number } {
71
- return {
72
- ready: snapshot.setupChecklist.filter((item) => item.status === 'ready').length,
73
- recommended: snapshot.setupChecklist.filter((item) => item.status === 'recommended').length,
74
- optional: snapshot.setupChecklist.filter((item) => item.status === 'optional').length,
75
- blocked: snapshot.setupChecklist.filter((item) => item.status === 'blocked').length,
76
- };
77
- }
78
-
79
- function setupStatusLabel(status: AgentWorkspaceRuntimeSnapshot['setupChecklist'][number]['status']): string {
80
- return status === 'ready'
81
- ? 'Ready'
82
- : status === 'recommended'
83
- ? 'Recommended'
84
- : status === 'blocked'
85
- ? 'Blocked'
86
- : 'Optional';
87
- }
88
-
89
- function formatMegabytes(bytes: number): string {
90
- if (!Number.isFinite(bytes) || bytes <= 0) return '0 MB';
91
- return `${Math.round(bytes / (1024 * 1024))} MB`;
92
- }
93
-
94
- function compactText(text: string, maxWidth = 104): string {
95
- const normalized = text.replace(/\s+/g, ' ').trim();
96
- if (normalized.length === 0) return '';
97
- const firstSentence = normalized.match(/^.*?[.!?](?:\s|$)/)?.[0]?.trim();
98
- const source = firstSentence && firstSentence.length <= maxWidth ? firstSentence : normalized;
99
- return truncateDisplay(source, maxWidth, '...');
100
- }
101
-
102
71
  function actionMetaLine(action: AgentWorkspaceAction): ContextLine {
103
72
  return {
104
73
  text: `Does: ${actionCommand(action)}`,
@@ -106,389 +75,7 @@ function actionMetaLine(action: AgentWorkspaceAction): ContextLine {
106
75
  };
107
76
  }
108
77
 
109
- function setupAttentionItems(snapshot: AgentWorkspaceRuntimeSnapshot, limit: number): AgentWorkspaceRuntimeSnapshot['setupChecklist'] {
110
- return [
111
- ...snapshot.setupChecklist.filter((item) => item.status === 'blocked'),
112
- ...snapshot.setupChecklist.filter((item) => item.status === 'recommended'),
113
- ...snapshot.setupChecklist.filter((item) => item.status === 'optional'),
114
- ].slice(0, limit);
115
- }
116
-
117
- function conciseSetupLine(snapshot: AgentWorkspaceRuntimeSnapshot): ContextLine {
118
- const counts = setupCounts(snapshot);
119
- return {
120
- text: `Setup: ${counts.ready}/${snapshot.setupChecklist.length} ready; ${counts.recommended} recommended; ${counts.blocked} blocked.`,
121
- fg: counts.blocked > 0 ? PALETTE.warn : PALETTE.info,
122
- };
123
- }
124
-
125
- function setupOverviewLines(snapshot: AgentWorkspaceRuntimeSnapshot): ContextLine[] {
126
- const counts = setupCounts(snapshot);
127
- const nextItems = setupAttentionItems(snapshot, 3);
128
- const lines: ContextLine[] = [
129
- { text: 'Onboarding', fg: PALETTE.title, bold: true },
130
- { text: `${counts.ready}/${snapshot.setupChecklist.length} ready; ${counts.recommended} recommended; ${counts.optional} optional; ${counts.blocked} blocked.`, fg: counts.blocked > 0 ? PALETTE.warn : PALETTE.info },
131
- { text: `Chat: ${snapshot.provider} / ${snapshot.modelDisplayName}.`, fg: PALETTE.info },
132
- { text: `Local: ${snapshot.localPersonaCount} personas, ${snapshot.localSkillCount} skills, ${snapshot.localRoutineCount} routines, ${snapshot.localMemoryCount} memories.`, fg: PALETTE.info },
133
- ];
134
- if (nextItems.length > 0) {
135
- const item = nextItems[0]!;
136
- lines.push({
137
- text: `Next: ${item.label} (${setupStatusLabel(item.status).toLowerCase()})`,
138
- fg: setupStatusColor(item.status),
139
- bold: item.status === 'blocked',
140
- });
141
- }
142
- return lines;
143
- }
144
-
145
- function homeNextActionLines(snapshot: AgentWorkspaceRuntimeSnapshot): ContextLine[] {
146
- const candidates = setupAttentionItems(snapshot, 3);
147
- if (candidates.length === 0) {
148
- return [
149
- { text: 'Next Actions', fg: PALETTE.title, bold: true },
150
- { text: 'Core setup is ready. Continue normal assistant work, review Knowledge sources, or tune local skills/routines as needed.', fg: PALETTE.good },
151
- ];
152
- }
153
- const lines: ContextLine[] = [{ text: 'Next Actions', fg: PALETTE.title, bold: true }];
154
- for (const item of candidates) {
155
- lines.push({
156
- text: `${setupStatusLabel(item.status)}: ${item.label}`,
157
- fg: setupStatusColor(item.status),
158
- bold: item.status === 'blocked',
159
- });
160
- }
161
- return lines;
162
- }
163
-
164
- function companionAccessLine(snapshot: AgentWorkspaceRuntimeSnapshot): ContextLine {
165
- const access = snapshot.companionAccess;
166
- const tokenState = access.tokenReadable
167
- ? `ready sha256:${access.tokenFingerprint ?? 'unknown'}`
168
- : access.tokenPresent
169
- ? 'present but unreadable'
170
- : 'missing';
171
- const error = access.tokenError ? `; token read error ${access.tokenError}` : '';
172
- return {
173
- text: `Companion: ${access.surface}; token ${tokenState}; QR ${access.qrCommand}${error}.`,
174
- fg: access.pairingReady ? PALETTE.good : PALETTE.warn,
175
- };
176
- }
177
-
178
- function compactLocalLibraryLines(
179
- title: string,
180
- items: readonly AgentWorkspaceRuntimeSnapshot['localPersonas'][number][],
181
- emptyText: string,
182
- selectedId: string | null,
183
- ): ContextLine[] {
184
- const lines: ContextLine[] = [];
185
- if (items.length === 0) {
186
- lines.push({ text: `${title}: 0. ${emptyText}`, fg: PALETTE.warn });
187
- return lines;
188
- }
189
- const selected = items.find((item) => item.id === selectedId) ?? items[0]!;
190
- const status = [
191
- selected.active ? 'active' : '',
192
- selected.enabled === true ? 'enabled' : selected.enabled === false ? 'disabled' : '',
193
- selected.scope && selected.cls ? `${selected.scope}/${selected.cls}` : '',
194
- selected.confidence !== undefined ? `${selected.confidence}%` : '',
195
- selected.requirementCount !== undefined && selected.requirementCount > 0
196
- ? (selected.missingRequirementCount && selected.missingRequirementCount > 0 ? `needs ${selected.missingRequirementCount}/${selected.requirementCount}` : `ready ${selected.requirementCount}/${selected.requirementCount}`)
197
- : '',
198
- formatAgentRecordReviewState(selected.reviewState),
199
- selected.startCount !== undefined ? `starts ${selected.startCount}` : '',
200
- ].filter(Boolean).join(', ');
201
- lines.push({
202
- text: `${title}: ${items.length}; selected ${selected.name}${status ? ` (${status})` : ''}.`,
203
- fg: selected.reviewState === 'stale' ? PALETTE.warn : PALETTE.info,
204
- bold: selected.active === true,
205
- });
206
- if (selected.missingRequirements && selected.missingRequirements.length > 0) {
207
- lines.push({ text: `Missing setup: ${selected.missingRequirements.join(', ')}`, fg: PALETTE.warn });
208
- }
209
- return lines;
210
- }
211
-
212
- type LocalRoutineItem = AgentWorkspaceRuntimeSnapshot['localRoutines'][number];
213
-
214
- function readyRoutineItems(snapshot: AgentWorkspaceRuntimeSnapshot): readonly LocalRoutineItem[] {
215
- return snapshot.localRoutines.filter((routine) =>
216
- routine.enabled === true
217
- && routine.reviewState === 'reviewed'
218
- && (routine.missingRequirementCount ?? 0) === 0
219
- );
220
- }
221
-
222
- function routinesNeedingSetup(snapshot: AgentWorkspaceRuntimeSnapshot): readonly LocalRoutineItem[] {
223
- return snapshot.localRoutines.filter((routine) => (routine.missingRequirementCount ?? 0) > 0);
224
- }
225
-
226
- function routinesNeedingReview(snapshot: AgentWorkspaceRuntimeSnapshot): readonly LocalRoutineItem[] {
227
- return snapshot.localRoutines.filter((routine) => routine.reviewState !== 'reviewed');
228
- }
229
-
230
- function routineNextActionLine(snapshot: AgentWorkspaceRuntimeSnapshot): ContextLine {
231
- const discovered = snapshot.discoveredBehavior.routines.count;
232
- const ready = readyRoutineItems(snapshot);
233
- const needsSetup = routinesNeedingSetup(snapshot);
234
- const needsReview = routinesNeedingReview(snapshot);
235
-
236
- if (snapshot.localRoutineCount === 0 && discovered > 0) {
237
- return { text: 'Next routine action: Discover routine files, preview one, then import it from this workspace.', fg: PALETTE.warn, bold: true };
238
- }
239
- if (snapshot.localRoutineCount === 0) {
240
- return { text: 'Next routine action: Create routine for a repeatable main-conversation workflow.', fg: PALETTE.warn, bold: true };
241
- }
242
- if (needsSetup.length > 0) {
243
- return { text: `Next routine action: Needs setup for ${needsSetup[0]?.id ?? 'a routine'} before it can be trusted for schedule promotion.`, fg: PALETTE.warn, bold: true };
244
- }
245
- if (needsReview.length > 0) {
246
- return { text: `Next routine action: Review selected or inspect ${needsReview[0]?.id ?? 'a routine'} before schedule promotion.`, fg: PALETTE.warn, bold: true };
247
- }
248
- if (ready.length > 0 && snapshot.routineScheduleReceiptCount === 0) {
249
- return { text: `Next routine action: Promote ${ready[0]?.id ?? 'a reviewed routine'} to a connected schedule when you have a real cadence.`, fg: PALETTE.good, bold: true };
250
- }
251
- return { text: 'Next routine action: Start selected in the main conversation, inspect receipts, or reconcile connected schedules.', fg: PALETTE.info, bold: true };
252
- }
253
-
254
- function compactRoutineReceiptLine(snapshot: AgentWorkspaceRuntimeSnapshot): ContextLine {
255
- const latest = snapshot.latestRoutineScheduleReceipt;
256
- if (!latest) {
257
- return {
258
- text: `Promotion receipts: ${snapshot.routineScheduleReceiptCount}; none created yet.`,
259
- fg: PALETTE.muted,
260
- };
261
- }
262
- return {
263
- text: `Promotion receipts: ${snapshot.routineScheduleReceiptCount}; latest ${latest.status} ${latest.routineId}.`,
264
- fg: latest.status === 'failed' ? PALETTE.warn : PALETTE.good,
265
- };
266
- }
267
-
268
- function automationNextActionLine(snapshot: AgentWorkspaceRuntimeSnapshot): ContextLine {
269
- const ready = readyRoutineItems(snapshot);
270
- const needsSetup = routinesNeedingSetup(snapshot);
271
- const needsReview = routinesNeedingReview(snapshot);
272
- if (snapshot.routineScheduleReceiptCount > 0) {
273
- return { text: 'Next automation action: Reconcile schedules to compare local receipts with the connected host.', fg: PALETTE.info, bold: true };
274
- }
275
- if (ready.length > 0) {
276
- return { text: `Next automation action: Promote ${ready[0]?.id ?? 'a reviewed routine'} or create a one-off reminder.`, fg: PALETTE.good, bold: true };
277
- }
278
- if (needsSetup.length > 0) {
279
- return { text: `Next automation action: Resolve routine setup gaps in ${needsSetup[0]?.id ?? 'Routines'} before promotion, or create a reminder.`, fg: PALETTE.warn, bold: true };
280
- }
281
- if (needsReview.length > 0) {
282
- return { text: `Next automation action: Review ${needsReview[0]?.id ?? 'a routine'} in Routines before schedule promotion, or create a reminder.`, fg: PALETTE.warn, bold: true };
283
- }
284
- return { text: 'Next automation action: Create a reminder, or create/import a routine before recurring workflow promotion.', fg: PALETTE.warn, bold: true };
285
- }
286
-
287
- function snapshotLines(workspace: AgentWorkspace, category: AgentWorkspaceCategory, snapshot: AgentWorkspaceRuntimeSnapshot | null): ContextLine[] {
288
- if (!snapshot) return [{ text: 'Runtime context is not loaded yet.', fg: PALETTE.warn }];
289
- const base: ContextLine[] = [];
290
- if (category.id === 'home') {
291
- base.push(
292
- { text: `Chat route: ${snapshot.provider} / ${snapshot.modelDisplayName}`, fg: PALETTE.info },
293
- { text: `Session: ${snapshot.sessionId}`, fg: PALETTE.muted },
294
- { text: `Policy: ${snapshot.executionPolicy}; delegated review ${snapshot.delegatedReviewPolicy}`, fg: PALETTE.good },
295
- conciseSetupLine(snapshot),
296
- ...homeNextActionLines(snapshot),
297
- );
298
- } else if (category.id === 'setup') {
299
- base.push(
300
- ...setupOverviewLines(snapshot),
301
- );
302
- } else if (category.id === 'account-model') {
303
- base.push(
304
- { text: `Chat route: ${snapshot.provider} / ${snapshot.modelDisplayName}`, fg: PALETTE.info },
305
- { text: `Subscriptions: ${snapshot.activeSubscriptionCount} active; ${snapshot.pendingSubscriptionCount} pending; ${snapshot.availableSubscriptionProviderCount} available.`, fg: snapshot.activeSubscriptionCount > 0 ? PALETTE.good : snapshot.pendingSubscriptionCount > 0 ? PALETTE.warn : PALETTE.muted },
306
- { text: `Embedding: ${snapshot.embeddingProvider}; reasoning ${snapshot.reasoningEffort}.`, fg: PALETTE.info },
307
- { text: `Helper: ${snapshot.helperEnabled ? 'enabled' : 'disabled'}; Tool LLM: ${snapshot.toolLlmEnabled ? 'enabled' : 'disabled'}.`, fg: snapshot.helperEnabled || snapshot.toolLlmEnabled ? PALETTE.good : PALETTE.muted },
308
- { text: `Cache: ${snapshot.cacheEnabled ? snapshot.cacheStableTtl : 'off'}; monitor ${snapshot.cacheMonitorHitRate ? snapshot.cacheHitRateWarningThreshold : 'off'}; failure hints ${snapshot.providerFailureHints ? 'on' : 'off'}.`, fg: snapshot.cacheEnabled ? PALETTE.info : PALETTE.muted },
309
- );
310
- } else if (category.id === 'assistant-behavior') {
311
- base.push(
312
- { text: `Interaction: ${snapshot.hitlMode}; guidance ${snapshot.guidanceMode}; history ${snapshot.saveHistory ? 'saved' : 'off'}.`, fg: PALETTE.info },
313
- { text: `Context: compact at ${snapshot.autoCompactThreshold}; stale warnings ${snapshot.staleContextWarnings ? 'on' : 'off'}.`, fg: PALETTE.info },
314
- { text: `Reasoning display: thinking ${snapshot.showThinking ? 'on' : 'off'}; summaries ${snapshot.showReasoningSummary ? 'on' : 'off'}.`, fg: PALETTE.muted },
315
- );
316
- } else if (category.id === 'tools-permissions') {
317
- base.push(
318
- { text: `Permission mode: ${snapshot.permissionMode}.`, fg: snapshot.permissionMode === 'allow-all' ? PALETTE.warn : PALETTE.info },
319
- { text: `Auto-approve ${snapshot.autoApprove ? 'on' : 'off'}; tool auto-heal ${snapshot.toolAutoHeal ? 'on' : 'off'}; token budget ${snapshot.toolsDefaultTokenBudget}.`, fg: snapshot.autoApprove ? PALETTE.warn : PALETTE.info },
320
- { text: `Artifact limit ${formatMegabytes(snapshot.artifactMaxBytes)}; raw prompt telemetry ${snapshot.rawPromptTelemetry ? 'on' : 'off'}.`, fg: snapshot.rawPromptTelemetry ? PALETTE.warn : PALETTE.muted },
321
- { text: `MCP servers: ${snapshot.mcpConnectedServerCount}/${snapshot.mcpServerCount} connected; quarantined ${snapshot.mcpQuarantinedServerCount}.`, fg: snapshot.mcpQuarantinedServerCount > 0 ? PALETTE.warn : PALETTE.info },
322
- { text: 'MCP and secret setup use forms; selecting a row does not run arbitrary tools.', fg: PALETTE.good },
323
- );
324
- } else if (category.id === 'onboarding-display') {
325
- base.push(
326
- { text: `Theme: ${snapshot.theme}; streaming ${snapshot.stream ? 'on' : 'off'}; line numbers ${snapshot.lineNumbers}.`, fg: PALETTE.info },
327
- { text: `Messages: operational ${snapshot.operationalMessages}; system ${snapshot.systemMessages}.`, fg: PALETTE.info },
328
- { text: `Release channel: ${snapshot.releaseChannel}.`, fg: PALETTE.muted },
329
- );
330
- } else if (category.id === 'onboarding-channels') {
331
- const enabledCount = snapshot.channels.filter((channel) => channel.enabled).length;
332
- const readyCount = snapshot.channels.filter((channel) => channel.ready).length;
333
- const needsConfig = snapshot.channels.filter((channel) => channel.setupState === 'needs-config');
334
- const needsTarget = snapshot.channels.filter((channel) => channel.setupState === 'needs-target');
335
- base.push(
336
- { text: `Channels: ${readyCount}/${snapshot.channels.length} ready; ${enabledCount} enabled.`, fg: enabledCount > 0 ? PALETTE.info : PALETTE.muted },
337
- { text: `Needs config: ${needsConfig.length}; needs target: ${needsTarget.length}.`, fg: needsConfig.length > 0 || needsTarget.length > 0 ? PALETTE.warn : PALETTE.good },
338
- { text: 'Enable only the channels you want; hidden channel fields appear after the channel is enabled.', fg: PALETTE.good },
339
- );
340
- } else if (category.id === 'onboarding-voice-media') {
341
- const readiness = snapshot.voiceMediaReadiness;
342
- base.push(
343
- { text: `Voice: ${snapshot.voiceSurfaceEnabled ? 'enabled' : 'disabled'}; TTS ${snapshot.ttsProvider}; voice ${snapshot.ttsVoice}.`, fg: snapshot.voiceSurfaceEnabled ? PALETTE.good : PALETTE.info },
344
- { text: `Media readiness: ${readiness.readyMediaProviderCount}/${snapshot.mediaProviderCount}; generation providers ${snapshot.mediaGenerationProviderCount}.`, fg: readiness.readyMediaProviderCount > 0 ? PALETTE.good : PALETTE.muted },
345
- { text: `Telephony channel: ${snapshot.channels.find((channel) => channel.id === 'telephony')?.setupState ?? 'disabled'}.`, fg: PALETTE.info },
346
- );
347
- } else if (category.id === 'onboarding-context') {
348
- base.push(
349
- { text: `Local context: ${snapshot.localMemoryCount} memories, ${snapshot.localNoteCount} notes, ${snapshot.localPersonaCount} personas.`, fg: PALETTE.info },
350
- { text: `Skills: ${snapshot.enabledSkillCount}/${snapshot.localSkillCount} enabled; routines ${snapshot.enabledRoutineCount}/${snapshot.localRoutineCount} enabled.`, fg: PALETTE.info },
351
- { text: `Discovered files: personas ${snapshot.discoveredBehavior.personas.count}, skills ${snapshot.discoveredBehavior.skills.count}, routines ${snapshot.discoveredBehavior.routines.count}.`, fg: PALETTE.muted },
352
- );
353
- } else if (category.id === 'onboarding-automation') {
354
- base.push(
355
- { text: `Automation: ${snapshot.automationEnabled ? 'enabled' : 'disabled'}; max ${snapshot.automationMaxConcurrentRuns} concurrent; history ${snapshot.automationRunHistoryLimit}.`, fg: snapshot.automationEnabled ? PALETTE.good : PALETTE.muted },
356
- { text: `Timeout ${snapshot.automationDefaultTimeoutMs} ms; catch-up ${snapshot.automationCatchUpWindowMinutes} min; cooldown ${snapshot.automationFailureCooldownMs} ms.`, fg: PALETTE.info },
357
- { text: `Delete one-shot jobs after success: ${snapshot.automationDeleteAfterRun ? 'yes' : 'no'}.`, fg: snapshot.automationDeleteAfterRun ? PALETTE.info : PALETTE.muted },
358
- );
359
- } else if (category.id === 'artifacts') {
360
- const mediaReady = snapshot.voiceMediaReadiness.readyMediaProviderCount;
361
- base.push(
362
- { text: `Chat: ${snapshot.provider} / ${snapshot.modelDisplayName}; Knowledge: ${snapshot.knowledgeRoute}`, fg: PALETTE.info },
363
- { text: `Media: ${mediaReady}/${snapshot.mediaProviderCount} ready; generation ${snapshot.mediaGenerationProviderCount}.`, fg: mediaReady > 0 ? PALETTE.good : PALETTE.warn },
364
- { text: 'Files: attach, export, inspect, ingest reviewed sources, or generate media.', fg: PALETTE.good },
365
- { text: 'Knowledge ingest and media generation require explicit actions.', fg: PALETTE.warn },
366
- );
367
- } else if (category.id === 'channels') {
368
- const enabledCount = snapshot.channels.filter((channel) => channel.enabled).length;
369
- const readyCount = snapshot.channels.filter((channel) => channel.ready).length;
370
- const configuredDefaults = snapshot.channels.filter((channel) => channel.defaultTarget === 'configured').length;
371
- const needsTarget = snapshot.channels.filter((channel) => channel.setupState === 'needs-target');
372
- const needsConfig = snapshot.channels.filter((channel) => channel.setupState === 'needs-config');
373
- const nextAttentionChannel = needsConfig[0] ?? needsTarget[0] ?? snapshot.channels.find((channel) => !channel.enabled);
374
- base.push(
375
- { text: `API: ${snapshot.runtimeBaseUrl}`, fg: PALETTE.info },
376
- companionAccessLine(snapshot),
377
- { text: `Channels: ${readyCount}/${snapshot.channels.length} ready; ${enabledCount} enabled; ${configuredDefaults} target(s).`, fg: PALETTE.info },
378
- { text: `Next: ${nextAttentionChannel ? `${nextAttentionChannel.label} - ${compactText(nextAttentionChannel.nextStep)}` : 'All enabled channels ready.'}`, fg: nextAttentionChannel ? PALETTE.warn : PALETTE.good },
379
- { text: 'Secrets hidden; sends require explicit action.', fg: PALETTE.warn },
380
- );
381
- } else if (category.id === 'knowledge') {
382
- base.push(
383
- { text: `Route: ${snapshot.knowledgeRoute}; isolation ${snapshot.knowledgeIsolation}.`, fg: PALETTE.info },
384
- { text: 'Ask/search, ingest, review, reindex, and reports stay Agent-owned.', fg: PALETTE.good },
385
- { text: 'Ingest requires explicit confirmation.', fg: PALETTE.warn },
386
- );
387
- } else if (category.id === 'research') {
388
- base.push(
389
- { text: `Chat: ${snapshot.provider} / ${snapshot.modelDisplayName}; Knowledge: ${snapshot.knowledgeRoute}`, fg: PALETTE.info },
390
- { text: `Browser: ${snapshot.voiceMediaReadiness.browserToolState}; public URL ${snapshot.browserToolPublicBaseUrl}.`, fg: snapshot.browserToolExposureEnabled ? PALETTE.warn : PALETTE.muted },
391
- { text: 'Research is read-only. Knowledge ingest is a separate confirmed action.', fg: PALETTE.good },
392
- { text: compactText(snapshot.voiceMediaReadiness.browserToolNextStep), fg: PALETTE.muted },
393
- );
394
- } else if (category.id === 'tools') {
395
- base.push(
396
- { text: `MCP servers: ${snapshot.mcpConnectedServerCount}/${snapshot.mcpServerCount} connected; quarantined ${snapshot.mcpQuarantinedServerCount}; allow-all ${snapshot.mcpAllowAllServerCount}.`, fg: snapshot.mcpQuarantinedServerCount > 0 || snapshot.mcpAllowAllServerCount > 0 ? PALETTE.warn : PALETTE.info },
397
- { text: 'Add/update/reload and trust changes require confirmation.', fg: PALETTE.good },
398
- { text: 'Start: /mcp review, /mcp tools, /mcp config, Add MCP server.', fg: PALETTE.muted },
399
- );
400
- } else if (category.id === 'voice-media') {
401
- const readiness = snapshot.voiceMediaReadiness;
402
- base.push(
403
- { text: `Voice: ${readiness.readyVoiceProviderCount}/${snapshot.voiceProviderCount} ready; TTS ${snapshot.ttsProvider}; voice ${snapshot.ttsVoice}.`, fg: readiness.readyVoiceProviderCount > 0 ? PALETTE.good : PALETTE.warn },
404
- { text: `Media: ${readiness.readyMediaProviderCount}/${snapshot.mediaProviderCount} ready; generation ${snapshot.mediaGenerationProviderCount}.`, fg: readiness.readyMediaProviderCount > 0 ? PALETTE.good : PALETTE.warn },
405
- { text: `Browser: ${readiness.browserToolState}; public URL ${snapshot.browserToolPublicBaseUrl}.`, fg: snapshot.browserToolExposureEnabled ? PALETTE.warn : PALETTE.muted },
406
- { text: readiness.nextSteps[0] ? `Next: ${compactText(readiness.nextSteps[0])}` : 'Next: voice/media setup is ready.', fg: readiness.nextSteps.length > 0 ? PALETTE.info : PALETTE.good },
407
- { text: 'Secrets hidden; voice, browser, and media side effects require explicit action.', fg: PALETTE.warn },
408
- );
409
- } else if (category.id === 'profiles') {
410
- const defaultProfile = snapshot.selectedRuntimeProfile
411
- ? `${snapshot.selectedRuntimeProfile}${snapshot.selectedRuntimeProfileExists ? '' : ' (missing)'}`
412
- : '(base Agent home)';
413
- base.push(
414
- { text: `Profiles: active ${snapshot.activeRuntimeProfile}; default ${defaultProfile}.`, fg: snapshot.selectedRuntimeProfileExists || !snapshot.selectedRuntimeProfile ? PALETTE.info : PALETTE.warn },
415
- { text: `Local profiles: ${snapshot.runtimeProfileCount}; starters ${snapshot.runtimeStarterTemplateCount}; custom ${snapshot.localStarterTemplateCount}.`, fg: PALETTE.info },
416
- { text: `Starter ids: ${truncateDisplay(snapshot.runtimeStarterTemplates.map((template) => template.id).join(', ') || 'none', 96, '...')}`, fg: PALETTE.muted },
417
- { text: 'Profiles isolate local Agent config, sessions, memory, personas, skills, routines, setup, and bundles.', fg: PALETTE.good },
418
- );
419
- } else if (category.id === 'memory') {
420
- base.push(
421
- { text: `Memory: ${snapshot.localMemoryCount}; prompt ${snapshot.localMemoryPromptActiveCount}; queue ${snapshot.localMemoryReviewQueueCount}; session ${snapshot.sessionMemoryCount}.`, fg: PALETTE.info },
422
- { text: `Notes: ${snapshot.localNoteCount}; skills ${snapshot.localSkillCount}/${snapshot.enabledSkillCount}; routines ${snapshot.localRoutineCount}/${snapshot.enabledRoutineCount}; personas ${snapshot.localPersonaCount}.`, fg: PALETTE.info },
423
- { text: `Active persona: ${snapshot.activePersonaName}.`, fg: PALETTE.info },
424
- ...compactLocalLibraryLines('Agent Memory', snapshot.localMemories, 'Create one with Create memory.', workspace.selectedLocalLibraryItem('memory')?.id ?? null),
425
- { text: 'Secrets are rejected or redacted; use secret references.', fg: PALETTE.warn },
426
- );
427
- } else if (category.id === 'notes') {
428
- base.push(
429
- { text: `Scratchpad notes: ${snapshot.localNoteCount}; review queue: ${snapshot.localNoteReviewQueueCount}`, fg: PALETTE.info },
430
- ...compactLocalLibraryLines('Scratchpad Notes', snapshot.localNotes, 'Create one with Create note.', workspace.selectedLocalLibraryItem('note')?.id ?? null),
431
- { text: 'Notes stay local unless promoted by explicit action.', fg: PALETTE.warn },
432
- );
433
- } else if (category.id === 'personas') {
434
- base.push(
435
- { text: `Personas: ${snapshot.localPersonaCount}; active: ${snapshot.activePersonaName}`, fg: PALETTE.info },
436
- ...compactLocalLibraryLines('Persona Library', snapshot.localPersonas, 'Create one with Create persona.', workspace.selectedLocalLibraryItem('persona')?.id ?? null),
437
- { text: 'Personas shape the serial main-conversation assistant.', fg: PALETTE.good },
438
- );
439
- } else if (category.id === 'skills') {
440
- base.push(
441
- { text: `Skills: ${snapshot.localSkillCount}; enabled: ${snapshot.enabledSkillCount}; bundles: ${snapshot.localSkillBundleCount}; enabled bundles: ${snapshot.enabledSkillBundleCount}; active skills: ${snapshot.activeSkillCount}`, fg: PALETTE.info },
442
- ...compactLocalLibraryLines('Skill Library', snapshot.localSkills, 'Create one with Create skill.', workspace.selectedLocalLibraryItem('skill')?.id ?? null),
443
- ...compactLocalLibraryLines('Skill Bundles', snapshot.localSkillBundles, 'Create one after adding skills.', null),
444
- { text: 'Enabled skills/bundles become operating guidance; secrets are rejected.', fg: PALETTE.warn },
445
- );
446
- } else if (category.id === 'routines') {
447
- const ready = readyRoutineItems(snapshot);
448
- const needsSetup = routinesNeedingSetup(snapshot);
449
- const needsReview = routinesNeedingReview(snapshot);
450
- base.push(
451
- { text: `Routines: ${snapshot.localRoutineCount}; enabled: ${snapshot.enabledRoutineCount}`, fg: PALETTE.info },
452
- { text: `Schedule-ready routines: ${ready.length}; setup gaps: ${needsSetup.length}; review needed: ${needsReview.length}`, fg: needsSetup.length > 0 || needsReview.length > 0 ? PALETTE.warn : PALETTE.good },
453
- routineNextActionLine(snapshot),
454
- compactRoutineReceiptLine(snapshot),
455
- ...compactLocalLibraryLines('Routine Library', snapshot.localRoutines, 'Create one with Create routine.', workspace.selectedLocalLibraryItem('routine')?.id ?? null),
456
- { text: 'Scheduling requires a confirmed action.', fg: PALETTE.warn },
457
- );
458
- } else if (category.id === 'work') {
459
- base.push(
460
- { text: 'Work plans and approvals are read or explicitly confirmed.', fg: PALETTE.info },
461
- { text: 'Selection alone does not approve, deny, cancel, or mutate requests.', fg: PALETTE.good },
462
- { text: 'Approval actions require id plus typed confirmation.', fg: PALETTE.warn },
463
- );
464
- } else if (category.id === 'automation') {
465
- const ready = readyRoutineItems(snapshot);
466
- base.push(
467
- { text: `Automation: ${ready.length} schedule-ready routine(s); receipts ${snapshot.routineScheduleReceiptCount}.`, fg: ready.length > 0 ? PALETTE.good : PALETTE.warn },
468
- automationNextActionLine(snapshot),
469
- compactRoutineReceiptLine(snapshot),
470
- { text: 'Reminders and routine promotion require confirmation.', fg: PALETTE.warn },
471
- );
472
- } else if (category.id === 'delegate') {
473
- base.push(
474
- { text: 'Build/fix/review work is handed to GoodVibes TUI.', fg: PALETTE.info },
475
- { text: `Delegated review policy: ${snapshot.delegatedReviewPolicy}`, fg: PALETTE.warn },
476
- { text: 'No coding-role Agent jobs are created here.', fg: PALETTE.good },
477
- );
478
- } else if (category.id === 'finish') {
479
- base.push(
480
- { text: 'Apply & close marks onboarding finished for this user.', fg: PALETTE.good },
481
- { text: 'Future normal launches start in the main conversation.', fg: PALETTE.info },
482
- { text: 'Use /agent, /setup, or /onboarding to reopen this workspace later.', fg: PALETTE.muted },
483
- );
484
- }
485
- if (snapshot.warnings.length > 0) {
486
- base.push({ text: `Warnings: ${snapshot.warnings.map((warning) => compactText(warning, 60)).join('; ')}`, fg: PALETTE.warn });
487
- }
488
- return base;
489
- }
490
-
491
- function editorContextLines(editor: AgentWorkspaceLocalEditor): ContextLine[] {
78
+ function editorContextLines(editor: AgentWorkspaceLocalEditor, snapshot: AgentWorkspaceRuntimeSnapshot | null): ContextLine[] {
492
79
  const selected = editor.fields[editor.selectedFieldIndex];
493
80
  const lines: ContextLine[] = [
494
81
  { text: editor.title, fg: PALETTE.title, bold: true },
@@ -501,6 +88,30 @@ function editorContextLines(editor: AgentWorkspaceLocalEditor): ContextLine[] {
501
88
  { text: compactText(selected.hint), fg: PALETTE.muted },
502
89
  );
503
90
  }
91
+ lines.push(...reviewerReadinessContextLines(editor, snapshot));
92
+ if (editor.kind === 'model-compare-handoff-diff') {
93
+ const left = editor.fields.find((field) => field.id === 'leftArtifactId')?.value.trim();
94
+ const right = editor.fields.find((field) => field.id === 'rightArtifactId')?.value.trim();
95
+ lines.push(
96
+ { text: 'Split view: compare left and right reviewer handoff artifacts without changing model routing.', fg: PALETTE.good },
97
+ { text: 'Section jumps: all, metadata, policy, related, comparison.', fg: PALETTE.info },
98
+ left && right
99
+ ? { text: `Current diff: ${left} -> ${right}.`, fg: PALETTE.good }
100
+ : { text: 'No complete handoff pair selected; submitting lists recent saved handoffs.', fg: PALETTE.info },
101
+ );
102
+ if (snapshot?.recentReviewerHandoffArtifacts.length) {
103
+ const choices = snapshot.recentReviewerHandoffArtifacts
104
+ .slice(0, 4)
105
+ .map((artifact) => `${artifact.id} (${artifact.sourceKind}; related ${artifact.relatedArtifactCount})`)
106
+ .join(', ');
107
+ lines.push({ text: `Recent choices: ${choices}.`, fg: PALETTE.muted });
108
+ }
109
+ } else if (editor.kind === 'document-reviewer-readiness') {
110
+ lines.push(
111
+ { text: 'Preflight checks: comments, suggestions, source artifacts, comparison reveal, route decisions, handoff evidence.', fg: PALETTE.info },
112
+ { text: 'Use before export, handoff archive, or applying a comparison winner.', fg: PALETTE.good },
113
+ );
114
+ }
504
115
  return lines;
505
116
  }
506
117
 
@@ -518,7 +129,7 @@ function buildContextRows(workspace: AgentWorkspace, category: AgentWorkspaceCat
518
129
  },
519
130
  { text: 'Enter opens; Esc clears.', fg: PALETTE.muted },
520
131
  ] satisfies ContextLine[] : []),
521
- ...(workspace.localEditor ? editorContextLines(workspace.localEditor) : []),
132
+ ...(workspace.localEditor ? editorContextLines(workspace.localEditor, workspace.runtimeSnapshot) : []),
522
133
  ];
523
134
 
524
135
  const selectedActionLines: ContextLine[] = action
@@ -85,6 +85,18 @@ export const CATEGORY_LABELS: Record<(typeof SETTINGS_CATEGORIES)[number], strin
85
85
  helper: 'Helper',
86
86
  tts: 'TTS',
87
87
  automation: 'Automation',
88
+ service: 'Service',
89
+ controlPlane: 'Control Plane',
90
+ httpListener: 'HTTP Listener',
91
+ web: 'Web',
92
+ watchers: 'Watchers',
93
+ network: 'Network',
94
+ orchestration: 'Orchestration',
95
+ runtime: 'Runtime',
96
+ sandbox: 'Sandbox',
97
+ batch: 'Batch',
98
+ cloudflare: 'Cloudflare',
99
+ wrfc: 'WRFC',
88
100
  telemetry: 'Telemetry',
89
101
  cache: 'Cache',
90
102
  mcp: 'MCP',
@@ -34,6 +34,18 @@ const CATEGORY_INFO: Record<SettingsCategory, string> = {
34
34
  helper: 'Helper model defaults used by helper subsystems when they do not use the main chat route.',
35
35
  tts: 'Text-to-speech provider, voice, and optional spoken-turn LLM overrides.',
36
36
  automation: 'Scheduled and automated run settings, concurrency, timeout, catch-up, cooldown, and retention behavior.',
37
+ service: 'GoodVibes daemon service posture and restart/autostart preferences.',
38
+ controlPlane: 'Control-plane endpoint, stream, remote access, and TLS settings used by daemon-backed operator routes.',
39
+ httpListener: 'HTTP listener binding, trust proxy, and TLS settings for inbound companion/channel routes.',
40
+ web: 'Web companion surface settings including host, port, public URL, and static asset path.',
41
+ watchers: 'Polling watcher and heartbeat behavior for runtime recovery and periodic checks.',
42
+ network: 'Outbound TLS and remote fetch network policy.',
43
+ orchestration: 'Visible agent orchestration limits such as recursion and active-agent caps.',
44
+ runtime: 'Runtime service limits and event bus settings.',
45
+ sandbox: 'Isolation settings for REPL, MCP, and VM-backed sessions.',
46
+ batch: 'Batch queue backend, limits, and provider batching behavior.',
47
+ cloudflare: 'Cloudflare worker, tunnel, queue, storage, and token-reference settings.',
48
+ wrfc: 'WRFC review/fix chain scoring, fix attempts, and commit preferences.',
37
49
  telemetry: 'Telemetry payload policy.',
38
50
  cache: 'Provider and model cache behavior, TTL, and hit-rate monitoring.',
39
51
  mcp: 'MCP server trust and scope review. Trust changes can expose local files, tools, databases, browsers, or remote automation depending on the server.',
@@ -10,6 +10,7 @@ import type { OpsApi } from '@/runtime/index.ts';
10
10
  import type { MutableRuntimeState } from '@/runtime/index.ts';
11
11
  import type { ProviderRegistry } from '@pellux/goodvibes-sdk/platform/providers';
12
12
  import type { CommandContext } from '../input/command-registry.ts';
13
+ import type { AgentPromptContextReceiptStore } from '../agent/prompt-context-receipts.ts';
13
14
  import type { KeybindingsManager } from '../input/keybindings.ts';
14
15
  import type { PermissionRequestHandler } from '@pellux/goodvibes-sdk/platform/permissions';
15
16
  import type { ToolRegistry } from '@pellux/goodvibes-sdk/platform/tools';
@@ -41,6 +42,7 @@ import type { VoiceProviderRegistry, VoiceService } from '@pellux/goodvibes-sdk/
41
42
  import type { MediaProviderRegistry } from '@pellux/goodvibes-sdk/platform/media';
42
43
  import type { ArtifactStore } from '@pellux/goodvibes-sdk/platform/artifacts';
43
44
  import type { ChannelDeliveryRouter } from '@pellux/goodvibes-sdk/platform/channels';
45
+ import type { AgentExecutionLedger } from './execution-ledger.ts';
44
46
  import {
45
47
  createBootstrapCommandActions,
46
48
  createBootstrapCommandClientsSection,
@@ -74,6 +76,8 @@ export type CreateBootstrapCommandContextOptions = {
74
76
  remoteRuntime?: RemoteCommandService;
75
77
  planRuntime?: PlanRuntimeService;
76
78
  fileUndoManager: FileUndoManager;
79
+ processManager?: import('@pellux/goodvibes-sdk/platform/tools').ProcessManager;
80
+ executionLedger?: AgentExecutionLedger;
77
81
  memoryRegistry?: MemoryRegistry;
78
82
  integrationHelpers?: IntegrationHelperService;
79
83
  automationManager?: ShellAutomationManagerRuntimeService;
@@ -107,6 +111,7 @@ export type CreateBootstrapCommandContextOptions = {
107
111
  operatorClient?: OperatorClient;
108
112
  peerClient?: PeerClient;
109
113
  agentKnowledgeApi?: KnowledgeApi;
114
+ promptContextReceipts?: AgentPromptContextReceiptStore;
110
115
  hookApi?: HookApi;
111
116
  mcpApi?: McpApi;
112
117
  opsApi?: OpsApi;
@@ -146,6 +151,8 @@ export function createBootstrapCommandContext(
146
151
  remoteRuntime,
147
152
  planRuntime,
148
153
  fileUndoManager,
154
+ processManager,
155
+ executionLedger,
149
156
  memoryRegistry,
150
157
  integrationHelpers,
151
158
  automationManager,
@@ -180,6 +187,7 @@ export function createBootstrapCommandContext(
180
187
  operatorClient,
181
188
  peerClient,
182
189
  agentKnowledgeApi,
190
+ promptContextReceipts,
183
191
  hookApi,
184
192
  mcpApi,
185
193
  opsApi,
@@ -240,6 +248,7 @@ export function createBootstrapCommandContext(
240
248
  keybindingsManager,
241
249
  fileUndoManager,
242
250
  panelManager,
251
+ processManager,
243
252
  profileManager,
244
253
  bookmarkManager,
245
254
  projectPlanningService,
@@ -255,6 +264,7 @@ export function createBootstrapCommandContext(
255
264
  operatorClient,
256
265
  peerClient,
257
266
  agentKnowledgeApi,
267
+ promptContextReceipts,
258
268
  providerApi,
259
269
  hookApi,
260
270
  mcpApi,
@@ -279,7 +289,7 @@ export function createBootstrapCommandContext(
279
289
  provider,
280
290
  workspace,
281
291
  platform,
282
- ops: createBootstrapCommandOpsSection(shellServices),
292
+ ops: createBootstrapCommandOpsSection(shellServices, { executionLedger }),
283
293
  extensions,
284
294
  clients,
285
295
  ...actions,