@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.
@@ -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
- DONNA — Daily Brief for <today>
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 both sections are empty and there are no existing tasks, print:
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
  ```
@@ -0,0 +1,128 @@
1
+ # Donna Contribute Idea Workflow
2
+
3
+ <objective>
4
+ Help users submit feature ideas or bug reports by checking for duplicates against existing GitHub Issues and the project's pending todos, then creating a new issue if the idea is novel.
5
+ </objective>
6
+
7
+ <step name="banner">
8
+ Print the Donna banner:
9
+ ```
10
+ ━━━ Donna ▸ Contribute Idea ━━━
11
+ ```
12
+ </step>
13
+
14
+ <step name="check-gh-auth">
15
+ Run via Bash:
16
+ ```bash
17
+ gh auth status 2>&1
18
+ ```
19
+
20
+ If the exit code is non-zero, print:
21
+ ```
22
+ ✗ The gh CLI is not authenticated. Run 'gh auth login' first, then re-run /donna:contribute-idea.
23
+ ```
24
+ Stop.
25
+ </step>
26
+
27
+ <step name="ask-idea">
28
+ Use AskUserQuestion:
29
+
30
+ ```
31
+ What's your idea or bug report?
32
+
33
+ Describe it in a few sentences — I'll check if something similar already exists before creating an issue.
34
+ ```
35
+
36
+ Store the response as `<user_idea>`.
37
+ </step>
38
+
39
+ <step name="check-duplicates">
40
+ Check two sources for potential duplicates.
41
+
42
+ **Source 1: GitHub Issues**
43
+
44
+ Run via Bash:
45
+ ```bash
46
+ gh issue list --repo pingvinen/donna --state open --json number,title,url --limit 100
47
+ ```
48
+
49
+ Parse the JSON output. Compare each issue title against `<user_idea>` using semantic similarity — judge whether the idea meaningfully overlaps with an existing issue. Do not use brittle substring matching.
50
+
51
+ **Source 2: GSD pending todos from STATE.md on GitHub**
52
+
53
+ Run via Bash:
54
+ ```bash
55
+ gh api repos/pingvinen/donna/contents/.planning/STATE.md --jq '.content | @base64d'
56
+ ```
57
+
58
+ Parse the `### Pending Todos` section from the decoded content. Each bullet is a pending todo. Compare each todo against `<user_idea>` using semantic similarity.
59
+
60
+ **If either source has a potential match**, present the match(es) to the user:
61
+
62
+ ```
63
+ I found something similar:
64
+
65
+ [For GitHub Issue match:]
66
+ → Issue #<number>: <title>
67
+ <url>
68
+ You can upvote or comment on this issue instead of creating a new one.
69
+
70
+ [For pending todo match:]
71
+ → Pending todo: "<todo text>"
72
+ This is already tracked internally.
73
+ ```
74
+
75
+ Then use AskUserQuestion:
76
+ ```
77
+ Would you like to:
78
+ 1. Create a new issue anyway (it's different enough)
79
+ 2. Skip — the existing one covers my idea
80
+ ```
81
+
82
+ If the user chooses option 2, print:
83
+ ```
84
+ ✓ Thanks for checking! The existing item covers this.
85
+ ```
86
+ Stop.
87
+
88
+ If no duplicates are found, proceed to the create-issue step.
89
+ </step>
90
+
91
+ <step name="create-issue">
92
+ Help the user create a well-formed GitHub Issue.
93
+
94
+ Draft a suggested title and body based on `<user_idea>`. Use AskUserQuestion:
95
+
96
+ ```
97
+ Let me help you write up the issue. Here's what I've drafted based on your idea:
98
+
99
+ Title: <suggested title based on user_idea>
100
+
101
+ Body:
102
+ <suggested body with description, context, and expected behavior>
103
+
104
+ Would you like to:
105
+ 1. Submit as-is
106
+ 2. Edit the title or body first
107
+ 3. Cancel
108
+ ```
109
+
110
+ Handle each option:
111
+
112
+ - **Option 1 (submit as-is):** Run via Bash:
113
+ ```bash
114
+ gh issue create --repo pingvinen/donna --title "<title>" --body "<body>"
115
+ ```
116
+ Print the resulting issue URL with a success message:
117
+ ```
118
+ ✓ Issue created: <url>
119
+ ```
120
+
121
+ - **Option 2 (edit):** Use AskUserQuestion to collect edits from the user. Re-present the updated draft and repeat until the user chooses to submit or cancel.
122
+
123
+ - **Option 3 (cancel):** Print:
124
+ ```
125
+ Issue cancelled.
126
+ ```
127
+ Stop.
128
+ </step>
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). This counter is added by begin-the-day's carry-forward and is transparent to task completion.
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). This counter is added by begin-the-day's carry-forward and is transparent to task completion.
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,155 @@
1
+ # Donna Help Workflow
2
+
3
+ <objective>
4
+ Provide interactive troubleshooting by inspecting Donna's state and guiding the user through diagnosing and resolving issues.
5
+ </objective>
6
+
7
+ <step name="banner">
8
+ Print the Donna banner:
9
+ ```
10
+ ━━━ Donna ▸ Help ━━━
11
+ ```
12
+ </step>
13
+
14
+ <step name="read-config">
15
+ Read `~/.config/donna/config.md`.
16
+
17
+ If the file does not exist, print:
18
+ ```
19
+ ✗ Donna is not configured. Run /donna:setup first.
20
+ ```
21
+ Stop.
22
+
23
+ Extract the `storage_repo`, `daily_folder` (default: `daily`), and `auto_push` (default: false) fields from the YAML frontmatter.
24
+ </step>
25
+
26
+ <step name="ask-problem">
27
+ Use AskUserQuestion:
28
+
29
+ ```
30
+ What do you need help with?
31
+
32
+ Some things I can help diagnose:
33
+ - Configuration issues
34
+ - Storage repo problems
35
+ - Skills not working
36
+ - Tool integration issues
37
+ - General questions about how Donna works
38
+
39
+ Describe what's going on:
40
+ ```
41
+
42
+ Store the response as `<user_problem>`.
43
+ </step>
44
+
45
+ <step name="diagnose">
46
+ Based on `<user_problem>`, inspect relevant state using keyword matching to determine the category and run the appropriate checks.
47
+
48
+ **Config issues** (keywords: config, setup, configure, path):
49
+
50
+ Run via Bash:
51
+ ```bash
52
+ test -d <storage_repo> && echo "EXISTS" || echo "MISSING"
53
+ ```
54
+ ```bash
55
+ git -C <storage_repo> status 2>&1 | head -1
56
+ ```
57
+
58
+ Display the contents of `~/.config/donna/config.md`. Report:
59
+ - Whether the storage_repo path exists
60
+ - Whether it is a valid git repository
61
+
62
+ **Storage issues** (keywords: storage, repo, git, daily, file, missing):
63
+
64
+ Run via Bash:
65
+ ```bash
66
+ test -d <storage_repo> && echo "EXISTS" || echo "MISSING"
67
+ ```
68
+ ```bash
69
+ git -C <storage_repo> status 2>&1 | head -1
70
+ ```
71
+ ```bash
72
+ ls <storage_repo>/donna/ 2>/dev/null
73
+ ```
74
+ ```bash
75
+ ls <storage_repo>/<daily_folder>/ 2>/dev/null | tail -5
76
+ ```
77
+ ```bash
78
+ git -C <storage_repo> status --short 2>/dev/null
79
+ ```
80
+
81
+ Report whether the storage repo exists and is a git repo, whether the donna/ subfolder is present, the most recent daily files, and any uncommitted changes.
82
+
83
+ **Skill issues** (keywords: skill, command, slash, workflow, not working, error):
84
+
85
+ Run via Bash:
86
+ ```bash
87
+ ls ~/.claude/commands/donna/ 2>/dev/null
88
+ ```
89
+ ```bash
90
+ ls ~/.donna/workflows/ 2>/dev/null
91
+ ```
92
+
93
+ Read `~/.donna/version.md` with the Read tool (if it exists).
94
+
95
+ Report the installed stubs and workflows, compare their counts, and print the Donna version.
96
+
97
+ **Tool issues** (keywords: tool, gh, jira, integration, pull, refresh):
98
+
99
+ Read `<storage_repo>/donna/tools.md` with the Read tool if it exists.
100
+
101
+ For each tool found in tools.md, run via Bash:
102
+ ```bash
103
+ which <tool_name> 2>/dev/null
104
+ ```
105
+
106
+ If `gh` is a configured tool, also run:
107
+ ```bash
108
+ gh auth status 2>&1
109
+ ```
110
+
111
+ Report which tools are installed and authenticated.
112
+
113
+ **General / no clear category** (catch-all when no keyword matches):
114
+
115
+ Run all checks from the above categories and present a full health summary. Include:
116
+ - Donna version (from `~/.donna/version.md`)
117
+ - Config status (file exists, storage_repo path valid)
118
+ - Storage status (git repo exists, donna/ and daily/ present, uncommitted changes)
119
+ - Installed skills count (stubs in `~/.claude/commands/donna/`, workflows in `~/.donna/workflows/`)
120
+ - Configured tools (from `<storage_repo>/donna/tools.md`)
121
+
122
+ After running diagnostics, present findings clearly:
123
+ - Use `✓` for things that look good
124
+ - Use `✗` for things that look broken
125
+ - Provide specific fix suggestions for each `✗` item
126
+ </step>
127
+
128
+ <step name="follow-up">
129
+ Use AskUserQuestion:
130
+
131
+ ```
132
+ Did that help? You can:
133
+ 1. Ask about something else
134
+ 2. Submit a bug report or feature idea (I'll point you to /donna:contribute-idea)
135
+ 3. Done — I'm all set
136
+
137
+ What would you like to do?
138
+ ```
139
+
140
+ Handle each option:
141
+
142
+ - **Option 1:** Ask the user for a new description of their issue. Loop back to the diagnose step with the new question.
143
+
144
+ - **Option 2:** Print:
145
+ ```
146
+ Tip: Run /donna:contribute-idea to submit ideas or bug reports via GitHub Issues.
147
+ ```
148
+ Stop.
149
+
150
+ - **Option 3:** Print:
151
+ ```
152
+ ✓ Glad I could help!
153
+ ```
154
+ Stop.
155
+ </step>