@pellux/goodvibes-agent 0.1.117 → 1.0.1

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 +20 -4
  2. package/README.md +35 -14
  3. package/bin/goodvibes-agent.ts +16 -2
  4. package/dist/package/main.js +176093 -171065
  5. package/docs/README.md +11 -5
  6. package/docs/channels-remote-and-api.md +50 -0
  7. package/docs/connected-host.md +3 -3
  8. package/docs/getting-started.md +29 -15
  9. package/docs/knowledge-artifacts-and-multimodal.md +91 -0
  10. package/docs/project-planning.md +79 -0
  11. package/docs/providers-and-routing.md +46 -0
  12. package/docs/release-and-publishing.md +44 -9
  13. package/docs/tools-and-commands.md +123 -0
  14. package/docs/voice-and-live-tts.md +51 -0
  15. package/package.json +2 -5
  16. package/src/agent/channel-delivery.ts +201 -0
  17. package/src/agent/media-generation.ts +159 -0
  18. package/src/agent/memory-prompt.ts +0 -1
  19. package/src/agent/note-registry.ts +329 -0
  20. package/src/agent/operator-actions.ts +343 -0
  21. package/src/agent/persona-registry.ts +15 -14
  22. package/src/agent/record-labels.ts +107 -0
  23. package/src/agent/reminder-schedule-format.ts +33 -24
  24. package/src/agent/reminder-schedule.ts +26 -25
  25. package/src/agent/routine-registry.ts +13 -12
  26. package/src/agent/routine-schedule-args.ts +2 -1
  27. package/src/agent/routine-schedule-format.ts +77 -53
  28. package/src/agent/routine-schedule-promotion.ts +34 -32
  29. package/src/agent/routine-schedule-receipts.ts +28 -26
  30. package/src/agent/runtime-profile-starters.ts +2 -2
  31. package/src/agent/runtime-profile.ts +18 -17
  32. package/src/agent/skill-registry.ts +25 -24
  33. package/src/cli/agent-knowledge-args.ts +5 -1
  34. package/src/cli/agent-knowledge-command.ts +39 -33
  35. package/src/cli/agent-knowledge-format.ts +80 -67
  36. package/src/cli/agent-knowledge-methods.ts +1 -1
  37. package/src/cli/agent-knowledge-runtime.ts +32 -26
  38. package/src/cli/bundle-command.ts +13 -8
  39. package/src/cli/config-overrides.ts +37 -36
  40. package/src/cli/external-runtime.ts +10 -4
  41. package/src/cli/help.ts +29 -11
  42. package/src/cli/local-library-command.ts +159 -73
  43. package/src/cli/management-commands.ts +98 -62
  44. package/src/cli/management.ts +52 -26
  45. package/src/cli/memory-command.ts +66 -32
  46. package/src/cli/parser.ts +37 -24
  47. package/src/cli/profiles-command.ts +52 -35
  48. package/src/cli/provider-auth-routes.ts +2 -1
  49. package/src/cli/routines-command.ts +59 -39
  50. package/src/cli/service-posture.ts +6 -6
  51. package/src/cli/status.ts +46 -121
  52. package/src/core/conversation-message-snapshot.ts +131 -0
  53. package/src/input/agent-workspace-activation.ts +33 -7
  54. package/src/input/agent-workspace-basic-command-editor-submission.ts +7 -3
  55. package/src/input/agent-workspace-basic-command-editors.ts +30 -10
  56. package/src/input/agent-workspace-categories.ts +276 -64
  57. package/src/input/agent-workspace-channel-command-editor-submission.ts +34 -0
  58. package/src/input/agent-workspace-channel-command-editors.ts +23 -5
  59. package/src/input/agent-workspace-channels.ts +35 -2
  60. package/src/input/agent-workspace-command-editor.ts +18 -2
  61. package/src/input/agent-workspace-config-reader.ts +16 -0
  62. package/src/input/agent-workspace-delegation-editor-submission.ts +1 -1
  63. package/src/input/agent-workspace-editors.ts +140 -2
  64. package/src/input/agent-workspace-knowledge-query-editor.ts +1 -1
  65. package/src/input/agent-workspace-knowledge-url-editor.ts +4 -11
  66. package/src/input/agent-workspace-learned-behavior.ts +2 -2
  67. package/src/input/agent-workspace-library-command-editor-submission.ts +1 -1
  68. package/src/input/agent-workspace-library-command-editors.ts +2 -2
  69. package/src/input/agent-workspace-local-operations.ts +218 -0
  70. package/src/input/agent-workspace-local-selection.ts +75 -0
  71. package/src/input/agent-workspace-media-command-editor-submission.ts +62 -0
  72. package/src/input/agent-workspace-media-command-editors.ts +27 -0
  73. package/src/input/agent-workspace-memory-command-editors.ts +1 -1
  74. package/src/input/agent-workspace-memory-editor.ts +2 -2
  75. package/src/input/agent-workspace-navigation.ts +38 -2
  76. package/src/input/agent-workspace-notify-editor-submission.ts +16 -2
  77. package/src/input/agent-workspace-operations-command-editor-submission.ts +63 -1
  78. package/src/input/agent-workspace-operations-command-editors.ts +80 -3
  79. package/src/input/agent-workspace-panel-route.ts +43 -0
  80. package/src/input/agent-workspace-reminder-schedule-editor.ts +1 -1
  81. package/src/input/agent-workspace-routine-schedule-editor.ts +2 -2
  82. package/src/input/agent-workspace-search.ts +169 -0
  83. package/src/input/agent-workspace-setup.ts +22 -11
  84. package/src/input/agent-workspace-skill-bundle-command-editor-submission.ts +6 -6
  85. package/src/input/agent-workspace-skill-bundle-command-editors.ts +10 -10
  86. package/src/input/agent-workspace-snapshot.ts +112 -13
  87. package/src/input/agent-workspace-task-command-editors.ts +4 -4
  88. package/src/input/agent-workspace-token.ts +18 -2
  89. package/src/input/agent-workspace-types.ts +92 -4
  90. package/src/input/agent-workspace-voice-media.ts +3 -6
  91. package/src/input/agent-workspace-web-research-editor.ts +104 -0
  92. package/src/input/agent-workspace.ts +136 -208
  93. package/src/input/command-registry.ts +4 -1
  94. package/src/input/commands/agent-local-library-args.ts +52 -0
  95. package/src/input/commands/agent-runtime-profile-runtime.ts +45 -41
  96. package/src/input/commands/agent-skills-runtime.ts +87 -99
  97. package/src/input/commands/agent-workspace-runtime.ts +23 -7
  98. package/src/input/commands/brief-runtime.ts +25 -24
  99. package/src/input/commands/channels-runtime.ts +145 -31
  100. package/src/input/commands/delegation-runtime.ts +29 -23
  101. package/src/input/commands/experience-runtime.ts +6 -4
  102. package/src/input/commands/guidance-runtime.ts +4 -4
  103. package/src/input/commands/health-runtime.ts +140 -115
  104. package/src/input/commands/knowledge.ts +57 -56
  105. package/src/input/commands/local-provider-runtime.ts +36 -18
  106. package/src/input/commands/local-runtime.ts +138 -16
  107. package/src/input/commands/local-setup-review.ts +7 -7
  108. package/src/input/commands/mcp-runtime.ts +118 -50
  109. package/src/input/commands/notify-runtime.ts +38 -9
  110. package/src/input/commands/operator-actions-runtime.ts +138 -0
  111. package/src/input/commands/operator-runtime.ts +6 -17
  112. package/src/input/commands/personas-runtime.ts +49 -59
  113. package/src/input/commands/planning-runtime.ts +1 -1
  114. package/src/input/commands/platform-access-runtime.ts +29 -29
  115. package/src/input/commands/provider-accounts-runtime.ts +60 -39
  116. package/src/input/commands/qrcode-runtime.ts +45 -6
  117. package/src/input/commands/recall-bundle.ts +11 -11
  118. package/src/input/commands/recall-capture.ts +13 -11
  119. package/src/input/commands/recall-query.ts +29 -21
  120. package/src/input/commands/recall-review.ts +2 -1
  121. package/src/input/commands/routines-runtime.ts +63 -72
  122. package/src/input/commands/schedule-runtime.ts +33 -20
  123. package/src/input/commands/security-runtime.ts +4 -4
  124. package/src/input/commands/session-content.ts +80 -78
  125. package/src/input/commands/session-workflow.ts +132 -93
  126. package/src/input/commands/session.ts +3 -174
  127. package/src/input/commands/shell-core.ts +32 -17
  128. package/src/input/commands/subscription-runtime.ts +53 -179
  129. package/src/input/commands/tasks-runtime.ts +20 -20
  130. package/src/input/commands/work-plan-runtime.ts +33 -8
  131. package/src/input/commands.ts +2 -2
  132. package/src/input/feed-context-factory.ts +2 -1
  133. package/src/input/file-picker.ts +3 -2
  134. package/src/input/handler-command-route.ts +4 -7
  135. package/src/input/handler-content-actions.ts +89 -1
  136. package/src/input/handler-feed-routes.ts +19 -12
  137. package/src/input/handler-feed.ts +6 -3
  138. package/src/input/handler-interactions.ts +7 -5
  139. package/src/input/handler-modal-stack.ts +3 -3
  140. package/src/input/handler-onboarding.ts +24 -80
  141. package/src/input/handler-shortcuts.ts +15 -4
  142. package/src/input/handler.ts +47 -17
  143. package/src/input/input-history.ts +5 -6
  144. package/src/input/keybindings.ts +22 -11
  145. package/src/input/onboarding/onboarding-wizard-apply.ts +13 -0
  146. package/src/input/onboarding/onboarding-wizard-constants.ts +1 -0
  147. package/src/input/onboarding/onboarding-wizard-operator-steps.ts +147 -57
  148. package/src/input/onboarding/onboarding-wizard-steps.ts +46 -29
  149. package/src/input/onboarding/onboarding-wizard-types.ts +3 -1
  150. package/src/input/onboarding/onboarding-wizard.ts +68 -0
  151. package/src/input/profile-picker-modal.ts +31 -12
  152. package/src/input/session-picker-modal.ts +22 -4
  153. package/src/input/settings-modal-behavior.ts +0 -3
  154. package/src/input/settings-modal-subscriptions.ts +3 -3
  155. package/src/input/settings-modal-types.ts +2 -13
  156. package/src/input/settings-modal.ts +6 -52
  157. package/src/input/submission-intent.ts +0 -1
  158. package/src/input/submission-router.ts +3 -3
  159. package/src/main.ts +18 -8
  160. package/src/panels/approval-panel.ts +8 -8
  161. package/src/panels/automation-control-panel.ts +2 -2
  162. package/src/panels/base-panel.ts +1 -1
  163. package/src/panels/builtin/agent.ts +1 -1
  164. package/src/panels/builtin/operations.ts +1 -10
  165. package/src/panels/builtin/session.ts +9 -9
  166. package/src/panels/builtin/shared.ts +2 -2
  167. package/src/panels/cost-tracker-panel.ts +1 -1
  168. package/src/panels/docs-panel.ts +5 -3
  169. package/src/panels/index.ts +0 -1
  170. package/src/panels/knowledge-panel.ts +6 -5
  171. package/src/panels/memory-panel.ts +7 -6
  172. package/src/panels/panel-list-panel.ts +36 -80
  173. package/src/panels/project-planning-panel.ts +18 -11
  174. package/src/panels/provider-account-snapshot.ts +51 -25
  175. package/src/panels/provider-accounts-panel.ts +33 -18
  176. package/src/panels/provider-health-domains.ts +45 -4
  177. package/src/panels/provider-health-panel.ts +5 -4
  178. package/src/panels/qr-panel.ts +1 -1
  179. package/src/panels/schedule-panel.ts +9 -17
  180. package/src/panels/security-panel.ts +8 -8
  181. package/src/panels/session-browser-panel.ts +10 -10
  182. package/src/panels/subscription-panel.ts +3 -3
  183. package/src/panels/system-messages-panel.ts +1 -1
  184. package/src/panels/tasks-panel.ts +20 -13
  185. package/src/panels/tool-inspector-panel.ts +19 -12
  186. package/src/panels/work-plan-panel.ts +5 -5
  187. package/src/planning/project-planning-coordinator.ts +1 -1
  188. package/src/provider-auth-route-display.ts +9 -0
  189. package/src/renderer/agent-workspace-style.ts +34 -0
  190. package/src/renderer/agent-workspace.ts +228 -52
  191. package/src/renderer/autocomplete-overlay.ts +25 -6
  192. package/src/renderer/bookmark-modal.ts +19 -4
  193. package/src/renderer/buffer.ts +4 -2
  194. package/src/renderer/context-inspector.ts +50 -13
  195. package/src/renderer/diff.ts +1 -1
  196. package/src/renderer/file-picker-overlay.ts +19 -6
  197. package/src/renderer/help-overlay.ts +106 -33
  198. package/src/renderer/history-search-overlay.ts +19 -4
  199. package/src/renderer/live-tail-modal.ts +27 -5
  200. package/src/renderer/mcp-workspace.ts +164 -50
  201. package/src/renderer/model-picker-overlay.ts +58 -2
  202. package/src/renderer/model-workspace.ts +104 -20
  203. package/src/renderer/process-modal.ts +27 -6
  204. package/src/renderer/profile-picker-modal.ts +20 -4
  205. package/src/renderer/search-overlay.ts +25 -5
  206. package/src/renderer/selection-modal-overlay.ts +46 -14
  207. package/src/renderer/session-picker-modal.ts +18 -1
  208. package/src/renderer/settings-modal-helpers.ts +2 -40
  209. package/src/renderer/settings-modal.ts +83 -50
  210. package/src/renderer/tool-call.ts +20 -11
  211. package/src/runtime/agent-runtime-events.ts +6 -6
  212. package/src/runtime/bootstrap-command-context.ts +7 -1
  213. package/src/runtime/bootstrap-command-parts.ts +9 -7
  214. package/src/runtime/bootstrap-core.ts +19 -1
  215. package/src/runtime/bootstrap-hook-bridge.ts +7 -18
  216. package/src/runtime/bootstrap-shell.ts +4 -4
  217. package/src/runtime/bootstrap.ts +31 -22
  218. package/src/runtime/connected-host-auth.ts +7 -2
  219. package/src/runtime/diagnostics/panels/index.ts +2 -2
  220. package/src/runtime/diagnostics/panels/policy.ts +7 -7
  221. package/src/runtime/index.ts +2 -1
  222. package/src/runtime/onboarding/apply-file-helpers.ts +66 -0
  223. package/src/runtime/onboarding/apply.ts +80 -79
  224. package/src/runtime/onboarding/derivation.ts +5 -8
  225. package/src/runtime/onboarding/snapshot.ts +0 -15
  226. package/src/runtime/onboarding/types.ts +8 -19
  227. package/src/runtime/onboarding/verify.ts +32 -10
  228. package/src/runtime/operator-token-cleanup.ts +1 -1
  229. package/src/runtime/services.ts +91 -22
  230. package/src/runtime/store/selectors/index.ts +3 -3
  231. package/src/runtime/store/state.ts +1 -4
  232. package/src/runtime/surface-feature-flags.ts +41 -6
  233. package/src/runtime/ui-read-models.ts +3 -4
  234. package/src/runtime/ui-services.ts +6 -6
  235. package/src/shell/blocking-input.ts +2 -1
  236. package/src/shell/ui-openers.ts +3 -13
  237. package/src/tools/agent-analysis-registry-policy.ts +0 -1
  238. package/src/tools/agent-channel-send-tool.ts +133 -0
  239. package/src/tools/agent-context-policy.ts +1 -1
  240. package/src/tools/agent-knowledge-ingest-tool.ts +405 -0
  241. package/src/tools/agent-knowledge-tool.ts +170 -0
  242. package/src/tools/agent-local-registry-tool.ts +269 -69
  243. package/src/tools/agent-media-generate-tool.ts +133 -0
  244. package/src/tools/agent-notify-tool.ts +143 -0
  245. package/src/tools/agent-operator-action-tool.ts +137 -0
  246. package/src/tools/agent-operator-briefing-tool.ts +217 -0
  247. package/src/tools/agent-reminder-schedule-tool.ts +237 -0
  248. package/src/tools/agent-tool-policy-guard.ts +8 -8
  249. package/src/tools/agent-work-plan-tool.ts +256 -0
  250. package/src/version.ts +1 -1
  251. package/src/input/commands/policy-dispatch.ts +0 -339
  252. package/src/input/commands/policy.ts +0 -13
  253. package/src/panels/panel-picker.ts +0 -105
  254. package/src/panels/policy-panel.ts +0 -308
  255. package/src/renderer/panel-picker-overlay.ts +0 -202
@@ -1,6 +1,7 @@
1
1
  import { createShellPathService } from '@/runtime/index.ts';
2
2
  import { discoverPersonas, type DiscoveredPersonaRecord } from '../agent/persona-discovery.ts';
3
3
  import { AgentPersonaRegistry, type AgentPersonaRecord } from '../agent/persona-registry.ts';
4
+ import { formatAgentRecordOrigin, formatAgentRecordReviewState } from '../agent/record-labels.ts';
4
5
  import { discoverSkills, type SkillRecord } from '../agent/skill-discovery.ts';
5
6
  import {
6
7
  AgentSkillRegistry,
@@ -32,6 +33,20 @@ interface ParsedOptions {
32
33
  readonly positionals: readonly string[];
33
34
  }
34
35
 
36
+ const LOCAL_LIBRARY_VALUE_OPTIONS = [
37
+ 'name',
38
+ 'description',
39
+ 'body',
40
+ 'procedure',
41
+ 'tags',
42
+ 'triggers',
43
+ 'requires-env',
44
+ 'requires-command',
45
+ 'requires-commands',
46
+ 'skills',
47
+ 'provenance',
48
+ ] as const;
49
+
35
50
  function jsonOrText(runtime: CliCommandRuntime, value: unknown, text: string): string {
36
51
  return runtime.cli.flags.outputFormat === 'json' ? JSON.stringify(value, null, 2) : text;
37
52
  }
@@ -49,24 +64,30 @@ function failure(runtime: CliCommandRuntime, kind: string, error: string, exitCo
49
64
  };
50
65
  }
51
66
 
52
- function parseOptions(args: readonly string[]): ParsedOptions {
67
+ function parseOptions(args: readonly string[], valueOptions: readonly string[] = LOCAL_LIBRARY_VALUE_OPTIONS): ParsedOptions {
68
+ const valued = new Set(valueOptions);
53
69
  const values = new Map<string, string>();
54
70
  const flags = new Set<string>();
55
71
  const positionals: string[] = [];
56
72
  for (let index = 0; index < args.length; index += 1) {
57
73
  const arg = args[index] ?? '';
74
+ if (arg === '--') {
75
+ positionals.push(...args.slice(index + 1));
76
+ break;
77
+ }
58
78
  if (!arg.startsWith('--')) {
59
79
  positionals.push(arg);
60
80
  continue;
61
81
  }
62
- const equalIndex = arg.indexOf('=');
82
+ const raw = arg.slice(2);
83
+ const equalIndex = raw.indexOf('=');
63
84
  if (equalIndex >= 0) {
64
- values.set(arg.slice(2, equalIndex), arg.slice(equalIndex + 1));
85
+ values.set(raw.slice(0, equalIndex), raw.slice(equalIndex + 1));
65
86
  continue;
66
87
  }
67
- const name = arg.slice(2);
88
+ const name = raw;
68
89
  const next = args[index + 1];
69
- if (next !== undefined && !next.startsWith('--')) {
90
+ if (next !== undefined && (valued.has(name) || !next.startsWith('--'))) {
70
91
  values.set(name, next);
71
92
  index += 1;
72
93
  continue;
@@ -122,8 +143,8 @@ function shellPaths(runtime: CliCommandRuntime): ReturnType<typeof createShellPa
122
143
 
123
144
  function summarizePersona(persona: AgentPersonaRecord, activePersonaId: string | null): string {
124
145
  const active = persona.id === activePersonaId ? 'active' : 'available';
125
- const tags = persona.tags.length > 0 ? ` tags=${persona.tags.join(',')}` : '';
126
- return ` ${persona.id} ${active} ${persona.reviewState} ${persona.name} - ${persona.description}${tags}`;
146
+ const tags = persona.tags.length > 0 ? ` tags ${persona.tags.join(', ')}` : '';
147
+ return ` ${persona.id} ${active} ${formatAgentRecordReviewState(persona.reviewState)} ${persona.name} - ${persona.description}${tags}`;
127
148
  }
128
149
 
129
150
  function renderPersonaList(title: string, path: string, personas: readonly AgentPersonaRecord[], activePersonaId: string | null): string {
@@ -131,12 +152,13 @@ function renderPersonaList(title: string, path: string, personas: readonly Agent
131
152
  return [
132
153
  title,
133
154
  ' No local Agent personas yet.',
155
+ ' No Agent-local personas yet.',
134
156
  ' Create one with: goodvibes-agent personas create --name <name> --description <summary> --body <instructions>',
135
157
  ].join('\n');
136
158
  }
137
159
  return [
138
160
  `${title} (${personas.length})`,
139
- ` store: ${path}`,
161
+ ` store ${path}`,
140
162
  ...personas.map((persona) => summarizePersona(persona, activePersonaId)),
141
163
  ].join('\n');
142
164
  }
@@ -144,11 +166,10 @@ function renderPersonaList(title: string, path: string, personas: readonly Agent
144
166
  function renderPersona(persona: AgentPersonaRecord, activePersonaId: string | null): string {
145
167
  return [
146
168
  `Persona ${persona.name}`,
147
- ` id: ${persona.id}`,
169
+ ` id ${persona.id}`,
148
170
  ` active: ${persona.id === activePersonaId ? 'yes' : 'no'}`,
149
- ` review: ${persona.reviewState}`,
150
- ` source: ${persona.source}`,
151
- ` provenance: ${persona.provenance}`,
171
+ ` review: ${formatAgentRecordReviewState(persona.reviewState)}`,
172
+ ` origin: ${formatAgentRecordOrigin(persona.source, persona.provenance)}`,
152
173
  ` tags: ${persona.tags.join(', ') || '(none)'}`,
153
174
  ` triggers: ${persona.triggers.join(', ') || '(manual)'}`,
154
175
  ` created: ${persona.createdAt}`,
@@ -165,7 +186,7 @@ function summarizeDiscoveredPersona(persona: DiscoveredPersonaRecord): string {
165
186
  const description = persona.description ? ` - ${persona.description}` : '';
166
187
  return [
167
188
  ` ${persona.name} ${persona.origin}${description}`,
168
- ` path: ${persona.path}`,
189
+ ` path ${persona.path}`,
169
190
  ].join('\n');
170
191
  }
171
192
 
@@ -207,10 +228,10 @@ function discoveredPersonaFrontmatterList(persona: DiscoveredPersonaRecord, key:
207
228
 
208
229
  function summarizeSkill(skill: AgentSkillRecord): string {
209
230
  const enabled = skill.enabled ? 'enabled' : 'disabled';
210
- const tags = skill.tags.length > 0 ? ` tags=${skill.tags.join(',')}` : '';
231
+ const tags = skill.tags.length > 0 ? ` tags ${skill.tags.join(', ')}` : '';
211
232
  const readiness = evaluateAgentSkillReadiness(skill);
212
233
  const ready = readiness.ready ? 'ready' : `needs ${readiness.missing.map(formatAgentSkillRequirement).join(',')}`;
213
- return ` ${skill.id} ${enabled} ${skill.reviewState} ${ready} ${skill.name} - ${skill.description}${tags}`;
234
+ return ` ${skill.id} ${enabled} ${formatAgentRecordReviewState(skill.reviewState)} ${ready} ${skill.name} - ${skill.description}${tags}`;
214
235
  }
215
236
 
216
237
  function summarizeBundle(bundle: AgentSkillBundleRecord, skills: readonly AgentSkillRecord[]): string {
@@ -221,31 +242,32 @@ function summarizeBundle(bundle: AgentSkillBundleRecord, skills: readonly AgentS
221
242
  ...readiness.missingSkillIds.map((skillId) => `skill:${skillId}`),
222
243
  ];
223
244
  const ready = readiness.ready ? 'ready' : `needs ${missing.join(',')}`;
224
- return ` ${bundle.id} ${enabled} ${bundle.reviewState} ${ready} ${bundle.name} - ${bundle.description} skills=${bundle.skillIds.join(',')}`;
245
+ return ` ${bundle.id} ${enabled} ${formatAgentRecordReviewState(bundle.reviewState)} ${ready} ${bundle.name} - ${bundle.description} skills ${bundle.skillIds.join(',')}`;
225
246
  }
226
247
 
227
248
  function renderSkillList(title: string, path: string, skills: readonly AgentSkillRecord[], emptyMessage?: string): string {
228
249
  if (skills.length === 0) {
229
250
  return [
230
251
  title,
231
- ` ${emptyMessage ?? 'No local Agent skills yet.'}`,
252
+ emptyMessage ? '' : ' No local Agent skills yet.',
253
+ ` ${emptyMessage ?? 'No Agent-local skills yet.'}`,
232
254
  emptyMessage ? '' : ' Create one with: goodvibes-agent skills create --name <name> --description <summary> --procedure <steps>',
233
255
  ].filter(Boolean).join('\n');
234
256
  }
235
257
  return [
236
258
  `${title} (${skills.length})`,
237
- ` store: ${path}`,
259
+ ` store ${path}`,
238
260
  ...skills.map(summarizeSkill),
239
261
  ].join('\n');
240
262
  }
241
263
 
242
264
  function summarizeDiscoveredSkill(skill: SkillRecord): string {
243
265
  const description = skill.description ? ` - ${skill.description}` : '';
244
- const dependencies = skill.dependencies.length > 0 ? ` deps=${skill.dependencies.join(',')}` : '';
245
- const includes = skill.includes.length > 0 ? ` includes=${skill.includes.join(',')}` : '';
266
+ const dependencies = skill.dependencies.length > 0 ? ` dependencies ${skill.dependencies.join(', ')}` : '';
267
+ const includes = skill.includes.length > 0 ? ` includes ${skill.includes.join(', ')}` : '';
246
268
  return [
247
269
  ` ${skill.name} ${skill.origin}${description}${dependencies}${includes}`,
248
- ` path: ${skill.path}`,
270
+ ` path ${skill.path}`,
249
271
  ].join('\n');
250
272
  }
251
273
 
@@ -297,13 +319,13 @@ function renderBundleList(title: string, path: string, bundles: readonly AgentSk
297
319
  if (bundles.length === 0) {
298
320
  return [
299
321
  title,
300
- ` ${emptyMessage ?? 'No local Agent skill bundles yet.'}`,
322
+ ` ${emptyMessage ?? 'No Agent-local skill bundles yet.'}`,
301
323
  emptyMessage ? '' : ' Create one with: goodvibes-agent skills bundle create --name <name> --description <summary> --skills <id,id>',
302
324
  ].filter(Boolean).join('\n');
303
325
  }
304
326
  return [
305
327
  `${title} (${bundles.length})`,
306
- ` store: ${path}`,
328
+ ` store ${path}`,
307
329
  ...bundles.map((bundle) => summarizeBundle(bundle, skills)),
308
330
  ].join('\n');
309
331
  }
@@ -312,14 +334,13 @@ function renderSkill(skill: AgentSkillRecord): string {
312
334
  const readiness = evaluateAgentSkillReadiness(skill);
313
335
  return [
314
336
  `Skill ${skill.name}`,
315
- ` id: ${skill.id}`,
337
+ ` id ${skill.id}`,
316
338
  ` enabled: ${skill.enabled ? 'yes' : 'no'}`,
317
339
  ` readiness: ${readiness.ready ? 'ready' : 'needs setup'}`,
318
340
  ` requirements: ${skill.requirements.map(formatAgentSkillRequirement).join(', ') || '(none)'}`,
319
341
  readiness.missing.length > 0 ? ` missing: ${readiness.missing.map(formatAgentSkillRequirement).join(', ')}` : '',
320
- ` review: ${skill.reviewState}`,
321
- ` source: ${skill.source}`,
322
- ` provenance: ${skill.provenance}`,
342
+ ` review: ${formatAgentRecordReviewState(skill.reviewState)}`,
343
+ ` origin: ${formatAgentRecordOrigin(skill.source, skill.provenance)}`,
323
344
  ` tags: ${skill.tags.join(', ') || '(none)'}`,
324
345
  ` triggers: ${skill.triggers.join(', ') || '(manual)'}`,
325
346
  ` created: ${skill.createdAt}`,
@@ -340,13 +361,12 @@ function renderBundle(bundle: AgentSkillBundleRecord, skills: readonly AgentSkil
340
361
  ];
341
362
  return [
342
363
  `Skill bundle ${bundle.name}`,
343
- ` id: ${bundle.id}`,
364
+ ` id ${bundle.id}`,
344
365
  ` enabled: ${bundle.enabled ? 'yes' : 'no'}`,
345
366
  ` readiness: ${readiness.ready ? 'ready' : 'needs setup'}`,
346
367
  missing.length > 0 ? ` missing: ${missing.join(', ')}` : '',
347
- ` review: ${bundle.reviewState}`,
348
- ` source: ${bundle.source}`,
349
- ` provenance: ${bundle.provenance}`,
368
+ ` review: ${formatAgentRecordReviewState(bundle.reviewState)}`,
369
+ ` origin: ${formatAgentRecordOrigin(bundle.source, bundle.provenance)}`,
350
370
  ` skills: ${bundle.skillIds.join(', ')}`,
351
371
  ` created: ${bundle.createdAt}`,
352
372
  ` updated: ${bundle.updatedAt}`,
@@ -398,17 +418,17 @@ export async function handlePersonasCommand(runtime: CliCommandRuntime): Promise
398
418
  if (!name) return failure(runtime, 'invalid_persona_command', 'Usage: goodvibes-agent personas import-discovered <name> [--use] --yes', 2);
399
419
  const discovered = findDiscoveredPersona(await discoverPersonas(shellPaths(runtime)), name);
400
420
  if (!discovered) {
401
- return failure(runtime, 'persona_discovery_not_found', `Unknown discovered Agent persona: ${name}\nRun goodvibes-agent personas discover to inspect available persona files.`, 1);
421
+ return failure(runtime, 'persona_discovery_not_found', `Unknown discovered Agent persona ${name}\nRun goodvibes-agent personas discover to inspect available persona files.`, 1);
402
422
  }
403
423
  if (!hasFlag(options, 'yes')) {
404
424
  return success(runtime, 'agent.personas.import_discovered.preview', { persona: discovered }, [
405
425
  'Agent persona import preview',
406
- ` name: ${discovered.name}`,
407
- ` origin: ${discovered.origin}`,
408
- ` path: ${discovered.path}`,
409
- ` description: ${discovered.description || '(none)'}`,
410
- ` body characters: ${discovered.body.length}`,
411
- ' next: rerun with --yes to import into the Agent-local persona registry',
426
+ ` name ${discovered.name}`,
427
+ ` origin ${discovered.origin}`,
428
+ ` path ${discovered.path}`,
429
+ ` description ${discovered.description || '(none)'}`,
430
+ ` body characters ${discovered.body.length}`,
431
+ ' next rerun with --yes to import into the Agent-local persona registry',
412
432
  ].join('\n'));
413
433
  }
414
434
  const persona = registry.create({
@@ -421,7 +441,11 @@ export async function handlePersonasCommand(runtime: CliCommandRuntime): Promise
421
441
  provenance: `discovered:${discovered.origin}:${discovered.path}`,
422
442
  });
423
443
  if (hasFlag(options, 'use')) registry.setActive(persona.id);
424
- return success(runtime, 'agent.personas.import_discovered', persona, `Imported Agent persona ${persona.id}: ${persona.name}${hasFlag(options, 'use') ? ' (active)' : ''}`);
444
+ return success(runtime, 'agent.personas.import_discovered', persona, [
445
+ `Imported Agent persona ${persona.id}: ${persona.name}${hasFlag(options, 'use') ? ' (active)' : ''}`,
446
+ ` name ${persona.name}`,
447
+ ` active ${hasFlag(options, 'use') ? 'yes' : 'no'}`,
448
+ ].join('\n'));
425
449
  }
426
450
  if (normalized === 'search' || normalized === 'find') {
427
451
  const query = rest.join(' ').trim();
@@ -432,7 +456,7 @@ export async function handlePersonasCommand(runtime: CliCommandRuntime): Promise
432
456
  const id = rest[0];
433
457
  if (!id) return failure(runtime, 'invalid_persona_command', 'Usage: goodvibes-agent personas show <id>', 2);
434
458
  const persona = registry.get(id);
435
- if (!persona) return failure(runtime, 'persona_not_found', `Unknown Agent persona: ${id}`, 1);
459
+ if (!persona) return failure(runtime, 'persona_not_found', `Unknown Agent persona ${id}`, 1);
436
460
  return success(runtime, 'agent.personas.show', persona, renderPersona(persona, snapshot.activePersonaId));
437
461
  }
438
462
  if (normalized === 'create') {
@@ -443,10 +467,15 @@ export async function handlePersonasCommand(runtime: CliCommandRuntime): Promise
443
467
  body: requiredOption(options, 'body', 'Usage: goodvibes-agent personas create --name <name> --description <summary> --body <instructions>'),
444
468
  tags: csvOption(options, 'tags'),
445
469
  triggers: csvOption(options, 'triggers'),
446
- provenance: optionValue(options, 'provenance') ?? 'cli',
470
+ provenance: optionValue(options, 'provenance') ?? 'Command',
447
471
  });
448
472
  if (hasFlag(options, 'use')) registry.setActive(persona.id);
449
- return success(runtime, 'agent.personas.create', persona, `Agent persona created: ${persona.id}${hasFlag(options, 'use') ? ' (active)' : ''}`);
473
+ return success(runtime, 'agent.personas.create', persona, [
474
+ 'Agent persona created',
475
+ ` id ${persona.id}`,
476
+ hasFlag(options, 'use') ? ' (active)' : '',
477
+ ` active ${hasFlag(options, 'use') ? 'yes' : 'no'}`,
478
+ ].filter(Boolean).join('\n'));
450
479
  }
451
480
  if (normalized === 'update') {
452
481
  const id = rest[0];
@@ -460,13 +489,19 @@ export async function handlePersonasCommand(runtime: CliCommandRuntime): Promise
460
489
  triggers: csvOption(options, 'triggers'),
461
490
  provenance: optionValue(options, 'provenance'),
462
491
  });
463
- return success(runtime, 'agent.personas.update', persona, `Agent persona updated: ${persona.id}`);
492
+ return success(runtime, 'agent.personas.update', persona, [
493
+ 'Agent persona updated',
494
+ ` id ${persona.id}`,
495
+ ].join('\n'));
464
496
  }
465
497
  if (normalized === 'use') {
466
498
  const id = rest[0];
467
499
  if (!id) return failure(runtime, 'invalid_persona_command', 'Usage: goodvibes-agent personas use <id>', 2);
468
500
  const persona = registry.setActive(id);
469
- return success(runtime, 'agent.personas.use', persona, `Active Agent persona: ${persona.id}`);
501
+ return success(runtime, 'agent.personas.use', persona, [
502
+ 'Active Agent persona',
503
+ ` id ${persona.id}`,
504
+ ].join('\n'));
470
505
  }
471
506
  if (normalized === 'clear') {
472
507
  registry.clearActive();
@@ -476,13 +511,19 @@ export async function handlePersonasCommand(runtime: CliCommandRuntime): Promise
476
511
  const id = rest[0];
477
512
  if (!id) return failure(runtime, 'invalid_persona_command', 'Usage: goodvibes-agent personas review <id>', 2);
478
513
  const persona = registry.markReviewed(id);
479
- return success(runtime, 'agent.personas.review', persona, `Agent persona reviewed: ${persona.id}`);
514
+ return success(runtime, 'agent.personas.review', persona, [
515
+ 'Agent persona reviewed',
516
+ ` id ${persona.id}`,
517
+ ].join('\n'));
480
518
  }
481
519
  if (normalized === 'stale') {
482
520
  const id = rest[0];
483
521
  if (!id || rest.length < 2) return failure(runtime, 'invalid_persona_command', 'Usage: goodvibes-agent personas stale <id> <reason>', 2);
484
522
  const persona = registry.markStale(id, rest.slice(1).join(' '));
485
- return success(runtime, 'agent.personas.stale', persona, `Agent persona marked stale: ${persona.id}`);
523
+ return success(runtime, 'agent.personas.stale', persona, [
524
+ 'Agent persona marked stale',
525
+ ` id ${persona.id}`,
526
+ ].join('\n'));
486
527
  }
487
528
  if (normalized === 'delete' || normalized === 'remove' || normalized === 'rm') {
488
529
  const options = parseOptions(rest);
@@ -490,7 +531,10 @@ export async function handlePersonasCommand(runtime: CliCommandRuntime): Promise
490
531
  if (!id) return failure(runtime, 'invalid_persona_command', 'Usage: goodvibes-agent personas delete <id> --yes', 2);
491
532
  if (!hasFlag(options, 'yes')) return failure(runtime, 'confirmation_required', `Refusing to delete Agent persona ${id} without --yes.`, 2);
492
533
  const persona = registry.deletePersona(id);
493
- return success(runtime, 'agent.personas.delete', persona, `Agent persona deleted: ${persona.id}`);
534
+ return success(runtime, 'agent.personas.delete', persona, [
535
+ `Agent persona deleted: ${id}`,
536
+ ` id ${persona.id}`,
537
+ ].join('\n'));
494
538
  }
495
539
  return failure(runtime, 'invalid_persona_command', usagePersonas(), 2);
496
540
  } catch (error) {
@@ -520,7 +564,7 @@ function skillPayloadFromOptions(options: ParsedOptions): {
520
564
  commands: csvOption(options, 'requires-command') ?? csvOption(options, 'requires-commands'),
521
565
  }),
522
566
  enabled: hasFlag(options, 'enabled') ? true : undefined,
523
- provenance: optionValue(options, 'provenance') ?? 'cli',
567
+ provenance: optionValue(options, 'provenance') ?? 'Command',
524
568
  };
525
569
  }
526
570
 
@@ -538,7 +582,7 @@ async function handleSkillBundleCommand(runtime: CliCommandRuntime, args: readon
538
582
  }
539
583
  if (normalized === 'attention' || normalized === 'needs-setup') {
540
584
  const bundles = snapshot.bundles.filter((bundle) => !evaluateAgentSkillBundleReadiness(bundle, snapshot.skills).ready);
541
- return success(runtime, 'agent.skills.bundles.attention', { path: snapshot.path, bundles }, renderBundleList('Agent skill bundles needing setup', snapshot.path, bundles, snapshot.skills, 'No local Agent skill bundles need setup.'));
585
+ return success(runtime, 'agent.skills.bundles.attention', { path: snapshot.path, bundles }, renderBundleList('Agent skill bundles needing setup', snapshot.path, bundles, snapshot.skills, 'No Agent-local skill bundles need setup.'));
542
586
  }
543
587
  if (normalized === 'search' || normalized === 'find') {
544
588
  const query = rest.join(' ').trim();
@@ -549,7 +593,7 @@ async function handleSkillBundleCommand(runtime: CliCommandRuntime, args: readon
549
593
  const id = rest[0];
550
594
  if (!id) return failure(runtime, 'invalid_skill_bundle_command', 'Usage: goodvibes-agent skills bundle show <id>', 2);
551
595
  const bundle = registry.getBundle(id);
552
- if (!bundle) return failure(runtime, 'skill_bundle_not_found', `Unknown Agent skill bundle: ${id}`, 1);
596
+ if (!bundle) return failure(runtime, 'skill_bundle_not_found', `Unknown Agent skill bundle ${id}`, 1);
553
597
  return success(runtime, 'agent.skills.bundles.show', bundle, renderBundle(bundle, snapshot.skills));
554
598
  }
555
599
  if (normalized === 'create') {
@@ -560,9 +604,12 @@ async function handleSkillBundleCommand(runtime: CliCommandRuntime, args: readon
560
604
  description: requiredOption(options, 'description', usage),
561
605
  skillIds: requiredOption(options, 'skills', usage).split(',').map((entry) => entry.trim()).filter(Boolean),
562
606
  enabled: hasFlag(options, 'enabled'),
563
- provenance: optionValue(options, 'provenance') ?? 'cli',
607
+ provenance: optionValue(options, 'provenance') ?? 'Command',
564
608
  });
565
- return success(runtime, 'agent.skills.bundles.create', bundle, `Agent skill bundle created: ${bundle.id}`);
609
+ return success(runtime, 'agent.skills.bundles.create', bundle, [
610
+ 'Agent skill bundle created',
611
+ ` id ${bundle.id}`,
612
+ ].join('\n'));
566
613
  }
567
614
  if (normalized === 'update') {
568
615
  const id = rest[0];
@@ -574,25 +621,37 @@ async function handleSkillBundleCommand(runtime: CliCommandRuntime, args: readon
574
621
  skillIds: csvOption(options, 'skills'),
575
622
  provenance: optionValue(options, 'provenance'),
576
623
  });
577
- return success(runtime, 'agent.skills.bundles.update', bundle, `Agent skill bundle updated: ${bundle.id}`);
624
+ return success(runtime, 'agent.skills.bundles.update', bundle, [
625
+ 'Agent skill bundle updated',
626
+ ` id ${bundle.id}`,
627
+ ].join('\n'));
578
628
  }
579
629
  if (normalized === 'enable' || normalized === 'disable') {
580
630
  const id = rest[0];
581
631
  if (!id) return failure(runtime, 'invalid_skill_bundle_command', `Usage: goodvibes-agent skills bundle ${normalized} <id>`, 2);
582
632
  const bundle = registry.setBundleEnabled(id, normalized === 'enable');
583
- return success(runtime, `agent.skills.bundles.${normalized}`, bundle, `Agent skill bundle ${normalized}d: ${bundle.id}`);
633
+ return success(runtime, `agent.skills.bundles.${normalized}`, bundle, [
634
+ `Agent skill bundle ${normalized === 'enable' ? 'enabled' : 'disabled'}`,
635
+ ` id ${bundle.id}`,
636
+ ].join('\n'));
584
637
  }
585
638
  if (normalized === 'review') {
586
639
  const id = rest[0];
587
640
  if (!id) return failure(runtime, 'invalid_skill_bundle_command', 'Usage: goodvibes-agent skills bundle review <id>', 2);
588
641
  const bundle = registry.markBundleReviewed(id);
589
- return success(runtime, 'agent.skills.bundles.review', bundle, `Agent skill bundle reviewed: ${bundle.id}`);
642
+ return success(runtime, 'agent.skills.bundles.review', bundle, [
643
+ 'Agent skill bundle reviewed',
644
+ ` id ${bundle.id}`,
645
+ ].join('\n'));
590
646
  }
591
647
  if (normalized === 'stale') {
592
648
  const id = rest[0];
593
649
  if (!id || rest.length < 2) return failure(runtime, 'invalid_skill_bundle_command', 'Usage: goodvibes-agent skills bundle stale <id> <reason>', 2);
594
650
  const bundle = registry.markBundleStale(id, rest.slice(1).join(' '));
595
- return success(runtime, 'agent.skills.bundles.stale', bundle, `Agent skill bundle marked stale: ${bundle.id}`);
651
+ return success(runtime, 'agent.skills.bundles.stale', bundle, [
652
+ 'Agent skill bundle marked stale',
653
+ ` id ${bundle.id}`,
654
+ ].join('\n'));
596
655
  }
597
656
  if (normalized === 'delete' || normalized === 'remove' || normalized === 'rm') {
598
657
  const options = parseOptions(rest);
@@ -600,7 +659,10 @@ async function handleSkillBundleCommand(runtime: CliCommandRuntime, args: readon
600
659
  if (!id) return failure(runtime, 'invalid_skill_bundle_command', 'Usage: goodvibes-agent skills bundle delete <id> --yes', 2);
601
660
  if (!hasFlag(options, 'yes')) return failure(runtime, 'confirmation_required', `Refusing to delete Agent skill bundle ${id} without --yes.`, 2);
602
661
  const bundle = registry.deleteBundle(id);
603
- return success(runtime, 'agent.skills.bundles.delete', bundle, `Agent skill bundle deleted: ${bundle.id}`);
662
+ return success(runtime, 'agent.skills.bundles.delete', bundle, [
663
+ 'Agent skill bundle deleted',
664
+ ` id ${bundle.id}`,
665
+ ].join('\n'));
604
666
  }
605
667
  return failure(runtime, 'invalid_skill_bundle_command', usageBundles(), 2);
606
668
  } catch (error) {
@@ -629,7 +691,7 @@ export async function handleSkillsCommand(runtime: CliCommandRuntime): Promise<C
629
691
  }
630
692
  if (normalized === 'attention' || normalized === 'needs-setup') {
631
693
  const skills = snapshot.skills.filter((skill) => !evaluateAgentSkillReadiness(skill).ready);
632
- return success(runtime, 'agent.skills.attention', { path: snapshot.path, skills }, renderSkillList('Agent skills needing setup', snapshot.path, skills, 'No local Agent skills need setup.'));
694
+ return success(runtime, 'agent.skills.attention', { path: snapshot.path, skills }, renderSkillList('Agent skills needing setup', snapshot.path, skills, 'No Agent-local skills need setup.'));
633
695
  }
634
696
  if (normalized === 'discover') {
635
697
  const discovered = await discoverSkills(shellPaths(runtime));
@@ -641,17 +703,17 @@ export async function handleSkillsCommand(runtime: CliCommandRuntime): Promise<C
641
703
  if (!name) return failure(runtime, 'invalid_skill_command', 'Usage: goodvibes-agent skills import-discovered <name> [--enabled] --yes', 2);
642
704
  const discovered = findDiscoveredSkill(await discoverSkills(shellPaths(runtime)), name);
643
705
  if (!discovered) {
644
- return failure(runtime, 'skill_discovery_not_found', `Unknown discovered Agent skill: ${name}\nRun goodvibes-agent skills discover to inspect available skill files.`, 1);
706
+ return failure(runtime, 'skill_discovery_not_found', `Unknown discovered Agent skill ${name}\nRun goodvibes-agent skills discover to inspect available skill files.`, 1);
645
707
  }
646
708
  if (!hasFlag(options, 'yes')) {
647
709
  return success(runtime, 'agent.skills.import_discovered.preview', { skill: discovered }, [
648
710
  'Agent skill import preview',
649
- ` name: ${discovered.name}`,
650
- ` origin: ${discovered.origin}`,
651
- ` path: ${discovered.path}`,
652
- ` description: ${discovered.description || '(none)'}`,
653
- ` procedure characters: ${discovered.body.length}`,
654
- ' next: rerun with --yes to import into the Agent-local skill registry',
711
+ ` name ${discovered.name}`,
712
+ ` origin ${discovered.origin}`,
713
+ ` path ${discovered.path}`,
714
+ ` description ${discovered.description || '(none)'}`,
715
+ ` procedure characters ${discovered.body.length}`,
716
+ ' next rerun with --yes to import into the Agent-local skill registry',
655
717
  ].join('\n'));
656
718
  }
657
719
  const skill = registry.create({
@@ -668,7 +730,11 @@ export async function handleSkillsCommand(runtime: CliCommandRuntime): Promise<C
668
730
  source: 'imported',
669
731
  provenance: `discovered:${discovered.origin}:${discovered.path}`,
670
732
  });
671
- return success(runtime, 'agent.skills.import_discovered', skill, `Imported Agent skill ${skill.id}: ${skill.name}${skill.enabled ? ' (enabled)' : ''}`);
733
+ return success(runtime, 'agent.skills.import_discovered', skill, [
734
+ `Imported Agent skill ${skill.id}: ${skill.name}${skill.enabled ? ' (enabled)' : ''}`,
735
+ ` name ${skill.name}`,
736
+ ` enabled ${skill.enabled ? 'yes' : 'no'}`,
737
+ ].join('\n'));
672
738
  }
673
739
  if (normalized === 'search' || normalized === 'find') {
674
740
  const query = rest.join(' ').trim();
@@ -679,12 +745,17 @@ export async function handleSkillsCommand(runtime: CliCommandRuntime): Promise<C
679
745
  const id = rest[0];
680
746
  if (!id) return failure(runtime, 'invalid_skill_command', 'Usage: goodvibes-agent skills show <id>', 2);
681
747
  const skill = registry.get(id);
682
- if (!skill) return failure(runtime, 'skill_not_found', `Unknown Agent skill: ${id}`, 1);
748
+ if (!skill) return failure(runtime, 'skill_not_found', `Unknown Agent skill ${id}`, 1);
683
749
  return success(runtime, 'agent.skills.show', skill, renderSkill(skill));
684
750
  }
685
751
  if (normalized === 'create') {
686
752
  const skill = registry.create(skillPayloadFromOptions(parseOptions(rest)));
687
- return success(runtime, 'agent.skills.create', skill, `Agent skill created: ${skill.id}${skill.enabled ? ' (enabled)' : ''}`);
753
+ return success(runtime, 'agent.skills.create', skill, [
754
+ 'Agent skill created',
755
+ ` id ${skill.id}`,
756
+ skill.enabled ? ' (enabled)' : '',
757
+ ` enabled ${skill.enabled ? 'yes' : 'no'}`,
758
+ ].filter(Boolean).join('\n'));
688
759
  }
689
760
  if (normalized === 'update') {
690
761
  const id = rest[0];
@@ -704,25 +775,37 @@ export async function handleSkillsCommand(runtime: CliCommandRuntime): Promise<C
704
775
  : undefined,
705
776
  provenance: optionValue(options, 'provenance'),
706
777
  });
707
- return success(runtime, 'agent.skills.update', skill, `Agent skill updated: ${skill.id}`);
778
+ return success(runtime, 'agent.skills.update', skill, [
779
+ 'Agent skill updated',
780
+ ` id ${skill.id}`,
781
+ ].join('\n'));
708
782
  }
709
783
  if (normalized === 'enable' || normalized === 'disable') {
710
784
  const id = rest[0];
711
785
  if (!id) return failure(runtime, 'invalid_skill_command', `Usage: goodvibes-agent skills ${normalized} <id>`, 2);
712
786
  const skill = registry.setEnabled(id, normalized === 'enable');
713
- return success(runtime, `agent.skills.${normalized}`, skill, `Agent skill ${normalized}d: ${skill.id}`);
787
+ return success(runtime, `agent.skills.${normalized}`, skill, [
788
+ `Agent skill ${normalized === 'enable' ? 'enabled' : 'disabled'}`,
789
+ ` id ${skill.id}`,
790
+ ].join('\n'));
714
791
  }
715
792
  if (normalized === 'review') {
716
793
  const id = rest[0];
717
794
  if (!id) return failure(runtime, 'invalid_skill_command', 'Usage: goodvibes-agent skills review <id>', 2);
718
795
  const skill = registry.markReviewed(id);
719
- return success(runtime, 'agent.skills.review', skill, `Agent skill reviewed: ${skill.id}`);
796
+ return success(runtime, 'agent.skills.review', skill, [
797
+ 'Agent skill reviewed',
798
+ ` id ${skill.id}`,
799
+ ].join('\n'));
720
800
  }
721
801
  if (normalized === 'stale') {
722
802
  const id = rest[0];
723
803
  if (!id || rest.length < 2) return failure(runtime, 'invalid_skill_command', 'Usage: goodvibes-agent skills stale <id> <reason>', 2);
724
804
  const skill = registry.markStale(id, rest.slice(1).join(' '));
725
- return success(runtime, 'agent.skills.stale', skill, `Agent skill marked stale: ${skill.id}`);
805
+ return success(runtime, 'agent.skills.stale', skill, [
806
+ 'Agent skill marked stale',
807
+ ` id ${skill.id}`,
808
+ ].join('\n'));
726
809
  }
727
810
  if (normalized === 'delete' || normalized === 'remove' || normalized === 'rm') {
728
811
  const options = parseOptions(rest);
@@ -730,7 +813,10 @@ export async function handleSkillsCommand(runtime: CliCommandRuntime): Promise<C
730
813
  if (!id) return failure(runtime, 'invalid_skill_command', 'Usage: goodvibes-agent skills delete <id> --yes', 2);
731
814
  if (!hasFlag(options, 'yes')) return failure(runtime, 'confirmation_required', `Refusing to delete Agent skill ${id} without --yes.`, 2);
732
815
  const skill = registry.deleteSkill(id);
733
- return success(runtime, 'agent.skills.delete', skill, `Agent skill deleted: ${skill.id}`);
816
+ return success(runtime, 'agent.skills.delete', skill, [
817
+ `Agent skill deleted: ${id}`,
818
+ ` id ${skill.id}`,
819
+ ].join('\n'));
734
820
  }
735
821
  return failure(runtime, 'invalid_skill_command', usageSkills(), 2);
736
822
  } catch (error) {