@pellux/goodvibes-agent 0.1.117 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (253) hide show
  1. package/CHANGELOG.md +13 -4
  2. package/README.md +35 -14
  3. package/bin/goodvibes-agent.ts +16 -2
  4. package/dist/package/main.js +176073 -170980
  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 +134 -68
  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 +44 -36
  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-learned-behavior.ts +2 -2
  66. package/src/input/agent-workspace-library-command-editor-submission.ts +1 -1
  67. package/src/input/agent-workspace-library-command-editors.ts +2 -2
  68. package/src/input/agent-workspace-local-operations.ts +218 -0
  69. package/src/input/agent-workspace-local-selection.ts +75 -0
  70. package/src/input/agent-workspace-media-command-editor-submission.ts +62 -0
  71. package/src/input/agent-workspace-media-command-editors.ts +27 -0
  72. package/src/input/agent-workspace-memory-command-editors.ts +1 -1
  73. package/src/input/agent-workspace-memory-editor.ts +2 -2
  74. package/src/input/agent-workspace-navigation.ts +38 -2
  75. package/src/input/agent-workspace-notify-editor-submission.ts +16 -2
  76. package/src/input/agent-workspace-operations-command-editor-submission.ts +63 -1
  77. package/src/input/agent-workspace-operations-command-editors.ts +80 -3
  78. package/src/input/agent-workspace-panel-route.ts +43 -0
  79. package/src/input/agent-workspace-reminder-schedule-editor.ts +1 -1
  80. package/src/input/agent-workspace-routine-schedule-editor.ts +2 -2
  81. package/src/input/agent-workspace-search.ts +169 -0
  82. package/src/input/agent-workspace-setup.ts +22 -11
  83. package/src/input/agent-workspace-skill-bundle-command-editor-submission.ts +6 -6
  84. package/src/input/agent-workspace-skill-bundle-command-editors.ts +10 -10
  85. package/src/input/agent-workspace-snapshot.ts +112 -13
  86. package/src/input/agent-workspace-task-command-editors.ts +4 -4
  87. package/src/input/agent-workspace-token.ts +18 -2
  88. package/src/input/agent-workspace-types.ts +92 -4
  89. package/src/input/agent-workspace-voice-media.ts +3 -6
  90. package/src/input/agent-workspace-web-research-editor.ts +104 -0
  91. package/src/input/agent-workspace.ts +136 -208
  92. package/src/input/command-registry.ts +4 -1
  93. package/src/input/commands/agent-runtime-profile-runtime.ts +45 -41
  94. package/src/input/commands/agent-skills-runtime.ts +83 -70
  95. package/src/input/commands/agent-workspace-runtime.ts +23 -7
  96. package/src/input/commands/brief-runtime.ts +25 -24
  97. package/src/input/commands/channels-runtime.ts +145 -31
  98. package/src/input/commands/delegation-runtime.ts +29 -23
  99. package/src/input/commands/experience-runtime.ts +6 -4
  100. package/src/input/commands/guidance-runtime.ts +4 -4
  101. package/src/input/commands/health-runtime.ts +140 -115
  102. package/src/input/commands/knowledge.ts +57 -56
  103. package/src/input/commands/local-provider-runtime.ts +36 -18
  104. package/src/input/commands/local-runtime.ts +138 -16
  105. package/src/input/commands/local-setup-review.ts +7 -7
  106. package/src/input/commands/mcp-runtime.ts +56 -35
  107. package/src/input/commands/notify-runtime.ts +38 -9
  108. package/src/input/commands/operator-actions-runtime.ts +138 -0
  109. package/src/input/commands/operator-runtime.ts +6 -17
  110. package/src/input/commands/personas-runtime.ts +45 -30
  111. package/src/input/commands/planning-runtime.ts +1 -1
  112. package/src/input/commands/platform-access-runtime.ts +29 -29
  113. package/src/input/commands/provider-accounts-runtime.ts +60 -39
  114. package/src/input/commands/qrcode-runtime.ts +45 -6
  115. package/src/input/commands/recall-bundle.ts +11 -11
  116. package/src/input/commands/recall-capture.ts +13 -11
  117. package/src/input/commands/recall-query.ts +29 -21
  118. package/src/input/commands/recall-review.ts +2 -1
  119. package/src/input/commands/routines-runtime.ts +59 -43
  120. package/src/input/commands/schedule-runtime.ts +33 -20
  121. package/src/input/commands/security-runtime.ts +4 -4
  122. package/src/input/commands/session-content.ts +80 -78
  123. package/src/input/commands/session-workflow.ts +132 -93
  124. package/src/input/commands/session.ts +3 -174
  125. package/src/input/commands/shell-core.ts +32 -17
  126. package/src/input/commands/subscription-runtime.ts +53 -179
  127. package/src/input/commands/tasks-runtime.ts +20 -20
  128. package/src/input/commands/work-plan-runtime.ts +33 -8
  129. package/src/input/commands.ts +2 -2
  130. package/src/input/feed-context-factory.ts +2 -1
  131. package/src/input/file-picker.ts +3 -2
  132. package/src/input/handler-command-route.ts +4 -7
  133. package/src/input/handler-content-actions.ts +89 -1
  134. package/src/input/handler-feed-routes.ts +19 -12
  135. package/src/input/handler-feed.ts +6 -3
  136. package/src/input/handler-interactions.ts +7 -5
  137. package/src/input/handler-modal-stack.ts +3 -3
  138. package/src/input/handler-onboarding.ts +24 -80
  139. package/src/input/handler-shortcuts.ts +15 -4
  140. package/src/input/handler.ts +47 -17
  141. package/src/input/input-history.ts +5 -6
  142. package/src/input/keybindings.ts +22 -11
  143. package/src/input/onboarding/onboarding-wizard-apply.ts +13 -0
  144. package/src/input/onboarding/onboarding-wizard-constants.ts +1 -0
  145. package/src/input/onboarding/onboarding-wizard-operator-steps.ts +147 -57
  146. package/src/input/onboarding/onboarding-wizard-steps.ts +46 -29
  147. package/src/input/onboarding/onboarding-wizard-types.ts +3 -1
  148. package/src/input/onboarding/onboarding-wizard.ts +68 -0
  149. package/src/input/profile-picker-modal.ts +31 -12
  150. package/src/input/session-picker-modal.ts +21 -4
  151. package/src/input/settings-modal-behavior.ts +0 -3
  152. package/src/input/settings-modal-subscriptions.ts +3 -3
  153. package/src/input/settings-modal-types.ts +2 -13
  154. package/src/input/settings-modal.ts +6 -52
  155. package/src/input/submission-intent.ts +0 -1
  156. package/src/input/submission-router.ts +3 -3
  157. package/src/main.ts +18 -8
  158. package/src/panels/approval-panel.ts +8 -8
  159. package/src/panels/automation-control-panel.ts +2 -2
  160. package/src/panels/base-panel.ts +1 -1
  161. package/src/panels/builtin/agent.ts +1 -1
  162. package/src/panels/builtin/operations.ts +1 -10
  163. package/src/panels/builtin/session.ts +9 -9
  164. package/src/panels/builtin/shared.ts +2 -2
  165. package/src/panels/cost-tracker-panel.ts +1 -1
  166. package/src/panels/docs-panel.ts +5 -3
  167. package/src/panels/index.ts +0 -1
  168. package/src/panels/knowledge-panel.ts +6 -5
  169. package/src/panels/memory-panel.ts +7 -6
  170. package/src/panels/panel-list-panel.ts +36 -80
  171. package/src/panels/project-planning-panel.ts +18 -11
  172. package/src/panels/provider-account-snapshot.ts +51 -25
  173. package/src/panels/provider-accounts-panel.ts +33 -18
  174. package/src/panels/provider-health-domains.ts +45 -4
  175. package/src/panels/provider-health-panel.ts +5 -4
  176. package/src/panels/qr-panel.ts +1 -1
  177. package/src/panels/schedule-panel.ts +9 -17
  178. package/src/panels/security-panel.ts +8 -8
  179. package/src/panels/session-browser-panel.ts +10 -10
  180. package/src/panels/subscription-panel.ts +3 -3
  181. package/src/panels/system-messages-panel.ts +1 -1
  182. package/src/panels/tasks-panel.ts +20 -13
  183. package/src/panels/tool-inspector-panel.ts +19 -12
  184. package/src/panels/work-plan-panel.ts +5 -5
  185. package/src/planning/project-planning-coordinator.ts +1 -1
  186. package/src/provider-auth-route-display.ts +9 -0
  187. package/src/renderer/agent-workspace-style.ts +34 -0
  188. package/src/renderer/agent-workspace.ts +228 -52
  189. package/src/renderer/autocomplete-overlay.ts +25 -6
  190. package/src/renderer/bookmark-modal.ts +19 -4
  191. package/src/renderer/buffer.ts +4 -2
  192. package/src/renderer/context-inspector.ts +50 -13
  193. package/src/renderer/diff.ts +1 -1
  194. package/src/renderer/file-picker-overlay.ts +19 -6
  195. package/src/renderer/help-overlay.ts +106 -33
  196. package/src/renderer/history-search-overlay.ts +19 -4
  197. package/src/renderer/live-tail-modal.ts +27 -5
  198. package/src/renderer/mcp-workspace.ts +164 -50
  199. package/src/renderer/model-picker-overlay.ts +58 -2
  200. package/src/renderer/model-workspace.ts +104 -20
  201. package/src/renderer/process-modal.ts +27 -6
  202. package/src/renderer/profile-picker-modal.ts +20 -4
  203. package/src/renderer/search-overlay.ts +25 -5
  204. package/src/renderer/selection-modal-overlay.ts +46 -14
  205. package/src/renderer/session-picker-modal.ts +18 -1
  206. package/src/renderer/settings-modal-helpers.ts +2 -40
  207. package/src/renderer/settings-modal.ts +83 -50
  208. package/src/renderer/tool-call.ts +20 -11
  209. package/src/runtime/agent-runtime-events.ts +6 -6
  210. package/src/runtime/bootstrap-command-context.ts +7 -1
  211. package/src/runtime/bootstrap-command-parts.ts +9 -7
  212. package/src/runtime/bootstrap-core.ts +19 -1
  213. package/src/runtime/bootstrap-hook-bridge.ts +7 -18
  214. package/src/runtime/bootstrap-shell.ts +4 -4
  215. package/src/runtime/bootstrap.ts +31 -22
  216. package/src/runtime/connected-host-auth.ts +7 -2
  217. package/src/runtime/diagnostics/panels/index.ts +2 -2
  218. package/src/runtime/diagnostics/panels/policy.ts +7 -7
  219. package/src/runtime/index.ts +2 -1
  220. package/src/runtime/onboarding/apply-file-helpers.ts +66 -0
  221. package/src/runtime/onboarding/apply.ts +80 -79
  222. package/src/runtime/onboarding/derivation.ts +5 -8
  223. package/src/runtime/onboarding/snapshot.ts +0 -15
  224. package/src/runtime/onboarding/types.ts +8 -19
  225. package/src/runtime/onboarding/verify.ts +32 -10
  226. package/src/runtime/operator-token-cleanup.ts +1 -1
  227. package/src/runtime/services.ts +91 -22
  228. package/src/runtime/store/selectors/index.ts +3 -3
  229. package/src/runtime/store/state.ts +1 -4
  230. package/src/runtime/surface-feature-flags.ts +41 -6
  231. package/src/runtime/ui-read-models.ts +3 -4
  232. package/src/runtime/ui-services.ts +6 -6
  233. package/src/shell/blocking-input.ts +2 -1
  234. package/src/shell/ui-openers.ts +3 -13
  235. package/src/tools/agent-analysis-registry-policy.ts +0 -1
  236. package/src/tools/agent-channel-send-tool.ts +133 -0
  237. package/src/tools/agent-context-policy.ts +1 -1
  238. package/src/tools/agent-knowledge-ingest-tool.ts +405 -0
  239. package/src/tools/agent-knowledge-tool.ts +170 -0
  240. package/src/tools/agent-local-registry-tool.ts +269 -69
  241. package/src/tools/agent-media-generate-tool.ts +133 -0
  242. package/src/tools/agent-notify-tool.ts +143 -0
  243. package/src/tools/agent-operator-action-tool.ts +137 -0
  244. package/src/tools/agent-operator-briefing-tool.ts +217 -0
  245. package/src/tools/agent-reminder-schedule-tool.ts +237 -0
  246. package/src/tools/agent-tool-policy-guard.ts +8 -8
  247. package/src/tools/agent-work-plan-tool.ts +256 -0
  248. package/src/version.ts +1 -1
  249. package/src/input/commands/policy-dispatch.ts +0 -339
  250. package/src/input/commands/policy.ts +0 -13
  251. package/src/panels/panel-picker.ts +0 -105
  252. package/src/panels/policy-panel.ts +0 -308
  253. package/src/renderer/panel-picker-overlay.ts +0 -202
@@ -2,14 +2,14 @@ import type { CommandRegistry } from '../command-registry.ts';
2
2
  import { networkInterfaces } from 'node:os';
3
3
  import {
4
4
  buildCompanionConnectionInfo,
5
+ type CompanionConnectionInfo,
5
6
  encodeConnectionPayload,
6
- formatConnectionBlock,
7
7
  generateQrMatrix,
8
8
  renderQrToString,
9
9
  } from '@pellux/goodvibes-sdk/platform/pairing';
10
10
  import { GOODVIBES_AGENT_PAIRING_SURFACE } from '../../config/surface.ts';
11
11
  import { resolveRuntimeEndpointBinding } from '../../cli/endpoints.ts';
12
- import { connectedHostTokenRequiredMessage, readConnectedHostOperatorToken } from '../../runtime/connected-host-auth.ts';
12
+ import { connectedHostOperatorTokenFingerprint, connectedHostTokenRequiredMessage, readConnectedHostOperatorToken } from '../../runtime/connected-host-auth.ts';
13
13
  import { requirePlatform, requireShellPaths } from './runtime-services.ts';
14
14
 
15
15
  function getLocalNetworkIp(): string {
@@ -31,13 +31,42 @@ function urlHostForBindHost(host: string): string {
31
31
  return host || '127.0.0.1';
32
32
  }
33
33
 
34
+ function formatTokenLine(token: string, showToken: boolean): string {
35
+ if (showToken) return `Token: ${token}`;
36
+ return `Token: present sha256:${connectedHostOperatorTokenFingerprint(token)} (hidden in text; QR contains pairing payload)`;
37
+ }
38
+
39
+ function formatAgentPairingBlock(info: CompanionConnectionInfo, qr: string, showToken: boolean): string {
40
+ return [
41
+ `GoodVibes Agent companion pairing v${info.version}`,
42
+ '━━━━━━━━━━━━━━━━━━━━━━━━',
43
+ `Connected host: ${info.url}`,
44
+ `Surface: ${info.surface}`,
45
+ `User: ${info.username}`,
46
+ formatTokenLine(info.token, showToken),
47
+ '',
48
+ 'Scan to connect:',
49
+ '',
50
+ qr,
51
+ '',
52
+ showToken
53
+ ? 'Manual token display was explicitly confirmed for this command.'
54
+ : 'For manual setup, rerun /pair --show-token --yes to print the token once.',
55
+ 'Agent is waiting for the companion app to connect to the owning GoodVibes host.',
56
+ ].join('\n');
57
+ }
58
+
59
+ function shouldShowToken(args: readonly string[]): boolean {
60
+ return args.includes('--show-token') || args.includes('--manual-token');
61
+ }
62
+
34
63
  export function registerQrcodeRuntimeCommands(registry: CommandRegistry): void {
35
64
  registry.register({
36
65
  name: 'qrcode',
37
66
  aliases: ['qr', 'pair'],
38
67
  description: 'Print companion pairing details and a QR code',
39
68
  usage: '',
40
- handler(_args, ctx) {
69
+ handler(args, ctx) {
41
70
  const shellPaths = requireShellPaths(ctx);
42
71
  const configManager = requirePlatform(ctx).configManager;
43
72
  const tokenRecord = readConnectedHostOperatorToken(shellPaths.homeDirectory);
@@ -46,16 +75,26 @@ export function registerQrcodeRuntimeCommands(registry: CommandRegistry): void {
46
75
  return;
47
76
  }
48
77
  const binding = resolveRuntimeEndpointBinding(configManager, 'controlPlane');
49
- const daemonUrl = `http://${urlHostForBindHost(binding.host)}:${binding.port}`;
78
+ const connectedHostUrl = `http://${urlHostForBindHost(binding.host)}:${binding.port}`;
50
79
  const info = buildCompanionConnectionInfo({
51
- daemonUrl,
80
+ daemonUrl: connectedHostUrl,
52
81
  token: tokenRecord.token,
53
82
  username: 'admin',
54
83
  surface: GOODVIBES_AGENT_PAIRING_SURFACE,
55
84
  });
56
85
  const payload = encodeConnectionPayload(info);
57
86
  const qr = renderQrToString(generateQrMatrix(payload));
58
- ctx.print([formatConnectionBlock(info, payload), '', qr].join('\n'));
87
+ const showToken = shouldShowToken(args);
88
+ if (showToken && !args.includes('--yes')) {
89
+ ctx.print([
90
+ 'Manual companion token display requires confirmation.',
91
+ ' rerun: /pair --show-token --yes',
92
+ ` token fingerprint: sha256:${connectedHostOperatorTokenFingerprint(tokenRecord.token)}`,
93
+ ' QR pairing remains available without printing the raw token.',
94
+ ].join('\n'));
95
+ return;
96
+ }
97
+ ctx.print(formatAgentPairingBlock(info, qr, showToken));
59
98
  },
60
99
  });
61
100
  }
@@ -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 {
@@ -73,12 +74,23 @@ function requiredFlag(flags: ReadonlyMap<string, string>, key: string): string {
73
74
  return value;
74
75
  }
75
76
 
77
+ function formatRoutineReceipt(title: string, routine: Pick<AgentRoutineRecord, 'id' | 'name'>, extra: readonly string[] = []): string {
78
+ const enabled = extra.some((line) => line.trim() === 'enabled yes');
79
+ return [
80
+ `${title} ${routine.id}: ${routine.name}${enabled ? ' (enabled)' : ''}`,
81
+ ` id ${routine.id}`,
82
+ ` name ${routine.name}`,
83
+ ...extra,
84
+ ].join('\n');
85
+ }
86
+
76
87
  function summarizeRoutine(routine: AgentRoutineRecord): string {
77
88
  const enabled = routine.enabled ? 'enabled' : 'disabled';
78
- const tags = routine.tags.length > 0 ? ` tags=${routine.tags.join(',')}` : '';
89
+ const tags = routine.tags.length > 0 ? ` tags ${routine.tags.join(', ')}` : '';
79
90
  const readiness = evaluateAgentRoutineReadiness(routine);
91
+ const review = formatAgentRecordReviewState(routine.reviewState);
80
92
  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}`;
93
+ return ` ${routine.id} ${enabled} ${review} ${ready} starts ${routine.startCount} ${routine.name} - ${routine.description}${tags}`;
82
94
  }
83
95
 
84
96
  function renderList(title: string, registry: AgentRoutineRegistry, routines: readonly AgentRoutineRecord[], emptyMessage?: string): string {
@@ -86,12 +98,12 @@ function renderList(title: string, registry: AgentRoutineRegistry, routines: rea
86
98
  if (routines.length === 0) {
87
99
  return emptyMessage
88
100
  ? `${title}\n ${emptyMessage}`
89
- : `${title}\n No local Agent routines yet. Create one with /routines create --name <name> --description <summary> --steps <steps>.`;
101
+ : `${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
102
  }
91
103
  return [
92
104
  `${title} (${routines.length})`,
93
- ` store: ${snapshot.path}`,
94
- ` enabled: ${snapshot.enabledRoutines.length}`,
105
+ ` store ${snapshot.path}`,
106
+ ` enabled ${snapshot.enabledRoutines.length}`,
95
107
  ...routines.map(summarizeRoutine),
96
108
  ].join('\n');
97
109
  }
@@ -100,20 +112,19 @@ function renderRoutine(routine: AgentRoutineRecord): string {
100
112
  const readiness = evaluateAgentRoutineReadiness(routine);
101
113
  return [
102
114
  `Routine ${routine.name}`,
103
- ` id: ${routine.id}`,
104
- ` enabled: ${routine.enabled ? 'yes' : 'no'}`,
115
+ ` id ${routine.id}`,
116
+ ` enabled ${routine.enabled ? 'yes' : 'no'}`,
105
117
  ` readiness: ${readiness.ready ? 'ready' : 'needs setup'}`,
106
- ` requirements: ${routine.requirements.map(formatAgentSkillRequirement).join(', ') || '(none)'}`,
118
+ ` requirements ${routine.requirements.map(formatAgentSkillRequirement).join(', ') || '(none)'}`,
107
119
  readiness.missing.length > 0 ? ` missing: ${readiness.missing.map(formatAgentSkillRequirement).join(', ')}` : '',
108
- ` review: ${routine.reviewState}`,
109
- ` source: ${routine.source}`,
110
- ` provenance: ${routine.provenance}`,
120
+ ` review ${formatAgentRecordReviewState(routine.reviewState)}`,
121
+ ` origin ${formatAgentRecordOrigin(routine.source, routine.provenance)}`,
111
122
  ` tags: ${routine.tags.join(', ') || '(none)'}`,
112
123
  ` 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}` : '',
124
+ ` started ${routine.startCount}${routine.lastStartedAt ? `; last ${routine.lastStartedAt}` : ''}`,
125
+ ` created ${routine.createdAt}`,
126
+ ` updated ${routine.updatedAt}`,
127
+ routine.staleReason ? ` stale reason ${routine.staleReason}` : '',
117
128
  '',
118
129
  routine.description,
119
130
  '',
@@ -123,7 +134,7 @@ function renderRoutine(routine: AgentRoutineRecord): string {
123
134
 
124
135
  function summarizeDiscoveredRoutine(routine: DiscoveredRoutineRecord): string {
125
136
  const description = routine.description ? ` - ${routine.description}` : '';
126
- return ` ${routine.name} ${routine.origin}${description}\n path: ${routine.path}`;
137
+ return ` ${routine.name} ${routine.origin}${description}\n path ${routine.path}`;
127
138
  }
128
139
 
129
140
  function renderDiscoveredRoutines(routines: readonly DiscoveredRoutineRecord[]): string {
@@ -169,7 +180,10 @@ function frontmatterAnyList(routine: DiscoveredRoutineRecord, keys: readonly str
169
180
  }
170
181
 
171
182
  function printError(ctx: CommandContext, error: unknown): void {
172
- ctx.print(`Error: ${error instanceof Error ? error.message : String(error)}`);
183
+ ctx.print([
184
+ 'Error',
185
+ ` message ${error instanceof Error ? error.message : String(error)}`,
186
+ ].join('\n'));
173
187
  }
174
188
 
175
189
  async function importDiscoveredRoutine(args: readonly string[], ctx: CommandContext, routineRegistry: AgentRoutineRegistry): Promise<void> {
@@ -181,18 +195,18 @@ async function importDiscoveredRoutine(args: readonly string[], ctx: CommandCont
181
195
  }
182
196
  const discovered = findDiscoveredRoutine(await discoverRoutines(requireShellPaths(ctx)), name);
183
197
  if (!discovered) {
184
- ctx.print(`Unknown discovered Agent routine: ${name}\nRun /routines discover to inspect available routine files.`);
198
+ ctx.print(`Unknown discovered Agent routine ${name}\nRun /routines discover to inspect available routine files.`);
185
199
  return;
186
200
  }
187
201
  if (!parsed.yes) {
188
202
  ctx.print([
189
203
  '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',
204
+ ` name ${discovered.name}`,
205
+ ` origin ${discovered.origin}`,
206
+ ` path ${discovered.path}`,
207
+ ` description ${discovered.description || '(none)'}`,
208
+ ` steps characters ${discovered.steps.length}`,
209
+ ' next rerun with --yes to import into the Agent-local routine registry',
196
210
  ].join('\n'));
197
211
  return;
198
212
  }
@@ -210,7 +224,7 @@ async function importDiscoveredRoutine(args: readonly string[], ctx: CommandCont
210
224
  source: 'imported',
211
225
  provenance: `discovered:${discovered.origin}:${discovered.path}`,
212
226
  });
213
- ctx.print(`Imported Agent routine ${routine.id}: ${routine.name}${routine.enabled ? ' (enabled)' : ''}`);
227
+ ctx.print(formatRoutineReceipt('Imported Agent routine', routine, [` enabled ${routine.enabled ? 'yes' : 'no'}`]));
214
228
  }
215
229
 
216
230
  async function promoteRoutine(args: readonly string[], routineRegistry: AgentRoutineRegistry, ctx: CommandContext): Promise<void> {
@@ -233,8 +247,8 @@ async function promoteRoutine(args: readonly string[], routineRegistry: AgentRou
233
247
  return;
234
248
  }
235
249
  const shellPaths = requireShellPaths(ctx);
236
- const connection = resolveAgentDaemonConnection(ctx.platform.configManager, shellPaths.homeDirectory);
237
- const result = await promoteRoutineToDaemonSchedule(connection, preview);
250
+ const connection = resolveAgentConnectedHostConnection(ctx.platform.configManager, shellPaths.homeDirectory);
251
+ const result = await promoteRoutineToConnectedSchedule(connection, preview);
238
252
  const receipt = receiptStoreFromContext(ctx).append(connection, preview, result);
239
253
  ctx.print(result.ok ? `${formatRoutineScheduleSuccess(result)}\n receipt: ${receipt.id}` : `${formatRoutineScheduleFailure(result)}\n receipt: ${receipt.id}`);
240
254
  }
@@ -254,7 +268,7 @@ export async function runRoutinesRuntimeCommand(args: readonly string[], ctx: Co
254
268
  }
255
269
  if (sub === 'attention' || sub === 'needs-setup') {
256
270
  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.'));
271
+ ctx.print(renderList('Agent Routines needing setup', routineRegistry, routines, 'No Agent-local routines need setup.'));
258
272
  return;
259
273
  }
260
274
  if (sub === 'discover' || sub === 'discovered') {
@@ -286,7 +300,7 @@ export async function runRoutinesRuntimeCommand(args: readonly string[], ctx: Co
286
300
  }
287
301
  if (sub === 'reconcile' || sub === 'sync' || sub === 'status') {
288
302
  const shellPaths = requireShellPaths(ctx);
289
- const connection = resolveAgentDaemonConnection(ctx.platform.configManager, shellPaths.homeDirectory);
303
+ const connection = resolveAgentConnectedHostConnection(ctx.platform.configManager, shellPaths.homeDirectory);
290
304
  const result = await reconcileRoutineScheduleReceipts(connection, receiptStoreFromContext(ctx).snapshot());
291
305
  ctx.print(formatRoutineScheduleCorrelation(result));
292
306
  return;
@@ -298,7 +312,7 @@ export async function runRoutinesRuntimeCommand(args: readonly string[], ctx: Co
298
312
  return;
299
313
  }
300
314
  const receipt = receiptStoreFromContext(ctx).get(id);
301
- ctx.print(receipt ? formatRoutineScheduleReceipt(receipt) : `Unknown routine schedule receipt: ${id}`);
315
+ ctx.print(receipt ? formatRoutineScheduleReceipt(receipt) : `Unknown routine schedule receipt ${id}`);
302
316
  return;
303
317
  }
304
318
  if (sub === 'create') {
@@ -316,9 +330,9 @@ export async function runRoutinesRuntimeCommand(args: readonly string[], ctx: Co
316
330
  }),
317
331
  enabled: parsed.flags.get('enabled') === 'true',
318
332
  source: 'user',
319
- provenance: 'slash-command',
333
+ provenance: 'Command',
320
334
  });
321
- ctx.print(`Created Agent routine ${routine.id}: ${routine.name}`);
335
+ ctx.print(formatRoutineReceipt('Created Agent routine', routine));
322
336
  return;
323
337
  }
324
338
  if (sub === 'update') {
@@ -340,9 +354,9 @@ export async function runRoutinesRuntimeCommand(args: readonly string[], ctx: Co
340
354
  commands: splitList(parsed.flags.get('requires-command') ?? parsed.flags.get('requires-commands')),
341
355
  })
342
356
  : undefined,
343
- provenance: 'slash-command',
357
+ provenance: 'Command',
344
358
  });
345
- ctx.print(`Updated Agent routine ${updated.id}: ${updated.name}`);
359
+ ctx.print(formatRoutineReceipt('Updated Agent routine', updated));
346
360
  return;
347
361
  }
348
362
  if (sub === 'enable' || sub === 'disable') {
@@ -352,7 +366,7 @@ export async function runRoutinesRuntimeCommand(args: readonly string[], ctx: Co
352
366
  return;
353
367
  }
354
368
  const routine = routineRegistry.setEnabled(id, sub === 'enable');
355
- ctx.print(`${sub === 'enable' ? 'Enabled' : 'Disabled'} Agent routine ${routine.id}: ${routine.name}`);
369
+ ctx.print(formatRoutineReceipt(`${sub === 'enable' ? 'Enabled' : 'Disabled'} Agent routine`, routine));
356
370
  return;
357
371
  }
358
372
  if (sub === 'start' || sub === 'run') {
@@ -364,9 +378,11 @@ export async function runRoutinesRuntimeCommand(args: readonly string[], ctx: Co
364
378
  const routine = routineRegistry.markStarted(id);
365
379
  const readiness = evaluateAgentRoutineReadiness(routine);
366
380
  ctx.print([
367
- `Started Agent routine ${routine.id}: ${routine.name}`,
381
+ `Started Agent routine ${routine.id}`,
382
+ ` id ${routine.id}`,
383
+ ` name ${routine.name}`,
368
384
  ` 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',
385
+ ' policy same main conversation; no hidden job, runtime mutation, or external side effect was started',
370
386
  '',
371
387
  routine.steps,
372
388
  ].join('\n'));
@@ -379,7 +395,7 @@ export async function runRoutinesRuntimeCommand(args: readonly string[], ctx: Co
379
395
  return;
380
396
  }
381
397
  const routine = routineRegistry.markReviewed(id);
382
- ctx.print(`Reviewed Agent routine ${routine.id}.`);
398
+ ctx.print(formatRoutineReceipt('Reviewed Agent routine', routine));
383
399
  return;
384
400
  }
385
401
  if (sub === 'stale') {
@@ -389,7 +405,7 @@ export async function runRoutinesRuntimeCommand(args: readonly string[], ctx: Co
389
405
  return;
390
406
  }
391
407
  const routine = routineRegistry.markStale(id, args.slice(2).join(' '));
392
- ctx.print(`Marked Agent routine ${routine.id} stale.`);
408
+ ctx.print(formatRoutineReceipt('Marked Agent routine stale', routine));
393
409
  return;
394
410
  }
395
411
  if (sub === 'promote' || sub === 'schedule' || sub === 'promote-schedule') {
@@ -408,7 +424,7 @@ export async function runRoutinesRuntimeCommand(args: readonly string[], ctx: Co
408
424
  return;
409
425
  }
410
426
  const removed = routineRegistry.deleteRoutine(id);
411
- ctx.print(`Deleted Agent routine ${removed.id}: ${removed.name}`);
427
+ ctx.print(formatRoutineReceipt('Deleted Agent routine', removed));
412
428
  return;
413
429
  }
414
430
  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 +437,7 @@ export function registerRoutinesRuntimeCommands(registry: CommandRegistry): void
421
437
  registry.register({
422
438
  name: 'routines',
423
439
  aliases: ['routine'],
424
- description: 'Manage local GoodVibes Agent routines',
440
+ description: 'Manage Agent-local routines',
425
441
  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
442
  handler: runRoutinesRuntimeCommand,
427
443
  });