@pingvinen/donna-assistant 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/package.json +1 -1
- package/src/installer.cjs +1 -1
- package/stubs/claude-code/donna/add-follow-up-task.md +17 -0
- package/workflows/begin-the-day.md +41 -4
- package/workflows/follow-up.md +163 -0
package/README.md
CHANGED
|
@@ -111,6 +111,7 @@ If a CLI tool version is newer than what the AI model knows, Donna will re-learn
|
|
|
111
111
|
donna/
|
|
112
112
|
role.md # your job role definition
|
|
113
113
|
recurring.md # recurring task schedule
|
|
114
|
+
follow-ups.md # scheduled follow-up tasks with due dates
|
|
114
115
|
tools.md # registered tool configurations
|
|
115
116
|
daily/
|
|
116
117
|
2026-03-16.md # today's tasks, tool data, notes
|
|
@@ -152,6 +153,7 @@ Instead, run `/donna:run-tools` on demand when you want fresh data, or let `/don
|
|
|
152
153
|
| `/donna:begin-the-day` | Morning brief with carry-forward, recurring tasks, tool data |
|
|
153
154
|
| `/donna:add-task` | Capture a task instantly |
|
|
154
155
|
| `/donna:done` | Mark a task complete |
|
|
156
|
+
| `/donna:add-follow-up-task` | Schedule a task for a future date -- Donna reminds you when it is due |
|
|
155
157
|
| `/donna:focus` | Distill today's tasks into a short prioritized focus list |
|
|
156
158
|
|
|
157
159
|
### Tool management
|
package/package.json
CHANGED
package/src/installer.cjs
CHANGED
|
@@ -79,7 +79,7 @@ async function run(options = {}) {
|
|
|
79
79
|
for (const provider of detected) {
|
|
80
80
|
fs.cpSync(provider.stubSource, provider.stubTarget, { recursive: true });
|
|
81
81
|
output.success(
|
|
82
|
-
`Copied donna skills (setup, add-task, done, set-role, begin-the-day, add-tool, remove-tool, relearn-tools, run-tools, help, contribute-idea, adjust-tool, focus) to ${provider.stubTarget}`,
|
|
82
|
+
`Copied donna skills (setup, add-task, done, set-role, begin-the-day, add-tool, remove-tool, relearn-tools, run-tools, help, contribute-idea, adjust-tool, focus, add-follow-up-task) to ${provider.stubTarget}`,
|
|
83
83
|
);
|
|
84
84
|
}
|
|
85
85
|
} else {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: donna:add-follow-up-task
|
|
3
|
+
description: Schedule a follow-up task for a future date
|
|
4
|
+
allowed-tools:
|
|
5
|
+
- Read
|
|
6
|
+
- Write
|
|
7
|
+
- Bash
|
|
8
|
+
- AskUserQuestion
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
<objective>
|
|
12
|
+
Run the Donna follow-up workflow.
|
|
13
|
+
</objective>
|
|
14
|
+
|
|
15
|
+
<execution_context>
|
|
16
|
+
@~/.donna/workflows/follow-up.md
|
|
17
|
+
</execution_context>
|
|
@@ -94,6 +94,26 @@ For each task, determine if it is due today using this logic:
|
|
|
94
94
|
Store the descriptions of all due tasks as `<recurring_tasks>` (just the description text, without the interval suffix).
|
|
95
95
|
</step>
|
|
96
96
|
|
|
97
|
+
<step name="check-follow-ups">
|
|
98
|
+
Read `<storage_repo>/donna/follow-ups.md` with the Read tool. If the file does not exist, set `<follow_up_tasks>` to an empty list, set `<follow_ups_modified>` to `false`, and continue (follow-ups are optional).
|
|
99
|
+
|
|
100
|
+
Parse each line matching the pattern `- [ ] <description> | due: YYYY-MM-DD`. For each matching entry:
|
|
101
|
+
|
|
102
|
+
- Parse the `due` date (YYYY-MM-DD).
|
|
103
|
+
- If `due <= <today>`: add to `<follow_up_tasks>` as: `- [ ] <description>` (no annotation).
|
|
104
|
+
- If `due > <today>`: task is future — leave the line in follow-ups.md. Do not add to `<follow_up_tasks>`.
|
|
105
|
+
|
|
106
|
+
After collecting all due/past-due tasks, remove those matched lines from follow-ups.md (the matched lines are NOT written back — only future lines remain). Write the updated file back with the Write tool. If lines were removed, set `<follow_ups_modified>` to `true`. If no lines were removed, set `<follow_ups_modified>` to `false` and skip the file write. Per D-03: items are removed, not checked off or left with a marker.
|
|
107
|
+
|
|
108
|
+
Store `<follow_up_tasks>` for use in the deduplicate step.
|
|
109
|
+
|
|
110
|
+
CRITICAL constraints:
|
|
111
|
+
- The step reads only one specific named file (`donna/follow-ups.md`) — no directory scan, no wildcard listing
|
|
112
|
+
- File existence check is done via the Read tool (handle missing file gracefully)
|
|
113
|
+
- macOS date command uses the exact same `date -j` pattern as the existing check-recurring step
|
|
114
|
+
- Invalid date strings caught by `date -j`; skip the entry (do not surface, do not remove)
|
|
115
|
+
</step>
|
|
116
|
+
|
|
97
117
|
<step name="pull-tool-data">
|
|
98
118
|
Read `<storage_repo>/donna/tools.md` with the Read tool.
|
|
99
119
|
|
|
@@ -212,7 +232,9 @@ Assemble the full task list using a single-pass deduplication to ensure idempote
|
|
|
212
232
|
|
|
213
233
|
3. Add `<recurring_tasks>` as `- [ ] <description>` — for each recurring task, normalize its description and check whether any task already in the final list normalizes to the same value. If no match, add it. If a match exists, skip it.
|
|
214
234
|
|
|
215
|
-
4. Add `<
|
|
235
|
+
4. Add `<follow_up_tasks>` as-is — for each follow-up task, normalize its description and check whether any task already in the final list normalizes to the same value. If no match, add it. If a match exists, skip it.
|
|
236
|
+
|
|
237
|
+
5. Add `<tool_tasks>` as-is — for each tool task, normalize its description and check whether any task already in the final list normalizes to the same value. If no match, add it. If a match exists, skip it.
|
|
216
238
|
|
|
217
239
|
CRITICAL: A closed task `- [x] Review PRs` must block a recurring `- [ ] Review PRs` from being re-added. Both open AND closed existing tasks count for deduplication.
|
|
218
240
|
|
|
@@ -239,6 +261,7 @@ date: <today>
|
|
|
239
261
|
<existing tasks, preserving their original order and open/closed state>
|
|
240
262
|
<carried-forward tasks not already in existing>
|
|
241
263
|
<recurring tasks not already in existing>
|
|
264
|
+
<follow-up tasks not already in existing>
|
|
242
265
|
|
|
243
266
|
## From Tools
|
|
244
267
|
<tool tasks not already in existing — only if there are tool tasks>
|
|
@@ -250,7 +273,7 @@ date: <today>
|
|
|
250
273
|
<tool warnings — only if there are warnings>
|
|
251
274
|
```
|
|
252
275
|
|
|
253
|
-
Tasks are written in this order: existing tasks first (preserving their original order and state), then carried-forward tasks, then recurring tasks.
|
|
276
|
+
Tasks are written in this order: existing tasks first (preserving their original order and state), then carried-forward tasks, then recurring tasks, then follow-up tasks.
|
|
254
277
|
|
|
255
278
|
If `<tool_tasks>` is empty and there are no resolved items, omit the `## From Tools` and `## Resolved` sections entirely.
|
|
256
279
|
If `<tool_warnings>` is empty, omit the `## Warnings` section entirely. Each warning is written as-is (e.g., `! jira: command not found — install jira first`).
|
|
@@ -265,10 +288,17 @@ If no "every other" recurring tasks were added, skip this step.
|
|
|
265
288
|
</step>
|
|
266
289
|
|
|
267
290
|
<step name="git-commit">
|
|
268
|
-
|
|
291
|
+
If `<follow_ups_modified>` is `true` (the check-follow-ups step modified follow-ups.md), run via Bash:
|
|
292
|
+
```bash
|
|
293
|
+
node ~/.donna/donna-tools.cjs commit "donna(daily): <today> daily brief" --files <daily_folder>/<today>.md donna/follow-ups.md
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
Otherwise (follow-ups.md was not modified), run via Bash:
|
|
269
297
|
```bash
|
|
270
298
|
node ~/.donna/donna-tools.cjs commit "donna(daily): <today> daily brief" --files <daily_folder>/<today>.md
|
|
271
299
|
```
|
|
300
|
+
|
|
301
|
+
Per D-07: follow-ups.md is included in the commit when items were surfaced and removed from the standing file.
|
|
272
302
|
</step>
|
|
273
303
|
|
|
274
304
|
<step name="print-brief">
|
|
@@ -293,6 +323,13 @@ If there are recurring tasks due today (tasks from `<recurring_tasks>` that were
|
|
|
293
323
|
- [ ] Review sprint backlog
|
|
294
324
|
```
|
|
295
325
|
|
|
326
|
+
If there are follow-up tasks (tasks from `<follow_up_tasks>` that were added to the final list), print:
|
|
327
|
+
```
|
|
328
|
+
## Follow-ups
|
|
329
|
+
- [ ] Review design doc
|
|
330
|
+
- [ ] Submit expense report
|
|
331
|
+
```
|
|
332
|
+
|
|
296
333
|
If there are tool tasks (tasks from `<tool_tasks>` that were added to the final list), print:
|
|
297
334
|
```
|
|
298
335
|
## From Tools
|
|
@@ -311,7 +348,7 @@ Always end with:
|
|
|
311
348
|
══════════════════════════════════════
|
|
312
349
|
```
|
|
313
350
|
|
|
314
|
-
Show ALL tasks — never truncate. If no carried-forward tasks, omit the "## Carried Forward" section. If no recurring tasks due today, omit the "## Due Today" section. If no tool tasks, omit the "## From Tools" section. If no tool warnings, omit the "## Warnings" section. If carried-forward, recurring, AND tool tasks are all empty and there are no existing tasks, print:
|
|
351
|
+
Show ALL tasks — never truncate. If no carried-forward tasks, omit the "## Carried Forward" section. If no recurring tasks due today, omit the "## Due Today" section. If no follow-up tasks, omit the "## Follow-ups" section. If no tool tasks, omit the "## From Tools" section. If no tool warnings, omit the "## Warnings" section. If carried-forward, recurring, follow-up, AND tool tasks are all empty and there are no existing tasks, print:
|
|
315
352
|
```
|
|
316
353
|
No tasks for today — enjoy your day!
|
|
317
354
|
```
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# Donna Follow-Up Workflow
|
|
2
|
+
|
|
3
|
+
<objective>
|
|
4
|
+
Capture a follow-up task with a future due date, resolve relative time expressions to concrete dates, store in donna/follow-ups.md, and commit via donna-tools.cjs.
|
|
5
|
+
</objective>
|
|
6
|
+
|
|
7
|
+
<step name="init">
|
|
8
|
+
Run via Bash:
|
|
9
|
+
```bash
|
|
10
|
+
INIT=$(node ~/.donna/donna-tools.cjs init)
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Parse the JSON response. If the `error` field is `"not_configured"`, print:
|
|
14
|
+
```
|
|
15
|
+
x Donna is not configured. Run /donna:setup first.
|
|
16
|
+
```
|
|
17
|
+
Stop.
|
|
18
|
+
|
|
19
|
+
Extract `storage_repo`, `daily_folder`, `auto_push` from the JSON.
|
|
20
|
+
|
|
21
|
+
If `update_available` is non-null, print:
|
|
22
|
+
```
|
|
23
|
+
Donna v<update_available> available -- run npx @pingvinen/donna-assistant to update
|
|
24
|
+
```
|
|
25
|
+
Continue normally.
|
|
26
|
+
</step>
|
|
27
|
+
|
|
28
|
+
<step name="parse-input">
|
|
29
|
+
The argument is the full user text (e.g., "/donna:add-follow-up-task remind team about Q3 planning in 2 months").
|
|
30
|
+
|
|
31
|
+
**If an argument was provided:**
|
|
32
|
+
Use language understanding to extract two things from the argument:
|
|
33
|
+
1. `<description>`: The task description (everything that is not a time expression)
|
|
34
|
+
2. `<due_expression>`: A time expression (e.g., "in 2 months", "on 2026-09-15", "next Tuesday", "in 3 weeks") — or null if no time expression is found
|
|
35
|
+
|
|
36
|
+
Examples:
|
|
37
|
+
- "remind team about Q3 planning in 2 months" → description: "remind team about Q3 planning", due_expression: "in 2 months"
|
|
38
|
+
- "call dentist on 2026-09-15" → description: "call dentist", due_expression: "on 2026-09-15"
|
|
39
|
+
- "review the design doc" → description: "review the design doc", due_expression: null
|
|
40
|
+
- "/donna:add-follow-up-task schedule 1:1 with Sarah next Tuesday at 2pm" → description: "schedule 1:1 with Sarah", due_expression: "next Tuesday"
|
|
41
|
+
|
|
42
|
+
**If no argument was provided:**
|
|
43
|
+
CRITICAL: Both AskUserQuestion prompts must use free-text input mode — do NOT use a picker with predefined options.
|
|
44
|
+
|
|
45
|
+
Print the following as prose (before asking any questions):
|
|
46
|
+
```
|
|
47
|
+
Time expression examples: "in 2 months", "on 2026-09-15", "next Tuesday", "in 3 weeks", or leave blank for today.
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Use AskUserQuestion to ask two questions:
|
|
51
|
+
|
|
52
|
+
First question:
|
|
53
|
+
```
|
|
54
|
+
What task would you like to schedule?
|
|
55
|
+
```
|
|
56
|
+
Store the free-text response as `<description>`.
|
|
57
|
+
|
|
58
|
+
Second question:
|
|
59
|
+
```
|
|
60
|
+
When is it due?
|
|
61
|
+
```
|
|
62
|
+
Store the free-text response as `<due_expression>`. If the user leaves it blank or says "today", set `<due_expression>` to null.
|
|
63
|
+
</step>
|
|
64
|
+
|
|
65
|
+
<step name="resolve-date">
|
|
66
|
+
Three cases for resolving the due date:
|
|
67
|
+
|
|
68
|
+
**Case 1: due_expression is null**
|
|
69
|
+
Use today's date. Run via Bash:
|
|
70
|
+
```bash
|
|
71
|
+
node -e "const d=new Date();const y=d.getFullYear();const m=String(d.getMonth()+1).padStart(2,'0');const dd=String(d.getDate()).padStart(2,'0');console.log(y+'-'+m+'-'+dd)"
|
|
72
|
+
```
|
|
73
|
+
Store the output as `<due_date>`.
|
|
74
|
+
|
|
75
|
+
**Case 2: due_expression matches YYYY-MM-DD format**
|
|
76
|
+
Extract the YYYY-MM-DD part from the expression (strip any leading words like "on"). Store directly as `<due_date>`.
|
|
77
|
+
|
|
78
|
+
**Case 3: due_expression is a relative expression**
|
|
79
|
+
The agent parses the natural language expression into structured {value, unit} pairs:
|
|
80
|
+
- "in 2 months" → months: 2
|
|
81
|
+
- "in 3 weeks" → weeks: 3
|
|
82
|
+
- "in 2 weeks and 3 days" → weeks: 2, days: 3
|
|
83
|
+
- "in 1 month and 2 weeks" → months: 1, weeks: 2
|
|
84
|
+
- "in 2 months and 5 days" → months: 2, days: 5
|
|
85
|
+
- "next Tuesday" → next occurrence of Tuesday from today (count days until the next Tuesday)
|
|
86
|
+
- "tomorrow" → days: 1
|
|
87
|
+
- "in 5 days" → days: 5
|
|
88
|
+
|
|
89
|
+
Inject the arithmetic into a Bash node -e command. Command template:
|
|
90
|
+
```bash
|
|
91
|
+
node -e "
|
|
92
|
+
const d = new Date();
|
|
93
|
+
<apply setMonth first: d.setMonth(d.getMonth() + N)>
|
|
94
|
+
<apply setDate next: d.setDate(d.getDate() + N)>
|
|
95
|
+
<apply setFullYear last: d.setFullYear(d.getFullYear() + N)>
|
|
96
|
+
const yyyy = d.getFullYear();
|
|
97
|
+
const mm = String(d.getMonth() + 1).padStart(2, '0');
|
|
98
|
+
const dd = String(d.getDate()).padStart(2, '0');
|
|
99
|
+
console.log(yyyy + '-' + mm + '-' + dd);
|
|
100
|
+
"
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Example for "in 2 months and 5 days":
|
|
104
|
+
```bash
|
|
105
|
+
node -e "const d=new Date();d.setMonth(d.getMonth()+2);d.setDate(d.getDate()+5);const y=d.getFullYear();const m=String(d.getMonth()+1).padStart(2,'0');const dd=String(d.getDate()).padStart(2,'0');console.log(y+'-'+m+'-'+dd)"
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Example for "in 3 weeks":
|
|
109
|
+
```bash
|
|
110
|
+
node -e "const d=new Date();d.setDate(d.getDate()+21);const y=d.getFullYear();const m=String(d.getMonth()+1).padStart(2,'0');const dd=String(d.getDate()).padStart(2,'0');console.log(y+'-'+m+'-'+dd)"
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
CRITICAL: Always use local date component extraction (`getFullYear()`, `getMonth() + 1`, `getDate()`) with padding. NEVER use `toISOString()` — it returns UTC which can produce off-by-one dates for users in timezones ahead of UTC.
|
|
114
|
+
|
|
115
|
+
If the resolved date is NaN or invalid (check by verifying the output matches YYYY-MM-DD format), print:
|
|
116
|
+
```
|
|
117
|
+
x Invalid date expression: <due_expression>. Use formats like "tomorrow", "next friday", "in 3 days", or YYYY-MM-DD.
|
|
118
|
+
```
|
|
119
|
+
Then stop the workflow. Do NOT fall back to today — the user must correct their date expression.
|
|
120
|
+
|
|
121
|
+
If the date resolved successfully, store the output as `<due_date>`.
|
|
122
|
+
</step>
|
|
123
|
+
|
|
124
|
+
<step name="ensure-file">
|
|
125
|
+
Check if `<storage_repo>/donna/follow-ups.md` exists. Use the Read tool to attempt reading it.
|
|
126
|
+
|
|
127
|
+
If the file does not exist (Read tool returns an error), create it with the Write tool using this content:
|
|
128
|
+
```markdown
|
|
129
|
+
---
|
|
130
|
+
created: <today>
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Follow-ups
|
|
134
|
+
```
|
|
135
|
+
Where `<today>` is today's date in YYYY-MM-DD format.
|
|
136
|
+
|
|
137
|
+
If the file already exists, continue to the next step.
|
|
138
|
+
</step>
|
|
139
|
+
|
|
140
|
+
<step name="append-entry">
|
|
141
|
+
Read `<storage_repo>/donna/follow-ups.md` with the Read tool.
|
|
142
|
+
|
|
143
|
+
Append the follow-up entry on a new line at the end of the file:
|
|
144
|
+
```
|
|
145
|
+
- [ ] <description> | due: <due_date>
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Write the updated file back with the Write tool.
|
|
149
|
+
</step>
|
|
150
|
+
|
|
151
|
+
<step name="git-commit">
|
|
152
|
+
Run via Bash:
|
|
153
|
+
```bash
|
|
154
|
+
node ~/.donna/donna-tools.cjs commit "donna(follow-up): <description>" --files donna/follow-ups.md
|
|
155
|
+
```
|
|
156
|
+
</step>
|
|
157
|
+
|
|
158
|
+
<step name="confirm">
|
|
159
|
+
Print:
|
|
160
|
+
```
|
|
161
|
+
✓ Follow-up scheduled: <description> (due: <due_date>)
|
|
162
|
+
```
|
|
163
|
+
</step>
|