@pingvinen/donna-assistant 0.4.0 → 0.5.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 +129 -2
- package/migrations/002-standing-files-subfolder.cjs +23 -0
- package/package.json +1 -1
- package/src/installer.cjs +1 -1
- package/stubs/claude-code/donna/add-tool.md +17 -0
- package/stubs/claude-code/donna/relearn-tools.md +16 -0
- package/stubs/claude-code/donna/run-tools.md +16 -0
- package/workflows/add-task.md +41 -0
- package/workflows/add-tool.md +261 -0
- package/workflows/begin-the-day.md +115 -5
- package/workflows/done.md +46 -3
- package/workflows/relearn-tools.md +180 -0
- package/workflows/run-tools.md +214 -0
- package/workflows/set-role.md +48 -7
- package/workflows/setup.md +3 -2
package/README.md
CHANGED
|
@@ -1,2 +1,129 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
1
|
+
# Donna
|
|
2
|
+
|
|
3
|
+
Your personal, digital version of Harvey Specter's amazing secretary.
|
|
4
|
+
|
|
5
|
+
Donna is an AI-powered personal assistant that manages the work that falls through the cracks — the 1:1 follow-ups, recurring process tasks, stakeholder requests, and self-initiated work that never makes it into Jira or Linear.
|
|
6
|
+
|
|
7
|
+
She lives inside your terminal. She knows your role, surfaces what needs attention each day, pulls data from your CLI tools, and captures tasks in seconds — all backed by plain markdown and git.
|
|
8
|
+
|
|
9
|
+
Donna is designed to be AI-agnostic, but currently only tested with [Claude Code](https://docs.anthropic.com/en/docs/claude-code). She works from any session, in any project — your tasks follow you wherever you work.
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npx @pingvinen/donna-assistant
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
The installer copies skill files into `~/.claude/commands/donna/` and shared runtime into `~/.donna/`. Run it again to upgrade.
|
|
18
|
+
|
|
19
|
+
**Requirements:** Node.js 18+, an AI coding assistant (tested with Claude Code)
|
|
20
|
+
|
|
21
|
+
## Setup
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
/donna:setup
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Donna will ask you for a **storage repo** — a git repository (local or remote) where all your tasks and daily files live. Everything is plain markdown, committed to git automatically. If you use [Obsidian](https://obsidian.md), you can open this repo as a vault for a free UI.
|
|
28
|
+
|
|
29
|
+
Then define your role so Donna can suggest recurring tasks relevant to your job:
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
/donna:set-role
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Daily workflow
|
|
36
|
+
|
|
37
|
+
### Start the day
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
/donna:begin-the-day
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
This is your morning ritual. Donna will:
|
|
44
|
+
|
|
45
|
+
- **Carry forward** open tasks from your last working day (handles weekends)
|
|
46
|
+
- **Surface recurring tasks** that are due today based on your role
|
|
47
|
+
- **Pull fresh data** from configured tools (GitHub PRs, Jira tickets, etc.)
|
|
48
|
+
- **Deduplicate** across all sources and give you a brief
|
|
49
|
+
|
|
50
|
+
### Capture tasks throughout the day
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
/donna:add-task Review Sarah's design doc before Thursday
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
One command, zero prompts, committed to git in seconds. Can also be called without arguments for a more conversational capture.
|
|
57
|
+
|
|
58
|
+
### Mark tasks done
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
/donna:done design doc
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Fuzzy-matches by name. Run without arguments to pick from a list.
|
|
65
|
+
|
|
66
|
+
### Refresh tool data mid-day
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
/donna:run-tools
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Re-pulls data from all configured tools. New items appear, resolved items get closed automatically. Your manually-marked tasks always win.
|
|
73
|
+
|
|
74
|
+
## External tools
|
|
75
|
+
|
|
76
|
+
Donna can pull tasks and status from CLI tools you already have installed. Register them with:
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
/donna:add-tool gh
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Or call it without arguments — Donna will check your role and suggest tools typically associated with your job.
|
|
83
|
+
|
|
84
|
+
Donna verifies the tool is installed and authenticated, learns its capabilities, and asks what scope to query (which repos, projects, namespaces). Any CLI tool can be added — Donna uses the AI model's knowledge of well-known tools and parses `--help` output for everything else.
|
|
85
|
+
|
|
86
|
+
If a tool version is newer than what the AI model knows, Donna will inspect it to learn its current capabilities. You can also re-learn tools at any time:
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
/donna:relearn-tools
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## How state is stored
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
<your-storage-repo>/
|
|
96
|
+
donna/
|
|
97
|
+
role.md # your job role definition
|
|
98
|
+
recurring.md # recurring task schedule
|
|
99
|
+
tools.md # registered tool configurations
|
|
100
|
+
daily/
|
|
101
|
+
2026-03-16.md # today's tasks, tool data, notes
|
|
102
|
+
2026-03-15.md
|
|
103
|
+
...
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Every change is committed to git. Files are plain markdown with YAML frontmatter — human-readable, hand-editable, and version-controlled.
|
|
107
|
+
|
|
108
|
+
The storage repo is yours. Donna only writes to the `donna/` and `daily/` directories, so you're free to keep any other notes, files, or folder structures alongside it — great if you're already using the repo as an Obsidian vault or similar.
|
|
109
|
+
|
|
110
|
+
## Idempotent by design
|
|
111
|
+
|
|
112
|
+
Most commands are safe to run again. Want to update your role? Run `/donna:set-role` again. Added a new tool mid-day? Run `/donna:begin-the-day` again to pull its data in. Re-running a command updates state rather than duplicating it.
|
|
113
|
+
|
|
114
|
+
## All commands
|
|
115
|
+
|
|
116
|
+
| Command | What it does |
|
|
117
|
+
|---------|-------------|
|
|
118
|
+
| `/donna:setup` | First-time configuration (storage repo, directories) |
|
|
119
|
+
| `/donna:set-role` | Define your job role, get recurring task suggestions |
|
|
120
|
+
| `/donna:begin-the-day` | Morning brief with carry-forward, recurring tasks, tool data |
|
|
121
|
+
| `/donna:add-task` | Capture a task instantly |
|
|
122
|
+
| `/donna:done` | Mark a task complete |
|
|
123
|
+
| `/donna:add-tool` | Register an external CLI tool |
|
|
124
|
+
| `/donna:run-tools` | Refresh tool data mid-day |
|
|
125
|
+
| `/donna:relearn-tools` | Update tool knowledge after upgrades |
|
|
126
|
+
|
|
127
|
+
## License
|
|
128
|
+
|
|
129
|
+
MIT
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
version: "0.4.0",
|
|
5
|
+
description: "Queue standing file move to donna/ subfolder (runs on next skill use)",
|
|
6
|
+
up(ctx) {
|
|
7
|
+
// Standing files live in the user's storage repo, which is not accessible
|
|
8
|
+
// from the migration context. We write a pending flag to state.md so that
|
|
9
|
+
// workflows can detect and execute the move on next skill run.
|
|
10
|
+
const statePath = ctx.path.join(ctx.donnaDir, "state.md");
|
|
11
|
+
|
|
12
|
+
if (ctx.fs.existsSync(statePath)) {
|
|
13
|
+
const content = ctx.fs.readFileSync(statePath, "utf8");
|
|
14
|
+
if (content.includes("move-standing-files")) {
|
|
15
|
+
// Already queued — idempotent, nothing to do
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const pendingFlag = "---\npending_migrations:\n - move-standing-files\n---\n";
|
|
21
|
+
ctx.fs.writeFileSync(statePath, pendingFlag, "utf8");
|
|
22
|
+
},
|
|
23
|
+
};
|
package/package.json
CHANGED
package/src/installer.cjs
CHANGED
|
@@ -77,7 +77,7 @@ async function run(options = {}) {
|
|
|
77
77
|
for (const provider of detected) {
|
|
78
78
|
fs.cpSync(provider.stubSource, provider.stubTarget, { recursive: true });
|
|
79
79
|
output.success(
|
|
80
|
-
`Copied donna skills (setup, add-task, done, set-role, begin-the-day) to ${provider.stubTarget}`,
|
|
80
|
+
`Copied donna skills (setup, add-task, done, set-role, begin-the-day, add-tool, relearn-tools, run-tools) to ${provider.stubTarget}`,
|
|
81
81
|
);
|
|
82
82
|
}
|
|
83
83
|
} else {
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: donna:add-tool
|
|
3
|
+
description: Declare an external CLI tool and teach Donna its capabilities
|
|
4
|
+
allowed-tools:
|
|
5
|
+
- Read
|
|
6
|
+
- Write
|
|
7
|
+
- Bash
|
|
8
|
+
- AskUserQuestion
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
<objective>
|
|
12
|
+
Run the Donna add-tool workflow. This command declares external CLI tools (like gh, jira, kubectl) and teaches Donna their capabilities so they can be surfaced in the daily brief.
|
|
13
|
+
</objective>
|
|
14
|
+
|
|
15
|
+
<execution_context>
|
|
16
|
+
@~/.donna/workflows/add-tool.md
|
|
17
|
+
</execution_context>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: donna:relearn-tools
|
|
3
|
+
description: Re-learn capabilities for tools whose installed version has changed
|
|
4
|
+
allowed-tools:
|
|
5
|
+
- Read
|
|
6
|
+
- Write
|
|
7
|
+
- Bash
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
<objective>
|
|
11
|
+
Run the Donna relearn-tools workflow. This command checks each registered tool's installed version against its stored version and re-learns capabilities for tools that have been updated.
|
|
12
|
+
</objective>
|
|
13
|
+
|
|
14
|
+
<execution_context>
|
|
15
|
+
@~/.donna/workflows/relearn-tools.md
|
|
16
|
+
</execution_context>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: donna:run-tools
|
|
3
|
+
description: Run external tools and pull fresh data into today's daily file
|
|
4
|
+
allowed-tools:
|
|
5
|
+
- Read
|
|
6
|
+
- Write
|
|
7
|
+
- Bash
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
<objective>
|
|
11
|
+
Run the Donna run-tools workflow. This command executes all configured external tool commands, pulls fresh data, and smart-merges results into today's daily file, without running the full begin-the-day carry-forward and recurring task logic.
|
|
12
|
+
</objective>
|
|
13
|
+
|
|
14
|
+
<execution_context>
|
|
15
|
+
@~/.donna/workflows/run-tools.md
|
|
16
|
+
</execution_context>
|
package/workflows/add-task.md
CHANGED
|
@@ -21,6 +21,47 @@ Extract the `storage_repo`, `daily_folder` (default: `daily`), and `auto_push` (
|
|
|
21
21
|
- Otherwise: do nothing.
|
|
22
22
|
</step>
|
|
23
23
|
|
|
24
|
+
<step name="check-pending-migrations">
|
|
25
|
+
Read `~/.donna/state.md` with the Read tool. If the file does not exist or has no `pending_migrations` field in its YAML frontmatter, skip this step.
|
|
26
|
+
|
|
27
|
+
For each entry in `pending_migrations`:
|
|
28
|
+
|
|
29
|
+
**`move-standing-files`:** Move standing files from storage repo root to donna/ subfolder.
|
|
30
|
+
|
|
31
|
+
Run via Bash:
|
|
32
|
+
```bash
|
|
33
|
+
STORAGE_REPO="<storage_repo>"
|
|
34
|
+
DONNA_DIR="$STORAGE_REPO/donna"
|
|
35
|
+
MOVED=0
|
|
36
|
+
|
|
37
|
+
mkdir -p "$DONNA_DIR"
|
|
38
|
+
for FILE in role.md recurring.md role-research.md; do
|
|
39
|
+
if [ -f "$STORAGE_REPO/$FILE" ] && [ ! -f "$DONNA_DIR/$FILE" ]; then
|
|
40
|
+
mv "$STORAGE_REPO/$FILE" "$DONNA_DIR/$FILE"
|
|
41
|
+
echo "Moved $FILE to donna/$FILE"
|
|
42
|
+
MOVED=$((MOVED + 1))
|
|
43
|
+
fi
|
|
44
|
+
done
|
|
45
|
+
|
|
46
|
+
echo "MOVED=$MOVED"
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
If MOVED > 0, commit the move:
|
|
50
|
+
```bash
|
|
51
|
+
git -C <storage_repo> add -A
|
|
52
|
+
git -C <storage_repo> diff --cached --quiet || git -C <storage_repo> commit -m "donna(migrate): move standing files to donna/ subfolder"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
If `auto_push` is true in config, also push.
|
|
56
|
+
|
|
57
|
+
After processing all pending migrations, update `~/.donna/state.md` with the Write tool: remove the completed entries from `pending_migrations`. If no entries remain, write:
|
|
58
|
+
```markdown
|
|
59
|
+
---
|
|
60
|
+
pending_migrations: []
|
|
61
|
+
---
|
|
62
|
+
```
|
|
63
|
+
</step>
|
|
64
|
+
|
|
24
65
|
<step name="get-description">
|
|
25
66
|
The task description is provided as the argument to this command (e.g., `/donna:add-task buy milk`).
|
|
26
67
|
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
# Donna Add-Tool Workflow
|
|
2
|
+
|
|
3
|
+
<objective>
|
|
4
|
+
Declare an external CLI tool, verify its installation and authentication, learn its capabilities, and persist the result to tools.md in the storage repo.
|
|
5
|
+
</objective>
|
|
6
|
+
|
|
7
|
+
<step name="read-config">
|
|
8
|
+
Read `~/.config/donna/config.md`.
|
|
9
|
+
|
|
10
|
+
If the file does not exist, print:
|
|
11
|
+
```
|
|
12
|
+
✗ Donna is not configured. Run /donna:setup first.
|
|
13
|
+
```
|
|
14
|
+
Stop.
|
|
15
|
+
|
|
16
|
+
Extract the `storage_repo`, `daily_folder` (default: `daily`), and `auto_push` (default: false) fields from the YAML frontmatter.
|
|
17
|
+
|
|
18
|
+
**Obsidian sync:** Check if `<storage_repo>/.obsidian/daily-notes.json` exists.
|
|
19
|
+
- If it exists and has a `folder` field that differs from `<daily_folder>`: update `<daily_folder>` to match Obsidian's value, and update `~/.config/donna/config.md` with the new `daily_folder`. Print `✓ Synced daily folder with Obsidian: <daily_folder>`.
|
|
20
|
+
- If `<storage_repo>/.obsidian/` exists but `daily-notes.json` does not exist or has no `folder` field: write `<storage_repo>/.obsidian/daily-notes.json` with `{"folder":"<daily_folder>"}`. Print `✓ Configured Obsidian daily notes to use <daily_folder>/`.
|
|
21
|
+
- Otherwise: do nothing.
|
|
22
|
+
</step>
|
|
23
|
+
|
|
24
|
+
<step name="check-pending-migrations">
|
|
25
|
+
Read `~/.donna/state.md` with the Read tool. If the file does not exist or has no `pending_migrations` field in its YAML frontmatter, skip this step.
|
|
26
|
+
|
|
27
|
+
For each entry in `pending_migrations`:
|
|
28
|
+
|
|
29
|
+
**`move-standing-files`:** Move standing files from storage repo root to donna/ subfolder.
|
|
30
|
+
|
|
31
|
+
Run via Bash:
|
|
32
|
+
```bash
|
|
33
|
+
STORAGE_REPO="<storage_repo>"
|
|
34
|
+
DONNA_DIR="$STORAGE_REPO/donna"
|
|
35
|
+
MOVED=0
|
|
36
|
+
|
|
37
|
+
mkdir -p "$DONNA_DIR"
|
|
38
|
+
for FILE in role.md recurring.md role-research.md; do
|
|
39
|
+
if [ -f "$STORAGE_REPO/$FILE" ] && [ ! -f "$DONNA_DIR/$FILE" ]; then
|
|
40
|
+
mv "$STORAGE_REPO/$FILE" "$DONNA_DIR/$FILE"
|
|
41
|
+
echo "Moved $FILE to donna/$FILE"
|
|
42
|
+
MOVED=$((MOVED + 1))
|
|
43
|
+
fi
|
|
44
|
+
done
|
|
45
|
+
|
|
46
|
+
echo "MOVED=$MOVED"
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
If MOVED > 0, commit the move:
|
|
50
|
+
```bash
|
|
51
|
+
git -C <storage_repo> add -A
|
|
52
|
+
git -C <storage_repo> diff --cached --quiet || git -C <storage_repo> commit -m "donna(migrate): move standing files to donna/ subfolder"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
If `auto_push` is true in config, also push.
|
|
56
|
+
|
|
57
|
+
After processing all pending migrations, update `~/.donna/state.md` with the Write tool: remove the completed entries from `pending_migrations`. If no entries remain, write:
|
|
58
|
+
```markdown
|
|
59
|
+
---
|
|
60
|
+
pending_migrations: []
|
|
61
|
+
---
|
|
62
|
+
```
|
|
63
|
+
</step>
|
|
64
|
+
|
|
65
|
+
<step name="detect-noted-tools">
|
|
66
|
+
Read `<storage_repo>/donna/role.md` and `<storage_repo>/donna/role-research.md` with the Read tool. If either file does not exist, skip reading that file.
|
|
67
|
+
|
|
68
|
+
Look for lines containing tool names noted by set-role's approve-tools step. These lines follow the pattern `✓ Noted: <ToolName>` or `- Noted: <ToolName>`. Collect the noted tool names as `<noted_tools>`.
|
|
69
|
+
|
|
70
|
+
If `<noted_tools>` has more than one entry and no specific tool name was provided as argument to the command, offer batch mode via AskUserQuestion:
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
Set-role noted these tools: <list>. Configure all of them now? (yes/no)
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
If yes, set batch mode active and process each tool sequentially through steps 4–11 below. If no, proceed to ask-tool-name for a single tool.
|
|
77
|
+
</step>
|
|
78
|
+
|
|
79
|
+
<step name="ask-tool-name">
|
|
80
|
+
If a tool name was provided as argument (e.g. `/donna:add-tool gh`), use it directly. Otherwise, use AskUserQuestion:
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
What tool would you like to add? (e.g. gh, jira, kubectl)
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Store the answer as `<tool_name>`.
|
|
87
|
+
|
|
88
|
+
Resolve the CLI command — default to the tool name itself. If the tool name is in `<noted_tools>`, pre-fill any context from set-role notes. Use AskUserQuestion to confirm or override the CLI command:
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
CLI command for <tool_name>? (default: <tool_name>)
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
If the user presses enter without typing, use the default. Store the confirmed CLI command as `<command>`.
|
|
95
|
+
</step>
|
|
96
|
+
|
|
97
|
+
<step name="verify-installation">
|
|
98
|
+
Run via Bash:
|
|
99
|
+
```bash
|
|
100
|
+
which <command> && echo "INSTALLED=true" || echo "INSTALLED=false"
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
If INSTALLED=false, print:
|
|
104
|
+
```
|
|
105
|
+
! <command> is not installed. You can still save it, but data pulling won't work until you install it.
|
|
106
|
+
```
|
|
107
|
+
Continue (do not stop — user may want to pre-configure).
|
|
108
|
+
|
|
109
|
+
If INSTALLED=true, run:
|
|
110
|
+
```bash
|
|
111
|
+
<command> --version 2>/dev/null | head -1
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Store the output as `<version>`. If the command does not support `--version`, store `<version>` as `unknown`.
|
|
115
|
+
</step>
|
|
116
|
+
|
|
117
|
+
<step name="auth-test">
|
|
118
|
+
For well-known tools, run the appropriate auth test via Bash with a 10-second timeout:
|
|
119
|
+
|
|
120
|
+
- `gh`: `timeout 10 gh api user --jq '.login' 2>&1`
|
|
121
|
+
- `jira`: `timeout 10 jira me 2>&1`
|
|
122
|
+
- `kubectl`: `timeout 10 kubectl auth whoami 2>&1`
|
|
123
|
+
- Other tools: skip auth test, print `ℹ No known auth test for <command>. Verify manually.`
|
|
124
|
+
|
|
125
|
+
On success (exit 0): print `✓ Authenticated as <output>`.
|
|
126
|
+
|
|
127
|
+
On failure (non-zero exit): print `! Authentication failed for <command>. Fix: <tool-specific fix instructions>`.
|
|
128
|
+
|
|
129
|
+
Fix instructions per tool:
|
|
130
|
+
- `gh` → run `gh auth login`
|
|
131
|
+
- `jira` → run `jira init`
|
|
132
|
+
- `kubectl` → check your kubeconfig
|
|
133
|
+
|
|
134
|
+
Continue (do not stop — user may want to save the tool despite auth issues).
|
|
135
|
+
</step>
|
|
136
|
+
|
|
137
|
+
<step name="ask-scope">
|
|
138
|
+
Ask the user to define the scope/context for this tool. Different tools need different scope:
|
|
139
|
+
|
|
140
|
+
- **gh**: Which GitHub orgs or repos to pull from (e.g., `mycompany`, `mycompany/api mycompany/web`)
|
|
141
|
+
- **jira**: Which Jira project(s) or board(s) (e.g., `AUTH`, `AUTH PLAT`)
|
|
142
|
+
- **kubectl**: Which namespace(s) or cluster(s) (e.g., `production`, `staging production`)
|
|
143
|
+
- **Other tools**: Any relevant filtering context
|
|
144
|
+
|
|
145
|
+
Use AskUserQuestion:
|
|
146
|
+
```
|
|
147
|
+
What scope should Donna use for <tool_name>?
|
|
148
|
+
(e.g., for gh: which orgs/repos; for jira: which projects)
|
|
149
|
+
Leave blank for no filtering.
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Store the answer as `<scope>`. If blank, set to empty string.
|
|
153
|
+
</step>
|
|
154
|
+
|
|
155
|
+
<step name="learn-capabilities">
|
|
156
|
+
Determine if the tool is well-known (gh, jira, kubectl) or unknown. For well-known tools, synthesize capabilities from training data. Do NOT parse --help for well-known tools.
|
|
157
|
+
|
|
158
|
+
**gh (GitHub CLI) — training data baseline:**
|
|
159
|
+
|
|
160
|
+
If `<scope>` is set, add `--owner=<org>` to each search command for each org in scope (space-separated). If scope contains specific repos (format `owner/repo`), use `--repo=<owner/repo>` instead. If scope is empty, do not add owner/repo filters.
|
|
161
|
+
|
|
162
|
+
- list-assigned-prs: `gh search prs --assignee=@me --state=open --json number,title,url --limit 20`
|
|
163
|
+
- list-review-requests: `gh search prs --review-requested=@me --state=open --json number,title,url --limit 20`
|
|
164
|
+
- list-assigned-issues: `gh search issues --assignee=@me --state=open --json number,title,url --limit 20`
|
|
165
|
+
|
|
166
|
+
**jira (ankitpokhrel/jira-cli) — training data baseline:**
|
|
167
|
+
|
|
168
|
+
If `<scope>` is set, add `-p<project>` to each command for each project in scope (space-separated). If scope is empty, do not add project filters.
|
|
169
|
+
|
|
170
|
+
- list-sprint-issues: `jira sprint list --current -a$(jira me) --plain`
|
|
171
|
+
- list-my-issues: `jira issue list -a$(jira me) --plain`
|
|
172
|
+
|
|
173
|
+
**kubectl — training data baseline:**
|
|
174
|
+
|
|
175
|
+
If `<scope>` is set, replace `--all-namespaces` with `-n <namespace>` for each namespace in scope. If scope is empty, keep `--all-namespaces`.
|
|
176
|
+
|
|
177
|
+
- list-pods: `kubectl get pods --all-namespaces --field-selector=status.phase!=Succeeded -o wide`
|
|
178
|
+
- list-failing: `kubectl get pods --all-namespaces --field-selector=status.phase=Failed -o wide`
|
|
179
|
+
|
|
180
|
+
For **unknown tools**, run `<command> --help 2>&1 | head -80` via Bash and use Claude's understanding to identify 3–5 capabilities relevant to daily task management. If `<scope>` is set, incorporate the scope into the CLI invocations where appropriate. Format each as `name: <cli invocation>`.
|
|
181
|
+
|
|
182
|
+
Store the full list as `<available_capabilities>`.
|
|
183
|
+
</step>
|
|
184
|
+
|
|
185
|
+
<step name="select-capabilities">
|
|
186
|
+
Present `<available_capabilities>` to the user via AskUserQuestion with multi-select. All capabilities are checked by default. The question text:
|
|
187
|
+
|
|
188
|
+
```
|
|
189
|
+
Which capabilities should Donna use for <tool_name>? (deselect any you don't want, or type additional ones)
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
If the user types additional capabilities as free text, parse them into the same `name: command` format.
|
|
193
|
+
|
|
194
|
+
Store the final selections as `<selected_capabilities>`.
|
|
195
|
+
</step>
|
|
196
|
+
|
|
197
|
+
<step name="write-tools-md">
|
|
198
|
+
Read `<storage_repo>/donna/tools.md` with the Read tool. If the file does not exist, create it with:
|
|
199
|
+
```markdown
|
|
200
|
+
---
|
|
201
|
+
# tools.md — managed by donna:add-tool
|
|
202
|
+
---
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
Upsert (not overwrite) the tool's section. Each tool section has this format:
|
|
206
|
+
```markdown
|
|
207
|
+
## <tool_name>
|
|
208
|
+
|
|
209
|
+
- command: <command>
|
|
210
|
+
- version: <version>
|
|
211
|
+
- learned: <today's date YYYY-MM-DD>
|
|
212
|
+
- auth_test: <auth_test_command or "none">
|
|
213
|
+
- scope: <scope or "none">
|
|
214
|
+
|
|
215
|
+
### Capabilities
|
|
216
|
+
- <capability_name>: <cli_invocation>
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
If a section for this tool already exists in tools.md, replace it entirely. Write the full file back with the Write tool. Preserve all other tool sections unchanged.
|
|
220
|
+
</step>
|
|
221
|
+
|
|
222
|
+
<step name="git-commit">
|
|
223
|
+
Run via Bash:
|
|
224
|
+
```bash
|
|
225
|
+
git -C <storage_repo> add -A
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Check whether there is anything to commit:
|
|
229
|
+
```bash
|
|
230
|
+
git -C <storage_repo> status --porcelain
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
If the output is empty, skip the commit and continue.
|
|
234
|
+
|
|
235
|
+
Otherwise, run:
|
|
236
|
+
```bash
|
|
237
|
+
git -C <storage_repo> commit -m "donna(add-tool): added <tool_name>"
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
If `auto_push` is true in config, also run:
|
|
241
|
+
```bash
|
|
242
|
+
git -C <storage_repo> push
|
|
243
|
+
```
|
|
244
|
+
</step>
|
|
245
|
+
|
|
246
|
+
<step name="confirm">
|
|
247
|
+
Print:
|
|
248
|
+
```
|
|
249
|
+
✓ Added <tool_name> to tools registry
|
|
250
|
+
Command: <command>
|
|
251
|
+
Version: <version>
|
|
252
|
+
Capabilities: <count> configured
|
|
253
|
+
|
|
254
|
+
Run /donna:begin-the-day to see tool data in your daily brief.
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
If in batch mode, repeat steps ask-tool-name through confirm for each remaining tool in `<noted_tools>`, then print a final summary:
|
|
258
|
+
```
|
|
259
|
+
✓ Configured <N> tools: <tool_name_1>, <tool_name_2>, ...
|
|
260
|
+
```
|
|
261
|
+
</step>
|
|
@@ -21,6 +21,47 @@ Extract the `storage_repo`, `daily_folder` (default: `daily`), and `auto_push` (
|
|
|
21
21
|
- Otherwise: do nothing.
|
|
22
22
|
</step>
|
|
23
23
|
|
|
24
|
+
<step name="check-pending-migrations">
|
|
25
|
+
Read `~/.donna/state.md` with the Read tool. If the file does not exist or has no `pending_migrations` field in its YAML frontmatter, skip this step.
|
|
26
|
+
|
|
27
|
+
For each entry in `pending_migrations`:
|
|
28
|
+
|
|
29
|
+
**`move-standing-files`:** Move standing files from storage repo root to donna/ subfolder.
|
|
30
|
+
|
|
31
|
+
Run via Bash:
|
|
32
|
+
```bash
|
|
33
|
+
STORAGE_REPO="<storage_repo>"
|
|
34
|
+
DONNA_DIR="$STORAGE_REPO/donna"
|
|
35
|
+
MOVED=0
|
|
36
|
+
|
|
37
|
+
mkdir -p "$DONNA_DIR"
|
|
38
|
+
for FILE in role.md recurring.md role-research.md; do
|
|
39
|
+
if [ -f "$STORAGE_REPO/$FILE" ] && [ ! -f "$DONNA_DIR/$FILE" ]; then
|
|
40
|
+
mv "$STORAGE_REPO/$FILE" "$DONNA_DIR/$FILE"
|
|
41
|
+
echo "Moved $FILE to donna/$FILE"
|
|
42
|
+
MOVED=$((MOVED + 1))
|
|
43
|
+
fi
|
|
44
|
+
done
|
|
45
|
+
|
|
46
|
+
echo "MOVED=$MOVED"
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
If MOVED > 0, commit the move:
|
|
50
|
+
```bash
|
|
51
|
+
git -C <storage_repo> add -A
|
|
52
|
+
git -C <storage_repo> diff --cached --quiet || git -C <storage_repo> commit -m "donna(migrate): move standing files to donna/ subfolder"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
If `auto_push` is true in config, also push.
|
|
56
|
+
|
|
57
|
+
After processing all pending migrations, update `~/.donna/state.md` with the Write tool: remove the completed entries from `pending_migrations`. If no entries remain, write:
|
|
58
|
+
```markdown
|
|
59
|
+
---
|
|
60
|
+
pending_migrations: []
|
|
61
|
+
---
|
|
62
|
+
```
|
|
63
|
+
</step>
|
|
64
|
+
|
|
24
65
|
<step name="get-today">
|
|
25
66
|
Run via Bash to get today's date, day-of-week, and day-of-month:
|
|
26
67
|
```bash
|
|
@@ -66,7 +107,7 @@ Do NOT modify the previous file — it is a historical record and must remain un
|
|
|
66
107
|
</step>
|
|
67
108
|
|
|
68
109
|
<step name="check-recurring">
|
|
69
|
-
Read `<storage_repo>/recurring.md` with the Read tool. If the file does not exist, set `<recurring_tasks>` to an empty list and continue (recurring tasks are optional — set-role may not have been run yet).
|
|
110
|
+
Read `<storage_repo>/donna/recurring.md` with the Read tool. If the file does not exist, set `<recurring_tasks>` to an empty list and continue (recurring tasks are optional — set-role may not have been run yet).
|
|
70
111
|
|
|
71
112
|
Parse each line matching the pattern `- <description>: <interval>`. For "every other" intervals, also parse the `| last_run: YYYY-MM-DD` suffix.
|
|
72
113
|
|
|
@@ -86,6 +127,46 @@ For each task, determine if it is due today using this logic:
|
|
|
86
127
|
Store the descriptions of all due tasks as `<recurring_tasks>` (just the description text, without the interval suffix).
|
|
87
128
|
</step>
|
|
88
129
|
|
|
130
|
+
<step name="pull-tool-data">
|
|
131
|
+
Read `<storage_repo>/donna/tools.md` with the Read tool.
|
|
132
|
+
|
|
133
|
+
If the file does not exist or has no tool sections (no `## ` headers after the frontmatter), set `<tool_tasks>` to an empty list and `<tool_warnings>` to an empty list. Continue to the next step. Do NOT print any error — tools are optional.
|
|
134
|
+
|
|
135
|
+
For each tool section in tools.md, parse the `command` field and the `### Capabilities` entries. For each capability entry (format: `- <name>: <cli_invocation>`):
|
|
136
|
+
|
|
137
|
+
Run the CLI invocation via Bash with a 10-second timeout:
|
|
138
|
+
```bash
|
|
139
|
+
timeout 10 <cli_invocation> 2>&1
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
**On success (exit 0):**
|
|
143
|
+
Parse the output into task entries. Every task line MUST include both a tool tag and a descriptive link.
|
|
144
|
+
|
|
145
|
+
CRITICAL — tool tag format: Every tool task line MUST start with `(<tool_name>)` after the checkbox, where `<tool_name>` is the `## <tool_name>` section header from tools.md (e.g., `gh`, `jira`, `kubectl`). This tag identifies which tool sourced the task. Example: if processing the `## gh` section, every task line starts with `- [ ] (gh) `.
|
|
146
|
+
|
|
147
|
+
For `gh` JSON output (`--json number,title,url`): parse the JSON array. Extract `<owner>/<repo>` from the `url` field (e.g., `https://github.com/acme/api/pull/42` → `acme/api`). For each item, create:
|
|
148
|
+
`- [ ] (gh) <title> [<owner/repo>#<number>](<url>)`
|
|
149
|
+
|
|
150
|
+
For `jira` plain output: parse each row. For each issue, create:
|
|
151
|
+
`- [ ] (jira) <summary> [<key>](https://<jira_host>/browse/<key>)`
|
|
152
|
+
Note: jira plain output may not include URLs — if the URL is not available, use the issue key only: `- [ ] (jira) <summary> [<key>](<key>)`
|
|
153
|
+
|
|
154
|
+
For other tools: use Claude's understanding to extract task-like items from the output. Format with a descriptive identifier as the link text and URL if available:
|
|
155
|
+
`- [ ] (<tool_name>) <description> [<identifier>](<url>)`
|
|
156
|
+
|
|
157
|
+
**On failure (non-zero exit):**
|
|
158
|
+
Determine the failure type from the exit code and output:
|
|
159
|
+
- Exit 124: `! <tool_name>: timed out after 10s — check network connectivity`
|
|
160
|
+
- Exit 1 with "auth" or "login" in output: `! <tool_name>: authentication failed — run \`<auth_fix_command>\``
|
|
161
|
+
- Exit 127 or "not found" in output: `! <tool_name>: command not found — install <command> first`
|
|
162
|
+
- Other: `! <tool_name>: <first line of stderr>`
|
|
163
|
+
|
|
164
|
+
Add the warning to `<tool_warnings>`. Continue to next capability/tool. Never retry. Tool failures must never block manual tasks, carry-forward, or recurring task processing.
|
|
165
|
+
|
|
166
|
+
Collect all task entries as `<tool_tasks>`.
|
|
167
|
+
Collect all warning messages as `<tool_warnings>`.
|
|
168
|
+
</step>
|
|
169
|
+
|
|
89
170
|
<step name="read-existing-today">
|
|
90
171
|
If today's daily file already exists, read it with the Read tool. Extract all task lines — both open (`- [ ] ...`) and closed (`- [x] ...`). Store as `<existing_tasks>`.
|
|
91
172
|
|
|
@@ -95,7 +176,7 @@ If the file does not exist, `<existing_tasks>` is an empty list.
|
|
|
95
176
|
<step name="deduplicate">
|
|
96
177
|
Assemble the full task list using a single-pass deduplication to ensure idempotency:
|
|
97
178
|
|
|
98
|
-
**Normalization for comparison:** strip `- [ ] ` or `- [x] ` prefix, strip any trailing ` (N times)` suffix (where N is any integer), lowercase all text, trim whitespace.
|
|
179
|
+
**Normalization for comparison:** strip `- [ ] ` or `- [x] ` prefix, strip any leading `(<tool>) ` prefix (tool tag, matching the pattern `\(\w+\) `), strip any trailing ` (N times)` suffix (where N is any integer), strip any trailing ` [<text>](<url>)` suffix (tool source link, matching the pattern ` \[[^\]]+\]\([^\)]+\)`), strip any trailing ` (<reason>)` suffix (e.g. `(merged)`, `(closed)`), lowercase all text, trim whitespace.
|
|
99
180
|
|
|
100
181
|
1. Start with `<existing_tasks>` — both open and closed tasks take priority. Add them all to the final list.
|
|
101
182
|
|
|
@@ -103,8 +184,12 @@ Assemble the full task list using a single-pass deduplication to ensure idempote
|
|
|
103
184
|
|
|
104
185
|
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.
|
|
105
186
|
|
|
187
|
+
4. 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.
|
|
188
|
+
|
|
106
189
|
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.
|
|
107
190
|
|
|
191
|
+
CRITICAL: A closed task `- [x] (gh) Review PR #42 [acme/api#42](https://...)` must block a tool task `- [ ] (gh) Review PR #42 [acme/api#42](https://...)` from being re-added. The normalization (strip tool tag + source link) ensures both normalize to "review pr #42".
|
|
192
|
+
|
|
108
193
|
CRITICAL: If a carried-forward task already exists in today's file (from a previous run of begin-the-day today), do not re-add it or re-increment its counter. The normalization (strip suffix) ensures this.
|
|
109
194
|
|
|
110
195
|
Store the result as `<final_tasks>`.
|
|
@@ -126,13 +211,25 @@ date: <today>
|
|
|
126
211
|
<existing tasks, preserving their original order and open/closed state>
|
|
127
212
|
<carried-forward tasks not already in existing>
|
|
128
213
|
<recurring tasks not already in existing>
|
|
214
|
+
|
|
215
|
+
## From Tools
|
|
216
|
+
<tool tasks not already in existing — only if there are tool tasks>
|
|
217
|
+
|
|
218
|
+
## Resolved
|
|
219
|
+
<resolved tool tasks — only if there are resolved items>
|
|
220
|
+
|
|
221
|
+
## Warnings
|
|
222
|
+
<tool warnings — only if there are warnings>
|
|
129
223
|
```
|
|
130
224
|
|
|
131
225
|
Tasks are written in this order: existing tasks first (preserving their original order and state), then carried-forward tasks, then recurring tasks.
|
|
226
|
+
|
|
227
|
+
If `<tool_tasks>` is empty and there are no resolved items, omit the `## From Tools` and `## Resolved` sections entirely.
|
|
228
|
+
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`).
|
|
132
229
|
</step>
|
|
133
230
|
|
|
134
231
|
<step name="update-recurring-last-run">
|
|
135
|
-
If any tasks from `<recurring_tasks>` came from "every other" intervals and were added to today's file, update their `last_run` date in `<storage_repo>/recurring.md`.
|
|
232
|
+
If any tasks from `<recurring_tasks>` came from "every other" intervals and were added to today's file, update their `last_run` date in `<storage_repo>/donna/recurring.md`.
|
|
136
233
|
|
|
137
234
|
Read the full recurring.md file. For each such task, find the line and update the `| last_run: <old_date>` suffix to `| last_run: <today>`. If no `last_run` suffix exists, append ` | last_run: <today>` to the line. Write the full file back with the Write tool.
|
|
138
235
|
|
|
@@ -167,7 +264,7 @@ git -C <storage_repo> push
|
|
|
167
264
|
Print the daily brief to the terminal:
|
|
168
265
|
```
|
|
169
266
|
══════════════════════════════════════
|
|
170
|
-
|
|
267
|
+
Donna — Daily Brief for <today>
|
|
171
268
|
══════════════════════════════════════
|
|
172
269
|
```
|
|
173
270
|
|
|
@@ -185,12 +282,25 @@ If there are recurring tasks due today (tasks from `<recurring_tasks>` that were
|
|
|
185
282
|
- [ ] Review sprint backlog
|
|
186
283
|
```
|
|
187
284
|
|
|
285
|
+
If there are tool tasks (tasks from `<tool_tasks>` that were added to the final list), print:
|
|
286
|
+
```
|
|
287
|
+
## From Tools
|
|
288
|
+
- [ ] (gh) Review PR #42 [org/repo#42](https://github.com/org/repo/pull/42)
|
|
289
|
+
- [ ] (jira) Implement AUTH-07 [AUTH-07](https://company.atlassian.net/browse/AUTH-07)
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
If there are tool warnings (`<tool_warnings>` is not empty), print:
|
|
293
|
+
```
|
|
294
|
+
## Warnings
|
|
295
|
+
! gh: authentication failed — run `gh auth login`
|
|
296
|
+
```
|
|
297
|
+
|
|
188
298
|
Always end with:
|
|
189
299
|
```
|
|
190
300
|
══════════════════════════════════════
|
|
191
301
|
```
|
|
192
302
|
|
|
193
|
-
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
|
|
303
|
+
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:
|
|
194
304
|
```
|
|
195
305
|
No tasks for today — enjoy your day!
|
|
196
306
|
```
|
package/workflows/done.md
CHANGED
|
@@ -21,6 +21,47 @@ Extract the `storage_repo`, `daily_folder` (default: `daily`), and `auto_push` (
|
|
|
21
21
|
- Otherwise: do nothing.
|
|
22
22
|
</step>
|
|
23
23
|
|
|
24
|
+
<step name="check-pending-migrations">
|
|
25
|
+
Read `~/.donna/state.md` with the Read tool. If the file does not exist or has no `pending_migrations` field in its YAML frontmatter, skip this step.
|
|
26
|
+
|
|
27
|
+
For each entry in `pending_migrations`:
|
|
28
|
+
|
|
29
|
+
**`move-standing-files`:** Move standing files from storage repo root to donna/ subfolder.
|
|
30
|
+
|
|
31
|
+
Run via Bash:
|
|
32
|
+
```bash
|
|
33
|
+
STORAGE_REPO="<storage_repo>"
|
|
34
|
+
DONNA_DIR="$STORAGE_REPO/donna"
|
|
35
|
+
MOVED=0
|
|
36
|
+
|
|
37
|
+
mkdir -p "$DONNA_DIR"
|
|
38
|
+
for FILE in role.md recurring.md role-research.md; do
|
|
39
|
+
if [ -f "$STORAGE_REPO/$FILE" ] && [ ! -f "$DONNA_DIR/$FILE" ]; then
|
|
40
|
+
mv "$STORAGE_REPO/$FILE" "$DONNA_DIR/$FILE"
|
|
41
|
+
echo "Moved $FILE to donna/$FILE"
|
|
42
|
+
MOVED=$((MOVED + 1))
|
|
43
|
+
fi
|
|
44
|
+
done
|
|
45
|
+
|
|
46
|
+
echo "MOVED=$MOVED"
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
If MOVED > 0, commit the move:
|
|
50
|
+
```bash
|
|
51
|
+
git -C <storage_repo> add -A
|
|
52
|
+
git -C <storage_repo> diff --cached --quiet || git -C <storage_repo> commit -m "donna(migrate): move standing files to donna/ subfolder"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
If `auto_push` is true in config, also push.
|
|
56
|
+
|
|
57
|
+
After processing all pending migrations, update `~/.donna/state.md` with the Write tool: remove the completed entries from `pending_migrations`. If no entries remain, write:
|
|
58
|
+
```markdown
|
|
59
|
+
---
|
|
60
|
+
pending_migrations: []
|
|
61
|
+
---
|
|
62
|
+
```
|
|
63
|
+
</step>
|
|
64
|
+
|
|
24
65
|
<step name="find-daily-file">
|
|
25
66
|
Run via Bash to get today's date:
|
|
26
67
|
```bash
|
|
@@ -41,7 +82,7 @@ Read the daily file with the Read tool.
|
|
|
41
82
|
|
|
42
83
|
Find all lines matching the pattern `- [ ] <description>` (open tasks). Collect them as `<open_tasks>`. Do not print the list — it will be shown in the next step via AskUserQuestion.
|
|
43
84
|
|
|
44
|
-
When presenting task descriptions to the user (in the numbered list or match confirmation), strip any trailing ` (N times)` suffix (where N is any integer, e.g., `Follow up with Sarah (3 times)` becomes `Follow up with Sarah`) for cleaner display. Keep the full line internally for file operations.
|
|
85
|
+
When presenting task descriptions to the user (in the numbered list or match confirmation), strip any leading `(<tool>) ` prefix (tool tag, e.g., `(gh) Review PR #42...` becomes `Review PR #42...`), strip any trailing ` (N times)` suffix (where N is any integer, e.g., `Follow up with Sarah (3 times)` becomes `Follow up with Sarah`), and strip any trailing ` [<text>](<url>)` suffix (e.g., `Review PR #42 [org/repo#42](https://github.com/org/repo/pull/42)` becomes `Review PR #42`) for cleaner display. Keep the full line internally for file operations.
|
|
45
86
|
|
|
46
87
|
If no open tasks are found, print:
|
|
47
88
|
```
|
|
@@ -54,7 +95,7 @@ Stop.
|
|
|
54
95
|
Two modes based on whether an argument was provided to this command:
|
|
55
96
|
|
|
56
97
|
**With argument** (e.g., `/donna:done buy milk`):
|
|
57
|
-
When fuzzy-matching task descriptions, strip any trailing ` (N times)` suffix (where N is any integer, matching the regex `\(\d+ times\)`, e.g., `Follow up with Sarah (3 times)` becomes `Follow up with Sarah` for matching purposes).
|
|
98
|
+
When fuzzy-matching task descriptions, strip any trailing ` (N times)` suffix (where N is any integer, matching the regex `\(\d+ times\)`, e.g., `Follow up with Sarah (3 times)` becomes `Follow up with Sarah` for matching purposes). Also strip any leading `(<tool>) ` prefix (tool tag, matching the regex `^\(\w+\) `) and any trailing ` [<text>](<url>)` suffix (source link, matching the regex ` \[[^\]]+\]\([^\)]+\)`, e.g., `(gh) Review PR #42 [org/repo#42](https://github.com/org/repo/pull/42)` becomes `Review PR #42` for matching purposes). These suffixes are added by begin-the-day and are transparent to task completion.
|
|
58
99
|
|
|
59
100
|
Use your natural language understanding to fuzzy-match the argument against the open task descriptions (after stripping the counter suffix). If a match is found, show it and use AskUserQuestion to confirm:
|
|
60
101
|
```
|
|
@@ -63,7 +104,7 @@ Mark as done: '<task>'? (yes/no)
|
|
|
63
104
|
If no match is found, tell the user and list all open tasks.
|
|
64
105
|
|
|
65
106
|
**Without argument**:
|
|
66
|
-
When fuzzy-matching task descriptions, strip any trailing ` (N times)` suffix (where N is any integer, matching the regex `\(\d+ times\)`, e.g., `Follow up with Sarah (3 times)` becomes `Follow up with Sarah` for matching purposes).
|
|
107
|
+
When fuzzy-matching task descriptions, strip any trailing ` (N times)` suffix (where N is any integer, matching the regex `\(\d+ times\)`, e.g., `Follow up with Sarah (3 times)` becomes `Follow up with Sarah` for matching purposes). Also strip any leading `(<tool>) ` prefix (tool tag, matching the regex `^\(\w+\) `) and any trailing ` [<text>](<url>)` suffix (source link, matching the regex ` \[[^\]]+\]\([^\)]+\)`, e.g., `(gh) Review PR #42 [org/repo#42](https://github.com/org/repo/pull/42)` becomes `Review PR #42` for matching purposes). These suffixes are added by begin-the-day and are transparent to task completion.
|
|
67
108
|
|
|
68
109
|
Use AskUserQuestion to ask which task to mark as done. Provide the open task descriptions as options so the user can select from a list. The question text should be:
|
|
69
110
|
```
|
|
@@ -86,6 +127,8 @@ For each task in `<completed_tasks>`, replace `- [ ] <description>` with `- [x]
|
|
|
86
127
|
|
|
87
128
|
When marking a carry-forward task as complete, strip the ` (N times)` suffix from the completed line. The completed task should read `- [x] Follow up with Sarah` (clean, no counter).
|
|
88
129
|
|
|
130
|
+
When marking a tool-sourced task as complete, keep both the `(<tool>)` prefix and `[<identifier>](<url>)` suffix on the completed line (they serve as provenance). The completed task should read `- [x] (gh) Review PR #42 [org/repo#42](https://github.com/org/repo/pull/42)` (tool tag and source link preserved for traceability).
|
|
131
|
+
|
|
89
132
|
Write the updated file with the Write tool.
|
|
90
133
|
</step>
|
|
91
134
|
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# Donna Relearn-Tools Workflow
|
|
2
|
+
|
|
3
|
+
<objective>
|
|
4
|
+
Check each registered tool's installed version against its stored version and re-learn capabilities for tools that have been updated. Tools at the same version are skipped.
|
|
5
|
+
</objective>
|
|
6
|
+
|
|
7
|
+
<step name="read-config">
|
|
8
|
+
Read `~/.config/donna/config.md`.
|
|
9
|
+
|
|
10
|
+
If the file does not exist, print:
|
|
11
|
+
```
|
|
12
|
+
✗ Donna is not configured. Run /donna:setup first.
|
|
13
|
+
```
|
|
14
|
+
Stop.
|
|
15
|
+
|
|
16
|
+
Extract the `storage_repo`, `daily_folder` (default: `daily`), and `auto_push` (default: false) fields from the YAML frontmatter.
|
|
17
|
+
|
|
18
|
+
**Obsidian sync:** Check if `<storage_repo>/.obsidian/daily-notes.json` exists.
|
|
19
|
+
- If it exists and has a `folder` field that differs from `<daily_folder>`: update `<daily_folder>` to match Obsidian's value, and update `~/.config/donna/config.md` with the new `daily_folder`. Print `✓ Synced daily folder with Obsidian: <daily_folder>`.
|
|
20
|
+
- If `<storage_repo>/.obsidian/` exists but `daily-notes.json` does not exist or has no `folder` field: write `<storage_repo>/.obsidian/daily-notes.json` with `{"folder":"<daily_folder>"}`. Print `✓ Configured Obsidian daily notes to use <daily_folder>/`.
|
|
21
|
+
- Otherwise: do nothing.
|
|
22
|
+
</step>
|
|
23
|
+
|
|
24
|
+
<step name="check-pending-migrations">
|
|
25
|
+
Read `~/.donna/state.md` with the Read tool. If the file does not exist or has no `pending_migrations` field in its YAML frontmatter, skip this step.
|
|
26
|
+
|
|
27
|
+
For each entry in `pending_migrations`:
|
|
28
|
+
|
|
29
|
+
**`move-standing-files`:** Move standing files from storage repo root to donna/ subfolder.
|
|
30
|
+
|
|
31
|
+
Run via Bash:
|
|
32
|
+
```bash
|
|
33
|
+
STORAGE_REPO="<storage_repo>"
|
|
34
|
+
DONNA_DIR="$STORAGE_REPO/donna"
|
|
35
|
+
MOVED=0
|
|
36
|
+
|
|
37
|
+
mkdir -p "$DONNA_DIR"
|
|
38
|
+
for FILE in role.md recurring.md role-research.md; do
|
|
39
|
+
if [ -f "$STORAGE_REPO/$FILE" ] && [ ! -f "$DONNA_DIR/$FILE" ]; then
|
|
40
|
+
mv "$STORAGE_REPO/$FILE" "$DONNA_DIR/$FILE"
|
|
41
|
+
echo "Moved $FILE to donna/$FILE"
|
|
42
|
+
MOVED=$((MOVED + 1))
|
|
43
|
+
fi
|
|
44
|
+
done
|
|
45
|
+
|
|
46
|
+
echo "MOVED=$MOVED"
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
If MOVED > 0, commit the move:
|
|
50
|
+
```bash
|
|
51
|
+
git -C <storage_repo> add -A
|
|
52
|
+
git -C <storage_repo> diff --cached --quiet || git -C <storage_repo> commit -m "donna(migrate): move standing files to donna/ subfolder"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
If `auto_push` is true in config, also push.
|
|
56
|
+
|
|
57
|
+
After processing all pending migrations, update `~/.donna/state.md` with the Write tool: remove the completed entries from `pending_migrations`. If no entries remain, write:
|
|
58
|
+
```markdown
|
|
59
|
+
---
|
|
60
|
+
pending_migrations: []
|
|
61
|
+
---
|
|
62
|
+
```
|
|
63
|
+
</step>
|
|
64
|
+
|
|
65
|
+
<step name="read-tools-md">
|
|
66
|
+
Read `<storage_repo>/donna/tools.md` with the Read tool. If the file does not exist, print:
|
|
67
|
+
```
|
|
68
|
+
✗ No tools registered. Run /donna:add-tool first.
|
|
69
|
+
```
|
|
70
|
+
Stop.
|
|
71
|
+
|
|
72
|
+
Parse each tool section (starting with `## <tool_name>`). For each tool, extract:
|
|
73
|
+
- `command` — the CLI command to run
|
|
74
|
+
- `version` — the stored version string
|
|
75
|
+
- `learned` — the date capabilities were last learned
|
|
76
|
+
- capabilities list under `### Capabilities`
|
|
77
|
+
|
|
78
|
+
Store the parsed tools as `<registered_tools>`.
|
|
79
|
+
</step>
|
|
80
|
+
|
|
81
|
+
<step name="check-versions">
|
|
82
|
+
For each tool in `<registered_tools>`, run via Bash:
|
|
83
|
+
```bash
|
|
84
|
+
<command> --version 2>/dev/null | head -1
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Compare the output against the stored `version` field using simple string equality — "is it different?" is sufficient; no semver parsing required.
|
|
88
|
+
|
|
89
|
+
If `<command>` is not found (command fails), treat it as changed with a warning note.
|
|
90
|
+
|
|
91
|
+
Collect tools into two lists:
|
|
92
|
+
- `<changed_tools>` — installed version differs from stored version (or command not found)
|
|
93
|
+
- `<unchanged_tools>` — installed version matches stored version exactly
|
|
94
|
+
</step>
|
|
95
|
+
|
|
96
|
+
<step name="report-unchanged">
|
|
97
|
+
For each tool in `<unchanged_tools>`, print:
|
|
98
|
+
```
|
|
99
|
+
⊘ <tool_name>: unchanged at <version> — skipped
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
If ALL tools are in `<unchanged_tools>` (no changes found), print:
|
|
103
|
+
```
|
|
104
|
+
✓ All tools up to date. Nothing to re-learn.
|
|
105
|
+
```
|
|
106
|
+
Stop.
|
|
107
|
+
</step>
|
|
108
|
+
|
|
109
|
+
<step name="relearn-changed">
|
|
110
|
+
For each tool in `<changed_tools>`, apply the same learn-capabilities logic as add-tool.md's learn-capabilities step.
|
|
111
|
+
|
|
112
|
+
Determine if the tool is well-known (gh, jira, kubectl) or unknown. For well-known tools, synthesize capabilities from training data. Do NOT parse --help for well-known tools.
|
|
113
|
+
|
|
114
|
+
**gh (GitHub CLI) — training data baseline:**
|
|
115
|
+
- list-assigned-prs: `gh search prs --assignee=@me --state=open --json number,title,url --limit 20`
|
|
116
|
+
- list-review-requests: `gh search prs --review-requested=@me --state=open --json number,title,url --limit 20`
|
|
117
|
+
- list-assigned-issues: `gh search issues --assignee=@me --state=open --json number,title,url --limit 20`
|
|
118
|
+
|
|
119
|
+
**jira (ankitpokhrel/jira-cli) — training data baseline:**
|
|
120
|
+
- list-sprint-issues: `jira sprint list --current -a$(jira me) --plain`
|
|
121
|
+
- list-my-issues: `jira issue list -a$(jira me) --plain`
|
|
122
|
+
|
|
123
|
+
**kubectl — training data baseline:**
|
|
124
|
+
- list-pods: `kubectl get pods --all-namespaces --field-selector=status.phase!=Succeeded -o wide`
|
|
125
|
+
- list-failing: `kubectl get pods --all-namespaces --field-selector=status.phase=Failed -o wide`
|
|
126
|
+
|
|
127
|
+
For **unknown tools**, run `<command> --help 2>&1 | head -80` via Bash and use Claude's understanding to identify 3–5 capabilities relevant to daily task management.
|
|
128
|
+
|
|
129
|
+
Do NOT ask the user to re-select capabilities — keep the same capability names, update only the CLI invocations if the training data suggests changes.
|
|
130
|
+
|
|
131
|
+
Get the new installed version:
|
|
132
|
+
```bash
|
|
133
|
+
<command> --version 2>/dev/null | head -1
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Print:
|
|
137
|
+
```
|
|
138
|
+
✓ Re-learned <tool_name> (was <old_version>, now <new_version>)
|
|
139
|
+
```
|
|
140
|
+
</step>
|
|
141
|
+
|
|
142
|
+
<step name="write-tools-md">
|
|
143
|
+
Update `<storage_repo>/donna/tools.md`: for each re-learned tool, update its `version`, `learned` date (today's date YYYY-MM-DD), and capabilities section with the new invocations.
|
|
144
|
+
|
|
145
|
+
Upsert — replace only the re-learned tool sections, do not remove other tool sections. Preserve all unchanged tool sections exactly as they are.
|
|
146
|
+
|
|
147
|
+
Write the full file back with the Write tool.
|
|
148
|
+
</step>
|
|
149
|
+
|
|
150
|
+
<step name="git-commit">
|
|
151
|
+
Run via Bash:
|
|
152
|
+
```bash
|
|
153
|
+
git -C <storage_repo> add -A
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Check whether there is anything to commit:
|
|
157
|
+
```bash
|
|
158
|
+
git -C <storage_repo> status --porcelain
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
If the output is empty, skip the commit and continue.
|
|
162
|
+
|
|
163
|
+
Otherwise, run:
|
|
164
|
+
```bash
|
|
165
|
+
git -C <storage_repo> commit -m "donna(relearn-tools): updated <count> tool(s)"
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
If `auto_push` is true in config, also run:
|
|
169
|
+
```bash
|
|
170
|
+
git -C <storage_repo> push
|
|
171
|
+
```
|
|
172
|
+
</step>
|
|
173
|
+
|
|
174
|
+
<step name="confirm">
|
|
175
|
+
Print summary:
|
|
176
|
+
```
|
|
177
|
+
✓ Re-learned <count> tool(s): <tool_names>
|
|
178
|
+
<count> tool(s) unchanged: <tool_names>
|
|
179
|
+
```
|
|
180
|
+
</step>
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# Donna Run-Tools Workflow
|
|
2
|
+
|
|
3
|
+
<objective>
|
|
4
|
+
Execute all configured external tool commands, pull fresh data, and smart-merge results into today's daily file. Does not run the full begin-the-day carry-forward or recurring task logic — this is a mid-day update only.
|
|
5
|
+
</objective>
|
|
6
|
+
|
|
7
|
+
<step name="read-config">
|
|
8
|
+
Read `~/.config/donna/config.md`.
|
|
9
|
+
|
|
10
|
+
If the file does not exist, print:
|
|
11
|
+
```
|
|
12
|
+
✗ Donna is not configured. Run /donna:setup first.
|
|
13
|
+
```
|
|
14
|
+
Stop.
|
|
15
|
+
|
|
16
|
+
Extract the `storage_repo`, `daily_folder` (default: `daily`), and `auto_push` (default: false) fields from the YAML frontmatter.
|
|
17
|
+
|
|
18
|
+
**Obsidian sync:** Check if `<storage_repo>/.obsidian/daily-notes.json` exists.
|
|
19
|
+
- If it exists and has a `folder` field that differs from `<daily_folder>`: update `<daily_folder>` to match Obsidian's value, and update `~/.config/donna/config.md` with the new `daily_folder`. Print `✓ Synced daily folder with Obsidian: <daily_folder>`.
|
|
20
|
+
- If `<storage_repo>/.obsidian/` exists but `daily-notes.json` does not exist or has no `folder` field: write `<storage_repo>/.obsidian/daily-notes.json` with `{"folder":"<daily_folder>"}`. Print `✓ Configured Obsidian daily notes to use <daily_folder>/`.
|
|
21
|
+
- Otherwise: do nothing.
|
|
22
|
+
</step>
|
|
23
|
+
|
|
24
|
+
<step name="check-pending-migrations">
|
|
25
|
+
Read `~/.donna/state.md` with the Read tool. If the file does not exist or has no `pending_migrations` field in its YAML frontmatter, skip this step.
|
|
26
|
+
|
|
27
|
+
For each entry in `pending_migrations`:
|
|
28
|
+
|
|
29
|
+
**`move-standing-files`:** Move standing files from storage repo root to donna/ subfolder.
|
|
30
|
+
|
|
31
|
+
Run via Bash:
|
|
32
|
+
```bash
|
|
33
|
+
STORAGE_REPO="<storage_repo>"
|
|
34
|
+
DONNA_DIR="$STORAGE_REPO/donna"
|
|
35
|
+
MOVED=0
|
|
36
|
+
|
|
37
|
+
mkdir -p "$DONNA_DIR"
|
|
38
|
+
for FILE in role.md recurring.md role-research.md; do
|
|
39
|
+
if [ -f "$STORAGE_REPO/$FILE" ] && [ ! -f "$DONNA_DIR/$FILE" ]; then
|
|
40
|
+
mv "$STORAGE_REPO/$FILE" "$DONNA_DIR/$FILE"
|
|
41
|
+
echo "Moved $FILE to donna/$FILE"
|
|
42
|
+
MOVED=$((MOVED + 1))
|
|
43
|
+
fi
|
|
44
|
+
done
|
|
45
|
+
|
|
46
|
+
echo "MOVED=$MOVED"
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
If MOVED > 0, commit the move:
|
|
50
|
+
```bash
|
|
51
|
+
git -C <storage_repo> add -A
|
|
52
|
+
git -C <storage_repo> diff --cached --quiet || git -C <storage_repo> commit -m "donna(migrate): move standing files to donna/ subfolder"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
If `auto_push` is true in config, also push.
|
|
56
|
+
|
|
57
|
+
After processing all pending migrations, update `~/.donna/state.md` with the Write tool: remove the completed entries from `pending_migrations`. If no entries remain, write:
|
|
58
|
+
```markdown
|
|
59
|
+
---
|
|
60
|
+
pending_migrations: []
|
|
61
|
+
---
|
|
62
|
+
```
|
|
63
|
+
</step>
|
|
64
|
+
|
|
65
|
+
<step name="read-tools-md">
|
|
66
|
+
Read `<storage_repo>/donna/tools.md` with the Read tool. If the file does not exist, print:
|
|
67
|
+
```
|
|
68
|
+
✗ No tools registered. Run /donna:add-tool first.
|
|
69
|
+
```
|
|
70
|
+
Stop.
|
|
71
|
+
|
|
72
|
+
Parse each tool section (starting with `## <tool_name>`). For each tool, extract the `command` field and the capabilities list under `### Capabilities`.
|
|
73
|
+
|
|
74
|
+
Store the parsed tools and their capabilities as `<registered_tools>`.
|
|
75
|
+
</step>
|
|
76
|
+
|
|
77
|
+
<step name="find-daily-file">
|
|
78
|
+
Get today's date via Bash:
|
|
79
|
+
```bash
|
|
80
|
+
date +%Y-%m-%d
|
|
81
|
+
```
|
|
82
|
+
Store as `<today>`.
|
|
83
|
+
|
|
84
|
+
Construct the path: `<storage_repo>/<daily_folder>/<today>.md`.
|
|
85
|
+
|
|
86
|
+
If the file does not exist, print:
|
|
87
|
+
```
|
|
88
|
+
✗ No daily file for today. Run /donna:begin-the-day first.
|
|
89
|
+
```
|
|
90
|
+
Stop.
|
|
91
|
+
</step>
|
|
92
|
+
|
|
93
|
+
<step name="read-existing-tool-tasks">
|
|
94
|
+
Read today's daily file with the Read tool.
|
|
95
|
+
|
|
96
|
+
Extract all lines from the `## From Tools` section and the `## Resolved` section.
|
|
97
|
+
|
|
98
|
+
For each line, extract the embedded URL from the `[<text>](<url>)` pattern — this URL is the stable identifier for matching. Store as `<existing_tool_lines>`: a map of URL to full line (including its checkbox state `[ ]` or `[x]` and tool tag).
|
|
99
|
+
|
|
100
|
+
If the `## From Tools` section does not exist in today's file, set `<existing_tool_lines>` to an empty map. The section will be created during smart-merge.
|
|
101
|
+
</step>
|
|
102
|
+
|
|
103
|
+
<step name="pull-fresh-data">
|
|
104
|
+
For each tool in `<registered_tools>`, for each capability:
|
|
105
|
+
|
|
106
|
+
Run the capability command via Bash with a 10-second timeout:
|
|
107
|
+
```bash
|
|
108
|
+
timeout 10 <capability_command> 2>&1
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
**On success (exit 0):** Parse the output into task entries. Every task line MUST include both a tool tag and a descriptive link.
|
|
112
|
+
|
|
113
|
+
CRITICAL — tool tag format: Every tool task line MUST start with `(<tool_name>)` after the checkbox, where `<tool_name>` is the `## <tool_name>` section header from tools.md (e.g., `gh`, `jira`, `kubectl`). This tag identifies which tool sourced the task. Example: if processing the `## gh` section, every task line starts with `- [ ] (gh) `.
|
|
114
|
+
|
|
115
|
+
For gh JSON output, extract `number`, `title`, `url` fields from each JSON object. Use the `url` field as the stable identifier. Extract `<owner>/<repo>` from the URL (e.g., `https://github.com/acme/api/pull/42` → `acme/api`). Format:
|
|
116
|
+
```
|
|
117
|
+
- [ ] (gh) <title> [<owner/repo>#<number>](<url>)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
For jira plain output, extract the issue key and summary from each line. Format:
|
|
121
|
+
```
|
|
122
|
+
- [ ] (jira) <summary> [<issue_key>](https://jira.company.com/browse/<issue_key>)
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
For other tools: use Claude's understanding to extract task-like items from the output. Format with a descriptive identifier as the link text and URL if available:
|
|
126
|
+
```
|
|
127
|
+
- [ ] (<tool_name>) <description> [<identifier>](<url>)
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
**On failure (exit non-zero, including exit 124 for timeout):** Add a warning:
|
|
131
|
+
```
|
|
132
|
+
! <tool_name>: <error_description>
|
|
133
|
+
```
|
|
134
|
+
Continue to the next capability. Never retry.
|
|
135
|
+
|
|
136
|
+
Store all fresh tasks as `<fresh_tool_tasks>`: a map of URL to task line.
|
|
137
|
+
Collect all warning messages as `<tool_warnings>`.
|
|
138
|
+
</step>
|
|
139
|
+
|
|
140
|
+
<step name="smart-merge">
|
|
141
|
+
Apply three-way merge rules in priority order. This is a read-modify-write operation — the entire daily file is rewritten atomically with all sections updated.
|
|
142
|
+
|
|
143
|
+
Read the full current content of today's daily file.
|
|
144
|
+
|
|
145
|
+
**Process existing tool lines** (from `<existing_tool_lines>`):
|
|
146
|
+
|
|
147
|
+
For each URL in `<existing_tool_lines>`:
|
|
148
|
+
1. If the line is `[x]` (user manually checked): **KEEP AS-IS** — user intent wins (Rule 1). Do not change regardless of tool state.
|
|
149
|
+
2. If the line is `[ ]` AND the URL exists in `<fresh_tool_tasks>`: **KEEP OPEN** — item is still active (Rule 2).
|
|
150
|
+
3. If the line is `[ ]` AND the URL is NOT in `<fresh_tool_tasks>`: the item was removed from the tool (reassigned, deleted, or closed).
|
|
151
|
+
- For gh items: check if the PR/issue was closed or merged via Bash: `timeout 10 gh pr view <number> --json state --jq '.state' 2>/dev/null || timeout 10 gh issue view <number> --json state --jq '.state' 2>/dev/null`
|
|
152
|
+
- If closed or merged: change to `- [x] (<tool>) <description> [<identifier>](<url>) (<reason>)` and move to `## Resolved` (Rule 3a).
|
|
153
|
+
- If status check fails or item simply no longer appears: move to `## Resolved` with `(removed)` (Rule 3b).
|
|
154
|
+
|
|
155
|
+
**Add new items** (from `<fresh_tool_tasks>`):
|
|
156
|
+
|
|
157
|
+
For each URL in `<fresh_tool_tasks>` that is NOT in `<existing_tool_lines>`:
|
|
158
|
+
- **ADD** the task line to the `## From Tools` section (Rule 4 — new item).
|
|
159
|
+
|
|
160
|
+
**Rebuild the file:**
|
|
161
|
+
|
|
162
|
+
Rewrite today's daily file with the Write tool, preserving all non-tool sections exactly. The `## From Tools` section contains only currently open tool tasks. The `## Resolved` section contains closed/removed items appended to any existing resolved items.
|
|
163
|
+
|
|
164
|
+
CRITICAL: Remove items from `## From Tools` when moving them to `## Resolved`. Do NOT just append. The entire file is rewritten in one Write operation.
|
|
165
|
+
|
|
166
|
+
If `## From Tools` does not yet exist in the file, add it after the `## Tasks` section. If `## Resolved` does not yet exist, add it at the end of the file when needed.
|
|
167
|
+
</step>
|
|
168
|
+
|
|
169
|
+
<step name="git-commit">
|
|
170
|
+
Run via Bash:
|
|
171
|
+
```bash
|
|
172
|
+
git -C <storage_repo> add -A
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Check whether there is anything to commit:
|
|
176
|
+
```bash
|
|
177
|
+
git -C <storage_repo> status --porcelain
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
If the output is empty, skip the commit and continue.
|
|
181
|
+
|
|
182
|
+
Otherwise, run:
|
|
183
|
+
```bash
|
|
184
|
+
git -C <storage_repo> commit -m "donna(run-tools): refreshed tool data for <today>"
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
If `auto_push` is true in config, also run:
|
|
188
|
+
```bash
|
|
189
|
+
git -C <storage_repo> push
|
|
190
|
+
```
|
|
191
|
+
</step>
|
|
192
|
+
|
|
193
|
+
<step name="print-summary">
|
|
194
|
+
Print:
|
|
195
|
+
```
|
|
196
|
+
══════════════════════════════════════
|
|
197
|
+
Donna — Run Tools for <today>
|
|
198
|
+
══════════════════════════════════════
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
If new tasks were added (Rule 4), print each new task line.
|
|
202
|
+
If tasks were auto-closed (Rule 3a), print each with reason.
|
|
203
|
+
If tasks were moved to Resolved (Rule 3b), print each with reason.
|
|
204
|
+
If there are warnings from `<tool_warnings>`, print each warning line.
|
|
205
|
+
If nothing changed, print:
|
|
206
|
+
```
|
|
207
|
+
No changes from tools.
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
End with:
|
|
211
|
+
```
|
|
212
|
+
══════════════════════════════════════
|
|
213
|
+
```
|
|
214
|
+
</step>
|
package/workflows/set-role.md
CHANGED
|
@@ -16,10 +16,51 @@ Stop.
|
|
|
16
16
|
Extract the `storage_repo` and `auto_push` (default: false) fields from the YAML frontmatter.
|
|
17
17
|
</step>
|
|
18
18
|
|
|
19
|
+
<step name="check-pending-migrations">
|
|
20
|
+
Read `~/.donna/state.md` with the Read tool. If the file does not exist or has no `pending_migrations` field in its YAML frontmatter, skip this step.
|
|
21
|
+
|
|
22
|
+
For each entry in `pending_migrations`:
|
|
23
|
+
|
|
24
|
+
**`move-standing-files`:** Move standing files from storage repo root to donna/ subfolder.
|
|
25
|
+
|
|
26
|
+
Run via Bash:
|
|
27
|
+
```bash
|
|
28
|
+
STORAGE_REPO="<storage_repo>"
|
|
29
|
+
DONNA_DIR="$STORAGE_REPO/donna"
|
|
30
|
+
MOVED=0
|
|
31
|
+
|
|
32
|
+
mkdir -p "$DONNA_DIR"
|
|
33
|
+
for FILE in role.md recurring.md role-research.md; do
|
|
34
|
+
if [ -f "$STORAGE_REPO/$FILE" ] && [ ! -f "$DONNA_DIR/$FILE" ]; then
|
|
35
|
+
mv "$STORAGE_REPO/$FILE" "$DONNA_DIR/$FILE"
|
|
36
|
+
echo "Moved $FILE to donna/$FILE"
|
|
37
|
+
MOVED=$((MOVED + 1))
|
|
38
|
+
fi
|
|
39
|
+
done
|
|
40
|
+
|
|
41
|
+
echo "MOVED=$MOVED"
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
If MOVED > 0, commit the move:
|
|
45
|
+
```bash
|
|
46
|
+
git -C <storage_repo> add -A
|
|
47
|
+
git -C <storage_repo> diff --cached --quiet || git -C <storage_repo> commit -m "donna(migrate): move standing files to donna/ subfolder"
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
If `auto_push` is true in config, also push.
|
|
51
|
+
|
|
52
|
+
After processing all pending migrations, update `~/.donna/state.md` with the Write tool: remove the completed entries from `pending_migrations`. If no entries remain, write:
|
|
53
|
+
```markdown
|
|
54
|
+
---
|
|
55
|
+
pending_migrations: []
|
|
56
|
+
---
|
|
57
|
+
```
|
|
58
|
+
</step>
|
|
59
|
+
|
|
19
60
|
<step name="check-existing-role">
|
|
20
61
|
Run via Bash:
|
|
21
62
|
```bash
|
|
22
|
-
test -f <storage_repo>/role.md && echo "exists" || echo "missing"
|
|
63
|
+
test -f <storage_repo>/donna/role.md && echo "exists" || echo "missing"
|
|
23
64
|
```
|
|
24
65
|
|
|
25
66
|
If the output is "exists", proceed to the rerun-menu step.
|
|
@@ -39,8 +80,8 @@ A role definition already exists. What would you like to do?
|
|
|
39
80
|
```
|
|
40
81
|
|
|
41
82
|
- On "reset" (option 1): proceed to ask-role (fresh start, will overwrite role.md and recurring.md).
|
|
42
|
-
- On "diff-update" (option 2): read current role.md with the Read tool, proceed to ask-role but pre-fill with current values and note this is an update. After research, show delta (added/removed recurring tasks vs current recurring.md). Preserve any manually-added recurring tasks (tasks in recurring.md not in the research suggestions).
|
|
43
|
-
- On "re-research" (option 3): read current role.md with the Read tool to get the existing role data, skip to the research step.
|
|
83
|
+
- On "diff-update" (option 2): read current `<storage_repo>/donna/role.md` with the Read tool, proceed to ask-role but pre-fill with current values and note this is an update. After research, show delta (added/removed recurring tasks vs current `<storage_repo>/donna/recurring.md`). Preserve any manually-added recurring tasks (tasks in recurring.md not in the research suggestions).
|
|
84
|
+
- On "re-research" (option 3): read current `<storage_repo>/donna/role.md` with the Read tool to get the existing role data, skip to the research step.
|
|
44
85
|
- On "Cancel" (option 4): print "Cancelled." and stop.
|
|
45
86
|
</step>
|
|
46
87
|
|
|
@@ -132,7 +173,7 @@ Do NOT create tools.md or configure anything — only note the user's interest.
|
|
|
132
173
|
</step>
|
|
133
174
|
|
|
134
175
|
<step name="save-role">
|
|
135
|
-
Write `<storage_repo>/role.md` with the Write tool.
|
|
176
|
+
Write `<storage_repo>/donna/role.md` with the Write tool.
|
|
136
177
|
|
|
137
178
|
Use this format (substituting actual values):
|
|
138
179
|
```markdown
|
|
@@ -151,7 +192,7 @@ updated: <today's date in YYYY-MM-DD format>
|
|
|
151
192
|
[Write a 2–3 sentence prose summary of the role as described by the user, incorporating their key responsibilities and team context.]
|
|
152
193
|
```
|
|
153
194
|
|
|
154
|
-
Write `<storage_repo>/role-research.md` with the Write tool.
|
|
195
|
+
Write `<storage_repo>/donna/role-research.md` with the Write tool.
|
|
155
196
|
|
|
156
197
|
Use this format:
|
|
157
198
|
```markdown
|
|
@@ -185,7 +226,7 @@ role: <job_title>
|
|
|
185
226
|
</step>
|
|
186
227
|
|
|
187
228
|
<step name="save-recurring">
|
|
188
|
-
Write `<storage_repo>/recurring.md` with the Write tool.
|
|
229
|
+
Write `<storage_repo>/donna/recurring.md` with the Write tool.
|
|
189
230
|
|
|
190
231
|
Format: one approved recurring task per line as `- Task description: interval`.
|
|
191
232
|
For "every other" intervals (biweekly, every other Monday, etc.), append ` | last_run: <today's date>` suffix.
|
|
@@ -202,7 +243,7 @@ Use this format:
|
|
|
202
243
|
```
|
|
203
244
|
|
|
204
245
|
If this is a diff-update (user chose option 2 in rerun-menu):
|
|
205
|
-
1. Read the existing `<storage_repo>/recurring.md` with the Read tool.
|
|
246
|
+
1. Read the existing `<storage_repo>/donna/recurring.md` with the Read tool.
|
|
206
247
|
2. Identify manually-added tasks: tasks in recurring.md that were NOT in the research suggestions.
|
|
207
248
|
3. Merge: keep manually-added tasks, add new approved tasks, remove tasks the user rejected.
|
|
208
249
|
4. Write the merged result.
|
package/workflows/setup.md
CHANGED
|
@@ -103,16 +103,17 @@ Set `<daily_folder>` to `daily`. Print:
|
|
|
103
103
|
</step>
|
|
104
104
|
|
|
105
105
|
<step name="create-storage-structure">
|
|
106
|
-
Create the daily
|
|
106
|
+
Create the daily and donna directories:
|
|
107
107
|
|
|
108
108
|
Run via Bash:
|
|
109
109
|
```bash
|
|
110
110
|
mkdir -p <repo>/<daily_folder>
|
|
111
|
+
mkdir -p <repo>/donna
|
|
111
112
|
```
|
|
112
113
|
|
|
113
114
|
Print:
|
|
114
115
|
```
|
|
115
|
-
✓ Created <daily_folder>/
|
|
116
|
+
✓ Created <daily_folder>/ and donna/ directories
|
|
116
117
|
```
|
|
117
118
|
</step>
|
|
118
119
|
|