@tungvivas/angular-vibe-kit 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +145 -12
- package/agents/angular-a11y-auditor.md +71 -0
- package/agents/angular-build-fixer.md +37 -0
- package/agents/angular-debugger.md +38 -0
- package/agents/angular-git-workflow.md +46 -0
- package/agents/angular-onboarding.md +56 -0
- package/agents/angular-reviewer.md +22 -0
- package/agents/angular-test-writer.md +26 -0
- package/agents/angular-ui-designer.md +55 -0
- package/bin/cli.js +131 -5
- package/commands/dev-cycle.md +44 -12
- package/commands/init.md +9 -3
- package/commands/new-feature.md +22 -43
- package/commands/plan.md +136 -0
- package/commands/review-pr.md +12 -71
- package/commands/write-tests.md +9 -107
- package/package.json +9 -3
- package/references/feature-structure.md +44 -0
- package/references/plan-spec.md +112 -0
- package/references/review-checklist.md +88 -0
- package/references/test-spec.md +92 -0
- package/skills/angular-practices/SKILL.md +34 -0
- package/skills/clarify-request/SKILL.md +100 -0
- package/skills/component-wrapper-priority/SKILL.md +38 -0
- package/skills/explain/SKILL.md +102 -0
- package/skills/explain/templates/vi.md +184 -0
- package/skills/git-commit/SKILL.md +107 -0
- package/skills/git-commit/references/conventions.md +100 -0
- package/templates/docs/srs/README.md +29 -0
- package/templates/rules/project-rules.md +8 -0
package/bin/cli.js
CHANGED
|
@@ -13,15 +13,18 @@
|
|
|
13
13
|
* PROJECT-STATUS.md
|
|
14
14
|
* decisions/
|
|
15
15
|
* .claude/
|
|
16
|
-
* commands/ ←
|
|
16
|
+
* commands/ ← 8 slash-commands
|
|
17
17
|
* angular-practices/<ver>.md ← version-matched best-practice file
|
|
18
|
+
* skills/ ← skills Claude auto-applies (no command needed)
|
|
19
|
+
* agents/ ← Angular subagents (isolated context, run in parallel)
|
|
20
|
+
* settings.json ← allowlist (fewer prompts) + build-verify hook
|
|
18
21
|
* rules/
|
|
19
22
|
* project-rules.md ← auto-loaded by Claude Code every session
|
|
20
23
|
*
|
|
21
24
|
* Generation (filling in actual content) happens later via /init in Claude Code.
|
|
22
25
|
*/
|
|
23
26
|
|
|
24
|
-
import { existsSync, mkdirSync, readFileSync, copyFileSync, readdirSync, statSync } from "node:fs";
|
|
27
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync, copyFileSync, readdirSync, statSync } from "node:fs";
|
|
25
28
|
import { fileURLToPath } from "node:url";
|
|
26
29
|
import { dirname, join, resolve, relative } from "node:path";
|
|
27
30
|
import { createRequire } from "node:module";
|
|
@@ -71,8 +74,11 @@ ${c.bold}Options${c.reset}
|
|
|
71
74
|
${c.bold}What gets created${c.reset}
|
|
72
75
|
CLAUDE.md ← project root entry point
|
|
73
76
|
docs/ ← reference docs (fill in with /init)
|
|
74
|
-
.claude/commands/ ←
|
|
77
|
+
.claude/commands/ ← 8 slash-commands
|
|
75
78
|
.claude/angular-practices/ ← version-matched best-practice file
|
|
79
|
+
.claude/skills/ ← skills Claude auto-applies (no command needed)
|
|
80
|
+
.claude/agents/ ← Angular subagents (isolated context, run in parallel)
|
|
81
|
+
.claude/settings.json ← allowlist (fewer prompts) + build-verify hook
|
|
76
82
|
.claude/rules/project-rules.md ← auto-loaded every Claude Code session`);
|
|
77
83
|
}
|
|
78
84
|
|
|
@@ -147,6 +153,76 @@ function copyDir(srcDir, destDir, cwd) {
|
|
|
147
153
|
}
|
|
148
154
|
}
|
|
149
155
|
|
|
156
|
+
// Write generated content to a file, honoring --force / --dry-run like copyOne.
|
|
157
|
+
function writeOne(content, dest, cwd) {
|
|
158
|
+
const rel = relative(cwd, dest);
|
|
159
|
+
if (existsSync(dest) && !flags.force) {
|
|
160
|
+
warn(`skip (exists): ${rel}`);
|
|
161
|
+
skipped++;
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
if (flags.dryRun) {
|
|
165
|
+
log(`${c.dim}would create → ${rel}${c.reset}`);
|
|
166
|
+
copied++;
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
ensureDir(dirname(dest));
|
|
170
|
+
writeFileSync(dest, content);
|
|
171
|
+
ok(rel);
|
|
172
|
+
copied++;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Angular profile filename → human label for the skill description.
|
|
176
|
+
// e.g. "v20plus.md" → "v20+", "v18-19.md" → "v18-19", "v17.md" → "v17"
|
|
177
|
+
function profileLabel(practiceFile) {
|
|
178
|
+
return practiceFile.replace(/\.md$/, "").replace(/plus$/, "+");
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Detect the package manager from the target project's lockfile.
|
|
182
|
+
function detectPackageManager(cwd) {
|
|
183
|
+
if (existsSync(join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
184
|
+
if (existsSync(join(cwd, "yarn.lock"))) return "yarn";
|
|
185
|
+
return "npm";
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Resolve the build-verify command for the Stop hook. Prefers a project "typecheck"
|
|
189
|
+
// script; otherwise falls back to a fast type-check (npx tsc --noEmit). Returns null
|
|
190
|
+
// only if there is no package.json at all.
|
|
191
|
+
function buildVerifyCommand(cwd) {
|
|
192
|
+
const pkgPath = join(cwd, "package.json");
|
|
193
|
+
if (!existsSync(pkgPath)) return null;
|
|
194
|
+
const pm = detectPackageManager(cwd);
|
|
195
|
+
try {
|
|
196
|
+
const raw = readFileSync(pkgPath, "utf8").replace(/^/, "");
|
|
197
|
+
const scripts = (JSON.parse(raw).scripts) || {};
|
|
198
|
+
if (scripts.typecheck) return pm === "npm" ? "npm run typecheck" : `${pm} typecheck`;
|
|
199
|
+
} catch { /* fall through to tsc */ }
|
|
200
|
+
// Fast type-check that works without an Angular-specific script.
|
|
201
|
+
// Swap for `ng build` / `${pm} run build` if you want full template checking.
|
|
202
|
+
return "npx tsc --noEmit";
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Build the .claude/settings.json object: a safe allowlist + (optionally) a Stop hook
|
|
206
|
+
// that type-checks only when .ts/.html files changed since HEAD (skips question-only turns).
|
|
207
|
+
function buildSettings(cwd) {
|
|
208
|
+
const settings = {
|
|
209
|
+
permissions: {
|
|
210
|
+
allow: [
|
|
211
|
+
"Bash(ng *)", "Bash(npm *)", "Bash(npx *)", "Bash(pnpm *)", "Bash(yarn *)",
|
|
212
|
+
"Bash(git status *)", "Bash(git diff *)", "Bash(git log *)", "Bash(git show *)",
|
|
213
|
+
],
|
|
214
|
+
},
|
|
215
|
+
};
|
|
216
|
+
const buildCmd = buildVerifyCommand(cwd);
|
|
217
|
+
if (buildCmd) {
|
|
218
|
+
const hookCmd = `git diff --quiet HEAD -- '*.ts' '*.html' || ${buildCmd}`;
|
|
219
|
+
settings.hooks = {
|
|
220
|
+
Stop: [{ hooks: [{ type: "command", command: hookCmd }] }],
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
return { settings, buildCmd };
|
|
224
|
+
}
|
|
225
|
+
|
|
150
226
|
// --- main -----------------------------------------------------------------
|
|
151
227
|
function main() {
|
|
152
228
|
if (flags.help) { printHelp(); return; }
|
|
@@ -208,7 +284,7 @@ function main() {
|
|
|
208
284
|
copyDir(join(KIT_ROOT, "templates", "docs"), join(cwd, "docs"), cwd);
|
|
209
285
|
log("");
|
|
210
286
|
|
|
211
|
-
// 5. .claude/commands/ →
|
|
287
|
+
// 5. .claude/commands/ → 8 slash-commands
|
|
212
288
|
log(`${c.bold}Commands${c.reset} → .claude/commands/`);
|
|
213
289
|
copyDir(join(KIT_ROOT, "commands"), join(claudeDir, "commands"), cwd);
|
|
214
290
|
log("");
|
|
@@ -232,7 +308,50 @@ function main() {
|
|
|
232
308
|
);
|
|
233
309
|
log("");
|
|
234
310
|
|
|
235
|
-
//
|
|
311
|
+
// 7b. .claude/references/ → shared source of truth for review/test (read by both commands & agents)
|
|
312
|
+
log(`${c.bold}References${c.reset} → .claude/references/ ${c.dim}(shared standards for commands + agents)${c.reset}`);
|
|
313
|
+
copyDir(join(KIT_ROOT, "references"), join(claudeDir, "references"), cwd);
|
|
314
|
+
log("");
|
|
315
|
+
|
|
316
|
+
// 8. .claude/skills/ → model-invoked skills (auto-applied by Claude, no command needed)
|
|
317
|
+
log(`${c.bold}Skills${c.reset} → .claude/skills/ ${c.dim}(auto-applied by Claude — no command needed)${c.reset}`);
|
|
318
|
+
const skillsDir = join(claudeDir, "skills");
|
|
319
|
+
const kitSkillsDir = join(KIT_ROOT, "skills");
|
|
320
|
+
|
|
321
|
+
// Static skills: copy each folder wholesale (preserves templates/ and references/ subfiles).
|
|
322
|
+
// angular-practices is the only generated one (needs profile injection) — handled below.
|
|
323
|
+
for (const skill of readdirSync(kitSkillsDir)) {
|
|
324
|
+
if (skill === "angular-practices") continue;
|
|
325
|
+
const src = join(kitSkillsDir, skill);
|
|
326
|
+
if (!statSync(src).isDirectory()) continue;
|
|
327
|
+
copyDir(src, join(skillsDir, skill), cwd);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// angular-practices: generated — inject the matched profile filename + label
|
|
331
|
+
const apTemplate = join(kitSkillsDir, "angular-practices", "SKILL.md");
|
|
332
|
+
if (existsSync(apTemplate)) {
|
|
333
|
+
const body = readFileSync(apTemplate, "utf8")
|
|
334
|
+
.replace(/\{\{PRACTICE_FILE\}\}/g, practice)
|
|
335
|
+
.replace(/\{\{NG_PROFILE_LABEL\}\}/g, profileLabel(practice));
|
|
336
|
+
writeOne(body, join(skillsDir, "angular-practices", "SKILL.md"), cwd);
|
|
337
|
+
} else {
|
|
338
|
+
err(`skill template missing in kit: angular-practices/SKILL.md`);
|
|
339
|
+
}
|
|
340
|
+
log("");
|
|
341
|
+
|
|
342
|
+
// 9. .claude/agents/ → Angular-specialized subagents (isolated context, run in parallel)
|
|
343
|
+
log(`${c.bold}Agents${c.reset} → .claude/agents/ ${c.dim}(isolated context — dispatch to run in background/parallel)${c.reset}`);
|
|
344
|
+
copyDir(join(KIT_ROOT, "agents"), join(claudeDir, "agents"), cwd);
|
|
345
|
+
log("");
|
|
346
|
+
|
|
347
|
+
// 10. .claude/settings.json → permission allowlist + Stop-hook build verify
|
|
348
|
+
log(`${c.bold}Settings${c.reset} → .claude/settings.json ${c.dim}(allowlist + build verify)${c.reset}`);
|
|
349
|
+
const { settings, buildCmd } = buildSettings(cwd);
|
|
350
|
+
if (!buildCmd) warn("no package.json found — writing permissions only (no build-verify hook)");
|
|
351
|
+
writeOne(JSON.stringify(settings, null, 2) + "\n", join(claudeDir, "settings.json"), cwd);
|
|
352
|
+
log("");
|
|
353
|
+
|
|
354
|
+
// 11. summary
|
|
236
355
|
log(`${c.bold}Done.${c.reset} ${copied} file(s) created, ${skipped} skipped.`);
|
|
237
356
|
if (skipped > 0 && !flags.force) log(`${c.dim}Re-run with --force to overwrite skipped files.${c.reset}`);
|
|
238
357
|
log("");
|
|
@@ -240,6 +359,13 @@ function main() {
|
|
|
240
359
|
log(` 1. Open this project in ${c.cyan}Claude Code${c.reset}.`);
|
|
241
360
|
log(` 2. Run ${c.cyan}/init${c.reset} — it will scan your codebase and fill in all the docs.`);
|
|
242
361
|
log(` 3. Each session: ${c.cyan}/start${c.reset} → work → ${c.cyan}/update-status${c.reset}.`);
|
|
362
|
+
log("");
|
|
363
|
+
log(`${c.dim}Skills in .claude/skills/ apply automatically when you write or review`);
|
|
364
|
+
log(`Angular code — no command needed to trigger them.`);
|
|
365
|
+
log(`Agents in .claude/agents/ run in an isolated context — ask Claude to use one`);
|
|
366
|
+
log(`(e.g. "use angular-build-fixer to fix this build error"), even in the background.`);
|
|
367
|
+
log(`settings.json pre-allows ng/npm/pnpm/yarn/git-read (fewer prompts) and type-checks`);
|
|
368
|
+
log(`at turn end only when .ts/.html changed. Remove its "hooks" block to disable.${c.reset}`);
|
|
243
369
|
}
|
|
244
370
|
|
|
245
371
|
main();
|
package/commands/dev-cycle.md
CHANGED
|
@@ -5,6 +5,11 @@ This is an ORCHESTRATOR. It chains the other commands' logic, but it is NOT
|
|
|
5
5
|
fully autonomous: after every phase it STOPS at a gate and waits for your
|
|
6
6
|
explicit confirmation before continuing.
|
|
7
7
|
|
|
8
|
+
Angular idioms depend on the project version — read `.claude/angular-practices/` and follow it.
|
|
9
|
+
**Precedence** (see `.claude/rules/project-rules.md` → Precedence): a valid project convention wins
|
|
10
|
+
over the BP profile; the profile applies only where the project has no convention or is below
|
|
11
|
+
standard (new code only); legacy modules are never refactored.
|
|
12
|
+
|
|
8
13
|
---
|
|
9
14
|
|
|
10
15
|
## THE GATE RULE (applies after EVERY phase — non-negotiable)
|
|
@@ -26,28 +31,50 @@ Never skip a gate. Never batch multiple phases past a gate. The user is always i
|
|
|
26
31
|
## Phase 0 — Kickoff
|
|
27
32
|
|
|
28
33
|
1. Read context:
|
|
29
|
-
-
|
|
34
|
+
- `CLAUDE.md`
|
|
35
|
+
- `.claude/rules/project-rules.md` → naming, structure, Coexistence, **Reference Examples**
|
|
30
36
|
- `docs/ARCHITECTURE.md`
|
|
31
37
|
- `docs/API_CONTRACT.md`
|
|
32
|
-
- `docs/DESIGN_SYSTEM.md`
|
|
38
|
+
- `docs/DESIGN_SYSTEM.md` → shared components + Wrapped Components table
|
|
33
39
|
- `.claude/angular-practices/` (the version profile)
|
|
34
|
-
|
|
35
|
-
|
|
40
|
+
- **`docs/plans/`** → if a plan for this feature exists, read it in full; it is the source of
|
|
41
|
+
truth for scope, File Map, and task Interfaces (written by `/plan` per
|
|
42
|
+
`.claude/references/plan-spec.md`)
|
|
43
|
+
- **Open the Reference Example files** listed in `project-rules.md` (best existing service / page /
|
|
44
|
+
component / spec) and mirror their style — the strongest signal for matching real conventions
|
|
45
|
+
2. Establish the feature:
|
|
46
|
+
- **If a plan was found** → the name and scope come from the plan's Goal. Do NOT re-ask them;
|
|
47
|
+
just confirm: **"Found plan `docs/plans/<file>` — follow it? (yes / no)"**.
|
|
48
|
+
- **If no plan** → ask ONE question: **"What is the feature name and what does it do?"** (name +
|
|
49
|
+
one sentence). If anything else about scope is unclear, ask it in the same batch — don't guess.
|
|
50
|
+
When the feature looks large (several screens or endpoints), add one line:
|
|
51
|
+
*"This looks sizeable — consider running `/plan` first for a reviewed task breakdown."* — then
|
|
52
|
+
continue anyway if the user wants to.
|
|
53
|
+
3. **GATE:** Wait for the answer / confirmation. Write no code until you have it.
|
|
36
54
|
|
|
37
55
|
---
|
|
38
56
|
|
|
39
57
|
## Phase 1 — Scaffold
|
|
40
58
|
|
|
41
|
-
1. Create the full folder + empty-file structure
|
|
42
|
-
|
|
59
|
+
1. Create the full folder + empty-file structure. **If a plan was found in Phase 0, create exactly
|
|
60
|
+
the files in the plan's File Map** (it already reflects the project's real layout). Otherwise
|
|
61
|
+
follow `.claude/references/feature-structure.md` → Folder Structure, using the project's actual
|
|
62
|
+
layout and folder names from `project-rules.md` (the reference file's tree is only the default shape).
|
|
43
63
|
2. Print the created file tree.
|
|
44
64
|
3. **GATE:** "✅ Folder structure OK? Continue to Phase 2 (Model + Service)? (yes / no)"
|
|
45
65
|
|
|
46
66
|
---
|
|
47
67
|
|
|
68
|
+
> Follow `.claude/references/feature-structure.md` → Coding Rules throughout Phase 2a and 2b
|
|
69
|
+
> (`OnPush`, subscription teardown per profile, no `any`, project's forms approach, no hardcoded
|
|
70
|
+
> URLs, wrapper priority — never import a raw UI-library component when a wrapper exists).
|
|
71
|
+
|
|
72
|
+
> If a plan was found in Phase 0, implement each piece from its tasks: use the exact model/DTO
|
|
73
|
+
> shapes and service signatures declared in the tasks' `Interfaces: Consumes/Produces` blocks.
|
|
74
|
+
|
|
48
75
|
## Phase 2a — Implement Model + Service
|
|
49
76
|
|
|
50
|
-
1. Write `models/{feature}.model.ts` — interfaces mirroring the backend's actual response shape from `API_CONTRACT.md` (envelope, raw DTO, or GraphQL type — per `project-rules.md`).
|
|
77
|
+
1. Write `models/{feature}.model.ts` — interfaces mirroring the backend's actual response shape from `API_CONTRACT.md` (envelope, raw DTO, or GraphQL type — per `project-rules.md`), matching the plan's declared types if a plan exists.
|
|
51
78
|
2. Write `services/{feature}.service.ts` — data-access methods returning `Observable<T>` typed with the project's response shape,
|
|
52
79
|
following the DI/idiom of the version profile.
|
|
53
80
|
3. Print the two files.
|
|
@@ -68,10 +95,14 @@ Never skip a gate. Never batch multiple phases past a gate. The user is always i
|
|
|
68
95
|
|
|
69
96
|
## Phase 3 — Tests + Context
|
|
70
97
|
|
|
71
|
-
1.
|
|
98
|
+
1. **Verify the build first**: `ng build` / `npx tsc --noEmit` and `ng lint`. Fix any failure
|
|
99
|
+
immediately — a broken build makes test results meaningless, and this must not slip through to
|
|
100
|
+
Phase 4 or the commit in Phase 5.
|
|
101
|
+
2. Write tests by dispatching the **`angular-test-writer`** agent (isolated — it follows
|
|
102
|
+
`.claude/references/test-spec.md`), or run `/write-tests` inline:
|
|
72
103
|
- `{feature}.service.spec.ts` (mock HttpClient: success + error + empty per method)
|
|
73
104
|
- `{feature}-list.component.spec.ts` (mock service: render + interaction + loading + error)
|
|
74
|
-
|
|
105
|
+
3. **Harness loop — tests (automated within this phase, max 3 rounds):**
|
|
75
106
|
```
|
|
76
107
|
round = 1
|
|
77
108
|
while round <= 3:
|
|
@@ -84,14 +115,15 @@ Never skip a gate. Never batch multiple phases past a gate. The user is always i
|
|
|
84
115
|
GATE: "❌ Tests still failing after 3 rounds. Exiting cycle — handle manually."
|
|
85
116
|
→ exit the automated cycle
|
|
86
117
|
```
|
|
87
|
-
|
|
88
|
-
|
|
118
|
+
4. After tests pass, write the feature's `CONTEXT.md` in the same folder created in Phase 1 (per `/write-context`).
|
|
119
|
+
5. **GATE:** "✅ Build/lint clean + tests pass (round {n}) + CONTEXT.md written. Continue to Phase 4 (Review)? (yes / no)"
|
|
89
120
|
|
|
90
121
|
---
|
|
91
122
|
|
|
92
123
|
## Phase 4 — Review + Harness
|
|
93
124
|
|
|
94
|
-
1.
|
|
125
|
+
1. Review by dispatching the **`angular-reviewer`** agent (isolated), or run `/review-pr` inline —
|
|
126
|
+
both apply `.claude/references/review-checklist.md` (all dimensions).
|
|
95
127
|
2. Print the result: count of 🔴 blockers, 🟡 suggestions, 🟢 good parts.
|
|
96
128
|
3. If 0 blockers → skip the loop, go straight to the Phase 4 gate.
|
|
97
129
|
4. If there are blockers:
|
package/commands/init.md
CHANGED
|
@@ -48,8 +48,12 @@ The version-matched best-practice file is in `.claude/angular-practices/`
|
|
|
48
48
|
4. **Find the best-example files** — the most complete, idiomatic feature to use as a
|
|
49
49
|
reference template. Pick the best example for each of: a service, a smart/page
|
|
50
50
|
component, a dumb component, a test spec. Verify each path exists.
|
|
51
|
-
5.
|
|
52
|
-
|
|
51
|
+
5. **Detect the commit convention** — run `git log --oneline -50` (skip if no git history) and infer:
|
|
52
|
+
- **Prefix**: a consistent leading token before the type (e.g. `VIVAS_feat(...)` → prefix `VIVAS_`); none if not present.
|
|
53
|
+
- **Language**: the language of commit subjects (`vi` / `en`).
|
|
54
|
+
- **Scope source**: the folder level scopes come from (e.g. `src/app/features/<scope>` or `src/app/modules/<scope>`), based on the detected Folder Structure.
|
|
55
|
+
6. Classify each finding: `standard` / `below-standard` / `uncertain`.
|
|
56
|
+
7. Print a short findings summary (3–5 lines) + the chosen best-example files.
|
|
53
57
|
|
|
54
58
|
## Stage 1: Ask ALL Open Questions at Once
|
|
55
59
|
1. Gather every `uncertain` item across ALL seven files into a single list
|
|
@@ -58,6 +62,8 @@ The version-matched best-practice file is in `.claude/angular-practices/`
|
|
|
58
62
|
- **Wrapper auto-detection**: if wrappers were detected in Stage 0, confirm for each:
|
|
59
63
|
(a) which library component it wraps, (b) custom additions, (c) is it required (BLOCKER) or preferred (SUGGESTION).
|
|
60
64
|
Default if team does not answer: treat as SUGGESTION.
|
|
65
|
+
- **Commit convention**: if the prefix or language is ambiguous from `git log`, confirm them
|
|
66
|
+
(default: no prefix, language vi).
|
|
61
67
|
2. Ask them as ONE grouped batch of multiple-choice questions.
|
|
62
68
|
3. **WAIT** for the answers. Do not write any file until the batch is answered.
|
|
63
69
|
4. If nothing is uncertain, say so and proceed directly to Stage 2.
|
|
@@ -69,7 +75,7 @@ placeholder with real content. Do NOT stop between files.
|
|
|
69
75
|
1. **CLAUDE.md** (root) — `Read first` links, `Common commands` from `package.json` scripts, `Runtime and tooling` from detected stack, `High-level architecture` (2–4 line summary, link to docs/ARCHITECTURE.md). Under 200 lines.
|
|
70
76
|
2. **docs/API_CONTRACT.md** — infer from existing `*.service.ts` calls; map endpoints → service methods → TypeScript interfaces. Mark gaps.
|
|
71
77
|
3. **docs/ARCHITECTURE.md** — actual layer structure, routing/lazy-loading, state approach, HTTP/interceptor flow, auth strategy. Full detail here (not in CLAUDE.md).
|
|
72
|
-
4. **.claude/rules/project-rules.md** — tech stack, naming, coding rules (actionable, not prose). Include the `## Precedence` section, the `## Reference Examples` section (best-example files from Stage 0 — paths that exist only), and the `## Coexistence Strategy` section (see below).
|
|
78
|
+
4. **.claude/rules/project-rules.md** — tech stack, naming, coding rules (actionable, not prose). Include the `## Precedence` section, the `## Commit Convention` section (prefix / language / scope source detected in Stage 0 — default prefix none, language vi), the `## Reference Examples` section (best-example files from Stage 0 — paths that exist only), and the `## Coexistence Strategy` section (see below).
|
|
73
79
|
5. **docs/PROJECT-STATUS.md** — snapshot: what exists, in progress, known issues, next tasks. Session counter = 1.
|
|
74
80
|
6. **docs/DESIGN_SYSTEM.md** — UI library, design tokens (infer from styles/theme), shared/reusable components in whatever the project calls that folder (record the actual name), AND the **Wrapped Components** table (filled from Stage 0 detection, confirmed in Stage 1). If no wrappers found, OMIT the Wrapped Components section and add: `> This project uses UI library components directly — no shared wrappers.`
|
|
75
81
|
7. **docs/decisions/** — one ADR per real decision confirmed (e.g. `001-state-management.md`, `002-auth-token-storage.md`). Only for actual decisions.
|
package/commands/new-feature.md
CHANGED
|
@@ -11,60 +11,39 @@ has no convention or is below standard (new code only); legacy modules are never
|
|
|
11
11
|
- Read `docs/ARCHITECTURE.md` → where this feature fits
|
|
12
12
|
- Read `docs/API_CONTRACT.md` → which endpoints this feature calls
|
|
13
13
|
- Read `docs/DESIGN_SYSTEM.md` → shared components to use, **AND the Wrapped Components table → which wrapper to use for each UI library primitive** (e.g. for a dropdown, use `<app-select>` not `p-dropdown`)
|
|
14
|
+
- Check `docs/plans/` → **if a plan for this feature exists** (written by `/plan`), it is the source
|
|
15
|
+
of truth for scope, File Map, and task Interfaces — follow it for Steps 2 and 3. If the feature is
|
|
16
|
+
large and no plan exists, suggest running `/plan` first, then continue if I want to.
|
|
14
17
|
- **Open the Reference Example files** listed in `project-rules.md` (best existing service / page / component / spec) and mirror their style — this is the strongest signal for matching the project's real conventions
|
|
15
18
|
- Ask me if anything is unclear before writing code
|
|
16
19
|
|
|
17
20
|
## Step 2: Create Feature Structure
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
│ │ ├── {feature}-list.component.ts
|
|
34
|
-
│ │ ├── {feature}-list.component.html
|
|
35
|
-
│ │ └── {feature}-list.component.scss
|
|
36
|
-
│ └── {feature}-detail/
|
|
37
|
-
└── components/ # Dumb (presentational) components
|
|
38
|
-
└── {feature}-form/
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
## Step 3: Implement in This Order
|
|
42
|
-
1. **Model** — interfaces for entity, request/response, mirroring the backend's actual DTOs / response shape (per `project-rules.md` — envelope, raw DTO, or GraphQL type)
|
|
43
|
-
2. **Service** — data-access methods returning `Observable<T>` typed with the project's response shape (HttpClient, or the project's client if it uses Apollo/another)
|
|
44
|
-
3. **Routes** — lazy-loaded, guard-protected where needed
|
|
45
|
-
4. **Page components (smart)** — data, loading/error/empty states
|
|
46
|
-
5. **Presentational components (dumb)** — inputs/outputs only, no data access
|
|
47
|
-
|
|
48
|
-
## Step 4: Write Tests (see /write-tests)
|
|
21
|
+
If a plan was found in Step 1, create exactly the files in its File Map. Otherwise follow
|
|
22
|
+
`.claude/references/feature-structure.md` → Folder Structure. **Always use the project's
|
|
23
|
+
actual layout and folder names from `project-rules.md`** — the reference file's tree is only the
|
|
24
|
+
default shape (e.g. the project may use `containers/` instead of `pages/`, an Nx `libs/` layout, etc.).
|
|
25
|
+
|
|
26
|
+
## Step 3: Implement
|
|
27
|
+
Follow `.claude/references/feature-structure.md` for both **Implementation Order** (Model → Service →
|
|
28
|
+
Routes → Page components → Presentational components) and **Coding Rules** (data access in services
|
|
29
|
+
only, `OnPush`, subscription teardown, no `any`, project's forms approach, no hardcoded URLs, wrapper
|
|
30
|
+
priority) — apply the rules AS you write each piece, not as an afterthought. If a plan was found, use
|
|
31
|
+
the exact model/DTO shapes and service signatures from its tasks' `Interfaces` blocks.
|
|
32
|
+
|
|
33
|
+
## Step 4: Write Tests
|
|
34
|
+
Dispatch the **`angular-test-writer`** agent (isolated context — it follows
|
|
35
|
+
`.claude/references/test-spec.md`), or run `/write-tests` inline for a small feature. Either way:
|
|
49
36
|
- Service: mock HttpClient, test success + error + empty per method
|
|
50
37
|
- Component: mock service, test render + interaction + loading + error states
|
|
51
38
|
|
|
52
|
-
## Step 5:
|
|
53
|
-
- Data access ONLY in services — never in components
|
|
54
|
-
- `ChangeDetectionStrategy.OnPush` on every component
|
|
55
|
-
- Tear down subscriptions per profile: `takeUntilDestroyed` (v16+) or `takeUntil(destroy$)` + `ngOnDestroy` (v12–15)
|
|
56
|
-
- No `any` — interfaces/types for every model and response
|
|
57
|
-
- Use the project's forms approach from `project-rules.md` (Reactive Forms by default; Formly / template-driven if that's what the project uses)
|
|
58
|
-
- No hardcoded backend URL — use `environment`
|
|
59
|
-
- **Wrapper priority**: import from `@shared/components/<name>` (or the project's wrapper folder) if a wrapper exists; never import the library component directly. See `docs/DESIGN_SYSTEM.md` → Wrapped Components.
|
|
60
|
-
|
|
61
|
-
## Step 6: Update Documentation
|
|
39
|
+
## Step 5: Update Documentation
|
|
62
40
|
- `docs/API_CONTRACT.md` if you used/discovered endpoints
|
|
63
41
|
- Create `CONTEXT.md` inside the feature folder (use /write-context)
|
|
64
42
|
- `docs/PROJECT-STATUS.md` (use /update-status)
|
|
65
43
|
|
|
66
|
-
## Step
|
|
44
|
+
## Step 6: Verify
|
|
67
45
|
- Build passes: `ng build` / `npx tsc --noEmit`
|
|
68
46
|
- All tests pass: `ng test` / `jest`
|
|
69
47
|
- Lint passes: `ng lint`
|
|
70
|
-
- Review
|
|
48
|
+
- Review before committing: dispatch the **`angular-reviewer`** agent (applies
|
|
49
|
+
`.claude/references/review-checklist.md` in an isolated context), or run `/review-pr` inline
|
package/commands/plan.md
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
Plan a feature before writing any code: clarify the requirement, weigh approaches, agree on a
|
|
2
|
+
design, then write a detailed, task-by-task implementation plan to `docs/plans/`.
|
|
3
|
+
|
|
4
|
+
This command produces a PLAN, not code. It writes exactly one file — the plan document — and
|
|
5
|
+
nothing else. `/dev-cycle` (gated, recommended) or `/new-feature` (linear) then execute it.
|
|
6
|
+
|
|
7
|
+
Angular idioms depend on the project version — the plan defers to `.claude/angular-practices/` and
|
|
8
|
+
to the **Precedence** rule in `.claude/rules/project-rules.md` (a valid project convention wins over
|
|
9
|
+
the BP profile; the profile applies only where the project has no convention or is below standard,
|
|
10
|
+
new code only; legacy modules are never refactored).
|
|
11
|
+
|
|
12
|
+
## Running under Claude Code's Plan Mode
|
|
13
|
+
|
|
14
|
+
If this session is in **Plan Mode** (you were given a plan-mode file path and told to use
|
|
15
|
+
`ExitPlanMode` for approval), `Write`/`Edit` are restricted to that one file — you cannot write
|
|
16
|
+
`docs/plans/<feature>.md` directly until Plan Mode ends. In that case:
|
|
17
|
+
- Phases A–D run exactly as written below (they are read-only or pure conversation).
|
|
18
|
+
- Phase D's GATE is skipped as a separate yes/no — approval happens via `ExitPlanMode` instead (see
|
|
19
|
+
Phase E's Plan Mode branch).
|
|
20
|
+
- Phase E branches: compose + self-review the plan first, write it into the Plan Mode file, call
|
|
21
|
+
`ExitPlanMode`, and only after the user approves (Plan Mode ends) write the real
|
|
22
|
+
`docs/plans/<feature>.md` — same content, now at its real path.
|
|
23
|
+
|
|
24
|
+
If this session is NOT in Plan Mode, ignore this section — run every phase as written, gates
|
|
25
|
+
included.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## THE GATE RULE (applies after Phases B, C, D — non-negotiable)
|
|
30
|
+
|
|
31
|
+
After a gated phase you MUST:
|
|
32
|
+
1. Print a short summary of what was decided.
|
|
33
|
+
2. Ask the gate question exactly as written for that phase.
|
|
34
|
+
3. Then WAIT. Do not proceed on silence or assumption.
|
|
35
|
+
4. If the user approves → continue to the next phase.
|
|
36
|
+
5. If the user asks for changes → revise in place and re-ask the same gate. Do not skip ahead.
|
|
37
|
+
|
|
38
|
+
Write NO code and scaffold NOTHING in any phase. The only file this command creates is the plan doc.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Phase A — Context (no gate)
|
|
43
|
+
|
|
44
|
+
Read, in this order:
|
|
45
|
+
- `CLAUDE.md`
|
|
46
|
+
- `.claude/rules/project-rules.md` → Precedence, naming, structure, Coexistence, **Reference Examples**
|
|
47
|
+
- `docs/ARCHITECTURE.md` → where this feature fits
|
|
48
|
+
- `docs/API_CONTRACT.md` → endpoints + payload shapes this feature will touch
|
|
49
|
+
- `docs/DESIGN_SYSTEM.md` → shared components + **Wrapped Components table**
|
|
50
|
+
- `.claude/angular-practices/` → the version profile
|
|
51
|
+
- **Open the Reference Example files** listed in `project-rules.md` (best existing service / page /
|
|
52
|
+
component / spec) — the plan's file shapes and interfaces should mirror them.
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Phase B — Clarify the requirement
|
|
57
|
+
|
|
58
|
+
1. **Scope check first.** If the request describes several independent subsystems (e.g. "a portal
|
|
59
|
+
with orders, chat, billing, and reports"), STOP and propose splitting it: name the independent
|
|
60
|
+
pieces and suggest one plan per piece. Brainstorm the first piece here; the rest get their own
|
|
61
|
+
`/plan` runs later. Do not spend questions on a feature that needs decomposition first.
|
|
62
|
+
2. For an appropriately-scoped feature, ask the clarifying questions you need — purpose,
|
|
63
|
+
constraints, success criteria, edge cases, which endpoints/screens are in scope.
|
|
64
|
+
- **Batch them** (ask all open questions in one message, like `/init` Stage 1). Do not drip one
|
|
65
|
+
question per message.
|
|
66
|
+
- Prefer multiple-choice / yes-no phrasing where possible.
|
|
67
|
+
- Don't ask what the docs already answer — pull it from Phase A instead.
|
|
68
|
+
3. **Adaptive follow-up:** if an answer reveals a new ambiguity you didn't anticipate (e.g. the user
|
|
69
|
+
mentions a status field that implies a workflow you need to understand), ask that **one**
|
|
70
|
+
follow-up question before the gate — don't silently guess, and don't revert to asking every
|
|
71
|
+
remaining question one at a time.
|
|
72
|
+
4. **GATE:** "✅ Requirements clear? (yes / add more)" — WAIT for answers. Write nothing until you
|
|
73
|
+
have them.
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Phase C — Approaches
|
|
78
|
+
|
|
79
|
+
1. Propose **2-3 approaches** with trade-offs (e.g. one feature service vs. split by concern;
|
|
80
|
+
reuse an existing service's pagination vs. a new one; smart/dumb split granularity).
|
|
81
|
+
2. Lead with your **recommendation and why**, framed against this project's conventions and version
|
|
82
|
+
idioms — not generic advice.
|
|
83
|
+
3. **GATE:** "✅ Which approach? (1 / 2 / 3 / other)" — WAIT.
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Phase D — Design
|
|
88
|
+
|
|
89
|
+
1. Present the design in short sections, each scaled to its complexity (a few sentences each, more
|
|
90
|
+
only if nuanced): architecture & where it sits, data flow, components (smart/dumb split),
|
|
91
|
+
error/loading/empty handling, testing scope.
|
|
92
|
+
2. Note explicitly which **shared wrappers** the UI will use (from the Wrapped Components table) and
|
|
93
|
+
which **endpoints** from `API_CONTRACT.md` it consumes.
|
|
94
|
+
3. **GATE (skip if in Plan Mode — see below):** "✅ Design OK? Write the plan? (yes / revise)" — WAIT.
|
|
95
|
+
There is no separate design file — once approved, the design goes straight into the plan header.
|
|
96
|
+
**If in Plan Mode**, don't ask this separately — go straight to Phase E; `ExitPlanMode` there is
|
|
97
|
+
the approval.
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Phase E — Write the plan
|
|
102
|
+
|
|
103
|
+
1. Determine today's date and the feature name → target path
|
|
104
|
+
`docs/plans/YYYY-MM-DD-<feature-name>.md`.
|
|
105
|
+
2. Compose the plan content **strictly following `.claude/references/plan-spec.md`**: header (Goal /
|
|
106
|
+
Architecture / Approach chosen / Global Constraints), File Map, then tasks in Implementation
|
|
107
|
+
Order (Model → Service → Routes → Pages → Components → Tests), each with `Files:`,
|
|
108
|
+
`Interfaces: Consumes/Produces`, and concrete steps with real code — **no placeholders**.
|
|
109
|
+
3. Run the **Self-Review checklist** from `plan-spec.md` (requirement coverage, placeholder scan,
|
|
110
|
+
type consistency vs. `API_CONTRACT.md`, wrapper check, layout check). Fix issues inline. Do this
|
|
111
|
+
BEFORE anything gets written below — either route commits the reviewed version.
|
|
112
|
+
|
|
113
|
+
**Not in Plan Mode:**
|
|
114
|
+
4. Create `docs/plans/` if it doesn't exist, write the reviewed content to the target path. Done.
|
|
115
|
+
|
|
116
|
+
**In Plan Mode:**
|
|
117
|
+
4. Write the reviewed content to the Plan Mode file (the one path you're currently allowed to
|
|
118
|
+
write). This is the plan the user will see when reviewing.
|
|
119
|
+
5. Call `ExitPlanMode`. This IS the approval gate for Phases D and E — do not also ask the Phase D
|
|
120
|
+
text gate.
|
|
121
|
+
6. Once the user approves and Plan Mode ends, immediately — before doing anything else — create
|
|
122
|
+
`docs/plans/` if needed and write the **same reviewed content** to
|
|
123
|
+
`docs/plans/YYYY-MM-DD-<feature-name>.md`. This is the real deliverable; the Plan Mode file was
|
|
124
|
+
only the approval copy.
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## Phase F — Handoff
|
|
129
|
+
|
|
130
|
+
Once `docs/plans/<file>.md` exists for real (directly from Phase E, or after the Plan Mode
|
|
131
|
+
approval + follow-up write), print:
|
|
132
|
+
> ✅ Plan saved to `docs/plans/<file>` — <N> tasks. I ran the self-review and fixed: <list, or "no
|
|
133
|
+
> issues">. Review it, then run **`/dev-cycle`** (gated, recommended) or **`/new-feature`** (linear)
|
|
134
|
+
> — both will detect and follow this plan.
|
|
135
|
+
|
|
136
|
+
Do not start implementing. The user reviews the plan first.
|
package/commands/review-pr.md
CHANGED
|
@@ -1,71 +1,12 @@
|
|
|
1
|
-
Review the code changes
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
- [ ] Smart / dumb separation: pages own data; presentational components only render + emit
|
|
14
|
-
- [ ] HTTP calls ONLY in services — never in components
|
|
15
|
-
- [ ] No business logic in templates
|
|
16
|
-
- [ ] Feature routes are lazy-loaded
|
|
17
|
-
|
|
18
|
-
## Type Safety
|
|
19
|
-
- [ ] No `any` — interfaces/types for every model and API response
|
|
20
|
-
- [ ] Responses typed with the project's response shape recorded in `project-rules.md` (e.g. an `ApiResponse<T>` envelope, a raw DTO, or a GraphQL type — whatever the backend actually returns)
|
|
21
|
-
- [ ] No `@ts-ignore` / `@ts-expect-error`
|
|
22
|
-
|
|
23
|
-
## Dependency Injection (follow `.claude/angular-practices/`)
|
|
24
|
-
- [ ] DI matches the profile: `inject()` (v16+) or constructor injection (v12–15) — consistent across the project
|
|
25
|
-
- [ ] Services `@Injectable({ providedIn: 'root' })`
|
|
26
|
-
|
|
27
|
-
## Reactive / RxJS / Signals (follow `.claude/angular-practices/`)
|
|
28
|
-
- [ ] Subscriptions torn down: `takeUntilDestroyed` (v16+) or `takeUntil(destroy$)` + `ngOnDestroy` (v12–15)
|
|
29
|
-
- [ ] `async` pipe preferred over manual subscribe
|
|
30
|
-
- [ ] No `toPromise()` — use `firstValueFrom()` if needed
|
|
31
|
-
- [ ] Services return `Observable<T>` — do NOT subscribe internally
|
|
32
|
-
- [ ] Signals used per profile: stable for state (v16+); derived state via `computed()`. `resource`/`httpResource` are experimental (v19+) — only if the team opted in
|
|
33
|
-
|
|
34
|
-
## Error Handling
|
|
35
|
-
- [ ] Loading / error / empty states handled in list/detail pages
|
|
36
|
-
- [ ] HTTP errors surfaced to user (not swallowed)
|
|
37
|
-
- [ ] Auth errors (e.g. 401) handled centrally by an interceptor — not per-feature
|
|
38
|
-
|
|
39
|
-
## Security
|
|
40
|
-
- [ ] Auth handled per the project's model in `project-rules.md` (token in memory / httpOnly cookie / session / OAuth) — and consistent with it. If tokens are used, they are NOT in localStorage
|
|
41
|
-
- [ ] No hardcoded backend URL — uses `environment`
|
|
42
|
-
- [ ] Routes needing auth are guarded
|
|
43
|
-
- [ ] No unsanitized HTML (`innerHTML` / `bypassSecurityTrust*`) without a clear, reviewed reason
|
|
44
|
-
|
|
45
|
-
## Performance
|
|
46
|
-
- [ ] `ChangeDetectionStrategy.OnPush` on every component (or zoneless on v20+ if enabled)
|
|
47
|
-
- [ ] List tracking present: `@for` with `track` (v17+) or `*ngFor` with `trackBy` (v12–16)
|
|
48
|
-
|
|
49
|
-
## Code Quality
|
|
50
|
-
- [ ] Component file < ~300 lines; method < ~50 lines
|
|
51
|
-
- [ ] No dead code, no `console.log`
|
|
52
|
-
- [ ] Naming follows `.claude/rules/project-rules.md`
|
|
53
|
-
|
|
54
|
-
## Component Wrapping (follow `docs/DESIGN_SYSTEM.md` → Wrapped Components)
|
|
55
|
-
- [ ] No feature imports a raw UI library component (`p-dropdown`, `mat-form-field`, `nz-input`, etc.) when a wrapper exists in `shared/components/`
|
|
56
|
-
- [ ] All UI primitive imports go through the project's wrapper (check the import path matches the wrapper's location)
|
|
57
|
-
- [ ] If a wrapper exists for the need but the PR uses the library directly → 🔴 BLOCKER
|
|
58
|
-
- [ ] If no wrapper exists and the library is used directly → 🟡 SUGGESTION: "Consider creating a wrapper in `shared/components/` for consistency"
|
|
59
|
-
- [ ] New components do NOT silently re-implement logic an existing wrapper already provides
|
|
60
|
-
- [ ] If a brand-new wrapper is introduced → verify it follows the Wrapper Reference Example from `project-rules.md`
|
|
61
|
-
|
|
62
|
-
## Documentation
|
|
63
|
-
- [ ] New feature: `CONTEXT.md` created inside feature folder
|
|
64
|
-
- [ ] Logic changed: `CONTEXT.md` Refactor Log updated (append only)
|
|
65
|
-
- [ ] Endpoint changed: `docs/API_CONTRACT.md` updated
|
|
66
|
-
- [ ] `docs/PROJECT-STATUS.md` updated
|
|
67
|
-
|
|
68
|
-
## Summary
|
|
69
|
-
1. **Blockers** 🔴 — must fix before merge
|
|
70
|
-
2. **Suggestions** 🟡 — improve but not blocking
|
|
71
|
-
3. **Good parts** 🟢 — what was done well
|
|
1
|
+
Review the current code changes against this project's Angular standards.
|
|
2
|
+
|
|
3
|
+
1. Get the diff: run `git diff` (unstaged) and `git diff --staged`, or `git diff <base>...HEAD` if a
|
|
4
|
+
base branch is named. Review only the changed code.
|
|
5
|
+
2. Apply the full checklist in `.claude/references/review-checklist.md` — it defines the review
|
|
6
|
+
dimensions, the Precedence rule (a valid project convention wins; don't flag legacy), and the
|
|
7
|
+
🔴/🟡/🟢 output format. That file is the single source of truth for what "correct" means here.
|
|
8
|
+
3. Output the report **inline** in this conversation using the format from the checklist. If there are
|
|
9
|
+
no blockers, say so explicitly.
|
|
10
|
+
|
|
11
|
+
> For a large diff, or to review in the background while you keep coding, dispatch the
|
|
12
|
+
> `angular-reviewer` agent instead — it applies the same checklist in an isolated context.
|