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.
Files changed (66) hide show
  1. package/.claude-plugin/plugin.json +13 -0
  2. package/.mcp.json +9 -0
  3. package/LICENSE +21 -0
  4. package/README.md +260 -0
  5. package/build/dashboard.d.ts +4 -0
  6. package/build/dashboard.d.ts.map +1 -0
  7. package/build/dashboard.js +91 -0
  8. package/build/dashboard.js.map +1 -0
  9. package/build/engine.d.ts +55 -0
  10. package/build/engine.d.ts.map +1 -0
  11. package/build/engine.js +486 -0
  12. package/build/engine.js.map +1 -0
  13. package/build/index.d.ts +2 -0
  14. package/build/index.d.ts.map +1 -0
  15. package/build/index.js +60 -0
  16. package/build/index.js.map +1 -0
  17. package/build/loader.d.ts +29 -0
  18. package/build/loader.d.ts.map +1 -0
  19. package/build/loader.js +166 -0
  20. package/build/loader.js.map +1 -0
  21. package/build/modifier.d.ts +42 -0
  22. package/build/modifier.d.ts.map +1 -0
  23. package/build/modifier.js +96 -0
  24. package/build/modifier.js.map +1 -0
  25. package/build/storage.d.ts +12 -0
  26. package/build/storage.d.ts.map +1 -0
  27. package/build/storage.js +62 -0
  28. package/build/storage.js.map +1 -0
  29. package/build/tools.d.ts +7 -0
  30. package/build/tools.d.ts.map +1 -0
  31. package/build/tools.js +316 -0
  32. package/build/tools.js.map +1 -0
  33. package/build/types.d.ts +417 -0
  34. package/build/types.d.ts.map +1 -0
  35. package/build/types.js +82 -0
  36. package/build/types.js.map +1 -0
  37. package/dashboard/dagre.min.js +801 -0
  38. package/dashboard/index.html +652 -0
  39. package/hooks/hooks.json +24 -0
  40. package/hooks/workflow-cleanup.sh +51 -0
  41. package/hooks/workflow-start.sh +79 -0
  42. package/package.json +44 -0
  43. package/templates/bug-fix.yaml +283 -0
  44. package/templates/code-review.yaml +164 -0
  45. package/templates/coding.yaml +176 -0
  46. package/templates/debugging.yaml +162 -0
  47. package/templates/explore.yaml +90 -0
  48. package/templates/file-code.yaml +69 -0
  49. package/templates/file-review.yaml +164 -0
  50. package/templates/investigate.yaml +84 -0
  51. package/templates/master.yaml +202 -0
  52. package/templates/new-feature.yaml +41 -0
  53. package/templates/planning.yaml +85 -0
  54. package/templates/refactoring.yaml +56 -0
  55. package/templates/reflection.yaml +61 -0
  56. package/templates/skills/architecture/SKILL.md +55 -0
  57. package/templates/skills/coding-skill-selector/SKILL.md +25 -0
  58. package/templates/skills/lang-haxe/SKILL.md +257 -0
  59. package/templates/skills/lang-python/SKILL.md +16 -0
  60. package/templates/skills/math/SKILL.md +14 -0
  61. package/templates/skills/preferences/SKILL.md +25 -0
  62. package/templates/skills/task-delegation/SKILL.md +53 -0
  63. package/templates/skills/web-reading/SKILL.md +62 -0
  64. package/templates/subagent.yaml +67 -0
  65. package/templates/testing.yaml +120 -0
  66. 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