@educa-corp/sdd-framework 0.5.0 → 0.7.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 +113 -19
- package/bin/gate-trace.js +487 -0
- package/bin/index.js +445 -146
- package/bin/lint-trace.js +643 -0
- package/bin/self-check.js +804 -2
- package/bin/trace-schema.json +621 -10
- package/core/FRAMEWORK_VERSION +1 -1
- package/core/README.md +20 -0
- package/core/commands/amend-prd.md +518 -0
- package/core/commands/debug.md +123 -511
- package/core/commands/define-product.md +86 -510
- package/core/commands/dev-gen-test.md +86 -510
- package/core/commands/dev-run-test.md +133 -519
- package/core/commands/dev-smoke-test.md +86 -510
- package/core/commands/extend-prd.md +128 -522
- package/core/commands/fix-bug.md +118 -509
- package/core/commands/generate-architecture.md +94 -515
- package/core/commands/generate-bdd.md +128 -513
- package/core/commands/generate-code.md +119 -510
- package/core/commands/generate-design-spec.md +86 -510
- package/core/commands/generate-prd.md +89 -510
- package/core/commands/generate-spec-manifest.md +86 -510
- package/core/commands/generate-tech-docs.md +120 -512
- package/core/commands/learn.md +172 -496
- package/core/commands/map-testids.md +86 -510
- package/core/commands/propose-scenario.md +86 -510
- package/core/commands/qc-analyze.md +86 -510
- package/core/commands/qc-design-test.md +86 -510
- package/core/commands/qc-plan.md +86 -510
- package/core/commands/qc-report.md +86 -510
- package/core/commands/qc-review.md +86 -510
- package/core/commands/qc-run-test.md +115 -513
- package/core/commands/refine-prd.md +112 -522
- package/core/commands/report-bug.md +86 -510
- package/core/commands/review-code.md +123 -511
- package/core/commands/review-context.md +136 -522
- package/core/commands/review-tech-docs.md +90 -511
- package/core/commands/setup-ai-first.md +166 -138
- package/core/commands/sync.md +155 -107
- package/core/commands/update-framework.md +16 -103
- package/core/commands/validate-traces.md +426 -511
- package/core/hooks/data-guard.js +174 -83
- package/core/hooks/settings.json +2 -1
- package/core/rules/workflow.md +64 -4
- package/core/steps/capture-lesson.md +34 -1
- package/core/steps/context-loader.md +50 -8
- package/core/steps/gate.md +92 -35
- package/core/steps/report-footer.md +23 -0
- package/core/templates/README.md +24 -1
- package/core/templates/ci/trace-gate.yml +146 -0
- package/core/templates/feature.template +1 -1
- package/core/templates/hooks/pre-push +61 -0
- package/docs/02-concepts/architecture.md +61 -6
- package/docs/02-concepts/traceability.md +57 -0
- package/docs/03-guides/architect.md +63 -0
- package/docs/04-reference/commands.md +148 -134
- package/docs/04-reference/model-selection.md +32 -19
- package/docs/04-reference/trace-schema.md +39 -0
- package/docs/explain/02b-extend-prd.md +1 -1
- package/docs/explain/02c-amend-prd.md +152 -0
- package/docs/explain/21-validate-traces.md +2 -1
- package/docs/explain/27-learn.md +5 -3
- package/docs/explain/28-sync.md +25 -0
- package/docs/explain/README.md +136 -135
- package/package.json +5 -9
- package/commands/debug.md +0 -917
- package/commands/debug.tmpl +0 -257
- package/commands/define-product.md +0 -862
- package/commands/define-product.tmpl +0 -225
- package/commands/dev-gen-test.md +0 -1124
- package/commands/dev-gen-test.tmpl +0 -490
- package/commands/dev-run-test.md +0 -859
- package/commands/dev-run-test.tmpl +0 -225
- package/commands/dev-smoke-test.md +0 -798
- package/commands/dev-smoke-test.tmpl +0 -217
- package/commands/extend-prd.md +0 -907
- package/commands/extend-prd.tmpl +0 -270
- package/commands/fix-bug.md +0 -910
- package/commands/fix-bug.tmpl +0 -197
- package/commands/generate-architecture.md +0 -775
- package/commands/generate-architecture.tmpl +0 -194
- package/commands/generate-bdd.md +0 -1347
- package/commands/generate-bdd.tmpl +0 -590
- package/commands/generate-code.md +0 -1283
- package/commands/generate-code.tmpl +0 -649
- package/commands/generate-design-spec.md +0 -1161
- package/commands/generate-design-spec.tmpl +0 -524
- package/commands/generate-prd.md +0 -1143
- package/commands/generate-prd.tmpl +0 -223
- package/commands/generate-spec-manifest.md +0 -745
- package/commands/generate-spec-manifest.tmpl +0 -164
- package/commands/generate-tech-docs.md +0 -1344
- package/commands/generate-tech-docs.tmpl +0 -273
- package/commands/learn.md +0 -723
- package/commands/learn.tmpl +0 -63
- package/commands/map-testids.md +0 -662
- package/commands/map-testids.tmpl +0 -81
- package/commands/propose-scenario.md +0 -783
- package/commands/propose-scenario.tmpl +0 -202
- package/commands/qc-analyze.md +0 -693
- package/commands/qc-analyze.tmpl +0 -112
- package/commands/qc-design-test.md +0 -650
- package/commands/qc-design-test.tmpl +0 -69
- package/commands/qc-plan.md +0 -630
- package/commands/qc-plan.tmpl +0 -49
- package/commands/qc-report.md +0 -641
- package/commands/qc-report.tmpl +0 -60
- package/commands/qc-review.md +0 -634
- package/commands/qc-review.tmpl +0 -53
- package/commands/qc-run-test.md +0 -750
- package/commands/qc-run-test.tmpl +0 -116
- package/commands/refine-prd.md +0 -1074
- package/commands/refine-prd.tmpl +0 -278
- package/commands/report-bug.md +0 -729
- package/commands/report-bug.tmpl +0 -148
- package/commands/review-code.md +0 -803
- package/commands/review-code.tmpl +0 -143
- package/commands/review-context.md +0 -1323
- package/commands/review-context.tmpl +0 -527
- package/commands/review-tech-docs.md +0 -982
- package/commands/review-tech-docs.tmpl +0 -401
- package/commands/setup-ai-first.md +0 -574
- package/commands/setup-ai-first.tmpl +0 -378
- package/commands/sync.md +0 -486
- package/commands/sync.tmpl +0 -384
- package/commands/update-framework.md +0 -290
- package/commands/update-framework.tmpl +0 -188
- package/commands/validate-traces.md +0 -1435
- package/commands/validate-traces.tmpl +0 -854
- package/hooks/data-guard.js +0 -141
- package/hooks/settings.json +0 -18
- package/modules/android-compose/module.yaml +0 -13
- package/modules/android-compose/stack-profile.yaml +0 -57
- package/modules/angular/architecture-snippets/component-patterns.md +0 -187
- package/modules/angular/module.yaml +0 -6
- package/modules/angular/stack-profile.yaml +0 -38
- package/modules/context-engineering/architecture-snippets/context-design.md +0 -119
- package/modules/context-engineering/module.yaml +0 -9
- package/modules/context-engineering/stack-profile.yaml +0 -61
- package/modules/dotnet/architecture-snippets/clean-arch.md +0 -160
- package/modules/dotnet/module.yaml +0 -6
- package/modules/dotnet/stack-profile.yaml +0 -50
- package/modules/flutter/module.yaml +0 -14
- package/modules/flutter/stack-profile.yaml +0 -59
- package/modules/golang/architecture-snippets/domain-layout.md +0 -283
- package/modules/golang/module.yaml +0 -6
- package/modules/golang/stack-profile.yaml +0 -40
- package/modules/ios-swiftui/module.yaml +0 -13
- package/modules/ios-swiftui/stack-profile.yaml +0 -55
- package/modules/java-spring/architecture-snippets/layered-arch.md +0 -201
- package/modules/java-spring/module.yaml +0 -15
- package/modules/java-spring/stack-profile.yaml +0 -28
- package/modules/nextjs/architecture-snippets/app-router-patterns.md +0 -269
- package/modules/nextjs/module.yaml +0 -14
- package/modules/nextjs/stack-profile.yaml +0 -74
- package/modules/nuxt/module.yaml +0 -14
- package/modules/nuxt/stack-profile.yaml +0 -58
- package/modules/phaser-game/architecture-snippets/phaser-scene-patterns.md +0 -646
- package/modules/phaser-game/module.yaml +0 -15
- package/modules/phaser-game/stack-profile.yaml +0 -90
- package/modules/php-laravel/architecture-snippets/service-repository.md +0 -302
- package/modules/php-laravel/module.yaml +0 -15
- package/modules/php-laravel/stack-profile.yaml +0 -56
- package/modules/qc-playwright/stack-profile.yaml +0 -66
- package/modules/react/architecture-snippets/hooks-query-patterns.md +0 -254
- package/modules/react/module.yaml +0 -14
- package/modules/react/stack-profile.yaml +0 -63
- package/modules/react-native/module.yaml +0 -14
- package/modules/react-native/stack-profile.yaml +0 -56
- package/modules/vue/module.yaml +0 -14
- package/modules/vue/stack-profile.yaml +0 -65
- package/rules/data-protection.md +0 -80
- package/rules/workflow.md +0 -73
- package/scripts/init.sh +0 -49
- package/scripts/upgrade.sh +0 -94
- package/skills/code/SKILL.md +0 -19
- package/skills/code/SKILL.tmpl +0 -19
- package/skills/debug/SKILL.md +0 -19
- package/skills/debug/SKILL.tmpl +0 -19
- package/skills/design-spec/SKILL.md +0 -11
- package/skills/design-spec/SKILL.tmpl +0 -11
- package/skills/discovery/SKILL.md +0 -14
- package/skills/discovery/SKILL.tmpl +0 -14
- package/skills/prd/SKILL.md +0 -19
- package/skills/prd/SKILL.tmpl +0 -19
- package/skills/qc/qa-analyst/DOC_GAPS.template.md +0 -63
- package/skills/qc/qa-analyst/acceptance-criteria.md +0 -60
- package/skills/qc/qa-analyst/business-rules.md +0 -59
- package/skills/qc/qa-analyst/data-flow.md +0 -64
- package/skills/qc/qa-analyst/spec-breakdown.md +0 -61
- package/skills/qc/qa-designer/e2e/journey.md +0 -41
- package/skills/qc/qa-designer/exploratory/charter.md +0 -68
- package/skills/qc/qa-designer/exploratory/explore-to-functional.md +0 -43
- package/skills/qc/qa-designer/functional/api.md +0 -45
- package/skills/qc/qa-designer/functional/gui-feature.md +0 -46
- package/skills/qc/qa-designer/functional/gui-screen.md +0 -52
- package/skills/qc/qa-designer/integration/api.md +0 -42
- package/skills/qc/qa-designer/integration/db.md +0 -39
- package/skills/qc/qa-designer/integration/gui.md +0 -40
- package/skills/qc/qa-designer/integration/kafka.md +0 -40
- package/skills/qc/qa-designer/non-functional.md +0 -40
- package/skills/qc/qa-planner/test-plan.md +0 -120
- package/skills/qc/qa-reviewer/script/e2e.md +0 -87
- package/skills/qc/qa-reviewer/script/exploratory.md +0 -45
- package/skills/qc/qa-reviewer/script/functional.md +0 -101
- package/skills/qc/qa-reviewer/script/integration.md +0 -91
- package/skills/qc/qa-reviewer/script/non-functional.md +0 -126
- package/skills/qc/qa-reviewer/test-case/e2e.md +0 -73
- package/skills/qc/qa-reviewer/test-case/exploratory.md +0 -43
- package/skills/qc/qa-reviewer/test-case/functional.md +0 -76
- package/skills/qc/qa-reviewer/test-case/integration.md +0 -69
- package/skills/qc/qa-reviewer/test-case/non-functional.md +0 -73
- package/skills/qc/qa-runner/e2e.md +0 -49
- package/skills/qc/qa-runner/exploratory/session.md +0 -36
- package/skills/qc/qa-runner/functional/api.md +0 -35
- package/skills/qc/qa-runner/functional/gui-feature.md +0 -51
- package/skills/qc/qa-runner/functional/gui-screen.md +0 -55
- package/skills/qc/qa-runner/integration.md +0 -47
- package/skills/qc/qa-runner/non-functional.md +0 -49
- package/skills/qc/qa-runner/report/report.md +0 -37
- package/skills/setup-ai-first/SKILL.md +0 -19
- package/skills/setup-ai-first/SKILL.tmpl +0 -19
- package/skills/spec/SKILL.md +0 -19
- package/skills/spec/SKILL.tmpl +0 -19
- package/skills/test/SKILL.md +0 -18
- package/skills/test/SKILL.tmpl +0 -18
- package/steps/business-language.md +0 -56
- package/steps/capture-lesson.md +0 -79
- package/steps/context-loader.md +0 -385
- package/steps/gate.md +0 -94
- package/steps/report-footer.md +0 -102
- package/steps/review-fanout.md +0 -159
- package/steps/spawn-agent.md +0 -129
- package/steps/trace-mirror.md +0 -53
- package/templates/README.md +0 -47
- package/templates/architecture.template.md +0 -394
- package/templates/design-spec.template.md +0 -217
- package/templates/feature.template +0 -123
- package/templates/platform-guide.template.md +0 -145
- package/templates/prd.template.md +0 -283
- package/templates/product-definition.template.md +0 -188
- package/templates/project-context.yaml +0 -212
- package/templates/tech-design.template.md +0 -490
package/core/FRAMEWORK_VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.
|
|
1
|
+
0.7.0
|
package/core/README.md
CHANGED
|
@@ -29,6 +29,26 @@ Từ v0.4.2, `--init` **phát hiện và cứu** các file đó:
|
|
|
29
29
|
- Danh sách file bị ghi đè được in ra ngay sau bước cài
|
|
30
30
|
- `.agent/.install-manifest.json` ghi hash của đúng những gì lần cài trước đã ghi — nhờ đó lệnh phân biệt được **bạn sửa file** với **framework tự đổi file giữa hai version** (một phép so nội dung thuần sẽ flag cả hai, và mỗi lần nâng cấp lại báo oan hàng chục file)
|
|
31
31
|
|
|
32
|
+
## Nâng cấp cũng GỠ file, không chỉ thêm
|
|
33
|
+
|
|
34
|
+
Từ v0.5.1, `--init` gỡ những file framework **không còn ship** — trước đó nó chỉ copy, nên một
|
|
35
|
+
lệnh bị bỏ ở version mới nằm lại trong `.agent/commands/` và `.claude/commands/` **vĩnh viễn**:
|
|
36
|
+
vẫn hiện trong menu `/`, vẫn chạy được, vẫn mang logic version cũ, kể cả khi framework đã bỏ nó
|
|
37
|
+
*vì nó sai*.
|
|
38
|
+
|
|
39
|
+
Một file chỉ bị gỡ khi **cả ba** đúng:
|
|
40
|
+
|
|
41
|
+
1. có trong manifest lần cài trước → do framework đặt vào, không phải bạn tạo
|
|
42
|
+
2. không còn trong bản mới → framework đã bỏ
|
|
43
|
+
3. hash khớp manifest → **còn nguyên bản**, gỡ đi không mất gì
|
|
44
|
+
|
|
45
|
+
Đúng (1)+(2) mà **bạn đã sửa** file đó → **giữ lại** + backup + báo ra. Thà để lại một file lạc
|
|
46
|
+
còn hơn xoá thứ ai đó đã bỏ công viết.
|
|
47
|
+
|
|
48
|
+
`.claude/commands/` cũng được quản như vậy — cộng thêm: nếu project bạn **đã có sẵn** một slash
|
|
49
|
+
command trùng tên (`/debug`, `/sync`, `/learn` là những cái hay trùng), bản cũ của nó được backup
|
|
50
|
+
vào `.agent/.overwritten-{YYYYMMDD}-shortcuts/` và bạn được báo, thay vì bị đè im lặng.
|
|
51
|
+
|
|
32
52
|
Nên thêm vào `.gitignore` của project:
|
|
33
53
|
|
|
34
54
|
```gitignore
|
|
@@ -0,0 +1,518 @@
|
|
|
1
|
+
# /amend-prd — Sửa tại chỗ một yêu cầu đã duyệt trong PRD
|
|
2
|
+
|
|
3
|
+
> **Nhánh thứ tư — đọc bảng này trước khi chọn lệnh:**
|
|
4
|
+
>
|
|
5
|
+
> | Tình huống | Lệnh | Thao tác ghi |
|
|
6
|
+
> |---|---|---|
|
|
7
|
+
> | PRD **chưa có** | `/generate-prd` | **Write** cả file |
|
|
8
|
+
> | PRD đã có, **thêm** UC/AC/BR mới | `/extend-prd` | **Edit add-only** — output là superset chặt |
|
|
9
|
+
> | PRD đã có, **sửa vấn đề review chỉ ra** | `/refine-prd` → Review Board → `--resume` | Edit trong phạm vi finding |
|
|
10
|
+
> | **PRD đã có, PO muốn ĐỔI một yêu cầu đang đúng cú pháp** | **`/amend-prd`** | **Edit tại chỗ** — output **KHÔNG** phải superset |
|
|
11
|
+
>
|
|
12
|
+
> **Vì sao phải là lệnh riêng (GAPS-v4 G54).** Ba lệnh kia đều **từ chối đúng việc này**:
|
|
13
|
+
> `/generate-prd` chỉ có một cổng chặn-cứng rồi vẫn ghi đè (mất changelog, **đánh số lại BR**,
|
|
14
|
+
> phá `@trace.business_rules` trong mọi `.feature` đã sinh) · `/extend-prd` chỉ **add-only**, luật
|
|
15
|
+
> Bước 5 §3 đòi output là *"superset chặt"* · `/refine-prd` tự cấm đụng section nào không được một
|
|
16
|
+
> finding trỏ tới, và findings sinh từ việc soi PRD hiện có nên **không có đường nào để một ý định
|
|
17
|
+
> MỚI của PO đi vào**.
|
|
18
|
+
>
|
|
19
|
+
> Trước lệnh này, hành vi hợp lý duy nhất còn lại là **mở file `.md` ra gõ** — và đó là con đường
|
|
20
|
+
> DUY NHẤT framework không nhìn thấy: mọi drift detector so **nhãn version**, không so **nội dung**
|
|
21
|
+
> (0 content hash trong toàn bộ codebase). Sửa tay không bump version ⇒ **0 cờ**, không 🔴 không 🟠
|
|
22
|
+
> không ⓘ. Nên nhánh thiếu không phải một tiện ích còn nợ; nó là **điểm mù mà chính thiết kế tạo ra**.
|
|
23
|
+
>
|
|
24
|
+
> **`/validate-traces` canh cửa sau** bằng cờ `PRD_UNTRACKED_EDIT` (schema → `spec_edit_detection`):
|
|
25
|
+
> nội dung PRD đổi mà `Version` không đổi ⇒ có người đi cửa sau. Cửa chính là lệnh này.
|
|
26
|
+
|
|
27
|
+
## Gate
|
|
28
|
+
|
|
29
|
+
*Checkpoint: **chặn CỨNG** — SỬA TẠI CHỖ một AC/BR/UC đã duyệt — thao tác ghi DUY NHẤT trong framework được phép làm output KHÔNG phải superset của bản cũ. `--yes` KHÔNG bỏ qua được (gate Bước 3a).*
|
|
30
|
+
|
|
31
|
+
# Gate — Quy trình vào chuẩn cho mọi lệnh
|
|
32
|
+
|
|
33
|
+
Mọi lệnh PHẢI chạy gate này trước khi thực thi phần logic riêng của nó.
|
|
34
|
+
|
|
35
|
+
## Bước 0 — Kiểm tra chế độ Sub-Agent
|
|
36
|
+
|
|
37
|
+
Trước tiên, kiểm tra xem `$ARGUMENTS` có phải là payload JSON từ một orchestrator hay không:
|
|
38
|
+
|
|
39
|
+
1. Thử parse `$ARGUMENTS` dưới dạng JSON.
|
|
40
|
+
2. Nếu parse thành công **và** chứa `"_agent_mode": true`:
|
|
41
|
+
- **Bỏ qua hoàn toàn Bước 1, 2 và 3 của Gate này.**
|
|
42
|
+
- Đặt target file = `payload.target_file`
|
|
43
|
+
- Đặt loaded context = `payload.context` (KHÔNG chạy context-loader.md)
|
|
44
|
+
- Đặt phạm vi UC = `payload.uc_id` (chỉ xử lý UC này)
|
|
45
|
+
- Đặt line range = `payload.uc_section` (chỉ đọc đúng section đó của PRD)
|
|
46
|
+
- Đặt dimension = `payload.dimension` nếu có (lệnh review per-UC: chỉ review đúng lăng kính này)
|
|
47
|
+
- Đi thẳng tới phần logic riêng của lệnh.
|
|
48
|
+
3. Nếu `$ARGUMENTS` không phải JSON hoặc không có `_agent_mode` → tiếp tục sang Bước 1 (chế độ thường).
|
|
49
|
+
|
|
50
|
+
## Bước 0-B — Ghi nhận Model *(KHÔNG chặn)*
|
|
51
|
+
|
|
52
|
+
*Bỏ qua nếu `_agent_mode: true` (sub-agent — orchestrator đã ghi nhận rồi).*
|
|
53
|
+
|
|
54
|
+
Ghi lại **model mà bạn — agent đang chạy lệnh này — thực sự đang dùng**, rồi mang nó vào
|
|
55
|
+
dòng `Model:` của report cuối (xem `report-footer`). Nếu bạn biết mình **không** phải một
|
|
56
|
+
model Opus, gắn thêm cảnh báo ngay ở dòng đó.
|
|
57
|
+
|
|
58
|
+
**KHÔNG hỏi người dùng. KHÔNG chờ. KHÔNG dừng.**
|
|
59
|
+
|
|
60
|
+
> **Vì sao bước này từng là prompt chặn, và vì sao bỏ (GAPS-v3 G41):** bản cũ hiện khối
|
|
61
|
+
> `⚙️ MODEL CHECK` rồi chờ `Y/S/N`. Ba vấn đề cùng chỉ một hướng:
|
|
62
|
+
> **(1)** nó hỏi người dùng thứ mà **agent đã biết chính xác**;
|
|
63
|
+
> **(2)** câu trả lời **không kiểm chứng được** — gõ `Y` xong vẫn đang chạy Haiku thì không
|
|
64
|
+
> gì phát hiện;
|
|
65
|
+
> **(3)** **cả `Y` lẫn `S` đều đi tiếp** — cách duy nhất để nó dừng là tự nguyện gõ `N`.
|
|
66
|
+
> Tức nó **không chặn được ai**, mà tốn một lần chặn ở **mọi** lệnh. Một feature đi hết
|
|
67
|
+
> pipeline dùng 20 lệnh; 30/32 lệnh chạy gate. Hai mươi lần bấm cho một tín hiệu tự-khai
|
|
68
|
+
> không kiểm chứng được — và chính cái giá đó làm mòn CHECKPOINT ở Bước 3, cổng có giá trị thật.
|
|
69
|
+
>
|
|
70
|
+
> Khai báo trong report **mạnh hơn** hỏi: đúng nguồn (agent, không phải người), và nằm
|
|
71
|
+
> **cạnh kết quả** để cân nhắc, thay vì nằm trước khi có kết quả để bấm cho xong.
|
|
72
|
+
|
|
73
|
+
**Vẫn khuyến nghị Opus:** phân tích spec, review kiến trúc và sinh code đòi hỏi suy luận sâu;
|
|
74
|
+
model nhỏ hơn dễ bỏ sót edge case và vi phạm kiến trúc. Đổi: `/model` → chọn Opus.
|
|
75
|
+
|
|
76
|
+
## Bước 1 — Xác định Target File
|
|
77
|
+
|
|
78
|
+
0. **Tách cờ trước khi resolve target.** `$ARGUMENTS` có thể lẫn các `--flag` (vd `--phase=integration`, `--comment`, `--fix`). **Loại bỏ mọi token bắt đầu bằng `--`** ra khỏi phần dùng để tìm target — chỉ giữ phần path/UC-ID/ticket. (Các flag đó do phần logic riêng của lệnh parse ở bước sau, KHÔNG phải tên file.)
|
|
79
|
+
1. Nếu `$ARGUMENTS` (đã tách cờ) được cung cấp và trỏ tới một file tồn tại → dùng trực tiếp làm target.
|
|
80
|
+
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/`):
|
|
81
|
+
- **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 đó.
|
|
82
|
+
- **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.)*
|
|
83
|
+
- **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:
|
|
84
|
+
- `$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`.
|
|
85
|
+
- `$ARGUMENTS` là **TICKET-ID** → glob trực tiếp như trên.
|
|
86
|
+
- Chưa biết domain → `{specs_dir}/*/*/tech-docs/{TICKET-ID}-tech-design.md`.
|
|
87
|
+
- 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.
|
|
88
|
+
*(Đừ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`.)*
|
|
89
|
+
- **Lệnh design-spec**: `{specs_dir}/{domain}/*/design-spec/{TICKET-ID}*.md`.
|
|
90
|
+
|
|
91
|
+
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.
|
|
92
|
+
3. Nếu `$ARGUMENTS` rỗng hoặc không tìm thấy file khớp:
|
|
93
|
+
- Liệt kê các file trong thư mục liên quan của lệnh này (vd: `specs/*/*/*.md` — file PRD ở gốc mỗi feature folder — cho lệnh PRD, `specs/*/*/bdd/**/*.feature` cho lệnh BDD).
|
|
94
|
+
- Hiển thị danh sách cho người dùng và hỏi: "Bạn muốn làm việc với file nào? (Nhập số thứ tự hoặc tên file)"
|
|
95
|
+
- Chờ người dùng chọn rồi mới tiếp tục.
|
|
96
|
+
|
|
97
|
+
## Bước 2 — Chạy Context Loader
|
|
98
|
+
|
|
99
|
+
Nạp toàn bộ context của dự án bằng cách làm theo quy trình trong `steps/context-loader.md`.
|
|
100
|
+
Lưu toàn bộ context đã nạp vào bộ nhớ để dùng xuyên suốt phiên làm việc của lệnh.
|
|
101
|
+
|
|
102
|
+
## Bước 3 — CHECKPOINT
|
|
103
|
+
|
|
104
|
+
*Bỏ qua nếu `_agent_mode: true`.*
|
|
105
|
+
|
|
106
|
+
### 3a — Lệnh này có phải chặn không?
|
|
107
|
+
|
|
108
|
+
| Mức | Lệnh nào | `--yes` bỏ qua được? |
|
|
109
|
+
|---|---|:---:|
|
|
110
|
+
| **Không chặn** | Lệnh read-only: `/review-code` · `/validate-traces` · `/debug` · `/review-context` · `/review-tech-docs` | — (vốn không có) |
|
|
111
|
+
| **Chặn thường** | Mọi lệnh sinh/sửa artifact | ✅ |
|
|
112
|
+
| **Chặn CỨNG** | Ghi đè file đã tồn tại · `--resume` áp findings · migrate · prune | ❌ **không bao giờ** |
|
|
113
|
+
|
|
114
|
+
`--yes` trong `$ARGUMENTS` → bỏ qua CHECKPOINT mức *chặn thường*. (Bước 1 đã tách mọi token
|
|
115
|
+
`--` khỏi phần resolve target, nên cờ này không ảnh hưởng việc tìm file.) Mở đường chạy
|
|
116
|
+
headless: `claude -p "/generate-code UC1 --yes"`.
|
|
117
|
+
|
|
118
|
+
> **KHÔNG tự suy mức từ bảng này.** Mỗi lệnh **tự khai** mức của nó ở một dòng `*Checkpoint: …*`
|
|
119
|
+
> ngay dưới `## Gate` của chính nó — đọc dòng đó, đừng suy diễn. Bảng trên chỉ giải thích ba mức
|
|
120
|
+
> **nghĩa là gì**.
|
|
121
|
+
> Nguồn máy đọc: `bin/trace-schema.json` → `gate.checkpoint_levels`; `self-check` **R11** fail
|
|
122
|
+
> build nếu nhãn trong file lệnh lệch với schema, hoặc nếu một lệnh `hard`/`none` thiếu nhãn.
|
|
123
|
+
> *(Lệnh không có dòng nào = mức **chặn thường**, mặc định.)*
|
|
124
|
+
|
|
125
|
+
> **Mức *không chặn* là thực thi đúng miễn trừ mà `rules/workflow.md` đã cấp từ trước** —
|
|
126
|
+
> trước G41 file đó viết *"read-only commands may skip CHECKPOINT"* còn gate thì luôn đòi.
|
|
127
|
+
> Hai file cùng được nạp vào mọi lệnh mà nói ngược nhau; agent theo cái nào là tuỳ lúc.
|
|
128
|
+
|
|
129
|
+
### 3b — In gì
|
|
130
|
+
|
|
131
|
+
**KHÔNG lặp lại những gì `[CTX LOADED]` vừa in.** Recap của context-loader (Bước 7) đã hiện
|
|
132
|
+
Stack · Platform · Layers · CLAUDE.md · Dict · Entities · Lessons · Service · Status ngay phía
|
|
133
|
+
trên. CHECKPOINT chỉ thêm **một** thông tin mới là `Target`.
|
|
134
|
+
|
|
135
|
+
**Mọi thứ sạch** — recap báo `Status: FULL`, không cờ nào bật → in đúng hai dòng:
|
|
136
|
+
|
|
137
|
+
```
|
|
138
|
+
CHECKPOINT — Target: {resolved file path}
|
|
139
|
+
Tiếp tục? (Y/N)
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
**Có bất thường** → thêm một dòng cho **mỗi** trạng thái, nặng nhất lên đầu:
|
|
143
|
+
|
|
144
|
+
```
|
|
145
|
+
CHECKPOINT
|
|
146
|
+
🔴 Service : unresolved — {lý do context-loader đã ghi}
|
|
147
|
+
⚠️ CLAUDE.md: service overlay THIẾU — dùng root (code sinh ra có thể sai stack)
|
|
148
|
+
⚠️ Target : resolve bằng wildcard — {n} file khớp, chọn {file}
|
|
149
|
+
⚠️ Module : not configured — code sinh ra sẽ dùng default
|
|
150
|
+
Status : PARTIAL — thiếu: {danh sách}
|
|
151
|
+
Target : {resolved file path}
|
|
152
|
+
Tiếp tục? (Y/N)
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### 3c — Cờ nào bật, cờ nào KHÔNG
|
|
156
|
+
|
|
157
|
+
Mỗi dòng ⚠️/🔴 phải ứng với một trạng thái **context-loader đã tính rồi** — không phát minh
|
|
158
|
+
điều kiện mới, chỉ mang thứ đang bị giấu lên chỗ người dùng phải quyết định:
|
|
159
|
+
|
|
160
|
+
| Bật cờ khi | Nguồn | Mức |
|
|
161
|
+
|---|---|:---:|
|
|
162
|
+
| `active_service = unresolved` | context-loader Bước 2b/2c/Fallback | 🔴 |
|
|
163
|
+
| `Status = MINIMAL` | recap Bước 7 | 🔴 |
|
|
164
|
+
| `Status = PARTIAL` | recap Bước 7 | ⚠️ |
|
|
165
|
+
| CLAUDE.md thiếu, hoặc service overlay thiếu | context-loader Bước 3 | ⚠️ |
|
|
166
|
+
| Target resolve qua wildcard, hoặc nhiều file khớp mà lệnh tự chọn | Bước 1 ở trên | ⚠️ |
|
|
167
|
+
| `module` không cấu hình | recap Bước 7 | ⚠️ |
|
|
168
|
+
|
|
169
|
+
**KHÔNG bật cờ cho:** `Lessons: chưa có` · `Dict: missing` · `Entities: missing`. Đó là
|
|
170
|
+
*"dự án chưa điền"*, không phải *"có gì đó sai"* — chúng ở lại trong recap.
|
|
171
|
+
|
|
172
|
+
> **Nguyên tắc một câu:** cờ dành cho thứ **framework không chắc chắn hoặc đã phải đoán**,
|
|
173
|
+
> không dành cho thứ **người dùng chưa làm**. Đẩy hết mọi thứ lên thì CHECKPOINT lại đầy như
|
|
174
|
+
> cũ, và ta quay về đúng chỗ xuất phát: một cổng luôn giống nhau thì bị lướt qua.
|
|
175
|
+
|
|
176
|
+
### 3d — Chờ trả lời
|
|
177
|
+
|
|
178
|
+
- "Y" → tiếp tục sang các bước riêng của lệnh.
|
|
179
|
+
- "N" → dừng, hỏi người dùng muốn thay đổi gì.
|
|
180
|
+
- Có `--yes` và mức *chặn thường* → coi như "Y", **nhưng vẫn IN khối CHECKPOINT** nếu có cờ
|
|
181
|
+
🔴/⚠️ (không chặn ≠ không báo — người đọc log sau này vẫn cần thấy).
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
*Lưu ý: Với lệnh này, target ở Bước 1 là **file PRD đã tồn tại** `{TICKET-ID}-{prd-slug}.md` (file `.md` duy nhất ở gốc feature folder). `$ARGUMENTS` rỗng → liệt kê `{specs_dir}/*/*/*.md` và hỏi. **Không tìm thấy file PRD → DỪNG** và chỉ sang `/generate-prd`.*
|
|
185
|
+
|
|
186
|
+
## Context
|
|
187
|
+
**BẮT BUỘC — đọc `.agent/steps/context-loader.md` và thực thi TOÀN BỘ quy trình trong đó**,
|
|
188
|
+
rồi mới tiếp tục phần bên dưới.
|
|
189
|
+
|
|
190
|
+
Bỏ qua bước này thì `{paths.*}`, `{tech_stack.*}`, `{conventions.*}`, guardrail từ
|
|
191
|
+
`project-lessons`, và routing service (chế độ umbrella) đều **chưa được phân giải** — mọi
|
|
192
|
+
placeholder bên dưới sẽ rỗng và lệnh sẽ đọc/ghi sai chỗ.
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## Ngôn ngữ nghiệp vụ *(áp cho mọi text được sửa: AC, BR, Business Logic, Scope)*
|
|
197
|
+
# Business Language Guard — chặn thuật ngữ kỹ thuật rò vào tài liệu nghiệp vụ
|
|
198
|
+
|
|
199
|
+
Tài liệu nghiệp vụ (PRD, product-definition) mô tả **WHAT** — chỉ ngôn ngữ nghiệp vụ. Guard này chạy **mỗi khi viết hoặc sửa** prose (gen mới, áp fix `--resume`, hiệu chỉnh): **quét và xử lý** các thuật ngữ kỹ thuật/UI phổ thông bên dưới **trước khi ghi**.
|
|
200
|
+
|
|
201
|
+
> Guard này là **baseline framework**, chạy **song song** với Banned Terms của `business-dictionary.md` (cơ chế dictionary giữ nguyên; project vẫn bổ sung term đặc thù vào đó). Khi cả hai cùng áp, ưu tiên bản chuẩn của dictionary nếu có.
|
|
202
|
+
|
|
203
|
+
## Bản đồ xử lý (4 nhóm)
|
|
204
|
+
|
|
205
|
+
**Nhóm 1 — Tương tác/triển khai → DIỄN ĐẠT LẠI sang nghiệp vụ (giữ nguyên nghĩa):**
|
|
206
|
+
|
|
207
|
+
| Kỹ thuật/UI | Cách nói nghiệp vụ |
|
|
208
|
+
|---|---|
|
|
209
|
+
| re-render / render lại / reload / refresh (màn) | "hiển thị lại {tên màn}" |
|
|
210
|
+
| timeout | "quá thời gian chờ" |
|
|
211
|
+
| lỗi mạng / network error | "lỗi kết nối" |
|
|
212
|
+
| UI / giao diện (khi chỉ một màn) | "màn" / "màn hình" |
|
|
213
|
+
| click / tap | "bấm" / "chọn" |
|
|
214
|
+
| popup / modal (nếu chỉ là khái niệm hiển thị) | "hộp thoại" / "thông báo" |
|
|
215
|
+
| disable / enable (nút) | "khoá" / "mở" thao tác |
|
|
216
|
+
| redirect / navigate | "chuyển tới {màn}" |
|
|
217
|
+
|
|
218
|
+
**Nhóm 2 — Visual thuần → CHUYỂN Design Spec (bỏ khỏi PRD, ghi nhận lại):**
|
|
219
|
+
`spinner`, `loading indicator`, `animation`, `fade/slide`, màu sắc, font, layout pixel, micro-interaction → *"Chi tiết visual này thuộc Design Spec — ghi nhận để tạo Design Spec sau."*
|
|
220
|
+
|
|
221
|
+
**Nhóm 3 — Backend/contract thuần → BỎ khỏi PRD (thuộc Tech Docs):**
|
|
222
|
+
`API`, `endpoint`, `token/JWT`, `HTTP status`, tên class/bảng/cột DB, query, payload, header.
|
|
223
|
+
*(Ngoại lệ DUY NHẤT: Appendix "Existing API Contract" khi `API Source: existing` — xem Platform Strategy.)*
|
|
224
|
+
|
|
225
|
+
**Nhóm 4 — Ẩn dụ dữ liệu/cài đặt cho trạng thái nghiệp vụ → XÉT THEO NGHĨA (KHÔNG phải bảng thay thế):**
|
|
226
|
+
|
|
227
|
+
Các từ như `cờ / flag`, `biến / trường / field`, `giá trị / value`, `trả về / return`, `đọc / ghi (cờ)` **đa nghĩa** — kỹ thuật ở ngữ cảnh này, nghiệp vụ ở ngữ cảnh khác. **ĐỪNG thay máy móc.** Một từ chỉ là leak khi **cả hai** điều sau đúng:
|
|
228
|
+
1. Nó chỉ một **artifact lưu trữ/cơ chế** (cờ, biến, trường, giá trị-trả-về, đọc/ghi) đứng thay cho một **trạng thái/khái niệm nghiệp vụ**; VÀ
|
|
229
|
+
2. Khái niệm đó **đã có tên nghiệp vụ** (trong business-dictionary hoặc hiển nhiên).
|
|
230
|
+
|
|
231
|
+
→ Cả hai đúng: viết lại theo **tên nghiệp vụ**, ưu tiên term chuẩn trong business-dictionary.
|
|
232
|
+
→ Từ **tự nó là khái niệm nghiệp vụ**: **GIỮ NGUYÊN**.
|
|
233
|
+
|
|
234
|
+
| Reframe (là leak) | Giữ nguyên (nghiệp vụ thật) |
|
|
235
|
+
|---|---|
|
|
236
|
+
| "cờ tình trạng = chưa làm" → "con *chưa làm khảo sát*" (có term Tình trạng khảo sát) | "giá trị đơn hàng", "giá trị hợp đồng" |
|
|
237
|
+
| "cờ trả giá trị lạ" → "không đọc được tình trạng khảo sát" | "khách trả về sản phẩm" (hoàn hàng) |
|
|
238
|
+
| "đọc cờ thất bại" → "không xác định được tình trạng" | "trả kết quả học tập cho phụ huynh" |
|
|
239
|
+
|
|
240
|
+
**Neo an toàn:** lái theo business-dictionary — nếu đang diễn giải một khái niệm **đã có entry** thì dùng đúng term đó. Hỏi *"khái niệm này có tên nghiệp vụ chưa"*, KHÔNG hỏi *"từ này có bị cấm không"*.
|
|
241
|
+
|
|
242
|
+
**Luật code-format:** trong prose nghiệp vụ, **không bọc backtick/`code`** quanh giá trị/trạng thái nghiệp vụ (`chưa làm`, `đã nộp`) — code-format báo hiệu "token kỹ thuật". Dùng *nghiêng* hoặc "trong ngoặc kép". Backtick chỉ dành cho định danh code/kỹ thuật thật.
|
|
243
|
+
|
|
244
|
+
## Quy tắc áp dụng
|
|
245
|
+
- Quét toàn bộ text sắp ghi (User Story, AC, BR, Business Logic, Scope, Edge Cases, Assumptions…).
|
|
246
|
+
- Nhóm 1 → thay tại chỗ, giữ nguyên nghĩa nghiệp vụ. **Đồng bộ cách diễn đạt** với chỗ đã có sẵn trong cùng tài liệu (vd nếu "quá thời gian chờ" đã dùng ở một BR → dùng nhất quán ở mọi nơi).
|
|
247
|
+
- Nhóm 2 → gỡ khỏi prose nghiệp vụ + nhắc chuyển Design Spec.
|
|
248
|
+
- Nhóm 3 → gỡ khỏi PRD (trừ ngoại lệ brownfield).
|
|
249
|
+
- Nhóm 4 → **xét ngữ cảnh, KHÔNG thay máy móc**: chỉ reframe khi là ẩn dụ dữ liệu cho một khái niệm đã có tên nghiệp vụ (ưu tiên term dictionary); **giữ nguyên** khi từ mang nghĩa nghiệp vụ thật. Đồng thời bỏ backtick khỏi giá trị nghiệp vụ trong prose.
|
|
250
|
+
- Nếu term không có trong bản đồ nhưng rõ ràng là tên kỹ thuật/triển khai → vẫn diễn đạt lại theo tinh thần Nhóm 1, đừng để lọt.
|
|
251
|
+
|
|
252
|
+
**Checklist (dùng ở Quality Checklist của lệnh):** 0 thuật ngữ kỹ thuật/UI (re-render, UI, timeout, spinner, API/endpoint/token…) trong prose nghiệp vụ — đã diễn đạt lại (Nhóm 1) / chuyển Design Spec (Nhóm 2) / bỏ về Tech Docs (Nhóm 3); 0 ẩn dụ dữ liệu cho trạng thái đã có tên nghiệp vụ (cờ/giá trị/đọc-ghi khi là artifact — Nhóm 4) và 0 backtick bọc giá trị nghiệp vụ.
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
## Bước 1 — Nạp PRD và **PO khai tường minh** cái cần sửa
|
|
258
|
+
|
|
259
|
+
Đọc target PRD, trích và lưu:
|
|
260
|
+
|
|
261
|
+
| Giá trị | Nguồn | Dùng để |
|
|
262
|
+
|---|---|---|
|
|
263
|
+
| `current_version` | Metadata `\| **Version** \|` | tính version mới ở Bước 5 |
|
|
264
|
+
| `current_status` | Metadata `\| **Status** \|` | cảnh báo nếu chưa `approved` |
|
|
265
|
+
| `existing_ucs` | danh sách UC-ID + tên | phân giải UC sở hữu · kiểm va chạm |
|
|
266
|
+
| `all_br` | mọi BR-ID + nội dung, theo UC sở hữu (bảng BR ở §3) | phân giải `BR{n}` → UC |
|
|
267
|
+
| `all_ac` | mọi AC-ID + nội dung, theo UC sở hữu (dòng `**AC liên quan:**`) | phân giải `AC{n}` → UC |
|
|
268
|
+
| `changelog_rows` | bảng `# Change Log` | biết PRD đã đi qua những gì |
|
|
269
|
+
| `bdd_generated` | glob `{specs_dir}/{domain}/{prd-slug}/bdd/*/{TICKET-ID}-UC*.feature` | tính blast radius ở Bước 6 |
|
|
270
|
+
|
|
271
|
+
### `amend_targets` — **BẮT BUỘC, không suy đoán**
|
|
272
|
+
|
|
273
|
+
PO phải nêu **chính xác ID** cần sửa. Đây là ràng buộc cứng nhất của lệnh: ID được khai
|
|
274
|
+
**trở thành `{changelog_scope}`** ở Bước 5, và cũng là **danh sách duy nhất** mà guard sau-ghi ở
|
|
275
|
+
Bước 4 cho phép nội dung thay đổi.
|
|
276
|
+
|
|
277
|
+
Nhận `amend_targets` theo thứ tự:
|
|
278
|
+
|
|
279
|
+
1. Từ `$ARGUMENTS` nếu PO đã nêu (vd `/amend-prd PAY01 UC3-BR8`).
|
|
280
|
+
2. Nếu không, **hỏi** — kèm danh sách để PO chọn, đừng để PO gõ mò:
|
|
281
|
+
```
|
|
282
|
+
Sửa gì trong {TICKET-ID}? (nhập ID, cách nhau bằng dấu phẩy)
|
|
283
|
+
|
|
284
|
+
UC3 "Xuất báo cáo"
|
|
285
|
+
BR8 tối đa 5 file mỗi lần
|
|
286
|
+
BR9 chỉ xuất được đơn đã duyệt
|
|
287
|
+
AC5 người dùng xuất được nhiều đơn trong một lần
|
|
288
|
+
UC4 …
|
|
289
|
+
```
|
|
290
|
+
3. **KHÔNG tự suy** target từ một mô tả mơ hồ (*"sửa cái giới hạn file ấy"*). Trình danh sách ứng
|
|
291
|
+
viên rồi để PO chốt. Đoán sai ở đây là sửa sai một yêu cầu đã duyệt.
|
|
292
|
+
|
|
293
|
+
Với **mỗi** target, phân giải **UC sở hữu** ngay (dùng `all_br` / `all_ac`) và lưu vào
|
|
294
|
+
`affected_ucs`. ID không phân giải được về UC nào → **DỪNG**, báo ID sai; đừng sửa mò.
|
|
295
|
+
|
|
296
|
+
### Hai chế độ — và những gì lệnh này **KHÔNG** làm
|
|
297
|
+
|
|
298
|
+
| Chế độ | Cờ | Làm gì |
|
|
299
|
+
|---|---|---|
|
|
300
|
+
| **Sửa nội dung** *(mặc định)* | — | Đổi nội dung của ID đã có. ID **giữ nguyên**. |
|
|
301
|
+
| **Khai tử tại chỗ** | `--retire {ID}` | Đánh dấu ID là không còn hiệu lực **NHƯNG GIỮ NGUYÊN row/ID** (xem Bước 4). |
|
|
302
|
+
|
|
303
|
+
**Ngoài phạm vi — route đi chỗ khác, đừng làm ở đây:**
|
|
304
|
+
|
|
305
|
+
| PO muốn | Lệnh đúng | Vì sao không phải lệnh này |
|
|
306
|
+
|---|---|---|
|
|
307
|
+
| Thêm UC/AC/BR mới | `/extend-prd` | Nó có Discovery delta + đánh số nối tiếp. Lệnh này **không đánh số mới** bao giờ |
|
|
308
|
+
| **XOÁ HẲN** một dòng BR/AC/UC | *(không có, và có chủ ý)* | Xoá row làm `@trace.business_rules` trong mọi `.feature` đã sinh trỏ vào ID không còn ⇒ đúng hình dạng `TRACE_ORPHAN`. Dùng `--retire` — nó đạt cùng mục đích nghiệp vụ mà **không** phá liên kết |
|
|
309
|
+
| Sửa lỗi mà `/refine-prd` vừa chỉ ra | `/refine-prd --resume` | Nó đã có findings + `applied_to_version` để theo dõi delta |
|
|
310
|
+
|
|
311
|
+
**Guard — PRD chưa `approved`:** nếu `current_status != approved` → cảnh báo mềm, không chặn:
|
|
312
|
+
```
|
|
313
|
+
⚠️ PRD đang ở Status: {status} (chưa approved).
|
|
314
|
+
Sửa một yêu cầu CHƯA được duyệt thì thường không cần lệnh này — cứ hoàn tất vòng review
|
|
315
|
+
hiện tại (/review-context → /refine-prd → PO duyệt) là nội dung sẽ đúng.
|
|
316
|
+
Vẫn sửa tại chỗ bây giờ? (Y/N)
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
---
|
|
320
|
+
|
|
321
|
+
## Bước 2 — Kiểm va chạm *(bắt buộc, không bỏ qua)*
|
|
322
|
+
|
|
323
|
+
*Tái dùng đúng **Bước 3.2** của `/extend-prd`, đảo hướng: ở đó câu hỏi là "phần THÊM có làm cái cũ
|
|
324
|
+
sai không"; ở đây là "cái SỬA có làm phần còn lại sai không". Cùng ba câu, cùng lý do — va chạm âm
|
|
325
|
+
thầm là cách một PRD tự mâu thuẫn.*
|
|
326
|
+
|
|
327
|
+
Với **mỗi** target, đối chiếu nội dung mới với toàn bộ PRD và hỏi PO:
|
|
328
|
+
|
|
329
|
+
1. **Mâu thuẫn ngược:** giá trị/hành vi mới có làm một BR **khác** trở nên sai hoặc không đủ không?
|
|
330
|
+
*(BR8 nâng 5→20, nhưng BR12 nói "gộp tối đa 5 file vào một hoá đơn")* → nếu có, **BR12 cũng phải
|
|
331
|
+
vào `amend_targets`**. Đây là lý do bước này không bỏ qua được: sửa một nửa của một cặp ràng buộc
|
|
332
|
+
là tạo một PRD tự mâu thuẫn, và không cờ nào bắt được mâu thuẫn nội bộ của tài liệu.
|
|
333
|
+
2. **AC lệch theo:** AC nào đang ref target này có còn diễn tả đúng outcome không? → nếu không, AC đó
|
|
334
|
+
vào `amend_targets`.
|
|
335
|
+
3. **Phụ thuộc liên service:** thay đổi có đụng cam kết ở **§1c** không? → cập nhật §1c (mức nghiệp vụ).
|
|
336
|
+
|
|
337
|
+
Mỗi câu trả lời "có" **mở rộng `amend_targets`** — và `affected_ucs` mở rộng theo. Chốt lại danh sách
|
|
338
|
+
trước khi sang CHECKPOINT.
|
|
339
|
+
|
|
340
|
+
### CHECKPOINT trước khi ghi
|
|
341
|
+
|
|
342
|
+
```
|
|
343
|
+
CHECKPOINT — Amend PRD {TICKET-ID}
|
|
344
|
+
─────────────────────────────────────────────────
|
|
345
|
+
PRD : v{current_version} ({current_status}) — {n} UC
|
|
346
|
+
Sửa : UC3-BR8 "tối đa 5 file" → "tối đa 20 file"
|
|
347
|
+
UC3-AC5 {tóm tắt thay đổi}
|
|
348
|
+
Khai tử : {UC4-BR15 (--retire) | không}
|
|
349
|
+
Va chạm : {UC5-BR12 cũng phải sửa (mâu thuẫn với BR8 mới) | không}
|
|
350
|
+
UC ảnh hưởng: UC3, UC5 ← sẽ là {changelog_scope}
|
|
351
|
+
Version : v{current} → v{new} ({major|minor}) · Status → draft
|
|
352
|
+
|
|
353
|
+
Sau khi ghi, các UC trên BẮT BUỘC:
|
|
354
|
+
/generate-bdd → /generate-code → /dev-gen-test → /dev-run-test
|
|
355
|
+
❌ KHÔNG dùng --realign-prd-version cho chúng (nội dung đổi thật)
|
|
356
|
+
|
|
357
|
+
BDD đã sinh sẽ lỗi thời: {danh sách UC × platform}
|
|
358
|
+
|
|
359
|
+
Tiếp tục? (Y/N)
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
---
|
|
363
|
+
|
|
364
|
+
## Bước 3 — Altitude: sửa ở đúng tầng
|
|
365
|
+
|
|
366
|
+
*Giống `/extend-prd` Bước 5 và `/refine-prd` Phase 2 — nêu lại vì đây là chỗ dễ trôi nhất khi sửa
|
|
367
|
+
tại chỗ: PO thường mô tả thay đổi bằng cơ chế, và cách rẻ nhất là nhét cơ chế vào AC.*
|
|
368
|
+
|
|
369
|
+
| Tầng | Chứa gì | KHÔNG chứa gì |
|
|
370
|
+
|---|---|---|
|
|
371
|
+
| **AC** | outcome **quan sát/kiểm được** + ref `_(BR: …)_` | số lần retry, timeout, tên cờ, nhánh lỗi vụn, và **không lặp lại nội dung BR nó ref** |
|
|
372
|
+
| **BR** | quy tắc nghiệp vụ (WHAT) — giá trị, giới hạn, điều kiện | chi tiết kỹ thuật triển khai |
|
|
373
|
+
| **Business Logic** | trình tự nghiệp vụ (HOW **nghiệp vụ**) | API, cấu trúc dữ liệu, thư viện |
|
|
374
|
+
|
|
375
|
+
Thay đổi là **cơ chế** mà PO đang muốn nhét vào AC → **route xuống BR/BL**, AC chỉ giữ outcome + ref.
|
|
376
|
+
|
|
377
|
+
**Chạy Business Language Guard trên MỌI text mới TRƯỚC khi ghi.**
|
|
378
|
+
|
|
379
|
+
---
|
|
380
|
+
|
|
381
|
+
## Bước 4 — Ghi *(Edit tại chỗ · guard sau-ghi ĐẢO NGƯỢC)*
|
|
382
|
+
|
|
383
|
+
> **Đây là chỗ lệnh này khác MỌI thao tác ghi khác trong framework.** `/extend-prd` guard bằng
|
|
384
|
+
> *"output là **superset chặt** của bản cũ"*. Ở đây output **cố ý KHÔNG** phải superset — nên guard
|
|
385
|
+
> phải đảo: **mọi thứ giữ nguyên NGOẠI TRỪ đúng các ID trong `amend_targets`.**
|
|
386
|
+
>
|
|
387
|
+
> Guard yếu hơn không được: một lệnh được phép sửa nội dung đã duyệt mà không có rào chính xác là
|
|
388
|
+
> đúng cái `/generate-prd` bị chặn-cứng để tránh.
|
|
389
|
+
|
|
390
|
+
1. **Đọc lại file trên disk NGAY TRƯỚC khi ghi** — không dựa vào bản nạp ở Bước 1.
|
|
391
|
+
2. **CHỈ dùng Edit.** **CẤM tuyệt đối Write cả file.**
|
|
392
|
+
3. **KHÔNG đánh số lại bất kỳ ID nào.** Không thêm ID mới (đó là `/extend-prd`). Không xoá row.
|
|
393
|
+
4. Chế độ `--retire {ID}`: **giữ nguyên row và ID**, đổi nội dung thành dạng khai tử rõ ràng —
|
|
394
|
+
`~~{nội dung cũ}~~ **(không còn hiệu lực từ v{new})**` — và thêm một dòng nêu lý do nghiệp vụ.
|
|
395
|
+
*Không xoá row vì `@trace.business_rules` trong `.feature` đã sinh đang trỏ vào ID này; xoá nó
|
|
396
|
+
biến một liên kết hợp lệ thành `TRACE_ORPHAN` 🔴.*
|
|
397
|
+
|
|
398
|
+
### Guard sau-ghi *(bắt buộc — DỪNG nếu fail)*
|
|
399
|
+
|
|
400
|
+
Đọc lại file vừa ghi, đối chiếu với bản trước khi sửa. Kiểm **hai chiều**:
|
|
401
|
+
|
|
402
|
+
| Chiều | Kiểm gì | Fail nghĩa là |
|
|
403
|
+
|---|---|---|
|
|
404
|
+
| **Bảo toàn** | Mọi UC-ID · BR-ID · AC-ID · row `# Change Log` cũ **vẫn còn** (kể cả ID vừa `--retire`) | Đã xoá thứ không được xoá |
|
|
405
|
+
| **Giới hạn** | **Mọi** nội dung đã đổi đều thuộc một ID trong `amend_targets` — **không có** chỗ nào khác đổi | Đã sửa lan ra ngoài phạm vi PO chốt |
|
|
406
|
+
|
|
407
|
+
Fail bất kỳ chiều nào → **DỪNG NGAY, khôi phục file về bản cũ** (`git checkout -- {file}` nếu đã
|
|
408
|
+
commit, hoặc hoàn tác edit), báo:
|
|
409
|
+
```
|
|
410
|
+
❌ AMEND vi phạm phạm vi — đã chặn.
|
|
411
|
+
{Mất: UC3-BR9 | Sửa ngoài phạm vi: UC7-BR22 (không có trong amend_targets)}
|
|
412
|
+
File đã khôi phục. Chỉ sửa đúng ID đã chốt rồi chạy lại.
|
|
413
|
+
```
|
|
414
|
+
**KHÔNG** tiếp tục sang Bước 5.
|
|
415
|
+
|
|
416
|
+
> **Vì sao chiều "Giới hạn" quan trọng bằng chiều "Bảo toàn":** `{changelog_scope}` ở Bước 5 dựng từ
|
|
417
|
+
> `amend_targets`. Nếu bản ghi lỡ sửa một UC không có trong danh sách đó, thì changelog **không nêu**
|
|
418
|
+
> UC ấy ⇒ `/validate-traces` xếp nó vào ⓘ `PRD_STALE_REF` ⇒ `--realign-prd-version` **mở cửa** và dán
|
|
419
|
+
> nhãn version lại lên một thay đổi chưa ai implement. Đúng hình dạng G53, chỉ đến từ một hướng khác.
|
|
420
|
+
|
|
421
|
+
---
|
|
422
|
+
|
|
423
|
+
## Bước 5 — Bump version & ghi changelog
|
|
424
|
+
|
|
425
|
+
1. Loại bump:
|
|
426
|
+
- **major** (X.0 → X+1.0): đổi hành vi theo hướng **breaking** · `--retire` một BR/AC · tái cấu
|
|
427
|
+
trúc scope. *(Đổi một giới hạn nghiệp vụ 5→20 là **major** — code hiện tại đang chặn ở 5, tức
|
|
428
|
+
nó đang sai so với spec mới.)*
|
|
429
|
+
- **minor** (x.Y → x.Y+1): làm rõ diễn đạt mà **không** đổi hành vi nghiệm thu được.
|
|
430
|
+
2. Cập nhật Metadata: `Version` = mới · `Updated` = hôm nay · **`Status` = `draft`**
|
|
431
|
+
*(yêu cầu đã duyệt vừa đổi ⇒ con dấu duyệt cũ hết hiệu lực — đồng bộ `/refine-prd`, `/extend-prd`.)*
|
|
432
|
+
3. Thêm row lên **đầu** bảng `# Change Log`:
|
|
433
|
+
```
|
|
434
|
+
| {new_version} | {today} | {changelog_scope} |
|
|
435
|
+
```
|
|
436
|
+
**`{changelog_scope}` — mỗi mệnh đề mở đầu bằng UC SỞ HỮU** *(contract:
|
|
437
|
+
`bin/trace-schema.json` → `changelog_row_contract`)*. Nguồn: `affected_ucs` đã chốt ở Bước 2 —
|
|
438
|
+
tức **UC sở hữu của từng ID trong `amend_targets`**. Ngăn nhau bằng `;`. Thay đổi ở §1c/§1d
|
|
439
|
+
(không thuộc UC nào) → `PRD-global`.
|
|
440
|
+
|
|
441
|
+
**Ví dụ đúng**
|
|
442
|
+
```
|
|
443
|
+
| 2.0 | 2026-08-19 | UC3: sửa BR8 (giới hạn 5→20 file), AC5 theo đó; UC5: sửa BR12 (bỏ ràng buộc gộp 5) |
|
|
444
|
+
| 3.0 | 2026-08-22 | UC4: khai tử BR15 (không còn yêu cầu duyệt hai cấp) |
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
⚠️ **BR/AC không bao giờ đứng một mình.** `sửa BR8` (thiếu `UC3:`) nêu đủ ID để **không** bị coi
|
|
448
|
+
là mơ hồ, nhưng consumer khớp theo **UC** — nên UC3 rơi vào ⓘ và `--realign` dán nhãn lại lên
|
|
449
|
+
đúng thay đổi này. **Lệnh này là producer dễ mắc lỗi đó nhất**, vì đầu vào của nó *là* một BR-ID.
|
|
450
|
+
|
|
451
|
+
⚠️ **KHÔNG dùng hậu tố `[no-behavior]` ở lệnh này.** Nó dành cho fix mà producer **chứng minh
|
|
452
|
+
được** là thuần cấu trúc (`changelog_row_contract.neutral_checks`). Lệnh này tồn tại để đổi **nội
|
|
453
|
+
dung nghiệp vụ** — theo định nghĩa là có đổi hành vi.
|
|
454
|
+
4. Cập nhật dòng đầu section: `> Hiện tại: **v{new}** ({today}) · Lịch sử đầy đủ → [changelog](./changelog/{TICKET-ID}-{prd-slug}.changelog.md)`
|
|
455
|
+
5. **Rollover** (cửa sổ trượt 5 row) — theo đúng quy ước `/refine-prd` Phase 3.
|
|
456
|
+
|
|
457
|
+
---
|
|
458
|
+
|
|
459
|
+
## Bước 6 — Report
|
|
460
|
+
|
|
461
|
+
**Đọc `.agent/steps/report-footer.md`** và áp đúng khuôn footer trong đó (Status Badge ·
|
|
462
|
+
Output Artifacts · Next) cho report cuối, kèm khối bên dưới.
|
|
463
|
+
|
|
464
|
+
Ví dụ footer cho lệnh này:
|
|
465
|
+
|
|
466
|
+
```
|
|
467
|
+
/amend-prd Đã sửa — {TICKET-ID} {tên feature}
|
|
468
|
+
|
|
469
|
+
Version : v1.3 → v2.0 (major) · Status → draft
|
|
470
|
+
Sửa : UC3-BR8 "tối đa 5 file" → "tối đa 20 file"
|
|
471
|
+
UC3-AC5 diễn đạt lại outcome theo BR8 mới
|
|
472
|
+
UC5-BR12 bỏ ràng buộc gộp 5 (va chạm với BR8 mới — Bước 2 câu 1)
|
|
473
|
+
Khai tử : không
|
|
474
|
+
Changelog : | 2.0 | 2026-08-19 | UC3: sửa BR8 (giới hạn 5→20 file), AC5 theo đó; UC5: sửa BR12 |
|
|
475
|
+
|
|
476
|
+
Guard sau-ghi : ✅ Bảo toàn — {n} UC · {m} AC · {k} BR · {j} changelog row cũ còn nguyên
|
|
477
|
+
✅ Giới hạn — 0 chỗ đổi ngoài amend_targets
|
|
478
|
+
|
|
479
|
+
🔴 UC PHẢI làm lại (nội dung đổi thật): UC3, UC5
|
|
480
|
+
/generate-bdd {prd-file} ← BDD hiện tại đang nghiệm thu giới hạn 5
|
|
481
|
+
→ /generate-code {UC-ID} ← code đang chặn ở 5
|
|
482
|
+
→ /dev-gen-test → /dev-run-test ← test đang assert 5 và vẫn PASS
|
|
483
|
+
❌ TUYỆT ĐỐI KHÔNG --realign-prd-version cho UC3/UC5 — đó là dán nhãn lên thay đổi
|
|
484
|
+
chưa ai implement.
|
|
485
|
+
|
|
486
|
+
BDD sẽ lỗi thời: bdd/system/{TICKET-ID}-UC3.feature · bdd/web/{TICKET-ID}-UC3.feature
|
|
487
|
+
|
|
488
|
+
UC KHÔNG đổi ({n}): {UC1, UC2, UC4…}
|
|
489
|
+
→ ⓘ PRD_STALE_REF. Sạch bằng: /validate-traces --realign-prd-version {UC-ID}
|
|
490
|
+
|
|
491
|
+
⚠️ Status đã reset về draft — thay đổi chưa được duyệt lại.
|
|
492
|
+
|
|
493
|
+
---
|
|
494
|
+
Status : ✅ Complete
|
|
495
|
+
Output Artifacts:
|
|
496
|
+
updated {paths.specs_dir}/{domain}/{prd-slug}/{TICKET-ID}-{prd-slug}.md (v2.0)
|
|
497
|
+
updated {paths.specs_dir}/{domain}/{prd-slug}/changelog/… (nếu có rollover)
|
|
498
|
+
Pipeline : Discovery → [PRD ◀ bạn ở đây] → Design Spec → BDD → Tech Design → Code → Dev Self-Check → QC → Trace Audit
|
|
499
|
+
Next : /review-context {prd-file} ← kiểm chất lượng phần vừa sửa
|
|
500
|
+
→ khi sạch critical, PO đặt Status: approved
|
|
501
|
+
→ /generate-bdd {prd-file} ← CHỈ cho UC3, UC5
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
---
|
|
505
|
+
|
|
506
|
+
## Quality Checklist *(kiểm trước khi ghi)*
|
|
507
|
+
|
|
508
|
+
- [ ] `amend_targets` do **PO khai tường minh** — không suy từ mô tả mơ hồ
|
|
509
|
+
- [ ] Mỗi target đã phân giải được **UC sở hữu**; ID không phân giải được → đã DỪNG
|
|
510
|
+
- [ ] Bước 2 đã hỏi đủ 3 câu va chạm, và mọi ID phát sinh **đã được thêm** vào `amend_targets`
|
|
511
|
+
- [ ] **KHÔNG** đánh số lại ID nào · **KHÔNG** thêm ID mới · **KHÔNG** xoá row nào
|
|
512
|
+
- [ ] `--retire` giữ nguyên row + ID (chỉ đổi nội dung sang dạng khai tử)
|
|
513
|
+
- [ ] Guard sau-ghi PASS **cả hai chiều**: Bảo toàn **và** Giới hạn
|
|
514
|
+
- [ ] Altitude đúng tầng: cơ chế nằm ở BR/BL, AC chỉ outcome + ref
|
|
515
|
+
- [ ] `{changelog_scope}`: mỗi mệnh đề **mở đầu bằng UC sở hữu**; **không** BR/AC đứng một mình; **không** `[no-behavior]`
|
|
516
|
+
- [ ] `Status` đã reset về `draft`
|
|
517
|
+
- [ ] Không có banned term; 0 thuật ngữ kỹ thuật/UI trong text mới
|
|
518
|
+
- [ ] Report nêu **UC PHẢI làm lại** kèm lệnh, và **cấm tường minh** `--realign` cho chúng
|