@educa-corp/sdd-framework 0.4.0 → 0.5.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/bin/build.js +9 -0
- package/bin/index.js +115 -4
- package/bin/self-check.js +354 -0
- package/bin/trace-schema.json +1199 -0
- package/commands/debug.md +19 -12
- package/commands/define-product.md +19 -12
- package/commands/dev-gen-test.md +53 -19
- package/commands/dev-run-test.md +55 -20
- package/commands/dev-run-test.tmpl +2 -1
- package/commands/dev-smoke-test.md +19 -12
- package/commands/extend-prd.md +907 -0
- package/commands/extend-prd.tmpl +270 -0
- package/commands/fix-bug.md +101 -15
- package/commands/fix-bug.tmpl +29 -3
- package/commands/generate-architecture.md +19 -12
- package/commands/generate-bdd.md +174 -48
- package/commands/generate-bdd.tmpl +107 -18
- package/commands/generate-code.md +122 -29
- package/commands/generate-code.tmpl +69 -10
- package/commands/generate-design-spec.md +19 -12
- package/commands/generate-prd.md +44 -12
- package/commands/generate-prd.tmpl +25 -0
- package/commands/generate-spec-manifest.md +19 -12
- package/commands/generate-tech-docs.md +22 -15
- package/commands/generate-tech-docs.tmpl +2 -2
- package/commands/learn.md +19 -12
- package/commands/map-testids.md +19 -12
- package/commands/propose-scenario.md +91 -15
- package/commands/propose-scenario.tmpl +72 -3
- package/commands/qc-analyze.md +19 -12
- package/commands/qc-design-test.md +20 -12
- package/commands/qc-design-test.tmpl +1 -0
- package/commands/qc-plan.md +19 -12
- package/commands/qc-report.md +19 -12
- package/commands/qc-review.md +19 -12
- package/commands/qc-run-test.md +88 -22
- package/commands/qc-run-test.tmpl +35 -3
- package/commands/refine-prd.md +19 -12
- package/commands/report-bug.md +19 -12
- package/commands/review-code.md +60 -14
- package/commands/review-code.tmpl +41 -2
- package/commands/review-context.md +62 -16
- package/commands/review-context.tmpl +43 -4
- package/commands/review-tech-docs.md +50 -14
- package/commands/review-tech-docs.tmpl +31 -2
- package/commands/setup-ai-first.md +26 -16
- package/commands/setup-ai-first.tmpl +7 -4
- package/commands/sync.md +43 -18
- package/commands/sync.tmpl +37 -14
- package/commands/update-framework.md +43 -4
- package/commands/update-framework.tmpl +37 -0
- package/commands/validate-traces.md +481 -49
- package/commands/validate-traces.tmpl +462 -37
- package/core/FRAMEWORK_VERSION +1 -1
- package/core/README.md +56 -0
- package/core/commands/debug.md +19 -12
- package/core/commands/define-product.md +19 -12
- package/core/commands/dev-gen-test.md +53 -19
- package/core/commands/dev-run-test.md +55 -20
- package/core/commands/dev-smoke-test.md +19 -12
- package/core/commands/extend-prd.md +907 -0
- package/core/commands/fix-bug.md +101 -15
- package/core/commands/generate-architecture.md +19 -12
- package/core/commands/generate-bdd.md +174 -48
- package/core/commands/generate-code.md +122 -29
- package/core/commands/generate-design-spec.md +19 -12
- package/core/commands/generate-prd.md +44 -12
- package/core/commands/generate-spec-manifest.md +19 -12
- package/core/commands/generate-tech-docs.md +22 -15
- package/core/commands/learn.md +19 -12
- package/core/commands/map-testids.md +19 -12
- package/core/commands/propose-scenario.md +91 -15
- package/core/commands/qc-analyze.md +19 -12
- package/core/commands/qc-design-test.md +20 -12
- package/core/commands/qc-plan.md +19 -12
- package/core/commands/qc-report.md +19 -12
- package/core/commands/qc-review.md +19 -12
- package/core/commands/qc-run-test.md +88 -22
- package/core/commands/refine-prd.md +19 -12
- package/core/commands/report-bug.md +19 -12
- package/core/commands/review-code.md +60 -14
- package/core/commands/review-context.md +62 -16
- package/core/commands/review-tech-docs.md +50 -14
- package/core/commands/setup-ai-first.md +26 -16
- package/core/commands/sync.md +43 -18
- package/core/commands/update-framework.md +43 -4
- package/core/commands/validate-traces.md +481 -49
- package/core/modules/android-compose/stack-profile.yaml +1 -1
- package/core/modules/flutter/stack-profile.yaml +1 -1
- package/core/modules/ios-swiftui/stack-profile.yaml +1 -1
- package/core/modules/java-spring/stack-profile.yaml +1 -1
- package/core/modules/nextjs/stack-profile.yaml +1 -1
- package/core/modules/nuxt/stack-profile.yaml +1 -1
- package/core/modules/phaser-game/stack-profile.yaml +1 -1
- package/core/modules/php-laravel/stack-profile.yaml +1 -1
- package/core/modules/qc-playwright/stack-profile.yaml +1 -1
- package/core/modules/react/stack-profile.yaml +1 -1
- package/core/modules/react-native/stack-profile.yaml +1 -1
- package/core/modules/vue/stack-profile.yaml +1 -1
- package/core/rules/workflow.md +29 -0
- package/core/steps/gate.md +13 -8
- package/core/steps/report-footer.md +6 -4
- package/core/steps/trace-mirror.md +34 -7
- package/core/templates/README.md +47 -0
- package/core/templates/feature.template +14 -11
- package/core/templates/project-context.yaml +26 -14
- package/core/templates/tech-design.template.md +1 -1
- package/docs/01-getting-started/installation.md +18 -1
- package/docs/01-getting-started/what-is-sdd.md +4 -2
- package/docs/02-concepts/architecture.md +27 -3
- package/docs/02-concepts/pipeline-steps/02-specification.md +39 -3
- package/docs/02-concepts/pipeline-steps/04-bdd.md +24 -2
- package/docs/02-concepts/pipeline-steps/05-tech-docs.md +18 -1
- package/docs/02-concepts/pipeline-steps/06-code.md +35 -4
- package/docs/02-concepts/pipeline-steps/09-validate-traces.md +137 -12
- package/docs/02-concepts/pipeline-steps/10-feedback-loop.md +59 -3
- package/docs/02-concepts/roles-and-hitl.md +1 -1
- package/docs/02-concepts/traceability.md +126 -94
- package/docs/03-guides/developer.md +20 -4
- package/docs/03-guides/product-owner.md +72 -68
- package/docs/03-guides/tester-qa.md +81 -70
- package/docs/04-reference/commands.md +134 -105
- package/docs/04-reference/configuration.md +146 -94
- package/docs/04-reference/trace-schema.md +145 -37
- package/docs/explain/02-generate-prd.md +80 -78
- package/docs/explain/02b-extend-prd.md +125 -0
- package/docs/explain/03-refine-prd.md +86 -86
- package/docs/explain/04-review-context.md +18 -1
- package/docs/explain/06-generate-bdd.md +23 -0
- package/docs/explain/08-review-tech-docs.md +20 -5
- package/docs/explain/10-review-code.md +36 -2
- package/docs/explain/19-qc-run-test.md +87 -67
- package/docs/explain/21-validate-traces.md +74 -68
- package/docs/explain/23-fix-bug.md +19 -3
- package/docs/explain/26-propose-scenario.md +70 -63
- package/docs/explain/README.md +135 -134
- package/modules/android-compose/stack-profile.yaml +1 -1
- package/modules/flutter/stack-profile.yaml +1 -1
- package/modules/ios-swiftui/stack-profile.yaml +1 -1
- package/modules/java-spring/stack-profile.yaml +1 -1
- package/modules/nextjs/stack-profile.yaml +1 -1
- package/modules/nuxt/stack-profile.yaml +1 -1
- package/modules/phaser-game/stack-profile.yaml +1 -1
- package/modules/php-laravel/stack-profile.yaml +1 -1
- package/modules/qc-playwright/stack-profile.yaml +1 -1
- package/modules/react/stack-profile.yaml +1 -1
- package/modules/react-native/stack-profile.yaml +1 -1
- package/modules/vue/stack-profile.yaml +1 -1
- package/package.json +5 -4
- package/rules/workflow.md +29 -0
- package/scripts/migrate-bdd-platform.js +286 -0
- package/steps/gate.md +13 -8
- package/steps/report-footer.md +6 -4
- package/steps/trace-mirror.md +34 -7
- package/templates/README.md +47 -0
- package/templates/feature.template +14 -11
- package/templates/project-context.yaml +26 -14
- package/templates/tech-design.template.md +1 -1
|
@@ -63,6 +63,14 @@ Lệnh này giới hạn nghiêm ngặt trong **một file feature** được tr
|
|
|
63
63
|
```
|
|
64
64
|
Chỉ tiếp khi Y. *(Khác FE: FE degrade êm để prototype qua mock; BE thì contract là sản phẩm chính → chặn mềm.)*
|
|
65
65
|
- **Có §4 nhưng `@trace.status = draft/in-review`, HOẶC §12 GAP Register còn 🔴 blocker `open` chạm UC này** → WARN (không chặn): "contract chưa chốt / còn {n} blocker-GAP open — có thể phải rework khi contract đổi."
|
|
66
|
+
- **Tech-doc lỗi thời so với BDD** — so entry `{@trace.platform}` trong map `@trace.bdd_versions` của tech-doc vs `@trace.bdd_version` của `.feature` target. Tech-doc **cũ hơn** → WARN (không chặn), kể cả khi `@trace.status: approved`:
|
|
67
|
+
```
|
|
68
|
+
⚠️ §4 contract dựng từ BDD v{old}, .feature này giờ v{new}.
|
|
69
|
+
Doc vẫn 'approved' nên shape dưới đây được lấy nguyên văn — nhưng nó phản ánh
|
|
70
|
+
behavior CŨ. Nếu BDD đổi request/response/error thì code sinh ra sẽ sai từ nguồn.
|
|
71
|
+
Khuyến nghị: /generate-tech-docs {feature-file} → /review-tech-docs (cổng T3b) trước.
|
|
72
|
+
```
|
|
73
|
+
*(Chỉ WARN chứ không chặn: BDD hay bump vì lý do không chạm contract — sửa từ ngữ step, thêm side-effect assertion. Người đọc warning là người biết. `/validate-traces` giữ cờ `TECHDOC_STALE_VS_BDD` song song.)*
|
|
66
74
|
- **Có §4 + `@trace.status: approved` + 0 blocker-GAP** → dùng §4 làm nguồn contract (shape DTO/endpoint/error lấy nguyên văn từ đây, KHÔNG tự chế).
|
|
67
75
|
|
|
68
76
|
---
|
|
@@ -71,14 +79,21 @@ Lệnh này giới hạn nghiêm ngặt trong **một file feature** được tr
|
|
|
71
79
|
|
|
72
80
|
> **Nguồn chuẩn quyết BE/FE = `@trace.platform` của FILE FEATURE** (`system` → BE · `web`/`app` → FE). KHÔNG dùng `platform_type` (suy từ module) để quyết BE/FE — nó chỉ dùng cho **idiom stack/module** (cú pháp, layer, thư viện). Lý do: repo fullstack một-module (vd Next.js có API route) có `platform_type` cố định một giá trị, nhưng vẫn có cả feature `system` (BE) lẫn `web` (FE) — chỉ tag của chính feature mới đúng.
|
|
73
81
|
|
|
74
|
-
Parse `$ARGUMENTS` tìm flag `--phase`:
|
|
82
|
+
Parse `$ARGUMENTS` tìm flag `--phase` và `--force`:
|
|
75
83
|
|
|
76
84
|
| Flag | Ý nghĩa |
|
|
77
85
|
|---|---|
|
|
78
86
|
| `--phase=ui` | FE Phase 1 — sinh UI + layer mock API từ System BDD contract |
|
|
79
87
|
| `--phase=integration` | FE Phase 2 — thay mock adapter bằng lời gọi API thật từ tech docs |
|
|
88
|
+
| `--force` | "Gen lại tường minh" — **CHỈ** bỏ qua guard status ở §Read Trace State (không skip row đang `OK`). Xem định nghĩa hẹp bên dưới. |
|
|
80
89
|
| *(không có)* | Default — full: **BE/`system`** → full backend; **FE (`web`/`app`)** → **FE full** (sinh UI + wire API thật trong một lần, không qua bước mock) |
|
|
81
90
|
|
|
91
|
+
> **`--force` có phạm vi HẸP — đây là ranh giới cứng, không phải khuyến nghị.**
|
|
92
|
+
> Nó bỏ qua **đúng một** thứ: luật "row `OK` thì skip" ở §Read Trace State. **Mọi guard khác giữ nguyên hiệu lực:** Scope Lock (cấm implement scenario của `.feature` khác) · quy tắc EXTEND phi-phá-huỷ (đọc lại trước khi ghi · CẤM full Write trên file đã tồn tại · output phải là superset chặt) · Guard sau-ghi · Fill-before-create · Build Verify.
|
|
93
|
+
> `--force` **KHÔNG** phải "ghi đè tất cả". Không có cờ nào trong lệnh này cho phép điều đó — mất member/tag của UC khác luôn là lỗi chặn, kể cả với `--force`.
|
|
94
|
+
>
|
|
95
|
+
> Dùng khi: tech-doc bump revision có đụng thật phần điều khiển UC này, hoặc cần dựng lại code cho một scenario đang `OK`. **Đọc diff của nguồn TRƯỚC** — nếu revision bump không đụng UC này (vd chỉ thêm UC khác vào doc gộp) thì sinh lại code chỉ để đồng bộ một dòng nhãn là rủi ro không đáng.
|
|
96
|
+
|
|
82
97
|
**Xác định `fe_full`:** khi **KHÔNG** có `--phase` VÀ `@trace.platform` là `web`/`app` → đây là **FE full mode**. Sinh UI **và** wire API thật trong cùng một lần chạy, **bỏ qua** layer mock. Cụ thể: các section **sinh UI** chạy · **Mock API Layer** bị bỏ (chỉ dành `--phase=ui`) · **DS4** và **Integration Phase** VẪN chạy (xem điều kiện của từng section). BE/`system` ở default vẫn là full backend như trước.
|
|
83
98
|
|
|
84
99
|
**Nếu `--phase` được set — xác nhận platform:**
|
|
@@ -203,8 +218,9 @@ Phân giải design điều khiển adapter từ **tech-doc gộp của PRD** `{
|
|
|
203
218
|
|--------|---------|-------------------|
|
|
204
219
|
| `UNTRACKED` | `implemented_by == —` | Generate — scenario chưa có code |
|
|
205
220
|
| `DRIFT` | `spec_ver != gen_ver` | Sửa **tại chỗ đúng method** của scenario đó (Edit) — KHÔNG viết lại cả file (file chung sẽ mất method UC khác) |
|
|
206
|
-
| `OK` | đã implement + test | Skip trừ khi
|
|
221
|
+
| `OK` | đã implement + test | **Skip** — trừ khi có `--force` (xem §Phase Detection). Sinh lại thì sửa **tại chỗ đúng method** (Edit), như hàng `DRIFT`.<br/>*(Tới đây vì cờ ⓘ `PRD_STALE_REF`/`TECHDOC_STALE_REF`? **Sai lệnh.** Hai cờ đó nghĩa là version bump KHÔNG đụng UC này — dùng `/validate-traces --realign-prd-version {UC-ID}` (chỉ sửa dòng nhãn, không đụng logic). Chỉ dùng `--force` khi cờ là 🟠 `PRD_DRIFT`/`TECHDOC_DRIFT` — nội dung đổi thật.)* |
|
|
207
222
|
| `GAP` | đã implement, chưa test | Skip codegen — đã code rồi; chạy `/dev-gen-test` thay vì |
|
|
223
|
+
| `ORPHANED` | SC không còn trong `.feature` nhưng code còn | **Skip codegen** — không có scenario nào để implement. **KHÔNG xoá** code/row (cần người quyết định behavior đó còn cần hay không). Nêu ở report cuối: `⚠️ {sc_id} ORPHANED — code {implemented_by} còn tồn tại nhưng scenario đã bị xoá khỏi .feature. Xử: xoá code+test, hoặc đưa scenario trở lại. (/validate-traces giữ cờ 🔴.)` |
|
|
208
224
|
|
|
209
225
|
Dùng các status này để điền số **Scenarios** trong plan CHECKPOINT (`{X} new, {Y} drifted, {Z} synced-skip`).
|
|
210
226
|
Nếu `.tsv` không tồn tại → coi mọi scenario là `UNTRACKED`.
|
|
@@ -400,16 +416,39 @@ DTOs → Entity/Model → Repository → Service interface → Service impl →
|
|
|
400
416
|
@trace.prd_version={đọc @trace.prd_version từ header file .feature}
|
|
401
417
|
@trace.bdd_version={đọc @trace.bdd_version từ header file .feature}
|
|
402
418
|
@trace.tech_doc_revision={đọc @trace.revision từ header tech-doc, hoặc bỏ nếu không có tech-doc}
|
|
403
|
-
@trace.
|
|
419
|
+
@trace.design_spec_version={CHỈ FE/App (@trace.platform = web|app): đọc | **Version** | từ Metadata design-spec đã nạp. BỎ HẲN dòng này với system/backend}
|
|
420
|
+
@trace.source={paths.specs_dir}/{domain}/{prd-slug}/bdd/{@trace.platform}/{UC-ID}-{slug}.feature
|
|
404
421
|
```
|
|
405
422
|
|
|
406
423
|
`@trace.prd_version` ghi code này được viết theo version PRD nào.
|
|
407
424
|
`@trace.bdd_version` ghi code này được sinh từ version BDD nào.
|
|
408
425
|
`@trace.tech_doc_revision` ghi code này theo revision tech-design nào.
|
|
426
|
+
`@trace.design_spec_version` *(chỉ FE/App)* ghi code này dựng theo version design-spec nào — nguồn của `DESIGNSPEC_DRIFT`. **Vì sao cần:** design-spec là input BẮT BUỘC của code FE (màn hình, component inventory, link Figma frame) và của cả BDD FE/App, nhưng trước đây nó là artifact upstream **DUY NHẤT** không có cột TSV, không có tag trong code, không có cờ drift — designer sửa design-spec sau khi code đã sinh thì không gì phát hiện được.
|
|
409
427
|
`/validate-traces` sẽ gắn cờ drift nếu bất kỳ artifact upstream nào được cập nhật lên version mới hơn.
|
|
410
428
|
|
|
411
429
|
> **Quy tắc entry-point:** `@trace.implements` phải xuất hiện ở **layer entry-point** như định nghĩa trong `CLAUDE.md §2`. Với REST API → Controller. Với module event-driven → event handler / consumer class. Với context-engineering → hàm orchestration prompt. Không bao giờ chỉ đặt ở layer trong.
|
|
412
430
|
|
|
431
|
+
> **File phủ NHIỀU UC → lặp CẢ BLOCK 5 tag, đặt trên method của từng UC. CẤM trỏ thư mục, CẤM gộp về một header file.**
|
|
432
|
+
>
|
|
433
|
+
> Đây là hình dạng đúng:
|
|
434
|
+
> ```
|
|
435
|
+
> // @trace.implements=USR-UC1-SC3
|
|
436
|
+
> // @trace.prd_version=1.2 @trace.bdd_version=1.4 @trace.tech_doc_revision=3
|
|
437
|
+
> // @trace.source=specs/user/create-account/bdd/system/USR-UC1-create-account.feature
|
|
438
|
+
> public AccountDto createAccount(...) { }
|
|
439
|
+
>
|
|
440
|
+
> // @trace.implements=USR-UC3-SC1
|
|
441
|
+
> // @trace.prd_version=2.0 @trace.bdd_version=2.1 @trace.tech_doc_revision=5
|
|
442
|
+
> // @trace.source=specs/user/create-account/bdd/system/USR-UC3-verify-email.feature
|
|
443
|
+
> public void verifyEmail(...) { }
|
|
444
|
+
> ```
|
|
445
|
+
>
|
|
446
|
+
> **Vì sao không được gộp:** 3 tag version là **scalar theo từng UC**. Một file phủ UC1 + UC3 mà chỉ có một header thì không diễn đạt được "UC1 ở bdd v1.4, UC3 ở v2.1" → `/validate-traces` Step 4/5/5c báo drift oan hoặc **mù** drift thật. Version phải nằm cạnh member nó mô tả.
|
|
447
|
+
>
|
|
448
|
+
> **Vì sao không được trỏ thư mục** (`@trace.source=…/bdd/system/`): độ phân giải của trace là `UC × SC`, thư mục làm mất cả hai bậc. Và các lệnh tra tag bằng **khớp chuỗi chính xác** (`/dev-gen-test`, `/dev-smoke-test`, `/review-code` đều tìm "file gắn `@trace.implements={UC-ID}`") → tag trỏ folder ra 0 kết quả, UC rơi về `UNTRACKED` dù code đã có.
|
|
449
|
+
>
|
|
450
|
+
> Quy tắc EXTEND ở §File Scan vốn đã yêu cầu giữ **nguyên si** mọi `@trace.implements` cũ *kể cả của UC khác* — tức là thiết kế vốn là **tích luỹ nhiều block**, không phải gộp lại.
|
|
451
|
+
|
|
413
452
|
> **Quy tắc nguồn giá trị (chống hard-code):** MỌI giá trị cụ thể (endpoint path, error code, tên field/DTO, enum, limit/timeout, header) phải lấy từ **nguồn đã chốt** — **KHÔNG bịa inline**. Nếu một hằng số nghiệp vụ lặp lại hoặc mang ý nghĩa (retry count, ngưỡng, key) → **đặt tên hằng số** (constant/config), không rải magic number/string trong code.
|
|
414
453
|
>
|
|
415
454
|
> **VÉT CẠN NGUỒN TRƯỚC KHI HỎI (SRC-CHAIN) — bắt buộc.** Khi một giá trị chưa thấy ở nguồn chính, PHẢI quét lần lượt các nguồn đã có trong context/spec-package theo thứ tự sau, **dừng ngay khi tìm thấy** (skip-if-answered), KHÔNG hỏi người ngay:
|
|
@@ -535,16 +574,36 @@ Cập nhật `{paths.trace_dir}/{domain}/{prd-slug}/{UC-ID}-{@trace.platform}.ts
|
|
|
535
574
|
| `bdd_version` | `@trace.bdd_version` từ header `.feature` |
|
|
536
575
|
| `tech_doc_revision` | `@trace.revision` từ tech-doc gộp `{TICKET-ID}-tech-design.md` (§4 backend đã điều khiển codegen của UC này), hoặc `—` nếu chưa có doc |
|
|
537
576
|
| `fe_tech_doc_revision` | `@trace.revision` của cùng tech-doc gộp, ghi khi sinh FE có wire adapter theo §4.5.4 (`--phase=integration` **hoặc** `fe_full`); `—` cho BE, hoặc cho FE `--phase=ui` / chưa có §4.5.4 |
|
|
538
|
-
| `fe_phase` | `ui` nếu `--phase=ui` \| `
|
|
577
|
+
| `fe_phase` | `ui` nếu `--phase=ui` \| `integration` nếu `--phase=integration` **hoặc** `fe_full` (đều đã wire real adapter) \| `—` cho BE |
|
|
539
578
|
| `last_updated` | hôm nay `YYYY-MM-DD` |
|
|
540
579
|
|
|
541
|
-
Giữ nguyên mọi cột khác (`sc_title`, `spec_ver`, `prd_version`, `prd_status`, `uc_status`, `test_count`, `test_classes`, `dev_selftest`, `dev_selftest_at`, `qc_status`, `qc_run_at`, `qc_owner`, `qc_blocked_by`).
|
|
580
|
+
Giữ nguyên mọi cột khác (`sc_title`, `spec_ver`, `prd_version`, `prd_status`, `uc_status`, `test_count`, `test_classes`, `dev_selftest`, `dev_selftest_at`, `qc_status`, `qc_run_at`, `qc_owner`, `qc_blocked_by`) — **trừ ngoại lệ có kiểm soát ngay dưới đây**: khi logic vừa đổi thật (lấp stub, hoặc sửa method vì `DRIFT`), 4 cột nghiệm thu `dev_selftest`/`dev_selftest_at`/`qc_status`/`qc_run_at` **phải bị hạ** về "chưa biết". Giữ một `pass` đã hết hiệu lực là báo cáo sai, không phải tôn trọng quyền sở hữu cột.
|
|
542
581
|
`status` được tính bởi `/validate-traces` — không set ở đây.
|
|
543
582
|
|
|
544
|
-
**
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
583
|
+
**Hạ hiệu lực tín hiệu kiểm thử khi logic vừa đổi thật.** Áp cho **HAI** trường hợp — cùng một lý do, cùng một tập cột *(luật "Làm mất hiệu lực ≠ ghi đè", `rules/workflow.md`)*:
|
|
584
|
+
|
|
585
|
+
| Trường hợp | Phạm vi scenario bị ảnh hưởng |
|
|
586
|
+
|---|---|
|
|
587
|
+
| **A. Lấp stub** (Fill-before-create — dòng sổ `→ RESOLVED`) | **Mọi** scenario chạy qua method vừa lấp — gồm cả scenario của **consumer_uc** (UC đã để trắng, thường nằm ở file TSV khác `{consumer_uc}-{platform}.tsv`) |
|
|
588
|
+
| **B. Sửa method vì row đang `DRIFT`** (spec đổi sau lần gen trước) | Đúng các SC vừa được sửa method trong lần chạy này |
|
|
589
|
+
|
|
590
|
+
Với mỗi scenario trong phạm vi:
|
|
591
|
+
- `dev_selftest → not_run` · `dev_selftest_at → —` · `qc_status → not_run` · `qc_run_at → —`.
|
|
592
|
+
- **CHỈ** đụng 4 cột này — ngoại lệ có kiểm soát của luật "giữ nguyên cột khác" ở trên; là thao tác an-toàn (không sửa code UC khác, chỉ hạ cờ nghiệm thu đã hết hiệu lực).
|
|
593
|
+
- **KHÔNG** đụng `test_count`/`test_classes` (test vẫn tồn tại — số lượng không sai, chỉ nội dung cũ; hạ số sẽ làm tỷ lệ coverage nhảy loạn) và **KHÔNG** đụng `qc_owner`/`qc_blocked_by` (con trỏ tới bug — code đổi không làm bug biến mất).
|
|
594
|
+
- Gom danh sách `{consumer_uc}` bị ảnh hưởng (trường hợp A) để in ở "Next".
|
|
595
|
+
|
|
596
|
+
> **Vì sao trường hợp B cũng phải hạ:** lý do giống hệt A — logic vừa đổi thật, nên test cũ đang nghiệm thu một hành vi không còn tồn tại. Trước đây chỉ A được xử lý, nên chuỗi "spec đổi → `DRIFT` → sửa code → `OK`" kết thúc với `qc_status = pass` từ lần QC chạy trên **spec cũ**, và dashboard hiện xanh hoàn toàn. `/fix-bug` đã làm đúng việc này từ trước với chính lời giải thích đó: *"code vừa đổi nên tín hiệu self-test cũ hết hiệu lực"*.
|
|
597
|
+
|
|
598
|
+
Bất kể trường hợp nào, in khối này ở report cuối để dev không tưởng là hệ thống hỏng:
|
|
599
|
+
```
|
|
600
|
+
🔻 Tín hiệu kiểm thử bị hạ ({spec vừa đổi | vừa lấp stub} — nghiệm thu cũ hết hiệu lực):
|
|
601
|
+
{sc_id}: dev_selftest pass→not_run · qc_status pass→not_run
|
|
602
|
+
⚠️ {n} test của các SC này viết cho bản cũ — rà lại nội dung, đừng chỉ chạy lại.
|
|
603
|
+
→ /dev-run-test {UC-ID} rồi QC chạy /qc-run-test {UC-ID}
|
|
604
|
+
ℹ️ Coverage "đã kiểm đạt" trên dashboard sẽ TỤT sau lần này — đó là số đúng;
|
|
605
|
+
số cũ mới là số sai. (Tỷ lệ phủ code/test không đổi — test_count giữ nguyên.)
|
|
606
|
+
```
|
|
548
607
|
|
|
549
608
|
## Refresh Panel Mirror
|
|
550
609
|
{{include:steps/trace-mirror.md}}
|
|
@@ -564,7 +623,7 @@ git commit -m "{commit_format}: {description}"
|
|
|
564
623
|
Files: created={N}, extended={M}, filled={F} stub, skipped={K} | Build: SUCCESS
|
|
565
624
|
Branch: feature/{TICKET_ID}-{slug}
|
|
566
625
|
Phase : {UI (mock layer) | Integration (real API) | FE full (UI + real API) | BE full}
|
|
567
|
-
fe_phase : {ui |
|
|
626
|
+
fe_phase : {ui | integration (—phase=integration | fe_full) | —}
|
|
568
627
|
Figma : {Dev Mode MCP local (grounded) | ⚠️ chỉ link web + text spec (không có MCP local) | n/a cho BE} ← chỉ UI FE/App
|
|
569
628
|
|
|
570
629
|
Next:
|
|
@@ -32,23 +32,23 @@ Hiển thị và chờ phản hồi:
|
|
|
32
32
|
```
|
|
33
33
|
⚙️ MODEL CHECK
|
|
34
34
|
──────────────────────────────────────────────────────────────────
|
|
35
|
-
Recommended :
|
|
35
|
+
Recommended : model Opus mới nhất
|
|
36
36
|
Why needed : Phân tích spec, review kiến trúc, sinh code đòi hỏi
|
|
37
|
-
suy luận sâu. Model nhỏ hơn dễ bỏ sót edge case.
|
|
37
|
+
suy luận sâu. Model nhỏ hơn (Haiku/Sonnet) dễ bỏ sót edge case.
|
|
38
38
|
|
|
39
39
|
Cách đổi trong Claude Code:
|
|
40
|
-
•
|
|
41
|
-
• hoặc:
|
|
40
|
+
• /model → chọn model Opus
|
|
41
|
+
• hoặc: Settings → Model
|
|
42
42
|
|
|
43
|
-
Đang chạy
|
|
44
|
-
Y — đúng
|
|
43
|
+
Đang chạy một model Opus?
|
|
44
|
+
Y — đúng → tiếp tục
|
|
45
45
|
S — bỏ qua kiểm tra (tôi chấp nhận rủi ro chất lượng thấp hơn với model hiện tại)
|
|
46
46
|
──────────────────────────────────────────────────────────────────
|
|
47
47
|
```
|
|
48
48
|
|
|
49
49
|
- "Y" → tiếp tục sang Bước 1.
|
|
50
50
|
- "S" → tiếp tục sang Bước 1 (người dùng chấp nhận rủi ro, thêm ⚠️ vào report cuối).
|
|
51
|
-
- "N" hoặc bất kỳ giá trị nào khác → **DỪNG.** Xuất: "Vui lòng chuyển sang
|
|
51
|
+
- "N" hoặc bất kỳ giá trị nào khác → **DỪNG.** Xuất: "Vui lòng chuyển sang một model Opus (`/model`) rồi chạy lại lệnh này."
|
|
52
52
|
|
|
53
53
|
## Bước 1 — Xác định Target File
|
|
54
54
|
|
|
@@ -57,7 +57,12 @@ Hiển thị và chờ phản hồi:
|
|
|
57
57
|
2. Nếu `$ARGUMENTS` là một **UC-ID / ticket ID / tên rút gọn** (không có path) → phân giải thành file bằng cách glob theo bố cục feature-package. `{prd-slug}` lúc này **chưa biết**, nên dùng wildcard `*` cho segment đó, và `**` đệ quy dưới `bdd/` để phủ hết các thư mục con theo platform (`bdd/web/`, `bdd/app/`, `bdd/system/`):
|
|
58
58
|
- **Lệnh BDD** (target là `.feature`): `{specs_dir}/{domain}/*/bdd/**/{UC-ID}*.feature` — hoặc `{specs_dir}/*/*/bdd/**/{UC-ID}*.feature` nếu domain cũng chưa biết. Nếu lệnh ngụ ý một platform/scope cụ thể (vd: system tech-doc cần BDD `system/`), ưu tiên kết quả trong thư mục con platform đó.
|
|
59
59
|
- **Lệnh PRD** (target là file PRD `{TICKET-ID}-{prd-slug}.md` — file `.md` duy nhất ở gốc feature folder, cạnh `bdd/`): `{specs_dir}/{domain}/*/{TICKET-ID}*.md` nếu biết TICKET-ID; nếu không, `{specs_dir}/{domain}/*/*.md` (khớp feature folder có id tương ứng), hoặc `{specs_dir}/*/*/*.md` nếu domain cũng chưa biết. *(Glob `*/*.md` ở cấp gốc folder chỉ khớp PRD — tech-docs/design-spec `.md` nằm sâu hơn trong thư mục con.)*
|
|
60
|
-
- **Lệnh tech-docs
|
|
60
|
+
- **Lệnh tech-docs** — target là tech-doc **gộp cấp PRD** `{TICKET-ID}-tech-design.md` (MỘT doc phủ nhiều UC; danh sách UC nằm ở `@trace.ucs`). Vì tên file mang `{TICKET-ID}` chứ **không** mang `{UC-ID}`, phải tách trước khi glob:
|
|
61
|
+
- `$ARGUMENTS` là **UC-ID** (`{TICKET-ID}-UC{N}`) → lấy `{TICKET-ID}` = phần **trước** `-UC`, rồi glob `{specs_dir}/{domain}/*/tech-docs/{TICKET-ID}-tech-design.md`.
|
|
62
|
+
- `$ARGUMENTS` là **TICKET-ID** → glob trực tiếp như trên.
|
|
63
|
+
- Chưa biết domain → `{specs_dir}/*/*/tech-docs/{TICKET-ID}-tech-design.md`.
|
|
64
|
+
- Vẫn không khớp → glob rộng `{specs_dir}/*/*/tech-docs/*tech-design*.md` rồi liệt kê để người dùng chọn.
|
|
65
|
+
*(Đừng glob `{UC-ID}*-tech-design*.md` — nó nở thành `FT-001-UC1*-tech-design*.md` và **không bao giờ** khớp `FT-001-tech-design.md`.)*
|
|
61
66
|
- **Lệnh design-spec**: `{specs_dir}/{domain}/*/design-spec/{TICKET-ID}*.md`.
|
|
62
67
|
|
|
63
68
|
Khi một file khớp: đặt nó làm target **và** ghi lại `domain` + `prd_slug` từ path của nó (theo quy tắc trích xuất trong `context-loader.md` Bước 1 — `prd_slug` = segment đầu tiên sau `{specs_dir}/{domain}/`). Mọi path mà lệnh đọc/ghi về sau (BDD/tech-docs/design-spec/trace cùng cấp) đều dùng **`prd_slug` đã phân giải đó**, nên tất cả artifact nằm chung một feature package. Nếu nhiều file khớp (vd: nhiều platform), chọn theo platform/scope của lệnh hoặc liệt kê ra và hỏi.
|
|
@@ -1064,7 +1069,7 @@ Tìm lệnh hiện tại trong bảng phase dưới đây và đánh dấu **pha
|
|
|
1064
1069
|
| Phase | Commands |
|
|
1065
1070
|
|-------|----------|
|
|
1066
1071
|
| Discovery | `/define-product` |
|
|
1067
|
-
| PRD | `/generate-prd` · `/refine-prd` · `/review-context` (PRD) |
|
|
1072
|
+
| PRD | `/generate-prd` · `/extend-prd` · `/refine-prd` · `/review-context` (PRD) |
|
|
1068
1073
|
| Design Spec | `/generate-design-spec` |
|
|
1069
1074
|
| BDD | `/generate-bdd` · `/review-context` (BDD) |
|
|
1070
1075
|
| Tech Design | `/generate-tech-docs` · `/map-testids` · `/review-tech-docs` |
|
|
@@ -1089,6 +1094,7 @@ Gợi ý lệnh kế tiếp hợp lý theo phase của workflow:
|
|
|
1089
1094
|
| /setup-ai-first | `/define-product` để bắt đầu feature đầu tiên |
|
|
1090
1095
|
| /define-product | `/generate-prd {product-definition-file}` |
|
|
1091
1096
|
| /generate-prd | `/refine-prd {prd-file}` rồi `/review-context {prd-file}` |
|
|
1097
|
+
| /extend-prd | `/refine-prd {prd-file}` (soi phần vừa thêm) rồi `/review-context {prd-file}` → PO duyệt → `/generate-bdd` **chỉ cho UC MỚI**; UC cũ dùng `/validate-traces --realign-prd-version {UC-ID}` |
|
|
1092
1098
|
| /refine-prd | Mở Review Board → cập nhật PRD → `/review-context {prd-file}` |
|
|
1093
1099
|
| /review-context (PRD) | Khi 0 critical → PO đặt `Status: approved`, rồi FE/App: `/generate-design-spec {prd-file}` (→ design sign-off → BDD); BE: `/generate-bdd {prd-file}`. Còn critical/NEEDS_FIX → sửa PRD (giữ draft) |
|
|
1094
1100
|
| /generate-design-spec | Designer review → xác nhận link Figma → PO + Designer sign-off → `/generate-bdd {prd-file}` |
|
|
@@ -1101,6 +1107,7 @@ Gợi ý lệnh kế tiếp hợp lý theo phase của workflow:
|
|
|
1101
1107
|
| /qc-run-test | `/qc-report {UC-ID}` rồi `/qc-review {UC-ID}` (review script) |
|
|
1102
1108
|
| /qc-review (script) | `/qc-report {UC-ID}` rồi tạo PR nếu APPROVED |
|
|
1103
1109
|
| /qc-report | `/validate-traces {UC-ID}` để làm mới Living Docs (qc_status) |
|
|
1110
|
+
| /map-testids | `/qc-design-test {UC-ID}` (QC dựng Page Object từ contract §4.5.6 vừa ghi) |
|
|
1104
1111
|
| /generate-tech-docs | `/review-tech-docs {tech-design-file}` |
|
|
1105
1112
|
| /review-tech-docs | `/generate-code {feature-file}` nếu APPROVED; sửa doc nếu NEEDS_FIX |
|
|
1106
1113
|
| /generate-code | Lần gen đầu → `/review-code {UC-ID}`; gen lại → `/dev-gen-test {UC-ID}` |
|
|
@@ -1109,11 +1116,11 @@ Gợi ý lệnh kế tiếp hợp lý theo phase của workflow:
|
|
|
1109
1116
|
| /dev-run-test (failing) | `/fix-bug {ticket-id}` hoặc `/debug {error}` |
|
|
1110
1117
|
| /review-code | `/dev-smoke-test {UC-ID}` hoặc tạo PR |
|
|
1111
1118
|
| /dev-smoke-test | Tạo PR và link tới ticket |
|
|
1112
|
-
| /validate-traces | DRIFT/UNTRACKED → `/generate-code {UC-ID}
|
|
1113
|
-
| /fix-bug |
|
|
1119
|
+
| /validate-traces | **Cờ 🔴 trước (chặn PR):** SEAM_UNWIRED → nối binding sang class thật, xoá/thay stub · STUB_UNRESOLVED → `/generate-code {owner_uc}` (lấp logic tại chỗ + xoá hàm song song) · ORPHANED/TRACE_ORPHAN → quyết định thủ công (xoá code+test, đưa scenario trở lại `.feature`, hoặc sửa `sc_id` của tag). **Rồi:** DRIFT/UNTRACKED → `/generate-code {UC-ID}` · BDD_DRIFT → `/generate-code {feature-file}` · tech-doc lỗi thời vs BDD → `/generate-tech-docs` → `/review-tech-docs` · PRD drift → `/generate-bdd {prd-file}` · GAP → `/dev-gen-test {UC-ID}`. **Chỉ tạo PR khi mọi cờ 🔴 = 0** |
|
|
1120
|
+
| /fix-bug | `/dev-run-test {UC-ID}` (dev_selftest vừa reset về not_run) → tạo PR; nếu fix một `{BUG-ID}` → QC chạy `/qc-run-test {UC-ID}` để verify + đóng bug |
|
|
1114
1121
|
| /debug | `/fix-bug {ticket-id}` nếu cần sửa |
|
|
1115
1122
|
| /report-bug | Gửi cho dev (`/fix-bug {BUG-ID}`); nếu thiếu coverage → `/propose-scenario {UC-ID}` |
|
|
1116
|
-
| /propose-scenario |
|
|
1123
|
+
| /propose-scenario | **Case A** (thiếu scenario cho AC có sẵn) → báo PO/Dev review trong `feedback/bdd-proposals/`; `/generate-bdd` tự chèn khi `Status: accepted`. **Case B** (requirement mới) → `feedback/prd-change-requests/` — PO phải đưa vào PRD trước, KHÔNG tự vào BDD được; `/validate-traces` nhắc lại kèm số ngày chờ chừng nào `Status: Open` |
|
|
1117
1124
|
| /learn | Tiếp tục làm việc — lesson áp dụng ở lệnh kế tiếp |
|
|
1118
1125
|
| /sync | `/validate-traces` để xem độ phủ đầy đủ; xử lý mọi `📥 tester feedback` được nêu |
|
|
1119
1126
|
| /update-framework | Review `git diff .agent/`, commit; `/sync` để đồng bộ nội dung dự án |
|
package/commands/generate-prd.md
CHANGED
|
@@ -32,23 +32,23 @@ Hiển thị và chờ phản hồi:
|
|
|
32
32
|
```
|
|
33
33
|
⚙️ MODEL CHECK
|
|
34
34
|
──────────────────────────────────────────────────────────────────
|
|
35
|
-
Recommended :
|
|
35
|
+
Recommended : model Opus mới nhất
|
|
36
36
|
Why needed : Phân tích spec, review kiến trúc, sinh code đòi hỏi
|
|
37
|
-
suy luận sâu. Model nhỏ hơn dễ bỏ sót edge case.
|
|
37
|
+
suy luận sâu. Model nhỏ hơn (Haiku/Sonnet) dễ bỏ sót edge case.
|
|
38
38
|
|
|
39
39
|
Cách đổi trong Claude Code:
|
|
40
|
-
•
|
|
41
|
-
• hoặc:
|
|
40
|
+
• /model → chọn model Opus
|
|
41
|
+
• hoặc: Settings → Model
|
|
42
42
|
|
|
43
|
-
Đang chạy
|
|
44
|
-
Y — đúng
|
|
43
|
+
Đang chạy một model Opus?
|
|
44
|
+
Y — đúng → tiếp tục
|
|
45
45
|
S — bỏ qua kiểm tra (tôi chấp nhận rủi ro chất lượng thấp hơn với model hiện tại)
|
|
46
46
|
──────────────────────────────────────────────────────────────────
|
|
47
47
|
```
|
|
48
48
|
|
|
49
49
|
- "Y" → tiếp tục sang Bước 1.
|
|
50
50
|
- "S" → tiếp tục sang Bước 1 (người dùng chấp nhận rủi ro, thêm ⚠️ vào report cuối).
|
|
51
|
-
- "N" hoặc bất kỳ giá trị nào khác → **DỪNG.** Xuất: "Vui lòng chuyển sang
|
|
51
|
+
- "N" hoặc bất kỳ giá trị nào khác → **DỪNG.** Xuất: "Vui lòng chuyển sang một model Opus (`/model`) rồi chạy lại lệnh này."
|
|
52
52
|
|
|
53
53
|
## Bước 1 — Xác định Target File
|
|
54
54
|
|
|
@@ -57,7 +57,12 @@ Hiển thị và chờ phản hồi:
|
|
|
57
57
|
2. Nếu `$ARGUMENTS` là một **UC-ID / ticket ID / tên rút gọn** (không có path) → phân giải thành file bằng cách glob theo bố cục feature-package. `{prd-slug}` lúc này **chưa biết**, nên dùng wildcard `*` cho segment đó, và `**` đệ quy dưới `bdd/` để phủ hết các thư mục con theo platform (`bdd/web/`, `bdd/app/`, `bdd/system/`):
|
|
58
58
|
- **Lệnh BDD** (target là `.feature`): `{specs_dir}/{domain}/*/bdd/**/{UC-ID}*.feature` — hoặc `{specs_dir}/*/*/bdd/**/{UC-ID}*.feature` nếu domain cũng chưa biết. Nếu lệnh ngụ ý một platform/scope cụ thể (vd: system tech-doc cần BDD `system/`), ưu tiên kết quả trong thư mục con platform đó.
|
|
59
59
|
- **Lệnh PRD** (target là file PRD `{TICKET-ID}-{prd-slug}.md` — file `.md` duy nhất ở gốc feature folder, cạnh `bdd/`): `{specs_dir}/{domain}/*/{TICKET-ID}*.md` nếu biết TICKET-ID; nếu không, `{specs_dir}/{domain}/*/*.md` (khớp feature folder có id tương ứng), hoặc `{specs_dir}/*/*/*.md` nếu domain cũng chưa biết. *(Glob `*/*.md` ở cấp gốc folder chỉ khớp PRD — tech-docs/design-spec `.md` nằm sâu hơn trong thư mục con.)*
|
|
60
|
-
- **Lệnh tech-docs
|
|
60
|
+
- **Lệnh tech-docs** — target là tech-doc **gộp cấp PRD** `{TICKET-ID}-tech-design.md` (MỘT doc phủ nhiều UC; danh sách UC nằm ở `@trace.ucs`). Vì tên file mang `{TICKET-ID}` chứ **không** mang `{UC-ID}`, phải tách trước khi glob:
|
|
61
|
+
- `$ARGUMENTS` là **UC-ID** (`{TICKET-ID}-UC{N}`) → lấy `{TICKET-ID}` = phần **trước** `-UC`, rồi glob `{specs_dir}/{domain}/*/tech-docs/{TICKET-ID}-tech-design.md`.
|
|
62
|
+
- `$ARGUMENTS` là **TICKET-ID** → glob trực tiếp như trên.
|
|
63
|
+
- Chưa biết domain → `{specs_dir}/*/*/tech-docs/{TICKET-ID}-tech-design.md`.
|
|
64
|
+
- Vẫn không khớp → glob rộng `{specs_dir}/*/*/tech-docs/*tech-design*.md` rồi liệt kê để người dùng chọn.
|
|
65
|
+
*(Đừng glob `{UC-ID}*-tech-design*.md` — nó nở thành `FT-001-UC1*-tech-design*.md` và **không bao giờ** khớp `FT-001-tech-design.md`.)*
|
|
61
66
|
- **Lệnh design-spec**: `{specs_dir}/{domain}/*/design-spec/{TICKET-ID}*.md`.
|
|
62
67
|
|
|
63
68
|
Khi một file khớp: đặt nó làm target **và** ghi lại `domain` + `prd_slug` từ path của nó (theo quy tắc trích xuất trong `context-loader.md` Bước 1 — `prd_slug` = segment đầu tiên sau `{specs_dir}/{domain}/`). Mọi path mà lệnh đọc/ghi về sau (BDD/tech-docs/design-spec/trace cùng cấp) đều dùng **`prd_slug` đã phân giải đó**, nên tất cả artifact nằm chung một feature package. Nếu nhiều file khớp (vd: nhiều platform), chọn theo platform/scope của lệnh hoặc liệt kê ra và hỏi.
|
|
@@ -671,6 +676,31 @@ Khi viết AC, nếu PO đề cập chi tiết visual (màu sắc, animation, la
|
|
|
671
676
|
|
|
672
677
|
---
|
|
673
678
|
|
|
679
|
+
## Guard — PRD đã tồn tại *(chạy TRƯỚC khi ghi bất cứ gì)*
|
|
680
|
+
|
|
681
|
+
Kiểm `{paths.specs_dir}/{domain}/{prd-slug}/{TICKET-ID}-{prd-slug}.md`.
|
|
682
|
+
|
|
683
|
+
**Tồn tại → DỪNG. KHÔNG ghi, KHÔNG hỏi Y/N.** Đọc `| **Version** |`, `| **Status** |`, và số row `# Change Log` để in:
|
|
684
|
+
|
|
685
|
+
```
|
|
686
|
+
❌ PRD đã tồn tại: {path}
|
|
687
|
+
Hiện: v{version} · Status {status} · {n} row Change Log
|
|
688
|
+
|
|
689
|
+
/generate-prd chỉ sinh PRD MỚI. Ghi đè sẽ mất:
|
|
690
|
+
• toàn bộ # Change Log (và file changelog/ đã rollover)
|
|
691
|
+
• Version thật → về 1.0 · Status approved → về draft
|
|
692
|
+
• đánh số lại BR từ đầu → HỎNG mọi @trace.business_rules trong bdd/ đã sinh
|
|
693
|
+
|
|
694
|
+
Muốn THÊM yêu cầu vào PRD này → /extend-prd {path}
|
|
695
|
+
Muốn sửa theo findings review → /refine-prd {path} rồi --resume
|
|
696
|
+
Thật sự muốn làm lại từ đầu → xoá/đổi tên file cũ rồi chạy lại (tự chịu trách nhiệm)
|
|
697
|
+
```
|
|
698
|
+
|
|
699
|
+
> **Vì sao DỪNG HẲN chứ không hỏi Y/N:** ghi đè một PRD đã ký duyệt không phải thứ nên nằm sau một phím bấm. Ba mất mát trên đều **không thể hoàn tác** từ trong lệnh, và cái thứ ba (BR ID churn) lan ra ngoài file — nó phá liên kết ở mọi `.feature` đã sinh, mà chính lệnh này đã dựng một guard riêng để chống ở thao tác *mở cột bảng BR*. Cùng thiệt hại, cùng phải chặn.
|
|
700
|
+
> `rules/workflow.md` có luật chung *"Prefer editing existing files over replacing"*, nhưng đó là prose toàn cục — không phải guard trong lệnh, nên không chặn được ai.
|
|
701
|
+
|
|
702
|
+
---
|
|
703
|
+
|
|
674
704
|
## Generate
|
|
675
705
|
|
|
676
706
|
Ghi `{paths.specs_dir}/{domain}/{prd-slug}/{TICKET-ID}-{prd-slug}.md` theo cấu trúc dưới đây.
|
|
@@ -1028,7 +1058,7 @@ Tìm lệnh hiện tại trong bảng phase dưới đây và đánh dấu **pha
|
|
|
1028
1058
|
| Phase | Commands |
|
|
1029
1059
|
|-------|----------|
|
|
1030
1060
|
| Discovery | `/define-product` |
|
|
1031
|
-
| PRD | `/generate-prd` · `/refine-prd` · `/review-context` (PRD) |
|
|
1061
|
+
| PRD | `/generate-prd` · `/extend-prd` · `/refine-prd` · `/review-context` (PRD) |
|
|
1032
1062
|
| Design Spec | `/generate-design-spec` |
|
|
1033
1063
|
| BDD | `/generate-bdd` · `/review-context` (BDD) |
|
|
1034
1064
|
| Tech Design | `/generate-tech-docs` · `/map-testids` · `/review-tech-docs` |
|
|
@@ -1053,6 +1083,7 @@ Gợi ý lệnh kế tiếp hợp lý theo phase của workflow:
|
|
|
1053
1083
|
| /setup-ai-first | `/define-product` để bắt đầu feature đầu tiên |
|
|
1054
1084
|
| /define-product | `/generate-prd {product-definition-file}` |
|
|
1055
1085
|
| /generate-prd | `/refine-prd {prd-file}` rồi `/review-context {prd-file}` |
|
|
1086
|
+
| /extend-prd | `/refine-prd {prd-file}` (soi phần vừa thêm) rồi `/review-context {prd-file}` → PO duyệt → `/generate-bdd` **chỉ cho UC MỚI**; UC cũ dùng `/validate-traces --realign-prd-version {UC-ID}` |
|
|
1056
1087
|
| /refine-prd | Mở Review Board → cập nhật PRD → `/review-context {prd-file}` |
|
|
1057
1088
|
| /review-context (PRD) | Khi 0 critical → PO đặt `Status: approved`, rồi FE/App: `/generate-design-spec {prd-file}` (→ design sign-off → BDD); BE: `/generate-bdd {prd-file}`. Còn critical/NEEDS_FIX → sửa PRD (giữ draft) |
|
|
1058
1089
|
| /generate-design-spec | Designer review → xác nhận link Figma → PO + Designer sign-off → `/generate-bdd {prd-file}` |
|
|
@@ -1065,6 +1096,7 @@ Gợi ý lệnh kế tiếp hợp lý theo phase của workflow:
|
|
|
1065
1096
|
| /qc-run-test | `/qc-report {UC-ID}` rồi `/qc-review {UC-ID}` (review script) |
|
|
1066
1097
|
| /qc-review (script) | `/qc-report {UC-ID}` rồi tạo PR nếu APPROVED |
|
|
1067
1098
|
| /qc-report | `/validate-traces {UC-ID}` để làm mới Living Docs (qc_status) |
|
|
1099
|
+
| /map-testids | `/qc-design-test {UC-ID}` (QC dựng Page Object từ contract §4.5.6 vừa ghi) |
|
|
1068
1100
|
| /generate-tech-docs | `/review-tech-docs {tech-design-file}` |
|
|
1069
1101
|
| /review-tech-docs | `/generate-code {feature-file}` nếu APPROVED; sửa doc nếu NEEDS_FIX |
|
|
1070
1102
|
| /generate-code | Lần gen đầu → `/review-code {UC-ID}`; gen lại → `/dev-gen-test {UC-ID}` |
|
|
@@ -1073,11 +1105,11 @@ Gợi ý lệnh kế tiếp hợp lý theo phase của workflow:
|
|
|
1073
1105
|
| /dev-run-test (failing) | `/fix-bug {ticket-id}` hoặc `/debug {error}` |
|
|
1074
1106
|
| /review-code | `/dev-smoke-test {UC-ID}` hoặc tạo PR |
|
|
1075
1107
|
| /dev-smoke-test | Tạo PR và link tới ticket |
|
|
1076
|
-
| /validate-traces | DRIFT/UNTRACKED → `/generate-code {UC-ID}
|
|
1077
|
-
| /fix-bug |
|
|
1108
|
+
| /validate-traces | **Cờ 🔴 trước (chặn PR):** SEAM_UNWIRED → nối binding sang class thật, xoá/thay stub · STUB_UNRESOLVED → `/generate-code {owner_uc}` (lấp logic tại chỗ + xoá hàm song song) · ORPHANED/TRACE_ORPHAN → quyết định thủ công (xoá code+test, đưa scenario trở lại `.feature`, hoặc sửa `sc_id` của tag). **Rồi:** DRIFT/UNTRACKED → `/generate-code {UC-ID}` · BDD_DRIFT → `/generate-code {feature-file}` · tech-doc lỗi thời vs BDD → `/generate-tech-docs` → `/review-tech-docs` · PRD drift → `/generate-bdd {prd-file}` · GAP → `/dev-gen-test {UC-ID}`. **Chỉ tạo PR khi mọi cờ 🔴 = 0** |
|
|
1109
|
+
| /fix-bug | `/dev-run-test {UC-ID}` (dev_selftest vừa reset về not_run) → tạo PR; nếu fix một `{BUG-ID}` → QC chạy `/qc-run-test {UC-ID}` để verify + đóng bug |
|
|
1078
1110
|
| /debug | `/fix-bug {ticket-id}` nếu cần sửa |
|
|
1079
1111
|
| /report-bug | Gửi cho dev (`/fix-bug {BUG-ID}`); nếu thiếu coverage → `/propose-scenario {UC-ID}` |
|
|
1080
|
-
| /propose-scenario |
|
|
1112
|
+
| /propose-scenario | **Case A** (thiếu scenario cho AC có sẵn) → báo PO/Dev review trong `feedback/bdd-proposals/`; `/generate-bdd` tự chèn khi `Status: accepted`. **Case B** (requirement mới) → `feedback/prd-change-requests/` — PO phải đưa vào PRD trước, KHÔNG tự vào BDD được; `/validate-traces` nhắc lại kèm số ngày chờ chừng nào `Status: Open` |
|
|
1081
1113
|
| /learn | Tiếp tục làm việc — lesson áp dụng ở lệnh kế tiếp |
|
|
1082
1114
|
| /sync | `/validate-traces` để xem độ phủ đầy đủ; xử lý mọi `📥 tester feedback` được nêu |
|
|
1083
1115
|
| /update-framework | Review `git diff .agent/`, commit; `/sync` để đồng bộ nội dung dự án |
|
|
@@ -141,6 +141,31 @@ Khi viết AC, nếu PO đề cập chi tiết visual (màu sắc, animation, la
|
|
|
141
141
|
|
|
142
142
|
---
|
|
143
143
|
|
|
144
|
+
## Guard — PRD đã tồn tại *(chạy TRƯỚC khi ghi bất cứ gì)*
|
|
145
|
+
|
|
146
|
+
Kiểm `{paths.specs_dir}/{domain}/{prd-slug}/{TICKET-ID}-{prd-slug}.md`.
|
|
147
|
+
|
|
148
|
+
**Tồn tại → DỪNG. KHÔNG ghi, KHÔNG hỏi Y/N.** Đọc `| **Version** |`, `| **Status** |`, và số row `# Change Log` để in:
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
❌ PRD đã tồn tại: {path}
|
|
152
|
+
Hiện: v{version} · Status {status} · {n} row Change Log
|
|
153
|
+
|
|
154
|
+
/generate-prd chỉ sinh PRD MỚI. Ghi đè sẽ mất:
|
|
155
|
+
• toàn bộ # Change Log (và file changelog/ đã rollover)
|
|
156
|
+
• Version thật → về 1.0 · Status approved → về draft
|
|
157
|
+
• đánh số lại BR từ đầu → HỎNG mọi @trace.business_rules trong bdd/ đã sinh
|
|
158
|
+
|
|
159
|
+
Muốn THÊM yêu cầu vào PRD này → /extend-prd {path}
|
|
160
|
+
Muốn sửa theo findings review → /refine-prd {path} rồi --resume
|
|
161
|
+
Thật sự muốn làm lại từ đầu → xoá/đổi tên file cũ rồi chạy lại (tự chịu trách nhiệm)
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
> **Vì sao DỪNG HẲN chứ không hỏi Y/N:** ghi đè một PRD đã ký duyệt không phải thứ nên nằm sau một phím bấm. Ba mất mát trên đều **không thể hoàn tác** từ trong lệnh, và cái thứ ba (BR ID churn) lan ra ngoài file — nó phá liên kết ở mọi `.feature` đã sinh, mà chính lệnh này đã dựng một guard riêng để chống ở thao tác *mở cột bảng BR*. Cùng thiệt hại, cùng phải chặn.
|
|
165
|
+
> `rules/workflow.md` có luật chung *"Prefer editing existing files over replacing"*, nhưng đó là prose toàn cục — không phải guard trong lệnh, nên không chặn được ai.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
144
169
|
## Generate
|
|
145
170
|
|
|
146
171
|
Ghi `{paths.specs_dir}/{domain}/{prd-slug}/{TICKET-ID}-{prd-slug}.md` theo cấu trúc dưới đây.
|
|
@@ -36,23 +36,23 @@ Hiển thị và chờ phản hồi:
|
|
|
36
36
|
```
|
|
37
37
|
⚙️ MODEL CHECK
|
|
38
38
|
──────────────────────────────────────────────────────────────────
|
|
39
|
-
Recommended :
|
|
39
|
+
Recommended : model Opus mới nhất
|
|
40
40
|
Why needed : Phân tích spec, review kiến trúc, sinh code đòi hỏi
|
|
41
|
-
suy luận sâu. Model nhỏ hơn dễ bỏ sót edge case.
|
|
41
|
+
suy luận sâu. Model nhỏ hơn (Haiku/Sonnet) dễ bỏ sót edge case.
|
|
42
42
|
|
|
43
43
|
Cách đổi trong Claude Code:
|
|
44
|
-
•
|
|
45
|
-
• hoặc:
|
|
44
|
+
• /model → chọn model Opus
|
|
45
|
+
• hoặc: Settings → Model
|
|
46
46
|
|
|
47
|
-
Đang chạy
|
|
48
|
-
Y — đúng
|
|
47
|
+
Đang chạy một model Opus?
|
|
48
|
+
Y — đúng → tiếp tục
|
|
49
49
|
S — bỏ qua kiểm tra (tôi chấp nhận rủi ro chất lượng thấp hơn với model hiện tại)
|
|
50
50
|
──────────────────────────────────────────────────────────────────
|
|
51
51
|
```
|
|
52
52
|
|
|
53
53
|
- "Y" → tiếp tục sang Bước 1.
|
|
54
54
|
- "S" → tiếp tục sang Bước 1 (người dùng chấp nhận rủi ro, thêm ⚠️ vào report cuối).
|
|
55
|
-
- "N" hoặc bất kỳ giá trị nào khác → **DỪNG.** Xuất: "Vui lòng chuyển sang
|
|
55
|
+
- "N" hoặc bất kỳ giá trị nào khác → **DỪNG.** Xuất: "Vui lòng chuyển sang một model Opus (`/model`) rồi chạy lại lệnh này."
|
|
56
56
|
|
|
57
57
|
## Bước 1 — Xác định Target File
|
|
58
58
|
|
|
@@ -61,7 +61,12 @@ Hiển thị và chờ phản hồi:
|
|
|
61
61
|
2. Nếu `$ARGUMENTS` là một **UC-ID / ticket ID / tên rút gọn** (không có path) → phân giải thành file bằng cách glob theo bố cục feature-package. `{prd-slug}` lúc này **chưa biết**, nên dùng wildcard `*` cho segment đó, và `**` đệ quy dưới `bdd/` để phủ hết các thư mục con theo platform (`bdd/web/`, `bdd/app/`, `bdd/system/`):
|
|
62
62
|
- **Lệnh BDD** (target là `.feature`): `{specs_dir}/{domain}/*/bdd/**/{UC-ID}*.feature` — hoặc `{specs_dir}/*/*/bdd/**/{UC-ID}*.feature` nếu domain cũng chưa biết. Nếu lệnh ngụ ý một platform/scope cụ thể (vd: system tech-doc cần BDD `system/`), ưu tiên kết quả trong thư mục con platform đó.
|
|
63
63
|
- **Lệnh PRD** (target là file PRD `{TICKET-ID}-{prd-slug}.md` — file `.md` duy nhất ở gốc feature folder, cạnh `bdd/`): `{specs_dir}/{domain}/*/{TICKET-ID}*.md` nếu biết TICKET-ID; nếu không, `{specs_dir}/{domain}/*/*.md` (khớp feature folder có id tương ứng), hoặc `{specs_dir}/*/*/*.md` nếu domain cũng chưa biết. *(Glob `*/*.md` ở cấp gốc folder chỉ khớp PRD — tech-docs/design-spec `.md` nằm sâu hơn trong thư mục con.)*
|
|
64
|
-
- **Lệnh tech-docs
|
|
64
|
+
- **Lệnh tech-docs** — target là tech-doc **gộp cấp PRD** `{TICKET-ID}-tech-design.md` (MỘT doc phủ nhiều UC; danh sách UC nằm ở `@trace.ucs`). Vì tên file mang `{TICKET-ID}` chứ **không** mang `{UC-ID}`, phải tách trước khi glob:
|
|
65
|
+
- `$ARGUMENTS` là **UC-ID** (`{TICKET-ID}-UC{N}`) → lấy `{TICKET-ID}` = phần **trước** `-UC`, rồi glob `{specs_dir}/{domain}/*/tech-docs/{TICKET-ID}-tech-design.md`.
|
|
66
|
+
- `$ARGUMENTS` là **TICKET-ID** → glob trực tiếp như trên.
|
|
67
|
+
- Chưa biết domain → `{specs_dir}/*/*/tech-docs/{TICKET-ID}-tech-design.md`.
|
|
68
|
+
- Vẫn không khớp → glob rộng `{specs_dir}/*/*/tech-docs/*tech-design*.md` rồi liệt kê để người dùng chọn.
|
|
69
|
+
*(Đừng glob `{UC-ID}*-tech-design*.md` — nó nở thành `FT-001-UC1*-tech-design*.md` và **không bao giờ** khớp `FT-001-tech-design.md`.)*
|
|
65
70
|
- **Lệnh design-spec**: `{specs_dir}/{domain}/*/design-spec/{TICKET-ID}*.md`.
|
|
66
71
|
|
|
67
72
|
Khi một file khớp: đặt nó làm target **và** ghi lại `domain` + `prd_slug` từ path của nó (theo quy tắc trích xuất trong `context-loader.md` Bước 1 — `prd_slug` = segment đầu tiên sau `{specs_dir}/{domain}/`). Mọi path mà lệnh đọc/ghi về sau (BDD/tech-docs/design-spec/trace cùng cấp) đều dùng **`prd_slug` đã phân giải đó**, nên tất cả artifact nằm chung một feature package. Nếu nhiều file khớp (vd: nhiều platform), chọn theo platform/scope của lệnh hoặc liệt kê ra và hỏi.
|
|
@@ -648,7 +653,7 @@ Tìm lệnh hiện tại trong bảng phase dưới đây và đánh dấu **pha
|
|
|
648
653
|
| Phase | Commands |
|
|
649
654
|
|-------|----------|
|
|
650
655
|
| Discovery | `/define-product` |
|
|
651
|
-
| PRD | `/generate-prd` · `/refine-prd` · `/review-context` (PRD) |
|
|
656
|
+
| PRD | `/generate-prd` · `/extend-prd` · `/refine-prd` · `/review-context` (PRD) |
|
|
652
657
|
| Design Spec | `/generate-design-spec` |
|
|
653
658
|
| BDD | `/generate-bdd` · `/review-context` (BDD) |
|
|
654
659
|
| Tech Design | `/generate-tech-docs` · `/map-testids` · `/review-tech-docs` |
|
|
@@ -673,6 +678,7 @@ Gợi ý lệnh kế tiếp hợp lý theo phase của workflow:
|
|
|
673
678
|
| /setup-ai-first | `/define-product` để bắt đầu feature đầu tiên |
|
|
674
679
|
| /define-product | `/generate-prd {product-definition-file}` |
|
|
675
680
|
| /generate-prd | `/refine-prd {prd-file}` rồi `/review-context {prd-file}` |
|
|
681
|
+
| /extend-prd | `/refine-prd {prd-file}` (soi phần vừa thêm) rồi `/review-context {prd-file}` → PO duyệt → `/generate-bdd` **chỉ cho UC MỚI**; UC cũ dùng `/validate-traces --realign-prd-version {UC-ID}` |
|
|
676
682
|
| /refine-prd | Mở Review Board → cập nhật PRD → `/review-context {prd-file}` |
|
|
677
683
|
| /review-context (PRD) | Khi 0 critical → PO đặt `Status: approved`, rồi FE/App: `/generate-design-spec {prd-file}` (→ design sign-off → BDD); BE: `/generate-bdd {prd-file}`. Còn critical/NEEDS_FIX → sửa PRD (giữ draft) |
|
|
678
684
|
| /generate-design-spec | Designer review → xác nhận link Figma → PO + Designer sign-off → `/generate-bdd {prd-file}` |
|
|
@@ -685,6 +691,7 @@ Gợi ý lệnh kế tiếp hợp lý theo phase của workflow:
|
|
|
685
691
|
| /qc-run-test | `/qc-report {UC-ID}` rồi `/qc-review {UC-ID}` (review script) |
|
|
686
692
|
| /qc-review (script) | `/qc-report {UC-ID}` rồi tạo PR nếu APPROVED |
|
|
687
693
|
| /qc-report | `/validate-traces {UC-ID}` để làm mới Living Docs (qc_status) |
|
|
694
|
+
| /map-testids | `/qc-design-test {UC-ID}` (QC dựng Page Object từ contract §4.5.6 vừa ghi) |
|
|
688
695
|
| /generate-tech-docs | `/review-tech-docs {tech-design-file}` |
|
|
689
696
|
| /review-tech-docs | `/generate-code {feature-file}` nếu APPROVED; sửa doc nếu NEEDS_FIX |
|
|
690
697
|
| /generate-code | Lần gen đầu → `/review-code {UC-ID}`; gen lại → `/dev-gen-test {UC-ID}` |
|
|
@@ -693,11 +700,11 @@ Gợi ý lệnh kế tiếp hợp lý theo phase của workflow:
|
|
|
693
700
|
| /dev-run-test (failing) | `/fix-bug {ticket-id}` hoặc `/debug {error}` |
|
|
694
701
|
| /review-code | `/dev-smoke-test {UC-ID}` hoặc tạo PR |
|
|
695
702
|
| /dev-smoke-test | Tạo PR và link tới ticket |
|
|
696
|
-
| /validate-traces | DRIFT/UNTRACKED → `/generate-code {UC-ID}
|
|
697
|
-
| /fix-bug |
|
|
703
|
+
| /validate-traces | **Cờ 🔴 trước (chặn PR):** SEAM_UNWIRED → nối binding sang class thật, xoá/thay stub · STUB_UNRESOLVED → `/generate-code {owner_uc}` (lấp logic tại chỗ + xoá hàm song song) · ORPHANED/TRACE_ORPHAN → quyết định thủ công (xoá code+test, đưa scenario trở lại `.feature`, hoặc sửa `sc_id` của tag). **Rồi:** DRIFT/UNTRACKED → `/generate-code {UC-ID}` · BDD_DRIFT → `/generate-code {feature-file}` · tech-doc lỗi thời vs BDD → `/generate-tech-docs` → `/review-tech-docs` · PRD drift → `/generate-bdd {prd-file}` · GAP → `/dev-gen-test {UC-ID}`. **Chỉ tạo PR khi mọi cờ 🔴 = 0** |
|
|
704
|
+
| /fix-bug | `/dev-run-test {UC-ID}` (dev_selftest vừa reset về not_run) → tạo PR; nếu fix một `{BUG-ID}` → QC chạy `/qc-run-test {UC-ID}` để verify + đóng bug |
|
|
698
705
|
| /debug | `/fix-bug {ticket-id}` nếu cần sửa |
|
|
699
706
|
| /report-bug | Gửi cho dev (`/fix-bug {BUG-ID}`); nếu thiếu coverage → `/propose-scenario {UC-ID}` |
|
|
700
|
-
| /propose-scenario |
|
|
707
|
+
| /propose-scenario | **Case A** (thiếu scenario cho AC có sẵn) → báo PO/Dev review trong `feedback/bdd-proposals/`; `/generate-bdd` tự chèn khi `Status: accepted`. **Case B** (requirement mới) → `feedback/prd-change-requests/` — PO phải đưa vào PRD trước, KHÔNG tự vào BDD được; `/validate-traces` nhắc lại kèm số ngày chờ chừng nào `Status: Open` |
|
|
701
708
|
| /learn | Tiếp tục làm việc — lesson áp dụng ở lệnh kế tiếp |
|
|
702
709
|
| /sync | `/validate-traces` để xem độ phủ đầy đủ; xử lý mọi `📥 tester feedback` được nêu |
|
|
703
710
|
| /update-framework | Review `git diff .agent/`, commit; `/sync` để đồng bộ nội dung dự án |
|