@pellux/goodvibes-agent 0.1.116 → 0.1.117

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 (168) hide show
  1. package/CHANGELOG.md +41 -663
  2. package/README.md +38 -52
  3. package/dist/package/main.js +37826 -35924
  4. package/docs/README.md +5 -4
  5. package/docs/{connected-services.md → connected-host.md} +18 -10
  6. package/docs/getting-started.md +41 -44
  7. package/docs/release-and-publishing.md +6 -4
  8. package/package.json +3 -3
  9. package/src/agent/behavior-discovery-summary.ts +1 -3
  10. package/src/agent/persona-discovery.ts +1 -3
  11. package/src/agent/persona-registry.ts +5 -3
  12. package/src/agent/reminder-schedule-format.ts +6 -6
  13. package/src/agent/reminder-schedule.ts +1 -1
  14. package/src/agent/routine-registry.ts +43 -4
  15. package/src/agent/routine-schedule-format.ts +6 -6
  16. package/src/agent/routine-schedule-promotion.ts +1 -1
  17. package/src/agent/routine-schedule-receipts.ts +1 -1
  18. package/src/agent/runtime-profile-starters.ts +3 -3
  19. package/src/agent/runtime-profile.ts +78 -0
  20. package/src/agent/skill-registry.ts +190 -13
  21. package/src/cli/agent-knowledge-command.ts +2 -2
  22. package/src/cli/agent-knowledge-format.ts +2 -2
  23. package/src/cli/agent-knowledge-runtime.ts +1 -1
  24. package/src/cli/bundle-command.ts +1 -1
  25. package/src/cli/entrypoint.ts +16 -7
  26. package/src/cli/help.ts +26 -19
  27. package/src/cli/local-library-command.ts +75 -21
  28. package/src/cli/management-commands.ts +7 -6
  29. package/src/cli/management.ts +6 -51
  30. package/src/cli/parser.ts +23 -2
  31. package/src/cli/profiles-command.ts +119 -1
  32. package/src/cli/routines-command.ts +139 -11
  33. package/src/cli/service-posture.ts +11 -11
  34. package/src/cli/status.ts +21 -25
  35. package/src/input/agent-workspace-access-command-editor-submission.ts +149 -0
  36. package/src/input/agent-workspace-access-command-editors.ts +170 -0
  37. package/src/input/agent-workspace-activation.ts +2 -1
  38. package/src/input/agent-workspace-basic-command-editor-submission.ts +345 -92
  39. package/src/input/agent-workspace-basic-command-editors.ts +480 -7
  40. package/src/input/agent-workspace-categories.ts +175 -15
  41. package/src/input/agent-workspace-channel-command-editor-submission.ts +49 -0
  42. package/src/input/agent-workspace-channel-command-editors.ts +47 -0
  43. package/src/input/agent-workspace-command-editor.ts +23 -1
  44. package/src/input/agent-workspace-delegation-editor-submission.ts +55 -0
  45. package/src/input/agent-workspace-editors.ts +27 -0
  46. package/src/input/agent-workspace-knowledge-command-editor-submission.ts +132 -0
  47. package/src/input/agent-workspace-knowledge-command-editors.ts +110 -0
  48. package/src/input/agent-workspace-learned-behavior.ts +67 -0
  49. package/src/input/agent-workspace-library-command-editor-submission.ts +50 -0
  50. package/src/input/agent-workspace-library-command-editors.ts +35 -0
  51. package/src/input/agent-workspace-mcp-command-editor-submission.ts +95 -0
  52. package/src/input/agent-workspace-memory-command-editor-submission.ts +232 -0
  53. package/src/input/agent-workspace-memory-command-editors.ts +180 -0
  54. package/src/input/agent-workspace-navigation.ts +45 -0
  55. package/src/input/agent-workspace-notify-editor-submission.ts +107 -0
  56. package/src/input/agent-workspace-operations-command-editor-submission.ts +146 -0
  57. package/src/input/agent-workspace-operations-command-editors.ts +119 -0
  58. package/src/input/agent-workspace-provider-command-editor-submission.ts +155 -0
  59. package/src/input/agent-workspace-provider-command-editors.ts +93 -0
  60. package/src/input/agent-workspace-requirements.ts +11 -0
  61. package/src/input/agent-workspace-secret-editor-submission.ts +153 -0
  62. package/src/input/agent-workspace-session-command-editor-submission.ts +199 -0
  63. package/src/input/agent-workspace-session-command-editors.ts +249 -0
  64. package/src/input/agent-workspace-setup.ts +24 -14
  65. package/src/input/agent-workspace-skill-bundle-command-editor-submission.ts +101 -0
  66. package/src/input/agent-workspace-skill-bundle-command-editors.ts +110 -0
  67. package/src/input/agent-workspace-snapshot.ts +50 -8
  68. package/src/input/agent-workspace-task-command-editor-submission.ts +61 -0
  69. package/src/input/agent-workspace-task-command-editors.ts +47 -0
  70. package/src/input/agent-workspace-types.ts +120 -0
  71. package/src/input/agent-workspace-voice-media.ts +1 -1
  72. package/src/input/agent-workspace-workplan-editor-submission.ts +153 -0
  73. package/src/input/agent-workspace.ts +47 -37
  74. package/src/input/command-registry.ts +1 -1
  75. package/src/input/commands/agent-runtime-profile-runtime.ts +89 -4
  76. package/src/input/commands/agent-skills-runtime.ts +76 -12
  77. package/src/input/commands/agent-workspace-runtime.ts +4 -3
  78. package/src/input/commands/brief-runtime.ts +38 -9
  79. package/src/input/commands/channels-runtime.ts +3 -3
  80. package/src/input/commands/compat-runtime.ts +32 -0
  81. package/src/input/commands/health-runtime.ts +22 -24
  82. package/src/input/commands/knowledge.ts +26 -5
  83. package/src/input/commands/local-provider-runtime.ts +7 -3
  84. package/src/input/commands/local-setup-review.ts +4 -14
  85. package/src/input/commands/mcp-runtime.ts +8 -12
  86. package/src/input/commands/operator-runtime.ts +8 -67
  87. package/src/input/commands/personas-runtime.ts +1 -1
  88. package/src/input/commands/platform-access-runtime.ts +7 -70
  89. package/src/input/commands/policy-dispatch.ts +1 -1
  90. package/src/input/commands/policy.ts +1 -5
  91. package/src/input/commands/product-runtime.ts +2 -2
  92. package/src/input/commands/qrcode-runtime.ts +6 -4
  93. package/src/input/commands/routines-runtime.ts +44 -6
  94. package/src/input/commands/runtime-services.ts +1 -14
  95. package/src/input/commands/security-runtime.ts +3 -8
  96. package/src/input/commands/session-content.ts +1 -1
  97. package/src/input/commands/session-workflow.ts +5 -14
  98. package/src/input/commands/shell-core.ts +8 -2
  99. package/src/input/commands/subscription-runtime.ts +1 -6
  100. package/src/input/commands/support-bundle-runtime.ts +53 -0
  101. package/src/input/commands/tasks-runtime.ts +2 -2
  102. package/src/input/commands.ts +4 -0
  103. package/src/input/feed-context-factory.ts +0 -1
  104. package/src/input/handler-content-actions.ts +0 -25
  105. package/src/input/handler-feed.ts +0 -2
  106. package/src/input/handler-interactions.ts +2 -31
  107. package/src/input/handler-onboarding.ts +29 -12
  108. package/src/input/handler-shortcuts.ts +1 -3
  109. package/src/input/handler.ts +4 -7
  110. package/src/input/keybindings.ts +9 -9
  111. package/src/input/mcp-workspace.ts +90 -26
  112. package/src/input/onboarding/handler-onboarding-routes.ts +3 -1
  113. package/src/input/onboarding/onboarding-wizard-apply.ts +49 -0
  114. package/src/input/onboarding/onboarding-wizard-helpers.ts +1 -1
  115. package/src/input/onboarding/onboarding-wizard-operator-steps.ts +81 -3
  116. package/src/input/onboarding/onboarding-wizard-steps.ts +14 -7
  117. package/src/input/onboarding/onboarding-wizard-types.ts +1 -0
  118. package/src/input/onboarding/onboarding-wizard.ts +19 -2
  119. package/src/input/profile-picker-modal.ts +2 -2
  120. package/src/input/settings-modal-agent-policy.ts +6 -6
  121. package/src/input/settings-modal-subscriptions.ts +3 -3
  122. package/src/input/settings-modal.ts +14 -14
  123. package/src/main.ts +0 -2
  124. package/src/panels/automation-control-panel.ts +3 -3
  125. package/src/panels/builtin/agent.ts +1 -1
  126. package/src/panels/builtin/operations.ts +2 -2
  127. package/src/panels/builtin/session.ts +26 -18
  128. package/src/panels/builtin/shared.ts +6 -6
  129. package/src/panels/project-planning-panel.ts +1 -1
  130. package/src/panels/provider-health-domains.ts +3 -3
  131. package/src/panels/qr-panel.ts +44 -20
  132. package/src/panels/subscription-panel.ts +3 -3
  133. package/src/panels/system-messages-panel.ts +2 -2
  134. package/src/panels/tasks-panel.ts +4 -4
  135. package/src/planning/project-planning-coordinator.ts +2 -2
  136. package/src/renderer/agent-workspace.ts +26 -5
  137. package/src/renderer/block-actions.ts +1 -3
  138. package/src/renderer/help-overlay.ts +13 -8
  139. package/src/renderer/mcp-workspace.ts +32 -13
  140. package/src/renderer/model-picker-overlay.ts +0 -1
  141. package/src/renderer/model-workspace.ts +0 -2
  142. package/src/renderer/onboarding/onboarding-wizard.ts +20 -4
  143. package/src/renderer/panel-picker-overlay.ts +1 -1
  144. package/src/renderer/profile-picker-modal.ts +2 -2
  145. package/src/renderer/settings-modal-helpers.ts +23 -23
  146. package/src/renderer/settings-modal.ts +18 -18
  147. package/src/renderer/system-message.ts +1 -1
  148. package/src/runtime/agent-runtime-events.ts +129 -0
  149. package/src/runtime/bootstrap-command-parts.ts +3 -2
  150. package/src/runtime/bootstrap-core.ts +4 -64
  151. package/src/runtime/bootstrap-shell.ts +42 -4
  152. package/src/runtime/bootstrap.ts +8 -27
  153. package/src/runtime/connected-host-auth.ts +42 -0
  154. package/src/runtime/diagnostics/panels/panel-resources.ts +1 -1
  155. package/src/runtime/index.ts +1 -5
  156. package/src/runtime/onboarding/apply.ts +213 -0
  157. package/src/runtime/onboarding/derivation.ts +5 -5
  158. package/src/runtime/onboarding/snapshot.ts +2 -2
  159. package/src/runtime/onboarding/types.ts +26 -1
  160. package/src/runtime/onboarding/verify.ts +81 -2
  161. package/src/runtime/operator-token-cleanup.ts +2 -2
  162. package/src/runtime/services.ts +27 -12
  163. package/src/shell/service-settings-sync.ts +7 -7
  164. package/src/shell/ui-openers.ts +27 -38
  165. package/src/tools/agent-local-registry-tool.ts +10 -4
  166. package/src/tools/agent-tool-policy-guard.ts +5 -7
  167. package/src/version.ts +1 -1
  168. package/src/cli/package-verification.ts +0 -274
package/docs/README.md CHANGED
@@ -5,7 +5,7 @@ These are the package-facing docs for GoodVibes Agent, the personal operator ass
5
5
  Current package docs:
6
6
 
7
7
  - [Getting Started](getting-started.md)
8
- - [Connected Services](connected-services.md)
8
+ - [Connected Host](connected-host.md)
9
9
  - [Release And Publishing](release-and-publishing.md)
10
10
 
11
11
  Important baseline constraints:
@@ -13,12 +13,13 @@ Important baseline constraints:
13
13
  - Agent installs one executable: `goodvibes-agent`.
14
14
  - Agent uses Bun and TypeScript-authored source.
15
15
  - Agent depends on `@pellux/goodvibes-sdk@0.33.35`.
16
- - Agent connects to GoodVibes services owned outside this product.
17
- - Agent does not start, stop, restart, install, uninstall, or own those connected GoodVibes services.
16
+ - Agent connects to a GoodVibes host owned outside this product.
17
+ - Agent does not start, stop, restart, install, uninstall, or own the connected GoodVibes host.
18
18
  - Agent Knowledge/Wiki uses only `/api/goodvibes-agent/knowledge/*`; there is no default Knowledge/Wiki or non-Agent product fallback.
19
19
  - Agent supports isolated Agent homes with `GOODVIBES_AGENT_HOME=<path>` and named profile homes with `goodvibes-agent profiles create <name> --template <starter> --yes` plus `--agent-profile <name>`.
20
- - Agent supports connected-service URL overrides with `--runtime-url http://host:port` or `GOODVIBES_AGENT_RUNTIME_URL=http://host:port`; these only change the Agent connection target.
20
+ - Agent supports connected-host URL overrides with `--runtime-url http://host:port` or `GOODVIBES_AGENT_RUNTIME_URL=http://host:port`; these only change the Agent connection target.
21
21
  - Agent ships starter profile templates for household, research, travel, operations, and personal productivity local state; `profiles templates export/import` and `/agent-profile guide` support local custom starters.
22
+ - First-run setup can seed an initial local persona, skill, and routine without writing to connected-host knowledge or non-Agent segments.
22
23
  - Local memory, personas, routines, and Agent skills are stored under the Agent home and are injected only into the serial Agent conversation.
23
24
  - Normal assistant chat is not coding-session delegation.
24
25
  - Build/fix/review delegation to GoodVibes TUI must be explicit; WRFC is not the default Agent behavior.
@@ -1,21 +1,21 @@
1
- # Connected Services
1
+ # Connected Host
2
2
 
3
- GoodVibes Agent is a TUI client for connected GoodVibes services owned outside this package. The package exposes one executable:
3
+ GoodVibes Agent is a TUI client for a connected GoodVibes host owned outside this package. The package exposes one executable:
4
4
 
5
5
  ```sh
6
6
  goodvibes-agent
7
7
  ```
8
8
 
9
- The installed command is backed by TypeScript-authored source with a Bun shebang. Package install smoke must verify:
9
+ The installed command is backed by TypeScript-authored source with a Bun shebang. Package install smoke verifies the executable path:
10
10
 
11
11
  - `goodvibes-agent --help`
12
12
  - `goodvibes-agent --version`
13
13
  - `goodvibes-agent status --json`
14
14
  - `goodvibes-agent` launches the TUI in a real PTY
15
15
 
16
- ## Service Prerequisite
16
+ ## Host Prerequisite
17
17
 
18
- Start connected GoodVibes services from GoodVibes TUI or the owning host before launching Agent. Agent expects those services to expose public operator routes and the isolated Agent Knowledge routes:
18
+ Start the owning GoodVibes host before launching Agent. Agent expects that host to expose public operator routes and the isolated Agent Knowledge routes:
19
19
 
20
20
  ```text
21
21
  http://127.0.0.1:3421
@@ -24,10 +24,10 @@ http://127.0.0.1:3421
24
24
  /api/goodvibes-agent/knowledge/search
25
25
  ```
26
26
 
27
- If the GoodVibes API is on a different host or port, use a one-off override:
27
+ If the GoodVibes API is on a different host or port, use a one-off override when launching the TUI:
28
28
 
29
29
  ```sh
30
- goodvibes-agent --runtime-url http://127.0.0.1:3421 status
30
+ goodvibes-agent --runtime-url http://127.0.0.1:3421
31
31
  ```
32
32
 
33
33
  For a persistent shell/session override, set:
@@ -36,15 +36,23 @@ For a persistent shell/session override, set:
36
36
  export GOODVIBES_AGENT_RUNTIME_URL=http://127.0.0.1:3421
37
37
  ```
38
38
 
39
- `GOODVIBES_AGENT_BASE_URL` is accepted as a legacy alias. These values only select the connected GoodVibes API root; they do not make Agent own services.
39
+ `GOODVIBES_AGENT_BASE_URL` is accepted as a legacy alias. These values only select the connected GoodVibes API root; they do not make Agent own host processes.
40
40
 
41
- If connected GoodVibes services are unavailable, unauthenticated, or on an incompatible SDK version, Agent commands report actionable diagnostics without printing token values.
41
+ If the connected host is unavailable, unauthenticated, or on an incompatible SDK version, the Agent TUI reports actionable diagnostics without printing token values.
42
+
43
+ Use the TUI first for those checks:
44
+
45
+ - Agent Workspace -> Home -> Host compatibility
46
+ - Agent Workspace -> Home -> Doctor diagnostics
47
+ - Agent Workspace -> Home -> Review health
48
+
49
+ `goodvibes-agent status --json`, `goodvibes-agent doctor`, and `goodvibes-agent compat` are scriptable equivalents for install checks and automation.
42
50
 
43
51
  ## Product Boundary
44
52
 
45
53
  Agent owns the operator assistant TUI, local profiles, local memory/routines/skills/personas, isolated Agent Knowledge calls, companion chat, approvals/automation visibility, and explicit build delegation.
46
54
 
47
- Agent does not own connected-service lifecycle. It does not provide commands to install, expose, start, stop, restart, or mutate connected GoodVibes services.
55
+ Agent does not own connected-host lifecycle. It does not provide commands to install, expose, start, stop, restart, or mutate the connected GoodVibes host.
48
56
 
49
57
  Agent Knowledge/Wiki is its own product segment. Agent uses `/api/goodvibes-agent/knowledge/*` only and must not fall back to default Knowledge/Wiki or other product-specific knowledge routes.
50
58
 
@@ -5,12 +5,12 @@ GoodVibes Agent is the installable public alpha of the personal operator assista
5
5
  ## Requirements
6
6
 
7
7
  - Bun `1.3.10` or newer
8
- - Connected GoodVibes services compatible with `@pellux/goodvibes-sdk@0.33.35`
9
- - A token/config path accepted by connected GoodVibes services
8
+ - A connected GoodVibes host compatible with `@pellux/goodvibes-sdk@0.33.35`
9
+ - A token/config path accepted by the connected host
10
10
 
11
- Agent does not launch connected GoodVibes services for you.
11
+ Agent does not launch the connected host for you.
12
12
 
13
- Use the interactive TUI first. CLI subcommands are secondary support paths for install checks, setup inspection, and scriptable local Agent libraries.
13
+ Use the interactive TUI first. CLI subcommands are secondary support paths for install checks, setup inspection, and scriptable mirrors of workflows that are already reachable from the workspace.
14
14
 
15
15
  ## Install From Package
16
16
 
@@ -18,10 +18,6 @@ Use the interactive TUI first. CLI subcommands are secondary support paths for i
18
18
  bun add -g @pellux/goodvibes-agent
19
19
  goodvibes-agent --help
20
20
  goodvibes-agent
21
- goodvibes-agent status
22
- goodvibes-agent personas list
23
- goodvibes-agent skills list
24
- goodvibes-agent memory list
25
21
  ```
26
22
 
27
23
  If the installed command is not found, add Bun's global bin directory to `PATH`:
@@ -44,74 +40,75 @@ bun run dev
44
40
 
45
41
  `goodvibes-agent` starts the interactive Agent TUI. On a fresh Agent home, the TUI opens Agent setup first.
46
42
 
47
- After setup has been shown once, the TUI opens directly into the Agent operator workspace. You can also reopen it with `/agent`, `/home`, or `/operator`. That fullscreen workspace is the current front door for setup/config, provider/model selection, Agent Knowledge, local memory/skills/routines/personas, channel readiness, voice/media setup, read-only work/approval/automation views, and explicit GoodVibes TUI build delegation.
43
+ After setup has been applied once, the TUI opens directly into the Agent operator workspace. You can also reopen it with `/agent`, `/home`, or `/operator`. That fullscreen workspace is the current front door for setup/config, provider/model selection, Agent Knowledge, local memory/skills/routines/personas, channel readiness, voice/media setup, read-only work/approval/automation views, and explicit GoodVibes TUI build delegation.
48
44
 
49
- The setup workspace scans local Agent behavior folders and shows importable persona, skill, and routine files before asking you to create blank records. Use `/personas discover`, `/agent-skills discover`, and `/routines discover` to preview files, then use the matching import action in the workspace after review.
45
+ The setup workspace scans local Agent behavior folders and shows importable persona, skill, and routine files before asking you to create blank records. It can also create one initial local persona, skill, and routine from the setup form. Use `/personas discover`, `/agent-skills discover`, and `/routines discover` to preview files, then use the matching import action in the workspace after review.
50
46
 
51
47
  Use `/agent-profile guide` inside that workspace to walk through starter-profile authoring. It lists built-in and local starters, exports a JSON starter for editing, imports the edited starter back into this Agent home, and creates isolated profiles from the result.
52
48
 
53
- Use `goodvibes-agent profiles create-from-discovered research-desk --yes` or the Profiles workspace form to assemble a local starter template and isolated Agent profile from reviewed discovered persona, skill, and routine files. Use `profiles templates from-discovered <id> --yes` only when you want to save the starter before creating a profile.
49
+ Use the Profiles workspace form to assemble a local starter template and isolated Agent profile from reviewed discovered persona, skill, and routine files. Scriptable profile commands mirror the same flow for automation; use them only when you intentionally want a shell-driven setup path.
54
50
 
55
51
  Use the Knowledge area in that workspace to ingest a source URL without leaving the TUI. The form requires typed confirmation and writes only to the isolated Agent Knowledge segment.
56
52
 
57
- Use `/schedule receipts` to review redacted local routine promotion history and `/schedule reconcile` to compare those receipts with live connected schedules through public `schedules.list`.
53
+ Use the Routines workspace receipt actions to review redacted local routine promotion history and reconcile those receipts with live connected schedules through public `schedules.list`. The `/schedule receipts` and `/schedule reconcile` commands are the power-user equivalents inside the TUI.
58
54
 
59
- The local behavior libraries are also available from the installed CLI:
55
+ The local behavior libraries are configured in the TUI first:
60
56
 
61
- ```sh
62
- goodvibes-agent personas create --name "Research Analyst" --description "Source-backed research" --body "Check sources and call out uncertainty" --use
63
- goodvibes-agent skills create --name "Morning Brief" --description "Daily briefing flow" --procedure "Check tasks, approvals, routines, and Agent Knowledge before summarizing" --enabled
64
- goodvibes-agent memory add fact "Prefers concise morning briefings" --scope project --tags preference
65
- goodvibes-agent routines list
66
- ```
57
+ - Memory & Skills -> Create memory or Capture learned behavior.
58
+ - Personas -> Create persona, Use selected, Review selected, or Delete selected.
59
+ - Skills -> Create skill, Create bundle, Enable selected, Review selected, or Delete selected.
60
+ - Routines -> Create routine, Start selected, Enable selected, Promote to schedule, or Review receipts.
61
+
62
+ The installed CLI mirrors these libraries for scripts, but it is not the primary user workflow.
67
63
 
68
64
  ## Isolated Agent Profiles
69
65
 
70
- Use a separate Agent home when you want isolated local state:
66
+ Use a separate Agent home when you want isolated local state. The normal launch still opens the TUI:
71
67
 
72
68
  ```sh
73
- GOODVIBES_AGENT_HOME=/path/to/agent-home goodvibes-agent status
69
+ GOODVIBES_AGENT_HOME=/path/to/agent-home goodvibes-agent
74
70
  ```
75
71
 
76
- Use named Agent profiles for repeatable local identities:
72
+ Use named Agent profiles for repeatable local identities from Agent Workspace -> Profiles. The workspace can browse starter templates, create isolated Agent profiles, set or clear the default profile for the next launch, and export/import starter JSON.
73
+
74
+ Scriptable equivalents for automation and setup scripts:
77
75
 
78
76
  ```sh
79
77
  goodvibes-agent profiles templates
80
78
  goodvibes-agent profiles create household --template household --yes
79
+ goodvibes-agent profiles use household --yes
80
+ goodvibes-agent
81
81
  goodvibes-agent profiles templates export research ./research-starter.json --yes
82
82
  goodvibes-agent profiles templates import ./research-starter.json --yes
83
83
  goodvibes-agent --agent-profile household status
84
84
  goodvibes-agent --agent-profile household
85
85
  ```
86
86
 
87
- Named profiles isolate Agent-local config, sessions, memory, personas, skills, routines, and setup state under a profile-specific home. Starter templates seed local personas, skills, and routines for household, research, travel, operations, and personal productivity profiles; exported starter JSON can be edited and re-imported as a local starter. They do not start or isolate connected GoodVibes services by themselves.
87
+ Named profiles isolate Agent-local config, sessions, memory, personas, skills, routines, and setup state under a profile-specific home. `profiles use <name> --yes` makes one profile the default for the next plain `goodvibes-agent` launch; `--agent-profile <name>` still overrides it for one launch, and `profiles default clear --yes` returns plain launches to the base Agent home. Starter templates seed local personas, skills, and routines for household, research, travel, operations, and personal productivity profiles; exported starter JSON can be edited and re-imported as a local starter. They do not start or isolate the connected host by themselves.
88
88
 
89
89
  ## Local Memory, Personas, Routines, And Skills
90
90
 
91
- Memory, personas, routines, and reusable Agent skills are local to GoodVibes Agent. They do not write into default Knowledge/Wiki or non-Agent knowledge segments.
92
-
93
- ```text
94
- /personas list
95
- /personas create --name Research --description "Source-backed research" --body "Check sources, call out uncertainty, keep answers concise."
96
- /personas use research
97
- /routines create --name "Evening Review" --description "Review open work before shutdown" --steps "Check work plan, approvals, and Agent Knowledge status before summarizing." --enabled true
98
- /routines start evening-review
99
- /schedule promote-routine evening-review --cron "0 17 * * 1-5" --timezone America/Chicago --yes
100
- /channels
101
- /agent-skills create --name "Morning Brief" --description "Daily briefing flow" --procedure "Check tasks, approvals, calendar, and unread state before summarizing." --enabled true
102
- /agent-skills enabled
103
- /skills list
104
- /memory add fact "Prefers concise morning briefings" --scope project --tags preference
105
- /memory search morning
106
- ```
91
+ Memory, personas, routines, and reusable Agent skills are local to GoodVibes Agent. First-run setup, TUI workspace forms, and CLI commands all write them to Agent-local registries. They do not write into default Knowledge/Wiki or non-Agent knowledge segments.
92
+
93
+ Use `Capture learned behavior` in the Agent workspace after reviewing a repeated workflow, lesson, or operating style. It saves one local skill, routine, or persona from the TUI and does not call connected-host mutation routes.
94
+
95
+ Day-one local behavior setup should stay in the fullscreen workspace:
96
+
97
+ - Personas -> Create persona, then Use selected.
98
+ - Routines -> Create routine, Start selected, or Promote to schedule after entering real timing and confirmation.
99
+ - Skills -> Create skill, Enable selected, and review setup requirements.
100
+ - Memory & Skills -> Create memory or Search memory.
101
+ - Channels -> inspect readiness before enabling notification delivery.
102
+
103
+ Typed slash commands are available for repeat users, but they are not required for the first-run workflow.
107
104
 
108
- The active persona plus enabled Agent routines, reviewed memory, and skills are injected into the main serial assistant conversation. Starting a routine records local usage and prints its steps; it does not spawn background agents or automation jobs. Promoting a routine to a schedule is an explicit `schedules.create` call, requires `--yes`, writes a local redacted promotion receipt, and preserves the rule that Agent Knowledge never falls back to default Knowledge/Wiki or non-Agent knowledge segments.
105
+ The active persona plus enabled Agent routines, reviewed memory, and skills are injected into the main serial assistant conversation. Starting a routine records local usage and prints its steps; it does not launch local workers or automation jobs. Promoting a routine to a schedule is an explicit `schedules.create` call, requires `--yes`, writes a local redacted promotion receipt, and preserves the rule that Agent Knowledge never falls back to default Knowledge/Wiki or non-Agent knowledge segments.
109
106
 
110
107
  Use `/channels` inside the TUI for a read-only channel readiness matrix. It shows enabled channels, missing config key names, delivery posture, and risk labels without sending messages or rendering token values.
111
108
 
112
- ## Connected GoodVibes Services
109
+ ## Connected GoodVibes Host
113
110
 
114
- Start connected GoodVibes services from GoodVibes TUI or the owning host before using service-backed Agent features. Agent expects those services to expose the public operator/Agent routes, including:
111
+ Start the owning GoodVibes host before using connected Agent features. Agent expects that host to expose the public operator/Agent routes, including:
115
112
 
116
113
  - `/status`
117
114
  - `/api/goodvibes-agent/knowledge/status`
@@ -119,11 +116,11 @@ Start connected GoodVibes services from GoodVibes TUI or the owning host before
119
116
  - `/api/goodvibes-agent/knowledge/search`
120
117
  - `/api/goodvibes-agent/knowledge/ingest/url`
121
118
 
122
- If the GoodVibes API is not on `http://127.0.0.1:3421`, use `goodvibes-agent --runtime-url http://host:port status` for a one-off check or set `GOODVIBES_AGENT_RUNTIME_URL=http://host:port` before launching the TUI.
119
+ If the GoodVibes API is not on `http://127.0.0.1:3421`, pass `--runtime-url http://host:port` for a one-off TUI launch or set `GOODVIBES_AGENT_RUNTIME_URL=http://host:port` before launching the TUI.
123
120
 
124
121
  Agent Knowledge/Wiki is an Agent-owned product segment. Agent commands must not fall back to default Knowledge/Wiki or other product-specific knowledge spaces.
125
122
 
126
- Service-hosting commands are not part of GoodVibes Agent. Use `goodvibes-agent status`, `goodvibes-agent doctor`, and the Agent TUI status views for diagnostics.
123
+ Host lifecycle commands are not part of GoodVibes Agent. Use Agent Workspace -> Home -> Host compatibility, Doctor diagnostics, and Review health for diagnostics. CLI status/doctor/compat commands are scriptable mirrors for install checks.
127
124
 
128
125
  ## Current Product Notes
129
126
 
@@ -9,7 +9,7 @@ GoodVibes Agent's current installable public alpha version is recorded in `packa
9
9
  - SDK dependency: exact pin to `@pellux/goodvibes-sdk@0.33.35`
10
10
  - runtime: Bun
11
11
  - source language: TypeScript
12
- - connected services ownership: outside Agent
12
+ - connected host ownership: outside Agent
13
13
 
14
14
  End users install and run GoodVibes Agent with Bun:
15
15
 
@@ -36,6 +36,8 @@ git diff --check
36
36
 
37
37
  `bun run publish:package` publishes from a staged package directory to the package registry. If `NPM_CONFIG_USERCONFIG` is already set, the registry publish command uses it. Otherwise the script creates a temporary 0600 registry userconfig from `NODE_AUTH_TOKEN` or `NPM_TOKEN`, uses it for that publish command, and removes it with the staging directory. The publish script is idempotent for reruns: if the exact package version is already present on the registry, it reports that state and exits successfully instead of failing the release retry.
38
38
 
39
+ `bun run release` requires product release notes instead of raw git-log output. Pass `--notes-file ./release-notes.md` or set `GOODVIBES_AGENT_RELEASE_NOTES` before a real release. Release notes should describe what changed for Agent users: TUI behavior, setup, Agent Knowledge, local behavior libraries, connected-host compatibility, package/install behavior, and safety policy. Do not use commit hashes as the shipped changelog content.
40
+
39
41
  The GitHub release workflow publishes to npm only when the repository variable `PUBLISH_NPM` is `true` and the repository secret `NPM_TOKEN` is configured. Without those repository settings, the workflow still validates and creates the GitHub release, but npm publish must be run from a local environment with an exported token.
40
42
 
41
43
  Branch CI is the only workflow that runs the full test suite and release gates. It runs `bun run test` once for the release SHA, along with typecheck, architecture, performance, build, publish, and packed install checks. The release workflow must not run tests or duplicate those gates; it verifies that branch CI passed for the exact checked-out SHA and then performs only package packing, GitHub Release creation, and optional npm publish.
@@ -52,16 +54,16 @@ Also run the package install smoke from a packed artifact. It must prove:
52
54
  - `goodvibes-agent --help` works
53
55
  - `goodvibes-agent --version` reports the package version
54
56
  - the installed TUI launches in a PTY and does not exit immediately
55
- - connected-service commands fail clearly when GoodVibes services are unavailable or unauthenticated
57
+ - connected-host commands fail clearly when GoodVibes host is unavailable or unauthenticated
56
58
  - no token value is printed
57
59
 
58
60
  ## Do Not Ship
59
61
 
60
- Do not publish if package-facing docs or install commands refer to another package name, another executable, or Agent-owned connected-service lifecycle.
62
+ Do not publish if package-facing docs or install commands refer to another package name, another executable, or Agent-owned connected-host lifecycle.
61
63
 
62
64
  Do not publish if Agent Knowledge commands can fall back to default Knowledge/Wiki or another product-specific knowledge route. Agent Knowledge must use the isolated `/api/goodvibes-agent/knowledge/*` segment.
63
65
 
64
- Do not ship GoodVibes service binaries from this package. If Agent later gets compiled artifacts, they must use Agent artifact names and remain separate from connected-service ownership.
66
+ Do not ship GoodVibes service binaries from this package. If Agent later gets compiled artifacts, they must use Agent artifact names and remain separate from connected-host ownership.
65
67
 
66
68
  ## Product Rule
67
69
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pellux/goodvibes-agent",
3
- "version": "0.1.116",
3
+ "version": "0.1.117",
4
4
  "private": false,
5
5
  "description": "GoodVibes personal operator assistant TUI with a proactive Agent product brain, isolated Agent Knowledge, local profiles, routines, skills, personas, and explicit build delegation.",
6
6
  "type": "module",
@@ -17,13 +17,14 @@
17
17
  "!src/test",
18
18
  "!src/**/*.test.ts",
19
19
  "!src/**/__tests__",
20
+ "!src/cli/package-verification.ts",
20
21
  "!src/verification",
21
22
  "tsconfig.json",
22
23
  "README.md",
23
24
  "CHANGELOG.md",
24
25
  "docs/README.md",
25
26
  "docs/getting-started.md",
26
- "docs/connected-services.md",
27
+ "docs/connected-host.md",
27
28
  "docs/release-and-publishing.md"
28
29
  ],
29
30
  "scripts": {
@@ -54,7 +55,6 @@
54
55
  "build:all": "bun run scripts/build.ts --all",
55
56
  "perf:check": "bun run scripts/perf-check.ts",
56
57
  "architecture:check": "bun run scripts/check-architecture.ts",
57
- "foundation:artifacts": "bun run scripts/export-foundation-artifacts.ts",
58
58
  "verification:ledger": "bun run scripts/verification-ledger.ts",
59
59
  "verification:live": "bun run scripts/verify-live.ts"
60
60
  },
@@ -126,12 +126,10 @@ function definitions(shellPaths: Pick<ShellPathService, 'workingDirectory' | 'ho
126
126
  roots: [
127
127
  { root: join(cwd, '.goodvibes', 'personas'), origin: 'project-local' },
128
128
  { root: join(cwd, '.goodvibes', GOODVIBES_AGENT_SURFACE_ROOT, 'personas'), origin: 'project-local' },
129
- { root: join(cwd, '.goodvibes', 'agents'), origin: 'project-local' },
130
129
  { root: join(homeDir, '.goodvibes', 'personas'), origin: 'global' },
131
130
  { root: join(homeDir, '.goodvibes', GOODVIBES_AGENT_SURFACE_ROOT, 'personas'), origin: 'global' },
132
- { root: join(homeDir, '.goodvibes', 'agents'), origin: 'global' },
133
131
  ],
134
- markers: ['PERSONA.md', 'persona.md', 'AGENT.md', 'agent.md'],
132
+ markers: ['PERSONA.md', 'persona.md'],
135
133
  frontmatterBodyKey: 'system_prompt',
136
134
  };
137
135
  const skills: DiscoveryKindDefinition = {
@@ -14,7 +14,7 @@ export interface DiscoveredPersonaRecord {
14
14
  readonly frontmatter: Record<string, string>;
15
15
  }
16
16
 
17
- const DIRECTORY_MARKERS: readonly string[] = ['PERSONA.md', 'persona.md', 'AGENT.md', 'agent.md'];
17
+ const DIRECTORY_MARKERS: readonly string[] = ['PERSONA.md', 'persona.md'];
18
18
 
19
19
  function parseFrontmatter(content: string): Record<string, string> {
20
20
  const match = content.match(/^---\n([\s\S]*?)\n---/);
@@ -33,10 +33,8 @@ function getPersonaDirectories(cwd: string, homeDir: string): Array<{ root: stri
33
33
  return [
34
34
  { root: join(cwd, '.goodvibes', 'personas'), origin: 'project-local' },
35
35
  { root: join(cwd, '.goodvibes', GOODVIBES_AGENT_SURFACE_ROOT, 'personas'), origin: 'project-local' },
36
- { root: join(cwd, '.goodvibes', 'agents'), origin: 'project-local' },
37
36
  { root: join(homeDir, '.goodvibes', 'personas'), origin: 'global' },
38
37
  { root: join(homeDir, '.goodvibes', GOODVIBES_AGENT_SURFACE_ROOT, 'personas'), origin: 'global' },
39
- { root: join(homeDir, '.goodvibes', 'agents'), origin: 'global' },
40
38
  ];
41
39
  }
42
40
 
@@ -158,14 +158,16 @@ function formatStore(store: PersonaStoreFile): string {
158
158
  return `${JSON.stringify(store, null, 2)}\n`;
159
159
  }
160
160
 
161
- export function personaStorePath(shellPaths: ShellPathService): string {
161
+ type AgentLocalStorePaths = Pick<ShellPathService, 'resolveUserPath'>;
162
+
163
+ export function personaStorePath(shellPaths: AgentLocalStorePaths): string {
162
164
  return shellPaths.resolveUserPath(GOODVIBES_AGENT_SURFACE_ROOT, 'personas', 'personas.json');
163
165
  }
164
166
 
165
167
  export class AgentPersonaRegistry {
166
168
  public constructor(private readonly storePath: string) {}
167
169
 
168
- public static fromShellPaths(shellPaths: ShellPathService): AgentPersonaRegistry {
170
+ public static fromShellPaths(shellPaths: AgentLocalStorePaths): AgentPersonaRegistry {
169
171
  return new AgentPersonaRegistry(personaStorePath(shellPaths));
170
172
  }
171
173
 
@@ -374,6 +376,6 @@ export function buildActivePersonaPrompt(shellPaths: ShellPathService): string |
374
376
  '',
375
377
  active.body,
376
378
  '',
377
- 'Apply this persona inside the same serial assistant conversation. Do not spawn background agents because a persona is active.',
379
+ 'Apply this persona inside the same serial assistant conversation. Do not launch local workers because a persona is active.',
378
380
  ].join('\n');
379
381
  }
@@ -33,7 +33,7 @@ export function formatReminderSchedulePreview(preview: ReminderSchedulePreview):
33
33
  ` schedule: ${preview.payload.kind} ${scheduleValue(preview)}`,
34
34
  ` enabled: ${preview.payload.enabled === false ? 'no' : 'yes'}`,
35
35
  ` delivery: ${delivery?.mode ?? 'none'}${deliveryTargetCount > 0 ? ` (${deliveryTargetCount} target${deliveryTargetCount === 1 ? '' : 's'})` : ''}`,
36
- ' target: connected GoodVibes services/main conversation route',
36
+ ' target: connected GoodVibes host/main conversation route',
37
37
  ' policy: reminder delivery only; isolated Agent Knowledge only; no default wiki/non-Agent fallback',
38
38
  ' next: rerun with --yes to create this connected reminder schedule',
39
39
  ].join('\n');
@@ -57,19 +57,19 @@ export function formatReminderScheduleFailure(failure: ReminderScheduleFailure):
57
57
  return [
58
58
  `GoodVibes reminder schedule error: ${failure.kind}`,
59
59
  ` ${failure.error}`,
60
- failure.baseUrl ? ` service: ${failure.baseUrl}` : null,
60
+ failure.baseUrl ? ` host: ${failure.baseUrl}` : null,
61
61
  ` route: ${REMINDER_SCHEDULE_METHOD} ${failure.route}`,
62
62
  failure.kind === 'version_mismatch' && failure.daemonVersion && failure.expectedSdkVersion
63
- ? ` versions: service=${failure.daemonVersion} expected=${failure.expectedSdkVersion}`
63
+ ? ` versions: host=${failure.daemonVersion} expected=${failure.expectedSdkVersion}`
64
64
  : null,
65
65
  failure.kind === 'auth_required'
66
- ? ' next: pair/authenticate with connected GoodVibes services, then retry with --yes.'
66
+ ? ' next: pair/authenticate with the connected GoodVibes host, then retry with --yes.'
67
67
  : null,
68
68
  failure.kind === 'daemon_unavailable'
69
- ? ' next: make connected GoodVibes services available outside Agent, then retry.'
69
+ ? ' next: make the connected GoodVibes host available outside Agent, then retry.'
70
70
  : null,
71
71
  failure.kind === 'version_mismatch' || failure.kind === 'daemon_route_unavailable'
72
- ? ' next: update connected GoodVibes services so public schedules.create is available.'
72
+ ? ' next: update the connected GoodVibes host so public schedules.create is available.'
73
73
  : null,
74
74
  ].filter((line): line is string => Boolean(line)).join('\n');
75
75
  }
@@ -468,7 +468,7 @@ export async function createReminderSchedule(
468
468
  return {
469
469
  ok: false,
470
470
  kind: 'auth_required',
471
- error: `No daemon operator token found at ${connection.tokenPath}`,
471
+ error: `No connected-host operator token found at ${connection.tokenPath}`,
472
472
  route: REMINDER_SCHEDULE_ROUTE,
473
473
  baseUrl: connection.baseUrl,
474
474
  };
@@ -3,9 +3,18 @@ import { dirname } from 'node:path';
3
3
  import type { ShellPathService } from '@/runtime/index.ts';
4
4
  import { GOODVIBES_AGENT_SURFACE_ROOT } from '../config/surface.ts';
5
5
  import { assertNoSecretLikeText } from './persona-registry.ts';
6
+ import {
7
+ evaluateAgentSkillReadiness,
8
+ formatAgentSkillRequirement,
9
+ normalizeAgentSkillRequirements,
10
+ type AgentSkillReadiness,
11
+ type AgentSkillRequirement,
12
+ } from './skill-registry.ts';
6
13
 
7
14
  export type AgentRoutineSource = 'user' | 'agent' | 'imported' | 'system';
8
15
  export type AgentRoutineReviewState = 'fresh' | 'reviewed' | 'stale';
16
+ export type AgentRoutineRequirement = AgentSkillRequirement;
17
+ export type AgentRoutineReadiness = AgentSkillReadiness;
9
18
 
10
19
  export interface AgentRoutineRecord {
11
20
  readonly id: string;
@@ -14,6 +23,7 @@ export interface AgentRoutineRecord {
14
23
  readonly steps: string;
15
24
  readonly triggers: readonly string[];
16
25
  readonly tags: readonly string[];
26
+ readonly requirements: readonly AgentRoutineRequirement[];
17
27
  readonly enabled: boolean;
18
28
  readonly source: AgentRoutineSource;
19
29
  readonly provenance: string;
@@ -32,6 +42,7 @@ export interface AgentRoutineCreateInput {
32
42
  readonly steps: string;
33
43
  readonly triggers?: readonly string[];
34
44
  readonly tags?: readonly string[];
45
+ readonly requirements?: readonly AgentRoutineRequirement[];
35
46
  readonly enabled?: boolean;
36
47
  readonly source?: AgentRoutineSource;
37
48
  readonly provenance?: string;
@@ -43,6 +54,7 @@ export interface AgentRoutineUpdateInput {
43
54
  readonly steps?: string;
44
55
  readonly triggers?: readonly string[];
45
56
  readonly tags?: readonly string[];
57
+ readonly requirements?: readonly AgentRoutineRequirement[];
46
58
  readonly provenance?: string;
47
59
  }
48
60
 
@@ -72,6 +84,18 @@ function readStringArray(value: unknown): string[] {
72
84
  return value.filter((entry): entry is string => typeof entry === 'string').map((entry) => entry.trim()).filter(Boolean);
73
85
  }
74
86
 
87
+ function readRequirementArray(value: unknown): readonly AgentRoutineRequirement[] {
88
+ if (!Array.isArray(value)) return [];
89
+ const requirements = value
90
+ .filter(isRecord)
91
+ .map((entry) => ({
92
+ kind: entry.kind === 'command' ? 'command' as const : 'env' as const,
93
+ name: readString(entry.name).trim(),
94
+ description: readString(entry.description).trim() || undefined,
95
+ }));
96
+ return normalizeAgentSkillRequirements(requirements);
97
+ }
98
+
75
99
  function readNonNegativeInteger(value: unknown): number {
76
100
  const parsed = typeof value === 'number' ? value : Number(value);
77
101
  return Number.isInteger(parsed) && parsed > 0 ? parsed : 0;
@@ -123,6 +147,7 @@ function parseRoutine(value: unknown): AgentRoutineRecord | null {
123
147
  steps,
124
148
  triggers: readStringArray(value.triggers),
125
149
  tags: readStringArray(value.tags),
150
+ requirements: readRequirementArray(value.requirements),
126
151
  enabled: value.enabled === true,
127
152
  source,
128
153
  provenance: readString(value.provenance, source).trim() || source,
@@ -151,14 +176,16 @@ function formatStore(store: RoutineStoreFile): string {
151
176
  return `${JSON.stringify(store, null, 2)}\n`;
152
177
  }
153
178
 
154
- export function routineStorePath(shellPaths: ShellPathService): string {
179
+ type AgentLocalStorePaths = Pick<ShellPathService, 'resolveUserPath'>;
180
+
181
+ export function routineStorePath(shellPaths: AgentLocalStorePaths): string {
155
182
  return shellPaths.resolveUserPath(GOODVIBES_AGENT_SURFACE_ROOT, 'routines', 'routines.json');
156
183
  }
157
184
 
158
185
  export class AgentRoutineRegistry {
159
186
  public constructor(private readonly storePath: string) {}
160
187
 
161
- public static fromShellPaths(shellPaths: ShellPathService): AgentRoutineRegistry {
188
+ public static fromShellPaths(shellPaths: AgentLocalStorePaths): AgentRoutineRegistry {
162
189
  return new AgentRoutineRegistry(routineStorePath(shellPaths));
163
190
  }
164
191
 
@@ -200,7 +227,8 @@ export class AgentRoutineRegistry {
200
227
  const description = input.description.trim();
201
228
  const steps = input.steps.trim();
202
229
  this.validateRequired(name, description, steps);
203
- assertNoSecretLikeText([name, description, steps, ...(input.tags ?? []), ...(input.triggers ?? [])]);
230
+ const requirements = normalizeAgentSkillRequirements(input.requirements);
231
+ assertNoSecretLikeText([name, description, steps, ...(input.tags ?? []), ...(input.triggers ?? []), ...requirements.flatMap((requirement) => [requirement.name, requirement.description ?? ''])]);
204
232
  const duplicate = store.routines.find((routine) => routine.name.toLowerCase() === name.toLowerCase());
205
233
  if (duplicate) throw new Error(`Routine already exists: ${duplicate.id}`);
206
234
  const timestamp = nowIso();
@@ -211,6 +239,7 @@ export class AgentRoutineRegistry {
211
239
  steps,
212
240
  triggers: normalizeList(input.triggers),
213
241
  tags: normalizeList(input.tags),
242
+ requirements,
214
243
  enabled: input.enabled === true,
215
244
  source: input.source ?? 'user',
216
245
  provenance: input.provenance?.trim() || input.source || 'user',
@@ -231,7 +260,8 @@ export class AgentRoutineRegistry {
231
260
  const description = input.description === undefined ? existing.description : input.description.trim();
232
261
  const steps = input.steps === undefined ? existing.steps : input.steps.trim();
233
262
  this.validateRequired(name, description, steps);
234
- assertNoSecretLikeText([name, description, steps, ...(input.tags ?? []), ...(input.triggers ?? [])]);
263
+ const requirements = input.requirements === undefined ? existing.requirements : normalizeAgentSkillRequirements(input.requirements);
264
+ assertNoSecretLikeText([name, description, steps, ...(input.tags ?? []), ...(input.triggers ?? []), ...requirements.flatMap((requirement) => [requirement.name, requirement.description ?? ''])]);
235
265
  const duplicate = store.routines.find((routine) => routine.id !== existing.id && routine.name.toLowerCase() === name.toLowerCase());
236
266
  if (duplicate) throw new Error(`Routine already exists: ${duplicate.id}`);
237
267
  const updated: AgentRoutineRecord = {
@@ -241,6 +271,7 @@ export class AgentRoutineRegistry {
241
271
  steps,
242
272
  triggers: input.triggers === undefined ? existing.triggers : normalizeList(input.triggers),
243
273
  tags: input.tags === undefined ? existing.tags : normalizeList(input.tags),
274
+ requirements,
244
275
  provenance: input.provenance === undefined ? existing.provenance : input.provenance.trim() || existing.provenance,
245
276
  reviewState: 'fresh',
246
277
  staleReason: undefined,
@@ -370,6 +401,13 @@ export class AgentRoutineRegistry {
370
401
  }
371
402
  }
372
403
 
404
+ export function evaluateAgentRoutineReadiness(
405
+ routine: Pick<AgentRoutineRecord, 'requirements'>,
406
+ options: Parameters<typeof evaluateAgentSkillReadiness>[1] = {},
407
+ ): AgentRoutineReadiness {
408
+ return evaluateAgentSkillReadiness(routine, options);
409
+ }
410
+
373
411
  export function buildEnabledRoutinesPrompt(shellPaths: ShellPathService): string | null {
374
412
  const enabled = AgentRoutineRegistry.fromShellPaths(shellPaths).snapshot().enabledRoutines;
375
413
  if (enabled.length === 0) return null;
@@ -382,6 +420,7 @@ export function buildEnabledRoutinesPrompt(shellPaths: ShellPathService): string
382
420
  `Description: ${routine.description}`,
383
421
  `Review state: ${routine.reviewState}`,
384
422
  `Triggers: ${routine.triggers.join(', ') || '(manual)'}`,
423
+ `Readiness: ${evaluateAgentRoutineReadiness(routine).ready ? 'ready' : `missing ${evaluateAgentRoutineReadiness(routine).missing.map(formatAgentSkillRequirement).join(', ')}`}`,
385
424
  routine.steps,
386
425
  '',
387
426
  ]),
@@ -111,13 +111,13 @@ export function formatRoutineScheduleCorrelation(result: RoutineScheduleCorrelat
111
111
  result.baseUrl ? ` runtime: ${result.baseUrl}` : null,
112
112
  ` route: ${ROUTINE_SCHEDULE_LIST_METHOD} ${result.route}`,
113
113
  result.kind === 'auth_required'
114
- ? ' next: pair/authenticate with connected GoodVibes services, then retry.'
114
+ ? ' next: pair/authenticate with the connected GoodVibes host, then retry.'
115
115
  : null,
116
116
  result.kind === 'daemon_unavailable'
117
- ? ' next: make connected GoodVibes services available outside Agent, then retry.'
117
+ ? ' next: make the connected GoodVibes host available outside Agent, then retry.'
118
118
  : null,
119
119
  result.kind === 'version_mismatch' || result.kind === 'daemon_route_unavailable'
120
- ? ' next: update connected GoodVibes services so public schedules.list is available.'
120
+ ? ' next: update the connected GoodVibes host so public schedules.list is available.'
121
121
  : null,
122
122
  ].filter((line): line is string => Boolean(line)).join('\n');
123
123
  }
@@ -166,13 +166,13 @@ export function formatRoutineScheduleFailure(failure: RoutineSchedulePromotionFa
166
166
  ? ` versions: runtime=${failure.daemonVersion} expected=${failure.expectedSdkVersion}`
167
167
  : null,
168
168
  failure.kind === 'auth_required'
169
- ? ' next: pair/authenticate with connected GoodVibes services, then retry with --yes.'
169
+ ? ' next: pair/authenticate with the connected GoodVibes host, then retry with --yes.'
170
170
  : null,
171
171
  failure.kind === 'daemon_unavailable'
172
- ? ' next: make connected GoodVibes services available outside Agent, then retry.'
172
+ ? ' next: make the connected GoodVibes host available outside Agent, then retry.'
173
173
  : null,
174
174
  failure.kind === 'version_mismatch' || failure.kind === 'daemon_route_unavailable'
175
- ? ' next: update connected GoodVibes services so public schedules.create is available.'
175
+ ? ' next: update the connected GoodVibes host so public schedules.create is available.'
176
176
  : null,
177
177
  ].filter((line): line is string => Boolean(line)).join('\n');
178
178
  }
@@ -416,7 +416,7 @@ export async function promoteRoutineToDaemonSchedule(
416
416
  return {
417
417
  ok: false,
418
418
  kind: 'auth_required',
419
- error: `No daemon operator token found at ${connection.tokenPath}`,
419
+ error: `No connected-host operator token found at ${connection.tokenPath}`,
420
420
  route: ROUTINE_SCHEDULE_ROUTE,
421
421
  baseUrl: connection.baseUrl,
422
422
  };