@relipa/ai-flow-kit 0.0.6-beta.0 → 0.0.6
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/java/spring-boot-examples.md +329 -329
- package/custom/templates/spring-boot.md +224 -224
- package/package.json +1 -1
- package/scripts/doctor.js +89 -89
- package/scripts/hooks/session-start.js +244 -244
- package/scripts/task.js +384 -384
|
@@ -1,244 +1,244 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* SessionStart hook for ai-flow-kit
|
|
4
|
-
* Injects:
|
|
5
|
-
* 1. using-superpowers skill content
|
|
6
|
-
* 2. Active ticket context + gate-aware workflow instruction
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
const fs = require('fs');
|
|
10
|
-
const path = require('path');
|
|
11
|
-
const { record } = require('../telemetry/record');
|
|
12
|
-
|
|
13
|
-
record('session.start');
|
|
14
|
-
|
|
15
|
-
// This script lives at .claude/hooks/session-start.js
|
|
16
|
-
// Project root is 2 levels up: .claude/hooks → .claude → project root
|
|
17
|
-
const projectRoot = path.resolve(__dirname, '..', '..');
|
|
18
|
-
const skillPath = path.join(projectRoot, '.claude', 'skills', 'using-superpowers', 'SKILL.md');
|
|
19
|
-
const contextPath = path.join(projectRoot, '.aiflow', 'context', 'current.json');
|
|
20
|
-
const tasksDir = path.join(projectRoot, '.aiflow', 'tasks');
|
|
21
|
-
|
|
22
|
-
// ── 1. Load superpowers skill ──────────────────────────────────
|
|
23
|
-
let skillContent = '';
|
|
24
|
-
try {
|
|
25
|
-
skillContent = fs.readFileSync(skillPath, 'utf-8');
|
|
26
|
-
} catch (_) {
|
|
27
|
-
process.stderr.write('[aiflow] WARNING: using-superpowers skill missing — run `aiflow update`\n');
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// ── 2. Load active ticket context ──────────────────────────────
|
|
31
|
-
let contextBlock = '';
|
|
32
|
-
try {
|
|
33
|
-
if (fs.existsSync(contextPath)) {
|
|
34
|
-
const ctx = JSON.parse(fs.readFileSync(contextPath, 'utf-8'));
|
|
35
|
-
if (ctx.taskId && ctx.title) {
|
|
36
|
-
const taskState = loadTaskState(ctx.taskId);
|
|
37
|
-
contextBlock = buildContextPrompt(ctx, taskState);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
} catch (_) {
|
|
41
|
-
// Context missing or invalid — continue without it
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// ── 3. Combine and output ──────────────────────────────────────
|
|
45
|
-
const parts = [];
|
|
46
|
-
|
|
47
|
-
if (skillContent) {
|
|
48
|
-
parts.push(`<EXTREMELY_IMPORTANT>\nYou have superpowers.\n\n**Below is the full content of your 'superpowers:using-superpowers' skill - your introduction to using skills. For all other skills, use the 'Skill' tool:**\n\n${skillContent}\n\n</EXTREMELY_IMPORTANT>`);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
if (contextBlock) {
|
|
52
|
-
parts.push(contextBlock);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const combined = parts.join('\n\n');
|
|
56
|
-
|
|
57
|
-
const escaped = combined
|
|
58
|
-
.replace(/\\/g, '\\\\')
|
|
59
|
-
.replace(/"/g, '\\"')
|
|
60
|
-
.replace(/\n/g, '\\n')
|
|
61
|
-
.replace(/\r/g, '\\r')
|
|
62
|
-
.replace(/\t/g, '\\t');
|
|
63
|
-
|
|
64
|
-
process.stdout.write(JSON.stringify({
|
|
65
|
-
hookSpecificOutput: {
|
|
66
|
-
hookEventName: 'SessionStart',
|
|
67
|
-
additionalContext: escaped
|
|
68
|
-
}
|
|
69
|
-
}));
|
|
70
|
-
|
|
71
|
-
process.exit(0);
|
|
72
|
-
|
|
73
|
-
// ── Helpers ────────────────────────────────────────────────────
|
|
74
|
-
|
|
75
|
-
function loadTaskState(taskId) {
|
|
76
|
-
try {
|
|
77
|
-
const statePath = path.join(tasksDir, taskId, 'task-state.json');
|
|
78
|
-
if (fs.existsSync(statePath)) {
|
|
79
|
-
return JSON.parse(fs.readFileSync(statePath, 'utf-8'));
|
|
80
|
-
}
|
|
81
|
-
} catch (_) {}
|
|
82
|
-
return null;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
function buildContextPrompt(ctx, taskState) {
|
|
86
|
-
const lines = [];
|
|
87
|
-
lines.push('<ACTIVE_TASK>');
|
|
88
|
-
lines.push(`**Active Ticket:** ${ctx.taskId} — ${ctx.title}`);
|
|
89
|
-
lines.push(`**Type:** ${ctx.taskType || 'feature'}`);
|
|
90
|
-
lines.push(`**Status:** ${ctx.status || 'Unknown'}`);
|
|
91
|
-
lines.push(`**Assignee:** ${ctx.assignee || 'Unknown'}`);
|
|
92
|
-
lines.push('');
|
|
93
|
-
|
|
94
|
-
if (ctx.description) {
|
|
95
|
-
lines.push('**Description:**');
|
|
96
|
-
lines.push(ctx.description.substring(0, 2000));
|
|
97
|
-
lines.push('');
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
if (ctx.acceptanceCriteria && ctx.acceptanceCriteria.length > 0) {
|
|
101
|
-
lines.push('**Acceptance Criteria:**');
|
|
102
|
-
for (const c of ctx.acceptanceCriteria) lines.push(`- ${c}`);
|
|
103
|
-
lines.push('');
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
if (ctx.comments && ctx.comments.length > 0) {
|
|
107
|
-
lines.push(`**Comments (${ctx.comments.length}):**`);
|
|
108
|
-
const recent = ctx.comments.slice(-5);
|
|
109
|
-
for (const c of recent) { lines.push(c); lines.push(''); }
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
if (ctx.context && ctx.context.files && ctx.context.files.length > 0) {
|
|
113
|
-
lines.push('**Related Files:**');
|
|
114
|
-
for (const f of ctx.context.files) lines.push(`- \`${f}\``);
|
|
115
|
-
lines.push('');
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
lines.push('---');
|
|
119
|
-
lines.push('');
|
|
120
|
-
|
|
121
|
-
// ── Gate-aware instruction ──────────────────────────────────
|
|
122
|
-
const mode = ctx.mode || 'fast';
|
|
123
|
-
const currentGate = taskState && taskState.currentGate ? taskState.currentGate : 1;
|
|
124
|
-
const isResume = taskState && taskState.pausedAt;
|
|
125
|
-
|
|
126
|
-
if (isResume && currentGate > 1) {
|
|
127
|
-
// Resuming a paused task — inject resume context
|
|
128
|
-
const gateApprovals = taskState.gateApprovals || {};
|
|
129
|
-
lines.push(`**RESUMING TASK: ${ctx.taskId} — Gate ${currentGate}**`);
|
|
130
|
-
lines.push('');
|
|
131
|
-
lines.push('This task was previously paused and is now being resumed.');
|
|
132
|
-
lines.push('');
|
|
133
|
-
lines.push('**Gate Progress:**');
|
|
134
|
-
for (let g = 1; g < currentGate; g++) {
|
|
135
|
-
const approvedAt = gateApprovals[String(g)];
|
|
136
|
-
const stamp = approvedAt ? ` — approved ${approvedAt}` : ' — approved';
|
|
137
|
-
lines.push(`- Gate ${g}: ✅ APPROVED${stamp}`);
|
|
138
|
-
}
|
|
139
|
-
lines.push(`- Gate ${currentGate}: 🔄 IN PROGRESS`);
|
|
140
|
-
lines.push('');
|
|
141
|
-
lines.push(`**DO NOT restart from Gate 1.** Resume directly at Gate ${currentGate} (${gateLabel(currentGate)}).`);
|
|
142
|
-
lines.push('');
|
|
143
|
-
|
|
144
|
-
if (currentGate === 2) {
|
|
145
|
-
lines.push('Gate 1 is already APPROVED. The requirement document is at:');
|
|
146
|
-
lines.push(` plan/${ctx.taskId}/requirement.md`);
|
|
147
|
-
lines.push('');
|
|
148
|
-
lines.push('Proceed to Gate 2: create the implementation plan.');
|
|
149
|
-
lines.push(buildModeInstruction(mode, 2));
|
|
150
|
-
} else if (currentGate === 3) {
|
|
151
|
-
lines.push('Gates 1 and 2 are already APPROVED. Plans are at:');
|
|
152
|
-
lines.push(` plan/${ctx.taskId}/requirement.md`);
|
|
153
|
-
lines.push(` plan/${ctx.taskId}/plan.md`);
|
|
154
|
-
lines.push('');
|
|
155
|
-
lines.push('Proceed to Gate 3: implement code following the plan (TDD).');
|
|
156
|
-
lines.push(buildModeInstruction(mode, 3));
|
|
157
|
-
} else if (currentGate === 4) {
|
|
158
|
-
lines.push('Gates 1–3 are APPROVED. Code has been implemented.');
|
|
159
|
-
lines.push('Proceed to Gate 4: run verification + impact-analysis + review checklist.');
|
|
160
|
-
lines.push(buildModeInstruction(mode, 4));
|
|
161
|
-
} else if (currentGate === 5) {
|
|
162
|
-
lines.push('Gates 1–4 are APPROVED. Self-review is done.');
|
|
163
|
-
lines.push('Proceed to Gate 5: guide the developer to create a Pull Request.');
|
|
164
|
-
}
|
|
165
|
-
if (taskState.notes) {
|
|
166
|
-
lines.push('');
|
|
167
|
-
lines.push(`**Note from developer:** ${taskState.notes}`);
|
|
168
|
-
}
|
|
169
|
-
} else {
|
|
170
|
-
// Fresh task — auto-start Gate 1
|
|
171
|
-
lines.push('**AUTO-START GATE 1: You MUST begin analyzing this ticket immediately.**');
|
|
172
|
-
lines.push('');
|
|
173
|
-
lines.push(`INVOKE the \`read-study-requirement\` skill NOW for ticket ${ctx.taskId}.`);
|
|
174
|
-
lines.push('');
|
|
175
|
-
|
|
176
|
-
if (mode === 'fast') {
|
|
177
|
-
lines.push('**MODE: fast** — Use the FAST TRACK path in the skill:');
|
|
178
|
-
lines.push('- Read ticket + identify changed files only (no deep source scan)');
|
|
179
|
-
lines.push('- Skip Q&A unless there is a critical blocking ambiguity');
|
|
180
|
-
lines.push('- Output a lite requirement doc (Sections 1, 3, 5 only)');
|
|
181
|
-
lines.push('- Target: Gate 1 complete in < 5 minutes');
|
|
182
|
-
} else {
|
|
183
|
-
lines.push('Gate 1 process:');
|
|
184
|
-
lines.push('1. Read the ticket context above');
|
|
185
|
-
lines.push('2. Read CLAUDE.md — understand project architecture and conventions');
|
|
186
|
-
lines.push('3. Read source code — identify related files, data flow, patterns');
|
|
187
|
-
lines.push('4. If anything is unclear — ask ONE question at a time');
|
|
188
|
-
lines.push('5. Output plan/' + ctx.taskId + '/requirement.md');
|
|
189
|
-
lines.push('6. Display GATE 1 prompt and wait for APPROVED');
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
lines.push('');
|
|
193
|
-
lines.push('DO NOT wait for the developer to ask. START NOW.');
|
|
194
|
-
lines.push('If you have not started automatically, begin as soon as the developer types **"start"**.');
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
lines.push('</ACTIVE_TASK>');
|
|
198
|
-
return lines.join('\n');
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
function gateLabel(n) {
|
|
202
|
-
const labels = {
|
|
203
|
-
1: 'AI Analyze Requirement',
|
|
204
|
-
2: 'Implementation Plan',
|
|
205
|
-
3: 'Code Generation',
|
|
206
|
-
4: 'AI Self-Review',
|
|
207
|
-
5: 'Peer Review & PR',
|
|
208
|
-
};
|
|
209
|
-
return labels[n] || `Gate ${n}`;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
function buildModeInstruction(mode, gate) {
|
|
213
|
-
if (mode !== 'fast') return ''; // full mode: không inject gì thêm, AI chạy đầy đủ các bước
|
|
214
|
-
|
|
215
|
-
const instructions = {
|
|
216
|
-
2: [
|
|
217
|
-
'**MODE: fast** — Gate 2 fast track:',
|
|
218
|
-
'- Create a simple task list (task-level, NOT step-level)',
|
|
219
|
-
'- DO NOT invoke `superpowers:writing-plans`',
|
|
220
|
-
'- Format: numbered list of tasks, each with file + action',
|
|
221
|
-
'- No code snippets, no step-by-step TDD breakdown required',
|
|
222
|
-
],
|
|
223
|
-
3: [
|
|
224
|
-
'**MODE: fast** — Gate 3 fast track:',
|
|
225
|
-
'- DO NOT use `superpowers:subagent-driven-development`',
|
|
226
|
-
'- DO NOT spawn Spec Reviewer or Code Quality Reviewer subagents',
|
|
227
|
-
'- Implement ALL tasks directly in this session',
|
|
228
|
-
'- Write tests and implementation in the same pass per task',
|
|
229
|
-
'- Run the test suite ONCE at the end of all tasks (not after each step)',
|
|
230
|
-
'- If tests fail: fix inline, do not spawn a subagent',
|
|
231
|
-
],
|
|
232
|
-
4: [
|
|
233
|
-
'**MODE: fast** — Gate 4 fast track:',
|
|
234
|
-
'- Run the full test suite — this is MANDATORY',
|
|
235
|
-
'- Impact Analysis: quick scan only — reason from git diff and changed files.',
|
|
236
|
-
' DO NOT grep the entire codebase. List affected files and assess impact level.',
|
|
237
|
-
'- Review checklist (3 items only): tests pass ✅, no hardcoded secrets ✅, no SQL injection ✅',
|
|
238
|
-
'- summary.md: short format (Implementation table + Test result only)',
|
|
239
|
-
],
|
|
240
|
-
};
|
|
241
|
-
|
|
242
|
-
const lines = instructions[gate];
|
|
243
|
-
return lines ? '\n' + lines.join('\n') : '';
|
|
244
|
-
}
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* SessionStart hook for ai-flow-kit
|
|
4
|
+
* Injects:
|
|
5
|
+
* 1. using-superpowers skill content
|
|
6
|
+
* 2. Active ticket context + gate-aware workflow instruction
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
const { record } = require('../telemetry/record');
|
|
12
|
+
|
|
13
|
+
record('session.start');
|
|
14
|
+
|
|
15
|
+
// This script lives at .claude/hooks/session-start.js
|
|
16
|
+
// Project root is 2 levels up: .claude/hooks → .claude → project root
|
|
17
|
+
const projectRoot = path.resolve(__dirname, '..', '..');
|
|
18
|
+
const skillPath = path.join(projectRoot, '.claude', 'skills', 'using-superpowers', 'SKILL.md');
|
|
19
|
+
const contextPath = path.join(projectRoot, '.aiflow', 'context', 'current.json');
|
|
20
|
+
const tasksDir = path.join(projectRoot, '.aiflow', 'tasks');
|
|
21
|
+
|
|
22
|
+
// ── 1. Load superpowers skill ──────────────────────────────────
|
|
23
|
+
let skillContent = '';
|
|
24
|
+
try {
|
|
25
|
+
skillContent = fs.readFileSync(skillPath, 'utf-8');
|
|
26
|
+
} catch (_) {
|
|
27
|
+
process.stderr.write('[aiflow] WARNING: using-superpowers skill missing — run `aiflow update`\n');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// ── 2. Load active ticket context ──────────────────────────────
|
|
31
|
+
let contextBlock = '';
|
|
32
|
+
try {
|
|
33
|
+
if (fs.existsSync(contextPath)) {
|
|
34
|
+
const ctx = JSON.parse(fs.readFileSync(contextPath, 'utf-8'));
|
|
35
|
+
if (ctx.taskId && ctx.title) {
|
|
36
|
+
const taskState = loadTaskState(ctx.taskId);
|
|
37
|
+
contextBlock = buildContextPrompt(ctx, taskState);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
} catch (_) {
|
|
41
|
+
// Context missing or invalid — continue without it
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// ── 3. Combine and output ──────────────────────────────────────
|
|
45
|
+
const parts = [];
|
|
46
|
+
|
|
47
|
+
if (skillContent) {
|
|
48
|
+
parts.push(`<EXTREMELY_IMPORTANT>\nYou have superpowers.\n\n**Below is the full content of your 'superpowers:using-superpowers' skill - your introduction to using skills. For all other skills, use the 'Skill' tool:**\n\n${skillContent}\n\n</EXTREMELY_IMPORTANT>`);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (contextBlock) {
|
|
52
|
+
parts.push(contextBlock);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const combined = parts.join('\n\n');
|
|
56
|
+
|
|
57
|
+
const escaped = combined
|
|
58
|
+
.replace(/\\/g, '\\\\')
|
|
59
|
+
.replace(/"/g, '\\"')
|
|
60
|
+
.replace(/\n/g, '\\n')
|
|
61
|
+
.replace(/\r/g, '\\r')
|
|
62
|
+
.replace(/\t/g, '\\t');
|
|
63
|
+
|
|
64
|
+
process.stdout.write(JSON.stringify({
|
|
65
|
+
hookSpecificOutput: {
|
|
66
|
+
hookEventName: 'SessionStart',
|
|
67
|
+
additionalContext: escaped
|
|
68
|
+
}
|
|
69
|
+
}));
|
|
70
|
+
|
|
71
|
+
process.exit(0);
|
|
72
|
+
|
|
73
|
+
// ── Helpers ────────────────────────────────────────────────────
|
|
74
|
+
|
|
75
|
+
function loadTaskState(taskId) {
|
|
76
|
+
try {
|
|
77
|
+
const statePath = path.join(tasksDir, taskId, 'task-state.json');
|
|
78
|
+
if (fs.existsSync(statePath)) {
|
|
79
|
+
return JSON.parse(fs.readFileSync(statePath, 'utf-8'));
|
|
80
|
+
}
|
|
81
|
+
} catch (_) {}
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function buildContextPrompt(ctx, taskState) {
|
|
86
|
+
const lines = [];
|
|
87
|
+
lines.push('<ACTIVE_TASK>');
|
|
88
|
+
lines.push(`**Active Ticket:** ${ctx.taskId} — ${ctx.title}`);
|
|
89
|
+
lines.push(`**Type:** ${ctx.taskType || 'feature'}`);
|
|
90
|
+
lines.push(`**Status:** ${ctx.status || 'Unknown'}`);
|
|
91
|
+
lines.push(`**Assignee:** ${ctx.assignee || 'Unknown'}`);
|
|
92
|
+
lines.push('');
|
|
93
|
+
|
|
94
|
+
if (ctx.description) {
|
|
95
|
+
lines.push('**Description:**');
|
|
96
|
+
lines.push(ctx.description.substring(0, 2000));
|
|
97
|
+
lines.push('');
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (ctx.acceptanceCriteria && ctx.acceptanceCriteria.length > 0) {
|
|
101
|
+
lines.push('**Acceptance Criteria:**');
|
|
102
|
+
for (const c of ctx.acceptanceCriteria) lines.push(`- ${c}`);
|
|
103
|
+
lines.push('');
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (ctx.comments && ctx.comments.length > 0) {
|
|
107
|
+
lines.push(`**Comments (${ctx.comments.length}):**`);
|
|
108
|
+
const recent = ctx.comments.slice(-5);
|
|
109
|
+
for (const c of recent) { lines.push(c); lines.push(''); }
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (ctx.context && ctx.context.files && ctx.context.files.length > 0) {
|
|
113
|
+
lines.push('**Related Files:**');
|
|
114
|
+
for (const f of ctx.context.files) lines.push(`- \`${f}\``);
|
|
115
|
+
lines.push('');
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
lines.push('---');
|
|
119
|
+
lines.push('');
|
|
120
|
+
|
|
121
|
+
// ── Gate-aware instruction ──────────────────────────────────
|
|
122
|
+
const mode = ctx.mode || 'fast';
|
|
123
|
+
const currentGate = taskState && taskState.currentGate ? taskState.currentGate : 1;
|
|
124
|
+
const isResume = taskState && taskState.pausedAt;
|
|
125
|
+
|
|
126
|
+
if (isResume && currentGate > 1) {
|
|
127
|
+
// Resuming a paused task — inject resume context
|
|
128
|
+
const gateApprovals = taskState.gateApprovals || {};
|
|
129
|
+
lines.push(`**RESUMING TASK: ${ctx.taskId} — Gate ${currentGate}**`);
|
|
130
|
+
lines.push('');
|
|
131
|
+
lines.push('This task was previously paused and is now being resumed.');
|
|
132
|
+
lines.push('');
|
|
133
|
+
lines.push('**Gate Progress:**');
|
|
134
|
+
for (let g = 1; g < currentGate; g++) {
|
|
135
|
+
const approvedAt = gateApprovals[String(g)];
|
|
136
|
+
const stamp = approvedAt ? ` — approved ${approvedAt}` : ' — approved';
|
|
137
|
+
lines.push(`- Gate ${g}: ✅ APPROVED${stamp}`);
|
|
138
|
+
}
|
|
139
|
+
lines.push(`- Gate ${currentGate}: 🔄 IN PROGRESS`);
|
|
140
|
+
lines.push('');
|
|
141
|
+
lines.push(`**DO NOT restart from Gate 1.** Resume directly at Gate ${currentGate} (${gateLabel(currentGate)}).`);
|
|
142
|
+
lines.push('');
|
|
143
|
+
|
|
144
|
+
if (currentGate === 2) {
|
|
145
|
+
lines.push('Gate 1 is already APPROVED. The requirement document is at:');
|
|
146
|
+
lines.push(` plan/${ctx.taskId}/requirement.md`);
|
|
147
|
+
lines.push('');
|
|
148
|
+
lines.push('Proceed to Gate 2: create the implementation plan.');
|
|
149
|
+
lines.push(buildModeInstruction(mode, 2));
|
|
150
|
+
} else if (currentGate === 3) {
|
|
151
|
+
lines.push('Gates 1 and 2 are already APPROVED. Plans are at:');
|
|
152
|
+
lines.push(` plan/${ctx.taskId}/requirement.md`);
|
|
153
|
+
lines.push(` plan/${ctx.taskId}/plan.md`);
|
|
154
|
+
lines.push('');
|
|
155
|
+
lines.push('Proceed to Gate 3: implement code following the plan (TDD).');
|
|
156
|
+
lines.push(buildModeInstruction(mode, 3));
|
|
157
|
+
} else if (currentGate === 4) {
|
|
158
|
+
lines.push('Gates 1–3 are APPROVED. Code has been implemented.');
|
|
159
|
+
lines.push('Proceed to Gate 4: run verification + impact-analysis + review checklist.');
|
|
160
|
+
lines.push(buildModeInstruction(mode, 4));
|
|
161
|
+
} else if (currentGate === 5) {
|
|
162
|
+
lines.push('Gates 1–4 are APPROVED. Self-review is done.');
|
|
163
|
+
lines.push('Proceed to Gate 5: guide the developer to create a Pull Request.');
|
|
164
|
+
}
|
|
165
|
+
if (taskState.notes) {
|
|
166
|
+
lines.push('');
|
|
167
|
+
lines.push(`**Note from developer:** ${taskState.notes}`);
|
|
168
|
+
}
|
|
169
|
+
} else {
|
|
170
|
+
// Fresh task — auto-start Gate 1
|
|
171
|
+
lines.push('**AUTO-START GATE 1: You MUST begin analyzing this ticket immediately.**');
|
|
172
|
+
lines.push('');
|
|
173
|
+
lines.push(`INVOKE the \`read-study-requirement\` skill NOW for ticket ${ctx.taskId}.`);
|
|
174
|
+
lines.push('');
|
|
175
|
+
|
|
176
|
+
if (mode === 'fast') {
|
|
177
|
+
lines.push('**MODE: fast** — Use the FAST TRACK path in the skill:');
|
|
178
|
+
lines.push('- Read ticket + identify changed files only (no deep source scan)');
|
|
179
|
+
lines.push('- Skip Q&A unless there is a critical blocking ambiguity');
|
|
180
|
+
lines.push('- Output a lite requirement doc (Sections 1, 3, 5 only)');
|
|
181
|
+
lines.push('- Target: Gate 1 complete in < 5 minutes');
|
|
182
|
+
} else {
|
|
183
|
+
lines.push('Gate 1 process:');
|
|
184
|
+
lines.push('1. Read the ticket context above');
|
|
185
|
+
lines.push('2. Read CLAUDE.md — understand project architecture and conventions');
|
|
186
|
+
lines.push('3. Read source code — identify related files, data flow, patterns');
|
|
187
|
+
lines.push('4. If anything is unclear — ask ONE question at a time');
|
|
188
|
+
lines.push('5. Output plan/' + ctx.taskId + '/requirement.md');
|
|
189
|
+
lines.push('6. Display GATE 1 prompt and wait for APPROVED');
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
lines.push('');
|
|
193
|
+
lines.push('DO NOT wait for the developer to ask. START NOW.');
|
|
194
|
+
lines.push('If you have not started automatically, begin as soon as the developer types **"start"**.');
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
lines.push('</ACTIVE_TASK>');
|
|
198
|
+
return lines.join('\n');
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function gateLabel(n) {
|
|
202
|
+
const labels = {
|
|
203
|
+
1: 'AI Analyze Requirement',
|
|
204
|
+
2: 'Implementation Plan',
|
|
205
|
+
3: 'Code Generation',
|
|
206
|
+
4: 'AI Self-Review',
|
|
207
|
+
5: 'Peer Review & PR',
|
|
208
|
+
};
|
|
209
|
+
return labels[n] || `Gate ${n}`;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function buildModeInstruction(mode, gate) {
|
|
213
|
+
if (mode !== 'fast') return ''; // full mode: không inject gì thêm, AI chạy đầy đủ các bước
|
|
214
|
+
|
|
215
|
+
const instructions = {
|
|
216
|
+
2: [
|
|
217
|
+
'**MODE: fast** — Gate 2 fast track:',
|
|
218
|
+
'- Create a simple task list (task-level, NOT step-level)',
|
|
219
|
+
'- DO NOT invoke `superpowers:writing-plans`',
|
|
220
|
+
'- Format: numbered list of tasks, each with file + action',
|
|
221
|
+
'- No code snippets, no step-by-step TDD breakdown required',
|
|
222
|
+
],
|
|
223
|
+
3: [
|
|
224
|
+
'**MODE: fast** — Gate 3 fast track:',
|
|
225
|
+
'- DO NOT use `superpowers:subagent-driven-development`',
|
|
226
|
+
'- DO NOT spawn Spec Reviewer or Code Quality Reviewer subagents',
|
|
227
|
+
'- Implement ALL tasks directly in this session',
|
|
228
|
+
'- Write tests and implementation in the same pass per task',
|
|
229
|
+
'- Run the test suite ONCE at the end of all tasks (not after each step)',
|
|
230
|
+
'- If tests fail: fix inline, do not spawn a subagent',
|
|
231
|
+
],
|
|
232
|
+
4: [
|
|
233
|
+
'**MODE: fast** — Gate 4 fast track:',
|
|
234
|
+
'- Run the full test suite — this is MANDATORY',
|
|
235
|
+
'- Impact Analysis: quick scan only — reason from git diff and changed files.',
|
|
236
|
+
' DO NOT grep the entire codebase. List affected files and assess impact level.',
|
|
237
|
+
'- Review checklist (3 items only): tests pass ✅, no hardcoded secrets ✅, no SQL injection ✅',
|
|
238
|
+
'- summary.md: short format (Implementation table + Test result only)',
|
|
239
|
+
],
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
const lines = instructions[gate];
|
|
243
|
+
return lines ? '\n' + lines.join('\n') : '';
|
|
244
|
+
}
|