claude-mcp-workflow 0.1.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/.claude-plugin/plugin.json +13 -0
- package/.mcp.json +9 -0
- package/LICENSE +21 -0
- package/README.md +260 -0
- package/build/dashboard.d.ts +4 -0
- package/build/dashboard.d.ts.map +1 -0
- package/build/dashboard.js +91 -0
- package/build/dashboard.js.map +1 -0
- package/build/engine.d.ts +55 -0
- package/build/engine.d.ts.map +1 -0
- package/build/engine.js +486 -0
- package/build/engine.js.map +1 -0
- package/build/index.d.ts +2 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +60 -0
- package/build/index.js.map +1 -0
- package/build/loader.d.ts +29 -0
- package/build/loader.d.ts.map +1 -0
- package/build/loader.js +166 -0
- package/build/loader.js.map +1 -0
- package/build/modifier.d.ts +42 -0
- package/build/modifier.d.ts.map +1 -0
- package/build/modifier.js +96 -0
- package/build/modifier.js.map +1 -0
- package/build/storage.d.ts +12 -0
- package/build/storage.d.ts.map +1 -0
- package/build/storage.js +62 -0
- package/build/storage.js.map +1 -0
- package/build/tools.d.ts +7 -0
- package/build/tools.d.ts.map +1 -0
- package/build/tools.js +316 -0
- package/build/tools.js.map +1 -0
- package/build/types.d.ts +417 -0
- package/build/types.d.ts.map +1 -0
- package/build/types.js +82 -0
- package/build/types.js.map +1 -0
- package/dashboard/dagre.min.js +801 -0
- package/dashboard/index.html +652 -0
- package/hooks/hooks.json +24 -0
- package/hooks/workflow-cleanup.sh +51 -0
- package/hooks/workflow-start.sh +79 -0
- package/package.json +44 -0
- package/templates/bug-fix.yaml +283 -0
- package/templates/code-review.yaml +164 -0
- package/templates/coding.yaml +176 -0
- package/templates/debugging.yaml +162 -0
- package/templates/explore.yaml +90 -0
- package/templates/file-code.yaml +69 -0
- package/templates/file-review.yaml +164 -0
- package/templates/investigate.yaml +84 -0
- package/templates/master.yaml +202 -0
- package/templates/new-feature.yaml +41 -0
- package/templates/planning.yaml +85 -0
- package/templates/refactoring.yaml +56 -0
- package/templates/reflection.yaml +61 -0
- package/templates/skills/architecture/SKILL.md +55 -0
- package/templates/skills/coding-skill-selector/SKILL.md +25 -0
- package/templates/skills/lang-haxe/SKILL.md +257 -0
- package/templates/skills/lang-python/SKILL.md +16 -0
- package/templates/skills/math/SKILL.md +14 -0
- package/templates/skills/preferences/SKILL.md +25 -0
- package/templates/skills/task-delegation/SKILL.md +53 -0
- package/templates/skills/web-reading/SKILL.md +62 -0
- package/templates/subagent.yaml +67 -0
- package/templates/testing.yaml +120 -0
- package/templates/web-research.yaml +53 -0
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: lang-haxe
|
|
3
|
+
description: Haxe language gotchas
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Haxe — Verified Gotchas
|
|
7
|
+
|
|
8
|
+
## String Interpolation: Single Quotes Only
|
|
9
|
+
|
|
10
|
+
Inverted from most languages. Double quotes are plain strings.
|
|
11
|
+
|
|
12
|
+
```haxe
|
|
13
|
+
var name = "world";
|
|
14
|
+
var greeting = 'Hello, $name!'; // ✓ Simple variable — no braces
|
|
15
|
+
var result = 'Sum is ${a + b}'; // ✓ Expression — braces required
|
|
16
|
+
var plain = "No $interpolation here"; // ✗ Literal text, no parsing
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
- `$name` for simple variables — NO braces
|
|
20
|
+
- `${expr}` only for expressions (field access, math, function calls)
|
|
21
|
+
- `'${_name}'` is wrong → `'$_name'`
|
|
22
|
+
|
|
23
|
+
## Properties: Never Call set_/get_ Directly
|
|
24
|
+
|
|
25
|
+
Haxe properties with `(default, set)` or `(get, default)` **always** route through the getter/setter — even for self-assignment inside the owning class. Never bypass the property syntax by calling `set_X()` / `get_X()` directly.
|
|
26
|
+
|
|
27
|
+
```haxe
|
|
28
|
+
public var thumbSize(default, set):Float = 0;
|
|
29
|
+
|
|
30
|
+
// WRONG — bypasses property system, anti-pattern
|
|
31
|
+
set_thumbSize(thumbSize);
|
|
32
|
+
|
|
33
|
+
// RIGHT — property syntax, calls setter
|
|
34
|
+
this.thumbSize = thumbSize;
|
|
35
|
+
|
|
36
|
+
// BETTER — if value unchanged, call only what's needed
|
|
37
|
+
redrawThumb(thumbSize); // when only the side-effect matters
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
- `this.thumbSize = thumbSize` (self-assignment) **does** trigger the setter — Haxe does not optimize it away
|
|
41
|
+
- Direct `set_X()` calls are a Java/C# habit — in Haxe, always use property access
|
|
42
|
+
|
|
43
|
+
## Null Safety: Narrowing Limitations
|
|
44
|
+
|
|
45
|
+
### Basic (`@:nullSafety`)
|
|
46
|
+
`if (x != null)` narrows for **argument passing** only. Does NOT narrow for:
|
|
47
|
+
- **Lambda captures**: `() -> useString(x)` — x still nullable
|
|
48
|
+
- **Method calls on nullable**: `handler.bind(...)`, `handler("x")` — error
|
|
49
|
+
|
|
50
|
+
Fix: pass narrowed value through a helper with non-null param, or use `.bind()` at call site for value types.
|
|
51
|
+
|
|
52
|
+
### Strict (`@:nullSafety(Strict)`)
|
|
53
|
+
Fields are NEVER narrowed — compiler assumes another thread/callback could modify them. Local variables narrow normally.
|
|
54
|
+
|
|
55
|
+
**Pattern: capture field into local immediately after null check:**
|
|
56
|
+
```haxe
|
|
57
|
+
// WRONG — field not narrowed in Strict, any statement between check and use resets it
|
|
58
|
+
if (_animate == null) return;
|
|
59
|
+
_transitioning = true; // ← field write invalidates narrowing
|
|
60
|
+
final animate:AnimatePanel = _animate; // ERROR: nullable
|
|
61
|
+
|
|
62
|
+
// RIGHT — local assigned immediately after null check, before any field writes
|
|
63
|
+
if (_animate == null) return;
|
|
64
|
+
final animate:AnimatePanel = _animate; // ✓ narrowed
|
|
65
|
+
_transitioning = true;
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**Pattern: field used multiple times — capture into local:**
|
|
69
|
+
```haxe
|
|
70
|
+
// WRONG — field access, Strict won't narrow
|
|
71
|
+
if (_logo != null) _logo.y = h - _logo.height; // ERROR
|
|
72
|
+
|
|
73
|
+
// RIGHT — local variable narrows normally
|
|
74
|
+
final logo:Null<DisplayObject> = _logo;
|
|
75
|
+
if (logo != null) logo.y = h - logo.height; // ✓
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**Pattern: field assigned then used — use local for the non-null path:**
|
|
79
|
+
```haxe
|
|
80
|
+
// WRONG — _logo is Null<T> field, stays nullable after assignment
|
|
81
|
+
_logo = new Bitmap(data);
|
|
82
|
+
_logo.alpha = 0.3; // ERROR
|
|
83
|
+
|
|
84
|
+
// RIGHT — assign to local first, then store in field
|
|
85
|
+
final logo:DisplayObject = new Bitmap(data);
|
|
86
|
+
_logo = logo;
|
|
87
|
+
logo.alpha = 0.3; // ✓
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**Key rule:** in Strict mode, ANY intervening statement (even writing to a *different* field) can invalidate narrowing of a nullable field. Always capture to local **immediately** after the null check.
|
|
91
|
+
|
|
92
|
+
## Map Key-Value Iteration
|
|
93
|
+
|
|
94
|
+
Use `for (key => value in map)` — cleaner than iterating keys and looking up values separately. Value is guaranteed non-null.
|
|
95
|
+
|
|
96
|
+
```haxe
|
|
97
|
+
// WRONG — extra lookup + unnecessary null check
|
|
98
|
+
for (f in _frames.keys()) {
|
|
99
|
+
final fData:Null<Map<Int, Data>> = _frames[f];
|
|
100
|
+
if (fData != null) { ... }
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// WRONG — _ => is redundant, Haxe iterates values by default
|
|
104
|
+
for (_ => data in frameData) { ... }
|
|
105
|
+
|
|
106
|
+
// RIGHT — key-value destructuring, no lookup, no null check
|
|
107
|
+
for (f => fData in _frames) { ... }
|
|
108
|
+
|
|
109
|
+
// RIGHT — values only (key unused), just iterate directly
|
|
110
|
+
for (data in frameData) { ... }
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
**Rule: NEVER use `_ =>` in map iteration.** If the key is unused, drop it — `for (val in map)` iterates values directly.
|
|
114
|
+
|
|
115
|
+
## Null Coalescing Operator `??`
|
|
116
|
+
|
|
117
|
+
Use `??` to provide a fallback when left side is null. Combines well with `?.` for chained nullable access.
|
|
118
|
+
|
|
119
|
+
```haxe
|
|
120
|
+
// WRONG — verbose ternary chains
|
|
121
|
+
fe != null && fe.action != null ? fe.action : (be != null ? be.action : null)
|
|
122
|
+
|
|
123
|
+
// RIGHT — null-safe access + coalescing
|
|
124
|
+
fe?.action ?? be?.action
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
- `a ?? b` → returns `a` if non-null, else `b`
|
|
128
|
+
- `fe?.field ?? be?.field` → try `fe.field`, fall back to `be.field`
|
|
129
|
+
|
|
130
|
+
## Enum Abstract for Simple Enums
|
|
131
|
+
|
|
132
|
+
For marker enums without associated data, use `enum abstract(Int)` — zero-cost at runtime, compiles to a primitive. Use `final` instead of `var` for values (immutable by intent).
|
|
133
|
+
|
|
134
|
+
```haxe
|
|
135
|
+
// WRONG — runtime enum objects, unnecessary overhead
|
|
136
|
+
enum ScrollDirection {
|
|
137
|
+
HORIZONTAL;
|
|
138
|
+
VERTICAL;
|
|
139
|
+
BOTH;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// RIGHT — zero-cost, compiles to Int
|
|
143
|
+
enum abstract ScrollDirection(Int) {
|
|
144
|
+
final HORIZONTAL = 0;
|
|
145
|
+
final VERTICAL = 1;
|
|
146
|
+
final BOTH = 2;
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
- Use regular `enum` only when you need associated data (`case Node(left, right)`) or pattern matching
|
|
151
|
+
- `enum abstract` supports `==` comparison, switch, and all typical enum usage
|
|
152
|
+
|
|
153
|
+
## Optional Parameters: Type-Based Skipping
|
|
154
|
+
|
|
155
|
+
Parameters with default values (`param:Type = default`) can be **skipped** at call site. Haxe compiler matches arguments to parameters by type, not just position.
|
|
156
|
+
|
|
157
|
+
```haxe
|
|
158
|
+
function new(?children:Array<DisplayObject>, ?w:Int, ?h:Int,
|
|
159
|
+
bgColor:Int = -1, bgAlpha:Float = 1, bgRadius:UInt = 0,
|
|
160
|
+
alignment:String = "start")
|
|
161
|
+
|
|
162
|
+
// Skip bgColor, bgAlpha, bgRadius — compiler matches String to alignment:
|
|
163
|
+
super(items, 30, 30, "end"); // ✓ Clean
|
|
164
|
+
super(items, 30, 30, -1, 1, 0, "end"); // ✗ Hardcoding someone else's defaults
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
**Never hardcode intermediate default values** to reach a later parameter — use type-based skipping instead.
|
|
168
|
+
|
|
169
|
+
**DANGER: Float constant passed to Int parameter silently skips it.** An `inline final X:Float = 180` looks like an integer but is typed Float. When passed to `new Row(children, X, 16, ...)` where `boxWidth:Int`, the Float skips `boxWidth` and lands on the next Float parameter (e.g. `bgAlpha`). Fix: use `Int` type for constants passed to Int parameters, or cast with `Std.int()`.
|
|
170
|
+
|
|
171
|
+
## Abstract Classes (Haxe 4.2+)
|
|
172
|
+
|
|
173
|
+
Native `abstract class` keyword — NOT the same as `abstract` types (which are compile-time wrappers over existing types).
|
|
174
|
+
|
|
175
|
+
```haxe
|
|
176
|
+
// Abstract base — cannot be instantiated directly
|
|
177
|
+
@:nullSafety abstract class ScrollAxis {
|
|
178
|
+
abstract private function contentMeasure(content:DisplayObject):Float;
|
|
179
|
+
abstract private function getScroll(content:DisplayObject):Float;
|
|
180
|
+
|
|
181
|
+
// Concrete methods can call abstract ones (template method pattern)
|
|
182
|
+
public function maxScroll(content:DisplayObject, vp:Float):Float {
|
|
183
|
+
return Math.max(0, contentMeasure(content) - vp);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Subclass — implements abstract methods WITHOUT `override`
|
|
188
|
+
@:nullSafety(Strict) final class VerticalScrollAxis extends ScrollAxis {
|
|
189
|
+
private function contentMeasure(content:DisplayObject):Float {
|
|
190
|
+
return content.getBounds(content).bottom * content.scaleY;
|
|
191
|
+
}
|
|
192
|
+
private function getScroll(content:DisplayObject):Float {
|
|
193
|
+
return content.y;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
**Key rules:**
|
|
199
|
+
- `abstract` methods have **no body** — just the signature
|
|
200
|
+
- Subclasses implement abstract methods **WITHOUT** `override` keyword
|
|
201
|
+
- Subclasses override concrete methods **WITH** `override` keyword
|
|
202
|
+
- `abstract class` **cannot** combine with `final` or `inline`
|
|
203
|
+
- Subclasses **can** be `final class`
|
|
204
|
+
- Abstract method calls from constructor work fine (vtable is ready)
|
|
205
|
+
|
|
206
|
+
## Switch Without Parentheses
|
|
207
|
+
|
|
208
|
+
In Haxe, `switch` does not require parentheses around the expression (unlike `if`/`while` where they are mandatory).
|
|
209
|
+
|
|
210
|
+
```haxe
|
|
211
|
+
// WRONG — C-style parentheses
|
|
212
|
+
switch (value) { ... }
|
|
213
|
+
|
|
214
|
+
// RIGHT — idiomatic Haxe
|
|
215
|
+
switch value { ... }
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## If-Expression for Conditional Assignment
|
|
219
|
+
|
|
220
|
+
`if/else` in Haxe is an expression — use it to assign `final` instead of `var` with mutation.
|
|
221
|
+
|
|
222
|
+
```haxe
|
|
223
|
+
// WRONG — var with overwrite, dummy initial value
|
|
224
|
+
var target:Float = currentScroll;
|
|
225
|
+
if (condA)
|
|
226
|
+
target = valueA;
|
|
227
|
+
else if (condB)
|
|
228
|
+
target = valueB;
|
|
229
|
+
else
|
|
230
|
+
return;
|
|
231
|
+
|
|
232
|
+
// RIGHT — final + if-expression
|
|
233
|
+
final target:Float = if (condA)
|
|
234
|
+
valueA;
|
|
235
|
+
else if (condB)
|
|
236
|
+
valueB;
|
|
237
|
+
else
|
|
238
|
+
return;
|
|
239
|
+
|
|
240
|
+
// RIGHT — with fallback value instead of return
|
|
241
|
+
final target:Float = if (condA) valueA;
|
|
242
|
+
else if (condB) valueB;
|
|
243
|
+
else currentScroll;
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
- `else return` works inside if-expression — exits function, never assigns
|
|
247
|
+
- Eliminates `var` + mutation pattern
|
|
248
|
+
- Works with `switch` too: `final x:Int = switch v { case A: 1; case B: 2; }`
|
|
249
|
+
|
|
250
|
+
**Null safety with `?.` on abstract method returns:**
|
|
251
|
+
```haxe
|
|
252
|
+
// WRONG — && narrowing fails for method calls on nullable
|
|
253
|
+
final scrolling:Bool = (_axis != null && _axis.isScrolling());
|
|
254
|
+
|
|
255
|
+
// RIGHT — safe navigation + explicit comparison
|
|
256
|
+
final scrolling:Bool = (_axis?.isScrolling() == true);
|
|
257
|
+
```
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: lang-python
|
|
3
|
+
description: Python language gotchas
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Python — Verified Gotchas
|
|
7
|
+
|
|
8
|
+
## Walrus Operator `:=` Scope Leak in Comprehensions
|
|
9
|
+
|
|
10
|
+
```python
|
|
11
|
+
results = [c for raw in data if (c := normalize(raw)) is not None]
|
|
12
|
+
# c IS accessible outside the comprehension! (PEP 572 design)
|
|
13
|
+
# Unlike regular loop variables, := leaks to enclosing scope
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Sonnet confidently says "c is NOT accessible" — this is wrong. The walrus operator in comprehensions intentionally binds in the containing scope.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: math
|
|
3
|
+
description: Math overflow boundary gotchas
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Math — Verified Gotchas
|
|
7
|
+
|
|
8
|
+
## Central Binomial Coefficient C(n, n/2) overflow
|
|
9
|
+
|
|
10
|
+
| Type | Last fits | First overflow |
|
|
11
|
+
|------|-----------|----------------|
|
|
12
|
+
| Int64 | C(66, 33) = 7,219,428,434,016,265,740 | C(67, 33) |
|
|
13
|
+
|
|
14
|
+
Sonnet consistently underestimates this boundary (says n=62, correct is n=66).
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: preferences
|
|
3
|
+
description: User's general coding preferences
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## User's personal coding preferences
|
|
7
|
+
|
|
8
|
+
These rules are set by the user through direct feedback.
|
|
9
|
+
They ALWAYS take priority over base skills.
|
|
10
|
+
|
|
11
|
+
<!-- Add your preferences here. Examples: -->
|
|
12
|
+
|
|
13
|
+
### Immutability
|
|
14
|
+
|
|
15
|
+
- Prefer immutable by default — use `final`/`const`/`readonly`/`val` when value is not reassigned
|
|
16
|
+
|
|
17
|
+
### Naming
|
|
18
|
+
|
|
19
|
+
- Private fields (variables) must start with `_` prefix: `_count`, `_items`
|
|
20
|
+
|
|
21
|
+
### Error handling
|
|
22
|
+
|
|
23
|
+
- Never silently swallow invalid state — throw exceptions instead of returning quietly
|
|
24
|
+
|
|
25
|
+
<!-- See https://github.com/anthropics/claude-code/wiki/Skills for more examples -->
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: task-delegation
|
|
3
|
+
description: When and how to delegate to subagents
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Task Delegation
|
|
7
|
+
|
|
8
|
+
## Quick Check
|
|
9
|
+
|
|
10
|
+
1. **Independent parts?** → if < 2, do it yourself
|
|
11
|
+
2. **Interfaces known?** → if no, do it yourself
|
|
12
|
+
3. **Different skills needed?** → if same, maybe don't split
|
|
13
|
+
4. **Plan ready?** → if no, plan first
|
|
14
|
+
|
|
15
|
+
**3+ yes → delegate**
|
|
16
|
+
|
|
17
|
+
## Available Agents
|
|
18
|
+
|
|
19
|
+
| Agent | Use for |
|
|
20
|
+
|-------|---------|
|
|
21
|
+
| **researcher** | Information gathering, docs, APIs |
|
|
22
|
+
| **coder-python** | Python code |
|
|
23
|
+
| **debugger** | Build, run, test |
|
|
24
|
+
| **general-purpose** | Complex tasks needing MCP tools |
|
|
25
|
+
|
|
26
|
+
<!-- Add your own agent mappings here, e.g.: -->
|
|
27
|
+
<!-- | **coder-haxe** | Haxe code | -->
|
|
28
|
+
<!-- | **coder-csharp** | C# code | -->
|
|
29
|
+
|
|
30
|
+
## ALWAYS Delegate to Subagent
|
|
31
|
+
|
|
32
|
+
Build, run, and test operations → **always** use `debugger` subagent.
|
|
33
|
+
Heavy output (compilation logs, long files, web content) → through subagent with **precise extraction prompt** ("extract only X"), never dump raw output into main context.
|
|
34
|
+
Preserves main context for decision-making.
|
|
35
|
+
|
|
36
|
+
## Do It Yourself When
|
|
37
|
+
|
|
38
|
+
- Small task (< 3 files), high coupling, unclear scope, refactoring
|
|
39
|
+
|
|
40
|
+
## Split By
|
|
41
|
+
|
|
42
|
+
- **Language**: different languages → different agents
|
|
43
|
+
- **Layer**: Backend / Frontend / Database
|
|
44
|
+
- **Domain**: separate independent domains
|
|
45
|
+
|
|
46
|
+
## Rules
|
|
47
|
+
|
|
48
|
+
- **Maximize parallelism** — launch ALL independent agents in **one message**, not sequentially
|
|
49
|
+
- Split by **logical component**, not per file
|
|
50
|
+
- Stabilize interfaces **before** parallelizing
|
|
51
|
+
- Give agents **specific prompts** with file paths and signatures
|
|
52
|
+
- After agents complete: verify integration, link components, test
|
|
53
|
+
- **Review subagent code against loaded skills** — subagent fixes compile but may violate style rules. ALWAYS read changed files and apply loaded preference/lang skills before considering done
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: web-reading
|
|
3
|
+
description: Fetch web content via subagents
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Goal: protect main context from web content bloat
|
|
7
|
+
|
|
8
|
+
Every web fetch MUST go through a subagent (Task tool).
|
|
9
|
+
Never put raw web content into main conversation context.
|
|
10
|
+
|
|
11
|
+
### Step 1: Source-specific tools (no fetch needed)
|
|
12
|
+
|
|
13
|
+
Pick the right tool before reaching for the web:
|
|
14
|
+
|
|
15
|
+
- GitHub repos/issues/PRs → `gh` CLI
|
|
16
|
+
- GitHub raw file URLs (.md, .json, .yaml, .txt, etc.) → `gh api` or direct WebFetch (NOT Jina)
|
|
17
|
+
- npm packages → `npm info <pkg>`
|
|
18
|
+
- PyPI packages → `pip show <pkg>`
|
|
19
|
+
- Local files → Read tool
|
|
20
|
+
|
|
21
|
+
If none apply → Step 2.
|
|
22
|
+
|
|
23
|
+
### Step 2: Jina Reader via subagent (HTML pages only)
|
|
24
|
+
|
|
25
|
+
Jina converts HTML → clean markdown. Use ONLY for web pages with HTML content.
|
|
26
|
+
Do NOT use Jina for raw files (.md, .json, .yaml, .txt, .xml, .csv) — use direct WebFetch instead (Step 3).
|
|
27
|
+
|
|
28
|
+
Use Task tool. Subagent fetches clean content:
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
https://r.jina.ai/<original-url>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
With a precise extraction prompt specifying WHAT to extract.
|
|
35
|
+
|
|
36
|
+
### Step 3: Direct WebFetch via subagent
|
|
37
|
+
|
|
38
|
+
If Jina failed (ECONNREFUSED, empty response, error page).
|
|
39
|
+
Subagent uses WebFetch with strict prompt:
|
|
40
|
+
|
|
41
|
+
> "Extract ONLY the main article content as clean markdown.
|
|
42
|
+
> Ignore navigation, sidebars, headers, footers, ads, cookie banners.
|
|
43
|
+
> Return structured content with headings, code blocks, and lists."
|
|
44
|
+
|
|
45
|
+
### Step 4: WebSearch
|
|
46
|
+
|
|
47
|
+
If the page itself is inaccessible — search for the same
|
|
48
|
+
content in mirrors, official docs, blogs, cached versions.
|
|
49
|
+
|
|
50
|
+
### Step 5: Browser via Playwright MCP (last resort)
|
|
51
|
+
|
|
52
|
+
When content requires JS rendering or visual analysis:
|
|
53
|
+
|
|
54
|
+
- Use browser_navigate to open the page
|
|
55
|
+
- Prefer browser_snapshot (text accessibility tree) over screenshots — much lighter
|
|
56
|
+
- Use browser_take_screenshot ONLY when visual layout matters
|
|
57
|
+
- If routing through subagent: subagent analyzes, returns TEXT summary only
|
|
58
|
+
- NEVER pass raw screenshots or DOM dumps to main context
|
|
59
|
+
|
|
60
|
+
### Prompt rules
|
|
61
|
+
|
|
62
|
+
ALWAYS specify exactly what to extract. Never "get the page content" or "summarize this page" — state precisely what data you need.
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
name: subagent
|
|
2
|
+
description: "Workflow for sub-agents spawned by the Task tool. Routes to appropriate sub-workflow, completes task, and exits. No chat, planning, or reflection."
|
|
3
|
+
initial: route
|
|
4
|
+
max_transitions: 50
|
|
5
|
+
|
|
6
|
+
states:
|
|
7
|
+
route:
|
|
8
|
+
prompt: |
|
|
9
|
+
You are a sub-agent with a specific assigned task.
|
|
10
|
+
Route based on your task type — do NOT enter chat or planning mode.
|
|
11
|
+
|
|
12
|
+
- Read/understand/explore code → explore
|
|
13
|
+
- Write/modify code → coding
|
|
14
|
+
- Debug/investigate an issue → debugging
|
|
15
|
+
- Fix a known bug → bug_fix
|
|
16
|
+
- Look up docs or web info → research
|
|
17
|
+
- Run or write tests → testing
|
|
18
|
+
- Simple direct task (single command, quick answer) → execute
|
|
19
|
+
transitions:
|
|
20
|
+
coding: run_coding
|
|
21
|
+
explore: run_explore
|
|
22
|
+
debugging: run_debugging
|
|
23
|
+
bug_fix: run_bug_fix
|
|
24
|
+
research: run_research
|
|
25
|
+
testing: run_testing
|
|
26
|
+
execute: execute
|
|
27
|
+
|
|
28
|
+
execute:
|
|
29
|
+
prompt: |
|
|
30
|
+
Execute the assigned task directly. No sub-workflow needed.
|
|
31
|
+
When done → transition `done`.
|
|
32
|
+
transitions:
|
|
33
|
+
done: done
|
|
34
|
+
|
|
35
|
+
run_coding:
|
|
36
|
+
sub_workflow: coding
|
|
37
|
+
on_complete: done
|
|
38
|
+
on_fail: done
|
|
39
|
+
|
|
40
|
+
run_explore:
|
|
41
|
+
sub_workflow: explore
|
|
42
|
+
on_complete: done
|
|
43
|
+
on_fail: done
|
|
44
|
+
|
|
45
|
+
run_debugging:
|
|
46
|
+
sub_workflow: debugging
|
|
47
|
+
on_complete: done
|
|
48
|
+
on_fail: done
|
|
49
|
+
|
|
50
|
+
run_bug_fix:
|
|
51
|
+
sub_workflow: bug-fix
|
|
52
|
+
on_complete: done
|
|
53
|
+
on_fail: done
|
|
54
|
+
|
|
55
|
+
run_research:
|
|
56
|
+
sub_workflow: web-research
|
|
57
|
+
on_complete: done
|
|
58
|
+
on_fail: done
|
|
59
|
+
|
|
60
|
+
run_testing:
|
|
61
|
+
sub_workflow: testing
|
|
62
|
+
on_complete: done
|
|
63
|
+
on_fail: done
|
|
64
|
+
|
|
65
|
+
done:
|
|
66
|
+
terminal: true
|
|
67
|
+
outcome: complete
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
name: testing
|
|
2
|
+
description: "Testing verification sub-workflow — unit tests first, then integration"
|
|
3
|
+
initial: assess
|
|
4
|
+
max_transitions: 30
|
|
5
|
+
|
|
6
|
+
states:
|
|
7
|
+
assess:
|
|
8
|
+
prompt: |
|
|
9
|
+
Assess what verification is needed for the current change.
|
|
10
|
+
|
|
11
|
+
**Decision matrix:**
|
|
12
|
+
| Change type | Unit tests | Integration |
|
|
13
|
+
|------------------------------------|-----------|-------------|
|
|
14
|
+
| Pure logic (data, state, algorithms)| YES | only if affects UI |
|
|
15
|
+
| Logic + UI (commands, properties) | YES | YES |
|
|
16
|
+
| Pure UI (layout, visual, wiring) | no | YES |
|
|
17
|
+
|
|
18
|
+
**IMPORTANT**: Steps are strictly sequential. Never parallelize unit and integration —
|
|
19
|
+
they often share the same output binary and will conflict.
|
|
20
|
+
|
|
21
|
+
Choose transition:
|
|
22
|
+
- `has_unit` → change touches logic with existing or meaningful tests
|
|
23
|
+
- `skip_to_integration` → pure UI change, no unit-testable logic
|
|
24
|
+
- `skip_all` → trivial wiring fix fully covered by existing tests
|
|
25
|
+
transitions:
|
|
26
|
+
has_unit: unit_tests
|
|
27
|
+
skip_to_integration: check_integration
|
|
28
|
+
skip_all: done
|
|
29
|
+
|
|
30
|
+
unit_tests:
|
|
31
|
+
max_visits: 5
|
|
32
|
+
prompt: |
|
|
33
|
+
Write and run unit tests for the changed behavior.
|
|
34
|
+
|
|
35
|
+
**If bug fix — Red-Green workflow (mandatory):**
|
|
36
|
+
1. Write test targeting buggy behavior → run → confirm FAILS (red)
|
|
37
|
+
2. Apply fix → run → confirm PASSES (green)
|
|
38
|
+
|
|
39
|
+
**Otherwise:**
|
|
40
|
+
1. Find existing test files for patterns
|
|
41
|
+
2. Write tests covering new/changed behavior
|
|
42
|
+
3. Register new test class if needed
|
|
43
|
+
|
|
44
|
+
Run via `debugger` subagent to keep build output out of main context.
|
|
45
|
+
|
|
46
|
+
Choose transition:
|
|
47
|
+
- `pass` → all unit tests pass
|
|
48
|
+
- `fail` → tests failing, need fixes
|
|
49
|
+
transitions:
|
|
50
|
+
pass: check_integration
|
|
51
|
+
fail: fix_unit
|
|
52
|
+
|
|
53
|
+
fix_unit:
|
|
54
|
+
prompt: |
|
|
55
|
+
Unit tests are failing. Analyze the failures and fix the code.
|
|
56
|
+
|
|
57
|
+
Do NOT fix tests to match wrong behavior — fix the implementation.
|
|
58
|
+
After fixing, transition back to re-run unit tests.
|
|
59
|
+
|
|
60
|
+
Choose transition:
|
|
61
|
+
- `retry` → fixed, re-run unit tests
|
|
62
|
+
- `give_up` → unable to fix after multiple attempts
|
|
63
|
+
transitions:
|
|
64
|
+
retry: unit_tests
|
|
65
|
+
give_up: failed
|
|
66
|
+
|
|
67
|
+
check_integration:
|
|
68
|
+
prompt: |
|
|
69
|
+
Does this change affect what the user sees or interacts with?
|
|
70
|
+
|
|
71
|
+
- If yes AND project has a debug bridge → `need_integration`
|
|
72
|
+
- If no (pure backend/data change fully covered by unit tests) → `skip`
|
|
73
|
+
|
|
74
|
+
Choose transition:
|
|
75
|
+
- `need_integration` → must verify via integration test
|
|
76
|
+
- `skip` → unit tests are sufficient
|
|
77
|
+
transitions:
|
|
78
|
+
need_integration: integration
|
|
79
|
+
skip: done
|
|
80
|
+
|
|
81
|
+
integration:
|
|
82
|
+
max_visits: 5
|
|
83
|
+
prompt: |
|
|
84
|
+
Run integration verification.
|
|
85
|
+
|
|
86
|
+
1. Build and launch via `debugger` subagent
|
|
87
|
+
2. Simulate the actual user workflow end-to-end
|
|
88
|
+
3. Verify state changes propagated correctly (screenshots, state inspection)
|
|
89
|
+
|
|
90
|
+
**Bug fixes**: reproduce the EXACT user scenario that triggered the bug.
|
|
91
|
+
Check for regressions in related workflows.
|
|
92
|
+
|
|
93
|
+
Choose transition:
|
|
94
|
+
- `pass` → integration verified, behavior correct
|
|
95
|
+
- `fail` → integration broken, need fixes
|
|
96
|
+
transitions:
|
|
97
|
+
pass: done
|
|
98
|
+
fail: fix_integration
|
|
99
|
+
|
|
100
|
+
fix_integration:
|
|
101
|
+
prompt: |
|
|
102
|
+
Integration test failed. Analyze what broke and fix it.
|
|
103
|
+
|
|
104
|
+
After fixing, transition back to re-run integration.
|
|
105
|
+
|
|
106
|
+
Choose transition:
|
|
107
|
+
- `retry` → fixed, re-run integration tests
|
|
108
|
+
- `give_up` → unable to fix after multiple attempts
|
|
109
|
+
transitions:
|
|
110
|
+
retry: integration
|
|
111
|
+
give_up: failed
|
|
112
|
+
|
|
113
|
+
done:
|
|
114
|
+
prompt: "All required tests pass. Verification complete."
|
|
115
|
+
terminal: true
|
|
116
|
+
|
|
117
|
+
failed:
|
|
118
|
+
prompt: "Testing failed after maximum attempts. Report failures to the user."
|
|
119
|
+
terminal: true
|
|
120
|
+
outcome: fail
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
name: web-research
|
|
2
|
+
description: "Web research workflow — check existing knowledge, then delegate to web subagents"
|
|
3
|
+
initial: check_existing
|
|
4
|
+
max_transitions: 20
|
|
5
|
+
|
|
6
|
+
states:
|
|
7
|
+
check_existing:
|
|
8
|
+
prompt: |
|
|
9
|
+
Before researching externally, check what you already know:
|
|
10
|
+
|
|
11
|
+
1. Check loaded skills and MEMORY.md
|
|
12
|
+
2. Check project documentation (CLAUDE.md, README)
|
|
13
|
+
3. If answer is already available → transition `already_known`
|
|
14
|
+
4. If not enough → transition `need_research`
|
|
15
|
+
|
|
16
|
+
**When NOT to research:**
|
|
17
|
+
- Confident and routine task
|
|
18
|
+
- Answer is in a loaded skill
|
|
19
|
+
transitions:
|
|
20
|
+
already_known: apply
|
|
21
|
+
need_research: delegate
|
|
22
|
+
|
|
23
|
+
delegate:
|
|
24
|
+
prompt: |
|
|
25
|
+
Call `Skill("web-reading")` for the web access tool hierarchy.
|
|
26
|
+
|
|
27
|
+
Delegate to `researcher` subagents:
|
|
28
|
+
- Split broad questions into 3-5 narrow ones, launch in parallel
|
|
29
|
+
- Each returns only a concise answer
|
|
30
|
+
- Follow tool hierarchy from loaded web-reading skill
|
|
31
|
+
- Extract ONLY what's needed
|
|
32
|
+
|
|
33
|
+
Choose transition:
|
|
34
|
+
- `found` → got the answer, ready to apply
|
|
35
|
+
- `not_found` → could not find reliable information
|
|
36
|
+
transitions:
|
|
37
|
+
found: apply
|
|
38
|
+
not_found: done
|
|
39
|
+
|
|
40
|
+
apply:
|
|
41
|
+
prompt: |
|
|
42
|
+
Apply research results to the current task.
|
|
43
|
+
|
|
44
|
+
If this reveals a recurring knowledge gap → note it for reflection.
|
|
45
|
+
|
|
46
|
+
Choose transition:
|
|
47
|
+
- `done` → results applied or communicated to user
|
|
48
|
+
transitions:
|
|
49
|
+
done: done
|
|
50
|
+
|
|
51
|
+
done:
|
|
52
|
+
prompt: "Web research complete."
|
|
53
|
+
terminal: true
|