@pingvinen/donna-assistant 0.3.2 → 0.4.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/bin/donna-assistant +3 -1
- package/package.json +1 -1
- package/src/installer.cjs +7 -2
- package/src/output.cjs +2 -2
- package/stubs/claude-code/donna/add-task.md +17 -0
- package/stubs/claude-code/donna/begin-the-day.md +16 -0
- package/stubs/claude-code/donna/done.md +17 -0
- package/stubs/claude-code/donna/set-role.md +18 -0
- package/stubs/claude-code/donna/setup.md +4 -2
- package/workflows/add-task.md +97 -0
- package/workflows/begin-the-day.md +198 -0
- package/workflows/done.md +126 -0
- package/workflows/set-role.md +247 -0
- package/workflows/setup.md +160 -18
package/bin/donna-assistant
CHANGED
package/package.json
CHANGED
package/src/installer.cjs
CHANGED
|
@@ -14,10 +14,12 @@ const providers = require("./providers/index.cjs");
|
|
|
14
14
|
*
|
|
15
15
|
* @param {object} [options]
|
|
16
16
|
* @param {string} [options.homeDir] - Override home directory (for testing)
|
|
17
|
+
* @param {boolean} [options.force] - Force re-install even if version matches
|
|
17
18
|
* @returns {Promise<void>}
|
|
18
19
|
*/
|
|
19
20
|
async function run(options = {}) {
|
|
20
21
|
const homeDir = options.homeDir || os.homedir();
|
|
22
|
+
const force = options.force || false;
|
|
21
23
|
const donnaDir = path.join(homeDir, ".donna");
|
|
22
24
|
const migrationsDir = path.join(__dirname, "..", "migrations");
|
|
23
25
|
const workflowsSource = path.join(__dirname, "..", "workflows");
|
|
@@ -36,7 +38,7 @@ async function run(options = {}) {
|
|
|
36
38
|
const lastMigration = current?.lastMigration || 0;
|
|
37
39
|
|
|
38
40
|
// Check if already up to date
|
|
39
|
-
if (currentVersion === packageVersion) {
|
|
41
|
+
if (currentVersion === packageVersion && !force) {
|
|
40
42
|
// Check for pending migrations too
|
|
41
43
|
const pendingResults = migrator.runMigrations(migrationsDir, donnaDir, lastMigration);
|
|
42
44
|
if (pendingResults.length === 0) {
|
|
@@ -74,7 +76,9 @@ async function run(options = {}) {
|
|
|
74
76
|
if (detected.length > 0) {
|
|
75
77
|
for (const provider of detected) {
|
|
76
78
|
fs.cpSync(provider.stubSource, provider.stubTarget, { recursive: true });
|
|
77
|
-
output.success(
|
|
79
|
+
output.success(
|
|
80
|
+
`Copied donna skills (setup, add-task, done, set-role, begin-the-day) to ${provider.stubTarget}`,
|
|
81
|
+
);
|
|
78
82
|
}
|
|
79
83
|
} else {
|
|
80
84
|
output.info("No supported AI providers detected");
|
|
@@ -92,6 +96,7 @@ async function run(options = {}) {
|
|
|
92
96
|
output.success(`Version ${packageVersion} installed`);
|
|
93
97
|
|
|
94
98
|
// Final message
|
|
99
|
+
console.log("");
|
|
95
100
|
output.info("Run /donna:setup in Claude Code to get started.");
|
|
96
101
|
}
|
|
97
102
|
|
package/src/output.cjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
function banner() {
|
|
4
4
|
console.log("");
|
|
5
|
-
console.log("━━━
|
|
5
|
+
console.log("━━━ Donna ━━━");
|
|
6
6
|
console.log("");
|
|
7
7
|
}
|
|
8
8
|
|
|
@@ -23,7 +23,7 @@ function upgradeHeader(from, to) {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
function migrationLine(desc) {
|
|
26
|
-
console.log(`
|
|
26
|
+
console.log(` \u2713 ${desc}`);
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
module.exports = { banner, success, fail, info, upgradeHeader, migrationLine };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: donna:add-task
|
|
3
|
+
description: Capture a task to today's daily journal
|
|
4
|
+
allowed-tools:
|
|
5
|
+
- Read
|
|
6
|
+
- Write
|
|
7
|
+
- Bash
|
|
8
|
+
- AskUserQuestion
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
<objective>
|
|
12
|
+
Run the Donna add-task workflow.
|
|
13
|
+
</objective>
|
|
14
|
+
|
|
15
|
+
<execution_context>
|
|
16
|
+
@~/.donna/workflows/add-task.md
|
|
17
|
+
</execution_context>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: donna:begin-the-day
|
|
3
|
+
description: Start your day — carry forward open tasks, surface recurring tasks due today, get your daily brief
|
|
4
|
+
allowed-tools:
|
|
5
|
+
- Read
|
|
6
|
+
- Write
|
|
7
|
+
- Bash
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
<objective>
|
|
11
|
+
Run the Donna begin-the-day workflow.
|
|
12
|
+
</objective>
|
|
13
|
+
|
|
14
|
+
<execution_context>
|
|
15
|
+
@~/.donna/workflows/begin-the-day.md
|
|
16
|
+
</execution_context>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: donna:done
|
|
3
|
+
description: Mark tasks as complete in today's daily journal
|
|
4
|
+
allowed-tools:
|
|
5
|
+
- Read
|
|
6
|
+
- Write
|
|
7
|
+
- Bash
|
|
8
|
+
- AskUserQuestion
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
<objective>
|
|
12
|
+
Run the Donna done workflow.
|
|
13
|
+
</objective>
|
|
14
|
+
|
|
15
|
+
<execution_context>
|
|
16
|
+
@~/.donna/workflows/done.md
|
|
17
|
+
</execution_context>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: donna:set-role
|
|
3
|
+
description: Define your job role, research recurring tasks, and build your daily rhythm
|
|
4
|
+
allowed-tools:
|
|
5
|
+
- Read
|
|
6
|
+
- Write
|
|
7
|
+
- Bash
|
|
8
|
+
- AskUserQuestion
|
|
9
|
+
- WebSearch
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
<objective>
|
|
13
|
+
Run the Donna set-role workflow. This command guides the user through defining their job role: collecting role details, researching recurring tasks and tools, presenting findings for approval, and persisting everything to the storage repo.
|
|
14
|
+
</objective>
|
|
15
|
+
|
|
16
|
+
<execution_context>
|
|
17
|
+
@~/.donna/workflows/set-role.md
|
|
18
|
+
</execution_context>
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: donna:setup
|
|
3
|
-
description: Set up Donna
|
|
3
|
+
description: Set up Donna — configure storage repo, initialize file structure, create bootstrap config
|
|
4
4
|
allowed-tools:
|
|
5
5
|
- Read
|
|
6
|
+
- Write
|
|
6
7
|
- Bash
|
|
8
|
+
- AskUserQuestion
|
|
7
9
|
---
|
|
8
10
|
|
|
9
11
|
<objective>
|
|
10
|
-
Run the Donna setup workflow. This command
|
|
12
|
+
Run the Donna setup workflow. This command guides the user through configuring Donna: setting the storage repo path, initializing the file structure, and writing the bootstrap config at ~/.config/donna/config.md.
|
|
11
13
|
</objective>
|
|
12
14
|
|
|
13
15
|
<execution_context>
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Donna Add-Task Workflow
|
|
2
|
+
|
|
3
|
+
<objective>
|
|
4
|
+
Capture a new task to today's daily journal file in the storage repo and commit it to git.
|
|
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="get-description">
|
|
25
|
+
The task description is provided as the argument to this command (e.g., `/donna:add-task buy milk`).
|
|
26
|
+
|
|
27
|
+
If no argument was provided, use AskUserQuestion to ask:
|
|
28
|
+
```
|
|
29
|
+
What task would you like to add?
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Store the response as `<description>`.
|
|
33
|
+
</step>
|
|
34
|
+
|
|
35
|
+
<step name="ensure-daily-file">
|
|
36
|
+
Run via Bash to get today's date:
|
|
37
|
+
```bash
|
|
38
|
+
date +%Y-%m-%d
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Store the result as `<date>`. Construct the daily file path: `<storage_repo>/<daily_folder>/<date>.md`.
|
|
42
|
+
|
|
43
|
+
Run via Bash to ensure the daily folder exists:
|
|
44
|
+
```bash
|
|
45
|
+
mkdir -p <storage_repo>/<daily_folder>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
If the daily file does not exist, create it with the Write tool using this content (substituting the actual date):
|
|
49
|
+
```markdown
|
|
50
|
+
---
|
|
51
|
+
date: <date>
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Tasks
|
|
55
|
+
```
|
|
56
|
+
</step>
|
|
57
|
+
|
|
58
|
+
<step name="append-task">
|
|
59
|
+
Read the daily file with the Read tool.
|
|
60
|
+
|
|
61
|
+
Append `- [ ] <description>` on a new line at the end of the file.
|
|
62
|
+
|
|
63
|
+
Write the updated file with the Write tool.
|
|
64
|
+
</step>
|
|
65
|
+
|
|
66
|
+
<step name="git-commit">
|
|
67
|
+
Run via Bash:
|
|
68
|
+
```bash
|
|
69
|
+
git -C <storage_repo> add -A
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Check whether there is anything to commit:
|
|
73
|
+
```bash
|
|
74
|
+
git -C <storage_repo> status --porcelain
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
If the output is empty, skip the commit and continue.
|
|
78
|
+
|
|
79
|
+
Otherwise, run:
|
|
80
|
+
```bash
|
|
81
|
+
git -C <storage_repo> commit -m "donna(add-task): <description>"
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
If `auto_push` is true in config, also run:
|
|
85
|
+
```bash
|
|
86
|
+
git -C <storage_repo> push
|
|
87
|
+
```
|
|
88
|
+
</step>
|
|
89
|
+
|
|
90
|
+
<step name="confirm">
|
|
91
|
+
Print:
|
|
92
|
+
```
|
|
93
|
+
✓ Added: <description>
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Also print the path to the daily file: `<storage_repo>/<daily_folder>/<date>.md`
|
|
97
|
+
</step>
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# Donna Begin-the-Day Workflow
|
|
2
|
+
|
|
3
|
+
<objective>
|
|
4
|
+
Carry forward open tasks from the previous day, surface recurring tasks due today, deduplicate, and present a concise daily brief.
|
|
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="get-today">
|
|
25
|
+
Run via Bash to get today's date, day-of-week, and day-of-month:
|
|
26
|
+
```bash
|
|
27
|
+
date +%Y-%m-%d
|
|
28
|
+
```
|
|
29
|
+
Store the result as `<today>`.
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
date +%A
|
|
33
|
+
```
|
|
34
|
+
Store the result as `<day_of_week>` (e.g., "Monday").
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
date +%-d
|
|
38
|
+
```
|
|
39
|
+
Store the result as `<day_of_month>` (e.g., "1" for the 1st).
|
|
40
|
+
|
|
41
|
+
Construct the daily file path: `<storage_repo>/<daily_folder>/<today>.md`.
|
|
42
|
+
</step>
|
|
43
|
+
|
|
44
|
+
<step name="find-previous-file">
|
|
45
|
+
Find the most recent previous daily file. Run via Bash:
|
|
46
|
+
```bash
|
|
47
|
+
TODAY=$(date +%Y-%m-%d)
|
|
48
|
+
DAILY_DIR="<storage_repo>/<daily_folder>"
|
|
49
|
+
PREV_FILE=$(ls "$DAILY_DIR"/*.md 2>/dev/null | sort | grep -v "$TODAY" | tail -1)
|
|
50
|
+
echo "${PREV_FILE:-NONE}"
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
CRITICAL: The `grep -v "$TODAY"` exclusion prevents a self-referencing loop. If the result is "NONE", there is no previous file — skip the carry-forward step. This reads a directory listing only (satisfies STORE-03), then reads at most ONE previous file.
|
|
54
|
+
</step>
|
|
55
|
+
|
|
56
|
+
<step name="carry-forward">
|
|
57
|
+
If the previous file result is "NONE", set `<carried_tasks>` to an empty list and continue to the next step.
|
|
58
|
+
|
|
59
|
+
If a previous file was found, read it with the Read tool. Extract all open tasks — every line matching the pattern `- [ ] <description>`. For each open task:
|
|
60
|
+
- If the description ends with ` (N times)` (where N is any integer): extract N, increment to N+1, replace the suffix with ` (N+1 times)`. For example: `- [ ] Follow up with Sarah (2 times)` becomes `- [ ] Follow up with Sarah (3 times)`.
|
|
61
|
+
- If the description has no such suffix: append ` (1 times)`. For example: `- [ ] Follow up with Sarah` becomes `- [ ] Follow up with Sarah (1 times)`.
|
|
62
|
+
|
|
63
|
+
Store the resulting list as `<carried_tasks>`.
|
|
64
|
+
|
|
65
|
+
Do NOT modify the previous file — it is a historical record and must remain unchanged.
|
|
66
|
+
</step>
|
|
67
|
+
|
|
68
|
+
<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).
|
|
70
|
+
|
|
71
|
+
Parse each line matching the pattern `- <description>: <interval>`. For "every other" intervals, also parse the `| last_run: YYYY-MM-DD` suffix.
|
|
72
|
+
|
|
73
|
+
For each task, determine if it is due today using this logic:
|
|
74
|
+
- `every <DayName>` (e.g., "every Monday"): due if `<day_of_week>` matches DayName
|
|
75
|
+
- `every weekday`: due if `<day_of_week>` is Monday, Tuesday, Wednesday, Thursday, or Friday
|
|
76
|
+
- `first <DayName> of month`: due if `<day_of_week>` matches DayName AND `<day_of_month>` <= 7
|
|
77
|
+
- `every other <DayName>` with `| last_run: YYYY-MM-DD`: due if `<day_of_week>` matches DayName AND days since last_run >= 14. Use macOS-compatible date arithmetic:
|
|
78
|
+
```bash
|
|
79
|
+
LAST_RUN="<last_run_date>"
|
|
80
|
+
last_run_epoch=$(date -j -f "%Y-%m-%d" "$LAST_RUN" "+%s")
|
|
81
|
+
today_epoch=$(date +%s)
|
|
82
|
+
days=$(( (today_epoch - last_run_epoch) / 86400 ))
|
|
83
|
+
echo "$days"
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Store the descriptions of all due tasks as `<recurring_tasks>` (just the description text, without the interval suffix).
|
|
87
|
+
</step>
|
|
88
|
+
|
|
89
|
+
<step name="read-existing-today">
|
|
90
|
+
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
|
+
|
|
92
|
+
If the file does not exist, `<existing_tasks>` is an empty list.
|
|
93
|
+
</step>
|
|
94
|
+
|
|
95
|
+
<step name="deduplicate">
|
|
96
|
+
Assemble the full task list using a single-pass deduplication to ensure idempotency:
|
|
97
|
+
|
|
98
|
+
**Normalization for comparison:** strip `- [ ] ` or `- [x] ` prefix, strip any trailing ` (N times)` suffix (where N is any integer), lowercase all text, trim whitespace.
|
|
99
|
+
|
|
100
|
+
1. Start with `<existing_tasks>` — both open and closed tasks take priority. Add them all to the final list.
|
|
101
|
+
|
|
102
|
+
2. Add `<carried_tasks>` — for each carried task, normalize its description and check whether any task already in the final list (from existing_tasks) normalizes to the same value. If no match, add it. If a match exists, skip it.
|
|
103
|
+
|
|
104
|
+
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
|
+
|
|
106
|
+
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
|
+
|
|
108
|
+
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
|
+
|
|
110
|
+
Store the result as `<final_tasks>`.
|
|
111
|
+
</step>
|
|
112
|
+
|
|
113
|
+
<step name="write-daily-file">
|
|
114
|
+
Ensure the daily folder exists:
|
|
115
|
+
```bash
|
|
116
|
+
mkdir -p <storage_repo>/<daily_folder>
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Write today's daily file with the Write tool. Content format:
|
|
120
|
+
```markdown
|
|
121
|
+
---
|
|
122
|
+
date: <today>
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Tasks
|
|
126
|
+
<existing tasks, preserving their original order and open/closed state>
|
|
127
|
+
<carried-forward tasks not already in existing>
|
|
128
|
+
<recurring tasks not already in existing>
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Tasks are written in this order: existing tasks first (preserving their original order and state), then carried-forward tasks, then recurring tasks.
|
|
132
|
+
</step>
|
|
133
|
+
|
|
134
|
+
<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`.
|
|
136
|
+
|
|
137
|
+
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
|
+
|
|
139
|
+
If no "every other" recurring tasks were added, skip this step.
|
|
140
|
+
</step>
|
|
141
|
+
|
|
142
|
+
<step name="git-commit">
|
|
143
|
+
Run via Bash:
|
|
144
|
+
```bash
|
|
145
|
+
git -C <storage_repo> add -A
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Check whether there is anything to commit:
|
|
149
|
+
```bash
|
|
150
|
+
git -C <storage_repo> status --porcelain
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
If the output is empty, skip the commit and continue.
|
|
154
|
+
|
|
155
|
+
Otherwise, run:
|
|
156
|
+
```bash
|
|
157
|
+
git -C <storage_repo> commit -m "donna(begin-the-day): daily brief for <today>"
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
If `auto_push` is true in config, also run:
|
|
161
|
+
```bash
|
|
162
|
+
git -C <storage_repo> push
|
|
163
|
+
```
|
|
164
|
+
</step>
|
|
165
|
+
|
|
166
|
+
<step name="print-brief">
|
|
167
|
+
Print the daily brief to the terminal:
|
|
168
|
+
```
|
|
169
|
+
══════════════════════════════════════
|
|
170
|
+
DONNA — Daily Brief for <today>
|
|
171
|
+
══════════════════════════════════════
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
If there are carried-forward tasks (tasks from `<carried_tasks>` that were added to the final list), print:
|
|
175
|
+
```
|
|
176
|
+
## Carried Forward
|
|
177
|
+
- [ ] Follow up with Sarah (3 times)
|
|
178
|
+
- [ ] Review design doc (1 times)
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
If there are recurring tasks due today (tasks from `<recurring_tasks>` that were added to the final list), print:
|
|
182
|
+
```
|
|
183
|
+
## Due Today
|
|
184
|
+
- [ ] Check team Slack
|
|
185
|
+
- [ ] Review sprint backlog
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Always end with:
|
|
189
|
+
```
|
|
190
|
+
══════════════════════════════════════
|
|
191
|
+
```
|
|
192
|
+
|
|
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:
|
|
194
|
+
```
|
|
195
|
+
No tasks for today — enjoy your day!
|
|
196
|
+
```
|
|
197
|
+
in place of both sections.
|
|
198
|
+
</step>
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# Donna Done Workflow
|
|
2
|
+
|
|
3
|
+
<objective>
|
|
4
|
+
Mark one or more tasks as complete in today's daily journal file and commit the change to git.
|
|
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="find-daily-file">
|
|
25
|
+
Run via Bash to get today's date:
|
|
26
|
+
```bash
|
|
27
|
+
date +%Y-%m-%d
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Store the result as `<date>`. Construct the daily file path: `<storage_repo>/<daily_folder>/<date>.md`.
|
|
31
|
+
|
|
32
|
+
If the file does not exist, print:
|
|
33
|
+
```
|
|
34
|
+
✗ No daily file for today. Add a task first with /donna:add-task
|
|
35
|
+
```
|
|
36
|
+
Stop.
|
|
37
|
+
</step>
|
|
38
|
+
|
|
39
|
+
<step name="read-tasks">
|
|
40
|
+
Read the daily file with the Read tool.
|
|
41
|
+
|
|
42
|
+
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
|
+
|
|
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.
|
|
45
|
+
|
|
46
|
+
If no open tasks are found, print:
|
|
47
|
+
```
|
|
48
|
+
✓ All tasks already complete for today!
|
|
49
|
+
```
|
|
50
|
+
Stop.
|
|
51
|
+
</step>
|
|
52
|
+
|
|
53
|
+
<step name="select-tasks">
|
|
54
|
+
Two modes based on whether an argument was provided to this command:
|
|
55
|
+
|
|
56
|
+
**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.
|
|
58
|
+
|
|
59
|
+
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
|
+
```
|
|
61
|
+
Mark as done: '<task>'? (yes/no)
|
|
62
|
+
```
|
|
63
|
+
If no match is found, tell the user and list all open tasks.
|
|
64
|
+
|
|
65
|
+
**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.
|
|
67
|
+
|
|
68
|
+
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
|
+
```
|
|
70
|
+
Which task(s) did you finish? (or type something you did that's not on the list)
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
If the user submits without selecting anything or typing anything, print:
|
|
74
|
+
```
|
|
75
|
+
Nothing selected — nothing to do.
|
|
76
|
+
```
|
|
77
|
+
Stop.
|
|
78
|
+
|
|
79
|
+
If the user selects from the list, store the selected task(s) as `<completed_tasks>`.
|
|
80
|
+
|
|
81
|
+
If the user types free text instead of selecting an option, treat it as a task that was already done: append `- [x] <typed text>` to the daily file (creating it if needed, same as add-task's ensure-daily-file step). Store it as `<completed_tasks>` so the git-commit and confirm steps handle it normally.
|
|
82
|
+
</step>
|
|
83
|
+
|
|
84
|
+
<step name="mark-complete">
|
|
85
|
+
For each task in `<completed_tasks>`, replace `- [ ] <description>` with `- [x] <description>` in the daily file.
|
|
86
|
+
|
|
87
|
+
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
|
+
|
|
89
|
+
Write the updated file with the Write tool.
|
|
90
|
+
</step>
|
|
91
|
+
|
|
92
|
+
<step name="git-commit">
|
|
93
|
+
Run via Bash:
|
|
94
|
+
```bash
|
|
95
|
+
git -C <storage_repo> add -A
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Check whether there is anything to commit:
|
|
99
|
+
```bash
|
|
100
|
+
git -C <storage_repo> status --porcelain
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
If the output is empty, skip the commit and continue.
|
|
104
|
+
|
|
105
|
+
If one task was completed, run:
|
|
106
|
+
```bash
|
|
107
|
+
git -C <storage_repo> commit -m "donna(done): <description>"
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
If multiple tasks were completed, run:
|
|
111
|
+
```bash
|
|
112
|
+
git -C <storage_repo> commit -m "donna(done): <N> tasks completed"
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
If `auto_push` is true in config, also run:
|
|
116
|
+
```bash
|
|
117
|
+
git -C <storage_repo> push
|
|
118
|
+
```
|
|
119
|
+
</step>
|
|
120
|
+
|
|
121
|
+
<step name="confirm">
|
|
122
|
+
For each completed task, print:
|
|
123
|
+
```
|
|
124
|
+
✓ Done: <description>
|
|
125
|
+
```
|
|
126
|
+
</step>
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
# Donna Set-Role Workflow
|
|
2
|
+
|
|
3
|
+
<objective>
|
|
4
|
+
Define the user's job role, research recurring tasks and tools for that role using WebSearch, present findings for approval, and persist role definition and recurring tasks to 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` and `auto_push` (default: false) fields from the YAML frontmatter.
|
|
17
|
+
</step>
|
|
18
|
+
|
|
19
|
+
<step name="check-existing-role">
|
|
20
|
+
Run via Bash:
|
|
21
|
+
```bash
|
|
22
|
+
test -f <storage_repo>/role.md && echo "exists" || echo "missing"
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
If the output is "exists", proceed to the rerun-menu step.
|
|
26
|
+
If the output is "missing", proceed to the ask-role step.
|
|
27
|
+
</step>
|
|
28
|
+
|
|
29
|
+
<step name="rerun-menu">
|
|
30
|
+
Use AskUserQuestion to present the re-run menu:
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
A role definition already exists. What would you like to do?
|
|
34
|
+
|
|
35
|
+
1. Something got messed up — start fresh (reset)
|
|
36
|
+
2. Got promoted or changed roles — update (diff-update)
|
|
37
|
+
3. Just want to refresh the research — re-research current role
|
|
38
|
+
4. Cancel
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
- 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.
|
|
44
|
+
- On "Cancel" (option 4): print "Cancelled." and stop.
|
|
45
|
+
</step>
|
|
46
|
+
|
|
47
|
+
<step name="ask-role">
|
|
48
|
+
Stage 1: Collect role details interactively.
|
|
49
|
+
|
|
50
|
+
Use AskUserQuestion to ask the following questions in sequence:
|
|
51
|
+
|
|
52
|
+
1. "What is your job title?" — store as `<job_title>`.
|
|
53
|
+
2. "How large is your team? How many direct reports do you have? (e.g. team of 8, 3 direct reports)" — store as `<team_info>`.
|
|
54
|
+
3. "What are 2–3 things you focus on most in your role? (e.g. sprint planning, hiring, technical architecture)" — store as `<key_responsibilities>`.
|
|
55
|
+
|
|
56
|
+
Parse `<team_info>` into `<team_size>` (total team) and `<direct_reports>` (direct reports count) as best you can.
|
|
57
|
+
Parse `<key_responsibilities>` into an array of 2–3 items.
|
|
58
|
+
|
|
59
|
+
Store all values for use in subsequent steps.
|
|
60
|
+
</step>
|
|
61
|
+
|
|
62
|
+
<step name="research">
|
|
63
|
+
Stage 2: Research the role using WebSearch.
|
|
64
|
+
|
|
65
|
+
Construct targeted queries using ALL collected data from Stage 1. Run 2–3 focused searches:
|
|
66
|
+
|
|
67
|
+
1. `<job_title> daily recurring tasks responsibilities`
|
|
68
|
+
2. `<job_title> <key_responsibilities[0]> common tools workflows`
|
|
69
|
+
3. (optional) `<job_title> weekly monthly recurring tasks best practices`
|
|
70
|
+
|
|
71
|
+
Use WebSearch for each query. Synthesize findings into a structured summary matching the role-research.md format:
|
|
72
|
+
|
|
73
|
+
- **Daily tasks**: recurring things done every workday
|
|
74
|
+
- **Weekly tasks**: recurring things done each week
|
|
75
|
+
- **Monthly tasks**: recurring things done each month
|
|
76
|
+
- **Tool suggestions**: tools commonly used for this role (with brief descriptions)
|
|
77
|
+
|
|
78
|
+
Tailor suggestions to the specific responsibilities the user described — avoid generic results that don't reflect their actual focus areas.
|
|
79
|
+
</step>
|
|
80
|
+
|
|
81
|
+
<step name="present-summary">
|
|
82
|
+
Print a concise summary of research findings (2–3 sentences covering the key patterns found).
|
|
83
|
+
|
|
84
|
+
Then use AskUserQuestion:
|
|
85
|
+
```
|
|
86
|
+
Which category would you like to review?
|
|
87
|
+
1. Recurring tasks
|
|
88
|
+
2. Tool suggestions
|
|
89
|
+
3. Both
|
|
90
|
+
4. Skip (accept all recurring tasks as-is)
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Store the choice for subsequent steps.
|
|
94
|
+
</step>
|
|
95
|
+
|
|
96
|
+
<step name="approve-recurring">
|
|
97
|
+
If the user chose to review recurring tasks (options 1 or 3):
|
|
98
|
+
|
|
99
|
+
Display each category in turn (daily, weekly, monthly) and use AskUserQuestion for each task:
|
|
100
|
+
```
|
|
101
|
+
[Daily] Check team Slack and unblock blockers
|
|
102
|
+
→ Approve, reject, or modify? (approve / reject / [type modification)
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Interpret modifications naturally:
|
|
106
|
+
- "make this biweekly" → change interval to "every other week"
|
|
107
|
+
- "every other Monday" → interval becomes "every other Monday"
|
|
108
|
+
- "first Monday of the month" → interval becomes "first Monday of month"
|
|
109
|
+
|
|
110
|
+
After reviewing all categories, ask: "Would you like to add any recurring tasks I missed?" Accept free-text additions.
|
|
111
|
+
|
|
112
|
+
Collect the final approved list with their intervals.
|
|
113
|
+
|
|
114
|
+
If the user chose to skip (option 4): accept all suggested recurring tasks with their default intervals.
|
|
115
|
+
</step>
|
|
116
|
+
|
|
117
|
+
<step name="approve-tools">
|
|
118
|
+
If the user chose to review tool suggestions (options 2 or 3):
|
|
119
|
+
|
|
120
|
+
Display each tool suggestion and use AskUserQuestion:
|
|
121
|
+
```
|
|
122
|
+
Tool: Jira (sprint management)
|
|
123
|
+
→ Note this for future configuration? (yes / no)
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
For noted tools, print:
|
|
127
|
+
```
|
|
128
|
+
✓ Noted: <tool name>. Run /donna:add-tool to configure <tool name> (available in a future update).
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Do NOT create tools.md or configure anything — only note the user's interest.
|
|
132
|
+
</step>
|
|
133
|
+
|
|
134
|
+
<step name="save-role">
|
|
135
|
+
Write `<storage_repo>/role.md` with the Write tool.
|
|
136
|
+
|
|
137
|
+
Use this format (substituting actual values):
|
|
138
|
+
```markdown
|
|
139
|
+
---
|
|
140
|
+
job_title: <job_title>
|
|
141
|
+
team_size: <team_size>
|
|
142
|
+
direct_reports: <direct_reports>
|
|
143
|
+
key_responsibilities:
|
|
144
|
+
- <responsibility 1>
|
|
145
|
+
- <responsibility 2>
|
|
146
|
+
updated: <today's date in YYYY-MM-DD format>
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
# Role: <job_title>
|
|
150
|
+
|
|
151
|
+
[Write a 2–3 sentence prose summary of the role as described by the user, incorporating their key responsibilities and team context.]
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Write `<storage_repo>/role-research.md` with the Write tool.
|
|
155
|
+
|
|
156
|
+
Use this format:
|
|
157
|
+
```markdown
|
|
158
|
+
---
|
|
159
|
+
researched: <today's date in YYYY-MM-DD format>
|
|
160
|
+
role: <job_title>
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
# Role Research: <job_title>
|
|
164
|
+
|
|
165
|
+
## Summary
|
|
166
|
+
[2–3 sentence overview of what the research found for this role]
|
|
167
|
+
|
|
168
|
+
## Recurring Task Suggestions
|
|
169
|
+
|
|
170
|
+
### Daily
|
|
171
|
+
[List daily task suggestions from research]
|
|
172
|
+
|
|
173
|
+
### Weekly
|
|
174
|
+
[List weekly task suggestions from research]
|
|
175
|
+
|
|
176
|
+
### Monthly
|
|
177
|
+
[List monthly task suggestions from research]
|
|
178
|
+
|
|
179
|
+
## Tool Suggestions
|
|
180
|
+
[List tool suggestions with brief descriptions]
|
|
181
|
+
|
|
182
|
+
## Notes
|
|
183
|
+
[Any additional context from research relevant to this specific role]
|
|
184
|
+
```
|
|
185
|
+
</step>
|
|
186
|
+
|
|
187
|
+
<step name="save-recurring">
|
|
188
|
+
Write `<storage_repo>/recurring.md` with the Write tool.
|
|
189
|
+
|
|
190
|
+
Format: one approved recurring task per line as `- Task description: interval`.
|
|
191
|
+
For "every other" intervals (biweekly, every other Monday, etc.), append ` | last_run: <today's date>` suffix.
|
|
192
|
+
|
|
193
|
+
Use this format:
|
|
194
|
+
```markdown
|
|
195
|
+
---
|
|
196
|
+
# Recurring tasks — managed by donna:set-role
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
- <task 1>: <interval 1>
|
|
200
|
+
- <task 2>: <interval 2>
|
|
201
|
+
- <task 3>: <interval 3> | last_run: <today's date>
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
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.
|
|
206
|
+
2. Identify manually-added tasks: tasks in recurring.md that were NOT in the research suggestions.
|
|
207
|
+
3. Merge: keep manually-added tasks, add new approved tasks, remove tasks the user rejected.
|
|
208
|
+
4. Write the merged result.
|
|
209
|
+
</step>
|
|
210
|
+
|
|
211
|
+
<step name="git-commit">
|
|
212
|
+
Run via Bash:
|
|
213
|
+
```bash
|
|
214
|
+
git -C <storage_repo> add -A
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Check whether there is anything to commit:
|
|
218
|
+
```bash
|
|
219
|
+
git -C <storage_repo> status --porcelain
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
If the output is empty, skip the commit and continue.
|
|
223
|
+
|
|
224
|
+
Otherwise, run:
|
|
225
|
+
```bash
|
|
226
|
+
git -C <storage_repo> commit -m "donna(set-role): define role as <job_title>"
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
If `auto_push` is true in config, also run:
|
|
230
|
+
```bash
|
|
231
|
+
git -C <storage_repo> push
|
|
232
|
+
```
|
|
233
|
+
</step>
|
|
234
|
+
|
|
235
|
+
<step name="confirm">
|
|
236
|
+
Print:
|
|
237
|
+
```
|
|
238
|
+
✓ Role defined: <job_title>
|
|
239
|
+
✓ <N> recurring tasks saved to recurring.md
|
|
240
|
+
✓ Research saved to role-research.md
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
If any tools were noted during approve-tools, remind:
|
|
244
|
+
```
|
|
245
|
+
→ Run /donna:add-tool to configure your noted tools (available in a future update).
|
|
246
|
+
```
|
|
247
|
+
</step>
|
package/workflows/setup.md
CHANGED
|
@@ -1,42 +1,184 @@
|
|
|
1
1
|
# Donna Setup Workflow
|
|
2
2
|
|
|
3
3
|
<objective>
|
|
4
|
-
|
|
4
|
+
Guide the user through configuring Donna: set the storage repo path, initialize the file structure, and write the bootstrap config at ~/.config/donna/config.md.
|
|
5
5
|
</objective>
|
|
6
6
|
|
|
7
7
|
<step name="banner">
|
|
8
|
-
Print the
|
|
8
|
+
Print the Donna banner:
|
|
9
9
|
```
|
|
10
|
-
━━━
|
|
10
|
+
━━━ Donna ▸ Setup ━━━
|
|
11
11
|
```
|
|
12
12
|
</step>
|
|
13
13
|
|
|
14
|
-
<step name="
|
|
15
|
-
Read `~/.donna/
|
|
14
|
+
<step name="check-existing-config">
|
|
15
|
+
Read `~/.config/donna/config.md`.
|
|
16
|
+
|
|
17
|
+
If the file exists, proceed to the re-run menu (step: rerun-menu).
|
|
18
|
+
If the file does not exist, proceed to first-run setup (step: ask-storage-path).
|
|
19
|
+
</step>
|
|
20
|
+
|
|
21
|
+
<step name="rerun-menu">
|
|
22
|
+
An existing Donna configuration was found. Use AskUserQuestion to present the user with this menu:
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
Donna is already configured. What would you like to do?
|
|
26
|
+
|
|
27
|
+
1. Change storage repo path
|
|
28
|
+
2. View current config
|
|
29
|
+
3. Reset (start over — deletes config and re-runs full setup)
|
|
30
|
+
4. Cancel
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Handle each option:
|
|
34
|
+
|
|
35
|
+
- **Option 1:** Ask the user for the new storage repo path using AskUserQuestion. Validate and expand the path (run `echo <path>` via Bash to expand ~). Update `~/.config/donna/config.md` with the new storage_repo value. Print `✓ Storage repo updated.` then print the summary (step: summary).
|
|
36
|
+
|
|
37
|
+
- **Option 2:** Display the contents of `~/.config/donna/config.md`. Then stop.
|
|
38
|
+
|
|
39
|
+
- **Option 3:** Run `rm ~/.config/donna/config.md` via Bash to delete the config. Proceed to first-run setup (step: ask-storage-path).
|
|
40
|
+
|
|
41
|
+
- **Option 4:** Print `Setup cancelled.` and stop.
|
|
42
|
+
</step>
|
|
43
|
+
|
|
44
|
+
<step name="ask-storage-path">
|
|
45
|
+
Use AskUserQuestion to ask the user:
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
Where is your Donna storage repo?
|
|
49
|
+
|
|
50
|
+
This is a local git repository where Donna stores your daily journal, tasks, and configuration. You can point to an existing git repo, an empty directory (Donna will initialize it), or a path that doesn't exist yet (Donna will create it).
|
|
51
|
+
|
|
52
|
+
Enter the path (e.g. ~/Documents/donna-notes):
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Wait for the user's response. Store the path as `<storage_path>`.
|
|
56
|
+
</step>
|
|
57
|
+
|
|
58
|
+
<step name="expand-and-validate-path">
|
|
59
|
+
Expand the path provided by the user:
|
|
60
|
+
|
|
61
|
+
Run via Bash:
|
|
62
|
+
```bash
|
|
63
|
+
echo <storage_path>
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Use the expanded absolute path for all subsequent steps. Store as `<repo>`.
|
|
67
|
+
|
|
68
|
+
Then check the path status:
|
|
69
|
+
|
|
70
|
+
- If `<repo>` is an existing git repo (test: `git -C <repo> rev-parse --is-inside-work-tree 2>/dev/null`): use it as-is. Print `✓ Using existing git repo at <repo>`.
|
|
71
|
+
|
|
72
|
+
- If `<repo>` exists as a directory but is not a git repo: run `git -C <repo> init`. Print `✓ Initialized git repo at <repo>`.
|
|
73
|
+
|
|
74
|
+
- If `<repo>` does not exist: run `mkdir -p <repo>` then `git -C <repo> init`. Print `✓ Created and initialized git repo at <repo>`.
|
|
75
|
+
</step>
|
|
76
|
+
|
|
77
|
+
<step name="detect-daily-folder">
|
|
78
|
+
Determine where daily files should live.
|
|
79
|
+
|
|
80
|
+
**If `<repo>/.obsidian/daily-notes.json` exists:**
|
|
81
|
+
Read it. If it has a `folder` field, use that value as `<daily_folder>`. Print:
|
|
82
|
+
```
|
|
83
|
+
✓ Found Obsidian daily notes folder: <daily_folder>
|
|
16
84
|
```
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
85
|
+
|
|
86
|
+
**If `<repo>/.obsidian/` exists but `.obsidian/daily-notes.json` does not exist or has no `folder` field:**
|
|
87
|
+
Set `<daily_folder>` to `daily`. Write `<repo>/.obsidian/daily-notes.json` with:
|
|
88
|
+
```json
|
|
89
|
+
{
|
|
90
|
+
"folder": "daily"
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
Print:
|
|
20
94
|
```
|
|
21
|
-
|
|
95
|
+
✓ Configured Obsidian daily notes to use daily/
|
|
22
96
|
```
|
|
23
|
-
|
|
24
|
-
|
|
97
|
+
|
|
98
|
+
**If `<repo>/.obsidian/` does not exist:**
|
|
99
|
+
Set `<daily_folder>` to `daily`. Print:
|
|
100
|
+
```
|
|
101
|
+
✓ Using daily/ for daily files
|
|
25
102
|
```
|
|
26
103
|
</step>
|
|
27
104
|
|
|
28
|
-
<step name="
|
|
29
|
-
|
|
105
|
+
<step name="create-storage-structure">
|
|
106
|
+
Create the daily directory:
|
|
107
|
+
|
|
108
|
+
Run via Bash:
|
|
109
|
+
```bash
|
|
110
|
+
mkdir -p <repo>/<daily_folder>
|
|
30
111
|
```
|
|
31
|
-
|
|
112
|
+
|
|
113
|
+
Print:
|
|
114
|
+
```
|
|
115
|
+
✓ Created <daily_folder>/ directory
|
|
32
116
|
```
|
|
33
117
|
</step>
|
|
34
118
|
|
|
35
|
-
<step name="
|
|
36
|
-
|
|
119
|
+
<step name="write-bootstrap-config">
|
|
120
|
+
Create the config directory if it does not exist:
|
|
121
|
+
|
|
122
|
+
Run via Bash:
|
|
123
|
+
```bash
|
|
124
|
+
mkdir -p ~/.config/donna
|
|
37
125
|
```
|
|
126
|
+
|
|
127
|
+
Write `~/.config/donna/config.md` with the following content (substituting the actual expanded path for `<repo>`):
|
|
128
|
+
|
|
129
|
+
```markdown
|
|
130
|
+
---
|
|
131
|
+
storage_repo: <repo>
|
|
132
|
+
daily_folder: <daily_folder>
|
|
133
|
+
auto_push: false
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
# Donna Configuration
|
|
137
|
+
|
|
138
|
+
This file is managed by `/donna:setup`. All Donna skills read this file to find your storage repo.
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Print:
|
|
142
|
+
```
|
|
143
|
+
✓ Wrote config at ~/.config/donna/config.md
|
|
144
|
+
```
|
|
145
|
+
</step>
|
|
146
|
+
|
|
147
|
+
<step name="initial-commit">
|
|
148
|
+
Check whether there is anything to commit:
|
|
149
|
+
|
|
150
|
+
Run via Bash:
|
|
151
|
+
```bash
|
|
152
|
+
git -C <repo> status --porcelain
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
If the output is non-empty (there are changes to commit):
|
|
156
|
+
|
|
157
|
+
Run:
|
|
158
|
+
```bash
|
|
159
|
+
git -C <repo> add -A
|
|
160
|
+
git -C <repo> commit -m "donna(setup): initialize storage"
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Print:
|
|
164
|
+
```
|
|
165
|
+
✓ Committed initial structure
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
If the output is empty (nothing to commit), skip the commit and continue.
|
|
169
|
+
</step>
|
|
170
|
+
|
|
171
|
+
<step name="summary">
|
|
172
|
+
Print the completion summary:
|
|
173
|
+
|
|
174
|
+
```
|
|
175
|
+
✓ Donna is ready!
|
|
176
|
+
|
|
177
|
+
Storage repo: <repo>
|
|
178
|
+
Config: ~/.config/donna/config.md
|
|
179
|
+
|
|
38
180
|
Next steps:
|
|
39
|
-
- Run /donna:
|
|
40
|
-
-
|
|
181
|
+
- Run /donna:add-task to capture your first task
|
|
182
|
+
- Run /donna:done to mark tasks complete
|
|
41
183
|
```
|
|
42
184
|
</step>
|