@anhth2/spec-driven-dev-plugin 0.8.0 → 0.9.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/ARCHITECTURE.md +6 -2
- package/commands/debug.md +152 -0
- package/commands/debug.tmpl +16 -0
- package/commands/define-product.md +57 -0
- package/commands/fix-bug.md +153 -0
- package/commands/fix-bug.tmpl +17 -0
- package/commands/generate-bdd.md +277 -13
- package/commands/generate-bdd.tmpl +220 -13
- package/commands/generate-code.md +154 -2
- package/commands/generate-code.tmpl +97 -2
- package/commands/generate-design-spec.md +57 -0
- package/commands/generate-prd.md +114 -20
- package/commands/generate-prd.tmpl +57 -20
- package/commands/generate-spec-manifest.md +57 -0
- package/commands/generate-tech-docs.md +79 -1
- package/commands/generate-tech-docs.tmpl +22 -1
- package/commands/generate-tests.md +57 -0
- package/commands/learn.md +554 -0
- package/commands/learn.tmpl +63 -0
- package/commands/propose-scenario.md +521 -0
- package/commands/propose-scenario.tmpl +109 -0
- package/commands/refine-prd.md +66 -1
- package/commands/refine-prd.tmpl +9 -1
- package/commands/report-bug.md +543 -0
- package/commands/report-bug.tmpl +131 -0
- package/commands/review-code.md +153 -0
- package/commands/review-code.tmpl +17 -0
- package/commands/review-context.md +65 -0
- package/commands/review-context.tmpl +8 -0
- package/commands/review-tech-docs.md +146 -4
- package/commands/review-tech-docs.tmpl +89 -4
- package/commands/run-tests.md +82 -0
- package/commands/run-tests.tmpl +25 -0
- package/commands/setup-ai-first.md +15 -5
- package/commands/setup-ai-first.tmpl +10 -5
- package/commands/smoke-test.md +57 -0
- package/commands/sync.md +405 -0
- package/commands/sync.tmpl +345 -0
- package/commands/update-framework.md +211 -0
- package/commands/update-framework.tmpl +151 -0
- package/commands/validate-traces.md +115 -2
- package/commands/validate-traces.tmpl +58 -2
- package/core/FRAMEWORK_VERSION +1 -1
- package/core/commands/debug.md +152 -0
- package/core/commands/define-product.md +57 -0
- package/core/commands/fix-bug.md +153 -0
- package/core/commands/generate-bdd.md +277 -13
- package/core/commands/generate-code.md +154 -2
- package/core/commands/generate-design-spec.md +57 -0
- package/core/commands/generate-prd.md +114 -20
- package/core/commands/generate-spec-manifest.md +57 -0
- package/core/commands/generate-tech-docs.md +79 -1
- package/core/commands/generate-tests.md +57 -0
- package/core/commands/learn.md +554 -0
- package/core/commands/propose-scenario.md +521 -0
- package/core/commands/refine-prd.md +66 -1
- package/core/commands/report-bug.md +543 -0
- package/core/commands/review-code.md +153 -0
- package/core/commands/review-context.md +65 -0
- package/core/commands/review-tech-docs.md +146 -4
- package/core/commands/run-tests.md +82 -0
- package/core/commands/setup-ai-first.md +15 -5
- package/core/commands/smoke-test.md +57 -0
- package/core/commands/sync.md +405 -0
- package/core/commands/update-framework.md +211 -0
- package/core/commands/validate-traces.md +115 -2
- package/core/skills/code/SKILL.md +62 -0
- package/core/skills/debug/SKILL.md +67 -0
- package/core/skills/design-spec/SKILL.md +57 -0
- package/core/skills/discovery/SKILL.md +57 -0
- package/core/skills/prd/SKILL.md +10 -0
- package/core/skills/setup-ai-first/SKILL.md +5 -0
- package/core/skills/spec/SKILL.md +10 -0
- package/core/skills/test/SKILL.md +119 -0
- package/core/steps/capture-lesson.md +79 -0
- package/core/steps/context-loader.md +52 -0
- package/core/steps/report-footer.md +5 -0
- package/core/templates/prd.template.md +35 -20
- package/core/templates/project-context.yaml +11 -0
- package/package.json +9 -2
- package/skills/code/SKILL.md +62 -0
- package/skills/debug/SKILL.md +67 -0
- package/skills/design-spec/SKILL.md +57 -0
- package/skills/discovery/SKILL.md +57 -0
- package/skills/prd/SKILL.md +10 -0
- package/skills/setup-ai-first/SKILL.md +5 -0
- package/skills/spec/SKILL.md +10 -0
- package/skills/test/SKILL.md +119 -0
- package/steps/capture-lesson.md +79 -0
- package/steps/context-loader.md +52 -0
- package/steps/report-footer.md +5 -0
- package/templates/prd.template.md +35 -20
- package/templates/project-context.yaml +11 -0
package/core/commands/fix-bug.md
CHANGED
|
@@ -178,6 +178,37 @@ If `services` section is present:
|
|
|
178
178
|
- Override `paths.domain_knowledge_dir` → `{spec_source}/specs/domain-knowledge`
|
|
179
179
|
- Override `paths.business_dictionary` → `{spec_source}/specs/domain-knowledge/business-dictionary.md`
|
|
180
180
|
- Override `paths.core_entities` → `{spec_source}/specs/domain-knowledge/core-entities.md`
|
|
181
|
+
- Override `paths.bug_reports_dir` → `{spec_source}/feedback/bug-reports`
|
|
182
|
+
- Override `paths.bdd_proposals_dir` → `{spec_source}/feedback/bdd-proposals`
|
|
183
|
+
|
|
184
|
+
> **Why under `spec_source`:** tester feedback (`/report-bug`, `/propose-scenario`) must land in the **shared spec repo** so PO/Dev see it when they `/sync`. In single-service mode (no `spec_source`), these default to `feedback/bug-reports` and `feedback/bdd-proposals` at repo root — still shared, same repo.
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## Step 1.6 — [SERVICE CONVENTIONS] Load service-specific conventions (umbrella mode)
|
|
189
|
+
|
|
190
|
+
*Skip this step entirely if `active_service` is `"unresolved"` or context is single-service mode.*
|
|
191
|
+
|
|
192
|
+
When `active_service` has been resolved to a real path in Step 1.5 (e.g., `user-service/`):
|
|
193
|
+
|
|
194
|
+
**1. Locate service config** — try in priority order:
|
|
195
|
+
- `{active_service}/.agent/project-context.yaml`
|
|
196
|
+
- `{active_service}/project-context.yaml`
|
|
197
|
+
|
|
198
|
+
**2. If found, override with service-specific values:**
|
|
199
|
+
|
|
200
|
+
| Variable | Source |
|
|
201
|
+
|----------|--------|
|
|
202
|
+
| `conventions.test_command` | service's `conventions.test_command` |
|
|
203
|
+
| `conventions.build_command` | service's `conventions.build_command` |
|
|
204
|
+
| `paths.trace_dir` | `{active_service}/{service paths.trace_dir}` — default: `{active_service}/.trace` |
|
|
205
|
+
| `paths.specs_dir` | `{active_service}/{service paths.specs_dir}` (if set in service config, else keep Step 1.5 override) |
|
|
206
|
+
|
|
207
|
+
**3. Store** `service_root = {active_service}` as the working directory anchor for all downstream commands:
|
|
208
|
+
- Shell commands (`/run-tests`, `/generate-tests`) run **from within** `service_root`
|
|
209
|
+
- File write operations (test files, trace TSVs) use paths **relative to** `service_root`
|
|
210
|
+
|
|
211
|
+
**4. If service config not found** — keep umbrella defaults, still set `service_root = {active_service}` (path anchor is always needed even without a config override).
|
|
181
212
|
|
|
182
213
|
---
|
|
183
214
|
|
|
@@ -271,6 +302,25 @@ These two variables (`active_module`, `platform_type`) are the canonical source
|
|
|
271
302
|
|
|
272
303
|
---
|
|
273
304
|
|
|
305
|
+
## Step 6.7 — [GUARDRAILS] Load Project Lessons (conditional)
|
|
306
|
+
|
|
307
|
+
*Accumulated mistakes the AI must not repeat in this project. These are added over time via `/learn`
|
|
308
|
+
or accepted during `/review-code`, `/fix-bug`, `/debug`.*
|
|
309
|
+
|
|
310
|
+
Resolve the lessons file path:
|
|
311
|
+
- Use `paths.lessons_file` if set (may be service-overridden in umbrella mode, Step 1.6)
|
|
312
|
+
- Else default `specs/domain-knowledge/lessons-learned.md`
|
|
313
|
+
- In umbrella/service mode (when `service_root` is set), if `paths.lessons_file` is unset, default to `{service_root}/.agent/project-lessons.md`
|
|
314
|
+
|
|
315
|
+
If the file exists, read it and store ALL lessons as **ACTIVE GUARDRAILS** for the session:
|
|
316
|
+
- Treat each lesson's **Rule** as a hard constraint — same priority as CLAUDE.md coding standards (Step 3).
|
|
317
|
+
- Before generating or modifying any artifact (PRD, BDD, tech-doc, code, test), check the output against every lesson whose `category` matches the current command AND whose `scope` matches the target (domain / file).
|
|
318
|
+
- If a generated output would violate a lesson → correct it **before** presenting, and note which lesson (`L-NNN`) was applied.
|
|
319
|
+
|
|
320
|
+
If the file does not exist → skip silently (no lessons captured yet).
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
274
324
|
## Step 7 — [RECAP] Working Memory Recap (anti-lost-in-middle)
|
|
275
325
|
|
|
276
326
|
After loading all context, synthesize and output a compact summary block.
|
|
@@ -286,7 +336,9 @@ Layers : {layer order from CLAUDE.md §2, e.g., Controller → Facade → Ser
|
|
|
286
336
|
Ticket : {ticket_prefix}-
|
|
287
337
|
Dict : {loaded — N canonical terms, M banned terms | missing}
|
|
288
338
|
Entities : {loaded — EntityA, EntityB, EntityC | missing}
|
|
339
|
+
Lessons : {loaded — N guardrails | none yet}
|
|
289
340
|
Service : {active_service} ({active_service_module}) | single-service
|
|
341
|
+
Svc Root : {service_root} — conventions + trace_dir loaded from service config | —
|
|
290
342
|
Status : {FULL | PARTIAL — missing: CLAUDE.md / business-dict / core-entities | MINIMAL}
|
|
291
343
|
```
|
|
292
344
|
|
|
@@ -410,6 +462,101 @@ git commit -m "fix({TICKET_ID}): {description}"
|
|
|
410
462
|
git push -u origin fix/{TICKET_ID}-{slug}
|
|
411
463
|
```
|
|
412
464
|
|
|
465
|
+
## Phase 6 — Offer to Record a Lesson (optional)
|
|
466
|
+
|
|
467
|
+
If the root cause was a **mistake the AI made during generation and could repeat**
|
|
468
|
+
(e.g. it generated code that skipped a layer, missed a null guard, used a wrong pattern —
|
|
469
|
+
NOT an external cause like a third-party outage or bad input data), ask:
|
|
470
|
+
|
|
471
|
+
```
|
|
472
|
+
This root cause looks like a repeatable AI mistake.
|
|
473
|
+
Record it as a project lesson so it isn't generated again? (Y/N)
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
If `Y` → run the capture procedure below with `source=/fix-bug {TICKET_ID}`, an appropriate
|
|
477
|
+
`category` (usually `code-gen`), and `scope` = the affected domain or file glob.
|
|
478
|
+
|
|
479
|
+
# Capture Lesson — Record a Recurring Mistake as a Guardrail
|
|
480
|
+
|
|
481
|
+
Reusable procedure to persist a "lesson" so the AI does not repeat a mistake in this project.
|
|
482
|
+
Used by `/learn` (manual) and offered by `/review-code`, `/fix-bug`, `/debug` (auto).
|
|
483
|
+
|
|
484
|
+
> **Project memory, not model training.** A lesson is plain text injected into context at the
|
|
485
|
+
> start of every command (context-loader Step 6.7). Functionally this stops the repeat — the AI
|
|
486
|
+
> sees the guardrail before it generates. No model weights change.
|
|
487
|
+
|
|
488
|
+
## L1 — Resolve the lessons file
|
|
489
|
+
|
|
490
|
+
Resolve `lessons_path` in this order:
|
|
491
|
+
1. `paths.lessons_file` from loaded context (may be service-overridden in umbrella mode, Step 1.6)
|
|
492
|
+
2. Default `specs/domain-knowledge/lessons-learned.md` (single-service)
|
|
493
|
+
3. In umbrella/service mode (when `service_root` is set) default `{service_root}/.agent/project-lessons.md`
|
|
494
|
+
|
|
495
|
+
## L2 — Build the lesson
|
|
496
|
+
|
|
497
|
+
Gather these fields — from `$ARGUMENTS` (for `/learn`) or from the calling command's findings
|
|
498
|
+
(for `/review-code`, `/fix-bug`, `/debug`):
|
|
499
|
+
|
|
500
|
+
| Field | Meaning |
|
|
501
|
+
|-------|---------|
|
|
502
|
+
| `category` | one of: `code-gen` \| `bdd` \| `tech-docs` \| `tests` \| `prd` \| `general` |
|
|
503
|
+
| `title` | short phrase naming the mistake |
|
|
504
|
+
| `mistake` | concretely, what the AI did wrong |
|
|
505
|
+
| `rule` | imperative correction — "Always …" / "Never …" — testable, not vague |
|
|
506
|
+
| `scope` | where it applies: a domain, a file glob (e.g. `*Controller.*`), or `all` |
|
|
507
|
+
| `source` | how captured: `/learn` \| `/review-code {UC-ID}` \| `/fix-bug {TICKET}` \| `/debug` |
|
|
508
|
+
|
|
509
|
+
If `rule` is vague (e.g. "be careful"), rewrite it into a concrete, checkable instruction before saving.
|
|
510
|
+
|
|
511
|
+
## L3 — De-duplicate
|
|
512
|
+
|
|
513
|
+
Read existing lessons in `lessons_path`. If one already covers the same mistake:
|
|
514
|
+
- **Refine** that entry (tighten the Rule, widen/narrow Scope, bump Date, append the new Source) — do NOT add a duplicate.
|
|
515
|
+
|
|
516
|
+
Otherwise assign the next id `L-{NNN}` = (highest existing number + 1), zero-padded to 3 digits.
|
|
517
|
+
|
|
518
|
+
## L4 — Write
|
|
519
|
+
|
|
520
|
+
If `lessons_path` does not exist, create it with this header first:
|
|
521
|
+
|
|
522
|
+
```markdown
|
|
523
|
+
# Project Lessons — Learned Guardrails
|
|
524
|
+
|
|
525
|
+
> Mistakes the AI must NOT repeat in this project. Loaded by context-loader at the start of
|
|
526
|
+
> every command and treated as hard constraints (same priority as CLAUDE.md coding standards).
|
|
527
|
+
> Add with /learn, or accept the prompt during /review-code, /fix-bug, /debug.
|
|
528
|
+
> Commit this file so the whole team shares the guardrails.
|
|
529
|
+
|
|
530
|
+
| Category | Applies to |
|
|
531
|
+
|----------|-----------|
|
|
532
|
+
| code-gen | /generate-code output |
|
|
533
|
+
| bdd | /generate-bdd output |
|
|
534
|
+
| tech-docs | /generate-tech-docs output |
|
|
535
|
+
| tests | /generate-tests output |
|
|
536
|
+
| prd | /generate-prd, /refine-prd output |
|
|
537
|
+
| general | every command |
|
|
538
|
+
|
|
539
|
+
---
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
Insert the new lesson directly under the `---` separator (**newest first**), in this exact shape:
|
|
543
|
+
|
|
544
|
+
```markdown
|
|
545
|
+
### L-{NNN} — [{category}] {title}
|
|
546
|
+
- **Date**: {today YYYY-MM-DD}
|
|
547
|
+
- **Scope**: {scope}
|
|
548
|
+
- **Mistake**: {mistake}
|
|
549
|
+
- **Rule**: {rule}
|
|
550
|
+
- **Source**: {source}
|
|
551
|
+
|
|
552
|
+
```
|
|
553
|
+
|
|
554
|
+
## L5 — Confirm
|
|
555
|
+
|
|
556
|
+
Print: `📝 Lesson {id} recorded → {lessons_path} ([{category}] {title})`
|
|
557
|
+
Then remind: `Commit {lessons_path} so the team shares this guardrail.`
|
|
558
|
+
|
|
559
|
+
|
|
413
560
|
## Output
|
|
414
561
|
|
|
415
562
|
# Report Footer — Standard Command Output Format
|
|
@@ -459,6 +606,11 @@ Suggest the logical next command based on workflow phase:
|
|
|
459
606
|
| /validate-traces | DRIFT/UNTRACKED → `/generate-code {UC-ID}`; GAP → `/generate-tests {UC-ID}`; all OK → create PR |
|
|
460
607
|
| /fix-bug | Create PR and link to ticket |
|
|
461
608
|
| /debug | `/fix-bug {ticket-id}` if fix needed |
|
|
609
|
+
| /report-bug | Send to dev (`/fix-bug {BUG-ID}`); if coverage gap → `/propose-scenario {UC-ID}` |
|
|
610
|
+
| /propose-scenario | Notify PO/Dev to review the proposal in `feedback/bdd-proposals/` |
|
|
611
|
+
| /learn | Continue working — lesson applies on next command |
|
|
612
|
+
| /sync | `/validate-traces` for full coverage; act on any `📥 tester feedback` surfaced |
|
|
613
|
+
| /update-framework | Review `git diff .agent/`, commit; `/sync` for project content |
|
|
462
614
|
|
|
463
615
|
Format the footer as:
|
|
464
616
|
```
|
|
@@ -474,6 +626,7 @@ Next : {suggested command with example arguments}
|
|
|
474
626
|
Root Cause: {analysis}
|
|
475
627
|
Changes: {list}
|
|
476
628
|
✅ Regression test added | ✅ Build: SUCCESS
|
|
629
|
+
{📝 Lesson L-NNN recorded (if captured)}
|
|
477
630
|
Branch: fix/{TICKET_ID}-{slug}
|
|
478
631
|
Next: Create PR and link to ticket.
|
|
479
632
|
```
|
|
@@ -176,6 +176,37 @@ If `services` section is present:
|
|
|
176
176
|
- Override `paths.domain_knowledge_dir` → `{spec_source}/specs/domain-knowledge`
|
|
177
177
|
- Override `paths.business_dictionary` → `{spec_source}/specs/domain-knowledge/business-dictionary.md`
|
|
178
178
|
- Override `paths.core_entities` → `{spec_source}/specs/domain-knowledge/core-entities.md`
|
|
179
|
+
- Override `paths.bug_reports_dir` → `{spec_source}/feedback/bug-reports`
|
|
180
|
+
- Override `paths.bdd_proposals_dir` → `{spec_source}/feedback/bdd-proposals`
|
|
181
|
+
|
|
182
|
+
> **Why under `spec_source`:** tester feedback (`/report-bug`, `/propose-scenario`) must land in the **shared spec repo** so PO/Dev see it when they `/sync`. In single-service mode (no `spec_source`), these default to `feedback/bug-reports` and `feedback/bdd-proposals` at repo root — still shared, same repo.
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## Step 1.6 — [SERVICE CONVENTIONS] Load service-specific conventions (umbrella mode)
|
|
187
|
+
|
|
188
|
+
*Skip this step entirely if `active_service` is `"unresolved"` or context is single-service mode.*
|
|
189
|
+
|
|
190
|
+
When `active_service` has been resolved to a real path in Step 1.5 (e.g., `user-service/`):
|
|
191
|
+
|
|
192
|
+
**1. Locate service config** — try in priority order:
|
|
193
|
+
- `{active_service}/.agent/project-context.yaml`
|
|
194
|
+
- `{active_service}/project-context.yaml`
|
|
195
|
+
|
|
196
|
+
**2. If found, override with service-specific values:**
|
|
197
|
+
|
|
198
|
+
| Variable | Source |
|
|
199
|
+
|----------|--------|
|
|
200
|
+
| `conventions.test_command` | service's `conventions.test_command` |
|
|
201
|
+
| `conventions.build_command` | service's `conventions.build_command` |
|
|
202
|
+
| `paths.trace_dir` | `{active_service}/{service paths.trace_dir}` — default: `{active_service}/.trace` |
|
|
203
|
+
| `paths.specs_dir` | `{active_service}/{service paths.specs_dir}` (if set in service config, else keep Step 1.5 override) |
|
|
204
|
+
|
|
205
|
+
**3. Store** `service_root = {active_service}` as the working directory anchor for all downstream commands:
|
|
206
|
+
- Shell commands (`/run-tests`, `/generate-tests`) run **from within** `service_root`
|
|
207
|
+
- File write operations (test files, trace TSVs) use paths **relative to** `service_root`
|
|
208
|
+
|
|
209
|
+
**4. If service config not found** — keep umbrella defaults, still set `service_root = {active_service}` (path anchor is always needed even without a config override).
|
|
179
210
|
|
|
180
211
|
---
|
|
181
212
|
|
|
@@ -269,6 +300,25 @@ These two variables (`active_module`, `platform_type`) are the canonical source
|
|
|
269
300
|
|
|
270
301
|
---
|
|
271
302
|
|
|
303
|
+
## Step 6.7 — [GUARDRAILS] Load Project Lessons (conditional)
|
|
304
|
+
|
|
305
|
+
*Accumulated mistakes the AI must not repeat in this project. These are added over time via `/learn`
|
|
306
|
+
or accepted during `/review-code`, `/fix-bug`, `/debug`.*
|
|
307
|
+
|
|
308
|
+
Resolve the lessons file path:
|
|
309
|
+
- Use `paths.lessons_file` if set (may be service-overridden in umbrella mode, Step 1.6)
|
|
310
|
+
- Else default `specs/domain-knowledge/lessons-learned.md`
|
|
311
|
+
- In umbrella/service mode (when `service_root` is set), if `paths.lessons_file` is unset, default to `{service_root}/.agent/project-lessons.md`
|
|
312
|
+
|
|
313
|
+
If the file exists, read it and store ALL lessons as **ACTIVE GUARDRAILS** for the session:
|
|
314
|
+
- Treat each lesson's **Rule** as a hard constraint — same priority as CLAUDE.md coding standards (Step 3).
|
|
315
|
+
- Before generating or modifying any artifact (PRD, BDD, tech-doc, code, test), check the output against every lesson whose `category` matches the current command AND whose `scope` matches the target (domain / file).
|
|
316
|
+
- If a generated output would violate a lesson → correct it **before** presenting, and note which lesson (`L-NNN`) was applied.
|
|
317
|
+
|
|
318
|
+
If the file does not exist → skip silently (no lessons captured yet).
|
|
319
|
+
|
|
320
|
+
---
|
|
321
|
+
|
|
272
322
|
## Step 7 — [RECAP] Working Memory Recap (anti-lost-in-middle)
|
|
273
323
|
|
|
274
324
|
After loading all context, synthesize and output a compact summary block.
|
|
@@ -284,7 +334,9 @@ Layers : {layer order from CLAUDE.md §2, e.g., Controller → Facade → Ser
|
|
|
284
334
|
Ticket : {ticket_prefix}-
|
|
285
335
|
Dict : {loaded — N canonical terms, M banned terms | missing}
|
|
286
336
|
Entities : {loaded — EntityA, EntityB, EntityC | missing}
|
|
337
|
+
Lessons : {loaded — N guardrails | none yet}
|
|
287
338
|
Service : {active_service} ({active_service_module}) | single-service
|
|
339
|
+
Svc Root : {service_root} — conventions + trace_dir loaded from service config | —
|
|
288
340
|
Status : {FULL | PARTIAL — missing: CLAUDE.md / business-dict / core-entities | MINIMAL}
|
|
289
341
|
```
|
|
290
342
|
|
|
@@ -306,6 +358,194 @@ After completing all steps, you have loaded:
|
|
|
306
358
|
Proceed to the next step of the calling command.
|
|
307
359
|
|
|
308
360
|
|
|
361
|
+
> **Tester proposals (optional input):** before generating, check `{paths.bdd_proposals_dir}/` (default `{spec_source}/feedback/bdd-proposals/`) for scenarios proposed by testers via `/propose-scenario` that map to this UC's ACs. Incorporate any the PO/Dev has accepted — then the tester's draft is removed/archived from `feedback/`. Skip if the folder is empty.
|
|
362
|
+
|
|
363
|
+
---
|
|
364
|
+
|
|
365
|
+
## Repo Mode Detection
|
|
366
|
+
|
|
367
|
+
After loading context, determine which mode to operate in:
|
|
368
|
+
|
|
369
|
+
- **Spec repo mode**: `project-context.yaml` has NO `services` section OR `setup.mode: spec`
|
|
370
|
+
- **Umbrella mode**: `project-context.yaml` HAS `services` section AND `setup.mode: umbrella`
|
|
371
|
+
|
|
372
|
+
→ Spec repo mode → proceed to **Platform Selection** below (skip Service Detection)
|
|
373
|
+
→ Umbrella mode → proceed to **Service Detection** below (skip Platform Selection)
|
|
374
|
+
|
|
375
|
+
---
|
|
376
|
+
|
|
377
|
+
## Platform Selection (Spec Repo Mode Only)
|
|
378
|
+
|
|
379
|
+
*Skip this section if running in umbrella mode.*
|
|
380
|
+
|
|
381
|
+
Ask the user to select the target platform:
|
|
382
|
+
|
|
383
|
+
```
|
|
384
|
+
Which platform is this BDD for?
|
|
385
|
+
1. web — FE/Web (React, Next.js, Angular, Vue, Nuxt)
|
|
386
|
+
2. app — Mobile (Flutter, React Native, iOS, Android)
|
|
387
|
+
3. system — System/BE BDD (synthesized from existing web + app BDDs)
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
Wait for user selection. Set `active_platform` = chosen value.
|
|
391
|
+
|
|
392
|
+
**Output path (spec repo mode):**
|
|
393
|
+
`{paths.specs_dir}/{domain}/{active_platform}/{TICKET-ID}-UC{N}-{slug}.feature`
|
|
394
|
+
|
|
395
|
+
**Platform vocabulary:**
|
|
396
|
+
|
|
397
|
+
| Platform | "user action" | "type/input" | "observe" | "navigate" |
|
|
398
|
+
|---|---|---|---|---|
|
|
399
|
+
| web | "clicks" | "types into" / "enters" | "sees" / "the page shows" | "navigates to" / "goes to" |
|
|
400
|
+
| app | "taps" | "enters" / "inputs" | "sees" / "the screen shows" | "navigates to" / "opens" |
|
|
401
|
+
| system | N/A — use business events | — | "the system returns" / "receives response" | — |
|
|
402
|
+
|
|
403
|
+
---
|
|
404
|
+
|
|
405
|
+
## System BDD Synthesis (active_platform = system)
|
|
406
|
+
|
|
407
|
+
*Only applies when platform = system. Skip for web and app.*
|
|
408
|
+
|
|
409
|
+
### Step S0 — Brownfield Check
|
|
410
|
+
|
|
411
|
+
Check the source PRD Metadata table for `| **API Source** | existing |`.
|
|
412
|
+
|
|
413
|
+
**Nếu `API Source: existing`:**
|
|
414
|
+
- API contract đã được PO ghi trong phần "Existing API Contract" của PRD.
|
|
415
|
+
- **Skip Steps S1–S3** — không cần scan FE/App BDD, không cần conflict resolution.
|
|
416
|
+
- Dùng bảng "Existing API Contract" trong PRD làm contract input cho Step S4.
|
|
417
|
+
- Set `# @trace.api_source: existing` trong header của file system BDD được gen.
|
|
418
|
+
|
|
419
|
+
**Nếu `API Source` không có hoặc không phải `existing`:**
|
|
420
|
+
- Tiếp tục Steps S1–S3 (normal synthesis flow).
|
|
421
|
+
|
|
422
|
+
---
|
|
423
|
+
|
|
424
|
+
### Step S1 — Scan available FE/App BDDs
|
|
425
|
+
|
|
426
|
+
Search for existing BDDs for this TICKET-ID:
|
|
427
|
+
- Web BDDs: `{paths.specs_dir}/{domain}/web/{TICKET-ID}-*.feature`
|
|
428
|
+
- App BDDs: `{paths.specs_dir}/{domain}/app/{TICKET-ID}-*.feature`
|
|
429
|
+
|
|
430
|
+
Classify the feature:
|
|
431
|
+
|
|
432
|
+
| Condition | Mode |
|
|
433
|
+
|---|---|
|
|
434
|
+
| Both web + app BDDs found | **Multi-platform** — synthesize from both |
|
|
435
|
+
| Only web BDD found | **Web-only** — synthesize from web |
|
|
436
|
+
| Only app BDD found | **App-only** — synthesize from app |
|
|
437
|
+
| No FE/App BDDs found | **Backend-only** — gen directly from PRD |
|
|
438
|
+
|
|
439
|
+
---
|
|
440
|
+
|
|
441
|
+
### Step S2 — Extract expected contracts per platform
|
|
442
|
+
|
|
443
|
+
For each found BDD file, extract:
|
|
444
|
+
- **Triggers**: what user actions call the backend? (map to logical "request" events)
|
|
445
|
+
- **Expected response data**: what fields/shape does each `Then` clause need from the system?
|
|
446
|
+
- **Error signals**: what error states must the backend signal?
|
|
447
|
+
- **Business rules**: what invariants does each platform assume the system enforces?
|
|
448
|
+
|
|
449
|
+
---
|
|
450
|
+
|
|
451
|
+
### Step S3 — Cross-Platform Conflict Check (multi-platform mode only)
|
|
452
|
+
|
|
453
|
+
*Skip if web-only, app-only, or backend-only.*
|
|
454
|
+
|
|
455
|
+
Compare the extracted contracts across platforms. Flag a conflict if any of these differ:
|
|
456
|
+
|
|
457
|
+
| Conflict type | Example |
|
|
458
|
+
|---|---|
|
|
459
|
+
| **Response shape mismatch** | Web expects `{ token, redirect_url }`, App expects `{ token, user_profile }` |
|
|
460
|
+
| **Error semantics mismatch** | Web expects HTTP 423 for lock, App expects custom error code `ACC_LOCKED` |
|
|
461
|
+
| **Business rule contradiction** | Web BDD says "lock after 5 attempts", App BDD says "lock after 3 attempts" |
|
|
462
|
+
| **Data field conflict** | Web expects `expires_in: seconds`, App expects `expires_at: ISO timestamp` |
|
|
463
|
+
|
|
464
|
+
**If conflicts detected → CHECKPOINT (mandatory, cannot skip):**
|
|
465
|
+
|
|
466
|
+
```
|
|
467
|
+
⚠️ CROSS-PLATFORM CONTRACT CONFLICT
|
|
468
|
+
──────────────────────────────────────────────────────────────────
|
|
469
|
+
Feature : {TICKET-ID} — {UC name}
|
|
470
|
+
|
|
471
|
+
Conflict 1: Response shape mismatch
|
|
472
|
+
Web BDD (Then): user sees dashboard → implies { token, redirect_url }
|
|
473
|
+
App BDD (Then): app navigates to HomeScreen → implies { token, user_profile }
|
|
474
|
+
|
|
475
|
+
Resolution options:
|
|
476
|
+
A — Union response
|
|
477
|
+
BE returns all fields: { token, redirect_url, user_profile }
|
|
478
|
+
Clients ignore fields they don't use. Simple, slight over-fetch.
|
|
479
|
+
B — Platform hint in request
|
|
480
|
+
Client sends X-Platform: web|app in header, BE tailors response.
|
|
481
|
+
Cleaner responses, more BE logic.
|
|
482
|
+
C — Separate endpoints
|
|
483
|
+
POST /auth/login/web and POST /auth/login/app
|
|
484
|
+
Maximum flexibility, more endpoints to maintain.
|
|
485
|
+
D — Custom: describe your approach
|
|
486
|
+
──────────────────────────────────────────────────────────────────
|
|
487
|
+
Choose resolution for each conflict (A/B/C/D):
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
Wait for PO's resolution per conflict. Record each decision as a `# @system.resolution:` annotation in the generated system BDD file.
|
|
491
|
+
|
|
492
|
+
**If no conflicts → proceed to Step S4 directly.**
|
|
493
|
+
|
|
494
|
+
---
|
|
495
|
+
|
|
496
|
+
### Step S4 — Generate System BDD scenarios
|
|
497
|
+
|
|
498
|
+
Generate scenarios based on mode and resolved conflicts:
|
|
499
|
+
|
|
500
|
+
- **Multi-platform**: synthesize from both web + app contracts, applying resolved resolutions
|
|
501
|
+
- **Web-only / App-only**: derive from the single platform's contracts
|
|
502
|
+
- **Backend-only**: derive directly from PRD AC/BR using business event language (not HTTP)
|
|
503
|
+
|
|
504
|
+
System BDD step vocabulary (always use — regardless of FE/App vocabulary):
|
|
505
|
+
- Triggers: "the system receives {event}" / "a {actor} submits {action}"
|
|
506
|
+
- Assertions: "the system returns {data}" / "the system signals {error}" / "the system stores {state}"
|
|
507
|
+
- Do NOT use UI words (click, tap, see, navigate) in system BDD
|
|
508
|
+
|
|
509
|
+
**If multi-platform with resolution A (union):**
|
|
510
|
+
- System BDD shows the full response contract: all fields from all platforms
|
|
511
|
+
- Add comment: `# @system.resolution: union — clients receive all fields`
|
|
512
|
+
|
|
513
|
+
**If resolution B (platform hint):**
|
|
514
|
+
- Write separate `Scenario Outline` using Examples table for `web` vs `app` response variants
|
|
515
|
+
- Add comment: `# @system.resolution: platform-hint — X-Platform header determines response shape`
|
|
516
|
+
|
|
517
|
+
**If resolution C (separate endpoints):**
|
|
518
|
+
- Write separate Scenarios for each endpoint
|
|
519
|
+
- Note the endpoint split explicitly in the SCOPE section
|
|
520
|
+
|
|
521
|
+
---
|
|
522
|
+
|
|
523
|
+
## Service Detection (Umbrella Mode Only)
|
|
524
|
+
|
|
525
|
+
*Skip this section if running in spec repo mode.*
|
|
526
|
+
|
|
527
|
+
Read the PRD Metadata table for `| **Service** |` and `| **Module** |` rows.
|
|
528
|
+
|
|
529
|
+
| Condition | Action |
|
|
530
|
+
|---|---|
|
|
531
|
+
| PRD has `Service` row AND value is not "default" | Use it as `active_service` + `active_module`. Load catalog for that module. |
|
|
532
|
+
| PRD has no `Service` row AND `services` defined in project-context.yaml | Ask: "Which service is this BDD for?" (list services, wait for selection) |
|
|
533
|
+
| Single-service project (no `services` array) | `active_service = "default"`, `active_module = tech_stack.module` |
|
|
534
|
+
|
|
535
|
+
**Output path (umbrella mode):**
|
|
536
|
+
- `active_service = "default"` → `{paths.specs_dir}/{domain}/{TICKET-ID}-UC{N}-{slug}.feature`
|
|
537
|
+
- `active_service ≠ "default"` → `{paths.specs_dir}/{domain}/{active_service}/{TICKET-ID}-UC{N}-{slug}.feature`
|
|
538
|
+
|
|
539
|
+
**Platform vocabulary** — adapt BDD step wording based on `active_module`:
|
|
540
|
+
|
|
541
|
+
| Platform type | Modules | "click" | "type" | "see" | "navigate" |
|
|
542
|
+
|---|---|---|---|---|---|
|
|
543
|
+
| Web | react, nextjs, vue, nuxt, angular | "clicks" | "types into" / "enters" | "sees" / "the page shows" | "navigates to" / "goes to" |
|
|
544
|
+
| Mobile | flutter, react-native, ios-swiftui, android-compose | "taps" | "enters" / "inputs" | "sees" / "the screen shows" | "navigates to" / "opens" |
|
|
545
|
+
| Backend / API | java-spring, golang, dotnet, php-laravel | *(no UI steps — use)* "submits a request" / "calls the API" | — | "receives response" / "the system returns" | — |
|
|
546
|
+
|
|
547
|
+
Apply this vocabulary silently when writing Gherkin steps. Do NOT mix web and mobile terms in the same feature file.
|
|
548
|
+
|
|
309
549
|
---
|
|
310
550
|
|
|
311
551
|
## Orchestration Check
|
|
@@ -342,7 +582,9 @@ After generating all `.feature` and `.tsv` files for the assigned UC, return the
|
|
|
342
582
|
|
|
343
583
|
Before generating, check for existing `.feature` files for this PRD:
|
|
344
584
|
|
|
345
|
-
1.
|
|
585
|
+
1. Resolve the search path based on mode:
|
|
586
|
+
- **Spec repo mode**: `{paths.specs_dir}/{domain}/{active_platform}/{TICKET-ID}-UC*.feature`
|
|
587
|
+
- **Umbrella mode**: `{paths.specs_dir}/{domain}/{TICKET-ID}-UC*.feature` (or with `{active_service}/` if multi-service)
|
|
346
588
|
2. Read current PRD `| **Version** |` from metadata (e.g., `1.2`).
|
|
347
589
|
|
|
348
590
|
**If no existing feature files** → fresh generation, proceed normally. Use PRD version as `@trace.prd_version`.
|
|
@@ -445,7 +687,12 @@ CHECKPOINT: "Does this outline look correct? Do you want to add or remove any SC
|
|
|
445
687
|
|
|
446
688
|
## Generate
|
|
447
689
|
|
|
448
|
-
|
|
690
|
+
**Output path by mode:**
|
|
691
|
+
- **Spec repo mode**: `{paths.specs_dir}/{domain}/{active_platform}/{TICKET-ID}-UC{N}-{slug}.feature`
|
|
692
|
+
- **Umbrella mode (single-service)**: `{paths.specs_dir}/{domain}/{TICKET-ID}-UC{N}-{slug}.feature`
|
|
693
|
+
- **Umbrella mode (multi-service)**: `{paths.specs_dir}/{domain}/{active_service}/{TICKET-ID}-UC{N}-{slug}.feature`
|
|
694
|
+
|
|
695
|
+
For each UC, write to the resolved path above. Use vocabulary for the active platform (from Platform Selection or Service Detection).
|
|
449
696
|
|
|
450
697
|
```gherkin
|
|
451
698
|
# ============================================================
|
|
@@ -453,8 +700,9 @@ For each UC, write `{paths.specs_dir}/{domain}/{TICKET-ID}-UC{N}-{slug}.feature`
|
|
|
453
700
|
# @trace.title: <Feature name>
|
|
454
701
|
# @trace.revision: 1 ← static field; use @trace.bdd_version for version tracking (incremented by /review-context --fix or --resume)
|
|
455
702
|
# @trace.domain: <domain>
|
|
456
|
-
# @trace.
|
|
457
|
-
# @trace.
|
|
703
|
+
# @trace.platform: {active_platform — web | app | system | (omit in umbrella mode)}
|
|
704
|
+
# @trace.service: {active_service — omit in spec repo mode}
|
|
705
|
+
# @trace.module: {active_module in umbrella mode; "unknown" in spec repo mode}
|
|
458
706
|
# @trace.status: draft
|
|
459
707
|
# @trace.author: AI-generated
|
|
460
708
|
# @trace.created_at: {YYYY-MM-DD}
|
|
@@ -562,7 +810,7 @@ After generating all `.feature` files, create or update `{paths.trace_dir}/{UC-I
|
|
|
562
810
|
|
|
563
811
|
**TSV columns (tab-separated, one header row + one data row per scenario):**
|
|
564
812
|
```
|
|
565
|
-
sc_id\tsc_title\tspec_ver\tgen_ver\timplemented_by\ttest_count\ttest_classes\tprd_version\tbdd_version\ttech_doc_revision\tprd_status\tuc_status\tstatus\tlast_updated
|
|
813
|
+
sc_id\tsc_title\tspec_ver\tgen_ver\timplemented_by\ttest_count\ttest_classes\tprd_version\tbdd_version\ttech_doc_revision\tprd_status\tuc_status\tfe_phase\tstatus\tlast_updated
|
|
566
814
|
```
|
|
567
815
|
|
|
568
816
|
**Rules:**
|
|
@@ -589,6 +837,7 @@ sc_id\tsc_title\tspec_ver\tgen_ver\timplemented_by\ttest_count\ttest_classes\tpr
|
|
|
589
837
|
| `tech_doc_revision` | `—` |
|
|
590
838
|
| `prd_status` | read `\| **Status** \|` from PRD metadata |
|
|
591
839
|
| `uc_status` | `draft` for new UCs; keep existing value for re-gen |
|
|
840
|
+
| `fe_phase` | `—` (set by `/generate-code --phase` when FE implements) |
|
|
592
841
|
| `status` | `UNTRACKED` |
|
|
593
842
|
| `last_updated` | today `YYYY-MM-DD` |
|
|
594
843
|
|
|
@@ -641,6 +890,11 @@ Suggest the logical next command based on workflow phase:
|
|
|
641
890
|
| /validate-traces | DRIFT/UNTRACKED → `/generate-code {UC-ID}`; GAP → `/generate-tests {UC-ID}`; all OK → create PR |
|
|
642
891
|
| /fix-bug | Create PR and link to ticket |
|
|
643
892
|
| /debug | `/fix-bug {ticket-id}` if fix needed |
|
|
893
|
+
| /report-bug | Send to dev (`/fix-bug {BUG-ID}`); if coverage gap → `/propose-scenario {UC-ID}` |
|
|
894
|
+
| /propose-scenario | Notify PO/Dev to review the proposal in `feedback/bdd-proposals/` |
|
|
895
|
+
| /learn | Continue working — lesson applies on next command |
|
|
896
|
+
| /sync | `/validate-traces` for full coverage; act on any `📥 tester feedback` surfaced |
|
|
897
|
+
| /update-framework | Review `git diff .agent/`, commit; `/sync` for project content |
|
|
644
898
|
|
|
645
899
|
Format the footer as:
|
|
646
900
|
```
|
|
@@ -653,16 +907,26 @@ Next : {suggested command with example arguments}
|
|
|
653
907
|
|
|
654
908
|
```
|
|
655
909
|
/generate-bdd Complete
|
|
910
|
+
|
|
911
|
+
[Spec repo mode — platform: {active_platform}]
|
|
656
912
|
Files:
|
|
657
|
-
{paths.specs_dir}/{domain}/{TICKET-ID}-UC1-{slug}.feature ({N} scenarios)
|
|
658
|
-
{paths.specs_dir}/{domain}/{TICKET-ID}-UC2-{slug}.feature ({N} scenarios)
|
|
913
|
+
{paths.specs_dir}/{domain}/{active_platform}/{TICKET-ID}-UC1-{slug}.feature ({N} scenarios)
|
|
914
|
+
{paths.specs_dir}/{domain}/{active_platform}/{TICKET-ID}-UC2-{slug}.feature ({N} scenarios)
|
|
659
915
|
Trace:
|
|
660
916
|
{paths.trace_dir}/{TICKET-ID}-UC1.tsv ({N} rows)
|
|
661
917
|
{paths.trace_dir}/{TICKET-ID}-UC2.tsv ({N} rows)
|
|
662
|
-
Next
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
918
|
+
Next (spec repo):
|
|
919
|
+
→ Run /generate-bdd again for other platforms (web → app → system)
|
|
920
|
+
→ After all platforms generated: commit + push + notify dev team
|
|
921
|
+
→ Dev team reads BDD from spec submodule — no /generate-bdd on their side
|
|
922
|
+
|
|
923
|
+
[Umbrella mode — service: {active_service}]
|
|
924
|
+
Files:
|
|
925
|
+
{paths.specs_dir}/{domain}/{TICKET-ID}-UC1-{slug}.feature ({N} scenarios)
|
|
926
|
+
Trace:
|
|
927
|
+
{paths.trace_dir}/{TICKET-ID}-UC1.tsv ({N} rows)
|
|
928
|
+
Next (umbrella):
|
|
929
|
+
→ /review-context {feature-file} to verify coverage
|
|
930
|
+
→ /generate-tech-docs {feature-file}
|
|
931
|
+
→ /generate-code {feature-file}
|
|
668
932
|
```
|