@relipa/ai-flow-kit 0.1.5-beta.0 → 0.1.5
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/coding-workflow.md +0 -0
- 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 +16 -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/docs-repo.js +49 -0
- package/scripts/hooks/session-start.js +9 -5
- package/scripts/init.js +4 -1
- package/scripts/link-resolver.js +0 -0
- package/scripts/prompt.js +11 -11
- package/scripts/task.js +70 -22
- package/scripts/update.js +4 -0
- package/scripts/use.js +0 -0
|
@@ -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 `AK-Docs/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 `AK-Docs/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
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
const fs = require('fs-extra');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const chalk = require('chalk');
|
|
4
|
+
const { execSync } = require('child_process');
|
|
5
|
+
|
|
6
|
+
// AK-Docs (per-project docs) and Shared-Docs (cross-project templates) are
|
|
7
|
+
// fixed-name folders living directly under the workspace root — the folder
|
|
8
|
+
// opened in the editor, which contains one or more source repos plus these
|
|
9
|
+
// two docs repos as siblings. `ak` is run from that root, so projectDir
|
|
10
|
+
// (process.cwd()) already IS the root — see docs/internal/Project-Structure.md.
|
|
11
|
+
const DOC_REPOS = [
|
|
12
|
+
{ name: 'AK-Docs', purpose: 'tài liệu dự án (Requirements, Specs, Test Cases, Coding docs...)' },
|
|
13
|
+
{ name: 'Shared-Docs', purpose: 'template dùng chung cho tất cả dự án (Spec, QA, Test Case, Test Report...)' },
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
function resolveDocsRepoPath(projectDir, repoName) {
|
|
17
|
+
return path.join(projectDir, repoName);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async function syncDocsRepo(projectDir, repoName, purpose) {
|
|
21
|
+
const repoPath = resolveDocsRepoPath(projectDir, repoName);
|
|
22
|
+
|
|
23
|
+
if (!(await fs.pathExists(repoPath))) {
|
|
24
|
+
console.log(chalk.yellow(`⚠ ${repoName}/ chưa tồn tại tại ${repoPath} (${purpose}). Hãy clone repo này vào thư mục root.`));
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (!(await fs.pathExists(path.join(repoPath, '.git')))) {
|
|
29
|
+
console.log(chalk.yellow(`⚠ ${repoName}/ tồn tại tại ${repoPath} nhưng không phải git repo — bỏ qua pull.`));
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
console.log(chalk.cyan(`\n⟳ Pulling latest ${repoName}...`));
|
|
34
|
+
try {
|
|
35
|
+
execSync('git pull', { cwd: repoPath, stdio: 'inherit' });
|
|
36
|
+
console.log(chalk.green(`✓ ${repoName} đã cập nhật mới nhất.`));
|
|
37
|
+
} catch (err) {
|
|
38
|
+
console.log(chalk.red(`✗ Không thể pull ${repoName}: ${err.message}`));
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
async function syncDocsRepos(projectDir) {
|
|
43
|
+
console.log(chalk.blue('\nĐồng bộ AK-Docs / Shared-Docs...'));
|
|
44
|
+
for (const repo of DOC_REPOS) {
|
|
45
|
+
await syncDocsRepo(projectDir, repo.name, repo.purpose);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
module.exports = { syncDocsRepos, resolveDocsRepoPath, DOC_REPOS };
|
|
@@ -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(` AK-Docs/04.Coding/01.Requirements/[functionId]/${ctx.taskId}.md`);
|
|
219
|
+
lines.push(` ([functionId] — look it up in AK-Docs/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(` AK-Docs/04.Coding/01.Requirements/[functionId]/${ctx.taskId}.md`);
|
|
226
|
+
lines.push(` AK-Docs/04.Coding/02.Plans/[functionId]/${ctx.taskId}.md`);
|
|
227
|
+
lines.push(` ([functionId] — look it up in AK-Docs/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 AK-Docs/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 AK-Docs/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 AK-Docs/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/init.js
CHANGED
|
@@ -3,6 +3,7 @@ const path = require('path');
|
|
|
3
3
|
const os = require('os');
|
|
4
4
|
const chalk = require('chalk');
|
|
5
5
|
const { input, checkbox, confirm } = require('@inquirer/prompts');
|
|
6
|
+
const { syncDocsRepos } = require('./docs-repo');
|
|
6
7
|
|
|
7
8
|
const PKG_DIR = path.join(__dirname, '..');
|
|
8
9
|
const GLOBAL_AIFLOW_DIR = path.join(os.homedir(), '.aiflow');
|
|
@@ -752,7 +753,6 @@ async function ensureAiflowGitignored(projectDir) {
|
|
|
752
753
|
const gitignorePath = path.join(projectDir, '.gitignore');
|
|
753
754
|
const entries = [
|
|
754
755
|
'.aiflow/',
|
|
755
|
-
'plan/',
|
|
756
756
|
'.claude/',
|
|
757
757
|
'.rules/',
|
|
758
758
|
'.mcp.json',
|
|
@@ -1048,6 +1048,9 @@ async function init(options) {
|
|
|
1048
1048
|
try {
|
|
1049
1049
|
console.log(chalk.blue(`Initializing ai-flow-kit (v${PKG_VERSION})...`));
|
|
1050
1050
|
|
|
1051
|
+
// ── Sync AK-Docs / Shared-Docs sibling repos ──────────────────
|
|
1052
|
+
await syncDocsRepos(projectDir);
|
|
1053
|
+
|
|
1051
1054
|
// ── Auto-detect or prompt for framework if not supplied ──────
|
|
1052
1055
|
if (frameworks.length === 0) {
|
|
1053
1056
|
const stateFilePath = path.join(aiflowDir, 'state.json');
|
package/scripts/link-resolver.js
CHANGED
|
File without changes
|
package/scripts/prompt.js
CHANGED
|
@@ -25,7 +25,7 @@ AI must:
|
|
|
25
25
|
1. Load ticket context + read source code related to the bug
|
|
26
26
|
2. Trace data flow to form root cause hypothesis (\`superpowers:systematic-debugging\`)
|
|
27
27
|
3. If unclear → ask ONE question at a time, wait for reply
|
|
28
|
-
4. Output \`
|
|
28
|
+
4. Output \`AK-Docs/04.Coding/01.Requirements/[functionId]/[ticketId].md\` with:
|
|
29
29
|
- Bug analysis (current vs expected behavior)
|
|
30
30
|
- Root cause hypothesis with evidence from source code
|
|
31
31
|
- Proposed fix approach (options if multiple)
|
|
@@ -52,7 +52,7 @@ Only runs after Gate 2 APPROVED.
|
|
|
52
52
|
1. \`superpowers:verification-before-completion\` — all tests PASS (including old tests)
|
|
53
53
|
2. \`impact-analysis\` skill — fix doesn't cause new bugs elsewhere
|
|
54
54
|
3. Tick \`custom/rules/review-checklist.md\`
|
|
55
|
-
4. Create \`
|
|
55
|
+
4. Create \`AK-Docs/04.Coding/04.Reviews/[functionId]/[ticketId].md\`
|
|
56
56
|
- Display: "GATE 4: type APPROVED or BUG: [description]"
|
|
57
57
|
- Coding bug → fix → repeat Gate 4
|
|
58
58
|
- Requirement bug → back to Gate 1
|
|
@@ -77,7 +77,7 @@ AI must:
|
|
|
77
77
|
2. Investigate related files, data flow, existing patterns
|
|
78
78
|
3. Propose 2-3 solution approaches using Q&A if the problem is complex
|
|
79
79
|
4. If unclear → ask ONE question at a time, wait for reply
|
|
80
|
-
5. Output \`
|
|
80
|
+
5. Output \`AK-Docs/04.Coding/01.Requirements/[functionId]/[ticketId].md\` with:
|
|
81
81
|
- Requirements summary (AI's understanding in technical language)
|
|
82
82
|
- Source code analysis (related files, data flow, patterns)
|
|
83
83
|
- Proposed solution with options (recommended + alternatives)
|
|
@@ -104,7 +104,7 @@ Only runs after Gate 2 APPROVED.
|
|
|
104
104
|
1. \`superpowers:verification-before-completion\` — all tests PASS
|
|
105
105
|
2. \`impact-analysis\` skill — no regressions
|
|
106
106
|
3. Tick \`custom/rules/review-checklist.md\`
|
|
107
|
-
4. Create \`
|
|
107
|
+
4. Create \`AK-Docs/04.Coding/04.Reviews/[functionId]/[ticketId].md\`
|
|
108
108
|
- Display: "GATE 4: type APPROVED or BUG: [description]"
|
|
109
109
|
- Coding bug → fix → repeat Gate 4
|
|
110
110
|
- Requirement bug → back to Gate 1
|
|
@@ -129,7 +129,7 @@ AI must:
|
|
|
129
129
|
2. **INVOKE:** \`superpowers:systematic-debugging\` — trace through all layers
|
|
130
130
|
3. **INVOKE:** \`investigate-bug\` skill — trace data flow through all layers
|
|
131
131
|
4. If unclear → ask ONE question at a time
|
|
132
|
-
5. Output \`
|
|
132
|
+
5. Output \`AK-Docs/04.Coding/01.Requirements/[functionId]/[ticketId].md\` with:
|
|
133
133
|
- Investigation scope and approach
|
|
134
134
|
- Source code analysis (all related files traced)
|
|
135
135
|
- Findings with evidence (log output, code references)
|
|
@@ -156,7 +156,7 @@ AI must:
|
|
|
156
156
|
1. Load ticket context + read source code to understand current state
|
|
157
157
|
2. **INVOKE:** \`impact-analysis\` skill — map ALL callers and dependants
|
|
158
158
|
3. If unclear → ask ONE question at a time
|
|
159
|
-
4. Output \`
|
|
159
|
+
4. Output \`AK-Docs/04.Coding/01.Requirements/[functionId]/[ticketId].md\` with:
|
|
160
160
|
- Current state analysis (what exists, what's wrong)
|
|
161
161
|
- Target state (what it should look like after refactor)
|
|
162
162
|
- Proposed approach (step-by-step refactor strategy)
|
|
@@ -182,7 +182,7 @@ Only runs after Gate 2 APPROVED.
|
|
|
182
182
|
1. \`superpowers:verification-before-completion\` — all tests PASS
|
|
183
183
|
2. \`impact-analysis\` skill — verify no regressions
|
|
184
184
|
3. Tick \`custom/rules/review-checklist.md\`
|
|
185
|
-
4. Create \`
|
|
185
|
+
4. Create \`AK-Docs/04.Coding/04.Reviews/[functionId]/[ticketId].md\`
|
|
186
186
|
- Display: "GATE 4: type APPROVED or BUG: [description]"
|
|
187
187
|
|
|
188
188
|
### GATE 5 — Peer Review & Done
|
|
@@ -203,7 +203,7 @@ AI must:
|
|
|
203
203
|
1. Load ticket context + read source code thoroughly
|
|
204
204
|
2. Map all dependencies, callers, services, jobs, tests
|
|
205
205
|
3. If unclear → ask ONE question at a time
|
|
206
|
-
4. Output \`
|
|
206
|
+
4. Output \`AK-Docs/04.Coding/01.Requirements/[functionId]/[ticketId].md\` with:
|
|
207
207
|
- Change description and scope
|
|
208
208
|
- Dependency map (all callers, services, jobs, tests)
|
|
209
209
|
- Impact level: 🟢 Low / 🟡 Medium / 🔴 High / 🔥 Critical
|
|
@@ -229,7 +229,7 @@ AI must:
|
|
|
229
229
|
1. Load ticket context + read source code thoroughly
|
|
230
230
|
2. Understand what needs to be tested (unit, integration, e2e)
|
|
231
231
|
3. If unclear → ask ONE question at a time
|
|
232
|
-
4. Output \`
|
|
232
|
+
4. Output \`AK-Docs/04.Coding/01.Requirements/[functionId]/[ticketId].md\` with:
|
|
233
233
|
- Test scope and strategy
|
|
234
234
|
- Test cases to cover (happy path + edge cases + failure cases)
|
|
235
235
|
- Source code references
|
|
@@ -239,7 +239,7 @@ AI must:
|
|
|
239
239
|
### GATE 2 — Implementation Plan
|
|
240
240
|
**INVOKE:** \`generate-spec\` skill, then \`superpowers:writing-plans\`
|
|
241
241
|
- Create detailed TDD test implementation plan.
|
|
242
|
-
- Output \`
|
|
242
|
+
- Output \`AK-Docs/04.Coding/02.Plans/[functionId]/[ticketId].md\`.
|
|
243
243
|
- Display: "GATE 2 PAUSED: type APPROVED to start coding".
|
|
244
244
|
|
|
245
245
|
### GATE 3 — Write Tests (TDD)
|
|
@@ -265,7 +265,7 @@ AI must:
|
|
|
265
265
|
1. Load ticket context + read source code
|
|
266
266
|
2. Understand what needs to be documented and for whom
|
|
267
267
|
3. If unclear → ask ONE question at a time
|
|
268
|
-
4. Output \`
|
|
268
|
+
4. Output \`AK-Docs/04.Coding/01.Requirements/[functionId]/[ticketId].md\` with:
|
|
269
269
|
- Documentation scope and target audience
|
|
270
270
|
- Content outline (sections to cover)
|
|
271
271
|
- Source code references
|
package/scripts/task.js
CHANGED
|
@@ -2,12 +2,14 @@ const fs = require('fs-extra');
|
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const chalk = require('chalk');
|
|
4
4
|
const { confirm } = require('@inquirer/prompts');
|
|
5
|
+
const { resolveDocsRepoPath } = require('./docs-repo');
|
|
5
6
|
|
|
6
7
|
const PROJECT_DIR = process.cwd();
|
|
7
8
|
const AIFLOW_DIR = path.join(PROJECT_DIR, '.aiflow');
|
|
8
9
|
const CONTEXT_DIR = path.join(AIFLOW_DIR, 'context');
|
|
9
10
|
const CURRENT_FILE = path.join(CONTEXT_DIR, 'current.json');
|
|
10
11
|
const TASKS_DIR = path.join(AIFLOW_DIR, 'tasks');
|
|
12
|
+
const CODING_DIR = path.join(resolveDocsRepoPath(PROJECT_DIR, 'AK-Docs'), '04.Coding');
|
|
11
13
|
|
|
12
14
|
// ──────────────────────────────────────────────────────────────
|
|
13
15
|
// Entry point
|
|
@@ -206,12 +208,8 @@ async function resetTask(taskId) {
|
|
|
206
208
|
}
|
|
207
209
|
|
|
208
210
|
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
|
-
}
|
|
211
|
+
const docPaths = await findTaskDocs(taskId);
|
|
212
|
+
const planFiles = docPaths.map(p => path.relative(PROJECT_DIR, p));
|
|
215
213
|
|
|
216
214
|
// Show what will happen
|
|
217
215
|
console.log(chalk.cyan(`\nReset task: ${taskId}\n`));
|
|
@@ -220,12 +218,12 @@ async function resetTask(taskId) {
|
|
|
220
218
|
console.log(chalk.gray(` Gate: ${taskState.currentGate} → 1 | Approvals cleared | Status: active`));
|
|
221
219
|
|
|
222
220
|
const deletePlan = planFiles.length > 0 && await confirm({
|
|
223
|
-
message: `Also delete ${planFiles.length}
|
|
221
|
+
message: `Also delete ${planFiles.length} gate doc file(s) (AK-Docs/04.Coding/ + legacy plan/) for ${taskId}?`,
|
|
224
222
|
default: false,
|
|
225
223
|
});
|
|
226
224
|
|
|
227
225
|
if (deletePlan) {
|
|
228
|
-
console.log(chalk.gray('\n
|
|
226
|
+
console.log(chalk.gray('\n Gate doc files to delete:'));
|
|
229
227
|
for (const f of planFiles) console.log(chalk.gray(` • ${f}`));
|
|
230
228
|
}
|
|
231
229
|
|
|
@@ -252,10 +250,13 @@ async function resetTask(taskId) {
|
|
|
252
250
|
await fs.copy(ctxPath, CURRENT_FILE, { overwrite: true });
|
|
253
251
|
}
|
|
254
252
|
|
|
255
|
-
if (deletePlan)
|
|
253
|
+
if (deletePlan) {
|
|
254
|
+
for (const p of docPaths) await fs.remove(p);
|
|
255
|
+
await fs.remove(path.join(PROJECT_DIR, 'plan', taskId));
|
|
256
|
+
}
|
|
256
257
|
|
|
257
258
|
console.log(chalk.green(`✓ Task ${taskId} reset to Gate 1.`));
|
|
258
|
-
if (deletePlan) console.log(chalk.gray(` Deleted
|
|
259
|
+
if (deletePlan) console.log(chalk.gray(` Deleted ${planFiles.length} gate doc file(s).`));
|
|
259
260
|
console.log(chalk.gray(' Open Claude to start Gate 1: claude'));
|
|
260
261
|
}
|
|
261
262
|
|
|
@@ -271,9 +272,9 @@ async function removeTask(taskId) {
|
|
|
271
272
|
|
|
272
273
|
const isActive = await fs.pathExists(CURRENT_FILE) &&
|
|
273
274
|
((await fs.readJson(CURRENT_FILE).catch(() => ({}))).taskId === taskId);
|
|
274
|
-
const
|
|
275
|
-
const hasPlan =
|
|
276
|
-
const planFiles =
|
|
275
|
+
const docPaths = await findTaskDocs(taskId);
|
|
276
|
+
const hasPlan = docPaths.length > 0;
|
|
277
|
+
const planFiles = docPaths.map(p => path.relative(PROJECT_DIR, p));
|
|
277
278
|
|
|
278
279
|
// Show what will be deleted
|
|
279
280
|
console.log(chalk.cyan(`\nRemove task: ${taskId}\n`));
|
|
@@ -281,8 +282,8 @@ async function removeTask(taskId) {
|
|
|
281
282
|
console.log(chalk.gray(` • .aiflow/tasks/${taskId}/ (context snapshot + gate state)`));
|
|
282
283
|
if (isActive) console.log(chalk.gray(` • .aiflow/context/current.json (this is the active task)`));
|
|
283
284
|
if (hasPlan) {
|
|
284
|
-
console.log(chalk.gray(` •
|
|
285
|
-
for (const f of planFiles) console.log(chalk.gray(` -
|
|
285
|
+
console.log(chalk.gray(` • Gate docs (${planFiles.length} file(s)):`));
|
|
286
|
+
for (const f of planFiles) console.log(chalk.gray(` - ${f}`));
|
|
286
287
|
}
|
|
287
288
|
|
|
288
289
|
console.log();
|
|
@@ -294,7 +295,10 @@ async function removeTask(taskId) {
|
|
|
294
295
|
|
|
295
296
|
await fs.remove(taskDir);
|
|
296
297
|
if (isActive) await fs.remove(CURRENT_FILE);
|
|
297
|
-
if (hasPlan)
|
|
298
|
+
if (hasPlan) {
|
|
299
|
+
for (const p of docPaths) await fs.remove(p);
|
|
300
|
+
await fs.remove(path.join(PROJECT_DIR, 'plan', taskId));
|
|
301
|
+
}
|
|
298
302
|
|
|
299
303
|
console.log(chalk.green(`✓ Task ${taskId} removed.`));
|
|
300
304
|
}
|
|
@@ -348,23 +352,21 @@ async function nextGate(taskId) {
|
|
|
348
352
|
// Clear current context so no task is "active"
|
|
349
353
|
await fs.remove(CURRENT_FILE);
|
|
350
354
|
|
|
351
|
-
// Generate cumulative task-summary.md
|
|
352
|
-
const
|
|
353
|
-
await fs.ensureDir(planDir);
|
|
354
|
-
const summaryPath = path.join(planDir, 'task-summary.md');
|
|
355
|
+
// Generate cumulative task-summary.md (task-internal state — lives in .aiflow/, not gate docs)
|
|
356
|
+
const summaryPath = path.join(TASKS_DIR, resolvedId, 'task-summary.md');
|
|
355
357
|
const summaryContent = await generateMarkdownSummary(taskState);
|
|
356
358
|
await fs.writeFile(summaryPath, summaryContent, 'utf-8');
|
|
357
359
|
|
|
358
360
|
const taskType = existing.taskType || 'feature';
|
|
359
361
|
console.log(chalk.green(`✓ Gate ${currentGate} approved for ${resolvedId}.`));
|
|
360
|
-
console.log(chalk.gray(` Summary saved to:
|
|
362
|
+
console.log(chalk.gray(` Summary saved to: .aiflow/tasks/${resolvedId}/task-summary.md`));
|
|
361
363
|
const nextLabel = gateLabel(nextGateNum, taskType);
|
|
362
364
|
console.log(chalk.white(`\n Next: Gate ${nextGateNum} — ${nextLabel}`));
|
|
363
365
|
console.log(chalk.cyan(`\n To continue in a fresh session (Recommended to avoid context pollution):`));
|
|
364
366
|
console.log(chalk.gray(` 1. Open a NEW chatbox or terminal session.`));
|
|
365
367
|
console.log(chalk.gray(` 2. Run: aiflow task resume ${resolvedId} (to load context).`));
|
|
366
368
|
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.
|
|
369
|
+
console.log(chalk.yellow(` (Note: Gate 3 progress is saved via [x] checkboxes in the Gate 2 plan doc (AK-Docs/04.Coding/02.Plans/).`));
|
|
368
370
|
console.log(chalk.yellow(` The AI will automatically resume the exact task you left off.)`));
|
|
369
371
|
console.log();
|
|
370
372
|
}
|
|
@@ -373,6 +375,37 @@ async function nextGate(taskId) {
|
|
|
373
375
|
// Internal helpers
|
|
374
376
|
// ──────────────────────────────────────────────────────────────
|
|
375
377
|
|
|
378
|
+
/**
|
|
379
|
+
* Find gate output docs for a task under AK-Docs/04.Coding/<section>/<functionId>/<taskId>.md
|
|
380
|
+
* (new convention) plus the legacy plan/<taskId>/ folder. Returns absolute paths.
|
|
381
|
+
*/
|
|
382
|
+
async function findTaskDocs(taskId) {
|
|
383
|
+
const results = [];
|
|
384
|
+
|
|
385
|
+
if (await fs.pathExists(CODING_DIR)) {
|
|
386
|
+
const sections = await fs.readdir(CODING_DIR, { withFileTypes: true }).catch(() => []);
|
|
387
|
+
for (const section of sections) {
|
|
388
|
+
if (!section.isDirectory()) continue;
|
|
389
|
+
const sectionDir = path.join(CODING_DIR, section.name);
|
|
390
|
+
const featureDirs = await fs.readdir(sectionDir, { withFileTypes: true }).catch(() => []);
|
|
391
|
+
for (const feature of featureDirs) {
|
|
392
|
+
if (!feature.isDirectory()) continue;
|
|
393
|
+
const docPath = path.join(sectionDir, feature.name, `${taskId}.md`);
|
|
394
|
+
if (await fs.pathExists(docPath)) results.push(docPath);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// Legacy convention: plan/<taskId>/
|
|
400
|
+
const legacyDir = path.join(PROJECT_DIR, 'plan', taskId);
|
|
401
|
+
if (await fs.pathExists(legacyDir)) {
|
|
402
|
+
const entries = await fs.readdir(legacyDir).catch(() => []);
|
|
403
|
+
for (const f of entries) results.push(path.join(legacyDir, f));
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
return results;
|
|
407
|
+
}
|
|
408
|
+
|
|
376
409
|
async function deactivateOtherTasks(exceptTaskId) {
|
|
377
410
|
if (!(await fs.pathExists(TASKS_DIR))) return;
|
|
378
411
|
const entries = await fs.readdir(TASKS_DIR, { withFileTypes: true });
|
|
@@ -410,6 +443,21 @@ async function detectCurrentGate(taskId) {
|
|
|
410
443
|
if (state.currentGate) return state.currentGate;
|
|
411
444
|
}
|
|
412
445
|
|
|
446
|
+
// New convention: AK-Docs/04.Coding/<section>/<functionId>/<taskId>.md
|
|
447
|
+
const hasDocInSection = async (section) => {
|
|
448
|
+
const dir = path.join(CODING_DIR, section);
|
|
449
|
+
if (!(await fs.pathExists(dir))) return false;
|
|
450
|
+
const features = await fs.readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
451
|
+
for (const f of features) {
|
|
452
|
+
if (f.isDirectory() && await fs.pathExists(path.join(dir, f.name, `${taskId}.md`))) return true;
|
|
453
|
+
}
|
|
454
|
+
return false;
|
|
455
|
+
};
|
|
456
|
+
if (await hasDocInSection('04.Reviews')) return 5;
|
|
457
|
+
if (await hasDocInSection('02.Plans')) return 3;
|
|
458
|
+
if (await hasDocInSection('01.Requirements')) return 2;
|
|
459
|
+
|
|
460
|
+
// Legacy convention: plan/<taskId>/
|
|
413
461
|
const planDir = path.join(PROJECT_DIR, 'plan', taskId);
|
|
414
462
|
if (!(await fs.pathExists(planDir))) return 1;
|
|
415
463
|
if (await fs.pathExists(path.join(planDir, 'summary.md'))) return 5;
|