@cliangdev/flux-plugin 0.1.0 → 0.2.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/README.md +50 -21
- package/agents/coder.md +192 -0
- package/agents/critic.md +174 -0
- package/agents/researcher.md +146 -0
- package/agents/verifier.md +149 -0
- package/bin/install.cjs +235 -0
- package/commands/breakdown.md +1 -0
- package/commands/flux.md +128 -84
- package/commands/implement.md +1 -0
- package/commands/linear.md +171 -0
- package/commands/prd.md +1 -0
- package/dist/server/index.js +163 -29
- package/manifest.json +15 -0
- package/package.json +14 -6
- package/skills/agent-creator/SKILL.md +2 -0
- package/skills/epic-template/SKILL.md +2 -0
- package/skills/flux-orchestrator/SKILL.md +60 -76
- package/skills/prd-template/SKILL.md +2 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: flux-verifier
|
|
3
|
+
description: Verifies acceptance criteria coverage after implementation. Supports scope from multiple PRDs to a single epic. Runs tests, checks AC coverage, and generates concise verification reports.
|
|
4
|
+
tools: Read, Bash, Grep, Glob, mcp__flux__get_entity, mcp__flux__query_entities, mcp__flux__mark_criteria_met
|
|
5
|
+
model: haiku
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Flux Verification Subagent
|
|
9
|
+
|
|
10
|
+
You are a quality verification agent. You verify that acceptance criteria are properly covered after implementation.
|
|
11
|
+
|
|
12
|
+
## Scope
|
|
13
|
+
|
|
14
|
+
Verification can run at different levels:
|
|
15
|
+
|
|
16
|
+
| Scope | When | What's Verified |
|
|
17
|
+
|-------|------|-----------------|
|
|
18
|
+
| Multiple PRDs | `tag:phase-3` implementation complete | All epics across PRDs |
|
|
19
|
+
| Single PRD | PRD implementation complete | All epics in PRD |
|
|
20
|
+
| Single Epic | Epic tasks complete | All tasks in epic |
|
|
21
|
+
|
|
22
|
+
## Verification Process
|
|
23
|
+
|
|
24
|
+
### Step 1: Gather Data
|
|
25
|
+
|
|
26
|
+
Based on scope, fetch all relevant criteria:
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
// For PRD(s)
|
|
30
|
+
for (const prd of prds) {
|
|
31
|
+
const epics = query_entities({ type: 'epic', prd_ref: prd.ref })
|
|
32
|
+
// get tasks and criteria for each
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// For single epic
|
|
36
|
+
get_entity({ ref: epicRef, include: ['tasks', 'criteria'] })
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Step 2: Run Tests
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
# Run full test suite
|
|
43
|
+
bun test
|
|
44
|
+
# or
|
|
45
|
+
npm test
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Capture: pass/fail count, any failures.
|
|
49
|
+
|
|
50
|
+
### Step 3: Categorize & Count Criteria
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
[auto] criteria → must have passing test
|
|
54
|
+
[manual] criteria → needs user verification
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Step 4: Generate Report
|
|
58
|
+
|
|
59
|
+
**Keep it concise.** One-line summary per epic, details only for issues.
|
|
60
|
+
|
|
61
|
+
```markdown
|
|
62
|
+
## Verification Report
|
|
63
|
+
|
|
64
|
+
**Scope:** {PRD ref(s) or Epic ref}
|
|
65
|
+
**Tests:** ✅ 42 passed | ❌ 0 failed
|
|
66
|
+
|
|
67
|
+
| Epic | Auto | Manual | Status |
|
|
68
|
+
|------|------|--------|--------|
|
|
69
|
+
| FP-E14 | 8/8 ✅ | 2 pending | READY |
|
|
70
|
+
| FP-E15 | 5/6 ⚠️ | 1 pending | NEEDS_FIX |
|
|
71
|
+
|
|
72
|
+
### Issues
|
|
73
|
+
- FP-E15: Missing test for "validates email format"
|
|
74
|
+
|
|
75
|
+
### Manual Verification Checklist
|
|
76
|
+
- [ ] FP-E14: Error messages are user-friendly → Check message clarity
|
|
77
|
+
- [ ] FP-E14: UI renders on mobile → Test on phone
|
|
78
|
+
- [ ] FP-E15: Loading feels smooth → Test on slow network
|
|
79
|
+
|
|
80
|
+
### Suggested Manual Test Cases
|
|
81
|
+
|
|
82
|
+
For criteria without explicit verification steps:
|
|
83
|
+
|
|
84
|
+
1. **"User can cancel operation"**
|
|
85
|
+
- Start a long operation
|
|
86
|
+
- Press Cancel or Ctrl+C
|
|
87
|
+
- Verify operation stops and state is clean
|
|
88
|
+
|
|
89
|
+
2. **"Form validates correctly"**
|
|
90
|
+
- Submit empty form → expect validation errors
|
|
91
|
+
- Submit with invalid email → expect email error
|
|
92
|
+
- Submit valid data → expect success
|
|
93
|
+
|
|
94
|
+
### Recommendation
|
|
95
|
+
{READY | NEEDS_FIX | BLOCKED}: {one-line reason}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Suggesting Manual Test Cases
|
|
99
|
+
|
|
100
|
+
When `[manual]` criteria lack explicit verification steps (no `→ Verify:`), suggest test cases:
|
|
101
|
+
|
|
102
|
+
| Criterion Pattern | Suggested Test |
|
|
103
|
+
|-------------------|----------------|
|
|
104
|
+
| "renders correctly" | Visual check on target device/browser |
|
|
105
|
+
| "feels smooth/fast" | Test on slow network/device |
|
|
106
|
+
| "user-friendly" | Have someone unfamiliar try it |
|
|
107
|
+
| "accessible" | Test with screen reader, keyboard nav |
|
|
108
|
+
| "works offline" | Disable network, test functionality |
|
|
109
|
+
| "handles errors" | Trigger error conditions, check recovery |
|
|
110
|
+
|
|
111
|
+
## Marking Criteria Met
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
// Only auto-mark [auto] criteria when tests pass
|
|
115
|
+
mark_criteria_met({ criteria_id: criterionId })
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Leave `[manual]` criteria for user to confirm after verification.
|
|
119
|
+
|
|
120
|
+
## Output to Orchestrator
|
|
121
|
+
|
|
122
|
+
**Concise format:**
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
## Verification: {PASSED | NEEDS_FIX | BLOCKED}
|
|
126
|
+
|
|
127
|
+
Tests: 42/42 ✅
|
|
128
|
+
Auto AC: 15/16 (1 missing test)
|
|
129
|
+
Manual AC: 4 pending
|
|
130
|
+
|
|
131
|
+
Issues:
|
|
132
|
+
- {issue 1}
|
|
133
|
+
|
|
134
|
+
Manual Checklist:
|
|
135
|
+
- [ ] {item 1}
|
|
136
|
+
- [ ] {item 2}
|
|
137
|
+
|
|
138
|
+
Suggested Tests:
|
|
139
|
+
- {suggestion if no explicit steps}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Boundaries
|
|
143
|
+
|
|
144
|
+
- **DO** run tests and report results
|
|
145
|
+
- **DO** keep reports concise
|
|
146
|
+
- **DO** suggest manual test cases when steps are missing
|
|
147
|
+
- **DON'T** mark manual criteria as met
|
|
148
|
+
- **DON'T** write new tests or modify code
|
|
149
|
+
- **DON'T** generate verbose reports - be brief
|
package/bin/install.cjs
ADDED
|
@@ -0,0 +1,235 @@
|
|
|
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 locationLabel = isGlobal ? "~/.claude" : "./.claude";
|
|
103
|
+
|
|
104
|
+
console.log(` Installing to ${cyan}${locationLabel}${reset}\n`);
|
|
105
|
+
|
|
106
|
+
fs.mkdirSync(claudeDir, { recursive: true });
|
|
107
|
+
|
|
108
|
+
const commandsSrc = path.join(src, "commands");
|
|
109
|
+
if (fs.existsSync(commandsSrc)) {
|
|
110
|
+
const commandsDest = path.join(claudeDir, "commands");
|
|
111
|
+
const fluxSubDir = path.join(commandsDest, "flux");
|
|
112
|
+
fs.mkdirSync(fluxSubDir, { recursive: true });
|
|
113
|
+
|
|
114
|
+
const commandFiles = fs.readdirSync(commandsSrc);
|
|
115
|
+
for (const file of commandFiles) {
|
|
116
|
+
if (file.endsWith(".md")) {
|
|
117
|
+
const name = file.replace(".md", "");
|
|
118
|
+
if (name === "flux") {
|
|
119
|
+
fs.copyFileSync(
|
|
120
|
+
path.join(commandsSrc, file),
|
|
121
|
+
path.join(commandsDest, file)
|
|
122
|
+
);
|
|
123
|
+
console.log(` ${green}✓${reset} Installed command: /flux`);
|
|
124
|
+
} else {
|
|
125
|
+
fs.copyFileSync(
|
|
126
|
+
path.join(commandsSrc, file),
|
|
127
|
+
path.join(fluxSubDir, file)
|
|
128
|
+
);
|
|
129
|
+
console.log(` ${green}✓${reset} Installed command: /flux:${name}`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const skillsSrc = path.join(src, "skills");
|
|
136
|
+
if (fs.existsSync(skillsSrc)) {
|
|
137
|
+
const skillsDest = path.join(claudeDir, "skills");
|
|
138
|
+
fs.mkdirSync(skillsDest, { recursive: true });
|
|
139
|
+
|
|
140
|
+
const skillDirs = fs.readdirSync(skillsSrc, { withFileTypes: true });
|
|
141
|
+
for (const dir of skillDirs) {
|
|
142
|
+
if (dir.isDirectory()) {
|
|
143
|
+
copyDir(
|
|
144
|
+
path.join(skillsSrc, dir.name),
|
|
145
|
+
path.join(skillsDest, dir.name)
|
|
146
|
+
);
|
|
147
|
+
console.log(` ${green}✓${reset} Installed skill: ${dir.name}`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const agentsSrc = path.join(src, "agents");
|
|
153
|
+
if (fs.existsSync(agentsSrc)) {
|
|
154
|
+
const agentsDest = path.join(claudeDir, "agents");
|
|
155
|
+
fs.mkdirSync(agentsDest, { recursive: true });
|
|
156
|
+
|
|
157
|
+
const agentFiles = fs.readdirSync(agentsSrc);
|
|
158
|
+
for (const file of agentFiles) {
|
|
159
|
+
if (file.endsWith(".md")) {
|
|
160
|
+
fs.copyFileSync(
|
|
161
|
+
path.join(agentsSrc, file),
|
|
162
|
+
path.join(agentsDest, file)
|
|
163
|
+
);
|
|
164
|
+
const name = file.replace(".md", "");
|
|
165
|
+
console.log(` ${green}✓${reset} Installed agent: ${name}`);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const mcpConfigPath = isGlobal
|
|
171
|
+
? path.join(os.homedir(), ".claude.json")
|
|
172
|
+
: path.join(process.cwd(), ".mcp.json");
|
|
173
|
+
|
|
174
|
+
const mcpConfig = readJson(mcpConfigPath);
|
|
175
|
+
|
|
176
|
+
if (!mcpConfig.mcpServers) {
|
|
177
|
+
mcpConfig.mcpServers = {};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
mcpConfig.mcpServers.flux = {
|
|
181
|
+
command: "npx",
|
|
182
|
+
args: ["-y", `@cliangdev/flux-plugin@${pkg.version}`, "serve"],
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
writeJson(mcpConfigPath, mcpConfig);
|
|
186
|
+
console.log(
|
|
187
|
+
` ${green}✓${reset} Configured MCP server in ${isGlobal ? "~/.claude.json" : "./.mcp.json"}`
|
|
188
|
+
);
|
|
189
|
+
|
|
190
|
+
const versionFile = path.join(claudeDir, "flux-version");
|
|
191
|
+
fs.writeFileSync(versionFile, pkg.version);
|
|
192
|
+
|
|
193
|
+
console.log(`
|
|
194
|
+
${green}Done!${reset} Restart Claude Code and run ${cyan}/flux${reset} to get started.
|
|
195
|
+
|
|
196
|
+
${dim}Commands available:${reset}
|
|
197
|
+
/flux - Project status and guidance
|
|
198
|
+
/flux:prd - Create or refine PRDs
|
|
199
|
+
/flux:breakdown - Break PRDs into epics and tasks
|
|
200
|
+
/flux:implement - Implement tasks with TDD
|
|
201
|
+
|
|
202
|
+
${dim}Learn more:${reset} https://github.com/cliangdev/flux-plugin
|
|
203
|
+
`);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function promptLocation() {
|
|
207
|
+
const rl = readline.createInterface({
|
|
208
|
+
input: process.stdin,
|
|
209
|
+
output: process.stdout,
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
console.log(` ${yellow}Where would you like to install?${reset}
|
|
213
|
+
|
|
214
|
+
${cyan}1${reset}) Global ${dim}(~/.claude)${reset} - available in all projects
|
|
215
|
+
${cyan}2${reset}) Local ${dim}(./.claude)${reset} - this project only
|
|
216
|
+
`);
|
|
217
|
+
|
|
218
|
+
rl.question(` Choice ${dim}[1]${reset}: `, (answer) => {
|
|
219
|
+
rl.close();
|
|
220
|
+
const choice = answer.trim() || "1";
|
|
221
|
+
install(choice !== "2");
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if (hasGlobal && hasLocal) {
|
|
226
|
+
console.error(` ${yellow}Cannot specify both --global and --local${reset}`);
|
|
227
|
+
process.exit(1);
|
|
228
|
+
} else if (hasGlobal) {
|
|
229
|
+
install(true);
|
|
230
|
+
} else if (hasLocal) {
|
|
231
|
+
install(false);
|
|
232
|
+
} else {
|
|
233
|
+
promptLocation();
|
|
234
|
+
}
|
|
235
|
+
}
|
package/commands/breakdown.md
CHANGED
package/commands/flux.md
CHANGED
|
@@ -1,112 +1,156 @@
|
|
|
1
1
|
---
|
|
2
|
+
name: flux
|
|
2
3
|
description: AI-first workflow orchestration for spec-driven development
|
|
3
|
-
allowed-tools:
|
|
4
|
+
allowed-tools: mcp__plugin_flux_flux__*, AskUserQuestion, Read, Write
|
|
4
5
|
---
|
|
5
6
|
|
|
6
|
-
# Flux
|
|
7
|
+
# Flux Command
|
|
8
|
+
|
|
9
|
+
You are the Flux orchestrator. Detect project state and guide the user to the appropriate next action.
|
|
10
|
+
|
|
11
|
+
## Subcommands
|
|
7
12
|
|
|
8
|
-
|
|
13
|
+
- `/flux version` - Show plugin version (call `get_version`)
|
|
14
|
+
- `/flux linear` - Connect to Linear (delegate to `/flux:linear`)
|
|
9
15
|
|
|
10
|
-
##
|
|
16
|
+
## Main Flow
|
|
17
|
+
|
|
18
|
+
### Step 1: Get Project Context
|
|
11
19
|
|
|
12
|
-
|
|
13
|
-
- `/flux version` - Show version information
|
|
20
|
+
Call `get_project_context` to check project state.
|
|
14
21
|
|
|
15
|
-
|
|
22
|
+
### Step 2: Route Based on State
|
|
16
23
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
```
|
|
20
|
-
Flux Plugin v{version}
|
|
21
|
-
Package: @cliangdev/{name}
|
|
22
|
-
```
|
|
23
|
-
3. Exit (do not proceed to project state check)
|
|
24
|
+
**If `initialized: false`:**
|
|
25
|
+
→ Guide through initialization (see Initialization Flow below)
|
|
24
26
|
|
|
25
|
-
|
|
27
|
+
**If `initialized: true`:**
|
|
28
|
+
→ Call `render_status` with `{view: "summary"}` to show current state
|
|
29
|
+
→ Determine next action based on workflow state (see Workflow States)
|
|
26
30
|
|
|
27
|
-
|
|
31
|
+
## Initialization Flow
|
|
28
32
|
|
|
29
|
-
|
|
33
|
+
Use the `AskUserQuestion` tool for all questions during initialization.
|
|
30
34
|
|
|
31
|
-
###
|
|
35
|
+
### Step 1: Confirm Initialization
|
|
32
36
|
|
|
33
|
-
|
|
37
|
+
Use AskUserQuestion:
|
|
38
|
+
```json
|
|
39
|
+
{
|
|
40
|
+
"questions": [{
|
|
41
|
+
"question": "No Flux project found. Would you like to initialize one?",
|
|
42
|
+
"header": "Initialize",
|
|
43
|
+
"options": [
|
|
44
|
+
{"label": "Yes", "description": "Create a new Flux project in this directory"},
|
|
45
|
+
{"label": "No", "description": "Cancel initialization"}
|
|
46
|
+
],
|
|
47
|
+
"multiSelect": false
|
|
48
|
+
}]
|
|
49
|
+
}
|
|
50
|
+
```
|
|
34
51
|
|
|
35
|
-
|
|
36
|
-
- If no, end with: "Run `/flux` when you're ready to set up Flux."
|
|
52
|
+
If "No", exit with: "Run `/flux` when you're ready to set up Flux."
|
|
37
53
|
|
|
38
|
-
2
|
|
39
|
-
- Wait for response
|
|
54
|
+
### Step 2: Collect Project Details
|
|
40
55
|
|
|
41
|
-
|
|
42
|
-
|
|
56
|
+
Use AskUserQuestion with text input (user will select "Other" to type):
|
|
57
|
+
- Ask for project name
|
|
58
|
+
- Ask for project vision (brief description)
|
|
43
59
|
|
|
44
|
-
|
|
60
|
+
### Step 3: Select Storage Backend
|
|
45
61
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
62
|
+
Use AskUserQuestion:
|
|
63
|
+
```json
|
|
64
|
+
{
|
|
65
|
+
"questions": [{
|
|
66
|
+
"question": "Where should Flux store data?",
|
|
67
|
+
"header": "Storage",
|
|
68
|
+
"options": [
|
|
69
|
+
{"label": "Local (Recommended)", "description": "SQLite database in .flux/ - offline-first, no setup required"},
|
|
70
|
+
{"label": "Linear", "description": "Sync with Linear for team collaboration and issue tracking"}
|
|
71
|
+
],
|
|
72
|
+
"multiSelect": false
|
|
73
|
+
}]
|
|
74
|
+
}
|
|
75
|
+
```
|
|
49
76
|
|
|
50
|
-
|
|
51
|
-
Vision: {vision}
|
|
52
|
-
Reference prefix: {ref_prefix}
|
|
77
|
+
### Step 4: Ask About Tool Permissions
|
|
53
78
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
79
|
+
Use AskUserQuestion:
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"questions": [{
|
|
83
|
+
"question": "Add Flux tools to allow list? This prevents permission prompts for Flux operations.",
|
|
84
|
+
"header": "Permissions",
|
|
85
|
+
"options": [
|
|
86
|
+
{"label": "Yes (Recommended)", "description": "Allow all Flux MCP tools without prompting"},
|
|
87
|
+
{"label": "No", "description": "Ask for permission each time"}
|
|
88
|
+
],
|
|
89
|
+
"multiSelect": false
|
|
90
|
+
}]
|
|
91
|
+
}
|
|
92
|
+
```
|
|
57
93
|
|
|
58
|
-
|
|
59
|
-
```
|
|
94
|
+
If "Yes", update the settings file:
|
|
60
95
|
|
|
61
|
-
|
|
96
|
+
1. Read `.claude/settings.local.json` (create if doesn't exist)
|
|
97
|
+
2. Parse JSON (or start with `{"permissions": {"allow": []}}` if empty/missing)
|
|
98
|
+
3. Add `"mcp__plugin_flux_flux__*"` to `permissions.allow` array if not already present
|
|
99
|
+
4. Write back to `.claude/settings.local.json`
|
|
62
100
|
|
|
63
|
-
|
|
101
|
+
Example result:
|
|
102
|
+
```json
|
|
103
|
+
{
|
|
104
|
+
"permissions": {
|
|
105
|
+
"allow": ["mcp__plugin_flux_flux__*"]
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
```
|
|
64
109
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
> "All tasks complete! Review your work and create a PR."
|
|
110
|
+
Confirm to user: "Flux tools added to allow list. No more permission prompts for Flux operations."
|
|
111
|
+
|
|
112
|
+
### Step 5: Initialize Project
|
|
113
|
+
|
|
114
|
+
Call `init_project` with collected values:
|
|
115
|
+
- `name`: project name
|
|
116
|
+
- `vision`: project vision
|
|
117
|
+
- `adapter`: "local" or "linear"
|
|
118
|
+
|
|
119
|
+
### Step 6: Next Steps
|
|
120
|
+
|
|
121
|
+
Display success message, then:
|
|
122
|
+
|
|
123
|
+
- **If Local**: "Project initialized! Run `/flux:prd` to create your first PRD."
|
|
124
|
+
- **If Linear**: "Project initialized! Now run `/flux:linear` to connect to Linear."
|
|
125
|
+
|
|
126
|
+
## Workflow States
|
|
127
|
+
|
|
128
|
+
Detect current state and suggest the appropriate next action:
|
|
129
|
+
|
|
130
|
+
| State | Detection | Next Action |
|
|
131
|
+
|-------|-----------|-------------|
|
|
132
|
+
| No PRDs | `prds.total == 0` | `/flux:prd` to create first PRD |
|
|
133
|
+
| Draft PRDs | PRDs in DRAFT | Review and refine or submit for review |
|
|
134
|
+
| Pending Review | PRDs in PENDING_REVIEW | Critique agent will analyze |
|
|
135
|
+
| Reviewed | PRDs in REVIEWED | Address feedback, approve or revise |
|
|
136
|
+
| Approved | PRDs in APPROVED, no epics | `/flux:breakdown` to create epics |
|
|
137
|
+
| Breakdown Ready | PRDs in BREAKDOWN_READY | `/flux:implement` to start coding |
|
|
138
|
+
| In Progress | Tasks IN_PROGRESS | Continue with `/flux:implement` |
|
|
139
|
+
| Complete | All tasks COMPLETED | Create PR |
|
|
140
|
+
|
|
141
|
+
## Confidence-Based Autonomy
|
|
142
|
+
|
|
143
|
+
When determining actions:
|
|
144
|
+
|
|
145
|
+
| Confidence | Behavior |
|
|
146
|
+
|------------|----------|
|
|
147
|
+
| > 80% | Auto-execute, inform user |
|
|
148
|
+
| 50-80% | Suggest action, wait for confirmation |
|
|
149
|
+
| < 50% | Ask clarifying question |
|
|
106
150
|
|
|
107
151
|
## Guidelines
|
|
108
152
|
|
|
109
|
-
-
|
|
110
|
-
-
|
|
111
|
-
-
|
|
112
|
-
-
|
|
153
|
+
- Use `AskUserQuestion` tool for all user choices during initialization
|
|
154
|
+
- Be concise - show status and one clear next action
|
|
155
|
+
- Use `render_status` for visual project overview
|
|
156
|
+
- Apply confidence-based autonomy for decisions
|