@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
@@ -31,7 +31,7 @@ export function handleRecallExport(args: string[], context: CommandContext): voi
31
31
  if (scopeIdx !== -1 && commandArgs[scopeIdx + 1]) {
32
32
  const scope = commandArgs[scopeIdx + 1];
33
33
  if (!isValidScope(scope)) {
34
- context.print(`[memory] Unknown scope "${scope}". Valid: ${VALID_SCOPES.join(', ')}`);
34
+ context.print(`[memory] Unknown scope "${scope}". Valid values ${VALID_SCOPES.join(', ')}.`);
35
35
  return;
36
36
  }
37
37
  filter.scope = scope;
@@ -41,7 +41,7 @@ export function handleRecallExport(args: string[], context: CommandContext): voi
41
41
  if (clsIdx !== -1 && commandArgs[clsIdx + 1]) {
42
42
  const cls = commandArgs[clsIdx + 1];
43
43
  if (!isValidClass(cls)) {
44
- context.print(`[memory] Unknown class "${cls}". Valid: ${VALID_CLASSES.join(', ')}`);
44
+ context.print(`[memory] Unknown class "${cls}". Valid values ${VALID_CLASSES.join(', ')}.`);
45
45
  return;
46
46
  }
47
47
  filter.cls = cls;
@@ -77,23 +77,23 @@ export async function handleRecallImport(args: string[], context: CommandContext
77
77
  try {
78
78
  bundle = JSON.parse(readFileSync(targetPath, 'utf-8')) as MemoryBundle;
79
79
  } catch (error) {
80
- context.print(`[memory] Failed to read memory bundle: ${summarizeError(error)}`);
80
+ context.print(`[memory] Failed to read memory bundle ${summarizeError(error)}`);
81
81
  return;
82
82
  }
83
83
 
84
84
  const result = await memory.importBundle(bundle);
85
85
  context.print(`[memory] Imported bundle from ${targetPath}`);
86
- context.print(` Records: imported=${result.importedRecords} skipped=${result.skippedRecords}`);
87
- context.print(` Links: imported=${result.importedLinks}`);
86
+ context.print(` records imported=${result.importedRecords} skipped=${result.skippedRecords}`);
87
+ context.print(` links imported=${result.importedLinks}`);
88
88
  }
89
89
 
90
90
  function inspectBundle(bundle: MemoryBundle): string {
91
91
  return [
92
92
  'Memory Handoff Review',
93
- ` scope: ${bundle.scope}`,
94
- ` records: ${bundle.recordCount}`,
95
- ` links: ${bundle.linkCount}`,
96
- ` exportedAt: ${new Date(bundle.exportedAt).toISOString()}`,
93
+ ` scope ${bundle.scope}`,
94
+ ` records ${bundle.recordCount}`,
95
+ ` links ${bundle.linkCount}`,
96
+ ` exportedAt ${new Date(bundle.exportedAt).toISOString()}`,
97
97
  ].join('\n');
98
98
  }
99
99
 
@@ -116,7 +116,7 @@ export function handleRecallHandoffExport(args: string[], context: CommandContex
116
116
  const scopeIdx = commandArgs.indexOf('--scope');
117
117
  const scopeRaw = scopeIdx !== -1 ? commandArgs[scopeIdx + 1] : 'team';
118
118
  if (!scopeRaw || !isValidScope(scopeRaw)) {
119
- context.print(`[memory] Unknown scope "${scopeRaw ?? ''}". Valid: ${VALID_SCOPES.join(', ')}`);
119
+ context.print(`[memory] Unknown scope "${scopeRaw ?? ''}". Valid values ${VALID_SCOPES.join(', ')}.`);
120
120
  return;
121
121
  }
122
122
  const bundle = memory.exportBundle({ scope: scopeRaw });
@@ -137,7 +137,7 @@ export function handleRecallHandoffInspect(args: string[], context: CommandConte
137
137
  const bundle = JSON.parse(readFileSync(targetPath, 'utf-8')) as MemoryBundle;
138
138
  context.print(inspectBundle(bundle));
139
139
  } catch (error) {
140
- context.print(`[memory] Failed to inspect handoff bundle: ${summarizeError(error)}`);
140
+ context.print(`[memory] Failed to inspect handoff bundle ${summarizeError(error)}`);
141
141
  }
142
142
  }
143
143
 
@@ -1,5 +1,6 @@
1
1
  import type { CommandContext } from '../command-registry.ts';
2
2
  import type { ProvenanceLink } from '@pellux/goodvibes-sdk/platform/state';
3
+ import { formatAgentRecordReferences } from '../../agent/record-labels.ts';
3
4
  import {
4
5
  buildIncidentMemoryAddOptions,
5
6
  buildMcpSecurityMemoryAddOptions,
@@ -17,7 +18,7 @@ export async function handleRecallAdd(args: string[], context: CommandContext):
17
18
 
18
19
  const cls = args[0];
19
20
  if (!cls || !isValidClass(cls)) {
20
- context.print(`[memory] Invalid class "${cls ?? ''}". Valid: ${VALID_CLASSES.join(', ')}`);
21
+ context.print(`[memory] Invalid class "${cls ?? ''}". Valid values ${VALID_CLASSES.join(', ')}.`);
21
22
  return;
22
23
  }
23
24
 
@@ -36,7 +37,7 @@ export async function handleRecallAdd(args: string[], context: CommandContext):
36
37
  const scope = scopeRaw && isValidScope(scopeRaw) ? scopeRaw : 'project';
37
38
 
38
39
  if (scopeRaw && !isValidScope(scopeRaw)) {
39
- context.print(`[memory] Invalid scope "${scopeRaw}". Valid: ${VALID_SCOPES.join(', ')}`);
40
+ context.print(`[memory] Invalid scope "${scopeRaw}". Valid values ${VALID_SCOPES.join(', ')}.`);
40
41
  return;
41
42
  }
42
43
 
@@ -60,12 +61,13 @@ export async function handleRecallAdd(args: string[], context: CommandContext):
60
61
  }
61
62
 
62
63
  const record = await memory.add({ scope, cls, summary, detail, tags, provenance });
63
- context.print(`[memory] Added ${cls}: ${record.id}`);
64
- context.print(` Scope: ${record.scope}`);
65
- context.print(` Summary: ${record.summary}`);
66
- if (record.tags.length) context.print(` Tags: ${record.tags.join(', ')}`);
64
+ context.print(`[memory] Added ${cls}`);
65
+ context.print(` id ${record.id}`);
66
+ context.print(` scope ${record.scope}`);
67
+ context.print(` summary ${record.summary}`);
68
+ if (record.tags.length) context.print(` tags ${record.tags.join(', ')}`);
67
69
  if (record.provenance.length) {
68
- context.print(` Provenance: ${record.provenance.map((entry) => `${entry.kind}:${entry.ref}`).join(', ')}`);
70
+ context.print(` origin ${formatAgentRecordReferences(record.provenance)}`);
69
71
  }
70
72
  }
71
73
 
@@ -87,12 +89,12 @@ export async function handleRecallCapture(args: string[], context: CommandContex
87
89
  ? context.extensions.forensicsRegistry.latest()
88
90
  : context.extensions.forensicsRegistry.getById(requestedId);
89
91
  if (!report) {
90
- context.print(`[memory] Incident not found: ${requestedId ?? 'latest'}`);
92
+ context.print(`[memory] Incident not found ${requestedId ?? 'latest'}`);
91
93
  return;
92
94
  }
93
95
  const bundle = context.extensions.forensicsRegistry.buildBundle(report.id);
94
96
  if (!bundle) {
95
- context.print(`[memory] Failed to build incident bundle: ${report.id}`);
97
+ context.print(`[memory] Failed to build incident bundle ${report.id}`);
96
98
  return;
97
99
  }
98
100
  const record = await memory.add(buildIncidentMemoryAddOptions(bundle));
@@ -119,7 +121,7 @@ export async function handleRecallCapture(args: string[], context: CommandContex
119
121
  }
120
122
  const server = context.extensions.mcpRegistry.listServerSecurity().find((entry) => entry.name === serverName);
121
123
  if (!server) {
122
- context.print(`[memory] MCP server not found: ${serverName}`);
124
+ context.print(`[memory] MCP server not found ${serverName}`);
123
125
  return;
124
126
  }
125
127
  const record = await memory.add(buildMcpSecurityMemoryAddOptions(server));
@@ -139,7 +141,7 @@ export async function handleRecallCapture(args: string[], context: CommandContex
139
141
  }
140
142
  const plugin = pluginManager.list().find((entry) => entry.name === pluginName);
141
143
  if (!plugin) {
142
- context.print(`[memory] Plugin not found: ${pluginName}`);
144
+ context.print(`[memory] Plugin not found ${pluginName}`);
143
145
  return;
144
146
  }
145
147
  const quarantineReason = pluginManager.getQuarantineRecord(plugin.name)?.reason;
@@ -1,6 +1,7 @@
1
1
  import type { CommandContext } from '../command-registry.ts';
2
2
  import type { MemoryApi } from '@pellux/goodvibes-sdk/platform/knowledge';
3
3
  import type { MemorySearchFilter } from '@pellux/goodvibes-sdk/platform/state';
4
+ import { formatAgentRecordReference, formatAgentRecordReferences } from '../../agent/record-labels.ts';
4
5
  import { VALID_CLASSES, VALID_SCOPES, isValidClass, isValidScope } from './recall-shared.ts';
5
6
  import { requireYesFlag, stripYesFlag } from './confirmation.ts';
6
7
 
@@ -8,7 +9,7 @@ export function getMemoryApi(context: CommandContext): MemoryApi | null {
8
9
  const memoryApi = context.clients?.agentKnowledgeApi?.memory;
9
10
  if (!memoryApi) {
10
11
  context.print('[memory] Agent Memory API is not available in this runtime.');
11
- context.print('[memory] Refusing to use default Knowledge/Wiki or non-Agent knowledge fallback.');
12
+ context.print('[memory] Refusing to use default knowledge or non-Agent knowledge fallback.');
12
13
  return null;
13
14
  }
14
15
  return memoryApi;
@@ -29,7 +30,7 @@ export function handleRecallSearch(args: string[], context: CommandContext): voi
29
30
  const cls = args[clsIdx + 1];
30
31
  if (isValidClass(cls)) filter.cls = cls;
31
32
  else {
32
- context.print(`[memory] Unknown class "${cls}". Valid: ${VALID_CLASSES.join(', ')}`);
33
+ context.print(`[memory] Unknown class "${cls}". Valid values ${VALID_CLASSES.join(', ')}.`);
33
34
  return;
34
35
  }
35
36
  }
@@ -39,7 +40,7 @@ export function handleRecallSearch(args: string[], context: CommandContext): voi
39
40
  const scope = args[scopeIdx + 1];
40
41
  if (isValidScope(scope)) filter.scope = scope;
41
42
  else {
42
- context.print(`[memory] Unknown scope "${scope}". Valid: ${VALID_SCOPES.join(', ')}`);
43
+ context.print(`[memory] Unknown scope "${scope}". Valid values ${VALID_SCOPES.join(', ')}.`);
43
44
  return;
44
45
  }
45
46
  }
@@ -63,7 +64,7 @@ export function handleRecallSearch(args: string[], context: CommandContext): voi
63
64
  return;
64
65
  }
65
66
 
66
- context.print(`[memory] ${results.length} ${semantic ? 'semantic ' : ''}record(s):`);
67
+ context.print(`[memory] ${results.length} ${semantic ? 'semantic ' : ''}record(s)`);
67
68
  for (const record of results) {
68
69
  const semanticEntry = semanticResults.find((entry) => entry.record.id === record.id);
69
70
  const ts = new Date(record.createdAt).toISOString().slice(0, 16).replace('T', ' ');
@@ -72,7 +73,7 @@ export function handleRecallSearch(args: string[], context: CommandContext): voi
72
73
  context.print(` ${record.id} [${record.cls}]${tagStr} ${ts}${scoreStr}`);
73
74
  context.print(` ${record.summary}`);
74
75
  if (record.provenance.length) {
75
- context.print(` via: ${record.provenance.map((entry) => `${entry.kind}:${entry.ref}`).join(', ')}`);
76
+ context.print(` origin ${formatAgentRecordReferences(record.provenance)}`);
76
77
  }
77
78
  }
78
79
  }
@@ -124,29 +125,28 @@ export function handleRecallGet(args: string[], context: CommandContext): void {
124
125
  }
125
126
  const record = memory.get(id);
126
127
  if (!record) {
127
- context.print(`[memory] Record not found: ${id}`);
128
+ context.print(`[memory] Record not found ${id}`);
128
129
  return;
129
130
  }
130
131
  const ts = new Date(record.createdAt).toISOString().slice(0, 19).replace('T', ' ');
131
132
  context.print(`[memory] ${record.id}`);
132
- context.print(` Scope: ${record.scope}`);
133
- context.print(` Class: ${record.cls}`);
134
- context.print(` Summary: ${record.summary}`);
135
- if (record.detail) context.print(` Detail: ${record.detail}`);
136
- if (record.tags.length) context.print(` Tags: ${record.tags.join(', ')}`);
137
- context.print(` Created: ${ts}`);
133
+ context.print(` scope ${record.scope}`);
134
+ context.print(` class ${record.cls}`);
135
+ context.print(` summary ${record.summary}`);
136
+ if (record.detail) context.print(` detail ${record.detail}`);
137
+ if (record.tags.length) context.print(` tags ${record.tags.join(', ')}`);
138
+ context.print(` created ${ts}`);
138
139
 
139
140
  if (record.provenance.length) {
140
- context.print(' Provenance:');
141
+ context.print(' origin');
141
142
  for (const provenance of record.provenance) {
142
- const label = provenance.label ? ` (${provenance.label})` : '';
143
- context.print(` ${provenance.kind}: ${provenance.ref}${label}`);
143
+ context.print(` ${formatAgentRecordReference(provenance)}`);
144
144
  }
145
145
  }
146
146
 
147
147
  const links = memory.linksFor(id);
148
148
  if (links.length) {
149
- context.print(' Links:');
149
+ context.print(' links');
150
150
  for (const link of links) {
151
151
  const dir = link.fromId === id ? '->' : '<-';
152
152
  const other = link.fromId === id ? link.toId : link.fromId;
@@ -175,7 +175,12 @@ export async function handleRecallLink(args: string[], context: CommandContext):
175
175
  context.print('[memory] Link failed — check that both IDs exist.');
176
176
  return;
177
177
  }
178
- context.print(`[memory] Linked: ${fromId} -> ${toId} [${relation}]`);
178
+ context.print([
179
+ '[memory] Linked',
180
+ ` from ${fromId}`,
181
+ ` to ${toId}`,
182
+ ` relation ${relation}`,
183
+ ].join('\n'));
179
184
  }
180
185
 
181
186
  export function handleRecallRemove(args: string[], context: CommandContext): void {
@@ -195,10 +200,13 @@ export function handleRecallRemove(args: string[], context: CommandContext): voi
195
200
  }
196
201
  const removed = memory.delete(id);
197
202
  if (!removed) {
198
- context.print(`[memory] Record not found: ${id}`);
203
+ context.print(`[memory] Record not found ${id}`);
199
204
  return;
200
205
  }
201
- context.print(`[memory] Deleted: ${id}`);
206
+ context.print([
207
+ '[memory] Deleted',
208
+ ` id ${id}`,
209
+ ].join('\n'));
202
210
  }
203
211
 
204
212
  export function handleRecallList(args: string[], context: CommandContext): void {
@@ -213,7 +221,7 @@ export function handleRecallList(args: string[], context: CommandContext): void
213
221
  if (scopeIdx !== -1 && args[scopeIdx + 1]) {
214
222
  const scope = args[scopeIdx + 1];
215
223
  if (!isValidScope(scope)) {
216
- context.print(`[memory] Unknown scope "${scope}". Valid: ${VALID_SCOPES.join(', ')}`);
224
+ context.print(`[memory] Unknown scope "${scope}". Valid values ${VALID_SCOPES.join(', ')}.`);
217
225
  return;
218
226
  }
219
227
  filter.scope = scope;
@@ -232,7 +240,7 @@ export function handleRecallList(args: string[], context: CommandContext): void
232
240
  }
233
241
 
234
242
  for (const [clsName, group] of Object.entries(grouped)) {
235
- context.print(`\n[memory] ${clsName.toUpperCase()} (${group.length}):`);
243
+ context.print(`\n[memory] ${clsName.toUpperCase()} (${group.length})`);
236
244
  for (const record of group) {
237
245
  const tagStr = record.tags.length ? ` [${record.tags.join(', ')}]` : '';
238
246
  context.print(` ${record.id} [${record.scope}]${tagStr} ${record.summary}`);
@@ -1,4 +1,5 @@
1
1
  import type { CommandContext } from '../command-registry.ts';
2
+ import { formatAgentRecordReviewState } from '../../agent/record-labels.ts';
2
3
  import { VALID_REVIEW_STATES, VALID_SCOPES, isValidReviewState, isValidScope } from './recall-shared.ts';
3
4
  import { getMemoryApi } from './recall-query.ts';
4
5
  import { requireYesFlag, stripYesFlag } from './confirmation.ts';
@@ -17,7 +18,7 @@ export function handleRecallQueue(args: string[], context: CommandContext): void
17
18
  context.print(`[memory] Review queue (${queue.length}):`);
18
19
  for (const record of queue) {
19
20
  const reason = record.staleReason ? ` — ${record.staleReason}` : '';
20
- context.print(` ${record.id} [${record.scope}/${record.cls}] ${record.reviewState} ${record.confidence}% ${record.summary}${reason}`);
21
+ context.print(` ${record.id} [${record.scope}/${record.cls}] ${formatAgentRecordReviewState(record.reviewState)} ${record.confidence}% ${record.summary}${reason}`);
21
22
  }
22
23
  }
23
24
 
@@ -1,10 +1,11 @@
1
1
  import { discoverRoutines, type DiscoveredRoutineRecord } from '../../agent/routine-discovery.ts';
2
2
  import { AgentRoutineRegistry, evaluateAgentRoutineReadiness, type AgentRoutineRecord } from '../../agent/routine-registry.ts';
3
+ import { formatAgentRecordOrigin, formatAgentRecordReviewState } from '../../agent/record-labels.ts';
3
4
  import { buildAgentSkillRequirements, formatAgentSkillRequirement } from '../../agent/skill-registry.ts';
4
5
  import {
5
6
  buildRoutineSchedulePreview,
6
- promoteRoutineToDaemonSchedule,
7
- resolveAgentDaemonConnection,
7
+ promoteRoutineToConnectedSchedule,
8
+ resolveAgentConnectedHostConnection,
8
9
  } from '../../agent/routine-schedule-promotion.ts';
9
10
  import { parseRoutineSchedulePromotionArgs } from '../../agent/routine-schedule-args.ts';
10
11
  import {
@@ -20,38 +21,13 @@ import {
20
21
  RoutineScheduleReceiptStore,
21
22
  } from '../../agent/routine-schedule-receipts.ts';
22
23
  import type { CommandContext, CommandRegistry } from '../command-registry.ts';
24
+ import { parseAgentLocalLibraryArgs, type ParsedAgentLocalLibraryArgs } from './agent-local-library-args.ts';
23
25
  import { requireShellPaths } from './runtime-services.ts';
24
26
 
25
- interface ParsedRoutineArgs {
26
- readonly rest: readonly string[];
27
- readonly flags: ReadonlyMap<string, string>;
28
- readonly yes: boolean;
29
- }
27
+ const ROUTINE_VALUE_FLAGS = ['name', 'description', 'steps', 'tags', 'triggers', 'requires-env', 'requires-command', 'requires-commands'] as const;
30
28
 
31
- function parseRoutineArgs(args: readonly string[]): ParsedRoutineArgs {
32
- const flags = new Map<string, string>();
33
- const rest: string[] = [];
34
- let yes = false;
35
- for (let index = 0; index < args.length; index += 1) {
36
- const token = args[index] ?? '';
37
- if (token === '--yes') {
38
- yes = true;
39
- continue;
40
- }
41
- if (token.startsWith('--')) {
42
- const key = token.slice(2);
43
- const next = args[index + 1];
44
- if (next !== undefined && !next.startsWith('--')) {
45
- flags.set(key, next);
46
- index += 1;
47
- } else {
48
- flags.set(key, 'true');
49
- }
50
- continue;
51
- }
52
- rest.push(token);
53
- }
54
- return { rest, flags, yes };
29
+ function parseRoutineArgs(args: readonly string[]): ParsedAgentLocalLibraryArgs {
30
+ return parseAgentLocalLibraryArgs(args, { valueFlags: ROUTINE_VALUE_FLAGS });
55
31
  }
56
32
 
57
33
  function splitList(value: string | undefined): readonly string[] {
@@ -73,12 +49,23 @@ function requiredFlag(flags: ReadonlyMap<string, string>, key: string): string {
73
49
  return value;
74
50
  }
75
51
 
52
+ function formatRoutineReceipt(title: string, routine: Pick<AgentRoutineRecord, 'id' | 'name'>, extra: readonly string[] = []): string {
53
+ const enabled = extra.some((line) => line.trim() === 'enabled yes');
54
+ return [
55
+ `${title} ${routine.id}: ${routine.name}${enabled ? ' (enabled)' : ''}`,
56
+ ` id ${routine.id}`,
57
+ ` name ${routine.name}`,
58
+ ...extra,
59
+ ].join('\n');
60
+ }
61
+
76
62
  function summarizeRoutine(routine: AgentRoutineRecord): string {
77
63
  const enabled = routine.enabled ? 'enabled' : 'disabled';
78
- const tags = routine.tags.length > 0 ? ` tags=${routine.tags.join(',')}` : '';
64
+ const tags = routine.tags.length > 0 ? ` tags ${routine.tags.join(', ')}` : '';
79
65
  const readiness = evaluateAgentRoutineReadiness(routine);
66
+ const review = formatAgentRecordReviewState(routine.reviewState);
80
67
  const ready = readiness.ready ? 'ready' : `needs ${readiness.missing.map(formatAgentSkillRequirement).join(',')}`;
81
- return ` ${routine.id} ${enabled} ${routine.reviewState} ${ready} starts=${routine.startCount} ${routine.name} - ${routine.description}${tags}`;
68
+ return ` ${routine.id} ${enabled} ${review} ${ready} starts ${routine.startCount} ${routine.name} - ${routine.description}${tags}`;
82
69
  }
83
70
 
84
71
  function renderList(title: string, registry: AgentRoutineRegistry, routines: readonly AgentRoutineRecord[], emptyMessage?: string): string {
@@ -86,12 +73,12 @@ function renderList(title: string, registry: AgentRoutineRegistry, routines: rea
86
73
  if (routines.length === 0) {
87
74
  return emptyMessage
88
75
  ? `${title}\n ${emptyMessage}`
89
- : `${title}\n No local Agent routines yet. Create one with /routines create --name <name> --description <summary> --steps <steps>.`;
76
+ : `${title}\n No local Agent routines yet.\n No Agent-local routines yet. Create one with /routines create --name <name> --description <summary> --steps <steps>.`;
90
77
  }
91
78
  return [
92
79
  `${title} (${routines.length})`,
93
- ` store: ${snapshot.path}`,
94
- ` enabled: ${snapshot.enabledRoutines.length}`,
80
+ ` store ${snapshot.path}`,
81
+ ` enabled ${snapshot.enabledRoutines.length}`,
95
82
  ...routines.map(summarizeRoutine),
96
83
  ].join('\n');
97
84
  }
@@ -100,20 +87,19 @@ function renderRoutine(routine: AgentRoutineRecord): string {
100
87
  const readiness = evaluateAgentRoutineReadiness(routine);
101
88
  return [
102
89
  `Routine ${routine.name}`,
103
- ` id: ${routine.id}`,
104
- ` enabled: ${routine.enabled ? 'yes' : 'no'}`,
90
+ ` id ${routine.id}`,
91
+ ` enabled ${routine.enabled ? 'yes' : 'no'}`,
105
92
  ` readiness: ${readiness.ready ? 'ready' : 'needs setup'}`,
106
- ` requirements: ${routine.requirements.map(formatAgentSkillRequirement).join(', ') || '(none)'}`,
93
+ ` requirements ${routine.requirements.map(formatAgentSkillRequirement).join(', ') || '(none)'}`,
107
94
  readiness.missing.length > 0 ? ` missing: ${readiness.missing.map(formatAgentSkillRequirement).join(', ')}` : '',
108
- ` review: ${routine.reviewState}`,
109
- ` source: ${routine.source}`,
110
- ` provenance: ${routine.provenance}`,
95
+ ` review ${formatAgentRecordReviewState(routine.reviewState)}`,
96
+ ` origin ${formatAgentRecordOrigin(routine.source, routine.provenance)}`,
111
97
  ` tags: ${routine.tags.join(', ') || '(none)'}`,
112
98
  ` triggers: ${routine.triggers.join(', ') || '(manual)'}`,
113
- ` started: ${routine.startCount}${routine.lastStartedAt ? `; last ${routine.lastStartedAt}` : ''}`,
114
- ` created: ${routine.createdAt}`,
115
- ` updated: ${routine.updatedAt}`,
116
- routine.staleReason ? ` stale reason: ${routine.staleReason}` : '',
99
+ ` started ${routine.startCount}${routine.lastStartedAt ? `; last ${routine.lastStartedAt}` : ''}`,
100
+ ` created ${routine.createdAt}`,
101
+ ` updated ${routine.updatedAt}`,
102
+ routine.staleReason ? ` stale reason ${routine.staleReason}` : '',
117
103
  '',
118
104
  routine.description,
119
105
  '',
@@ -123,7 +109,7 @@ function renderRoutine(routine: AgentRoutineRecord): string {
123
109
 
124
110
  function summarizeDiscoveredRoutine(routine: DiscoveredRoutineRecord): string {
125
111
  const description = routine.description ? ` - ${routine.description}` : '';
126
- return ` ${routine.name} ${routine.origin}${description}\n path: ${routine.path}`;
112
+ return ` ${routine.name} ${routine.origin}${description}\n path ${routine.path}`;
127
113
  }
128
114
 
129
115
  function renderDiscoveredRoutines(routines: readonly DiscoveredRoutineRecord[]): string {
@@ -169,7 +155,10 @@ function frontmatterAnyList(routine: DiscoveredRoutineRecord, keys: readonly str
169
155
  }
170
156
 
171
157
  function printError(ctx: CommandContext, error: unknown): void {
172
- ctx.print(`Error: ${error instanceof Error ? error.message : String(error)}`);
158
+ ctx.print([
159
+ 'Error',
160
+ ` message ${error instanceof Error ? error.message : String(error)}`,
161
+ ].join('\n'));
173
162
  }
174
163
 
175
164
  async function importDiscoveredRoutine(args: readonly string[], ctx: CommandContext, routineRegistry: AgentRoutineRegistry): Promise<void> {
@@ -181,18 +170,18 @@ async function importDiscoveredRoutine(args: readonly string[], ctx: CommandCont
181
170
  }
182
171
  const discovered = findDiscoveredRoutine(await discoverRoutines(requireShellPaths(ctx)), name);
183
172
  if (!discovered) {
184
- ctx.print(`Unknown discovered Agent routine: ${name}\nRun /routines discover to inspect available routine files.`);
173
+ ctx.print(`Unknown discovered Agent routine ${name}\nRun /routines discover to inspect available routine files.`);
185
174
  return;
186
175
  }
187
176
  if (!parsed.yes) {
188
177
  ctx.print([
189
178
  'Agent routine import preview',
190
- ` name: ${discovered.name}`,
191
- ` origin: ${discovered.origin}`,
192
- ` path: ${discovered.path}`,
193
- ` description: ${discovered.description || '(none)'}`,
194
- ` steps characters: ${discovered.steps.length}`,
195
- ' next: rerun with --yes to import into the Agent-local routine registry',
179
+ ` name ${discovered.name}`,
180
+ ` origin ${discovered.origin}`,
181
+ ` path ${discovered.path}`,
182
+ ` description ${discovered.description || '(none)'}`,
183
+ ` steps characters ${discovered.steps.length}`,
184
+ ' next rerun with --yes to import into the Agent-local routine registry',
196
185
  ].join('\n'));
197
186
  return;
198
187
  }
@@ -210,7 +199,7 @@ async function importDiscoveredRoutine(args: readonly string[], ctx: CommandCont
210
199
  source: 'imported',
211
200
  provenance: `discovered:${discovered.origin}:${discovered.path}`,
212
201
  });
213
- ctx.print(`Imported Agent routine ${routine.id}: ${routine.name}${routine.enabled ? ' (enabled)' : ''}`);
202
+ ctx.print(formatRoutineReceipt('Imported Agent routine', routine, [` enabled ${routine.enabled ? 'yes' : 'no'}`]));
214
203
  }
215
204
 
216
205
  async function promoteRoutine(args: readonly string[], routineRegistry: AgentRoutineRegistry, ctx: CommandContext): Promise<void> {
@@ -233,8 +222,8 @@ async function promoteRoutine(args: readonly string[], routineRegistry: AgentRou
233
222
  return;
234
223
  }
235
224
  const shellPaths = requireShellPaths(ctx);
236
- const connection = resolveAgentDaemonConnection(ctx.platform.configManager, shellPaths.homeDirectory);
237
- const result = await promoteRoutineToDaemonSchedule(connection, preview);
225
+ const connection = resolveAgentConnectedHostConnection(ctx.platform.configManager, shellPaths.homeDirectory);
226
+ const result = await promoteRoutineToConnectedSchedule(connection, preview);
238
227
  const receipt = receiptStoreFromContext(ctx).append(connection, preview, result);
239
228
  ctx.print(result.ok ? `${formatRoutineScheduleSuccess(result)}\n receipt: ${receipt.id}` : `${formatRoutineScheduleFailure(result)}\n receipt: ${receipt.id}`);
240
229
  }
@@ -254,7 +243,7 @@ export async function runRoutinesRuntimeCommand(args: readonly string[], ctx: Co
254
243
  }
255
244
  if (sub === 'attention' || sub === 'needs-setup') {
256
245
  const routines = routineRegistry.list().filter((routine) => !evaluateAgentRoutineReadiness(routine).ready);
257
- ctx.print(renderList('Agent Routines needing setup', routineRegistry, routines, 'No local Agent routines need setup.'));
246
+ ctx.print(renderList('Agent Routines needing setup', routineRegistry, routines, 'No Agent-local routines need setup.'));
258
247
  return;
259
248
  }
260
249
  if (sub === 'discover' || sub === 'discovered') {
@@ -286,7 +275,7 @@ export async function runRoutinesRuntimeCommand(args: readonly string[], ctx: Co
286
275
  }
287
276
  if (sub === 'reconcile' || sub === 'sync' || sub === 'status') {
288
277
  const shellPaths = requireShellPaths(ctx);
289
- const connection = resolveAgentDaemonConnection(ctx.platform.configManager, shellPaths.homeDirectory);
278
+ const connection = resolveAgentConnectedHostConnection(ctx.platform.configManager, shellPaths.homeDirectory);
290
279
  const result = await reconcileRoutineScheduleReceipts(connection, receiptStoreFromContext(ctx).snapshot());
291
280
  ctx.print(formatRoutineScheduleCorrelation(result));
292
281
  return;
@@ -298,7 +287,7 @@ export async function runRoutinesRuntimeCommand(args: readonly string[], ctx: Co
298
287
  return;
299
288
  }
300
289
  const receipt = receiptStoreFromContext(ctx).get(id);
301
- ctx.print(receipt ? formatRoutineScheduleReceipt(receipt) : `Unknown routine schedule receipt: ${id}`);
290
+ ctx.print(receipt ? formatRoutineScheduleReceipt(receipt) : `Unknown routine schedule receipt ${id}`);
302
291
  return;
303
292
  }
304
293
  if (sub === 'create') {
@@ -316,9 +305,9 @@ export async function runRoutinesRuntimeCommand(args: readonly string[], ctx: Co
316
305
  }),
317
306
  enabled: parsed.flags.get('enabled') === 'true',
318
307
  source: 'user',
319
- provenance: 'slash-command',
308
+ provenance: 'Command',
320
309
  });
321
- ctx.print(`Created Agent routine ${routine.id}: ${routine.name}`);
310
+ ctx.print(formatRoutineReceipt('Created Agent routine', routine));
322
311
  return;
323
312
  }
324
313
  if (sub === 'update') {
@@ -340,9 +329,9 @@ export async function runRoutinesRuntimeCommand(args: readonly string[], ctx: Co
340
329
  commands: splitList(parsed.flags.get('requires-command') ?? parsed.flags.get('requires-commands')),
341
330
  })
342
331
  : undefined,
343
- provenance: 'slash-command',
332
+ provenance: 'Command',
344
333
  });
345
- ctx.print(`Updated Agent routine ${updated.id}: ${updated.name}`);
334
+ ctx.print(formatRoutineReceipt('Updated Agent routine', updated));
346
335
  return;
347
336
  }
348
337
  if (sub === 'enable' || sub === 'disable') {
@@ -352,7 +341,7 @@ export async function runRoutinesRuntimeCommand(args: readonly string[], ctx: Co
352
341
  return;
353
342
  }
354
343
  const routine = routineRegistry.setEnabled(id, sub === 'enable');
355
- ctx.print(`${sub === 'enable' ? 'Enabled' : 'Disabled'} Agent routine ${routine.id}: ${routine.name}`);
344
+ ctx.print(formatRoutineReceipt(`${sub === 'enable' ? 'Enabled' : 'Disabled'} Agent routine`, routine));
356
345
  return;
357
346
  }
358
347
  if (sub === 'start' || sub === 'run') {
@@ -364,9 +353,11 @@ export async function runRoutinesRuntimeCommand(args: readonly string[], ctx: Co
364
353
  const routine = routineRegistry.markStarted(id);
365
354
  const readiness = evaluateAgentRoutineReadiness(routine);
366
355
  ctx.print([
367
- `Started Agent routine ${routine.id}: ${routine.name}`,
356
+ `Started Agent routine ${routine.id}`,
357
+ ` id ${routine.id}`,
358
+ ` name ${routine.name}`,
368
359
  ` readiness: ${readiness.ready ? 'ready' : `needs setup (${readiness.missing.map(formatAgentSkillRequirement).join(', ')})`}`,
369
- ' policy: same main conversation; no hidden job, runtime mutation, or external side effect was started',
360
+ ' policy same main conversation; no hidden job, runtime mutation, or external side effect was started',
370
361
  '',
371
362
  routine.steps,
372
363
  ].join('\n'));
@@ -379,7 +370,7 @@ export async function runRoutinesRuntimeCommand(args: readonly string[], ctx: Co
379
370
  return;
380
371
  }
381
372
  const routine = routineRegistry.markReviewed(id);
382
- ctx.print(`Reviewed Agent routine ${routine.id}.`);
373
+ ctx.print(formatRoutineReceipt('Reviewed Agent routine', routine));
383
374
  return;
384
375
  }
385
376
  if (sub === 'stale') {
@@ -389,7 +380,7 @@ export async function runRoutinesRuntimeCommand(args: readonly string[], ctx: Co
389
380
  return;
390
381
  }
391
382
  const routine = routineRegistry.markStale(id, args.slice(2).join(' '));
392
- ctx.print(`Marked Agent routine ${routine.id} stale.`);
383
+ ctx.print(formatRoutineReceipt('Marked Agent routine stale', routine));
393
384
  return;
394
385
  }
395
386
  if (sub === 'promote' || sub === 'schedule' || sub === 'promote-schedule') {
@@ -408,7 +399,7 @@ export async function runRoutinesRuntimeCommand(args: readonly string[], ctx: Co
408
399
  return;
409
400
  }
410
401
  const removed = routineRegistry.deleteRoutine(id);
411
- ctx.print(`Deleted Agent routine ${removed.id}: ${removed.name}`);
402
+ ctx.print(formatRoutineReceipt('Deleted Agent routine', removed));
412
403
  return;
413
404
  }
414
405
  ctx.print('Usage: /routines [list|enabled|attention|discover|import-discovered|search|show|receipts|reconcile|receipt|create|update|enable|disable|start|review|stale|promote|delete]');
@@ -421,7 +412,7 @@ export function registerRoutinesRuntimeCommands(registry: CommandRegistry): void
421
412
  registry.register({
422
413
  name: 'routines',
423
414
  aliases: ['routine'],
424
- description: 'Manage local GoodVibes Agent routines',
415
+ description: 'Manage Agent-local routines',
425
416
  usage: '[list|enabled|attention|discover|import-discovered <name> --yes|search <query>|show <id>|receipts|reconcile|receipt <id>|create --name <name> --description <summary> --steps <steps> [--requires-env A,B] [--requires-command gh,jq]|update <id> [--name ...] [--description ...] [--steps ...]|enable <id>|disable <id>|start <id>|review <id>|stale <id> <reason...>|promote <id> --cron <expr> [--delivery-channel slack] --yes|delete <id> --yes]',
426
417
  handler: runRoutinesRuntimeCommand,
427
418
  });