@cliangdev/flux-plugin 0.0.0-dev.1db9c6c

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/README.md ADDED
@@ -0,0 +1,159 @@
1
+ # Flux Plugin
2
+
3
+ Agent-orchestrated, spec-driven workflow for Claude Code.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npx @cliangdev/flux-plugin
9
+ ```
10
+
11
+ This installs:
12
+ - Commands (`/flux`, `/flux:prd`, `/flux:breakdown`, `/flux:implement`)
13
+ - Skills for AI orchestration
14
+ - MCP server for project data
15
+
16
+ ### Options
17
+
18
+ ```bash
19
+ npx @cliangdev/flux-plugin --global # Install to ~/.claude (all projects)
20
+ npx @cliangdev/flux-plugin --local # Install to ./.claude (current project)
21
+ ```
22
+
23
+ ### What Gets Configured
24
+
25
+ The installer automatically:
26
+ 1. Creates plugin at `.claude/plugins/marketplaces/npm/flux-plugin/`
27
+ 2. Adds MCP server config to `.claude.json`
28
+
29
+ ## Commands
30
+
31
+ | Command | Purpose |
32
+ |---------|---------|
33
+ | `/flux` | Smart entry point - shows status and guides you to the next step |
34
+ | `/flux:prd` | Create product requirements through guided interview |
35
+ | `/flux:breakdown` | Break PRDs into epics and tasks with acceptance criteria |
36
+ | `/flux:implement` | Implement tasks with TDD workflow |
37
+
38
+ ### Typical Workflow
39
+
40
+ 1. **Start**: Run `/flux` to initialize your project
41
+ 2. **Define**: Run `/flux:prd` to create requirements through interactive Q&A
42
+ 3. **Plan**: Run `/flux:breakdown` to generate implementation tasks
43
+ 4. **Build**: Run `/flux:implement` to code with test-driven development
44
+
45
+ The orchestrator tracks your progress and always suggests the logical next step.
46
+
47
+ ## How It Works
48
+
49
+ ```mermaid
50
+ flowchart TB
51
+ subgraph User["User Intent"]
52
+ U["/flux - Start Here"]
53
+ end
54
+
55
+ subgraph Orchestrator["Flux Orchestrator"]
56
+ O{Analyze Context}
57
+ O -->|No Project| Init[Initialize Project]
58
+ O -->|No PRDs| PRD[Guide to /flux:prd]
59
+ O -->|PRD Ready| Break[Guide to /flux:breakdown]
60
+ O -->|Tasks Ready| Impl[Guide to /flux:implement]
61
+ end
62
+
63
+ subgraph PRDPhase["Requirements Phase"]
64
+ P1["/flux:prd"]
65
+ P2[Interactive Interview]
66
+ P3[Generate PRD Document]
67
+ P1 --> P2 --> P3
68
+ end
69
+
70
+ subgraph BreakdownPhase["Planning Phase"]
71
+ B1["/flux:breakdown"]
72
+ B2[Analyze PRD]
73
+ B3[Create Epics & Tasks]
74
+ B4[Define Acceptance Criteria]
75
+ B1 --> B2 --> B3 --> B4
76
+ end
77
+
78
+ subgraph ImplementPhase["Implementation Phase"]
79
+ I1["/flux:implement"]
80
+ I2[Select Next Task]
81
+ I3[TDD: Write Tests First]
82
+ I4[Implement Code]
83
+ I5[Verify & Commit]
84
+ I1 --> I2 --> I3 --> I4 --> I5
85
+ I5 -->|More Tasks| I2
86
+ end
87
+
88
+ U --> O
89
+ Init --> PRD
90
+ PRD --> P1
91
+ Break --> B1
92
+ Impl --> I1
93
+ P3 -->|PRD Complete| O
94
+ B4 -->|Breakdown Complete| O
95
+ I5 -->|All Done| Done[Project Complete]
96
+ ```
97
+
98
+ ## Features
99
+
100
+ - **Intelligent Orchestration**: Automatically guides you through the workflow based on project state
101
+ - **Spec-Driven Development**: All implementation traces back to documented requirements
102
+ - **Test-Driven Implementation**: Write tests first, then implement until they pass
103
+ - **Acceptance Criteria**: Every task has verifiable criteria for completion
104
+ - **Backend Agnostic**: Works with local SQLite or Linear for team collaboration
105
+
106
+ ## Project Structure
107
+
108
+ ```
109
+ your-project/
110
+ ├── .flux/
111
+ │ ├── project.json # Project configuration
112
+ │ ├── flux.db # Local database
113
+ │ └── docs/
114
+ │ └── prd-*/ # PRD documents
115
+ └── ...
116
+ ```
117
+
118
+ ## Updating
119
+
120
+ To update to the latest version, simply re-run the installer:
121
+
122
+ ```bash
123
+ npx @cliangdev/flux-plugin@latest --global
124
+ ```
125
+
126
+ This will:
127
+ - Update commands and skills to the latest version
128
+ - Update the MCP server configuration
129
+
130
+ Check your current version:
131
+ ```
132
+ /flux version
133
+ ```
134
+
135
+ ## Uninstall
136
+
137
+ ### Global Installation
138
+
139
+ ```bash
140
+ rm -rf ~/.claude/plugins/marketplaces/npm/flux-plugin
141
+ # Edit ~/.claude.json and remove the "flux" entry from "mcpServers"
142
+ ```
143
+
144
+ ### Local Installation
145
+
146
+ ```bash
147
+ rm -rf .claude/plugins/marketplaces/npm/flux-plugin
148
+ # Edit .claude.json and remove the "flux" entry from "mcpServers"
149
+ ```
150
+
151
+ Note: Your project data in `.flux/` is preserved. Delete it manually if you want to remove all Flux data.
152
+
153
+ ## Support
154
+
155
+ GitHub: [github.com/cliangdev/flux-plugin](https://github.com/cliangdev/flux-plugin)
156
+
157
+ ## License
158
+
159
+ MIT
@@ -0,0 +1,222 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require("fs");
4
+ const path = require("path");
5
+ const os = require("os");
6
+ const readline = require("readline");
7
+
8
+ const args = process.argv.slice(2);
9
+
10
+ if (args[0] === "serve") {
11
+ import("../dist/server/index.js").catch((err) => {
12
+ console.error("Failed to start Flux MCP server:", err.message);
13
+ process.exit(1);
14
+ });
15
+ } else {
16
+ runInstaller();
17
+ }
18
+
19
+ function runInstaller() {
20
+ const cyan = "\x1b[36m";
21
+ const green = "\x1b[32m";
22
+ const yellow = "\x1b[33m";
23
+ const dim = "\x1b[2m";
24
+ const reset = "\x1b[0m";
25
+ const pkg = require("../package.json");
26
+
27
+ const banner = `
28
+ ${cyan} ███████╗██╗ ██╗ ██╗██╗ ██╗
29
+ ██╔════╝██║ ██║ ██║╚██╗██╔╝
30
+ █████╗ ██║ ██║ ██║ ╚███╔╝
31
+ ██╔══╝ ██║ ██║ ██║ ██╔██╗
32
+ ██║ ███████╗╚██████╔╝██╔╝ ██╗
33
+ ╚═╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═╝${reset}
34
+
35
+ Flux Plugin ${dim}v${pkg.version}${reset}
36
+ AI-first workflow orchestration for Claude Code
37
+ `;
38
+
39
+ const hasGlobal = args.includes("--global") || args.includes("-g");
40
+ const hasLocal = args.includes("--local") || args.includes("-l");
41
+ const hasHelp = args.includes("--help") || args.includes("-h");
42
+
43
+ console.log(banner);
44
+
45
+ if (hasHelp) {
46
+ console.log(` ${yellow}Usage:${reset} npx @cliangdev/flux-plugin [options]
47
+
48
+ ${yellow}Options:${reset}
49
+ ${cyan}-g, --global${reset} Install globally (to ~/.claude)
50
+ ${cyan}-l, --local${reset} Install locally (to ./.claude in current directory)
51
+ ${cyan}-h, --help${reset} Show this help message
52
+
53
+ ${yellow}Examples:${reset}
54
+ ${dim}# Interactive installation${reset}
55
+ npx @cliangdev/flux-plugin
56
+
57
+ ${dim}# Install globally (all projects)${reset}
58
+ npx @cliangdev/flux-plugin --global
59
+
60
+ ${dim}# Install locally (current project only)${reset}
61
+ npx @cliangdev/flux-plugin --local
62
+ `);
63
+ process.exit(0);
64
+ }
65
+
66
+ function copyDir(src, dest) {
67
+ fs.mkdirSync(dest, { recursive: true });
68
+ const entries = fs.readdirSync(src, { withFileTypes: true });
69
+
70
+ for (const entry of entries) {
71
+ const srcPath = path.join(src, entry.name);
72
+ const destPath = path.join(dest, entry.name);
73
+
74
+ if (entry.isDirectory()) {
75
+ copyDir(srcPath, destPath);
76
+ } else {
77
+ fs.copyFileSync(srcPath, destPath);
78
+ }
79
+ }
80
+ }
81
+
82
+ function readJson(filePath) {
83
+ if (fs.existsSync(filePath)) {
84
+ try {
85
+ return JSON.parse(fs.readFileSync(filePath, "utf8"));
86
+ } catch {
87
+ return {};
88
+ }
89
+ }
90
+ return {};
91
+ }
92
+
93
+ function writeJson(filePath, data) {
94
+ fs.writeFileSync(filePath, JSON.stringify(data, null, 2) + "\n");
95
+ }
96
+
97
+ function install(isGlobal) {
98
+ const src = path.join(__dirname, "..");
99
+ const claudeDir = isGlobal
100
+ ? path.join(os.homedir(), ".claude")
101
+ : path.join(process.cwd(), ".claude");
102
+ const pluginDir = path.join(claudeDir, "plugins", "marketplaces", "npm", "flux-plugin");
103
+ const locationLabel = isGlobal ? "~/.claude" : "./.claude";
104
+
105
+ console.log(` Installing to ${cyan}${locationLabel}/plugins/marketplaces/npm/flux-plugin${reset}\n`);
106
+
107
+ fs.mkdirSync(pluginDir, { recursive: true });
108
+
109
+ const pluginConfigDir = path.join(pluginDir, ".claude-plugin");
110
+ fs.mkdirSync(pluginConfigDir, { recursive: true });
111
+ writeJson(path.join(pluginConfigDir, "plugin.json"), {
112
+ name: "flux-plugin",
113
+ description: "AI-first workflow orchestration for spec-driven development",
114
+ version: pkg.version,
115
+ author: {
116
+ name: "cliangdev",
117
+ url: "https://github.com/cliangdev/flux-plugin"
118
+ }
119
+ });
120
+ console.log(` ${green}✓${reset} Created plugin config`);
121
+
122
+ const commandsSrc = path.join(src, "commands");
123
+ if (fs.existsSync(commandsSrc)) {
124
+ const commandsDest = path.join(pluginDir, "commands");
125
+ fs.mkdirSync(commandsDest, { recursive: true });
126
+
127
+ const commandFiles = fs.readdirSync(commandsSrc);
128
+ for (const file of commandFiles) {
129
+ if (file.endsWith(".md")) {
130
+ fs.copyFileSync(
131
+ path.join(commandsSrc, file),
132
+ path.join(commandsDest, file)
133
+ );
134
+ const name = file.replace(".md", "");
135
+ console.log(` ${green}✓${reset} Installed command: /${name}`);
136
+ }
137
+ }
138
+ }
139
+
140
+ const skillsSrc = path.join(src, "skills");
141
+ if (fs.existsSync(skillsSrc)) {
142
+ const skillsDest = path.join(pluginDir, "skills");
143
+ fs.mkdirSync(skillsDest, { recursive: true });
144
+
145
+ const skillDirs = fs.readdirSync(skillsSrc, { withFileTypes: true });
146
+ for (const dir of skillDirs) {
147
+ if (dir.isDirectory()) {
148
+ copyDir(
149
+ path.join(skillsSrc, dir.name),
150
+ path.join(skillsDest, dir.name)
151
+ );
152
+ console.log(` ${green}✓${reset} Installed skill: ${dir.name}`);
153
+ }
154
+ }
155
+ }
156
+
157
+ const claudeJsonPath = isGlobal
158
+ ? path.join(os.homedir(), ".claude.json")
159
+ : path.join(process.cwd(), ".claude.json");
160
+
161
+ const claudeJson = readJson(claudeJsonPath);
162
+
163
+ if (!claudeJson.mcpServers) {
164
+ claudeJson.mcpServers = {};
165
+ }
166
+
167
+ claudeJson.mcpServers.flux = {
168
+ command: "npx",
169
+ args: ["-y", "@cliangdev/flux-plugin", "serve"],
170
+ };
171
+
172
+ writeJson(claudeJsonPath, claudeJson);
173
+ console.log(
174
+ ` ${green}✓${reset} Configured MCP server in ${isGlobal ? "~/.claude.json" : "./.claude.json"}`
175
+ );
176
+
177
+ const versionFile = path.join(pluginDir, "version");
178
+ fs.writeFileSync(versionFile, pkg.version);
179
+
180
+ console.log(`
181
+ ${green}Done!${reset} Restart Claude Code and run ${cyan}/flux${reset} to get started.
182
+
183
+ ${dim}Commands available:${reset}
184
+ /flux - Project status and guidance
185
+ /flux:prd - Create or refine PRDs
186
+ /flux:breakdown - Break PRDs into epics and tasks
187
+ /flux:implement - Implement tasks with TDD
188
+
189
+ ${dim}Learn more:${reset} https://github.com/cliangdev/flux-plugin
190
+ `);
191
+ }
192
+
193
+ function promptLocation() {
194
+ const rl = readline.createInterface({
195
+ input: process.stdin,
196
+ output: process.stdout,
197
+ });
198
+
199
+ console.log(` ${yellow}Where would you like to install?${reset}
200
+
201
+ ${cyan}1${reset}) Global ${dim}(~/.claude)${reset} - available in all projects
202
+ ${cyan}2${reset}) Local ${dim}(./.claude)${reset} - this project only
203
+ `);
204
+
205
+ rl.question(` Choice ${dim}[1]${reset}: `, (answer) => {
206
+ rl.close();
207
+ const choice = answer.trim() || "1";
208
+ install(choice !== "2");
209
+ });
210
+ }
211
+
212
+ if (hasGlobal && hasLocal) {
213
+ console.error(` ${yellow}Cannot specify both --global and --local${reset}`);
214
+ process.exit(1);
215
+ } else if (hasGlobal) {
216
+ install(true);
217
+ } else if (hasLocal) {
218
+ install(false);
219
+ } else {
220
+ promptLocation();
221
+ }
222
+ }
@@ -0,0 +1,263 @@
1
+ ---
2
+ name: flux:breakdown
3
+ description: Break approved PRD into dependency-ordered epics and tasks
4
+ allowed-tools: mcp__flux__*, Read, AskUserQuestion
5
+ ---
6
+
7
+ # PRD Breakdown
8
+
9
+ You are the Flux breakdown orchestrator. Your job is to break an approved PRD into well-structured, dependency-ordered epics and tasks.
10
+
11
+ ## Mode Detection
12
+
13
+ Check if arguments were provided:
14
+ - `/flux:breakdown` - Select from approved PRDs
15
+ - `/flux:breakdown {ref}` - Break down specific PRD (e.g., `FLUX-P1`)
16
+
17
+ ## Pre-checks
18
+
19
+ 1. Call `get_project_context` to ensure Flux is initialized
20
+ - If not initialized, tell user: "Run `/flux` first to initialize the project."
21
+
22
+ 2. If no ref provided, call `query_entities` with type=prd, status=APPROVED
23
+ - If no approved PRDs, tell user: "No approved PRDs found. Approve a PRD first or run `/flux:prd` to create one."
24
+ - If multiple approved PRDs, use AskUserQuestion to let user select which one
25
+
26
+ 3. If ref provided, call `get_entity` with the ref
27
+ - Verify status is APPROVED
28
+ - If not approved: "PRD {ref} is in {status} status. Only APPROVED PRDs can be broken down."
29
+
30
+ ## Confidence-Based Autonomy
31
+
32
+ Use confidence levels to determine when to proceed autonomously vs. ask for confirmation:
33
+
34
+ | Confidence | Behavior | When |
35
+ |------------|----------|------|
36
+ | **High (>80%)** | Auto-proceed, inform user | Clear PRD, obvious epic structure, standard patterns |
37
+ | **Medium (50-80%)** | Show plan, ask to confirm | Some ambiguity, multiple valid approaches |
38
+ | **Low (<50%)** | Ask clarifying questions | Unclear requirements, unfamiliar domain, contradictions |
39
+
40
+ **High confidence indicators:**
41
+ - PRD has clear feature list with priorities
42
+ - Dependencies are explicit or obvious
43
+ - Standard tech stack with known patterns
44
+ - No conflicting requirements
45
+
46
+ **Low confidence indicators:**
47
+ - Vague or incomplete PRD sections
48
+ - Multiple valid ways to structure epics
49
+ - Unfamiliar technology or domain
50
+ - Conflicting or ambiguous requirements
51
+
52
+ **When confident, proceed like this:**
53
+ ```
54
+ Analyzing PRD [FP-P3]...
55
+
56
+ Creating 4 epics in dependency order:
57
+ - FP-E1: Core Infrastructure (foundation)
58
+ - FP-E2: Data Layer (depends on E1)
59
+ - FP-E3: API Layer (depends on E2)
60
+ - FP-E4: UI Components (depends on E3)
61
+
62
+ [Proceeds to create epics and tasks...]
63
+ ```
64
+
65
+ **When uncertain, ask for clarification:**
66
+ ```
67
+ I see two ways to structure the auth feature:
68
+
69
+ 1. Single "Authentication" epic with login, logout, session tasks
70
+ 2. Separate "Login Flow" and "Session Management" epics
71
+
72
+ Which approach do you prefer?
73
+ ```
74
+
75
+ ## Breakdown Workflow
76
+
77
+ ### Step 1: Read PRD Content
78
+
79
+ 1. Get PRD entity with `get_entity` including `include: ['epics']`
80
+ 2. Read full PRD content from `folder_path + '/prd.md'` using Read tool
81
+ 3. If PRD already has epics, inform user:
82
+ - "This PRD already has {count} epics. Continue adding more or start fresh?"
83
+ - Use AskUserQuestion with options: "Add more epics", "View existing", "Start fresh (delete existing)"
84
+
85
+ ### Step 2: Analyze & Identify Epics
86
+
87
+ Analyze the PRD content to identify logical work packages:
88
+
89
+ 1. **Group features** into cohesive epics:
90
+ - Each P0 feature often maps to 1-2 epics
91
+ - Shared infrastructure (auth, database setup) = separate epic
92
+ - Consider technical vs. functional groupings
93
+
94
+ 2. **Identify dependencies** between epics:
95
+ - Infrastructure epics come first (database, auth)
96
+ - Feature epics depend on infrastructure
97
+ - Some features can be parallelized
98
+
99
+ 3. **Create epic structure** mentally before presenting:
100
+ ```
101
+ Epic 1: Project Setup (no deps)
102
+ Epic 2: Database Schema (depends on 1)
103
+ Epic 3: Core Feature A (depends on 2)
104
+ Epic 4: Core Feature B (depends on 2) ← can parallel with 3
105
+ ```
106
+
107
+ ### Step 3: Present Epic Structure (Confidence-Based)
108
+
109
+ **If high confidence (>80%):** Show structure and proceed to create epics immediately.
110
+
111
+ ```
112
+ ## Epic Breakdown
113
+
114
+ Creating 4 epics for [PRD Title]:
115
+
116
+ 1. **{Title}** - {goal} (foundation)
117
+ 2. **{Title}** - {goal} → depends on Epic 1
118
+ 3. **{Title}** - {goal} → depends on Epic 2
119
+ 4. **{Title}** - {goal} → depends on Epic 2 (parallel with 3)
120
+
121
+ Creating epics...
122
+ ```
123
+
124
+ **If medium/low confidence:** Show structure and ask for confirmation.
125
+
126
+ ```
127
+ ## Proposed Epic Breakdown
128
+
129
+ Based on the PRD, I recommend these epics:
130
+
131
+ ### Epic 1: {Title}
132
+ **Goal:** {one sentence}
133
+ **Depends on:** None (foundation)
134
+
135
+ ### Epic 2: {Title}
136
+ **Goal:** {one sentence}
137
+ **Depends on:** Epic 1
138
+
139
+ ...
140
+
141
+ Ready to create these epics?
142
+ ```
143
+
144
+ Use AskUserQuestion only when uncertain:
145
+ - Create all epics (Recommended)
146
+ - Modify structure first
147
+ - Add/remove epics
148
+
149
+ ### Step 4: Create Epics
150
+
151
+ For each approved epic:
152
+
153
+ 1. Call `create_epic` with:
154
+ - `prd_ref`: The PRD reference
155
+ - `title`: Epic title
156
+ - `description`: Goal and scope summary
157
+
158
+ 2. Call `add_criteria` for each epic-level acceptance criterion
159
+ - Use `[auto]` or `[manual]` prefix (see Test Type Convention below)
160
+
161
+ 3. Call `add_dependency` to set up epic dependencies
162
+ - `ref`: The dependent epic
163
+ - `depends_on_ref`: The prerequisite epic
164
+
165
+ ### Step 5: Task Breakdown (Confidence-Based)
166
+
167
+ For each epic, break down into tasks:
168
+
169
+ 1. Analyze epic scope and identify 3-7 tasks:
170
+ - Start with data/schema tasks
171
+ - Then business logic
172
+ - Then API/interface
173
+ - Finally integration/wiring
174
+
175
+ 2. **If high confidence:** Create tasks immediately, show progress.
176
+
177
+ ```
178
+ Breaking down {Epic Title} into tasks...
179
+
180
+ Created:
181
+ - FP-T1: {title} (3 criteria)
182
+ - FP-T2: {title} (2 criteria)
183
+ - FP-T3: {title} (2 criteria)
184
+ ```
185
+
186
+ 3. **If medium/low confidence:** Present task structure and confirm.
187
+
188
+ ```
189
+ ## Tasks for {Epic Title}
190
+
191
+ 1. {Task title} - {brief description}
192
+ - [auto] {criterion 1}
193
+ - [auto] {criterion 2}
194
+
195
+ 2. {Task title} - {brief description}
196
+ - [auto] {criterion}
197
+ - [manual] {criterion} → Verify: {steps}
198
+
199
+ Create these tasks?
200
+ ```
201
+
202
+ 4. Create tasks:
203
+ - Call `create_task` with epic_ref, title, description, priority
204
+ - Call `add_criteria` for each task criterion (1-3 per task)
205
+
206
+ ### Step 6: Completion
207
+
208
+ After all epics and tasks are created:
209
+
210
+ 1. Update PRD status: Call `update_status` with ref and status=BREAKDOWN_READY
211
+
212
+ 2. Show summary:
213
+ ```
214
+ ## Breakdown Complete
215
+
216
+ PRD: {title} (now BREAKDOWN_READY)
217
+
218
+ Created:
219
+ - {X} Epics
220
+ - {Y} Tasks
221
+ - {Z} Acceptance Criteria
222
+
223
+ Dependency Order:
224
+ 1. {Epic 1} - {status}
225
+ 2. {Epic 2} - depends on {Epic 1}
226
+ ...
227
+
228
+ Next: Run `/flux:implement` to start working on tasks.
229
+ ```
230
+
231
+ ## Test Type Convention
232
+
233
+ Mark each acceptance criterion with its test type as a text prefix:
234
+
235
+ - **`[auto]`** - Verified by automated test (unit, integration, e2e)
236
+ - **`[manual]`** - Requires human verification
237
+
238
+ For manual criteria, include verification steps after `→ Verify:`:
239
+ ```
240
+ [manual] Dashboard displays correctly on mobile → Verify: Open on phone, check layout
241
+ ```
242
+
243
+ ### Examples
244
+
245
+ Good criteria:
246
+ - `[auto] API returns 401 for invalid credentials`
247
+ - `[auto] User record is created in database`
248
+ - `[manual] Error message is user-friendly → Verify: Read message aloud, is it clear?`
249
+ - `[manual] Loading animation feels smooth → Verify: Test on slow network`
250
+
251
+ Bad criteria:
252
+ - `User authentication works` (not specific, no test type)
253
+ - `The feature is complete` (not testable)
254
+
255
+ ## Guidelines
256
+
257
+ - **Right-size epics**: 3-7 tasks, 1-3 days of work
258
+ - **Right-size tasks**: One commit, 30min-4hrs, clear "done" state
259
+ - **1-3 criteria per task**: Keep tasks focused and testable
260
+ - **Dependencies first**: Foundation epics before feature epics
261
+ - **Prefer [auto]**: Automated tests where possible
262
+ - **Be specific**: Criteria should be objectively verifiable
263
+ - **Allow iteration**: User can modify structure at each step