@pellux/goodvibes-agent 0.1.56 → 0.1.58

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 (95) hide show
  1. package/.goodvibes/GOODVIBES.md +1 -1
  2. package/CHANGELOG.md +18 -9
  3. package/README.md +3 -3
  4. package/docs/README.md +1 -1
  5. package/docs/getting-started.md +3 -3
  6. package/docs/release-and-publishing.md +2 -2
  7. package/package.json +1 -3
  8. package/src/agent/routine-schedule-args.ts +219 -0
  9. package/src/agent/routine-schedule-format.ts +173 -0
  10. package/src/agent/routine-schedule-promotion.ts +3 -811
  11. package/src/agent/routine-schedule-receipts.ts +502 -0
  12. package/src/cli/agent-knowledge-command.ts +6 -6
  13. package/src/cli/help.ts +3 -25
  14. package/src/cli/package-verification.ts +23 -16
  15. package/src/cli/redaction.ts +4 -1
  16. package/src/cli/routines-command.ts +10 -6
  17. package/src/cli/service-posture.ts +47 -280
  18. package/src/cli/status.ts +0 -1
  19. package/src/cli/tui-startup.ts +23 -0
  20. package/src/config/secret-config.ts +0 -2
  21. package/src/input/agent-workspace-categories.ts +219 -0
  22. package/src/input/agent-workspace-editors.ts +143 -0
  23. package/src/input/agent-workspace-snapshot.ts +265 -0
  24. package/src/input/agent-workspace-types.ts +142 -0
  25. package/src/input/agent-workspace.ts +22 -766
  26. package/src/input/commands/agent-runtime-profile-runtime.ts +1 -1
  27. package/src/input/commands/delegation-runtime.ts +1 -1
  28. package/src/input/commands/experience-runtime.ts +3 -4
  29. package/src/input/commands/guidance-runtime.ts +1 -2
  30. package/src/input/commands/health-runtime.ts +3 -65
  31. package/src/input/commands/knowledge.ts +7 -7
  32. package/src/input/commands/local-setup-review.ts +0 -61
  33. package/src/input/commands/local-setup-transfer.ts +0 -3
  34. package/src/input/commands/local-setup.ts +2 -15
  35. package/src/input/commands/planning-runtime.ts +4 -1
  36. package/src/input/commands/platform-access-runtime.ts +1 -10
  37. package/src/input/commands/platform-services-runtime.ts +0 -1
  38. package/src/input/commands/recall-query.ts +1 -1
  39. package/src/input/commands/routines-runtime.ts +10 -6
  40. package/src/input/commands/schedule-runtime.ts +10 -6
  41. package/src/input/commands/session-workflow.ts +1 -1
  42. package/src/input/commands/tasks-runtime.ts +1 -14
  43. package/src/input/commands.ts +0 -4
  44. package/src/input/handler-onboarding.ts +10 -120
  45. package/src/input/onboarding/onboarding-wizard-apply.ts +5 -196
  46. package/src/input/onboarding/onboarding-wizard-constants.ts +8 -119
  47. package/src/input/onboarding/onboarding-wizard-helpers.ts +2 -53
  48. package/src/input/onboarding/onboarding-wizard-rules.ts +2 -236
  49. package/src/input/onboarding/onboarding-wizard-state.ts +1 -69
  50. package/src/input/onboarding/onboarding-wizard-steps.ts +584 -737
  51. package/src/input/onboarding/onboarding-wizard-types.ts +8 -26
  52. package/src/input/onboarding/onboarding-wizard.ts +4 -109
  53. package/src/input/settings-modal-agent-policy.ts +10 -0
  54. package/src/input/settings-modal-types.ts +2 -4
  55. package/src/input/settings-modal.ts +3 -1
  56. package/src/input/submission-router.ts +0 -1
  57. package/src/main.ts +13 -12
  58. package/src/panels/approval-panel.ts +1 -2
  59. package/src/panels/builtin/operations.ts +1 -2
  60. package/src/panels/knowledge-panel.ts +2 -2
  61. package/src/panels/project-planning-panel.ts +4 -1
  62. package/src/panels/provider-health-domains.ts +0 -22
  63. package/src/panels/provider-health-panel.ts +1 -5
  64. package/src/panels/session-browser-panel.ts +0 -5
  65. package/src/panels/tasks-panel.ts +2 -64
  66. package/src/renderer/agent-workspace.ts +1 -1
  67. package/src/renderer/help-overlay.ts +1 -2
  68. package/src/renderer/semantic-diff.ts +1 -1
  69. package/src/renderer/settings-modal-helpers.ts +0 -16
  70. package/src/renderer/settings-modal.ts +3 -5
  71. package/src/runtime/bootstrap-hook-bridge.ts +0 -3
  72. package/src/runtime/bootstrap-shell.ts +2 -1
  73. package/src/runtime/bootstrap.ts +1 -1
  74. package/src/runtime/index.ts +0 -1
  75. package/src/runtime/onboarding/derivation.ts +1 -28
  76. package/src/runtime/onboarding/snapshot.ts +0 -1
  77. package/src/runtime/onboarding/types.ts +1 -4
  78. package/src/runtime/services.ts +4 -23
  79. package/src/runtime/ui-read-models.ts +4 -3
  80. package/src/shell/service-settings-sync.ts +15 -244
  81. package/src/tools/agent-context-policy.ts +1 -1
  82. package/src/tools/wrfc-agent-guard.ts +3 -3
  83. package/src/verification/live-verifier.ts +11 -5
  84. package/src/verification/verification-ledger.ts +3 -6
  85. package/src/version.ts +1 -1
  86. package/src/input/commands/agent-externalized-tui.ts +0 -73
  87. package/src/input/commands/cloudflare-runtime.ts +0 -385
  88. package/src/input/handler-onboarding-cloudflare.ts +0 -322
  89. package/src/input/onboarding/onboarding-runtime-status.ts +0 -87
  90. package/src/input/onboarding/onboarding-wizard-cloudflare-step.ts +0 -494
  91. package/src/input/onboarding/onboarding-wizard-cloudflare.ts +0 -199
  92. package/src/input/onboarding/onboarding-wizard-external-surface-extra-specs.ts +0 -130
  93. package/src/input/onboarding/onboarding-wizard-external-surfaces.ts +0 -762
  94. package/src/runtime/cloudflare-control-plane.ts +0 -350
  95. package/src/runtime/sandbox-public-gaps.ts +0 -358
@@ -0,0 +1,219 @@
1
+ import type { AgentWorkspaceCategory } from './agent-workspace-types.ts';
2
+
3
+ export const AGENT_WORKSPACE_CATEGORIES: readonly AgentWorkspaceCategory[] = [
4
+ {
5
+ id: 'home',
6
+ group: 'OPERATE',
7
+ label: 'Home',
8
+ summary: 'Main operator surface for normal assistant work.',
9
+ detail: 'Use this as the Agent front door: chat in the main conversation, inspect state, choose model/provider, and open setup surfaces without switching into coding-TUI behavior.',
10
+ actions: [
11
+ { id: 'chat', label: 'Continue assistant chat', detail: 'Close this workspace and type a normal message. Agent work stays serial in the main conversation.', kind: 'guidance', safety: 'safe' },
12
+ { id: 'model', label: 'Choose model', detail: 'Open the model/provider workspace for the Agent chat route.', command: '/model', kind: 'command', safety: 'safe' },
13
+ { id: 'setup-home', label: 'Setup checklist', detail: 'Jump to the first-run checklist for provider, knowledge, personas, skills, routines, memory, channels, and voice/media.', targetCategoryId: 'setup', kind: 'workspace', safety: 'safe' },
14
+ { id: 'knowledge-home', label: 'Agent Knowledge', detail: 'Jump to isolated Agent Knowledge status, ingest, search, and review flows.', targetCategoryId: 'knowledge', kind: 'workspace', safety: 'read-only' },
15
+ { id: 'memory-home', label: 'Memory, skills, routines', detail: 'Jump to local memory, persona, skill, and routine setup. These are core Agent product features.', targetCategoryId: 'memory', kind: 'workspace', safety: 'safe' },
16
+ { id: 'channels-home', label: 'Channels', detail: 'Jump to companion pairing and channel readiness without changing daemon lifecycle.', targetCategoryId: 'channels', kind: 'workspace', safety: 'read-only' },
17
+ { id: 'voice-home', label: 'Voice and media', detail: 'Jump to voice, TTS, image input, browser, and node posture setup.', targetCategoryId: 'voice-media', kind: 'workspace', safety: 'safe' },
18
+ { id: 'help', label: 'Browse commands', detail: 'Open registry-driven command help.', command: '/help', kind: 'command', safety: 'safe' },
19
+ { id: 'health', label: 'Review health', detail: 'Show the local health review surface without starting or mutating daemon services.', command: '/health review', kind: 'command', safety: 'read-only' },
20
+ ],
21
+ },
22
+ {
23
+ id: 'setup',
24
+ group: 'SETUP',
25
+ label: 'Setup',
26
+ summary: 'Configuration, auth, provider, and onboarding surfaces.',
27
+ detail: 'Agent connects to an external daemon and owns local assistant configuration only. Daemon lifecycle and listener posture remain external.',
28
+ actions: [
29
+ { id: 'config', label: 'Open config workspace', detail: 'Use the TUI-derived fullscreen settings workspace.', command: '/config', kind: 'command', safety: 'safe' },
30
+ { id: 'onboarding', label: 'Open setup wizard', detail: 'Review Agent runtime settings in the fullscreen setup flow.', command: '/onboarding', kind: 'command', safety: 'safe' },
31
+ { id: 'setup-provider-model', label: 'Provider and model', detail: 'Choose the provider/model route for normal assistant chat.', command: '/model', kind: 'command', safety: 'safe' },
32
+ { id: 'setup-agent-knowledge', label: 'Agent Knowledge', detail: 'Inspect the isolated Agent Knowledge store before ingesting source-backed material.', command: '/knowledge status', kind: 'command', safety: 'read-only' },
33
+ { id: 'setup-runtime-profiles', label: 'Runtime profiles', detail: 'Browse starter templates for isolated Agent homes and operator identities.', command: '/agent-profile templates', kind: 'command', safety: 'read-only' },
34
+ { id: 'setup-personas', label: 'Personas', detail: 'Create or select the active local Agent persona.', targetCategoryId: 'personas', kind: 'workspace', safety: 'safe' },
35
+ { id: 'setup-skills', label: 'Skills', detail: 'Create, review, and enable reusable local Agent skills.', targetCategoryId: 'skills', kind: 'workspace', safety: 'safe' },
36
+ { id: 'setup-routines', label: 'Routines', detail: 'Create, review, and enable local Agent routines before any explicit schedule promotion.', targetCategoryId: 'routines', kind: 'workspace', safety: 'safe' },
37
+ { id: 'setup-memory', label: 'Local memory', detail: 'Inspect local/session memory; secrets stay rejected or redacted.', command: '/memory', kind: 'command', safety: 'read-only' },
38
+ { id: 'setup-channels', label: 'Channels', detail: 'Open companion pairing and channel readiness setup.', command: '/pair', kind: 'command', safety: 'safe' },
39
+ { id: 'setup-voice-media', label: 'Voice and media', detail: 'Open TTS/media settings for voice and image-capable Agent flows.', command: '/config tts', kind: 'command', safety: 'safe' },
40
+ { id: 'provider', label: 'Provider status', detail: 'Review provider/model posture.', command: '/provider', kind: 'command', safety: 'read-only' },
41
+ { id: 'auth', label: 'Auth review', detail: 'Review authentication posture without printing token values.', command: '/auth review', kind: 'command', safety: 'read-only' },
42
+ ],
43
+ },
44
+ {
45
+ id: 'channels',
46
+ group: 'SETUP',
47
+ label: 'Channels',
48
+ summary: 'Companion pairing, channel posture, and delivery safety.',
49
+ detail: 'Agent uses externally owned daemon channel surfaces. Pairing, account inspection, and readiness checks are visible here; inbound delivery and public channel exposure stay policy-gated.',
50
+ actions: [
51
+ { id: 'pair', label: 'Pair companion', detail: 'Open the TUI-derived QR pairing surface for companion app setup.', command: '/pair', kind: 'command', safety: 'safe' },
52
+ { id: 'communication', label: 'Communication routes', detail: 'Inspect structured communication routes and recent activity.', command: '/communication', kind: 'command', safety: 'read-only' },
53
+ { id: 'setup-review', label: 'Channel setup review', detail: 'Review setup posture without starting listeners or mutating daemon surface state.', command: '/setup review', kind: 'command', safety: 'read-only' },
54
+ { id: 'channel-safety', label: 'Delivery safety', detail: 'External messages, channel DMs, and public delivery targets require explicit user action and daemon-side policy. Agent will not silently send or expose channels from this workspace.', kind: 'guidance', safety: 'blocked' },
55
+ ],
56
+ },
57
+ {
58
+ id: 'knowledge',
59
+ group: 'KNOW',
60
+ label: 'Knowledge',
61
+ summary: 'Agent Knowledge/Wiki and source-backed lookup.',
62
+ detail: 'Agent knowledge calls must use the isolated /api/goodvibes-agent/knowledge routes. Default regular wiki and non-Agent knowledge segments are not the Agent knowledge environment.',
63
+ actions: [
64
+ { id: 'knowledge-status', label: 'Knowledge status', detail: 'Inspect Agent knowledge readiness and counts.', command: '/knowledge status', kind: 'command', safety: 'read-only' },
65
+ { id: 'knowledge-search', label: 'Search Agent knowledge', detail: 'Search the isolated Agent Knowledge index. Close this workspace and provide an actual query.', command: '/knowledge search <query>', kind: 'command', safety: 'read-only' },
66
+ { id: 'knowledge-ingest-url', label: 'Ingest URL', detail: 'Ingest a URL into Agent Knowledge only. Requires an explicit --yes command with a real URL.', command: '/knowledge ingest-url <url> --yes', kind: 'command', safety: 'safe' },
67
+ { id: 'knowledge-import-bookmarks', label: 'Import bookmarks', detail: 'Import a browser bookmark export into Agent Knowledge only. Requires an explicit --yes command with a real path.', command: '/knowledge import-bookmarks <path> --yes', kind: 'command', safety: 'safe' },
68
+ { id: 'knowledge-review-queue', label: 'Review queue', detail: 'Inspect source/node/issue review work before accepting, rejecting, or resolving anything.', command: '/knowledge queue', kind: 'command', safety: 'read-only' },
69
+ { id: 'knowledge-consolidation', label: 'Consolidation review', detail: 'Inspect consolidation candidates and reports before running Agent Knowledge mutations.', command: '/knowledge candidates', kind: 'command', safety: 'read-only' },
70
+ { id: 'knowledge-ask', label: 'Ask Agent knowledge', detail: 'Close this workspace and run /knowledge ask <question> or ask normally in chat.', kind: 'guidance', safety: 'read-only' },
71
+ ],
72
+ },
73
+ {
74
+ id: 'voice-media',
75
+ group: 'SETUP',
76
+ label: 'Voice, Media & Nodes',
77
+ summary: 'Voice, TTS, image input, browser surface, and node/remote posture.',
78
+ detail: 'Voice, media, browser, and node surfaces are first-class operator surfaces. Agent uses the GoodVibes voice/media/provider/browser/remote bones while keeping daemon ownership external and side effects explicit.',
79
+ actions: [
80
+ { id: 'tts-config', label: 'Configure live TTS', detail: 'Open the TUI-derived config workspace at the TTS settings group.', command: '/config tts', kind: 'command', safety: 'safe' },
81
+ { id: 'tts-provider', label: 'Choose TTS provider', detail: 'Open provider/model routing for spoken responses through the settings flow.', command: '/config tts.provider', kind: 'command', safety: 'safe' },
82
+ { id: 'tts-speak', label: 'Speak a prompt', detail: 'Submit a normal assistant turn and play the reply through configured live TTS. Close this workspace and provide real prompt text.', command: '/tts <prompt>', kind: 'command', safety: 'safe' },
83
+ { id: 'image-attach', label: 'Attach image input', detail: 'Attach an image to the next assistant turn. Close this workspace and provide a real path and prompt.', command: '/image <path> <prompt>', kind: 'command', safety: 'safe' },
84
+ { id: 'browser-surface', label: 'Browser surface status', detail: 'Inspect browser/web posture through setup diagnostics without starting listeners or daemon services.', command: '/setup services', kind: 'command', safety: 'read-only' },
85
+ { id: 'mcp-browser', label: 'Browser MCP tools', detail: 'Inspect MCP servers and tools, including browser/automation roles, without mutating server setup.', command: '/mcp servers', kind: 'command', safety: 'read-only' },
86
+ { id: 'node-posture', label: 'Node/remote posture', detail: 'Inspect remote runner/node posture. Dispatch remains blocked unless the task is explicit build delegation to TUI.', command: '/remote list', kind: 'command', safety: 'read-only' },
87
+ ],
88
+ },
89
+ {
90
+ id: 'profiles',
91
+ group: 'SETUP',
92
+ label: 'Profiles & Portability',
93
+ summary: 'Isolated Agent homes, config profiles, and setup bundles.',
94
+ detail: 'Profiles isolate agent state. GoodVibes Agent exposes named runtime homes, config profile pickers, profile-sync bundles, setup transfer bundles, and support bundles while keeping the daemon external.',
95
+ actions: [
96
+ { id: 'profiles-open', label: 'Open config profiles', detail: 'Open the TUI-derived config profile picker for display/provider/behavior profile files.', command: '/profiles', kind: 'command', safety: 'safe' },
97
+ { id: 'runtime-profile-guide', label: 'Starter authoring guide', detail: 'Open the Agent-local starter authoring flow inside the TUI command surface.', command: '/agent-profile guide', kind: 'command', safety: 'safe' },
98
+ { id: 'runtime-profile-templates', label: 'Browse starter templates', detail: 'List built-in and local Agent starter templates with persona, skill, routine, and source details.', command: '/agent-profile templates', kind: 'command', safety: 'read-only' },
99
+ { id: 'profile-sync-list', label: 'Profile sync list', detail: 'Inspect saved config profiles available for export/import.', command: '/profilesync list', kind: 'command', safety: 'read-only' },
100
+ { id: 'profile-sync-export', label: 'Export profile sync', detail: 'Export config profiles to a portable bundle. Requires a real path and explicit --yes.', command: '/profilesync export <path> --yes', kind: 'command', safety: 'safe' },
101
+ { id: 'setup-transfer-export', label: 'Export setup transfer', detail: 'Export Agent setup transfer data from the current home. Requires a real path and explicit --yes.', command: '/setup transfer export <path> --yes', kind: 'command', safety: 'safe' },
102
+ { id: 'runtime-profile-create', label: 'Create runtime profile', detail: 'Create an isolated Agent runtime profile from a built-in or local starter. Requires a real name and explicit --yes.', command: '/agent-profile create <name> --template <id> --yes', kind: 'command', safety: 'safe' },
103
+ { id: 'runtime-profile-template-edit', label: 'Customize starter', detail: 'Export a starter JSON file, edit it, import it as a local starter, then create a profile from it.', command: '/agent-profile template export <id> <path> --yes', kind: 'command', safety: 'safe' },
104
+ { id: 'runtime-profile-switch', label: 'Switch runtime profile', detail: 'Launch goodvibes-agent --agent-profile <name> to use that isolated Agent home. This workspace cannot switch the current process home after startup.', kind: 'guidance', safety: 'safe' },
105
+ ],
106
+ },
107
+ {
108
+ id: 'memory',
109
+ group: 'LEARN',
110
+ label: 'Memory & Skills',
111
+ summary: 'Local assistant memory, routines, skills, and reusable behavior.',
112
+ detail: 'Memory, routines, skills, and personas stay Agent-local until stable shared daemon registry contracts exist. Secrets must not be stored as memory.',
113
+ actions: [
114
+ { id: 'memory', label: 'Open memory', detail: 'Inspect local/session memory commands and surfaces.', command: '/memory', kind: 'command', safety: 'read-only' },
115
+ { id: 'personas', label: 'Persona library', detail: 'Open the local persona workspace for active role selection and review.', targetCategoryId: 'personas', kind: 'workspace', safety: 'safe' },
116
+ { id: 'skills', label: 'Local skill library', detail: 'Open the local skill workspace for reusable procedures and review.', targetCategoryId: 'skills', kind: 'workspace', safety: 'safe' },
117
+ { id: 'routines', label: 'Routine library', detail: 'Open the local routine workspace for repeatable workflows and schedule promotion review.', targetCategoryId: 'routines', kind: 'workspace', safety: 'safe' },
118
+ ],
119
+ },
120
+ {
121
+ id: 'personas',
122
+ group: 'LEARN',
123
+ label: 'Personas',
124
+ summary: 'Local behavior profiles for the main assistant.',
125
+ detail: 'Personas shape the serial Agent in the main conversation. They are not background agents and they never spawn specialist roots.',
126
+ actions: [
127
+ { id: 'personas-list', label: 'List personas', detail: 'Print the full local persona library.', command: '/personas list', kind: 'command', safety: 'read-only' },
128
+ { id: 'personas-active', label: 'Show active persona', detail: 'Inspect the active local persona applied to new turns.', command: '/personas active', kind: 'command', safety: 'read-only' },
129
+ { id: 'personas-prev', label: 'Previous persona', detail: 'Move the local persona selection up without changing active state.', localKind: 'persona', selectionDelta: -1, kind: 'local-selection', safety: 'safe' },
130
+ { id: 'personas-next', label: 'Next persona', detail: 'Move the local persona selection down without changing active state.', localKind: 'persona', selectionDelta: 1, kind: 'local-selection', safety: 'safe' },
131
+ { id: 'personas-create', label: 'Create persona', detail: 'Open an in-workspace form for a local persona. No placeholder command is dispatched.', editorKind: 'persona', kind: 'editor', safety: 'safe' },
132
+ { id: 'personas-edit', label: 'Edit selected', detail: 'Open the selected local persona in an in-workspace editor.', localKind: 'persona', localOperation: 'persona-edit', kind: 'local-operation', safety: 'safe' },
133
+ { id: 'personas-use', label: 'Use selected', detail: 'Activate the selected local persona for future main-conversation turns.', localKind: 'persona', localOperation: 'persona-use', kind: 'local-operation', safety: 'safe' },
134
+ { id: 'personas-review', label: 'Review selected', detail: 'Mark the selected local persona reviewed after inspecting it.', localKind: 'persona', localOperation: 'persona-review', kind: 'local-operation', safety: 'safe' },
135
+ { id: 'personas-clear', label: 'Clear active persona', detail: 'Return to the default Agent policy without deleting any persona.', localKind: 'persona', localOperation: 'persona-clear', kind: 'local-operation', safety: 'safe' },
136
+ { id: 'personas-delete', label: 'Delete selected', detail: 'Open a confirmation form before deleting the selected local persona.', localKind: 'persona', localOperation: 'persona-delete', kind: 'local-operation', safety: 'safe' },
137
+ ],
138
+ },
139
+ {
140
+ id: 'skills',
141
+ group: 'LEARN',
142
+ label: 'Skills',
143
+ summary: 'Reusable local procedures the assistant can apply on demand.',
144
+ detail: 'Skills are local, reviewable procedures. Enabled skills inform the main conversation; secret-looking content is rejected.',
145
+ actions: [
146
+ { id: 'skills-list', label: 'List skills', detail: 'Print the full local Agent skill library.', command: '/agent-skills list', kind: 'command', safety: 'read-only' },
147
+ { id: 'skills-enabled', label: 'Enabled skills', detail: 'Show only skills currently injected into Agent guidance.', command: '/agent-skills enabled', kind: 'command', safety: 'read-only' },
148
+ { id: 'skills-prev', label: 'Previous skill', detail: 'Move the local skill selection up without changing enabled state.', localKind: 'skill', selectionDelta: -1, kind: 'local-selection', safety: 'safe' },
149
+ { id: 'skills-next', label: 'Next skill', detail: 'Move the local skill selection down without changing enabled state.', localKind: 'skill', selectionDelta: 1, kind: 'local-selection', safety: 'safe' },
150
+ { id: 'skills-create', label: 'Create skill', detail: 'Open an in-workspace form for a reusable local procedure. No placeholder command is dispatched.', editorKind: 'skill', kind: 'editor', safety: 'safe' },
151
+ { id: 'skills-edit', label: 'Edit selected', detail: 'Open the selected local Agent skill in an in-workspace editor.', localKind: 'skill', localOperation: 'skill-edit', kind: 'local-operation', safety: 'safe' },
152
+ { id: 'skills-enable', label: 'Enable selected', detail: 'Enable the selected local Agent skill for future main-conversation guidance.', localKind: 'skill', localOperation: 'skill-enable', kind: 'local-operation', safety: 'safe' },
153
+ { id: 'skills-disable', label: 'Disable selected', detail: 'Disable the selected local Agent skill without deleting it.', localKind: 'skill', localOperation: 'skill-disable', kind: 'local-operation', safety: 'safe' },
154
+ { id: 'skills-review', label: 'Review selected', detail: 'Mark the selected local skill reviewed after inspecting it.', localKind: 'skill', localOperation: 'skill-review', kind: 'local-operation', safety: 'safe' },
155
+ { id: 'skills-delete', label: 'Delete selected', detail: 'Open a confirmation form before deleting the selected local Agent skill.', localKind: 'skill', localOperation: 'skill-delete', kind: 'local-operation', safety: 'safe' },
156
+ ],
157
+ },
158
+ {
159
+ id: 'routines',
160
+ group: 'LEARN',
161
+ label: 'Routines',
162
+ summary: 'Repeatable workflows for the main conversation.',
163
+ detail: 'Routines run in the main conversation by default. Promotion to an external daemon schedule requires a real schedule command and --yes.',
164
+ actions: [
165
+ { id: 'routines-list', label: 'List routines', detail: 'Print the full local Agent routine library.', command: '/routines list', kind: 'command', safety: 'read-only' },
166
+ { id: 'routines-enabled', label: 'Enabled routines', detail: 'Show routines available for direct use.', command: '/routines enabled', kind: 'command', safety: 'read-only' },
167
+ { id: 'routines-prev', label: 'Previous routine', detail: 'Move the local routine selection up without changing enabled state.', localKind: 'routine', selectionDelta: -1, kind: 'local-selection', safety: 'safe' },
168
+ { id: 'routines-next', label: 'Next routine', detail: 'Move the local routine selection down without changing enabled state.', localKind: 'routine', selectionDelta: 1, kind: 'local-selection', safety: 'safe' },
169
+ { id: 'routines-create', label: 'Create routine', detail: 'Open an in-workspace form for a repeatable local workflow. No placeholder command is dispatched.', editorKind: 'routine', kind: 'editor', safety: 'safe' },
170
+ { id: 'routines-edit', label: 'Edit selected', detail: 'Open the selected local Agent routine in an in-workspace editor.', localKind: 'routine', localOperation: 'routine-edit', kind: 'local-operation', safety: 'safe' },
171
+ { id: 'routines-start', label: 'Start selected', detail: 'Mark the selected routine started and show it as a main-conversation workflow. This creates no hidden job.', localKind: 'routine', localOperation: 'routine-start', kind: 'local-operation', safety: 'safe' },
172
+ { id: 'routines-enable', label: 'Enable selected', detail: 'Enable the selected routine for future main-conversation guidance.', localKind: 'routine', localOperation: 'routine-enable', kind: 'local-operation', safety: 'safe' },
173
+ { id: 'routines-disable', label: 'Disable selected', detail: 'Disable the selected routine without deleting it.', localKind: 'routine', localOperation: 'routine-disable', kind: 'local-operation', safety: 'safe' },
174
+ { id: 'routines-review', label: 'Review selected', detail: 'Mark the selected local routine reviewed after inspecting it.', localKind: 'routine', localOperation: 'routine-review', kind: 'local-operation', safety: 'safe' },
175
+ { id: 'routines-delete', label: 'Delete selected', detail: 'Open a confirmation form before deleting the selected local Agent routine.', localKind: 'routine', localOperation: 'routine-delete', kind: 'local-operation', safety: 'safe' },
176
+ { id: 'routines-promote', label: 'Promote to schedule', detail: 'Create an external daemon schedule from a reviewed routine only with real timing and --yes.', command: '/routines promote <id> --cron <expr> --yes', kind: 'command', safety: 'safe' },
177
+ { id: 'routines-receipts', label: 'Promotion receipts', detail: 'Inspect local redacted routine schedule promotion receipts.', command: '/routines receipts', kind: 'command', safety: 'read-only' },
178
+ ],
179
+ },
180
+ {
181
+ id: 'work',
182
+ group: 'TRACK',
183
+ label: 'Work & Approvals',
184
+ summary: 'Visible task state, work plan, and approval posture.',
185
+ detail: 'Use these surfaces to inspect active operator state. Side-effecting approval decisions require explicit commands and confirmation outside this workspace.',
186
+ actions: [
187
+ { id: 'workplan', label: 'Open work plan', detail: 'Open the workspace-scoped work plan panel.', command: '/workplan panel', kind: 'command', safety: 'read-only' },
188
+ { id: 'workplan-list', label: 'List work plan', detail: 'Print a concise work plan summary.', command: '/workplan list', kind: 'command', safety: 'read-only' },
189
+ { id: 'approvals', label: 'Review approvals', detail: 'Open/read approval posture. This workspace does not approve or deny requests.', command: '/approval open', kind: 'command', safety: 'read-only' },
190
+ ],
191
+ },
192
+ {
193
+ id: 'automation',
194
+ group: 'WATCH',
195
+ label: 'Automation',
196
+ summary: 'Automation and schedule observability with explicit routine promotion.',
197
+ detail: 'Agent does not create local automation jobs or hidden scheduler spawns. Reviewed local routines can be promoted into externally owned daemon schedules only through an explicit schedules.create command with --yes, optional delivery targets, and a redacted local receipt.',
198
+ actions: [
199
+ { id: 'schedule-list', label: 'List schedules', detail: 'Inspect configured jobs and history without running or mutating them.', command: '/schedule list', kind: 'command', safety: 'read-only' },
200
+ { id: 'schedule-promote-routine', label: 'Promote routine', detail: 'Create an external daemon schedule from a local Agent routine. Requires a real routine id, schedule expression, optional delivery target, and explicit --yes.', command: '/schedule promote-routine <routine-id> --cron <expr> [--delivery-surface slack] --yes', kind: 'command', safety: 'safe' },
201
+ { id: 'schedule-receipts', label: 'Promotion receipts', detail: 'Review local redacted receipt history for routine-to-daemon schedule promotion attempts.', command: '/schedule receipts', kind: 'command', safety: 'read-only' },
202
+ { id: 'schedule-reconcile', label: 'Reconcile schedules', detail: 'Compare local promotion receipts with live externally owned daemon schedules using schedules.list.', command: '/schedule reconcile', kind: 'command', safety: 'read-only' },
203
+ { id: 'schedule-policy', label: 'Local scheduler blocked', detail: 'Local schedule add/run/remove/enable/disable remain blocked; only explicit external daemon schedule promotion is allowed here.', kind: 'guidance', safety: 'blocked' },
204
+ { id: 'health-services', label: 'Service health', detail: 'Inspect service readiness without starting, stopping, or restarting daemon services.', command: '/health services', kind: 'command', safety: 'read-only' },
205
+ ],
206
+ },
207
+ {
208
+ id: 'delegate',
209
+ group: 'BUILD',
210
+ label: 'Build Delegation',
211
+ summary: 'Explicit handoff to GoodVibes TUI for code work.',
212
+ detail: 'Agent does not become the coding TUI. Build, implement, fix, patch, and review work must be handed to GoodVibes TUI with the full original ask and WRFC only when explicitly requested.',
213
+ actions: [
214
+ { id: 'delegate-guidance', label: 'Delegation rule', detail: 'For build/fix/review work, delegate one request to GoodVibes TUI instead of spawning local Engineer/Reviewer/Tester roots.', kind: 'guidance', safety: 'delegates' },
215
+ { id: 'review-command', label: 'Review delegation command', detail: 'Use /delegate --wrfc <task> only when the user explicitly asks for code review/build execution. Close this workspace and include the actual task text.', kind: 'guidance', safety: 'delegates' },
216
+ { id: 'remote-policy', label: 'Remote runner policy', detail: 'Remote dispatch/rerun is blocked in Agent; TUI owns runner topology for delegated build work.', command: '/remote dispatch', kind: 'command', safety: 'blocked' },
217
+ ],
218
+ },
219
+ ];
@@ -0,0 +1,143 @@
1
+ import type { AgentPersonaRecord } from '../agent/persona-registry.ts';
2
+ import type { AgentRoutineRecord } from '../agent/routine-registry.ts';
3
+ import type { AgentSkillRecord } from '../agent/skill-registry.ts';
4
+ import type { AgentWorkspaceLocalEditor, AgentWorkspaceLocalEditorKind, AgentWorkspaceLocalLibraryItem } from './agent-workspace-types.ts';
5
+
6
+ export function createLocalEditor(kind: AgentWorkspaceLocalEditorKind): AgentWorkspaceLocalEditor {
7
+ if (kind === 'persona') {
8
+ return {
9
+ kind,
10
+ mode: 'create',
11
+ title: 'Create Persona',
12
+ selectedFieldIndex: 0,
13
+ message: 'Enter a local behavior profile for the serial main-conversation assistant.',
14
+ fields: [
15
+ { id: 'name', label: 'Name', value: '', required: true, multiline: false, hint: 'Short persona name.' },
16
+ { id: 'description', label: 'Description', value: '', required: true, multiline: false, hint: 'One-line summary of when to use it.' },
17
+ { id: 'body', label: 'Instructions', value: '', required: true, multiline: true, hint: 'Operating guidance. Ctrl-J inserts a new line.' },
18
+ { id: 'tags', label: 'Tags', value: '', required: false, multiline: false, hint: 'Comma-separated optional tags.' },
19
+ { id: 'triggers', label: 'Triggers', value: '', required: false, multiline: false, hint: 'Comma-separated words that suggest this persona.' },
20
+ { id: 'activate', label: 'Activate now', value: 'yes', required: false, multiline: false, hint: 'yes/no.' },
21
+ ],
22
+ };
23
+ }
24
+ if (kind === 'skill') {
25
+ return {
26
+ kind,
27
+ mode: 'create',
28
+ title: 'Create Skill',
29
+ selectedFieldIndex: 0,
30
+ message: 'Enter a reusable local procedure the assistant can apply from the main conversation.',
31
+ fields: [
32
+ { id: 'name', label: 'Name', value: '', required: true, multiline: false, hint: 'Short skill name.' },
33
+ { id: 'description', label: 'Description', value: '', required: true, multiline: false, hint: 'One-line summary of the procedure.' },
34
+ { id: 'procedure', label: 'Procedure', value: '', required: true, multiline: true, hint: 'Reusable steps. Ctrl-J inserts a new line.' },
35
+ { id: 'triggers', label: 'Triggers', value: '', required: false, multiline: false, hint: 'Comma-separated words that suggest this skill.' },
36
+ { id: 'tags', label: 'Tags', value: '', required: false, multiline: false, hint: 'Comma-separated optional tags.' },
37
+ { id: 'enabled', label: 'Enable now', value: 'yes', required: false, multiline: false, hint: 'yes/no.' },
38
+ ],
39
+ };
40
+ }
41
+ return {
42
+ kind,
43
+ mode: 'create',
44
+ title: 'Create Routine',
45
+ selectedFieldIndex: 0,
46
+ message: 'Enter a repeatable workflow. It runs in the main conversation unless explicitly promoted to a daemon schedule.',
47
+ fields: [
48
+ { id: 'name', label: 'Name', value: '', required: true, multiline: false, hint: 'Short routine name.' },
49
+ { id: 'description', label: 'Description', value: '', required: true, multiline: false, hint: 'One-line summary of the workflow.' },
50
+ { id: 'steps', label: 'Steps', value: '', required: true, multiline: true, hint: 'Workflow steps. Ctrl-J inserts a new line.' },
51
+ { id: 'triggers', label: 'Triggers', value: '', required: false, multiline: false, hint: 'Comma-separated words that suggest this routine.' },
52
+ { id: 'tags', label: 'Tags', value: '', required: false, multiline: false, hint: 'Comma-separated optional tags.' },
53
+ { id: 'enabled', label: 'Enable now', value: 'yes', required: false, multiline: false, hint: 'yes/no.' },
54
+ ],
55
+ };
56
+ }
57
+
58
+ export function createPersonaUpdateEditor(record: AgentPersonaRecord, active: boolean): AgentWorkspaceLocalEditor {
59
+ return {
60
+ kind: 'persona',
61
+ mode: 'update',
62
+ recordId: record.id,
63
+ title: 'Edit Persona',
64
+ selectedFieldIndex: 0,
65
+ message: `Editing ${record.name}. Saving marks it fresh for review.`,
66
+ fields: [
67
+ { id: 'name', label: 'Name', value: record.name, required: true, multiline: false, hint: 'Short persona name.' },
68
+ { id: 'description', label: 'Description', value: record.description, required: true, multiline: false, hint: 'One-line summary of when to use it.' },
69
+ { id: 'body', label: 'Instructions', value: record.body, required: true, multiline: true, hint: 'Operating guidance. Ctrl-J inserts a new line.' },
70
+ { id: 'tags', label: 'Tags', value: record.tags.join(', '), required: false, multiline: false, hint: 'Comma-separated optional tags.' },
71
+ { id: 'triggers', label: 'Triggers', value: record.triggers.join(', '), required: false, multiline: false, hint: 'Comma-separated words that suggest this persona.' },
72
+ { id: 'activate', label: 'Active', value: active ? 'yes' : 'no', required: false, multiline: false, hint: 'yes/no. Setting no clears this persona only if it is currently active.' },
73
+ ],
74
+ };
75
+ }
76
+
77
+ export function createSkillUpdateEditor(record: AgentSkillRecord): AgentWorkspaceLocalEditor {
78
+ return {
79
+ kind: 'skill',
80
+ mode: 'update',
81
+ recordId: record.id,
82
+ title: 'Edit Skill',
83
+ selectedFieldIndex: 0,
84
+ message: `Editing ${record.name}. Saving marks it fresh for review.`,
85
+ fields: [
86
+ { id: 'name', label: 'Name', value: record.name, required: true, multiline: false, hint: 'Short skill name.' },
87
+ { id: 'description', label: 'Description', value: record.description, required: true, multiline: false, hint: 'One-line summary of the procedure.' },
88
+ { id: 'procedure', label: 'Procedure', value: record.procedure, required: true, multiline: true, hint: 'Reusable steps. Ctrl-J inserts a new line.' },
89
+ { id: 'triggers', label: 'Triggers', value: record.triggers.join(', '), required: false, multiline: false, hint: 'Comma-separated words that suggest this skill.' },
90
+ { id: 'tags', label: 'Tags', value: record.tags.join(', '), required: false, multiline: false, hint: 'Comma-separated optional tags.' },
91
+ { id: 'enabled', label: 'Enabled', value: record.enabled ? 'yes' : 'no', required: false, multiline: false, hint: 'yes/no.' },
92
+ ],
93
+ };
94
+ }
95
+
96
+ export function createRoutineUpdateEditor(record: AgentRoutineRecord): AgentWorkspaceLocalEditor {
97
+ return {
98
+ kind: 'routine',
99
+ mode: 'update',
100
+ recordId: record.id,
101
+ title: 'Edit Routine',
102
+ selectedFieldIndex: 0,
103
+ message: `Editing ${record.name}. Saving marks it fresh for review.`,
104
+ fields: [
105
+ { id: 'name', label: 'Name', value: record.name, required: true, multiline: false, hint: 'Short routine name.' },
106
+ { id: 'description', label: 'Description', value: record.description, required: true, multiline: false, hint: 'One-line summary of the workflow.' },
107
+ { id: 'steps', label: 'Steps', value: record.steps, required: true, multiline: true, hint: 'Workflow steps. Ctrl-J inserts a new line.' },
108
+ { id: 'triggers', label: 'Triggers', value: record.triggers.join(', '), required: false, multiline: false, hint: 'Comma-separated words that suggest this routine.' },
109
+ { id: 'tags', label: 'Tags', value: record.tags.join(', '), required: false, multiline: false, hint: 'Comma-separated optional tags.' },
110
+ { id: 'enabled', label: 'Enabled', value: record.enabled ? 'yes' : 'no', required: false, multiline: false, hint: 'yes/no.' },
111
+ ],
112
+ };
113
+ }
114
+
115
+ export function createDeleteEditor(kind: AgentWorkspaceLocalEditorKind, item: AgentWorkspaceLocalLibraryItem): AgentWorkspaceLocalEditor {
116
+ const label = kind[0]!.toUpperCase() + kind.slice(1);
117
+ return {
118
+ kind,
119
+ mode: 'delete',
120
+ recordId: item.id,
121
+ title: `Delete ${label}`,
122
+ selectedFieldIndex: 0,
123
+ message: `Type ${item.id} exactly to delete ${item.name}. This only changes the Agent-local registry.`,
124
+ fields: [
125
+ { id: 'confirm', label: 'Confirm id', value: '', required: true, multiline: false, hint: `Type ${item.id} exactly.` },
126
+ ],
127
+ };
128
+ }
129
+
130
+ export function splitList(value: string): string[] {
131
+ return value.split(',').map((part) => part.trim()).filter(Boolean);
132
+ }
133
+
134
+ export function isAffirmative(value: string): boolean {
135
+ const normalized = value.trim().toLowerCase();
136
+ return normalized === '' || normalized === 'yes' || normalized === 'y' || normalized === 'true' || normalized === 'enabled' || normalized === 'on';
137
+ }
138
+
139
+ export function editorCategoryId(kind: AgentWorkspaceLocalEditorKind): string {
140
+ if (kind === 'persona') return 'personas';
141
+ if (kind === 'skill') return 'skills';
142
+ return 'routines';
143
+ }