@pingvinen/donna-assistant 0.9.0 → 0.10.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/workflows/done.md CHANGED
@@ -4,71 +4,33 @@
4
4
  Mark one or more tasks as complete in today's daily journal file and commit the change to git.
5
5
  </objective>
6
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
-
7
+ <step name="init">
31
8
  Run via Bash:
32
9
  ```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"
10
+ INIT=$(node ~/.donna/donna-tools.cjs init)
47
11
  ```
48
12
 
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"
13
+ Parse the JSON response. If the `error` field is `"not_configured"`, print:
14
+ ```
15
+ x Donna is not configured. Run /donna:setup first.
53
16
  ```
17
+ Stop.
54
18
 
55
- If `auto_push` is true in config, also push.
19
+ Extract `storage_repo`, `daily_folder`, `auto_push` from the JSON.
56
20
 
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
- ---
21
+ If `update_available` is non-null, print:
22
+ ```
23
+ Donna v<update_available> available -- run npx @pingvinen/donna-assistant to update
62
24
  ```
25
+ Continue normally.
63
26
  </step>
64
27
 
65
28
  <step name="find-daily-file">
66
- Run via Bash to get today's date:
29
+ Get the daily file path via donna-tools:
67
30
  ```bash
68
- date +%Y-%m-%d
31
+ DAILY_PATH=$(node ~/.donna/donna-tools.cjs daily-path | node -e "process.stdin.resume();let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>console.log(JSON.parse(d).path))")
69
32
  ```
70
-
71
- Store the result as `<date>`. Construct the daily file path: `<storage_repo>/<daily_folder>/<date>.md`.
33
+ Store the result as `<daily_file_path>`. Extract `<date>` from the filename (last path component without `.md`).
72
34
 
73
35
  If the file does not exist, print:
74
36
  ```
@@ -135,30 +97,10 @@ Write the updated file with the Write tool.
135
97
  <step name="git-commit">
136
98
  Run via Bash:
137
99
  ```bash
138
- git -C <storage_repo> add -A
139
- ```
140
-
141
- Check whether there is anything to commit:
142
- ```bash
143
- git -C <storage_repo> status --porcelain
100
+ node ~/.donna/donna-tools.cjs commit "donna(done): <task_summary>" --files <daily_folder>/<date>.md
144
101
  ```
145
102
 
146
- If the output is empty, skip the commit and continue.
147
-
148
- If one task was completed, run:
149
- ```bash
150
- git -C <storage_repo> commit -m "donna(done): <description>"
151
- ```
152
-
153
- If multiple tasks were completed, run:
154
- ```bash
155
- git -C <storage_repo> commit -m "donna(done): <N> tasks completed"
156
- ```
157
-
158
- If `auto_push` is true in config, also run:
159
- ```bash
160
- git -C <storage_repo> push
161
- ```
103
+ Where `<task_summary>` is the completed task description (if one task) or `<N> tasks completed` (if multiple tasks).
162
104
  </step>
163
105
 
164
106
  <step name="confirm">
@@ -4,92 +4,33 @@
4
4
  Read today's daily file, score open tasks on urgency and context signals, optionally re-query active tools for enriched data, and produce a short prioritized focus list written to daily/focus.md and printed to the terminal. This is a read-only operation relative to the daily file: only focus.md is written.
5
5
  </objective>
6
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
-
7
+ <step name="init">
31
8
  Run via Bash:
32
9
  ```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"
10
+ INIT=$(node ~/.donna/donna-tools.cjs init)
47
11
  ```
48
12
 
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"
13
+ Parse the JSON response. If the `error` field is `"not_configured"`, print:
53
14
  ```
54
-
55
- If `auto_push` is true in config, also push.
56
-
57
- **`backfill-tool-type`:** Backfill `type` on existing tool sections in tools.md using heuristic detection.
58
-
59
- Read `<storage_repo>/donna/tools.md` with the Read tool. If the file does not exist or has no tool sections, skip this handler.
60
-
61
- For each tool section (starting with `## <tool_name>`), check if a `- type:` line already exists. If the `- type:` line is missing, detect the correct type:
62
-
63
- 1. If the tool section contains a `- command:` line where the value starts with `mcp:` (e.g., `- command: mcp:linear`), insert `- type: mcp` immediately after the `- command:` line.
64
- 2. Else, if the tool section contains a `- base_url:` line:
65
- - If the capabilities section contains entries that look like GraphQL queries (contain `query {` or `mutation {`), insert `- type: graphql` immediately after `## <tool_name>` (REST/GraphQL tools have no `- command:` line).
66
- - Otherwise, insert `- type: rest` immediately after `## <tool_name>`.
67
- 3. Else (no `mcp:` prefix, no `base_url` field), insert `- type: cli` immediately after the `- command:` line.
68
-
69
- Write the updated file back with the Write tool. If any changes were made, commit:
70
- ```bash
71
- git -C <storage_repo> add -A
72
- git -C <storage_repo> diff --cached --quiet || git -C <storage_repo> commit -m "donna(migrate): backfill tool types on existing tools"
15
+ x Donna is not configured. Run /donna:setup first.
73
16
  ```
17
+ Stop.
74
18
 
75
- If `auto_push` is true in config, also push.
19
+ Extract `storage_repo`, `daily_folder`, `auto_push` from the JSON.
76
20
 
77
- 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:
78
- ```markdown
79
- ---
80
- pending_migrations: []
81
- ---
21
+ If `update_available` is non-null, print:
82
22
  ```
23
+ Donna v<update_available> available -- run npx @pingvinen/donna-assistant to update
24
+ ```
25
+ Continue normally.
83
26
  </step>
84
27
 
85
28
  <step name="read-daily-file">
86
- Get today's date via Bash:
29
+ Get the daily file path via donna-tools:
87
30
  ```bash
88
- date +%Y-%m-%d
31
+ DAILY_PATH=$(node ~/.donna/donna-tools.cjs daily-path | node -e "process.stdin.resume();let d='';process.stdin.on('data',c=>d+=c);process.stdin.on('end',()=>console.log(JSON.parse(d).path))")
89
32
  ```
90
- Store as `<today>`.
91
-
92
- Construct the daily file path: `<storage_repo>/<daily_folder>/<today>.md`.
33
+ Store the result as `<daily_file_path>`. Extract `<today>` from the filename (last path component without `.md`).
93
34
 
94
35
  Read the daily file with the Read tool. If the file does not exist, print:
95
36
  ```
@@ -154,23 +95,25 @@ For each matched tool, extract:
154
95
  **Type-aware execution within each agent (or direct execution for single tool):**
155
96
 
156
97
  For `type: cli` capabilities (format: `<name>: <cli_invocation>`):
98
+
99
+ Run via Bash (set the Bash tool's `timeout` parameter to `10000`):
157
100
  ```bash
158
- timeout 10 <cli_invocation> 2>&1
101
+ <cli_invocation> 2>&1
159
102
  ```
160
103
 
161
104
  For `type: rest` capabilities (format: `<name>: <METHOD> /path`):
162
105
  1. Read `<storage_repo>/donna/secrets.md` with the Read tool. Parse key-value pairs from under the frontmatter.
163
106
  2. Resolve the `auth_secret` key to get the actual secret value. If the key is not found in secrets.md or the value is `REPLACE_WITH_YOUR_SECRET`, add warning `! <tool_name>: missing secret <auth_secret> — edit donna/secrets.md` and skip this tool.
164
- 3. For each capability, run via Bash with a 10-second timeout:
107
+ 3. For each capability, run via Bash (set the Bash tool's `timeout` parameter to `10000`):
165
108
  ```bash
166
- timeout 10 curl -s -H "<auth_header>: <resolved_secret>" "<base_url><path>" 2>&1
109
+ curl -s -H "<auth_header>: <resolved_secret>" "<base_url><path>" 2>&1
167
110
  ```
168
111
 
169
112
  For `type: graphql` capabilities (format: `<name>: <graphql_query>`):
170
113
  1. Same secrets resolution as REST.
171
- 2. For each capability, run via Bash with a 10-second timeout:
114
+ 2. For each capability, run via Bash (set the Bash tool's `timeout` parameter to `10000`):
172
115
  ```bash
173
- timeout 10 curl -s -X POST -H "<auth_header>: <resolved_secret>" -H "Content-Type: application/json" -d '{"query":"<graphql_query>"}' "<base_url>" 2>&1
116
+ curl -s -X POST -H "<auth_header>: <resolved_secret>" -H "Content-Type: application/json" -d '{"query":"<graphql_query>"}' "<base_url>" 2>&1
174
117
  ```
175
118
 
176
119
  For `type: mcp` capabilities (format: `<name>: mcp:<server>/<tool>`):
@@ -262,24 +205,7 @@ If there are tool warnings from `<tool_warnings>`, append them after the footer:
262
205
  <step name="git-commit">
263
206
  Run via Bash:
264
207
  ```bash
265
- git -C <storage_repo> add -A
266
- ```
267
-
268
- Check whether there is anything to commit:
269
- ```bash
270
- git -C <storage_repo> status --porcelain
271
- ```
272
-
273
- If the output is empty, skip the commit and continue.
274
-
275
- Otherwise, run:
276
- ```bash
277
- git -C <storage_repo> commit -m "donna(focus): focus list for <today>"
278
- ```
279
-
280
- If `auto_push` is true in config, also run:
281
- ```bash
282
- git -C <storage_repo> push
208
+ node ~/.donna/donna-tools.cjs commit "donna(focus): updated focus list" --files <daily_folder>/<today>.md
283
209
  ```
284
210
  </step>
285
211
 
@@ -4,82 +4,25 @@
4
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
5
  </objective>
6
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
-
7
+ <step name="init">
31
8
  Run via Bash:
32
9
  ```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"
10
+ INIT=$(node ~/.donna/donna-tools.cjs init)
47
11
  ```
48
12
 
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"
13
+ Parse the JSON response. If the `error` field is `"not_configured"`, print:
53
14
  ```
54
-
55
- If `auto_push` is true in config, also push.
56
-
57
- **`backfill-tool-type`:** Backfill `type` on existing tool sections in tools.md using heuristic detection.
58
-
59
- Read `<storage_repo>/donna/tools.md` with the Read tool. If the file does not exist or has no tool sections, skip this handler.
60
-
61
- For each tool section (starting with `## <tool_name>`), check if a `- type:` line already exists. If the `- type:` line is missing, detect the correct type:
62
-
63
- 1. If the tool section contains a `- command:` line where the value starts with `mcp:` (e.g., `- command: mcp:linear`), insert `- type: mcp` immediately after the `- command:` line.
64
- 2. Else, if the tool section contains a `- base_url:` line:
65
- - If the capabilities section contains entries that look like GraphQL queries (contain `query {` or `mutation {`), insert `- type: graphql` immediately after `## <tool_name>` (REST/GraphQL tools have no `- command:` line).
66
- - Otherwise, insert `- type: rest` immediately after `## <tool_name>`.
67
- 3. Else (no `mcp:` prefix, no `base_url` field), insert `- type: cli` immediately after the `- command:` line.
68
-
69
- Write the updated file back with the Write tool. If any changes were made, commit:
70
- ```bash
71
- git -C <storage_repo> add -A
72
- git -C <storage_repo> diff --cached --quiet || git -C <storage_repo> commit -m "donna(migrate): backfill tool types on existing tools"
15
+ x Donna is not configured. Run /donna:setup first.
73
16
  ```
17
+ Stop.
74
18
 
75
- If `auto_push` is true in config, also push.
19
+ Extract `storage_repo`, `daily_folder`, `auto_push` from the JSON.
76
20
 
77
- 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:
78
- ```markdown
79
- ---
80
- pending_migrations: []
81
- ---
21
+ If `update_available` is non-null, print:
22
+ ```
23
+ Donna v<update_available> available -- run npx @pingvinen/donna-assistant to update
82
24
  ```
25
+ Continue normally.
83
26
  </step>
84
27
 
85
28
  <step name="read-tools-md">
@@ -114,12 +57,16 @@ If `<type>` is `graphql`:
114
57
 
115
58
  **IMPORTANT: Auth is OPTIONAL for GraphQL tools. Public APIs work without any secret. You MUST always attempt introspection regardless of whether auth is configured. NEVER skip a GraphQL tool just because it has no auth_secret.**
116
59
 
117
- 1. Attempt to read `<storage_repo>/donna/secrets.md` with the Read tool. If the file exists and contains the `auth_secret` key with a value that is not a placeholder (does not contain "REPLACE_WITH"), set `<resolved_secret>` to that value. Otherwise, set `<resolved_secret>` to empty (no auth). **An empty resolved_secret is perfectly valid — proceed to step 2 regardless.**
60
+ 1. Resolve the auth secret via Bash:
61
+ ```bash
62
+ node ~/.donna/donna-tools.cjs resolve-secret <auth_secret>
63
+ ```
64
+ Parse the JSON response. If `error` is `"key_not_found"` or `"placeholder_value"`, set `<resolved_secret>` to empty (no auth). Otherwise extract the `value` field as `<resolved_secret>`. **An empty resolved_secret is perfectly valid — proceed to step 2 regardless.**
118
65
 
119
- 2. Run via Bash with a 15-second timeout. Include the auth header only when a real secret was resolved:
66
+ 2. Run via Bash with a 15-second timeout (set the Bash tool's `timeout` parameter to `15000`). Include the auth header only when a real secret was resolved:
120
67
  - If `<resolved_secret>` is non-empty:
121
68
  ```bash
122
- timeout 15 curl -s -X POST \
69
+ curl -s -X POST \
123
70
  -H "<auth_header>: <resolved_secret>" \
124
71
  -H "Content-Type: application/json" \
125
72
  -d '{"query":"{ __schema { types { name fields { name type { name } } } } }"}' \
@@ -127,7 +74,7 @@ If `<type>` is `graphql`:
127
74
  ```
128
75
  - If `<resolved_secret>` is empty (public API or no secret configured):
129
76
  ```bash
130
- timeout 15 curl -s -X POST \
77
+ curl -s -X POST \
131
78
  -H "Content-Type: application/json" \
132
79
  -d '{"query":"{ __schema { types { name fields { name type { name } } } } }"}' \
133
80
  "<base_url>" 2>&1
@@ -232,9 +179,48 @@ Determine if the tool is well-known (gh, jira, kubectl) or unknown. For well-kno
232
179
  - list-pods: `kubectl get pods --all-namespaces --field-selector=status.phase!=Succeeded -o wide`
233
180
  - list-failing: `kubectl get pods --all-namespaces --field-selector=status.phase=Failed -o wide`
234
181
 
235
- 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.
182
+ For **unknown tools**, use a cascading approach to re-learn capabilities. Each stage builds on the previous. The goal is to update CLI invocations for existing capability names — do NOT ask the user to re-select capabilities.
183
+
184
+ **Stage 1 — Local docs:**
185
+ Attempt to find local documentation for the tool:
186
+ ```bash
187
+ TOOL_PATH=$(which <command> 2>/dev/null)
188
+ ```
189
+ If found, check for README or docs in the tool's package directory:
190
+ ```bash
191
+ TOOL_DIR=$(dirname "$(dirname "$TOOL_PATH")")
192
+ ls "$TOOL_DIR"/README* "$TOOL_DIR"/doc* "$TOOL_DIR"/docs* 2>/dev/null | head -5
193
+ ```
194
+ If doc files exist, read the entry-point doc (prefer README, then docs/index or equivalent). Then follow internal links, references, or "see also" pointers to sections relevant to the existing capabilities. Use Claude's understanding to navigate — don't stop at a fixed line count.
195
+
196
+ **Stage 2 — CLI help (baseline):**
197
+ Run `<command> --help 2>&1 | head -80` via Bash. If the help output lists subcommands, also run `<command> <subcommand> --help` for subcommands relevant to existing capabilities. Combine with Stage 1 findings. Update invocations for existing capability names based on any changes to flags, subcommands, or output formats.
198
+
199
+ **Stage 3 — Web docs (if invocations could not be updated from stages 1-2):**
200
+ If any existing capability's invocation could not be validated from local docs or help output, attempt to fetch the tool's web documentation. Use WebFetch on common doc URLs:
201
+ - `https://<command>.dev` or `https://<command>.io`
202
+ - The homepage URL from `<command> --help` output if one was printed
203
+
204
+ If a docs page is found, follow links to CLI reference, commands, or API sections rather than reading only the landing page.
205
+
206
+ **Stage 4 — Source code analysis (user opt-in per D-09):**
207
+ After stages 1-3, if the tool path was found, ask the user:
208
+
209
+ Use AskUserQuestion:
210
+ ```
211
+ Updated <N> capability invocations from docs and help output. Want me to analyze <command>'s source code for additional capabilities?
212
+ ```
236
213
 
237
- 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.
214
+ If the user says yes:
215
+ - Read the main entry point (e.g., bin/<command>, cli.js, main.py)
216
+ - Follow imports/requires to command registration, subcommand definitions, or handler modules
217
+ - Navigate into the files that define actual commands and actions — don't stop at the entry point
218
+ - Identify new capabilities from function names, subcommands, or API surface
219
+ - Add any new relevant capabilities to the list
220
+
221
+ If no: continue with updated invocations.
222
+
223
+ Do NOT ask the user to re-select capabilities — keep the same capability names, update only the CLI invocations. The cascade's Stage 4 is the only place where NEW capabilities might be added (with user opt-in).
238
224
 
239
225
  Get the new installed version:
240
226
  ```bash
@@ -258,24 +244,7 @@ Write the full file back with the Write tool.
258
244
  <step name="git-commit">
259
245
  Run via Bash:
260
246
  ```bash
261
- git -C <storage_repo> add -A
262
- ```
263
-
264
- Check whether there is anything to commit:
265
- ```bash
266
- git -C <storage_repo> status --porcelain
267
- ```
268
-
269
- If the output is empty, skip the commit and continue.
270
-
271
- Otherwise, run:
272
- ```bash
273
- git -C <storage_repo> commit -m "donna(relearn-tools): updated <count> tool(s)"
274
- ```
275
-
276
- If `auto_push` is true in config, also run:
277
- ```bash
278
- git -C <storage_repo> push
247
+ node ~/.donna/donna-tools.cjs commit "donna(relearn-tools): updated <count> tool(s)" --files donna/tools.md
279
248
  ```
280
249
  </step>
281
250
 
@@ -0,0 +1,93 @@
1
+ # Donna Remove-Tool Workflow
2
+
3
+ <objective>
4
+ Remove a registered tool from tools.md cleanly — confirm with the user, delete the tool's section, and commit.
5
+ </objective>
6
+
7
+ <step name="init">
8
+ Run via Bash:
9
+ ```bash
10
+ INIT=$(node ~/.donna/donna-tools.cjs init)
11
+ ```
12
+
13
+ Parse the JSON response. If the `error` field is `"not_configured"`, print:
14
+ ```
15
+ x Donna is not configured. Run /donna:setup first.
16
+ ```
17
+ Stop.
18
+
19
+ Extract `storage_repo`, `daily_folder`, `auto_push` from the JSON.
20
+
21
+ If `update_available` is non-null, print:
22
+ ```
23
+ Donna v<update_available> available -- run npx @pingvinen/donna-assistant to update
24
+ ```
25
+ Continue normally.
26
+ </step>
27
+
28
+ <step name="read-tools-md">
29
+ Read `<storage_repo>/donna/tools.md` with the Read tool. If the file does not exist or has no tool sections, print:
30
+ ```
31
+ ! No tools registered. Nothing to remove.
32
+ ```
33
+ Stop.
34
+
35
+ Parse each tool section (starting with `## <tool_name>`). For each tool, extract `type`, `command`, `scope`, and the capabilities list.
36
+
37
+ Store as `<registered_tools>`.
38
+ </step>
39
+
40
+ <step name="select-tool">
41
+ If a tool name was provided as argument (e.g., `/donna:remove-tool gh`), look it up in `<registered_tools>`. If not found, print `! Tool "<name>" not found in tools.md` and stop.
42
+
43
+ If no argument was provided, list all registered tools via AskUserQuestion:
44
+ ```
45
+ Which tool would you like to remove?
46
+
47
+ <numbered list of tool names with their type>
48
+ ```
49
+ Store the selected tool as `<selected_tool>`.
50
+ </step>
51
+
52
+ <step name="confirm-removal">
53
+ Display the tool's current configuration summary:
54
+ ```
55
+ About to remove <tool_name>:
56
+
57
+ type: <type>
58
+ command: <command>
59
+ scope: <scope>
60
+ capabilities: <count> registered
61
+
62
+ This will delete the tool's entire section from tools.md.
63
+ ```
64
+
65
+ Use AskUserQuestion:
66
+ ```
67
+ Remove <tool_name>? (yes/no)
68
+ ```
69
+
70
+ If no, print `Cancelled.` and stop.
71
+ </step>
72
+
73
+ <step name="remove-from-tools-md">
74
+ Read `<storage_repo>/donna/tools.md`. Remove the entire `## <tool_name>` section (from the `## <tool_name>` heading up to but not including the next `## ` heading, or end of file). Preserve all other tool sections unchanged. Write the full file back with the Write tool.
75
+
76
+ If no tool sections remain after removal, write the file with just the frontmatter header (preserve any existing frontmatter).
77
+ </step>
78
+
79
+ <step name="git-commit">
80
+ Run via Bash:
81
+ ```bash
82
+ node ~/.donna/donna-tools.cjs commit "donna(remove-tool): removed <tool_name>" --files donna/tools.md
83
+ ```
84
+ </step>
85
+
86
+ <step name="confirm">
87
+ Print:
88
+ ```
89
+ ! Removed <tool_name> from tools.md
90
+
91
+ To re-add with a different configuration: /donna:add-tool <tool_name>
92
+ ```
93
+ </step>