@pellux/goodvibes-agent 0.1.116 → 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 (285) hide show
  1. package/CHANGELOG.md +48 -661
  2. package/README.md +64 -57
  3. package/bin/goodvibes-agent.ts +16 -2
  4. package/dist/package/main.js +199180 -192185
  5. package/docs/README.md +15 -8
  6. package/docs/channels-remote-and-api.md +50 -0
  7. package/docs/connected-host.md +59 -0
  8. package/docs/getting-started.md +61 -50
  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 +48 -11
  13. package/docs/tools-and-commands.md +123 -0
  14. package/docs/voice-and-live-tts.md +51 -0
  15. package/package.json +3 -6
  16. package/src/agent/behavior-discovery-summary.ts +1 -3
  17. package/src/agent/channel-delivery.ts +201 -0
  18. package/src/agent/media-generation.ts +159 -0
  19. package/src/agent/memory-prompt.ts +0 -1
  20. package/src/agent/note-registry.ts +329 -0
  21. package/src/agent/operator-actions.ts +343 -0
  22. package/src/agent/persona-discovery.ts +1 -3
  23. package/src/agent/persona-registry.ts +19 -16
  24. package/src/agent/record-labels.ts +107 -0
  25. package/src/agent/reminder-schedule-format.ts +33 -24
  26. package/src/agent/reminder-schedule.ts +27 -26
  27. package/src/agent/routine-registry.ts +54 -14
  28. package/src/agent/routine-schedule-args.ts +2 -1
  29. package/src/agent/routine-schedule-format.ts +77 -53
  30. package/src/agent/routine-schedule-promotion.ts +35 -33
  31. package/src/agent/routine-schedule-receipts.ts +29 -27
  32. package/src/agent/runtime-profile-starters.ts +5 -5
  33. package/src/agent/runtime-profile.ts +91 -12
  34. package/src/agent/skill-registry.ts +210 -32
  35. package/src/cli/agent-knowledge-args.ts +5 -1
  36. package/src/cli/agent-knowledge-command.ts +40 -34
  37. package/src/cli/agent-knowledge-format.ts +80 -67
  38. package/src/cli/agent-knowledge-methods.ts +1 -1
  39. package/src/cli/agent-knowledge-runtime.ts +32 -26
  40. package/src/cli/bundle-command.ts +14 -9
  41. package/src/cli/config-overrides.ts +37 -36
  42. package/src/cli/entrypoint.ts +16 -7
  43. package/src/cli/external-runtime.ts +10 -4
  44. package/src/cli/help.ts +54 -29
  45. package/src/cli/local-library-command.ts +203 -83
  46. package/src/cli/management-commands.ts +105 -68
  47. package/src/cli/management.ts +55 -74
  48. package/src/cli/memory-command.ts +66 -32
  49. package/src/cli/parser.ts +37 -3
  50. package/src/cli/profiles-command.ts +166 -31
  51. package/src/cli/provider-auth-routes.ts +2 -1
  52. package/src/cli/routines-command.ts +176 -40
  53. package/src/cli/service-posture.ts +16 -16
  54. package/src/cli/status.ts +56 -135
  55. package/src/core/conversation-message-snapshot.ts +131 -0
  56. package/src/input/agent-workspace-access-command-editor-submission.ts +149 -0
  57. package/src/input/agent-workspace-access-command-editors.ts +170 -0
  58. package/src/input/agent-workspace-activation.ts +35 -8
  59. package/src/input/agent-workspace-basic-command-editor-submission.ts +351 -94
  60. package/src/input/agent-workspace-basic-command-editors.ts +502 -9
  61. package/src/input/agent-workspace-categories.ts +423 -51
  62. package/src/input/agent-workspace-channel-command-editor-submission.ts +83 -0
  63. package/src/input/agent-workspace-channel-command-editors.ts +65 -0
  64. package/src/input/agent-workspace-channels.ts +35 -2
  65. package/src/input/agent-workspace-command-editor.ts +41 -3
  66. package/src/input/agent-workspace-config-reader.ts +16 -0
  67. package/src/input/agent-workspace-delegation-editor-submission.ts +55 -0
  68. package/src/input/agent-workspace-editors.ts +166 -1
  69. package/src/input/agent-workspace-knowledge-command-editor-submission.ts +132 -0
  70. package/src/input/agent-workspace-knowledge-command-editors.ts +110 -0
  71. package/src/input/agent-workspace-knowledge-query-editor.ts +1 -1
  72. package/src/input/agent-workspace-learned-behavior.ts +67 -0
  73. package/src/input/agent-workspace-library-command-editor-submission.ts +50 -0
  74. package/src/input/agent-workspace-library-command-editors.ts +35 -0
  75. package/src/input/agent-workspace-local-operations.ts +218 -0
  76. package/src/input/agent-workspace-local-selection.ts +75 -0
  77. package/src/input/agent-workspace-mcp-command-editor-submission.ts +95 -0
  78. package/src/input/agent-workspace-media-command-editor-submission.ts +62 -0
  79. package/src/input/agent-workspace-media-command-editors.ts +27 -0
  80. package/src/input/agent-workspace-memory-command-editor-submission.ts +232 -0
  81. package/src/input/agent-workspace-memory-command-editors.ts +180 -0
  82. package/src/input/agent-workspace-memory-editor.ts +2 -2
  83. package/src/input/agent-workspace-navigation.ts +81 -0
  84. package/src/input/agent-workspace-notify-editor-submission.ts +121 -0
  85. package/src/input/agent-workspace-operations-command-editor-submission.ts +208 -0
  86. package/src/input/agent-workspace-operations-command-editors.ts +196 -0
  87. package/src/input/agent-workspace-panel-route.ts +43 -0
  88. package/src/input/agent-workspace-provider-command-editor-submission.ts +155 -0
  89. package/src/input/agent-workspace-provider-command-editors.ts +93 -0
  90. package/src/input/agent-workspace-reminder-schedule-editor.ts +1 -1
  91. package/src/input/agent-workspace-requirements.ts +11 -0
  92. package/src/input/agent-workspace-routine-schedule-editor.ts +2 -2
  93. package/src/input/agent-workspace-search.ts +169 -0
  94. package/src/input/agent-workspace-secret-editor-submission.ts +153 -0
  95. package/src/input/agent-workspace-session-command-editor-submission.ts +199 -0
  96. package/src/input/agent-workspace-session-command-editors.ts +249 -0
  97. package/src/input/agent-workspace-setup.ts +37 -16
  98. package/src/input/agent-workspace-skill-bundle-command-editor-submission.ts +101 -0
  99. package/src/input/agent-workspace-skill-bundle-command-editors.ts +110 -0
  100. package/src/input/agent-workspace-snapshot.ts +162 -21
  101. package/src/input/agent-workspace-task-command-editor-submission.ts +61 -0
  102. package/src/input/agent-workspace-task-command-editors.ts +47 -0
  103. package/src/input/agent-workspace-token.ts +18 -2
  104. package/src/input/agent-workspace-types.ts +212 -4
  105. package/src/input/agent-workspace-voice-media.ts +4 -7
  106. package/src/input/agent-workspace-web-research-editor.ts +104 -0
  107. package/src/input/agent-workspace-workplan-editor-submission.ts +153 -0
  108. package/src/input/agent-workspace.ts +178 -240
  109. package/src/input/command-registry.ts +5 -2
  110. package/src/input/commands/agent-runtime-profile-runtime.ts +126 -37
  111. package/src/input/commands/agent-skills-runtime.ts +149 -72
  112. package/src/input/commands/agent-workspace-runtime.ts +23 -6
  113. package/src/input/commands/brief-runtime.ts +55 -25
  114. package/src/input/commands/channels-runtime.ts +147 -33
  115. package/src/input/commands/compat-runtime.ts +32 -0
  116. package/src/input/commands/delegation-runtime.ts +29 -23
  117. package/src/input/commands/experience-runtime.ts +6 -4
  118. package/src/input/commands/guidance-runtime.ts +4 -4
  119. package/src/input/commands/health-runtime.ts +149 -126
  120. package/src/input/commands/knowledge.ts +82 -60
  121. package/src/input/commands/local-provider-runtime.ts +43 -21
  122. package/src/input/commands/local-runtime.ts +138 -16
  123. package/src/input/commands/local-setup-review.ts +10 -20
  124. package/src/input/commands/mcp-runtime.ts +63 -46
  125. package/src/input/commands/notify-runtime.ts +38 -9
  126. package/src/input/commands/operator-actions-runtime.ts +138 -0
  127. package/src/input/commands/operator-runtime.ts +6 -76
  128. package/src/input/commands/personas-runtime.ts +46 -31
  129. package/src/input/commands/planning-runtime.ts +1 -1
  130. package/src/input/commands/platform-access-runtime.ts +35 -98
  131. package/src/input/commands/product-runtime.ts +2 -2
  132. package/src/input/commands/provider-accounts-runtime.ts +60 -39
  133. package/src/input/commands/qrcode-runtime.ts +50 -9
  134. package/src/input/commands/recall-bundle.ts +11 -11
  135. package/src/input/commands/recall-capture.ts +13 -11
  136. package/src/input/commands/recall-query.ts +29 -21
  137. package/src/input/commands/recall-review.ts +2 -1
  138. package/src/input/commands/routines-runtime.ts +99 -45
  139. package/src/input/commands/runtime-services.ts +1 -14
  140. package/src/input/commands/schedule-runtime.ts +33 -20
  141. package/src/input/commands/security-runtime.ts +6 -11
  142. package/src/input/commands/session-content.ts +80 -78
  143. package/src/input/commands/session-workflow.ts +134 -104
  144. package/src/input/commands/session.ts +3 -174
  145. package/src/input/commands/shell-core.ts +38 -17
  146. package/src/input/commands/subscription-runtime.ts +54 -185
  147. package/src/input/commands/support-bundle-runtime.ts +53 -0
  148. package/src/input/commands/tasks-runtime.ts +21 -21
  149. package/src/input/commands/work-plan-runtime.ts +33 -8
  150. package/src/input/commands.ts +6 -2
  151. package/src/input/feed-context-factory.ts +2 -2
  152. package/src/input/file-picker.ts +3 -2
  153. package/src/input/handler-command-route.ts +4 -7
  154. package/src/input/handler-content-actions.ts +89 -26
  155. package/src/input/handler-feed-routes.ts +19 -12
  156. package/src/input/handler-feed.ts +6 -5
  157. package/src/input/handler-interactions.ts +9 -36
  158. package/src/input/handler-modal-stack.ts +3 -3
  159. package/src/input/handler-onboarding.ts +52 -91
  160. package/src/input/handler-shortcuts.ts +16 -7
  161. package/src/input/handler.ts +50 -23
  162. package/src/input/input-history.ts +5 -6
  163. package/src/input/keybindings.ts +27 -16
  164. package/src/input/mcp-workspace.ts +90 -26
  165. package/src/input/onboarding/handler-onboarding-routes.ts +3 -1
  166. package/src/input/onboarding/onboarding-wizard-apply.ts +62 -0
  167. package/src/input/onboarding/onboarding-wizard-constants.ts +1 -0
  168. package/src/input/onboarding/onboarding-wizard-helpers.ts +1 -1
  169. package/src/input/onboarding/onboarding-wizard-operator-steps.ts +223 -55
  170. package/src/input/onboarding/onboarding-wizard-steps.ts +59 -35
  171. package/src/input/onboarding/onboarding-wizard-types.ts +4 -1
  172. package/src/input/onboarding/onboarding-wizard.ts +87 -2
  173. package/src/input/profile-picker-modal.ts +31 -12
  174. package/src/input/session-picker-modal.ts +21 -4
  175. package/src/input/settings-modal-agent-policy.ts +6 -6
  176. package/src/input/settings-modal-behavior.ts +0 -3
  177. package/src/input/settings-modal-subscriptions.ts +3 -3
  178. package/src/input/settings-modal-types.ts +2 -13
  179. package/src/input/settings-modal.ts +20 -66
  180. package/src/input/submission-intent.ts +0 -1
  181. package/src/input/submission-router.ts +3 -3
  182. package/src/main.ts +18 -10
  183. package/src/panels/approval-panel.ts +8 -8
  184. package/src/panels/automation-control-panel.ts +4 -4
  185. package/src/panels/base-panel.ts +1 -1
  186. package/src/panels/builtin/agent.ts +1 -1
  187. package/src/panels/builtin/operations.ts +3 -12
  188. package/src/panels/builtin/session.ts +32 -24
  189. package/src/panels/builtin/shared.ts +7 -7
  190. package/src/panels/cost-tracker-panel.ts +1 -1
  191. package/src/panels/docs-panel.ts +5 -3
  192. package/src/panels/index.ts +0 -1
  193. package/src/panels/knowledge-panel.ts +6 -5
  194. package/src/panels/memory-panel.ts +7 -6
  195. package/src/panels/panel-list-panel.ts +36 -80
  196. package/src/panels/project-planning-panel.ts +19 -12
  197. package/src/panels/provider-account-snapshot.ts +51 -25
  198. package/src/panels/provider-accounts-panel.ts +33 -18
  199. package/src/panels/provider-health-domains.ts +48 -7
  200. package/src/panels/provider-health-panel.ts +5 -4
  201. package/src/panels/qr-panel.ts +44 -20
  202. package/src/panels/schedule-panel.ts +9 -17
  203. package/src/panels/security-panel.ts +8 -8
  204. package/src/panels/session-browser-panel.ts +10 -10
  205. package/src/panels/subscription-panel.ts +6 -6
  206. package/src/panels/system-messages-panel.ts +3 -3
  207. package/src/panels/tasks-panel.ts +21 -14
  208. package/src/panels/tool-inspector-panel.ts +19 -12
  209. package/src/panels/work-plan-panel.ts +5 -5
  210. package/src/planning/project-planning-coordinator.ts +3 -3
  211. package/src/provider-auth-route-display.ts +9 -0
  212. package/src/renderer/agent-workspace-style.ts +34 -0
  213. package/src/renderer/agent-workspace.ts +254 -57
  214. package/src/renderer/autocomplete-overlay.ts +25 -6
  215. package/src/renderer/block-actions.ts +1 -3
  216. package/src/renderer/bookmark-modal.ts +19 -4
  217. package/src/renderer/buffer.ts +4 -2
  218. package/src/renderer/context-inspector.ts +50 -13
  219. package/src/renderer/diff.ts +1 -1
  220. package/src/renderer/file-picker-overlay.ts +19 -6
  221. package/src/renderer/help-overlay.ts +112 -34
  222. package/src/renderer/history-search-overlay.ts +19 -4
  223. package/src/renderer/live-tail-modal.ts +27 -5
  224. package/src/renderer/mcp-workspace.ts +176 -43
  225. package/src/renderer/model-picker-overlay.ts +58 -3
  226. package/src/renderer/model-workspace.ts +104 -22
  227. package/src/renderer/onboarding/onboarding-wizard.ts +20 -4
  228. package/src/renderer/process-modal.ts +27 -6
  229. package/src/renderer/profile-picker-modal.ts +21 -5
  230. package/src/renderer/search-overlay.ts +25 -5
  231. package/src/renderer/selection-modal-overlay.ts +46 -14
  232. package/src/renderer/session-picker-modal.ts +18 -1
  233. package/src/renderer/settings-modal-helpers.ts +2 -40
  234. package/src/renderer/settings-modal.ts +88 -55
  235. package/src/renderer/system-message.ts +1 -1
  236. package/src/renderer/tool-call.ts +20 -11
  237. package/src/runtime/agent-runtime-events.ts +129 -0
  238. package/src/runtime/bootstrap-command-context.ts +7 -1
  239. package/src/runtime/bootstrap-command-parts.ts +11 -8
  240. package/src/runtime/bootstrap-core.ts +23 -65
  241. package/src/runtime/bootstrap-hook-bridge.ts +7 -18
  242. package/src/runtime/bootstrap-shell.ts +46 -8
  243. package/src/runtime/bootstrap.ts +36 -46
  244. package/src/runtime/connected-host-auth.ts +47 -0
  245. package/src/runtime/diagnostics/panels/index.ts +2 -2
  246. package/src/runtime/diagnostics/panels/panel-resources.ts +1 -1
  247. package/src/runtime/diagnostics/panels/policy.ts +7 -7
  248. package/src/runtime/index.ts +2 -5
  249. package/src/runtime/onboarding/apply-file-helpers.ts +66 -0
  250. package/src/runtime/onboarding/apply.ts +288 -74
  251. package/src/runtime/onboarding/derivation.ts +10 -13
  252. package/src/runtime/onboarding/snapshot.ts +2 -17
  253. package/src/runtime/onboarding/types.ts +34 -20
  254. package/src/runtime/onboarding/verify.ts +105 -4
  255. package/src/runtime/operator-token-cleanup.ts +3 -3
  256. package/src/runtime/services.ts +95 -11
  257. package/src/runtime/store/selectors/index.ts +3 -3
  258. package/src/runtime/store/state.ts +1 -4
  259. package/src/runtime/surface-feature-flags.ts +41 -6
  260. package/src/runtime/ui-read-models.ts +3 -4
  261. package/src/runtime/ui-services.ts +6 -6
  262. package/src/shell/blocking-input.ts +2 -1
  263. package/src/shell/service-settings-sync.ts +7 -7
  264. package/src/shell/ui-openers.ts +17 -38
  265. package/src/tools/agent-analysis-registry-policy.ts +0 -1
  266. package/src/tools/agent-channel-send-tool.ts +133 -0
  267. package/src/tools/agent-context-policy.ts +1 -1
  268. package/src/tools/agent-knowledge-ingest-tool.ts +405 -0
  269. package/src/tools/agent-knowledge-tool.ts +170 -0
  270. package/src/tools/agent-local-registry-tool.ts +279 -73
  271. package/src/tools/agent-media-generate-tool.ts +133 -0
  272. package/src/tools/agent-notify-tool.ts +143 -0
  273. package/src/tools/agent-operator-action-tool.ts +137 -0
  274. package/src/tools/agent-operator-briefing-tool.ts +217 -0
  275. package/src/tools/agent-reminder-schedule-tool.ts +237 -0
  276. package/src/tools/agent-tool-policy-guard.ts +13 -15
  277. package/src/tools/agent-work-plan-tool.ts +256 -0
  278. package/src/version.ts +1 -1
  279. package/docs/connected-services.md +0 -51
  280. package/src/cli/package-verification.ts +0 -274
  281. package/src/input/commands/policy-dispatch.ts +0 -339
  282. package/src/input/commands/policy.ts +0 -17
  283. package/src/panels/panel-picker.ts +0 -105
  284. package/src/panels/policy-panel.ts +0 -308
  285. package/src/renderer/panel-picker-overlay.ts +0 -202
@@ -97,7 +97,6 @@ export const restoreRuntimeModel = bootstrap.restoreRuntimeModel;
97
97
  export const restoreSavedModel = bootstrap.restoreRuntimeModel;
98
98
  export const synchronizeConfiguredServices = bootstrap.synchronizeConfiguredServices;
99
99
  export const syncConfiguredServices = bootstrap.synchronizeConfiguredServices;
100
- export const registerBootstrapRuntimeEvents = bootstrap.registerBootstrapRuntimeEvents;
101
100
  export const registerHostRuntimeEvents = bootstrap.registerHostRuntimeEvents;
102
101
  function agentExternalHostStatus(
103
102
  config: Bootstrap.HostServicesConfig,
@@ -113,7 +112,7 @@ function agentExternalHostStatus(
113
112
  port,
114
113
  baseUrl: `http://${host}:${port}`,
115
114
  reason: service === 'daemon'
116
- ? 'GoodVibes Agent connects to GoodVibes services owned outside this product and does not start or restart them.'
115
+ ? 'GoodVibes Agent connects to a GoodVibes host owned outside this product and does not start or restart it.'
117
116
  : 'GoodVibes Agent does not own listener lifecycle.',
118
117
  };
119
118
  }
@@ -245,7 +244,6 @@ export type RemoteRuntimeEvents = Transport.RemoteRuntimeEvents;
245
244
  export type SerializedRuntimeEnvelope = Transport.SerializedRuntimeEnvelope;
246
245
 
247
246
  // Operations compatibility aliases.
248
- export const AcpTaskAdapter = operations.AcpTaskAdapter;
249
247
  export const OpsControlPlane = operations.OpsControlPlane;
250
248
  export const OpsIllegalActionError = operations.OpsIllegalActionError;
251
249
  export const OpsTargetNotFoundError = operations.OpsTargetNotFoundError;
@@ -436,10 +434,10 @@ export const uninstallEcosystemCatalogEntry = shell.uninstallEcosystemCatalogEnt
436
434
  export const updateInstalledEcosystemEntry = shell.updateInstalledEcosystemEntry;
437
435
  export const upsertEcosystemCatalogEntry = shell.upsertEcosystemCatalogEntry;
438
436
  export const summarizeWorktreeOwnership = shell.summarizeWorktreeOwnership;
439
- export const WorktreeRegistry = shell.WorktreeRegistry;
440
437
  export const listPersistedWorktreeMeta = shell.listPersistedWorktreeMeta;
441
438
  export const getPersistedWorktreeMeta = shell.getPersistedWorktreeMeta;
442
439
  export const reviewWorktreeAttachments = shell.reviewWorktreeAttachments;
440
+ export const WorktreeRegistry = shell.WorktreeRegistry;
443
441
 
444
442
  export type MutableRuntimeState = Shell.MutableRuntimeState;
445
443
  export type ProviderAccountRecord = Shell.ProviderAccountRecord;
@@ -458,7 +456,6 @@ export type WorktreeRegistry = Shell.WorktreeRegistry;
458
456
  export type WorktreeStatusRecord = Shell.WorktreeStatusRecord;
459
457
  export type ManagedWorktreeMeta = Shell.ManagedWorktreeMeta;
460
458
  export type ShellAgentManagerService = Shell.ShellAgentManagerService;
461
- export type ShellAcpManagerService = Shell.ShellAcpManagerService;
462
459
  export type ShellAutomationManagerService = Shell.ShellAutomationManagerService;
463
460
  export type ShellAutomationManagerRuntimeService = Shell.ShellAutomationManagerRuntimeService;
464
461
  export type ShellModeManagerService = Shell.ShellModeManagerService;
@@ -0,0 +1,66 @@
1
+ import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs';
2
+ import { dirname } from 'node:path';
3
+
4
+ export type RollbackAction = () => Promise<void> | void;
5
+
6
+ export function isPlainObject(value: unknown): value is Record<string, unknown> {
7
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
8
+ }
9
+
10
+ export function readJsonObject(path: string): Record<string, unknown> {
11
+ if (!existsSync(path)) return {};
12
+ const parsed = JSON.parse(readFileSync(path, 'utf-8')) as unknown;
13
+ if (!isPlainObject(parsed)) throw new Error(`Expected an object JSON payload at ${path}.`);
14
+ return parsed;
15
+ }
16
+
17
+ export function writeJsonObject(path: string, payload: Record<string, unknown>): void {
18
+ mkdirSync(dirname(path), { recursive: true });
19
+ writeFileSync(path, `${JSON.stringify(payload, null, 2)}\n`, 'utf-8');
20
+ }
21
+
22
+ export function setNestedValue(root: Record<string, unknown>, key: string, value: unknown): Record<string, unknown> {
23
+ const parts = key.split('.');
24
+ const next = structuredClone(root);
25
+ let cursor: Record<string, unknown> = next;
26
+
27
+ for (let index = 0; index < parts.length - 1; index += 1) {
28
+ const part = parts[index]!;
29
+ let existing = cursor[part];
30
+ if (!isPlainObject(existing)) {
31
+ existing = {};
32
+ cursor[part] = existing;
33
+ }
34
+ cursor = existing as Record<string, unknown>;
35
+ }
36
+
37
+ cursor[parts[parts.length - 1]!] = structuredClone(value);
38
+ return next;
39
+ }
40
+
41
+ export function restoreFile(path: string, previous: string | null, reload?: () => void): void {
42
+ if (previous === null) {
43
+ if (existsSync(path)) unlinkSync(path);
44
+ } else {
45
+ mkdirSync(dirname(path), { recursive: true });
46
+ writeFileSync(path, previous, 'utf-8');
47
+ }
48
+ reload?.();
49
+ }
50
+
51
+ export function snapshotFileRollback(path: string, reload?: () => void): RollbackAction {
52
+ const previous = existsSync(path) ? readFileSync(path, 'utf-8') : null;
53
+ return () => restoreFile(path, previous, reload);
54
+ }
55
+
56
+ export async function runRollbacks(rollbacks: readonly RollbackAction[]): Promise<readonly string[]> {
57
+ const errors: string[] = [];
58
+ for (const rollback of [...rollbacks].reverse()) {
59
+ try {
60
+ await rollback();
61
+ } catch (error) {
62
+ errors.push(error instanceof Error ? error.message : String(error));
63
+ }
64
+ }
65
+ return errors;
66
+ }
@@ -1,13 +1,24 @@
1
- import { existsSync, mkdirSync, readFileSync, rmSync, unlinkSync, writeFileSync } from 'node:fs';
2
- import { dirname } from 'node:path';
1
+ import { existsSync, readFileSync, rmSync } from 'node:fs';
3
2
  import { isSecretRefInput } from '@pellux/goodvibes-sdk/platform/config';
4
3
  import { CONFIG_SCHEMA, DEFAULT_CONFIG } from '../../config/index.ts';
5
4
  import {
6
5
  createAgentRuntimeProfile,
7
6
  getAgentRuntimeProfileTemplate,
7
+ getAgentRuntimeProfileSelectionPath,
8
+ readAgentRuntimeProfileSelection,
8
9
  resolveAgentRuntimeProfileHome,
10
+ setAgentRuntimeProfileSelection,
9
11
  } from '../../agent/runtime-profile.ts';
10
- import type { FeatureFlagConfigKey } from '../surface-feature-flags.ts';
12
+ import { AgentNoteRegistry } from '../../agent/note-registry.ts';
13
+ import { AgentPersonaRegistry, assertNoSecretLikeText } from '../../agent/persona-registry.ts';
14
+ import { AgentRoutineRegistry } from '../../agent/routine-registry.ts';
15
+ import { AgentSkillRegistry } from '../../agent/skill-registry.ts';
16
+ import {
17
+ isFeatureFlagConfigKey,
18
+ mergeFeatureFlagConfigValue,
19
+ readFeatureFlagConfigValue,
20
+ type FeatureFlagConfigKey,
21
+ } from '../surface-feature-flags.ts';
11
22
  import {
12
23
  getOnboardingRuntimeStatePath,
13
24
  readOnboardingRuntimeState,
@@ -23,72 +34,12 @@ import type {
23
34
  OnboardingApplyRequest,
24
35
  OnboardingApplyResult,
25
36
  } from './types.ts';
37
+ import { isPlainObject, readJsonObject, restoreFile, runRollbacks, setNestedValue, snapshotFileRollback, writeJsonObject, type RollbackAction } from './apply-file-helpers.ts';
26
38
 
27
39
  function getNow(deps: Pick<OnboardingApplyDependencies, 'clock'>): number {
28
40
  return deps.clock?.() ?? Date.now();
29
41
  }
30
42
 
31
- function isPlainObject(value: unknown): value is Record<string, unknown> {
32
- return typeof value === 'object' && value !== null && !Array.isArray(value);
33
- }
34
-
35
- function readJsonObject(path: string): Record<string, unknown> {
36
- if (!existsSync(path)) return {};
37
- const parsed = JSON.parse(readFileSync(path, 'utf-8')) as unknown;
38
- if (!isPlainObject(parsed)) throw new Error(`Expected an object JSON payload at ${path}.`);
39
- return parsed;
40
- }
41
-
42
- function writeJsonObject(path: string, payload: Record<string, unknown>): void {
43
- mkdirSync(dirname(path), { recursive: true });
44
- writeFileSync(path, `${JSON.stringify(payload, null, 2)}\n`, 'utf-8');
45
- }
46
-
47
- function setNestedValue(root: Record<string, unknown>, key: string, value: unknown): Record<string, unknown> {
48
- const parts = key.split('.');
49
- const next = structuredClone(root);
50
- let cursor: Record<string, unknown> = next;
51
-
52
- for (let index = 0; index < parts.length - 1; index += 1) {
53
- const part = parts[index]!;
54
- const existing = cursor[part];
55
- if (!isPlainObject(existing)) cursor[part] = {};
56
- cursor = cursor[part] as Record<string, unknown>;
57
- }
58
-
59
- cursor[parts[parts.length - 1]!] = structuredClone(value);
60
- return next;
61
- }
62
-
63
- type RollbackAction = () => Promise<void> | void;
64
-
65
- function restoreFile(path: string, previous: string | null, reload?: () => void): void {
66
- if (previous === null) {
67
- if (existsSync(path)) unlinkSync(path);
68
- } else {
69
- mkdirSync(dirname(path), { recursive: true });
70
- writeFileSync(path, previous, 'utf-8');
71
- }
72
- reload?.();
73
- }
74
-
75
- function snapshotFileRollback(path: string, reload?: () => void): RollbackAction {
76
- const previous = existsSync(path) ? readFileSync(path, 'utf-8') : null;
77
- return () => restoreFile(path, previous, reload);
78
- }
79
-
80
- async function runRollbacks(rollbacks: readonly RollbackAction[]): Promise<readonly string[]> {
81
- const errors: string[] = [];
82
- for (const rollback of [...rollbacks].reverse()) {
83
- try {
84
- await rollback();
85
- } catch (error) {
86
- errors.push(error instanceof Error ? error.message : String(error));
87
- }
88
- }
89
- return errors;
90
- }
91
-
92
43
  function isGoodVibesSecretReferenceValue(value: string): boolean {
93
44
  const normalized = value.trim();
94
45
  return normalized.startsWith('goodvibes://secrets/') && isSecretRefInput(normalized);
@@ -99,10 +50,6 @@ function isMalformedGoodVibesSecretReferenceValue(value: string): boolean {
99
50
  return normalized.startsWith('goodvibes://') && !isGoodVibesSecretReferenceValue(normalized);
100
51
  }
101
52
 
102
- function isFeatureFlagConfigKey(key: string): key is FeatureFlagConfigKey {
103
- return key === 'featureFlags' || key.startsWith('featureFlags.');
104
- }
105
-
106
53
  function validateFeatureFlagConfigValue(operation: Extract<OnboardingApplyOperation, { kind: 'set-config' }>): boolean {
107
54
  if (!isFeatureFlagConfigKey(operation.key)) return false;
108
55
 
@@ -137,7 +84,7 @@ function validateConfigValue(operation: Extract<OnboardingApplyOperation, { kind
137
84
  const defaultValue = operation.key.split('.').reduce<unknown>((cursor, part) => (
138
85
  isPlainObject(cursor) ? cursor[part] : undefined
139
86
  ), DEFAULT_CONFIG);
140
- if (defaultValue === undefined) throw new Error(`Unknown config key: ${operation.key}`);
87
+ if (defaultValue === undefined) throw new Error(`Unknown config key ${operation.key}`);
141
88
  if (typeof defaultValue === 'boolean' && typeof operation.value !== 'boolean') {
142
89
  throw new Error(`Config key ${operation.key} expects a boolean value.`);
143
90
  }
@@ -164,11 +111,11 @@ function validateConfigValue(operation: Extract<OnboardingApplyOperation, { kind
164
111
  }
165
112
 
166
113
  if (schema.type === 'enum' && schema.enumValues && stringValue !== null && !schema.enumValues.includes(stringValue)) {
167
- throw new Error(`Invalid value for ${operation.key}: ${String(operation.value)}.`);
114
+ throw new Error(`Invalid value for ${operation.key} ${String(operation.value)}.`);
168
115
  }
169
116
 
170
117
  if (schema.validate && !schema.validate(operation.value)) {
171
- throw new Error(`Invalid value for ${operation.key}: ${String(operation.value)}.`);
118
+ throw new Error(`Invalid value for ${operation.key} ${String(operation.value)}.`);
172
119
  }
173
120
  }
174
121
 
@@ -222,6 +169,80 @@ function validateCreateAgentProfileOperation(
222
169
  if (templateId) getAgentRuntimeProfileTemplate(templateId, deps.shellPaths.homeDirectory);
223
170
  }
224
171
 
172
+ function validateSelectAgentProfileOperation(
173
+ deps: OnboardingApplyDependencies,
174
+ operation: Extract<OnboardingApplyOperation, { kind: 'select-agent-profile' }>,
175
+ ): void {
176
+ const name = operation.name.trim();
177
+ if (name.length === 0) throw new Error('Agent profile name is required.');
178
+ const resolution = resolveAgentRuntimeProfileHome(deps.shellPaths.homeDirectory, name);
179
+ if (!existsSync(resolution.homeDirectory)) {
180
+ throw new Error(`Agent profile does not exist: ${resolution.id}`);
181
+ }
182
+ }
183
+
184
+ function validateCreateLocalPersonaOperation(
185
+ deps: OnboardingApplyDependencies,
186
+ operation: Extract<OnboardingApplyOperation, { kind: 'create-local-persona' }>,
187
+ ): void {
188
+ const name = operation.name.trim();
189
+ const description = operation.description.trim();
190
+ const body = operation.body.trim();
191
+ if (!name) throw new Error('Persona name is required.');
192
+ if (!description) throw new Error('Persona description is required.');
193
+ if (!body) throw new Error('Persona body is required.');
194
+ assertNoSecretLikeText([name, description, body]);
195
+ const duplicate = AgentPersonaRegistry.fromShellPaths(deps.shellPaths).get(name);
196
+ if (duplicate) throw new Error(`Persona already exists: ${duplicate.id}`);
197
+ }
198
+
199
+ function validateCreateLocalSkillOperation(
200
+ deps: OnboardingApplyDependencies,
201
+ operation: Extract<OnboardingApplyOperation, { kind: 'create-local-skill' }>,
202
+ ): void {
203
+ const registry = AgentSkillRegistry.fromShellPaths(deps.shellPaths);
204
+ const name = operation.name.trim();
205
+ const description = operation.description.trim();
206
+ const procedure = operation.procedure.trim();
207
+ if (!name) throw new Error('Skill name is required.');
208
+ if (!description) throw new Error('Skill description is required.');
209
+ if (!procedure) throw new Error('Skill procedure is required.');
210
+ assertNoSecretLikeText([name, description, procedure]);
211
+ const duplicate = registry.get(name);
212
+ if (duplicate) throw new Error(`Skill already exists: ${duplicate.id}`);
213
+ }
214
+
215
+ function validateCreateLocalRoutineOperation(
216
+ deps: OnboardingApplyDependencies,
217
+ operation: Extract<OnboardingApplyOperation, { kind: 'create-local-routine' }>,
218
+ ): void {
219
+ const registry = AgentRoutineRegistry.fromShellPaths(deps.shellPaths);
220
+ const name = operation.name.trim();
221
+ const description = operation.description.trim();
222
+ const steps = operation.steps.trim();
223
+ if (!name) throw new Error('Routine name is required.');
224
+ if (!description) throw new Error('Routine description is required.');
225
+ if (!steps) throw new Error('Routine steps are required.');
226
+ assertNoSecretLikeText([name, description, steps]);
227
+ const duplicate = registry.get(name);
228
+ if (duplicate) throw new Error(`Routine already exists: ${duplicate.id}`);
229
+ }
230
+
231
+ function validateCreateLocalNoteOperation(
232
+ deps: OnboardingApplyDependencies,
233
+ operation: Extract<OnboardingApplyOperation, { kind: 'create-local-note' }>,
234
+ ): void {
235
+ const registry = AgentNoteRegistry.fromShellPaths(deps.shellPaths);
236
+ const title = operation.title.trim();
237
+ const body = operation.body.trim();
238
+ const tags = operation.tags ?? [];
239
+ if (!title) throw new Error('Note title is required.');
240
+ if (!body) throw new Error('Note body is required.');
241
+ assertNoSecretLikeText([title, body, ...tags]);
242
+ const duplicate = registry.get(title);
243
+ if (duplicate) throw new Error(`Note already exists: ${duplicate.id}`);
244
+ }
245
+
225
246
  function applyConfigOperation(
226
247
  deps: OnboardingApplyDependencies,
227
248
  operation: Extract<OnboardingApplyOperation, { kind: 'set-config' }>,
@@ -241,7 +262,11 @@ function applyConfigOperation(
241
262
  };
242
263
  }
243
264
 
244
- deps.config.setDynamic(operation.key as never, operation.value);
265
+ if (isFeatureFlagConfigKey(operation.key)) {
266
+ mergeFeatureFlagConfigValue(deps.config, operation.key, operation.value);
267
+ } else {
268
+ deps.config.setDynamic(operation.key, operation.value);
269
+ }
245
270
  return {
246
271
  kind: operation.kind,
247
272
  summary: `Updated ${operation.key} in global onboarding settings.`,
@@ -294,9 +319,15 @@ async function buildRollbackAction(
294
319
  );
295
320
  }
296
321
 
297
- const previous = deps.config.get(operation.key as never);
322
+ const previous = isFeatureFlagConfigKey(operation.key)
323
+ ? readFeatureFlagConfigValue(deps.config, operation.key)
324
+ : deps.config.get(operation.key);
298
325
  return () => {
299
- deps.config.setDynamic(operation.key as never, previous);
326
+ if (isFeatureFlagConfigKey(operation.key)) {
327
+ mergeFeatureFlagConfigValue(deps.config, operation.key, previous ?? 'disabled');
328
+ } else {
329
+ deps.config.setDynamic(operation.key, previous);
330
+ }
300
331
  };
301
332
  }
302
333
 
@@ -322,6 +353,31 @@ async function buildRollbackAction(
322
353
  };
323
354
  }
324
355
 
356
+ if (operation.kind === 'select-agent-profile') {
357
+ const path = getAgentRuntimeProfileSelectionPath(deps.shellPaths.homeDirectory);
358
+ return snapshotFileRollback(path);
359
+ }
360
+
361
+ if (operation.kind === 'create-local-note') {
362
+ const registry = AgentNoteRegistry.fromShellPaths(deps.shellPaths);
363
+ return snapshotFileRollback(registry.snapshot().path);
364
+ }
365
+
366
+ if (operation.kind === 'create-local-persona') {
367
+ const registry = AgentPersonaRegistry.fromShellPaths(deps.shellPaths);
368
+ return snapshotFileRollback(registry.snapshot().path);
369
+ }
370
+
371
+ if (operation.kind === 'create-local-skill') {
372
+ const registry = AgentSkillRegistry.fromShellPaths(deps.shellPaths);
373
+ return snapshotFileRollback(registry.snapshot().path);
374
+ }
375
+
376
+ if (operation.kind === 'create-local-routine') {
377
+ const registry = AgentRoutineRegistry.fromShellPaths(deps.shellPaths);
378
+ return snapshotFileRollback(registry.snapshot().path);
379
+ }
380
+
325
381
  const neverOperation: never = operation;
326
382
  throw new Error(`Unsupported onboarding operation: ${JSON.stringify(neverOperation)}`);
327
383
  }
@@ -364,6 +420,90 @@ function applyCreateAgentProfileOperation(
364
420
  };
365
421
  }
366
422
 
423
+ function applySelectAgentProfileOperation(
424
+ deps: OnboardingApplyDependencies,
425
+ operation: Extract<OnboardingApplyOperation, { kind: 'select-agent-profile' }>,
426
+ ): OnboardingAppliedOperation {
427
+ validateSelectAgentProfileOperation(deps, operation);
428
+ const selection = setAgentRuntimeProfileSelection(deps.shellPaths.homeDirectory, operation.name);
429
+ return {
430
+ kind: operation.kind,
431
+ summary: `Selected Agent profile ${selection.id} for later plain goodvibes-agent runs.`,
432
+ };
433
+ }
434
+
435
+ function applyCreateLocalPersonaOperation(
436
+ deps: OnboardingApplyDependencies,
437
+ operation: Extract<OnboardingApplyOperation, { kind: 'create-local-persona' }>,
438
+ ): OnboardingAppliedOperation {
439
+ const registry = AgentPersonaRegistry.fromShellPaths(deps.shellPaths);
440
+ const persona = registry.create({
441
+ name: operation.name,
442
+ description: operation.description,
443
+ body: operation.body,
444
+ source: 'user',
445
+ provenance: 'onboarding',
446
+ });
447
+ if (operation.activate !== false) registry.setActive(persona.id);
448
+ return {
449
+ kind: operation.kind,
450
+ summary: `Created Agent-local persona ${persona.id}.`,
451
+ };
452
+ }
453
+
454
+ function applyCreateLocalSkillOperation(
455
+ deps: OnboardingApplyDependencies,
456
+ operation: Extract<OnboardingApplyOperation, { kind: 'create-local-skill' }>,
457
+ ): OnboardingAppliedOperation {
458
+ const skill = AgentSkillRegistry.fromShellPaths(deps.shellPaths).create({
459
+ name: operation.name,
460
+ description: operation.description,
461
+ procedure: operation.procedure,
462
+ enabled: operation.enabled !== false,
463
+ source: 'user',
464
+ provenance: 'onboarding',
465
+ });
466
+ return {
467
+ kind: operation.kind,
468
+ summary: `Created Agent-local skill ${skill.id}.`,
469
+ };
470
+ }
471
+
472
+ function applyCreateLocalRoutineOperation(
473
+ deps: OnboardingApplyDependencies,
474
+ operation: Extract<OnboardingApplyOperation, { kind: 'create-local-routine' }>,
475
+ ): OnboardingAppliedOperation {
476
+ const routine = AgentRoutineRegistry.fromShellPaths(deps.shellPaths).create({
477
+ name: operation.name,
478
+ description: operation.description,
479
+ steps: operation.steps,
480
+ enabled: operation.enabled !== false,
481
+ source: 'user',
482
+ provenance: 'onboarding',
483
+ });
484
+ return {
485
+ kind: operation.kind,
486
+ summary: `Created Agent-local routine ${routine.id}.`,
487
+ };
488
+ }
489
+
490
+ function applyCreateLocalNoteOperation(
491
+ deps: OnboardingApplyDependencies,
492
+ operation: Extract<OnboardingApplyOperation, { kind: 'create-local-note' }>,
493
+ ): OnboardingAppliedOperation {
494
+ const note = AgentNoteRegistry.fromShellPaths(deps.shellPaths).create({
495
+ title: operation.title,
496
+ body: operation.body,
497
+ tags: operation.tags ?? [],
498
+ source: 'user',
499
+ provenance: 'onboarding',
500
+ });
501
+ return {
502
+ kind: operation.kind,
503
+ summary: `Created Agent-local note ${note.id}.`,
504
+ };
505
+ }
506
+
367
507
  function orderApplyOperations(
368
508
  operations: readonly OnboardingApplyOperation[],
369
509
  ): readonly OnboardingApplyOperation[] {
@@ -376,6 +516,13 @@ function orderApplyOperations(
376
516
  operation.kind === 'set-config' && operation.key !== 'storage.secretPolicy'
377
517
  ));
378
518
  const agentProfileOperations = operations.filter((operation) => operation.kind === 'create-agent-profile');
519
+ const agentProfileSelectionOperations = operations.filter((operation) => operation.kind === 'select-agent-profile');
520
+ const localBehaviorOperations = operations.filter((operation) => (
521
+ operation.kind === 'create-local-note'
522
+ || operation.kind === 'create-local-persona'
523
+ || operation.kind === 'create-local-skill'
524
+ || operation.kind === 'create-local-routine'
525
+ ));
379
526
  const finalOperations = operations.filter((operation) => (
380
527
  operation.kind === 'acknowledge'
381
528
  ));
@@ -386,6 +533,8 @@ function orderApplyOperations(
386
533
  ...secretOperations,
387
534
  ...configOperations,
388
535
  ...agentProfileOperations,
536
+ ...agentProfileSelectionOperations,
537
+ ...localBehaviorOperations,
389
538
  ...finalOperations,
390
539
  ];
391
540
  }
@@ -427,6 +576,36 @@ function prevalidateApplyRequest(
427
576
  continue;
428
577
  }
429
578
 
579
+ if (operation.kind === 'select-agent-profile') {
580
+ const createdEarlier = orderedOperations.some((candidate) => (
581
+ candidate.kind === 'create-agent-profile'
582
+ && resolveAgentRuntimeProfileHome(deps.shellPaths.homeDirectory, candidate.name).id
583
+ === resolveAgentRuntimeProfileHome(deps.shellPaths.homeDirectory, operation.name).id
584
+ ));
585
+ if (!createdEarlier) validateSelectAgentProfileOperation(deps, operation);
586
+ continue;
587
+ }
588
+
589
+ if (operation.kind === 'create-local-persona') {
590
+ validateCreateLocalPersonaOperation(deps, operation);
591
+ continue;
592
+ }
593
+
594
+ if (operation.kind === 'create-local-note') {
595
+ validateCreateLocalNoteOperation(deps, operation);
596
+ continue;
597
+ }
598
+
599
+ if (operation.kind === 'create-local-skill') {
600
+ validateCreateLocalSkillOperation(deps, operation);
601
+ continue;
602
+ }
603
+
604
+ if (operation.kind === 'create-local-routine') {
605
+ validateCreateLocalRoutineOperation(deps, operation);
606
+ continue;
607
+ }
608
+
430
609
  const neverOperation: never = operation;
431
610
  throw new Error(`Unsupported onboarding operation: ${JSON.stringify(neverOperation)}`);
432
611
  } catch (error) {
@@ -446,6 +625,11 @@ function getVerificationFailureKind(itemId: string): OnboardingApplyOperation['k
446
625
  if (itemId.startsWith('auth:')) return 'ensure-auth-user';
447
626
  if (itemId.startsWith('acknowledge:')) return 'acknowledge';
448
627
  if (itemId.startsWith('agent-profile:')) return 'create-agent-profile';
628
+ if (itemId.startsWith('selected-agent-profile:')) return 'select-agent-profile';
629
+ if (itemId.startsWith('local-note:')) return 'create-local-note';
630
+ if (itemId.startsWith('local-persona:')) return 'create-local-persona';
631
+ if (itemId.startsWith('local-skill:')) return 'create-local-skill';
632
+ if (itemId.startsWith('local-routine:')) return 'create-local-routine';
449
633
  return 'set-config';
450
634
  }
451
635
 
@@ -502,6 +686,36 @@ export async function applyOnboardingRequest(
502
686
  continue;
503
687
  }
504
688
 
689
+ if (operation.kind === 'select-agent-profile') {
690
+ applied.push(applySelectAgentProfileOperation(deps, operation));
691
+ rollbacks.push(rollback);
692
+ continue;
693
+ }
694
+
695
+ if (operation.kind === 'create-local-persona') {
696
+ applied.push(applyCreateLocalPersonaOperation(deps, operation));
697
+ rollbacks.push(rollback);
698
+ continue;
699
+ }
700
+
701
+ if (operation.kind === 'create-local-note') {
702
+ applied.push(applyCreateLocalNoteOperation(deps, operation));
703
+ rollbacks.push(rollback);
704
+ continue;
705
+ }
706
+
707
+ if (operation.kind === 'create-local-skill') {
708
+ applied.push(applyCreateLocalSkillOperation(deps, operation));
709
+ rollbacks.push(rollback);
710
+ continue;
711
+ }
712
+
713
+ if (operation.kind === 'create-local-routine') {
714
+ applied.push(applyCreateLocalRoutineOperation(deps, operation));
715
+ rollbacks.push(rollback);
716
+ continue;
717
+ }
718
+
505
719
  const neverOperation: never = operation;
506
720
  throw new Error(`Unsupported onboarding operation: ${JSON.stringify(neverOperation)}`);
507
721
  } catch (error) {
@@ -83,7 +83,7 @@ function isDeepEqual(left: unknown, right: unknown): boolean {
83
83
  const rightEntries = Object.entries(right);
84
84
  if (leftEntries.length !== rightEntries.length) return false;
85
85
 
86
- return leftEntries.every(([key, value]) => isDeepEqual(value, (right as Record<string, unknown>)[key]));
86
+ return leftEntries.every(([key, value]) => isDeepEqual(value, Reflect.get(right, key)));
87
87
  }
88
88
 
89
89
  return false;
@@ -224,7 +224,7 @@ function hasAutomationReviewSignals(snapshot: OnboardingSnapshotState): boolean
224
224
  }
225
225
 
226
226
  function describeOperatorTerminal(): string {
227
- return 'Use GoodVibes Agent as the terminal operator while connecting to existing GoodVibes services. Agent setup does not create new entrypoints.';
227
+ return 'Use GoodVibes Agent as the terminal operator while connecting to an existing GoodVibes host. Agent setup does not create new entrypoints.';
228
228
  }
229
229
 
230
230
  function describeProviderAccess(snapshot: OnboardingSnapshotState): string {
@@ -250,7 +250,7 @@ function describeLocalBehavior(snapshot: OnboardingSnapshotState): string {
250
250
  ...discovery.routines.names,
251
251
  ].slice(0, 4);
252
252
  const sampleText = samples.length > 0 ? ` Found: ${samples.join(', ')}.` : '';
253
- return `Import ${discoveredCount} discovered Agent persona/skill/routine file(s) from local Agent folders before creating blank behavior.${sampleText}`;
253
+ return `Import ${discoveredCount} discovered Agent persona/skill/routine file(s) from Agent-local folders before creating blank behavior.${sampleText}`;
254
254
  }
255
255
 
256
256
  if (!hasLocalBehaviorCustomization(snapshot)) {
@@ -288,7 +288,7 @@ function describeAutomationReview(snapshot: OnboardingSnapshotState): string {
288
288
  }
289
289
 
290
290
  function describeTuiDelegation(): string {
291
- return 'Delegate explicit build, fix, implementation, and review work to GoodVibes TUI; WRFC is requested only when the user explicitly asks for it.';
291
+ return 'Delegate explicit build, fix, implementation, and review work to GoodVibes TUI; delegated review is requested only when the user explicitly asks for it.';
292
292
  }
293
293
 
294
294
  function getAcknowledgementAccepted(
@@ -391,10 +391,7 @@ export function deriveStep1CapabilityFlags(
391
391
  };
392
392
  }
393
393
 
394
- export function deriveStep1_5NetworkMode(
395
- bindSettings: Pick<OnboardingSnapshotState, 'bindSettings'>['bindSettings'],
396
- ): OnboardingNetworkMode {
397
- void bindSettings;
394
+ export function deriveStep1_5NetworkMode(): OnboardingNetworkMode {
398
395
  return 'local-network-default';
399
396
  }
400
397
 
@@ -458,23 +455,23 @@ export function deriveReopenEditAcknowledgementState(
458
455
  snapshot,
459
456
  'auth',
460
457
  'bootstrap-credential',
461
- 'A connected-service bootstrap credential signal is still visible to Agent.',
458
+ 'A connected-host bootstrap credential signal is still visible to Agent.',
462
459
  )
463
460
  : authSessionCount > 0
464
461
  ? buildRequiredAcknowledgement(
465
462
  snapshot,
466
463
  'auth',
467
464
  'active-sessions',
468
- `${authSessionCount} connected-service auth session signal(s) are currently visible.`,
465
+ `${authSessionCount} connected-host auth session signal(s) are currently visible.`,
469
466
  )
470
467
  : authUserCount > 0
471
468
  ? buildRequiredAcknowledgement(
472
469
  snapshot,
473
470
  'auth',
474
471
  'auth-state',
475
- `${authUserCount} connected-service auth user signal(s) are already visible.`,
472
+ `${authUserCount} connected-host auth user signal(s) are already visible.`,
476
473
  )
477
- : buildNotNeededAcknowledgement(snapshot, 'auth', 'No connected-service auth signal needs confirmation.');
474
+ : buildNotNeededAcknowledgement(snapshot, 'auth', 'No connected-host auth signal needs confirmation.');
478
475
 
479
476
  return {
480
477
  providers,
@@ -488,7 +485,7 @@ export function deriveOnboardingStepState(
488
485
  ): OnboardingStepDerivationState {
489
486
  return {
490
487
  step1Capabilities: deriveStep1Capabilities(snapshot),
491
- step1_5NetworkMode: deriveStep1_5NetworkMode(snapshot.bindSettings),
488
+ step1_5NetworkMode: deriveStep1_5NetworkMode(),
492
489
  reopenEditAcknowledgements: deriveReopenEditAcknowledgementState(snapshot),
493
490
  };
494
491
  }