@pellux/goodvibes-agent 0.1.114 → 0.1.116

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.
@@ -46,8 +46,12 @@ bun run dev
46
46
 
47
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.
48
48
 
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.
50
+
49
51
  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.
50
52
 
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.
54
+
51
55
  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.
52
56
 
53
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`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pellux/goodvibes-agent",
3
- "version": "0.1.114",
3
+ "version": "0.1.116",
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",
@@ -0,0 +1,167 @@
1
+ import { readdirSync, readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import type { ShellPathService } from '@/runtime/index.ts';
4
+ import { GOODVIBES_AGENT_SURFACE_ROOT } from '../config/surface.ts';
5
+
6
+ type DiscoveryOrigin = 'project-local' | 'global';
7
+
8
+ interface DiscoveryRoot {
9
+ readonly root: string;
10
+ readonly origin: DiscoveryOrigin;
11
+ }
12
+
13
+ interface DiscoveryKindDefinition {
14
+ readonly roots: readonly DiscoveryRoot[];
15
+ readonly markers: readonly string[];
16
+ readonly frontmatterBodyKey?: string;
17
+ }
18
+
19
+ export interface AgentBehaviorDiscoverySummary {
20
+ readonly count: number;
21
+ readonly projectLocalCount: number;
22
+ readonly globalCount: number;
23
+ readonly names: readonly string[];
24
+ }
25
+
26
+ export interface AgentBehaviorDiscoverySnapshot {
27
+ readonly personas: AgentBehaviorDiscoverySummary;
28
+ readonly skills: AgentBehaviorDiscoverySummary;
29
+ readonly routines: AgentBehaviorDiscoverySummary;
30
+ }
31
+
32
+ const EMPTY_SUMMARY: AgentBehaviorDiscoverySummary = {
33
+ count: 0,
34
+ projectLocalCount: 0,
35
+ globalCount: 0,
36
+ names: [],
37
+ };
38
+
39
+ export const EMPTY_AGENT_BEHAVIOR_DISCOVERY_SNAPSHOT: AgentBehaviorDiscoverySnapshot = {
40
+ personas: EMPTY_SUMMARY,
41
+ skills: EMPTY_SUMMARY,
42
+ routines: EMPTY_SUMMARY,
43
+ };
44
+
45
+ function parseFrontmatter(content: string): Record<string, string> {
46
+ const match = content.match(/^---\n([\s\S]*?)\n---/);
47
+ if (!match) return {};
48
+ const result: Record<string, string> = {};
49
+ for (const line of match[1].split('\n')) {
50
+ const [key, ...rest] = line.split(':');
51
+ if (key && rest.length > 0) {
52
+ result[key.trim()] = rest.join(':').trim();
53
+ }
54
+ }
55
+ return result;
56
+ }
57
+
58
+ function markdownBody(content: string): string {
59
+ return content.replace(/^---\n[\s\S]*?\n---\n?/, '').trim();
60
+ }
61
+
62
+ function readDiscoveryCandidate(path: string, origin: DiscoveryOrigin, definition: DiscoveryKindDefinition): { readonly name: string; readonly origin: DiscoveryOrigin } | null {
63
+ let content = '';
64
+ try {
65
+ content = readFileSync(path, 'utf-8');
66
+ } catch {
67
+ return null;
68
+ }
69
+
70
+ const frontmatter = parseFrontmatter(content);
71
+ const body = definition.frontmatterBodyKey
72
+ ? (frontmatter[definition.frontmatterBodyKey] ?? markdownBody(content)).trim()
73
+ : markdownBody(content);
74
+ if (body.length === 0) return null;
75
+ const name = frontmatter.name ?? path.split(/[\\/]/).pop()?.replace(/\.md$/i, '') ?? '';
76
+ const normalized = name.trim();
77
+ return normalized ? { name: normalized, origin } : null;
78
+ }
79
+
80
+ function candidatePaths(root: string, entry: string, markers: readonly string[]): readonly string[] {
81
+ if (entry.endsWith('.md')) return [join(root, entry)];
82
+ return markers.map((marker) => join(root, entry, marker));
83
+ }
84
+
85
+ function summarizeDefinition(definition: DiscoveryKindDefinition, limit: number): AgentBehaviorDiscoverySummary {
86
+ const seen = new Set<string>();
87
+ const names: string[] = [];
88
+ let projectLocalCount = 0;
89
+ let globalCount = 0;
90
+
91
+ for (const { root, origin } of definition.roots) {
92
+ let entries: string[] = [];
93
+ try {
94
+ entries = readdirSync(root);
95
+ } catch {
96
+ continue;
97
+ }
98
+ for (const entry of entries.sort((left, right) => left.localeCompare(right))) {
99
+ for (const path of candidatePaths(root, entry, definition.markers)) {
100
+ const candidate = readDiscoveryCandidate(path, origin, definition);
101
+ if (!candidate) continue;
102
+ const key = candidate.name.toLowerCase();
103
+ if (seen.has(key)) break;
104
+ seen.add(key);
105
+ if (candidate.origin === 'project-local') projectLocalCount += 1;
106
+ else globalCount += 1;
107
+ if (names.length < limit) names.push(candidate.name);
108
+ break;
109
+ }
110
+ }
111
+ }
112
+
113
+ if (seen.size === 0) return EMPTY_SUMMARY;
114
+ return {
115
+ count: seen.size,
116
+ projectLocalCount,
117
+ globalCount,
118
+ names,
119
+ };
120
+ }
121
+
122
+ function definitions(shellPaths: Pick<ShellPathService, 'workingDirectory' | 'homeDirectory'>): AgentBehaviorDiscoverySnapshot {
123
+ const cwd = shellPaths.workingDirectory;
124
+ const homeDir = shellPaths.homeDirectory;
125
+ const personas: DiscoveryKindDefinition = {
126
+ roots: [
127
+ { root: join(cwd, '.goodvibes', 'personas'), origin: 'project-local' },
128
+ { root: join(cwd, '.goodvibes', GOODVIBES_AGENT_SURFACE_ROOT, 'personas'), origin: 'project-local' },
129
+ { root: join(cwd, '.goodvibes', 'agents'), origin: 'project-local' },
130
+ { root: join(homeDir, '.goodvibes', 'personas'), origin: 'global' },
131
+ { root: join(homeDir, '.goodvibes', GOODVIBES_AGENT_SURFACE_ROOT, 'personas'), origin: 'global' },
132
+ { root: join(homeDir, '.goodvibes', 'agents'), origin: 'global' },
133
+ ],
134
+ markers: ['PERSONA.md', 'persona.md', 'AGENT.md', 'agent.md'],
135
+ frontmatterBodyKey: 'system_prompt',
136
+ };
137
+ const skills: DiscoveryKindDefinition = {
138
+ roots: [
139
+ { root: join(cwd, '.goodvibes', 'skills'), origin: 'project-local' },
140
+ { root: join(cwd, '.goodvibes', GOODVIBES_AGENT_SURFACE_ROOT, 'skills'), origin: 'project-local' },
141
+ { root: join(homeDir, '.goodvibes', 'skills'), origin: 'global' },
142
+ { root: join(homeDir, '.goodvibes', GOODVIBES_AGENT_SURFACE_ROOT, 'skills'), origin: 'global' },
143
+ ],
144
+ markers: ['SKILL.md'],
145
+ };
146
+ const routines: DiscoveryKindDefinition = {
147
+ roots: [
148
+ { root: join(cwd, '.goodvibes', 'routines'), origin: 'project-local' },
149
+ { root: join(cwd, '.goodvibes', GOODVIBES_AGENT_SURFACE_ROOT, 'routines'), origin: 'project-local' },
150
+ { root: join(homeDir, '.goodvibes', 'routines'), origin: 'global' },
151
+ { root: join(homeDir, '.goodvibes', GOODVIBES_AGENT_SURFACE_ROOT, 'routines'), origin: 'global' },
152
+ ],
153
+ markers: ['ROUTINE.md', 'routine.md'],
154
+ frontmatterBodyKey: 'steps',
155
+ };
156
+
157
+ return {
158
+ personas: summarizeDefinition(personas, 4),
159
+ skills: summarizeDefinition(skills, 4),
160
+ routines: summarizeDefinition(routines, 4),
161
+ };
162
+ }
163
+
164
+ export function summarizeAgentBehaviorDiscovery(shellPaths: Pick<ShellPathService, 'workingDirectory' | 'homeDirectory'> | undefined): AgentBehaviorDiscoverySnapshot {
165
+ if (!shellPaths) return EMPTY_AGENT_BEHAVIOR_DISCOVERY_SNAPSHOT;
166
+ return definitions(shellPaths);
167
+ }
@@ -0,0 +1,331 @@
1
+ import type { AgentRuntimeProfileTemplateSummary } from './runtime-profile.ts';
2
+
3
+ export interface AgentRuntimeProfileStarterTemplate extends AgentRuntimeProfileTemplateSummary {
4
+ readonly persona: {
5
+ readonly name: string;
6
+ readonly description: string;
7
+ readonly body: string;
8
+ readonly tags: readonly string[];
9
+ readonly triggers: readonly string[];
10
+ };
11
+ readonly skills: readonly {
12
+ readonly name: string;
13
+ readonly description: string;
14
+ readonly procedure: string;
15
+ readonly triggers: readonly string[];
16
+ readonly tags: readonly string[];
17
+ }[];
18
+ readonly routines: readonly {
19
+ readonly name: string;
20
+ readonly description: string;
21
+ readonly steps: string;
22
+ readonly triggers: readonly string[];
23
+ readonly tags: readonly string[];
24
+ }[];
25
+ }
26
+
27
+ export interface AgentRuntimeProfileStarterTemplateFile {
28
+ readonly version: 1;
29
+ readonly template: AgentRuntimeProfileStarterTemplate;
30
+ }
31
+
32
+ export const STARTER_TEMPLATES: readonly AgentRuntimeProfileStarterTemplate[] = [
33
+ {
34
+ id: 'household',
35
+ source: 'builtin',
36
+ name: 'Household Operator',
37
+ description: 'Coordinate household tasks, home service checks, shared routines, and family logistics.',
38
+ personaName: 'Household Operator',
39
+ skillNames: ['Household Triage', 'Home Service Check'],
40
+ routineNames: ['Weekly Household Review'],
41
+ persona: {
42
+ name: 'Household Operator',
43
+ description: 'Practical assistant for home operations, shared chores, services, and family logistics.',
44
+ body: [
45
+ 'Operate as a calm household coordinator.',
46
+ 'Track preferences, routines, device/service notes, and recurring decisions in Agent-local memory after they are durable and non-secret.',
47
+ 'Use read-only daemon/operator routes for status checks. Require explicit approval for purchases, messages to other people, service changes, deletions, or secret handling.',
48
+ 'Keep replies concrete: next action, owner, date, and open question when one is needed.',
49
+ ].join('\n'),
50
+ tags: ['household', 'home', 'coordination'],
51
+ triggers: ['home', 'household', 'family', 'chores', 'errands'],
52
+ },
53
+ skills: [
54
+ {
55
+ name: 'Household Triage',
56
+ description: 'Turn a household request into owner, urgency, next step, and reminder/delegation posture.',
57
+ procedure: [
58
+ '1. Identify whether the task is information, coordination, purchase, repair, or reminder.',
59
+ '2. Check Agent-local memory for known preferences or constraints before asking repeat questions.',
60
+ '3. Propose the next non-destructive action. Ask before external messages, payments, account changes, or device/service changes.',
61
+ '4. Record durable non-secret decisions locally with provenance.',
62
+ ].join('\n'),
63
+ triggers: ['plan household', 'home task', 'family logistics'],
64
+ tags: ['household', 'triage'],
65
+ },
66
+ {
67
+ name: 'Home Service Check',
68
+ description: 'Review configured services and surface actionable household status without taking hidden action.',
69
+ procedure: [
70
+ '1. Inspect configured read-only status, approval, schedule, and knowledge routes.',
71
+ '2. Summarize degraded services, pending approvals, and stale routines.',
72
+ '3. Suggest explicit commands for approved follow-up instead of mutating services directly.',
73
+ ].join('\n'),
74
+ triggers: ['home status', 'service check', 'household check'],
75
+ tags: ['household', 'ops'],
76
+ },
77
+ ],
78
+ routines: [
79
+ {
80
+ name: 'Weekly Household Review',
81
+ description: 'Review open household commitments, pending approvals, and stale home notes.',
82
+ steps: [
83
+ '1. List pending local routines, workplan tasks, and approvals.',
84
+ '2. Summarize what changed since the last review from local Agent state.',
85
+ '3. Ask for confirmation before scheduling, sending messages, purchasing, or changing services.',
86
+ '4. Record reviewed preferences and stale notes locally.',
87
+ ].join('\n'),
88
+ triggers: ['weekly review', 'household review'],
89
+ tags: ['household', 'review'],
90
+ },
91
+ ],
92
+ },
93
+ {
94
+ id: 'research',
95
+ source: 'builtin',
96
+ name: 'Research Analyst',
97
+ description: 'Source-grounded research, brief generation, question tracking, and evidence review.',
98
+ personaName: 'Research Analyst',
99
+ skillNames: ['Source-grounded Brief', 'Research Gap Tracker'],
100
+ routineNames: ['Research Packet Review'],
101
+ persona: {
102
+ name: 'Research Analyst',
103
+ description: 'Evidence-first analyst for research questions, summaries, and decision support.',
104
+ body: [
105
+ 'Prefer primary sources and cite provenance clearly.',
106
+ 'Use Agent Knowledge only through the isolated Agent knowledge routes.',
107
+ 'Separate findings, confidence, gaps, and recommendations.',
108
+ 'Do not store secrets or unsupported claims as durable knowledge.',
109
+ ].join('\n'),
110
+ tags: ['research', 'analysis', 'evidence'],
111
+ triggers: ['research', 'brief', 'compare', 'investigate'],
112
+ },
113
+ skills: [
114
+ {
115
+ name: 'Source-grounded Brief',
116
+ description: 'Produce concise findings with source provenance and confidence.',
117
+ procedure: [
118
+ '1. Clarify the decision or question if the request is ambiguous.',
119
+ '2. Search current sources when freshness matters.',
120
+ '3. Return answer, evidence, confidence, gaps, and suggested follow-up.',
121
+ '4. Save durable, reviewed, non-secret facts to Agent-local memory only when useful later.',
122
+ ].join('\n'),
123
+ triggers: ['brief me', 'research this', 'compare options'],
124
+ tags: ['research', 'briefing'],
125
+ },
126
+ {
127
+ name: 'Research Gap Tracker',
128
+ description: 'Maintain open research questions and stale assumptions.',
129
+ procedure: [
130
+ '1. Extract unknowns, weak evidence, and stale facts from the current task.',
131
+ '2. Convert actionable follow-up into workplan or local routine guidance only after explicit user direction.',
132
+ '3. Mark resolved gaps with source and date.',
133
+ ].join('\n'),
134
+ triggers: ['research gaps', 'unknowns', 'follow up'],
135
+ tags: ['research', 'quality'],
136
+ },
137
+ ],
138
+ routines: [
139
+ {
140
+ name: 'Research Packet Review',
141
+ description: 'Review recent research notes for stale assumptions and missing citations.',
142
+ steps: [
143
+ '1. Inspect local memory/skills/personas relevant to the current topic.',
144
+ '2. Identify claims lacking provenance.',
145
+ '3. Recommend refresh searches for time-sensitive claims.',
146
+ '4. Mark stale local notes instead of deleting them without explicit command intent.',
147
+ ].join('\n'),
148
+ triggers: ['review research', 'research packet'],
149
+ tags: ['research', 'review'],
150
+ },
151
+ ],
152
+ },
153
+ {
154
+ id: 'travel',
155
+ source: 'builtin',
156
+ name: 'Travel Planner',
157
+ description: 'Trip planning, itinerary decisions, packing, local constraints, and travel follow-through.',
158
+ personaName: 'Travel Planner',
159
+ skillNames: ['Trip Decision Matrix', 'Travel Checklist Builder'],
160
+ routineNames: ['Pre-trip Readiness Review'],
161
+ persona: {
162
+ name: 'Travel Planner',
163
+ description: 'Travel planning assistant focused on constraints, itinerary tradeoffs, and readiness.',
164
+ body: [
165
+ 'Track destinations, dates, preferences, constraints, and open decisions locally.',
166
+ 'Search current details for prices, schedules, visa/rule changes, weather, and safety.',
167
+ 'Ask before bookings, purchases, external messages, or account changes.',
168
+ 'Keep recommendations practical and time-aware.',
169
+ ].join('\n'),
170
+ tags: ['travel', 'planning', 'logistics'],
171
+ triggers: ['trip', 'travel', 'itinerary', 'flight', 'hotel'],
172
+ },
173
+ skills: [
174
+ {
175
+ name: 'Trip Decision Matrix',
176
+ description: 'Compare travel options against user constraints and live facts.',
177
+ procedure: [
178
+ '1. List hard constraints: dates, budget, location, accessibility, work needs, and risk tolerance.',
179
+ '2. Search current schedule/price/rule data when decisions depend on fresh details.',
180
+ '3. Present ranked options with tradeoffs and next checks.',
181
+ '4. Ask for confirmation before bookings or payments.',
182
+ ].join('\n'),
183
+ triggers: ['choose travel', 'compare hotels', 'compare flights'],
184
+ tags: ['travel', 'decision'],
185
+ },
186
+ {
187
+ name: 'Travel Checklist Builder',
188
+ description: 'Create trip-specific prep lists and reminders from known constraints.',
189
+ procedure: [
190
+ '1. Infer trip type and constraints from the current conversation and local memory.',
191
+ '2. Build checklist sections for documents, packing, transport, lodging, work, health, and communications.',
192
+ '3. Keep tasks local until the user explicitly requests scheduling or external coordination.',
193
+ ].join('\n'),
194
+ triggers: ['packing list', 'trip checklist', 'travel prep'],
195
+ tags: ['travel', 'checklist'],
196
+ },
197
+ ],
198
+ routines: [
199
+ {
200
+ name: 'Pre-trip Readiness Review',
201
+ description: 'Check documents, reservations, transport, packing, weather, and open decisions.',
202
+ steps: [
203
+ '1. Review trip dates, locations, reservations, and open decisions from local Agent state.',
204
+ '2. Refresh current weather, schedule, and rule data when needed.',
205
+ '3. Summarize blockers and next confirmed action.',
206
+ '4. Ask before external sends, purchases, or reservation changes.',
207
+ ].join('\n'),
208
+ triggers: ['pre trip review', 'before travel'],
209
+ tags: ['travel', 'review'],
210
+ },
211
+ ],
212
+ },
213
+ {
214
+ id: 'operations',
215
+ source: 'builtin',
216
+ name: 'Operations Lead',
217
+ description: 'Operational monitoring, incident triage, approvals, schedules, and service health.',
218
+ personaName: 'Operations Lead',
219
+ skillNames: ['Incident Intake', 'Approval Review'],
220
+ routineNames: ['Daily Operations Sweep'],
221
+ persona: {
222
+ name: 'Operations Lead',
223
+ description: 'Operator persona for systems, incidents, runbooks, approvals, and service posture.',
224
+ body: [
225
+ 'Favor explicit state, logs, health, approvals, and next action.',
226
+ 'Use read-only daemon/operator routes by default.',
227
+ 'Require explicit confirmation for run, pause, resume, cancel, retry, approve, deny, service changes, or writes.',
228
+ 'Delegate code/build fixes to GoodVibes TUI when explicitly requested.',
229
+ ].join('\n'),
230
+ tags: ['operations', 'incident', 'runbook'],
231
+ triggers: ['incident', 'ops', 'approval', 'automation', 'service'],
232
+ },
233
+ skills: [
234
+ {
235
+ name: 'Incident Intake',
236
+ description: 'Convert a symptom into severity, suspected system, evidence, and next safe checks.',
237
+ procedure: [
238
+ '1. Identify symptom, affected surface, time window, severity, and user impact.',
239
+ '2. Pull read-only status, approvals, schedules, runs, and workplan summaries.',
240
+ '3. Separate evidence from hypothesis.',
241
+ '4. Ask before mutating services, automation, schedules, or approvals.',
242
+ ].join('\n'),
243
+ triggers: ['incident', 'outage', 'broken', 'triage'],
244
+ tags: ['operations', 'incident'],
245
+ },
246
+ {
247
+ name: 'Approval Review',
248
+ description: 'Summarize pending approvals with risk, route, and required decision.',
249
+ procedure: [
250
+ '1. List pending approvals and classify risk labels.',
251
+ '2. Explain what each approval would allow.',
252
+ '3. Only approve, deny, or cancel from exact user command with confirmation.',
253
+ ].join('\n'),
254
+ triggers: ['approvals', 'pending approval', 'review approvals'],
255
+ tags: ['operations', 'approvals'],
256
+ },
257
+ ],
258
+ routines: [
259
+ {
260
+ name: 'Daily Operations Sweep',
261
+ description: 'Inspect service posture, pending approvals, failed runs, and stale tasks.',
262
+ steps: [
263
+ '1. Refresh daemon status, compat, approvals, workplan, automation snapshot, runs, schedules, and capacity.',
264
+ '2. Summarize degraded items and blocked work.',
265
+ '3. Recommend exact follow-up commands with confirmation gates for side effects.',
266
+ ].join('\n'),
267
+ triggers: ['daily ops', 'operations sweep'],
268
+ tags: ['operations', 'review'],
269
+ },
270
+ ],
271
+ },
272
+ {
273
+ id: 'personal-productivity',
274
+ source: 'builtin',
275
+ name: 'Personal Productivity',
276
+ description: 'Task capture, weekly planning, focus blocks, reminders, and decision hygiene.',
277
+ personaName: 'Personal Productivity Coach',
278
+ skillNames: ['Inbox Zero Triage', 'Focus Block Planner'],
279
+ routineNames: ['Weekly Personal Planning'],
280
+ persona: {
281
+ name: 'Personal Productivity Coach',
282
+ description: 'Personal assistant for task capture, planning, prioritization, and follow-through.',
283
+ body: [
284
+ 'Keep planning lightweight and action-oriented.',
285
+ 'Capture durable preferences, commitments, and constraints locally when they are useful later.',
286
+ 'Prefer one clear next action over broad plans.',
287
+ 'Ask before sending messages, spending money, changing services, or deleting records.',
288
+ ].join('\n'),
289
+ tags: ['productivity', 'planning', 'personal'],
290
+ triggers: ['plan my day', 'prioritize', 'tasks', 'focus'],
291
+ },
292
+ skills: [
293
+ {
294
+ name: 'Inbox Zero Triage',
295
+ description: 'Sort loose tasks into do, delegate, defer, drop, or ask-for-info.',
296
+ procedure: [
297
+ '1. Capture each item as an outcome and next action.',
298
+ '2. Classify by urgency, effort, dependency, and consequence.',
299
+ '3. Recommend a short ordered list for today and parking lot for later.',
300
+ '4. Store durable commitments locally with source and date.',
301
+ ].join('\n'),
302
+ triggers: ['triage tasks', 'organize tasks', 'inbox'],
303
+ tags: ['productivity', 'triage'],
304
+ },
305
+ {
306
+ name: 'Focus Block Planner',
307
+ description: 'Design realistic focus blocks around constraints and energy.',
308
+ procedure: [
309
+ '1. Identify available time, constraints, and high-value outcome.',
310
+ '2. Split work into 25-90 minute blocks with breakpoints.',
311
+ '3. Keep schedule changes local unless the user explicitly asks for calendar or external updates.',
312
+ ].join('\n'),
313
+ triggers: ['focus block', 'plan my day', 'deep work'],
314
+ tags: ['productivity', 'focus'],
315
+ },
316
+ ],
317
+ routines: [
318
+ {
319
+ name: 'Weekly Personal Planning',
320
+ description: 'Review commitments, priorities, routines, and open decisions for the week.',
321
+ steps: [
322
+ '1. Review local tasks, routines, memory, and recent decisions.',
323
+ '2. Identify top outcomes, blockers, and decisions needed from the user.',
324
+ '3. Suggest a small weekly plan and ask before creating external reminders or sending messages.',
325
+ ].join('\n'),
326
+ triggers: ['weekly planning', 'plan my week'],
327
+ tags: ['productivity', 'review'],
328
+ },
329
+ ],
330
+ },
331
+ ];