@orderful/droid 0.47.0 → 0.48.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.
Files changed (37) hide show
  1. package/.claude-plugin/plugin.json +2 -0
  2. package/CHANGELOG.md +10 -0
  3. package/dist/tools/brain/.claude-plugin/plugin.json +1 -1
  4. package/dist/tools/brain/TOOL.yaml +1 -1
  5. package/dist/tools/brain/skills/brain/SKILL.md +3 -1
  6. package/dist/tools/brain/skills/brain/references/workflows.md +4 -2
  7. package/dist/tools/comments/.claude-plugin/plugin.json +1 -1
  8. package/dist/tools/comments/TOOL.yaml +1 -1
  9. package/dist/tools/comments/skills/comments/SKILL.md +14 -0
  10. package/dist/tools/excalidraw/.claude-plugin/plugin.json +22 -0
  11. package/dist/tools/excalidraw/TOOL.yaml +16 -0
  12. package/dist/tools/excalidraw/commands/excalidraw.md +34 -0
  13. package/dist/tools/excalidraw/skills/excalidraw/SKILL.md +100 -0
  14. package/dist/tools/excalidraw/skills/excalidraw/references/element-templates.md +336 -0
  15. package/dist/tools/excalidraw/skills/excalidraw/references/format-spec.md +102 -0
  16. package/dist/tools/plan/.claude-plugin/plugin.json +1 -1
  17. package/dist/tools/plan/TOOL.yaml +1 -1
  18. package/dist/tools/plan/skills/plan/SKILL.md +2 -0
  19. package/dist/tools/plan/skills/plan/references/workflows.md +11 -2
  20. package/package.json +1 -1
  21. package/src/tools/brain/.claude-plugin/plugin.json +1 -1
  22. package/src/tools/brain/TOOL.yaml +1 -1
  23. package/src/tools/brain/skills/brain/SKILL.md +3 -1
  24. package/src/tools/brain/skills/brain/references/workflows.md +4 -2
  25. package/src/tools/comments/.claude-plugin/plugin.json +1 -1
  26. package/src/tools/comments/TOOL.yaml +1 -1
  27. package/src/tools/comments/skills/comments/SKILL.md +14 -0
  28. package/src/tools/excalidraw/.claude-plugin/plugin.json +22 -0
  29. package/src/tools/excalidraw/TOOL.yaml +16 -0
  30. package/src/tools/excalidraw/commands/excalidraw.md +34 -0
  31. package/src/tools/excalidraw/skills/excalidraw/SKILL.md +100 -0
  32. package/src/tools/excalidraw/skills/excalidraw/references/element-templates.md +336 -0
  33. package/src/tools/excalidraw/skills/excalidraw/references/format-spec.md +102 -0
  34. package/src/tools/plan/.claude-plugin/plugin.json +1 -1
  35. package/src/tools/plan/TOOL.yaml +1 -1
  36. package/src/tools/plan/skills/plan/SKILL.md +2 -0
  37. package/src/tools/plan/skills/plan/references/workflows.md +11 -2
@@ -0,0 +1,336 @@
1
+ # Element Templates and Colour Palette
2
+
3
+ ## Common Properties (all elements)
4
+
5
+ Every element must include these fields:
6
+
7
+ ```json
8
+ {
9
+ "version": 1,
10
+ "seed": 1,
11
+ "versionNonce": 1,
12
+ "index": "a0",
13
+ "isDeleted": false,
14
+ "updated": 1,
15
+ "link": null,
16
+ "locked": false,
17
+ "groupIds": [],
18
+ "boundElements": [],
19
+ "strokeStyle": "solid",
20
+ "frameId": null,
21
+ "opacity": 100,
22
+ "angle": 0,
23
+ "roughness": 1
24
+ }
25
+ ```
26
+
27
+ **Element ID convention:** Increment `index` for each element: `"a0"`, `"a1"`, `"a2"`, etc. Use short unique alphanumeric strings for `id` fields (e.g., `"box_api"`, `"text_api"`, `"arrow_api_db"`).
28
+
29
+ ## Rectangle (container)
30
+
31
+ ```json
32
+ {
33
+ "type": "rectangle",
34
+ "id": "box_unique_id",
35
+ "x": 0, "y": 0,
36
+ "width": 260, "height": 120,
37
+ "strokeColor": "#1e1e1e",
38
+ "backgroundColor": "#d0ebff",
39
+ "fillStyle": "solid",
40
+ "strokeWidth": 2,
41
+ "roundness": { "type": 3 },
42
+ "boundElements": [
43
+ { "type": "text", "id": "text_for_this_box" }
44
+ ],
45
+ "version": 1,
46
+ "seed": 1,
47
+ "versionNonce": 1,
48
+ "index": "a0",
49
+ "isDeleted": false,
50
+ "updated": 1,
51
+ "link": null,
52
+ "locked": false,
53
+ "groupIds": [],
54
+ "strokeStyle": "solid",
55
+ "frameId": null,
56
+ "opacity": 100,
57
+ "angle": 0,
58
+ "roughness": 1
59
+ }
60
+ ```
61
+
62
+ ## Text (bound to container)
63
+
64
+ Bound text lives inside a rectangle. The `containerId` on the text and the matching `boundElements` on the rectangle must reference each other.
65
+
66
+ ```json
67
+ {
68
+ "type": "text",
69
+ "id": "text_for_this_box",
70
+ "x": 10, "y": 10,
71
+ "width": 240, "height": 100,
72
+ "text": "Service Name\n\nHandles auth\nManages sessions",
73
+ "fontSize": 16,
74
+ "fontFamily": 1,
75
+ "textAlign": "center",
76
+ "verticalAlign": "middle",
77
+ "strokeColor": "#1e1e1e",
78
+ "backgroundColor": "transparent",
79
+ "fillStyle": "solid",
80
+ "strokeWidth": 1,
81
+ "containerId": "box_unique_id",
82
+ "originalText": "Service Name\n\nHandles auth\nManages sessions",
83
+ "autoResize": true,
84
+ "lineHeight": 1.25,
85
+ "hasTextLink": false,
86
+ "rawText": "",
87
+ "version": 1,
88
+ "seed": 1,
89
+ "versionNonce": 1,
90
+ "index": "a1",
91
+ "isDeleted": false,
92
+ "updated": 1,
93
+ "link": null,
94
+ "locked": false,
95
+ "groupIds": [],
96
+ "boundElements": [],
97
+ "strokeStyle": "solid",
98
+ "frameId": null,
99
+ "opacity": 100,
100
+ "angle": 0,
101
+ "roughness": 1
102
+ }
103
+ ```
104
+
105
+ ## Text (standalone — titles, labels)
106
+
107
+ Same as bound text but with `"containerId": null` and no parent rectangle reference.
108
+
109
+ ```json
110
+ {
111
+ "type": "text",
112
+ "id": "title_text",
113
+ "x": 100, "y": 20,
114
+ "width": 400, "height": 40,
115
+ "text": "My Architecture Diagram",
116
+ "fontSize": 28,
117
+ "fontFamily": 1,
118
+ "textAlign": "center",
119
+ "verticalAlign": "middle",
120
+ "strokeColor": "#1e1e1e",
121
+ "backgroundColor": "transparent",
122
+ "fillStyle": "solid",
123
+ "strokeWidth": 1,
124
+ "containerId": null,
125
+ "originalText": "My Architecture Diagram",
126
+ "autoResize": true,
127
+ "lineHeight": 1.25,
128
+ "hasTextLink": false,
129
+ "rawText": "",
130
+ "version": 1,
131
+ "seed": 1,
132
+ "versionNonce": 1,
133
+ "index": "a0",
134
+ "isDeleted": false,
135
+ "updated": 1,
136
+ "link": null,
137
+ "locked": false,
138
+ "groupIds": [],
139
+ "boundElements": [],
140
+ "strokeStyle": "solid",
141
+ "frameId": null,
142
+ "opacity": 100,
143
+ "angle": 0,
144
+ "roughness": 1
145
+ }
146
+ ```
147
+
148
+ ## Arrow
149
+
150
+ For connected arrows, `startBinding` and `endBinding` must reference the source and target element IDs. The `points` array defines the arrow path relative to the arrow's `x`/`y` origin.
151
+
152
+ ```json
153
+ {
154
+ "type": "arrow",
155
+ "id": "arrow_unique_id",
156
+ "x": 260, "y": 60,
157
+ "width": 80, "height": 0,
158
+ "strokeColor": "#868e96",
159
+ "backgroundColor": "transparent",
160
+ "fillStyle": "solid",
161
+ "strokeWidth": 2,
162
+ "roundness": { "type": 2 },
163
+ "startBinding": { "elementId": "source_box_id", "focus": 0, "gap": 5 },
164
+ "endBinding": { "elementId": "target_box_id", "focus": 0, "gap": 5 },
165
+ "startArrowhead": null,
166
+ "endArrowhead": "arrow",
167
+ "points": [[0, 0], [80, 0]],
168
+ "version": 1,
169
+ "seed": 1,
170
+ "versionNonce": 1,
171
+ "index": "a3",
172
+ "isDeleted": false,
173
+ "updated": 1,
174
+ "link": null,
175
+ "locked": false,
176
+ "groupIds": [],
177
+ "boundElements": [],
178
+ "strokeStyle": "solid",
179
+ "frameId": null,
180
+ "opacity": 100,
181
+ "angle": 0,
182
+ "roughness": 1
183
+ }
184
+ ```
185
+
186
+ For vertical arrows, adjust `height` instead of `width` and set points accordingly (e.g., `[[0, 0], [0, 80]]`).
187
+
188
+ ## Sticky Note
189
+
190
+ A sticky note is a rectangle with bound text that auto-resizes to fit content. Useful for annotations, callouts, and concept maps.
191
+
192
+ ```json
193
+ {
194
+ "type": "rectangle",
195
+ "id": "note_unique_id",
196
+ "x": 0, "y": 0,
197
+ "width": 200, "height": 80,
198
+ "strokeColor": "#e8590c",
199
+ "backgroundColor": "#ffe8cc",
200
+ "fillStyle": "solid",
201
+ "strokeWidth": 1,
202
+ "roundness": { "type": 3 },
203
+ "customData": { "legacyTextWrap": true },
204
+ "boundElements": [
205
+ { "type": "text", "id": "note_text_id" }
206
+ ],
207
+ "version": 1,
208
+ "seed": 1,
209
+ "versionNonce": 1,
210
+ "index": "a4",
211
+ "isDeleted": false,
212
+ "updated": 1,
213
+ "link": null,
214
+ "locked": false,
215
+ "groupIds": [],
216
+ "strokeStyle": "solid",
217
+ "frameId": null,
218
+ "opacity": 100,
219
+ "angle": 0,
220
+ "roughness": 1
221
+ }
222
+ ```
223
+
224
+ With matching bound text (same pattern as bound text above, with `"containerId": "note_unique_id"`).
225
+
226
+ ## Colour Palette
227
+
228
+ Use Excalidraw's built-in colours for consistency:
229
+
230
+ | Purpose | `strokeColor` | `backgroundColor` |
231
+ |---------|--------------|------------------|
232
+ | Primary / highlighted | `#2f9e44` | `#b2f2bb` (green) |
233
+ | Secondary | `#1971c2` | `#d0ebff` (blue) |
234
+ | Tertiary | `#e8590c` | `#ffe8cc` (orange) |
235
+ | Neutral / supporting | `#868e96` | `#e9ecef` (grey) |
236
+ | Warning / attention | `#e03131` | `#ffc9c9` (red) |
237
+ | Purple / alternate | `#6741d9` | `#d0bfff` (purple) |
238
+ | Labels / arrows | `#868e96` | `transparent` |
239
+ | Title text | `#1e1e1e` | `transparent` |
240
+
241
+ **Colour grouping rule:** Use one colour per logical group (e.g., all API services blue, all data stores green). Before generating, propose the colour assignments to the user so they can adjust. This ensures the legend is meaningful, not arbitrary.
242
+
243
+ ## Colour Legend
244
+
245
+ **Every diagram must include a colour legend.** Place it in the bottom-left corner of the canvas, below and to the left of the main diagram content.
246
+
247
+ The legend is a vertical stack of small colour swatches (rectangles) with labels explaining what each colour represents in this specific diagram. Only include colours that are actually used.
248
+
249
+ ```
250
+ ┌──────────────────┐
251
+ │ Legend │ ← title text (fontSize: 16, bold)
252
+ │ │
253
+ │ ■ API Services │ ← small coloured rectangle + label
254
+ │ ■ Data Stores │
255
+ │ ■ External │
256
+ │ ■ Infrastructure │
257
+ └──────────────────┘
258
+ ```
259
+
260
+ **Implementation:** Use a group of elements:
261
+ - One standalone title text element ("Legend", fontSize: 16)
262
+ - For each colour: a small rectangle (30x20px) + standalone text label to its right
263
+ - Stack vertically with 8px gap between rows
264
+ - Position below the main diagram content with ~60px margin
265
+
266
+ Example swatch element:
267
+ ```json
268
+ {
269
+ "type": "rectangle",
270
+ "id": "legend_swatch_blue",
271
+ "x": 100, "y": 600,
272
+ "width": 30, "height": 20,
273
+ "strokeColor": "#1971c2",
274
+ "backgroundColor": "#d0ebff",
275
+ "fillStyle": "solid",
276
+ "strokeWidth": 1,
277
+ "roundness": { "type": 3 }
278
+ }
279
+ ```
280
+
281
+ With a matching label:
282
+ ```json
283
+ {
284
+ "type": "text",
285
+ "id": "legend_label_blue",
286
+ "x": 140, "y": 600,
287
+ "width": 120, "height": 20,
288
+ "text": "API Services",
289
+ "fontSize": 14,
290
+ "fontFamily": 1,
291
+ "textAlign": "left",
292
+ "verticalAlign": "middle",
293
+ "strokeColor": "#1e1e1e",
294
+ "backgroundColor": "transparent",
295
+ "containerId": null
296
+ }
297
+ ```
298
+
299
+ Repeat for each colour used in the diagram, incrementing y by 28px per row.
300
+
301
+ ## Sizing Guidelines
302
+
303
+ | Element | Recommended size |
304
+ |---------|-----------------|
305
+ | Box width | 200–300px (varies by text length) |
306
+ | Box height | 80–160px (varies by content lines) |
307
+ | Horizontal gap between boxes | 80–120px |
308
+ | Vertical gap between rows | 60–100px |
309
+ | Title font size | 28 |
310
+ | Box text font size | 16–20 |
311
+ | Label font size | 14 |
312
+
313
+ **Text width estimate:** ~8px per character at `fontSize: 16`
314
+
315
+ **Arrow labels:** Place as standalone text near the arrow midpoint.
316
+
317
+ ## Layout Style Guidance
318
+
319
+ ### Flow Chart
320
+ For processes, workflows, request lifecycles. Arrange top-to-bottom or left-to-right with directional arrows. Each step is a box; decisions can use diamond shapes (rotated rectangles).
321
+
322
+ ### Architecture Diagram
323
+ For system components, services, layers. Use grouped boxes with labels, arrows showing data flow between services. Group related services with a larger background rectangle.
324
+
325
+ ### Entity Relationship
326
+ For data models, schemas, relationships. Boxes represent entities with field lists inside. Lines (not arrows) show relationships; label the line with cardinality (1:N, etc.).
327
+
328
+ ### Concept Map
329
+ For brainstorming, exploring ideas. Loose arrangement, grouped by theme. Connecting lines with labels, sticky notes for annotations. Less rigid than a flow chart.
330
+
331
+ ## Tips
332
+
333
+ - Keep text concise — bullet points over paragraphs
334
+ - Add a title text element at the top of the canvas
335
+ - For large diagrams, organise in clear rows/columns — the user can rearrange in Excalidraw
336
+ - Start elements at coordinates (100, 100) or higher to leave canvas margin
@@ -0,0 +1,102 @@
1
+ # Excalidraw File Format Specification
2
+
3
+ ## Important: Use `.excalidraw.md`, NOT `.excalidraw`
4
+
5
+ The Obsidian Excalidraw plugin uses `.excalidraw.md` files (a markdown wrapper format). Plain `.excalidraw` JSON opens in "compatibility mode" with limited functionality.
6
+
7
+ ## YAML Frontmatter
8
+
9
+ The file MUST start with this frontmatter:
10
+
11
+ ```
12
+ ---
13
+ excalidraw-plugin: parsed
14
+ ---
15
+ ```
16
+
17
+ The `excalidraw-plugin: parsed` key is mandatory. Without it, Obsidian won't recognise the file as an Excalidraw drawing.
18
+
19
+ ## Full File Structure
20
+
21
+ ````markdown
22
+ ---
23
+ excalidraw-plugin: parsed
24
+ ---
25
+
26
+ # Drawing
27
+
28
+ ```json
29
+ {
30
+ "type": "excalidraw",
31
+ "version": 2,
32
+ "source": "https://excalidraw.com",
33
+ "elements": [],
34
+ "appState": {
35
+ "gridSize": null,
36
+ "viewBackgroundColor": "#ffffff"
37
+ },
38
+ "files": {}
39
+ }
40
+ ```
41
+
42
+ %%
43
+ # Drawing
44
+ ```json
45
+ {
46
+ "type": "excalidraw",
47
+ "version": 2,
48
+ "source": "https://excalidraw.com",
49
+ "elements": [],
50
+ "appState": {
51
+ "gridSize": null,
52
+ "viewBackgroundColor": "#ffffff"
53
+ },
54
+ "files": {}
55
+ }
56
+ ```
57
+ %%
58
+ ````
59
+
60
+ ## Structure Explained
61
+
62
+ The JSON appears **twice** in the file:
63
+
64
+ 1. **Visible block** — inside a fenced ` ```json ` code block after `# Drawing`. This is what shows in Obsidian's markdown preview.
65
+ 2. **Plugin working copy** — the same JSON repeated inside `%% ... %%` comment markers. This is what the Excalidraw plugin uses to render the drawing.
66
+
67
+ **Both blocks must contain identical JSON.** The plugin reads from the `%%` block when rendering; the visible block is for human reference.
68
+
69
+ ## Top-Level JSON Schema
70
+
71
+ ```json
72
+ {
73
+ "type": "excalidraw",
74
+ "version": 2,
75
+ "source": "https://excalidraw.com",
76
+ "elements": [ /* all drawing elements go here */ ],
77
+ "appState": {
78
+ "gridSize": null,
79
+ "viewBackgroundColor": "#ffffff"
80
+ },
81
+ "files": {}
82
+ }
83
+ ```
84
+
85
+ | Field | Value | Notes |
86
+ |-------|-------|-------|
87
+ | `type` | `"excalidraw"` | Always this string |
88
+ | `version` | `2` | Always 2 |
89
+ | `source` | `"https://excalidraw.com"` | Always this URL |
90
+ | `elements` | array | All drawing elements |
91
+ | `appState.gridSize` | `null` | No grid by default |
92
+ | `appState.viewBackgroundColor` | `"#ffffff"` | White background |
93
+ | `files` | `{}` | Empty unless images embedded |
94
+
95
+ ## What Happens If Format Is Wrong
96
+
97
+ | Problem | Result |
98
+ |---------|--------|
99
+ | Missing `excalidraw-plugin: parsed` frontmatter | File opens as plain markdown, not as a drawing |
100
+ | JSON only in visible block, missing `%%` block | Drawing renders as JSON text only |
101
+ | JSON mismatch between blocks | Plugin uses `%%` block; visible block shows stale content |
102
+ | Using `.excalidraw` instead of `.excalidraw.md` | Opens in compatibility mode with limited functionality |
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "droid-plan",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "Task-scoped planning with portable, structured plans. Use when planning implementation for a PR, ticket, or small feature. User prompts like 'let's plan this', 'can we start a plan', 'think through the implementation'.",
5
5
  "author": {
6
6
  "name": "Orderful",
@@ -1,6 +1,6 @@
1
1
  name: plan
2
2
  description: "Task-scoped planning with portable, structured plans. Use when planning implementation for a PR, ticket, or small feature. User prompts like 'let's plan this', 'can we start a plan', 'think through the implementation'."
3
- version: 0.1.5
3
+ version: 0.1.6
4
4
  status: alpha
5
5
 
6
6
  includes:
@@ -74,6 +74,8 @@ Example: `/plan new auth-refactor -- we must stay backward compatible with v1 cl
74
74
  2. Address each, respond with `> @{user_mention}`
75
75
  3. Update the doc
76
76
 
77
+ With `--holistic`: group related comments into thematic clusters and respond cohesively to each cluster instead of one-by-one. Unrelated comments still get individual responses. See `comments` skill for full holistic mode behaviour.
78
+
77
79
  ## `/plan cleanup`
78
80
 
79
81
  **Trigger:** `/plan cleanup` or user says "clean up", "lock in decisions", "resolve these threads"
@@ -126,6 +126,8 @@ Store as active plan for session.
126
126
 
127
127
  ## `/plan check`
128
128
 
129
+ Supports `--holistic` flag for cohesive responses to related comments.
130
+
129
131
  ### Step 1: Load Active Plan
130
132
 
131
133
  If no active plan, prompt to search for one.
@@ -138,13 +140,20 @@ Search for `> @droid` lines (user comments addressed to AI):
138
140
  grep -n "> @droid" {plan_path}
139
141
  ```
140
142
 
141
- ### Step 3: Address Each Comment
143
+ ### Step 3: Address Comments
142
144
 
143
- For each comment:
145
+ **Default mode:** For each comment:
144
146
 
145
147
  1. **Read context** - surrounding lines, section it's in
146
148
  2. **Respond** - add response below with `> @{user_mention}`
147
149
 
150
+ **Holistic mode (`--holistic`):**
151
+
152
+ 1. **Read all comments first** with their surrounding context
153
+ 2. **Group related comments** — identify thematic clusters (comments exploring the same question, building on each other, or pulling in different directions on the same topic)
154
+ 3. **For each cluster:** respond once at the last comment in the group with a cohesive answer that addresses the whole cluster. Earlier comments get a brief forward-reference: `> @{user_mention} Addressed below with the related comments.`
155
+ 4. **Standalone comments:** respond individually as normal
156
+
148
157
  ### Step 4: Update Doc
149
158
 
150
159
  Write changes back to plan file.