@relipa/ai-flow-kit 0.0.6 → 0.0.7-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/README.md +41 -16
- package/bin/aiflow.js +65 -2
- package/custom/mcp-presets/gitnexus.json +8 -0
- package/custom/skills/generate-spec/SKILL.md +7 -0
- package/custom/skills/impact-analysis/SKILL.md +10 -0
- package/custom/skills/investigate-bug/SKILL.md +17 -0
- package/custom/skills/read-study-requirement/SKILL.md +11 -0
- package/custom/skills/review-plan/SKILL.md +15 -0
- package/custom/templates/php-plain.md +261 -0
- package/docs/common/AIFLOW.md +17 -6
- package/docs/common/CHANGELOG.md +63 -5
- package/docs/common/QUICK_START.md +33 -13
- package/docs/common/cli-reference.md +23 -0
- package/package.json +2 -7
- package/scripts/checkpoint.js +46 -0
- package/scripts/doctor.js +111 -8
- package/scripts/gitnexus-worker.js +94 -0
- package/scripts/guide.js +42 -51
- package/scripts/hooks/session-start.js +35 -5
- package/scripts/hooks/session-stop.js +55 -0
- package/scripts/init.js +299 -19
- package/scripts/prompt.js +2 -2
- package/scripts/remove.js +54 -0
- package/scripts/task.js +101 -0
- package/scripts/update.js +14 -4
- package/scripts/use.js +78 -6
- package/upstream/.claude-plugin/marketplace.json +4 -4
- package/upstream/.claude-plugin/plugin.json +2 -4
- package/upstream/.cursor-plugin/plugin.json +2 -4
- package/upstream/docs/plans/2025-11-22-opencode-support-design.md +1 -1
- package/upstream/docs/plans/2025-11-28-skills-improvements-from-user-feedback.md +2 -2
- package/upstream/docs/testing.md +2 -2
- package/upstream/skills/subagent-driven-development/SKILL.md +5 -6
- package/upstream/skills/subagent-driven-development/implementer-prompt.md +2 -3
- package/upstream/skills/systematic-debugging/CREATION-LOG.md +1 -1
- package/upstream/skills/systematic-debugging/root-cause-tracing.md +1 -1
- package/upstream/skills/tdd-lean/SKILL.md +127 -0
- package/upstream/skills/using-git-worktrees/SKILL.md +4 -5
- package/upstream/skills/writing-plans/SKILL.md +3 -9
- package/upstream/tests/brainstorm-server/package-lock.json +36 -0
package/README.md
CHANGED
|
@@ -16,18 +16,18 @@ Developers only need a single command to load ticket context → AI automaticall
|
|
|
16
16
|
| New plugins (superpowers, MCP...) require manual setup | Package auto-sets up hooks, skills, and MCP on init |
|
|
17
17
|
| Missing investigation / bug reproduction flow | Skill `investigate-bug` (inherits systematic-debugging) |
|
|
18
18
|
| Missing impact analysis flow | Skill `impact-analysis` |
|
|
19
|
-
| Hard to resume tasks | **State Resumption**: Unified `plan/` docs and
|
|
19
|
+
| Hard to resume tasks | **State Resumption**: Unified `plan/` docs, `task-summary.md` progress tracking, and intelligent session continuity (automatic Gate 3 resumption). |
|
|
20
20
|
|
|
21
21
|
## Documentation & Guides
|
|
22
22
|
|
|
23
23
|
> [!TIP]
|
|
24
24
|
> After running `aiflow init`, documentation files are automatically copied to `.aiflow/docs/` in your project for easy access.
|
|
25
25
|
|
|
26
|
-
- **[Quick Start Guide](https://
|
|
27
|
-
- **[Full Workflow (5 Gates)](https://
|
|
28
|
-
- **[Troubleshooting](https://
|
|
29
|
-
- **[Integration Guide](https://
|
|
30
|
-
- **[Changelog](https://
|
|
26
|
+
- **[Quick Start Guide](https://github.com/example/ai-flow-kit/blob/main/docs/common/QUICK_START.md)** — Step-by-step instructions for developers.
|
|
27
|
+
- **[Full Workflow (5 Gates)](https://github.com/example/ai-flow-kit/blob/main/docs/common/AIFLOW.md)** — In-depth look at the Gate process.
|
|
28
|
+
- **[Troubleshooting](https://github.com/example/ai-flow-kit/blob/main/docs/common/troubleshooting.md)** — Common issues and fixes.
|
|
29
|
+
- **[Integration Guide](https://github.com/example/ai-flow-kit/blob/main/docs/common/ai-integration.md)** — Advanced tool setup (Claude, Cursor, Gemini).
|
|
30
|
+
- **[Changelog](https://github.com/example/ai-flow-kit/blob/main/docs/common/CHANGELOG.md)** — Version history and release notes.
|
|
31
31
|
|
|
32
32
|
---
|
|
33
33
|
|
|
@@ -52,7 +52,7 @@ PM writes ticket on Backlog/Jira
|
|
|
52
52
|
▼
|
|
53
53
|
⛩️ GATE 3 — Code Generation (TDD) [AI]
|
|
54
54
|
AI writes tests first → implement → tests pass
|
|
55
|
-
|
|
55
|
+
Verify implementation works
|
|
56
56
|
│ Code done
|
|
57
57
|
▼
|
|
58
58
|
⛩️ GATE 4 — AI Self-Review [AI + DEV]
|
|
@@ -74,13 +74,13 @@ PM writes ticket on Backlog/Jira
|
|
|
74
74
|
|
|
75
75
|
```bash
|
|
76
76
|
# Stable version
|
|
77
|
-
npm install -g
|
|
77
|
+
npm install -g ai-flow-kit
|
|
78
78
|
|
|
79
79
|
# Beta version (recommend for newest features)
|
|
80
|
-
npm install -g
|
|
80
|
+
npm install -g ai-flow-kit@beta
|
|
81
81
|
|
|
82
82
|
# Uninstall
|
|
83
|
-
npm uninstall -g
|
|
83
|
+
npm uninstall -g ai-flow-kit
|
|
84
84
|
```
|
|
85
85
|
|
|
86
86
|
---
|
|
@@ -93,6 +93,7 @@ npm uninstall -g @relipa/ai-flow-kit
|
|
|
93
93
|
| `aiflow use <ticket>` | Load ticket context (Backlog/Jira). |
|
|
94
94
|
| `aiflow task` | Manage multiple tasks — pause, switch, resume. |
|
|
95
95
|
| `aiflow prompt` | Generate tool-optimized prompts (`--env cursor`). |
|
|
96
|
+
| `aiflow sync-skills` | Manually synchronize AI Instruction files with local custom skills. |
|
|
96
97
|
| `aiflow telemetry` | Manage telemetry tracking (enable/disable/status). |
|
|
97
98
|
| `aiflow guide` | View integrated multi-AI integration guide. |
|
|
98
99
|
|
|
@@ -104,8 +105,10 @@ Initial setup for the project. Run once per project.
|
|
|
104
105
|
# Single framework + adapter
|
|
105
106
|
aiflow init --framework spring-boot --adapter backlog
|
|
106
107
|
|
|
107
|
-
#
|
|
108
|
-
aiflow init --with-rtk
|
|
108
|
+
# Enable token savings tools
|
|
109
|
+
aiflow init --with-rtk # RTK: compress bash outputs (60–90% reduction)
|
|
110
|
+
# aiflow init --with-gitnexus # GitNexus: code intelligence (waits for index)
|
|
111
|
+
# aiflow init --with-gitnexus --no-wait # GitNexus: index in background
|
|
109
112
|
|
|
110
113
|
# Multiple frameworks and adapters
|
|
111
114
|
aiflow init --framework spring-boot,reactjs --adapter backlog,jira
|
|
@@ -120,12 +123,27 @@ aiflow init --framework spring-boot,reactjs --adapter backlog,jira
|
|
|
120
123
|
- `.mcp.json` + Claude Desktop config — MCP adapter
|
|
121
124
|
- `.aiflow/credentials.json` — save API credentials
|
|
122
125
|
|
|
123
|
-
**Supported Frameworks:** `spring-boot`, `laravel`, `reactjs`, `nextjs`, `vue-nuxt`
|
|
126
|
+
**Supported Frameworks:** `spring-boot`, `laravel`, `php-plain`, `nestjs`, `reactjs`, `nextjs`, `vue-nuxt`, `nodejs-express`, `python-django`, `python-fastapi`
|
|
124
127
|
|
|
125
128
|
**Supported Adapters:** `backlog`, `jira`, `google-sheets`, `figma`
|
|
126
129
|
|
|
127
130
|
---
|
|
128
131
|
|
|
132
|
+
### `aiflow sync-skills`
|
|
133
|
+
|
|
134
|
+
Synchronize AI instruction files (`CLAUDE.md`, `GEMINI.md`, etc.) and Skills without upgrading the package version.
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
aiflow sync-skills
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
**Features:**
|
|
141
|
+
- Intelligent marker-based updates (`<!-- aiflow-kit-start -->`)
|
|
142
|
+
- Confirmation prompts before overwriting custom rules
|
|
143
|
+
- English notifications and status reports
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
129
147
|
### `aiflow use <ticket>`
|
|
130
148
|
|
|
131
149
|
Load ticket context into `.aiflow/context/current.json`.
|
|
@@ -154,7 +172,7 @@ aiflow use PROJ-33 --comments-from 3
|
|
|
154
172
|
aiflow use --manual
|
|
155
173
|
|
|
156
174
|
# Load from local file (JSON or plain text)
|
|
157
|
-
aiflow use --file task.md
|
|
175
|
+
aiflow use --file task.md # Auto-generates taskId from filename & prompts for taskType
|
|
158
176
|
|
|
159
177
|
# Modes (Fast is default)
|
|
160
178
|
aiflow use PROJ-33 # Fast Mode: skip Q&A, target < 5 min
|
|
@@ -179,6 +197,8 @@ aiflow task switch PROJ-99 # pause current + switch to another task
|
|
|
179
197
|
aiflow task resume PROJ-33 # resume a paused task (restores context + gate state)
|
|
180
198
|
aiflow task reset PROJ-33 # reset to Gate 1 (keeps ticket context, clears progress)
|
|
181
199
|
aiflow task remove PROJ-33 # permanently delete all saved data for the task
|
|
200
|
+
aiflow task next # approve current gate + prepare for fresh session
|
|
201
|
+
aiflow task next --ticket PROJ-33 # same, but specify ticket explicitly
|
|
182
202
|
```
|
|
183
203
|
|
|
184
204
|
**Use case — switching tasks mid-flow:**
|
|
@@ -285,9 +305,14 @@ aiflow memory list
|
|
|
285
305
|
|-----------|---------|--------------|
|
|
286
306
|
| `spring-boot` | Java 17+ | `rules/java/` |
|
|
287
307
|
| `laravel` | PHP 8.1+ | `rules/php/` |
|
|
308
|
+
| `php-plain` | PHP 8.1+ (no framework) | `rules/php/` |
|
|
309
|
+
| `nestjs` | TypeScript | `rules/javascript/` |
|
|
288
310
|
| `reactjs` | TypeScript | `rules/javascript/` |
|
|
289
311
|
| `nextjs` | TypeScript | `rules/javascript/` |
|
|
290
312
|
| `vue-nuxt` | TypeScript | `rules/javascript/` |
|
|
313
|
+
| `nodejs-express` | JavaScript/TypeScript | `rules/javascript/` |
|
|
314
|
+
| `python-django` | Python | — |
|
|
315
|
+
| `python-fastapi` | Python | — |
|
|
291
316
|
|
|
292
317
|
---
|
|
293
318
|
|
|
@@ -337,7 +362,7 @@ ai-flow-kit/
|
|
|
337
362
|
|
|
338
363
|
**Custom skill:** create `custom/skills/<name>/SKILL.md`
|
|
339
364
|
|
|
340
|
-
Then run `aiflow update` to apply.
|
|
365
|
+
Then run `aiflow update` or `aiflow sync-skills` to apply.
|
|
341
366
|
|
|
342
367
|
---
|
|
343
368
|
|
|
@@ -355,7 +380,7 @@ Then run `aiflow update` to apply.
|
|
|
355
380
|
|
|
356
381
|
**`aiflow` not found:**
|
|
357
382
|
```bash
|
|
358
|
-
npm install -g
|
|
383
|
+
npm install -g ai-flow-kit
|
|
359
384
|
```
|
|
360
385
|
|
|
361
386
|
**Backlog load fails:**
|
package/bin/aiflow.js
CHANGED
|
@@ -16,6 +16,7 @@ const removeCommand = require('../scripts/remove');
|
|
|
16
16
|
const guideCommand = require('../scripts/guide');
|
|
17
17
|
const telemetryCommand= require('../scripts/telemetry/cli');
|
|
18
18
|
const taskCommand = require('../scripts/task');
|
|
19
|
+
const checkpointCommand = require('../scripts/checkpoint');
|
|
19
20
|
const { record } = require('../scripts/telemetry/record');
|
|
20
21
|
|
|
21
22
|
program
|
|
@@ -63,6 +64,8 @@ program
|
|
|
63
64
|
.option('-e, --env <types>', 'AI environment(s)/tool(s), comma-separated (e.g. cursor,gemini,copilot)')
|
|
64
65
|
.option('--with-rtk', 'force enable RTK token compression hook')
|
|
65
66
|
.option('--no-rtk', 'skip RTK setup even if RTK is detected')
|
|
67
|
+
// .option('--with-gitnexus', 'enable GitNexus code intelligence (indexes in background)')
|
|
68
|
+
// .option('--wait', 'wait for GitNexus indexing to complete before exiting')
|
|
66
69
|
.action((options) => {
|
|
67
70
|
options.frameworks = options.framework
|
|
68
71
|
? options.framework.split(',').map(s => s.trim()).filter(Boolean)
|
|
@@ -162,6 +165,15 @@ taskCmd
|
|
|
162
165
|
.description('Permanently delete all saved data for a task')
|
|
163
166
|
.action((ticketId) => { record('command.invoked', { command: 'task.remove' }); taskCommand('remove', { taskId: ticketId }); });
|
|
164
167
|
|
|
168
|
+
taskCmd
|
|
169
|
+
.command('next')
|
|
170
|
+
.description('Approve current gate and prepare next session (saves state for resume)')
|
|
171
|
+
.option('-t, --ticket <id>', 'ticket ID (defaults to active task)')
|
|
172
|
+
.action((opts) => {
|
|
173
|
+
record('command.invoked', { command: 'task.next' });
|
|
174
|
+
taskCommand('next', { taskId: opts.ticket });
|
|
175
|
+
});
|
|
176
|
+
|
|
165
177
|
// ── context ───────────────────────────────────────────────────
|
|
166
178
|
program
|
|
167
179
|
.command('context [action]')
|
|
@@ -176,6 +188,19 @@ program
|
|
|
176
188
|
contextCommand(action, options);
|
|
177
189
|
});
|
|
178
190
|
|
|
191
|
+
// ── checkpoint ────────────────────────────────────────────────
|
|
192
|
+
program
|
|
193
|
+
.command('checkpoint')
|
|
194
|
+
.description('Record token usage checkpoint (called by AI during gate work)')
|
|
195
|
+
.requiredOption('--gate <n>', 'gate number (1–5)', parseInt)
|
|
196
|
+
.requiredOption('--step <name>', 'step name (e.g. "tests-written")')
|
|
197
|
+
.requiredOption('--tokens <n>', 'estimated token count', parseInt)
|
|
198
|
+
.option('-t, --ticket <id>', 'ticket ID (defaults to active task)')
|
|
199
|
+
.action((opts) => {
|
|
200
|
+
record('command.invoked', { command: 'checkpoint' });
|
|
201
|
+
checkpointCommand({ gate: opts.gate, step: opts.step, tokens: opts.tokens, ticket: opts.ticket });
|
|
202
|
+
});
|
|
203
|
+
|
|
179
204
|
// ── validate ──────────────────────────────────────────────────
|
|
180
205
|
program
|
|
181
206
|
.command('validate <file>')
|
|
@@ -253,6 +278,13 @@ program
|
|
|
253
278
|
command: `gate${gateNum}.${action}`,
|
|
254
279
|
ai_tool: options.aiTool || ''
|
|
255
280
|
});
|
|
281
|
+
|
|
282
|
+
if (action === 'approved') {
|
|
283
|
+
console.log(chalk.cyan(`\n Gate ${gateNum} approved!`));
|
|
284
|
+
console.log(chalk.yellow(` Pro-Tip: To avoid context pollution, it's recommended to start a fresh chat session.`));
|
|
285
|
+
console.log(chalk.gray(` Run: aiflow task next${options.ticket ? ` --ticket ${options.ticket}` : ''} to save progress,`));
|
|
286
|
+
console.log(chalk.gray(` then open a NEW chatbox and type "continue".\n`));
|
|
287
|
+
}
|
|
256
288
|
});
|
|
257
289
|
|
|
258
290
|
// ── remove ────────────────────────────────────────────────────
|
|
@@ -276,14 +308,45 @@ program
|
|
|
276
308
|
updateCommand(options);
|
|
277
309
|
});
|
|
278
310
|
|
|
311
|
+
// ── sync-skills ───────────────────────────────────────────────
|
|
312
|
+
program
|
|
313
|
+
.command('sync-skills')
|
|
314
|
+
.description('Manually synchronize AI Instruction files with local custom skills')
|
|
315
|
+
.action(async () => {
|
|
316
|
+
record('command.invoked', { command: 'sync-skills' });
|
|
317
|
+
const projectDir = process.cwd();
|
|
318
|
+
const { setupFramework, AI_TOOL_FILES, ensureAiflowGitignored } = require('../scripts/init');
|
|
319
|
+
const fs = require('fs-extra');
|
|
320
|
+
const path = require('path');
|
|
321
|
+
const chalk = require('chalk');
|
|
322
|
+
|
|
323
|
+
const stateFile = path.join(projectDir, '.aiflow', 'state.json');
|
|
324
|
+
if (!(await fs.pathExists(stateFile))) {
|
|
325
|
+
console.log(chalk.red('Project is not initialized. Please run `aiflow init` first.'));
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
const state = await fs.readJson(stateFile);
|
|
330
|
+
const frameworks = state.frameworks || [];
|
|
331
|
+
const selectedTools = state.aiTools || Object.keys(AI_TOOL_FILES);
|
|
332
|
+
|
|
333
|
+
console.log(chalk.cyan('⟳ Syncing AI Instruction files...'));
|
|
334
|
+
for (const fw of frameworks) {
|
|
335
|
+
await setupFramework(projectDir, fw, frameworks.length > 1, selectedTools);
|
|
336
|
+
}
|
|
337
|
+
await ensureAiflowGitignored(projectDir);
|
|
338
|
+
console.log(chalk.green('✨ Sync completed!'));
|
|
339
|
+
});
|
|
340
|
+
|
|
279
341
|
// ── doctor ────────────────────────────────────────────────────
|
|
280
342
|
program
|
|
281
343
|
.command('doctor')
|
|
282
344
|
.description('Health check of AI Flow Kit setup')
|
|
345
|
+
.option('-t, --ticket <id>', 'show token breakdown for specific ticket')
|
|
283
346
|
.option('-v, --verbose', 'detailed output')
|
|
284
|
-
.action(() => {
|
|
347
|
+
.action((opts) => {
|
|
285
348
|
record('command.invoked', { command: 'doctor' });
|
|
286
|
-
doctorCommand();
|
|
349
|
+
doctorCommand({ ticket: opts.ticket, verbose: opts.verbose });
|
|
287
350
|
});
|
|
288
351
|
|
|
289
352
|
// ── telemetry ──────────────────────────────────────────────────
|
|
@@ -17,6 +17,13 @@ keywords: spec, plan, implementation, tdd, coding plan
|
|
|
17
17
|
- ✅ Gate 1 APPROVED — `plan/[ticket-id]/requirement.md` reviewed and approved by DEV
|
|
18
18
|
- ✅ Requirement document includes: requirements, solution, impact analysis, estimate
|
|
19
19
|
|
|
20
|
+
## Fast Mode Output Rules (CRITICAL)
|
|
21
|
+
|
|
22
|
+
When updating `plan/[ticket-id]/summary.md` in **fast mode**:
|
|
23
|
+
- **Keep it extremely short.**
|
|
24
|
+
- Add a bullet point indicating Gate 2 plan is ready.
|
|
25
|
+
- **DO NOT copy the entire plan.md into summary.md.**
|
|
26
|
+
|
|
20
27
|
---
|
|
21
28
|
|
|
22
29
|
## Process
|
|
@@ -20,6 +20,16 @@ keywords: impact, refactor, breaking change, scope
|
|
|
20
20
|
|
|
21
21
|
### Step 1: Find all usage (Dependency Map)
|
|
22
22
|
|
|
23
|
+
**Preferred — If GitNexus MCP is available** (`.mcp.json` has `gitnexus` entry):
|
|
24
|
+
```
|
|
25
|
+
impact("ClassName") → structured blast radius: callers, dependents, risk score
|
|
26
|
+
detect_changes() → reads current git diff, maps changed lines → affected symbols
|
|
27
|
+
```
|
|
28
|
+
- Use `impact()` when you know the class/function name being modified.
|
|
29
|
+
- Use `detect_changes()` when starting Gate 4 review — it auto-detects what changed from git diff without needing to specify names.
|
|
30
|
+
- One call replaces all grep commands below. Proceed directly to Step 2 with the result.
|
|
31
|
+
|
|
32
|
+
**Fallback — grep manually** (if GitNexus not configured):
|
|
23
33
|
```bash
|
|
24
34
|
# Find all files importing/calling the class/function being modified
|
|
25
35
|
grep -r "ClassName\|functionName\|methodName" --include="*.php" .
|
|
@@ -50,6 +50,23 @@ Route / Controller
|
|
|
50
50
|
→ Database
|
|
51
51
|
```
|
|
52
52
|
|
|
53
|
+
**NestJS**
|
|
54
|
+
```
|
|
55
|
+
Controller (@Controller)
|
|
56
|
+
→ Service (@Injectable)
|
|
57
|
+
→ Repository / TypeORM Entity
|
|
58
|
+
→ Database
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**PHP Plain (no framework)**
|
|
62
|
+
```
|
|
63
|
+
index.php (router)
|
|
64
|
+
→ Controller
|
|
65
|
+
→ Service
|
|
66
|
+
→ Repository (PDO)
|
|
67
|
+
→ Database
|
|
68
|
+
```
|
|
69
|
+
|
|
53
70
|
**React / Next.js**
|
|
54
71
|
```
|
|
55
72
|
Page / Route component
|
|
@@ -28,6 +28,13 @@ Check `mode` in `.aiflow/context/current.json` before starting:
|
|
|
28
28
|
|
|
29
29
|
> Target: Gate 1 complete in **< 5 minutes**, minimum token usage.
|
|
30
30
|
|
|
31
|
+
## Fast Mode Output Rules (CRITICAL)
|
|
32
|
+
|
|
33
|
+
When creating `plan/[ticket-id]/summary.md` during Gate 1:
|
|
34
|
+
- You must create the `summary.md` file after Gate 1 is APPROVED, to track session progress.
|
|
35
|
+
- Keep `summary.md` concise. Only include short bullet points tracking Gates.
|
|
36
|
+
- Do not write verbose implementation details in `summary.md` at Gate 1.
|
|
37
|
+
|
|
31
38
|
1. Read `.aiflow/context/current.json` — ticket title, description, acceptance criteria
|
|
32
39
|
2. Identify **directly affected files** from ticket text and file names only.
|
|
33
40
|
DO NOT trace data flow or read unrelated source files.
|
|
@@ -73,6 +80,10 @@ Check `mode` in `.aiflow/context/current.json` before starting:
|
|
|
73
80
|
1. Read `.aiflow/context/current.json` — ticket info from Backlog/Jira
|
|
74
81
|
2. Read `CLAUDE.md` — understand project architecture, tech stack, conventions
|
|
75
82
|
3. Read related source files — trace data flow, identify patterns, dependencies
|
|
83
|
+
- **If GitNexus MCP is available** (`.mcp.json` has `gitnexus` entry): invoke GitNexus MCP tools instead of reading files directly — one call returns full context without multi-file exploration:
|
|
84
|
+
- `gitnexus: context("ClassName")` → 360° view of a symbol (dependencies, callers, methods)
|
|
85
|
+
- `gitnexus: query("keyword or description")` → hybrid search across codebase
|
|
86
|
+
- Saves ~50% of token cost at this step vs reading files manually
|
|
76
87
|
- **If task is a Bug Fix:** Invoke `superpowers:systematic-debugging` to trace root cause before proposing fixes.
|
|
77
88
|
4. Read ticket comments — additional context from PM/team
|
|
78
89
|
|
|
@@ -41,6 +41,21 @@ Assess impact by reasoning about the changed files only:
|
|
|
41
41
|
- [ ] No hardcoded credentials or secrets
|
|
42
42
|
- [ ] No SQL injection risk in new queries
|
|
43
43
|
|
|
44
|
+
## Fast Mode Output Rules (CRITICAL)
|
|
45
|
+
|
|
46
|
+
When creating `plan/[ticket-id]/summary.md` in **fast mode**:
|
|
47
|
+
- **Do not write long explanations or descriptions.**
|
|
48
|
+
- **List format only:** Bullet points with `[NEW]`, `[MODIFIED]`, `[DELETED]`.
|
|
49
|
+
- **Purpose:** Next to each file, write exactly 1 sentence explaining the *purpose* (the "why"), not the implementation details.
|
|
50
|
+
|
|
51
|
+
**Example summary.md block:**
|
|
52
|
+
```markdown
|
|
53
|
+
### Gate 3 — Code
|
|
54
|
+
- ✅ **Implemented batch endpoints**
|
|
55
|
+
- \`[NEW] src/controllers/BatchController.ts\`: Handle bulk export requests
|
|
56
|
+
- \`[MODIFIED] src/services/ExportService.ts\`: Added S3 upload integration
|
|
57
|
+
```
|
|
58
|
+
|
|
44
59
|
---
|
|
45
60
|
|
|
46
61
|
## Process
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
# PHP Plain AI System Prompt
|
|
2
|
+
|
|
3
|
+
You are an expert PHP developer working with plain PHP (no framework). Follow these rules to produce clean, secure, maintainable code.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Architecture
|
|
8
|
+
|
|
9
|
+
Organise code in a layered structure. Avoid writing logic directly in view files.
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
public/ # Web root — index.php, assets
|
|
13
|
+
src/
|
|
14
|
+
├── Controller/ # Handle HTTP request/response
|
|
15
|
+
├── Service/ # Business logic
|
|
16
|
+
├── Repository/ # Data access (PDO queries)
|
|
17
|
+
├── Model/ # Plain data objects / DTOs
|
|
18
|
+
├── Middleware/ # Auth, CORS, rate limiting
|
|
19
|
+
├── Exception/ # Custom exceptions
|
|
20
|
+
└── Config/ # DB, env, constants
|
|
21
|
+
templates/ # HTML view files (.php/.html)
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Coding Rules
|
|
27
|
+
|
|
28
|
+
### General
|
|
29
|
+
|
|
30
|
+
- Use **PHP 8.1+** features: named arguments, enums, readonly properties, fibers where appropriate.
|
|
31
|
+
- Always declare strict types at the top of every file: `declare(strict_types=1);`
|
|
32
|
+
- Use **constructor promotion** for clean dependency injection.
|
|
33
|
+
- Follow **PSR-12** coding style.
|
|
34
|
+
- Prefer `match` over long `switch` blocks.
|
|
35
|
+
- Never suppress errors with `@` — handle them properly.
|
|
36
|
+
|
|
37
|
+
```php
|
|
38
|
+
// ✅ Good
|
|
39
|
+
declare(strict_types=1);
|
|
40
|
+
|
|
41
|
+
class UserService
|
|
42
|
+
{
|
|
43
|
+
public function __construct(
|
|
44
|
+
private readonly UserRepository $userRepository,
|
|
45
|
+
) {}
|
|
46
|
+
|
|
47
|
+
public function findById(int $id): UserDto
|
|
48
|
+
{
|
|
49
|
+
$user = $this->userRepository->findById($id);
|
|
50
|
+
if ($user === null) {
|
|
51
|
+
throw new NotFoundException("User $id not found");
|
|
52
|
+
}
|
|
53
|
+
return UserDto::fromArray($user);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// ❌ Bad — no strict types, logic in global scope
|
|
58
|
+
$pdo = new PDO(...);
|
|
59
|
+
$user = $pdo->query("SELECT * FROM users WHERE id = $_GET[id]")->fetch();
|
|
60
|
+
echo $user['name'];
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
### Security Rules (CRITICAL)
|
|
66
|
+
|
|
67
|
+
- **NEVER** interpolate user input into SQL — always use **PDO prepared statements**.
|
|
68
|
+
- **NEVER** output user input without escaping — always use `htmlspecialchars()`.
|
|
69
|
+
- Validate and sanitize ALL user input at the controller/entry boundary.
|
|
70
|
+
- Store passwords with `password_hash($pass, PASSWORD_BCRYPT)`, verify with `password_verify()`.
|
|
71
|
+
- Use `random_bytes()` / `bin2hex(random_bytes(32))` for tokens — never `rand()` or `md5()`.
|
|
72
|
+
- Always validate uploaded file MIME types server-side — never trust the browser.
|
|
73
|
+
|
|
74
|
+
```php
|
|
75
|
+
// ✅ Good — prepared statement
|
|
76
|
+
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = :email');
|
|
77
|
+
$stmt->execute([':email' => $email]);
|
|
78
|
+
$user = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
79
|
+
|
|
80
|
+
// ✅ Good — safe HTML output
|
|
81
|
+
echo htmlspecialchars($user['name'], ENT_QUOTES, 'UTF-8');
|
|
82
|
+
|
|
83
|
+
// ❌ Bad — SQL injection
|
|
84
|
+
$result = $pdo->query("SELECT * FROM users WHERE email = '$email'");
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
### Database / Repository Rules
|
|
90
|
+
|
|
91
|
+
- All DB access goes through Repository classes — never call PDO from controllers or services.
|
|
92
|
+
- Use PDO with `PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION`.
|
|
93
|
+
- Wrap multi-step writes in transactions.
|
|
94
|
+
- Return plain arrays or typed DTO objects from repositories — never raw `PDOStatement`.
|
|
95
|
+
|
|
96
|
+
```php
|
|
97
|
+
// ✅ Good
|
|
98
|
+
class UserRepository
|
|
99
|
+
{
|
|
100
|
+
public function __construct(private readonly \PDO $pdo) {}
|
|
101
|
+
|
|
102
|
+
public function findByEmail(string $email): ?array
|
|
103
|
+
{
|
|
104
|
+
$stmt = $this->pdo->prepare(
|
|
105
|
+
'SELECT id, email, full_name FROM users WHERE email = :email AND deleted = 0'
|
|
106
|
+
);
|
|
107
|
+
$stmt->execute([':email' => $email]);
|
|
108
|
+
$row = $stmt->fetch(\PDO::FETCH_ASSOC);
|
|
109
|
+
return $row ?: null;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
public function create(string $email, string $fullName, string $passwordHash): int
|
|
113
|
+
{
|
|
114
|
+
$stmt = $this->pdo->prepare(
|
|
115
|
+
'INSERT INTO users (email, full_name, password_hash) VALUES (:email, :full_name, :password_hash)'
|
|
116
|
+
);
|
|
117
|
+
$stmt->execute([
|
|
118
|
+
':email' => $email,
|
|
119
|
+
':full_name' => $fullName,
|
|
120
|
+
':password_hash' => $passwordHash,
|
|
121
|
+
]);
|
|
122
|
+
return (int) $this->pdo->lastInsertId();
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
### Controller Rules
|
|
130
|
+
|
|
131
|
+
- Controllers handle HTTP only: parse input, call service, output response.
|
|
132
|
+
- Never put business logic or direct DB calls in controllers.
|
|
133
|
+
- Validate input before passing to the service layer.
|
|
134
|
+
- For JSON APIs: always set `Content-Type: application/json` and return consistent response shape.
|
|
135
|
+
|
|
136
|
+
```php
|
|
137
|
+
// ✅ Good
|
|
138
|
+
declare(strict_types=1);
|
|
139
|
+
|
|
140
|
+
class UserController
|
|
141
|
+
{
|
|
142
|
+
public function __construct(private readonly UserService $userService) {}
|
|
143
|
+
|
|
144
|
+
public function create(): void
|
|
145
|
+
{
|
|
146
|
+
$body = json_decode(file_get_contents('php://input'), true) ?? [];
|
|
147
|
+
$email = trim($body['email'] ?? '');
|
|
148
|
+
$fullName = trim($body['full_name'] ?? '');
|
|
149
|
+
$password = $body['password'] ?? '';
|
|
150
|
+
|
|
151
|
+
if ($email === '' || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
|
152
|
+
http_response_code(400);
|
|
153
|
+
echo json_encode(['error' => 'Invalid email']);
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
$user = $this->userService->create($email, $fullName, $password);
|
|
158
|
+
http_response_code(201);
|
|
159
|
+
echo json_encode($user);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
### Error Handling
|
|
167
|
+
|
|
168
|
+
- Define custom exception classes (`NotFoundException`, `ValidationException`, etc.).
|
|
169
|
+
- Register a global exception handler via `set_exception_handler()`.
|
|
170
|
+
- Never expose stack traces or internal paths to the client.
|
|
171
|
+
- Log errors to a file/syslog with a timestamp and context.
|
|
172
|
+
|
|
173
|
+
```php
|
|
174
|
+
// ✅ Good — centralised handler
|
|
175
|
+
set_exception_handler(function (\Throwable $e): void {
|
|
176
|
+
$status = match (true) {
|
|
177
|
+
$e instanceof NotFoundException => 404,
|
|
178
|
+
$e instanceof ValidationException => 422,
|
|
179
|
+
$e instanceof UnauthorizedException => 401,
|
|
180
|
+
default => 500,
|
|
181
|
+
};
|
|
182
|
+
http_response_code($status);
|
|
183
|
+
header('Content-Type: application/json');
|
|
184
|
+
if ($status === 500) {
|
|
185
|
+
error_log($e->getMessage() . ' ' . $e->getTraceAsString());
|
|
186
|
+
echo json_encode(['error' => 'Internal server error']);
|
|
187
|
+
} else {
|
|
188
|
+
echo json_encode(['error' => $e->getMessage()]);
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
### Autoloading
|
|
196
|
+
|
|
197
|
+
- Use **Composer autoload** (PSR-4) — no manual `require` chains.
|
|
198
|
+
- `composer.json` minimum:
|
|
199
|
+
|
|
200
|
+
```json
|
|
201
|
+
{
|
|
202
|
+
"autoload": {
|
|
203
|
+
"psr-4": {
|
|
204
|
+
"App\\": "src/"
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## Naming Conventions
|
|
213
|
+
|
|
214
|
+
| Element | Convention | Example |
|
|
215
|
+
|---------|-----------|---------|
|
|
216
|
+
| Class | PascalCase | `UserService`, `OrderRepository` |
|
|
217
|
+
| Method | camelCase | `findById`, `createOrder` |
|
|
218
|
+
| Variable | camelCase | `$userId`, `$orderList` |
|
|
219
|
+
| Constant | UPPER_SNAKE_CASE | `MAX_LOGIN_ATTEMPTS` |
|
|
220
|
+
| DB table | snake_case | `user_orders` |
|
|
221
|
+
| DB column | snake_case | `created_at` |
|
|
222
|
+
| File | Matches class name | `UserService.php` |
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## Testing Rules
|
|
227
|
+
|
|
228
|
+
- Use **PHPUnit** for unit and integration tests.
|
|
229
|
+
- Test class mirrors source path: `tests/Service/UserServiceTest.php`.
|
|
230
|
+
- Mock dependencies with `$this->createMock()` or a stub.
|
|
231
|
+
- Cover: happy path, validation errors, not-found cases.
|
|
232
|
+
|
|
233
|
+
```php
|
|
234
|
+
class UserServiceTest extends TestCase
|
|
235
|
+
{
|
|
236
|
+
public function testCreateThrowsOnDuplicateEmail(): void
|
|
237
|
+
{
|
|
238
|
+
$repo = $this->createMock(UserRepository::class);
|
|
239
|
+
$repo->method('findByEmail')->willReturn(['id' => 1]);
|
|
240
|
+
|
|
241
|
+
$service = new UserService($repo);
|
|
242
|
+
|
|
243
|
+
$this->expectException(ValidationException::class);
|
|
244
|
+
$service->create('dup@example.com', 'Test', 'password');
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
## Anti-Patterns to Avoid
|
|
252
|
+
|
|
253
|
+
- ❌ Raw SQL in controllers or views
|
|
254
|
+
- ❌ User input directly in SQL / HTML output
|
|
255
|
+
- ❌ Global `$_GET` / `$_POST` access outside the controller boundary
|
|
256
|
+
- ❌ `die()` / `exit()` for error handling — use exceptions
|
|
257
|
+
- ❌ Storing plain-text passwords
|
|
258
|
+
- ❌ `include`/`require` inside business logic — use autoloading
|
|
259
|
+
- ❌ Logic-heavy view files (`.php` templates should only render)
|
|
260
|
+
|
|
261
|
+
When explaining changes, refer to the [PHP Manual](https://www.php.net/manual) and [PSR standards](https://www.php-fig.org/psr/).
|