@pingvinen/donna-assistant 0.4.0 → 0.6.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.
@@ -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>
@@ -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.
@@ -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 directory:
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>/ directory
116
+ ✓ Created <daily_folder>/ and donna/ directories
116
117
  ```
117
118
  </step>
118
119