@relipa/ai-flow-kit 0.1.5-beta.0 → 0.1.5-beta.1
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/custom/rules/project-conventions.md +67 -51
- package/custom/skills/gate-review/SKILL.md +1 -1
- package/custom/skills/generate-spec/SKILL.md +99 -99
- package/custom/skills/read-study-requirement/SKILL.md +7 -5
- package/custom/skills/review-plan/SKILL.md +194 -194
- package/custom/templates/shared/create-testcase-workflow.md +21 -9
- package/custom/templates/shared/gate-workflow.md +61 -8
- package/custom/templates/tools/claude.md +13 -13
- package/custom/templates/tools/copilot.md +12 -12
- package/custom/templates/tools/cursor.md +12 -12
- package/custom/templates/tools/gemini.md +22 -22
- package/custom/templates/tools/generic.md +17 -17
- package/docs/common/AIFLOW.md +10 -10
- package/docs/common/CHANGELOG.md +5 -0
- package/docs/common/ai-integration.md +53 -53
- package/docs/common/workflows/bug-fix.md +126 -126
- package/docs/common/workflows/feature.md +123 -123
- package/package.json +1 -1
- package/scripts/hooks/session-start.js +9 -5
- package/scripts/task.js +69 -22
|
@@ -1,123 +1,123 @@
|
|
|
1
|
-
# Feature Development Workflow
|
|
2
|
-
|
|
3
|
-
> See the full workflow at [AIFLOW.md](../../AIFLOW.md)
|
|
4
|
-
> **Gates must pass in order: 1 → 2 → 3 → 4 → 5**
|
|
5
|
-
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
## Step 1: Load ticket & AI analyzes (Gate 1)
|
|
9
|
-
|
|
10
|
-
```bash
|
|
11
|
-
aiflow use PROJ-33 # from Backlog/Jira
|
|
12
|
-
claude # AI auto-starts Gate 1
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
AI will **automatically**:
|
|
16
|
-
1. Load ticket info from Backlog/Jira
|
|
17
|
-
2. Read source code — understand architecture, related files, patterns
|
|
18
|
-
3. Ask clarifying questions if anything is unclear (one at a time)
|
|
19
|
-
4. Output `
|
|
20
|
-
- Requirements summary (AI's understanding)
|
|
21
|
-
- Source code analysis (related files, data flow)
|
|
22
|
-
- **Proposed solution** with options and recommendation
|
|
23
|
-
- **Impact analysis** — affected areas, risks
|
|
24
|
-
- **Effort estimate** (S/M/L/XL)
|
|
25
|
-
- Testing plan
|
|
26
|
-
|
|
27
|
-
**PM needs to prepare on the ticket:**
|
|
28
|
-
```markdown
|
|
29
|
-
## Description
|
|
30
|
-
Clear business requirement. Who uses it, and for what purpose.
|
|
31
|
-
|
|
32
|
-
## Acceptance Criteria
|
|
33
|
-
- [ ] [Condition for completion 1]
|
|
34
|
-
- [ ] [Condition for completion 2]
|
|
35
|
-
|
|
36
|
-
## Mockup / Wireframe
|
|
37
|
-
[Link or UI description]
|
|
38
|
-
|
|
39
|
-
## Context
|
|
40
|
-
Constraints, business rules specially requiring attention.
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
**If ticket content is unclear:** AI will ask questions based on source code analysis — not just checking format.
|
|
44
|
-
|
|
45
|
-
**When satisfied with the requirement document, type:**
|
|
46
|
-
```
|
|
47
|
-
APPROVED
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
---
|
|
51
|
-
|
|
52
|
-
## Step 2: Review Implementation Plan (Gate 2)
|
|
53
|
-
|
|
54
|
-
AI generates a detailed implementation plan:
|
|
55
|
-
- TDD task breakdown (test first → implement → verify)
|
|
56
|
-
- Commit strategy (small, focused commits)
|
|
57
|
-
- Test commands
|
|
58
|
-
|
|
59
|
-
**When agreed, type:**
|
|
60
|
-
```
|
|
61
|
-
APPROVED
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
**CODE WILL NOT BE GENERATED BEFORE RECEIVING "APPROVED".**
|
|
65
|
-
|
|
66
|
-
---
|
|
67
|
-
|
|
68
|
-
## Step 3: AI Generate Code (Gate 3)
|
|
69
|
-
|
|
70
|
-
AI performs automatically:
|
|
71
|
-
1. Complex feature (3+ files): `superpowers:subagent-driven-development`
|
|
72
|
-
2. Write tests FIRST → run → confirm FAIL
|
|
73
|
-
3. Implement → tests PASS
|
|
74
|
-
4. Commit each small step
|
|
75
|
-
|
|
76
|
-
Developer doesn't need to do anything at this step — just monitor.
|
|
77
|
-
|
|
78
|
-
---
|
|
79
|
-
|
|
80
|
-
## Step 4: Review Summary (Gate 4)
|
|
81
|
-
|
|
82
|
-
AI runs:
|
|
83
|
-
1. `superpowers:verification-before-completion` — all tests PASS
|
|
84
|
-
2. `impact-analysis` — no breaking changes outside of scope
|
|
85
|
-
3. Review checklist — all items ticked
|
|
86
|
-
4. Create `
|
|
87
|
-
|
|
88
|
-
AI displays summary and waits for developer review.
|
|
89
|
-
|
|
90
|
-
**If OK, type:**
|
|
91
|
-
```
|
|
92
|
-
APPROVED
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
**If there are bugs, type:**
|
|
96
|
-
```
|
|
97
|
-
BUG: [specific description]
|
|
98
|
-
```
|
|
99
|
-
- Coding bug → AI fixes → repeat Gate 4
|
|
100
|
-
- Requirement bug → AI returns to Gate 1, update requirement doc
|
|
101
|
-
|
|
102
|
-
---
|
|
103
|
-
|
|
104
|
-
## Step 5: Peer Review & PR (Gate 5)
|
|
105
|
-
|
|
106
|
-
AI invokes `superpowers:requesting-code-review` and guides PR creation.
|
|
107
|
-
|
|
108
|
-
```bash
|
|
109
|
-
git push origin feature/PROJ-33-feature-name
|
|
110
|
-
# Create PR with full description following the template in AIFLOW.md
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
Peer reviewer uses the `superpowers:receiving-code-review` skill during review.
|
|
114
|
-
|
|
115
|
-
---
|
|
116
|
-
|
|
117
|
-
## Completion Checklist
|
|
118
|
-
|
|
119
|
-
- [ ] Gate 1 APPROVED — requirement doc with solution, impact, estimate
|
|
120
|
-
- [ ] Gate 2 APPROVED — implementation plan confirmed by developer
|
|
121
|
-
- [ ] Gate 3 done — code + tests are green
|
|
122
|
-
- [ ] Gate 4 APPROVED — summary + checklist complete
|
|
123
|
-
- [ ] Gate 5 done — PR is peer-reviewed and merged
|
|
1
|
+
# Feature Development Workflow
|
|
2
|
+
|
|
3
|
+
> See the full workflow at [AIFLOW.md](../../AIFLOW.md)
|
|
4
|
+
> **Gates must pass in order: 1 → 2 → 3 → 4 → 5**
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Step 1: Load ticket & AI analyzes (Gate 1)
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
aiflow use PROJ-33 # from Backlog/Jira
|
|
12
|
+
claude # AI auto-starts Gate 1
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
AI will **automatically**:
|
|
16
|
+
1. Load ticket info from Backlog/Jira
|
|
17
|
+
2. Read source code — understand architecture, related files, patterns
|
|
18
|
+
3. Ask clarifying questions if anything is unclear (one at a time)
|
|
19
|
+
4. Output `04.Coding/01.Requirements/[functionId]/[ticketId].md` containing:
|
|
20
|
+
- Requirements summary (AI's understanding)
|
|
21
|
+
- Source code analysis (related files, data flow)
|
|
22
|
+
- **Proposed solution** with options and recommendation
|
|
23
|
+
- **Impact analysis** — affected areas, risks
|
|
24
|
+
- **Effort estimate** (S/M/L/XL)
|
|
25
|
+
- Testing plan
|
|
26
|
+
|
|
27
|
+
**PM needs to prepare on the ticket:**
|
|
28
|
+
```markdown
|
|
29
|
+
## Description
|
|
30
|
+
Clear business requirement. Who uses it, and for what purpose.
|
|
31
|
+
|
|
32
|
+
## Acceptance Criteria
|
|
33
|
+
- [ ] [Condition for completion 1]
|
|
34
|
+
- [ ] [Condition for completion 2]
|
|
35
|
+
|
|
36
|
+
## Mockup / Wireframe
|
|
37
|
+
[Link or UI description]
|
|
38
|
+
|
|
39
|
+
## Context
|
|
40
|
+
Constraints, business rules specially requiring attention.
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**If ticket content is unclear:** AI will ask questions based on source code analysis — not just checking format.
|
|
44
|
+
|
|
45
|
+
**When satisfied with the requirement document, type:**
|
|
46
|
+
```
|
|
47
|
+
APPROVED
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Step 2: Review Implementation Plan (Gate 2)
|
|
53
|
+
|
|
54
|
+
AI generates a detailed implementation plan:
|
|
55
|
+
- TDD task breakdown (test first → implement → verify)
|
|
56
|
+
- Commit strategy (small, focused commits)
|
|
57
|
+
- Test commands
|
|
58
|
+
|
|
59
|
+
**When agreed, type:**
|
|
60
|
+
```
|
|
61
|
+
APPROVED
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**CODE WILL NOT BE GENERATED BEFORE RECEIVING "APPROVED".**
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Step 3: AI Generate Code (Gate 3)
|
|
69
|
+
|
|
70
|
+
AI performs automatically:
|
|
71
|
+
1. Complex feature (3+ files): `superpowers:subagent-driven-development`
|
|
72
|
+
2. Write tests FIRST → run → confirm FAIL
|
|
73
|
+
3. Implement → tests PASS
|
|
74
|
+
4. Commit each small step
|
|
75
|
+
|
|
76
|
+
Developer doesn't need to do anything at this step — just monitor.
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Step 4: Review Summary (Gate 4)
|
|
81
|
+
|
|
82
|
+
AI runs:
|
|
83
|
+
1. `superpowers:verification-before-completion` — all tests PASS
|
|
84
|
+
2. `impact-analysis` — no breaking changes outside of scope
|
|
85
|
+
3. Review checklist — all items ticked
|
|
86
|
+
4. Create `04.Coding/04.Reviews/[functionId]/[ticketId].md`
|
|
87
|
+
|
|
88
|
+
AI displays summary and waits for developer review.
|
|
89
|
+
|
|
90
|
+
**If OK, type:**
|
|
91
|
+
```
|
|
92
|
+
APPROVED
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**If there are bugs, type:**
|
|
96
|
+
```
|
|
97
|
+
BUG: [specific description]
|
|
98
|
+
```
|
|
99
|
+
- Coding bug → AI fixes → repeat Gate 4
|
|
100
|
+
- Requirement bug → AI returns to Gate 1, update requirement doc
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Step 5: Peer Review & PR (Gate 5)
|
|
105
|
+
|
|
106
|
+
AI invokes `superpowers:requesting-code-review` and guides PR creation.
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
git push origin feature/PROJ-33-feature-name
|
|
110
|
+
# Create PR with full description following the template in AIFLOW.md
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Peer reviewer uses the `superpowers:receiving-code-review` skill during review.
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Completion Checklist
|
|
118
|
+
|
|
119
|
+
- [ ] Gate 1 APPROVED — requirement doc with solution, impact, estimate
|
|
120
|
+
- [ ] Gate 2 APPROVED — implementation plan confirmed by developer
|
|
121
|
+
- [ ] Gate 3 done — code + tests are green
|
|
122
|
+
- [ ] Gate 4 APPROVED — summary + checklist complete
|
|
123
|
+
- [ ] Gate 5 done — PR is peer-reviewed and merged
|
package/package.json
CHANGED
|
@@ -215,14 +215,16 @@ function buildContextPrompt(ctx, taskState) {
|
|
|
215
215
|
|
|
216
216
|
if (currentGate === 2) {
|
|
217
217
|
lines.push('Gate 1 is already APPROVED. The requirement document is at:');
|
|
218
|
-
lines.push(`
|
|
218
|
+
lines.push(` 04.Coding/01.Requirements/[functionId]/${ctx.taskId}.md`);
|
|
219
|
+
lines.push(` ([functionId] — look it up in 04.Coding/00.Overview/_Index.md or the folder containing ${ctx.taskId}.md)`);
|
|
219
220
|
lines.push('');
|
|
220
221
|
lines.push('Proceed to Gate 2: create the implementation plan.');
|
|
221
222
|
lines.push(buildModeInstruction(mode, 2));
|
|
222
223
|
} else if (currentGate === 3) {
|
|
223
224
|
lines.push('Gates 1 and 2 are already APPROVED. Plans are at:');
|
|
224
|
-
lines.push(`
|
|
225
|
-
lines.push(`
|
|
225
|
+
lines.push(` 04.Coding/01.Requirements/[functionId]/${ctx.taskId}.md`);
|
|
226
|
+
lines.push(` 04.Coding/02.Plans/[functionId]/${ctx.taskId}.md`);
|
|
227
|
+
lines.push(` ([functionId] — look it up in 04.Coding/00.Overview/_Index.md)`);
|
|
226
228
|
lines.push('');
|
|
227
229
|
lines.push('Proceed to Gate 3: implement code following the plan (TDD).');
|
|
228
230
|
lines.push(buildModeInstruction(mode, 3));
|
|
@@ -246,17 +248,19 @@ function buildContextPrompt(ctx, taskState) {
|
|
|
246
248
|
|
|
247
249
|
if (mode === 'fast') {
|
|
248
250
|
lines.push('**MODE: fast** — Use the FAST TRACK path in the skill:');
|
|
251
|
+
lines.push('- Pre-flight: determine functionId first (from context / input UC Spec file / ask DEV to confirm) — see the DEV workflow Pre-flight step');
|
|
249
252
|
lines.push('- Read ticket + identify changed files only (no deep source scan)');
|
|
250
253
|
lines.push('- Skip Q&A unless there is a critical blocking ambiguity');
|
|
251
|
-
lines.push('- Output a lite requirement doc (Sections 1, 3, 5 only)');
|
|
254
|
+
lines.push('- Output a lite requirement doc (Sections 1, 3, 5 only) to 04.Coding/01.Requirements/[functionId]/' + ctx.taskId + '.md');
|
|
252
255
|
lines.push('- Target: Gate 1 complete in < 5 minutes');
|
|
253
256
|
} else {
|
|
254
257
|
lines.push('Gate 1 process:');
|
|
258
|
+
lines.push('0. Pre-flight: determine functionId (from context / input UC Spec file / ask DEV to confirm) + ensure 04.Coding/ tree exists — see the DEV workflow Pre-flight step. DO NOT continue without functionId.');
|
|
255
259
|
lines.push('1. Read the ticket context above');
|
|
256
260
|
lines.push('2. Read CLAUDE.md — understand project architecture and conventions');
|
|
257
261
|
lines.push('3. Read source code — identify related files, data flow, patterns');
|
|
258
262
|
lines.push('4. If anything is unclear — ask ONE question at a time');
|
|
259
|
-
lines.push('5. Output
|
|
263
|
+
lines.push('5. Output 04.Coding/01.Requirements/[functionId]/' + ctx.taskId + '.md');
|
|
260
264
|
lines.push('6. Display GATE 1 prompt and wait for APPROVED');
|
|
261
265
|
}
|
|
262
266
|
|
package/scripts/task.js
CHANGED
|
@@ -206,12 +206,8 @@ async function resetTask(taskId) {
|
|
|
206
206
|
}
|
|
207
207
|
|
|
208
208
|
const taskState = await fs.readJson(statePath);
|
|
209
|
-
const
|
|
210
|
-
const planFiles =
|
|
211
|
-
if (await fs.pathExists(planDir)) {
|
|
212
|
-
const entries = await fs.readdir(planDir);
|
|
213
|
-
for (const f of entries) planFiles.push(path.join('plan', taskId, f));
|
|
214
|
-
}
|
|
209
|
+
const docPaths = await findTaskDocs(taskId);
|
|
210
|
+
const planFiles = docPaths.map(p => path.relative(PROJECT_DIR, p));
|
|
215
211
|
|
|
216
212
|
// Show what will happen
|
|
217
213
|
console.log(chalk.cyan(`\nReset task: ${taskId}\n`));
|
|
@@ -220,12 +216,12 @@ async function resetTask(taskId) {
|
|
|
220
216
|
console.log(chalk.gray(` Gate: ${taskState.currentGate} → 1 | Approvals cleared | Status: active`));
|
|
221
217
|
|
|
222
218
|
const deletePlan = planFiles.length > 0 && await confirm({
|
|
223
|
-
message: `Also delete ${planFiles.length}
|
|
219
|
+
message: `Also delete ${planFiles.length} gate doc file(s) (04.Coding/ + legacy plan/) for ${taskId}?`,
|
|
224
220
|
default: false,
|
|
225
221
|
});
|
|
226
222
|
|
|
227
223
|
if (deletePlan) {
|
|
228
|
-
console.log(chalk.gray('\n
|
|
224
|
+
console.log(chalk.gray('\n Gate doc files to delete:'));
|
|
229
225
|
for (const f of planFiles) console.log(chalk.gray(` • ${f}`));
|
|
230
226
|
}
|
|
231
227
|
|
|
@@ -252,10 +248,13 @@ async function resetTask(taskId) {
|
|
|
252
248
|
await fs.copy(ctxPath, CURRENT_FILE, { overwrite: true });
|
|
253
249
|
}
|
|
254
250
|
|
|
255
|
-
if (deletePlan)
|
|
251
|
+
if (deletePlan) {
|
|
252
|
+
for (const p of docPaths) await fs.remove(p);
|
|
253
|
+
await fs.remove(path.join(PROJECT_DIR, 'plan', taskId));
|
|
254
|
+
}
|
|
256
255
|
|
|
257
256
|
console.log(chalk.green(`✓ Task ${taskId} reset to Gate 1.`));
|
|
258
|
-
if (deletePlan) console.log(chalk.gray(` Deleted
|
|
257
|
+
if (deletePlan) console.log(chalk.gray(` Deleted ${planFiles.length} gate doc file(s).`));
|
|
259
258
|
console.log(chalk.gray(' Open Claude to start Gate 1: claude'));
|
|
260
259
|
}
|
|
261
260
|
|
|
@@ -271,9 +270,9 @@ async function removeTask(taskId) {
|
|
|
271
270
|
|
|
272
271
|
const isActive = await fs.pathExists(CURRENT_FILE) &&
|
|
273
272
|
((await fs.readJson(CURRENT_FILE).catch(() => ({}))).taskId === taskId);
|
|
274
|
-
const
|
|
275
|
-
const hasPlan =
|
|
276
|
-
const planFiles =
|
|
273
|
+
const docPaths = await findTaskDocs(taskId);
|
|
274
|
+
const hasPlan = docPaths.length > 0;
|
|
275
|
+
const planFiles = docPaths.map(p => path.relative(PROJECT_DIR, p));
|
|
277
276
|
|
|
278
277
|
// Show what will be deleted
|
|
279
278
|
console.log(chalk.cyan(`\nRemove task: ${taskId}\n`));
|
|
@@ -281,8 +280,8 @@ async function removeTask(taskId) {
|
|
|
281
280
|
console.log(chalk.gray(` • .aiflow/tasks/${taskId}/ (context snapshot + gate state)`));
|
|
282
281
|
if (isActive) console.log(chalk.gray(` • .aiflow/context/current.json (this is the active task)`));
|
|
283
282
|
if (hasPlan) {
|
|
284
|
-
console.log(chalk.gray(` •
|
|
285
|
-
for (const f of planFiles) console.log(chalk.gray(` -
|
|
283
|
+
console.log(chalk.gray(` • Gate docs (${planFiles.length} file(s)):`));
|
|
284
|
+
for (const f of planFiles) console.log(chalk.gray(` - ${f}`));
|
|
286
285
|
}
|
|
287
286
|
|
|
288
287
|
console.log();
|
|
@@ -294,7 +293,10 @@ async function removeTask(taskId) {
|
|
|
294
293
|
|
|
295
294
|
await fs.remove(taskDir);
|
|
296
295
|
if (isActive) await fs.remove(CURRENT_FILE);
|
|
297
|
-
if (hasPlan)
|
|
296
|
+
if (hasPlan) {
|
|
297
|
+
for (const p of docPaths) await fs.remove(p);
|
|
298
|
+
await fs.remove(path.join(PROJECT_DIR, 'plan', taskId));
|
|
299
|
+
}
|
|
298
300
|
|
|
299
301
|
console.log(chalk.green(`✓ Task ${taskId} removed.`));
|
|
300
302
|
}
|
|
@@ -348,23 +350,21 @@ async function nextGate(taskId) {
|
|
|
348
350
|
// Clear current context so no task is "active"
|
|
349
351
|
await fs.remove(CURRENT_FILE);
|
|
350
352
|
|
|
351
|
-
// Generate cumulative task-summary.md
|
|
352
|
-
const
|
|
353
|
-
await fs.ensureDir(planDir);
|
|
354
|
-
const summaryPath = path.join(planDir, 'task-summary.md');
|
|
353
|
+
// Generate cumulative task-summary.md (task-internal state — lives in .aiflow/, not gate docs)
|
|
354
|
+
const summaryPath = path.join(TASKS_DIR, resolvedId, 'task-summary.md');
|
|
355
355
|
const summaryContent = await generateMarkdownSummary(taskState);
|
|
356
356
|
await fs.writeFile(summaryPath, summaryContent, 'utf-8');
|
|
357
357
|
|
|
358
358
|
const taskType = existing.taskType || 'feature';
|
|
359
359
|
console.log(chalk.green(`✓ Gate ${currentGate} approved for ${resolvedId}.`));
|
|
360
|
-
console.log(chalk.gray(` Summary saved to:
|
|
360
|
+
console.log(chalk.gray(` Summary saved to: .aiflow/tasks/${resolvedId}/task-summary.md`));
|
|
361
361
|
const nextLabel = gateLabel(nextGateNum, taskType);
|
|
362
362
|
console.log(chalk.white(`\n Next: Gate ${nextGateNum} — ${nextLabel}`));
|
|
363
363
|
console.log(chalk.cyan(`\n To continue in a fresh session (Recommended to avoid context pollution):`));
|
|
364
364
|
console.log(chalk.gray(` 1. Open a NEW chatbox or terminal session.`));
|
|
365
365
|
console.log(chalk.gray(` 2. Run: aiflow task resume ${resolvedId} (to load context).`));
|
|
366
366
|
console.log(chalk.gray(` 3. Type "start" or "continue from the current plan".`));
|
|
367
|
-
console.log(chalk.yellow(` (Note: Gate 3 progress is saved via [x] checkboxes in plan.
|
|
367
|
+
console.log(chalk.yellow(` (Note: Gate 3 progress is saved via [x] checkboxes in the Gate 2 plan doc (04.Coding/02.Plans/).`));
|
|
368
368
|
console.log(chalk.yellow(` The AI will automatically resume the exact task you left off.)`));
|
|
369
369
|
console.log();
|
|
370
370
|
}
|
|
@@ -373,6 +373,38 @@ async function nextGate(taskId) {
|
|
|
373
373
|
// Internal helpers
|
|
374
374
|
// ──────────────────────────────────────────────────────────────
|
|
375
375
|
|
|
376
|
+
/**
|
|
377
|
+
* Find gate output docs for a task under 04.Coding/<section>/<functionId>/<taskId>.md
|
|
378
|
+
* (new convention) plus the legacy plan/<taskId>/ folder. Returns absolute paths.
|
|
379
|
+
*/
|
|
380
|
+
async function findTaskDocs(taskId) {
|
|
381
|
+
const results = [];
|
|
382
|
+
|
|
383
|
+
const codingDir = path.join(PROJECT_DIR, '04.Coding');
|
|
384
|
+
if (await fs.pathExists(codingDir)) {
|
|
385
|
+
const sections = await fs.readdir(codingDir, { withFileTypes: true }).catch(() => []);
|
|
386
|
+
for (const section of sections) {
|
|
387
|
+
if (!section.isDirectory()) continue;
|
|
388
|
+
const sectionDir = path.join(codingDir, section.name);
|
|
389
|
+
const featureDirs = await fs.readdir(sectionDir, { withFileTypes: true }).catch(() => []);
|
|
390
|
+
for (const feature of featureDirs) {
|
|
391
|
+
if (!feature.isDirectory()) continue;
|
|
392
|
+
const docPath = path.join(sectionDir, feature.name, `${taskId}.md`);
|
|
393
|
+
if (await fs.pathExists(docPath)) results.push(docPath);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// Legacy convention: plan/<taskId>/
|
|
399
|
+
const legacyDir = path.join(PROJECT_DIR, 'plan', taskId);
|
|
400
|
+
if (await fs.pathExists(legacyDir)) {
|
|
401
|
+
const entries = await fs.readdir(legacyDir).catch(() => []);
|
|
402
|
+
for (const f of entries) results.push(path.join(legacyDir, f));
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
return results;
|
|
406
|
+
}
|
|
407
|
+
|
|
376
408
|
async function deactivateOtherTasks(exceptTaskId) {
|
|
377
409
|
if (!(await fs.pathExists(TASKS_DIR))) return;
|
|
378
410
|
const entries = await fs.readdir(TASKS_DIR, { withFileTypes: true });
|
|
@@ -410,6 +442,21 @@ async function detectCurrentGate(taskId) {
|
|
|
410
442
|
if (state.currentGate) return state.currentGate;
|
|
411
443
|
}
|
|
412
444
|
|
|
445
|
+
// New convention: 04.Coding/<section>/<functionId>/<taskId>.md
|
|
446
|
+
const hasDocInSection = async (section) => {
|
|
447
|
+
const dir = path.join(PROJECT_DIR, '04.Coding', section);
|
|
448
|
+
if (!(await fs.pathExists(dir))) return false;
|
|
449
|
+
const features = await fs.readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
450
|
+
for (const f of features) {
|
|
451
|
+
if (f.isDirectory() && await fs.pathExists(path.join(dir, f.name, `${taskId}.md`))) return true;
|
|
452
|
+
}
|
|
453
|
+
return false;
|
|
454
|
+
};
|
|
455
|
+
if (await hasDocInSection('04.Reviews')) return 5;
|
|
456
|
+
if (await hasDocInSection('02.Plans')) return 3;
|
|
457
|
+
if (await hasDocInSection('01.Requirements')) return 2;
|
|
458
|
+
|
|
459
|
+
// Legacy convention: plan/<taskId>/
|
|
413
460
|
const planDir = path.join(PROJECT_DIR, 'plan', taskId);
|
|
414
461
|
if (!(await fs.pathExists(planDir))) return 1;
|
|
415
462
|
if (await fs.pathExists(path.join(planDir, 'summary.md'))) return 5;
|