@educa-corp/sdd-framework 0.6.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/gate-trace.js +25 -2
- package/bin/index.js +32 -5
- package/bin/lint-trace.js +41 -0
- package/bin/self-check.js +430 -3
- package/bin/trace-schema.json +418 -31
- package/core/FRAMEWORK_VERSION +1 -1
- package/{commands/extend-prd.md → core/commands/amend-prd.md} +206 -173
- package/core/commands/dev-run-test.md +48 -10
- package/core/commands/extend-prd.md +39 -12
- package/core/commands/generate-bdd.md +52 -10
- package/core/commands/generate-code.md +35 -2
- package/core/commands/generate-tech-docs.md +36 -4
- package/core/commands/map-testids.md +1 -1
- package/core/commands/qc-run-test.md +29 -3
- package/core/commands/refine-prd.md +13 -2
- package/core/commands/review-context.md +43 -8
- package/core/commands/sync.md +105 -1
- package/core/commands/validate-traces.md +289 -16
- package/core/rules/workflow.md +34 -0
- package/core/steps/context-loader.md +27 -6
- package/core/templates/feature.template +1 -1
- package/core/templates/project-context.yaml +3 -3
- package/core/templates/tech-design.template.md +2 -2
- package/docs/02-concepts/architecture.md +37 -1
- package/docs/02-concepts/overview.md +1 -1
- package/docs/02-concepts/pipeline-steps/02-specification.md +13 -7
- package/docs/02-concepts/pipeline-steps/07-dev-selftest.md +2 -0
- package/docs/02-concepts/pipeline-steps/08-qc-automation.md +1 -0
- package/docs/02-concepts/pipeline-steps/09-validate-traces.md +34 -3
- package/docs/02-concepts/pipeline-steps/10-feedback-loop.md +10 -1
- package/docs/02-concepts/traceability.md +187 -183
- package/docs/03-guides/architect.md +13 -4
- package/docs/03-guides/developer.md +1 -0
- package/docs/03-guides/product-owner.md +89 -72
- package/docs/03-guides/tester-qa.md +81 -81
- package/docs/04-reference/commands.md +148 -134
- package/docs/04-reference/trace-schema.md +45 -1
- package/docs/explain/02b-extend-prd.md +1 -1
- package/docs/explain/02c-amend-prd.md +152 -0
- package/docs/explain/06-generate-bdd.md +1 -1
- package/docs/explain/13-dev-run-test.md +15 -1
- package/docs/explain/19-qc-run-test.md +91 -87
- package/docs/explain/21-validate-traces.md +79 -75
- package/docs/explain/28-sync.md +25 -0
- package/docs/explain/README.md +136 -135
- package/package.json +1 -8
- package/commands/debug.md +0 -529
- package/commands/debug.tmpl +0 -260
- package/commands/define-product.md +0 -438
- package/commands/define-product.tmpl +0 -225
- package/commands/dev-gen-test.md +0 -700
- package/commands/dev-gen-test.tmpl +0 -490
- package/commands/dev-run-test.md +0 -435
- package/commands/dev-run-test.tmpl +0 -225
- package/commands/dev-smoke-test.md +0 -374
- package/commands/dev-smoke-test.tmpl +0 -217
- package/commands/extend-prd.tmpl +0 -273
- package/commands/fix-bug.md +0 -519
- package/commands/fix-bug.tmpl +0 -197
- package/commands/generate-architecture.md +0 -354
- package/commands/generate-architecture.tmpl +0 -197
- package/commands/generate-bdd.md +0 -923
- package/commands/generate-bdd.tmpl +0 -590
- package/commands/generate-code.md +0 -859
- package/commands/generate-code.tmpl +0 -649
- package/commands/generate-design-spec.md +0 -737
- package/commands/generate-design-spec.tmpl +0 -524
- package/commands/generate-prd.md +0 -722
- package/commands/generate-prd.tmpl +0 -226
- package/commands/generate-spec-manifest.md +0 -321
- package/commands/generate-spec-manifest.tmpl +0 -164
- package/commands/generate-tech-docs.md +0 -920
- package/commands/generate-tech-docs.tmpl +0 -273
- package/commands/learn.md +0 -399
- package/commands/learn.tmpl +0 -130
- package/commands/map-testids.md +0 -238
- package/commands/map-testids.tmpl +0 -81
- package/commands/propose-scenario.md +0 -359
- package/commands/propose-scenario.tmpl +0 -202
- package/commands/qc-analyze.md +0 -269
- package/commands/qc-analyze.tmpl +0 -112
- package/commands/qc-design-test.md +0 -226
- package/commands/qc-design-test.tmpl +0 -69
- package/commands/qc-plan.md +0 -206
- package/commands/qc-plan.tmpl +0 -49
- package/commands/qc-report.md +0 -217
- package/commands/qc-report.tmpl +0 -60
- package/commands/qc-review.md +0 -210
- package/commands/qc-review.tmpl +0 -53
- package/commands/qc-run-test.md +0 -326
- package/commands/qc-run-test.tmpl +0 -116
- package/commands/refine-prd.md +0 -653
- package/commands/refine-prd.tmpl +0 -281
- package/commands/report-bug.md +0 -305
- package/commands/report-bug.tmpl +0 -148
- package/commands/review-code.md +0 -415
- package/commands/review-code.tmpl +0 -146
- package/commands/review-context.md +0 -902
- package/commands/review-context.tmpl +0 -530
- package/commands/review-tech-docs.md +0 -561
- package/commands/review-tech-docs.tmpl +0 -404
- package/commands/setup-ai-first.md +0 -602
- package/commands/setup-ai-first.tmpl +0 -450
- package/commands/sync.md +0 -430
- package/commands/sync.tmpl +0 -429
- package/commands/update-framework.md +0 -203
- package/commands/update-framework.tmpl +0 -202
- package/commands/validate-traces.md +0 -1077
- package/commands/validate-traces.tmpl +0 -920
- package/hooks/data-guard.js +0 -232
- package/hooks/settings.json +0 -19
- 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 -99
- 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 -112
- package/steps/context-loader.md +0 -406
- package/steps/gate.md +0 -151
- package/steps/report-footer.md +0 -125
- 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 -70
- package/templates/architecture.template.md +0 -394
- package/templates/ci/trace-gate.yml +0 -146
- package/templates/design-spec.template.md +0 -217
- package/templates/feature.template +0 -123
- package/templates/hooks/pre-push +0 -61
- 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/rules/workflow.md
CHANGED
|
@@ -65,6 +65,40 @@ Ba mức, định nghĩa đầy đủ ở `steps/gate.md` Bước 3a — **đây
|
|
|
65
65
|
**Ngoại lệ có chủ ý:** `qc_owner`/`qc_blocked_by` (con trỏ tới bug — spec đổi không làm bug biến
|
|
66
66
|
mất) và `test_count`/`test_classes` (test vẫn tồn tại trên đĩa; số lượng không sai, chỉ nội dung
|
|
67
67
|
cũ → **cảnh báo**, không hạ số, để tỷ lệ coverage không nhảy loạn).
|
|
68
|
+
- **Sửa spec phải đi qua một lệnh.** Mọi drift detector so **nhãn version**, không so **nội dung**
|
|
69
|
+
(0 content hash trong toàn bộ codebase) — nên một PRD/tech-doc bị sửa tay mà không bump version là
|
|
70
|
+
điểm mù **tuyệt đối**: cả `/validate-traces`, `gate-trace`, và `require-fresh-audit` đều xanh, và
|
|
71
|
+
cả ba **đúng theo định nghĩa của chính chúng**. Bốn cửa chính: `/generate-prd` (mới) ·
|
|
72
|
+
`/extend-prd` (**thêm**) · **`/amend-prd`** (**đổi**) · `/refine-prd`/`/review-context --resume`
|
|
73
|
+
(áp finding). `/validate-traces` Step 3.9 canh cửa sau bằng cờ 🔴 `PRD_UNTRACKED_EDIT`
|
|
74
|
+
(`spec_edit_detection`: git diff **và** git status vs mốc `spec_baseline`).
|
|
75
|
+
*Đường ra cố ý **tự lành**, không có `--accept-edit`: bump version + ghi row changelog nêu UC là
|
|
76
|
+
hết cờ. Một cờ escape sẽ là một đường dán nhãn lên thay đổi chưa ai xem — đúng cái ba rào của
|
|
77
|
+
`--realign` tồn tại để chặn.*
|
|
78
|
+
- **Làm mất hiệu lực có MỆNH ĐỀ ĐỐI NGẪU: ai KHẲNG ĐỊNH một giá trị dương phải được phép khẳng
|
|
79
|
+
định.** Luật ngay trên nói *"ai làm giá trị hết đúng thì phải hạ nó"* — đúng, và được thực thi tốt.
|
|
80
|
+
Nhưng thiếu nửa này thì chuỗi thành **hạ xuống → dựng lại**: `/generate-bdd` hạ
|
|
81
|
+
`dev_selftest → not_run` khi spec đổi, rồi `/dev-run-test` (lệnh kế tiếp trong vòng lặp dev bình
|
|
82
|
+
thường) ghi lại `pass` kèm **ngày hôm nay** vì test cũ + code cũ vẫn xanh.
|
|
83
|
+
`pass` **không** mang nghĩa *"test đã chạy xanh"* — nó mang nghĩa *"scenario này đã được nghiệm thu
|
|
84
|
+
theo spec **hiện tại**"*. Trên row `DRIFT` nghĩa thứ nhất đúng và nghĩa thứ hai **sai**. Nên `status`
|
|
85
|
+
trực giao với **kết quả chạy**, **KHÔNG** trực giao với **quyền khẳng định**.
|
|
86
|
+
Contract: `bin/trace-schema.json` → `positive_assertion_guards`; `self-check` **R14** canh chủ cột
|
|
87
|
+
thực sự rẽ nhánh theo `status`, `lint-trace` **T12** bắt trạng thái ở sổ thật bất kể ai ghi.
|
|
88
|
+
**`fail` không bao giờ bị chặn** — đây là guard chống *báo cáo sai*, không phải guard *che tin xấu*.
|
|
89
|
+
- **Dòng changelog là contract máy đọc, không phải ghi chú cho người đọc.** PRD và tech-doc gộp
|
|
90
|
+
đều phủ nhiều UC nhưng chỉ có **một** nhãn version, nên `/validate-traces` Step 4/5 lọc 🟠 `*_DRIFT`
|
|
91
|
+
vs ⓘ `*_STALE_REF` **bằng chính dòng đó**. Grammar khai ở `bin/trace-schema.json` →
|
|
92
|
+
`changelog_row_contract`; `self-check` **R12** fail build nếu lệch. Ba luật:
|
|
93
|
+
**(1)** mỗi mệnh đề mở đầu bằng **đơn vị sở hữu** — `{UC-ID}:` hoặc `PRD-global:`/`doc-global:`;
|
|
94
|
+
**(2)** BR/AC **luôn đi kèm UC sở hữu** (`UC3: sửa BR8`), **không bao giờ đứng một mình** —
|
|
95
|
+
consumer khớp theo UC, nên `sửa BR8` trơ trọi làm UC3 bị xếp ⓘ trong khi BR8 vừa đổi hành vi, và
|
|
96
|
+
`--realign-prd-version` (chỉ chặn 🟠) sẽ dán nhãn version lại lên đó;
|
|
97
|
+
**(3)** hậu tố `[no-behavior]` **chỉ** cho thay đổi mà producer **chứng minh được** là không đổi
|
|
98
|
+
hành vi (`changelog_row_contract.neutral_checks`) — không dành cho người tự khai.
|
|
99
|
+
*Lưới an toàn "row mơ hồ → 🟠 cho MỌI UC" đúng khi **thiếu** thông tin, và sai khi producer **có**
|
|
100
|
+
thông tin mà không ghi: đó là G52 — `/review-context --fix` từng ghi cứng một dòng 0 scope trong
|
|
101
|
+
khi findings YAML của nó có `uc_id` bắt buộc cho từng finding.*
|
|
68
102
|
- **Mỗi audit flag phải quan sát được ở CẢ BA tầng.** Mọi giá trị trong
|
|
69
103
|
`vocabularies.audit_flags` bắt buộc có đủ: **(1)** một counter `{flag_lowercase}_count`
|
|
70
104
|
trong Step 7 + `summary` của `trace-report.json` · **(2)** một mảng trong `issues` ·
|
|
@@ -161,11 +161,25 @@ services:
|
|
|
161
161
|
|
|
162
162
|
*(Cả 2a/2b/2c: override `paths.specs_dir`/`paths.tech_docs_dir` per-service CHỈ khi `setup.spec_source` KHÔNG được đặt. Khi `spec_source` ĐƯỢC đặt, MỌI BDD/tech-doc là artifact liên team → để bước 4 route sang spec repo; KHÔNG pin per-service ở đây.)*
|
|
163
163
|
|
|
164
|
-
**3. Fallback
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
164
|
+
**3. Fallback** — **hai trạng thái khác nhau, đừng gộp** *(G51)*:
|
|
165
|
+
|
|
166
|
+
> `unrouted` = **chưa ai quyết** repo. Hợp lệ, bình thường ở feature đầu tiên của domain mới.
|
|
167
|
+
> `unresolved` = **config sai cấu trúc**. Là **bug** cần sửa file, không phải trạng thái chờ.
|
|
168
|
+
>
|
|
169
|
+
> Trước G51 cả hai dùng chung tên `unresolved` nên chịu chung hình phạt: `/generate-bdd` DỪNG HẲN.
|
|
170
|
+
> Nhưng PRD/BDD là artifact **nghiệp vụ** — PO biết `domain` và biết `platform`, **không** biết code
|
|
171
|
+
> sẽ nằm repo nào, và thường lúc đó chưa ai quyết. Cổng đặt sai phase.
|
|
172
|
+
|
|
173
|
+
**→ `unrouted`** (chưa có mapping — **không** phải lỗi):
|
|
174
|
+
- Không phát hiện được domain, hoặc domain **không khớp key nào** trong `services` → giữ path mặc định từ Bước 1, đặt `active_service = unrouted`.
|
|
175
|
+
- Domain khớp map-theo-platform (2b) nhưng thiếu sub-key cho `active_platform` → `active_service = unrouted`, ghi lý do rõ (không tự đoán platform).
|
|
176
|
+
- Entry là map-theo-prd_slug (2c) nhưng thiếu key cho `prd_slug` → `active_service = unrouted`, ghi lý do rõ (không tự đoán submodule).
|
|
177
|
+
|
|
178
|
+
**→ `unresolved`** (config **sai cấu trúc** — bug):
|
|
179
|
+
- Entry vừa có `path` vừa có `by_prd_slug`, hoặc `by_prd_slug` lồng nhau → `active_service = unresolved`, nêu đúng key sai để người dùng sửa `project-context.yaml`.
|
|
180
|
+
|
|
181
|
+
*Cả hai đều KHÔNG chặn việc nạp context. Lệnh nào chặn là quyết định của lệnh đó: `/generate-bdd`
|
|
182
|
+
đi tiếp với `unrouted` (Step 1.6) · `/generate-code` DỪNG ở cả hai (nó buộc phải biết ghi vào đâu).*
|
|
169
183
|
|
|
170
184
|
**4. Tự động override theo spec source** — nếu `setup.spec_source` được đặt VÀ path tương ứng chưa được set tường minh trong `paths:`:
|
|
171
185
|
- Override `paths.specs_dir` → `{spec_source}/specs` — **luôn khi `spec_source` được đặt.** Mọi spec artifact (PRD, BDD, tech-docs, design-spec) nằm dưới gốc spec thống nhất trong spec repo dùng chung theo bố cục feature-package: `{spec_source}/specs/{domain}/{prd-slug}/`. Mọi umbrella (FE/App/BE) đều đọc từ đây. *(`specs/` theo service chỉ khi không có `spec_source`.)*
|
|
@@ -209,6 +223,13 @@ Khi `active_service` đã được phân giải thành một path thật ở Bư
|
|
|
209
223
|
|
|
210
224
|
**4. Nếu không tìm thấy config của service** — giữ mặc định umbrella, vẫn set `service_root = {active_service}` (luôn cần mốc path kể cả khi không có config override).
|
|
211
225
|
|
|
226
|
+
> ⚠️ **`service_root` KHÔNG BAO GIỜ được là một chuỗi trạng thái** *(G51)*. Nếu `active_service` là
|
|
227
|
+
> `unrouted` / `unresolved` / `multi` / `—` thì đặt **`service_root = null`** và giữ path mặc định
|
|
228
|
+
> umbrella — **đừng** nội suy giá trị đó thành tên thư mục.
|
|
229
|
+
> Bản trước đặt `service_root = {active_service}` vô điều kiện, nên `/generate-code` (ghi file
|
|
230
|
+
> **tương đối với `service_root`**) sẽ ghi source vào một thư mục tên đúng chữ `unresolved/`.
|
|
231
|
+
> `service_root = null` là tín hiệu để `/generate-code` DỪNG thay vì ghi bừa.
|
|
232
|
+
|
|
212
233
|
---
|
|
213
234
|
|
|
214
235
|
## Bước 2 — [PROJECT-CONFIG] Nạp module stack profile (có điều kiện)
|
|
@@ -382,7 +403,7 @@ Dict : {loaded — N canonical terms, M banned terms | missing}
|
|
|
382
403
|
Entities : {loaded — EntityA, EntityB, EntityC | missing}
|
|
383
404
|
Lessons : {loaded — {n} active cho lệnh này ({tổng} tổng) | chưa có}
|
|
384
405
|
{⚠️ CHỈ IN khi tổng ≥ 40: "{tổng} guardrail đang hoạt động — /learn --review để rà"}
|
|
385
|
-
Platform : {active_platform: system | web | app | — nếu chưa xác định}
|
|
406
|
+
Platform : {active_platform: system | web | app | webview | … | — nếu chưa xác định}
|
|
386
407
|
Service : {active_service} ({active_service_module}) [← domain{/platform}{/prd_slug} nếu route qua by_prd_slug] | multi (map-theo-platform hoặc map-theo-prd_slug, chốt khi target đủ platform/prd_slug) | single-service
|
|
387
408
|
Svc Root : {service_root} — đã nạp conventions + trace_dir từ config service | —
|
|
388
409
|
Status : {FULL | PARTIAL — thiếu: CLAUDE.md / business-dict / core-entities | MINIMAL}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# @trace.revision: 1 ← field tĩnh; version theo dõi bằng @trace.bdd_version
|
|
5
5
|
# @trace.domain: <domain>
|
|
6
6
|
# @trace.platform: {active_platform — web | app | system} ← BẮT BUỘC mọi mode; phải khớp segment bdd/{platform}/ của path
|
|
7
|
-
# @trace.service: {
|
|
7
|
+
# @trace.service: {service của ĐÚNG platform file này — BẮT BUỘC mọi mode. Nguồn của cột TSV `service`; trace gộp không tách theo service nên đây là chỗ DUY NHẤT mang thông tin sở hữu ở cấp row. Bốn giá trị: {path} · "unrouted" (chưa ai quyết repo — HỢP LỆ, cờ 🟠, KHÔNG chặn) · "unresolved" (config sai cấu trúc — bug) · "—" (single-service). KHÔNG ghi "multi": file này đã có MỘT platform xác định nên service_candidates.{platform}.path đã biết — ghi path đó (G51)}
|
|
8
8
|
# @trace.module: {active_module trong umbrella mode; "unknown" trong spec repo mode}
|
|
9
9
|
# @trace.status: draft
|
|
10
10
|
# @trace.author: AI-generated
|
|
@@ -26,7 +26,7 @@ project:
|
|
|
26
26
|
paths:
|
|
27
27
|
# Feature-Package Layout:
|
|
28
28
|
# specs/{domain}/{prd-slug}/{TICKET-ID}-{prd-slug}.md — PRD document
|
|
29
|
-
# specs/{domain}/{prd-slug}/bdd/{platform}/ — BDD .feature ({platform} = web | app | system)
|
|
29
|
+
# specs/{domain}/{prd-slug}/bdd/{platform}/ — BDD .feature ({platform} = web | app | system | webview)
|
|
30
30
|
# specs/{domain}/{prd-slug}/tech-docs/ — Technical design (ONE merged doc per PRD: {TICKET-ID}-tech-design.md)
|
|
31
31
|
# specs/{domain}/{prd-slug}/design-spec/ — Design specs (FE/App only)
|
|
32
32
|
# specs/{domain}/{prd-slug}/changelog/ — PRD changelog overflow (created once history exceeds 5 versions)
|
|
@@ -97,7 +97,7 @@ paths:
|
|
|
97
97
|
# {spec_source}/specs so FE/App read the contract via the spec submodule.
|
|
98
98
|
tech_docs_dir: "specs"
|
|
99
99
|
|
|
100
|
-
# Design Specs (
|
|
100
|
+
# Design Specs (client platforms only — every platform except `system`: web, app, webview).
|
|
101
101
|
# In the feature-package layout, design-specs live at specs/{domain}/{prd-slug}/design-spec/.
|
|
102
102
|
# This variable is no longer needed as a separate path — derived from specs_dir.
|
|
103
103
|
# design_spec_dir: "specs/design-spec" ← removed; use specs_dir instead
|
|
@@ -163,7 +163,7 @@ domains:
|
|
|
163
163
|
# #
|
|
164
164
|
# # FORM B — PER-PLATFORM MAP (one business-domain implemented on several platforms /
|
|
165
165
|
# # submodules — a merged monorepo/workspace). No direct `path`; instead one
|
|
166
|
-
# # sub-key per platform (system | web | app). context-loader routes by the
|
|
166
|
+
# # sub-key per platform (system | web | app | webview). context-loader routes by the
|
|
167
167
|
# # target .feature's @trace.platform → picks {path, module} for that platform.
|
|
168
168
|
# # The PRD keeps a SINGLE business @trace.domain (do NOT invent onboarding-web).
|
|
169
169
|
# {{DOMAIN_2}}:
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
@trace.ucs: {TICKET-ID}-UC1, {TICKET-ID}-UC2{, …}
|
|
40
40
|
@trace.service: {service — từ header BDD @trace.service}
|
|
41
41
|
@trace.module: {module liên quan — vd dotnet, angular}
|
|
42
|
-
@trace.platforms: {system | web | app — tuỳ thư mục BDD nào tồn tại}
|
|
42
|
+
@trace.platforms: {system | web | app | webview | … — tuỳ thư mục BDD nào tồn tại}
|
|
43
43
|
@trace.bdd_versions: {MAP theo từng platform — số nhiều, KHÁC @trace.bdd_version (scalar) của .feature — vd system=1.5, web=1.9, app=1.7; chỉ platform có mặt. Mỗi feature mang bdd_version riêng; đừng gộp về một số.}
|
|
44
44
|
@trace.api_source: {existing | —}
|
|
45
45
|
@trace.revision: 1
|
|
@@ -412,7 +412,7 @@ sequenceDiagram
|
|
|
412
412
|
|
|
413
413
|
| UC | Feature | Platforms | Section phủ | Trạng thái |
|
|
414
414
|
|----|---------|-----------|------------------|--------|
|
|
415
|
-
| {TICKET-ID}-UC1 | {title} | {system, web, app} | §… | ✅ Covered |
|
|
415
|
+
| {TICKET-ID}-UC1 | {title} | {system, web, app, webview…} | §… | ✅ Covered |
|
|
416
416
|
|
|
417
417
|
### Độ phủ Scenario UC1
|
|
418
418
|
|
|
@@ -66,7 +66,7 @@ Spec-driven thành/bại phụ thuộc **~80%** vào việc context được n
|
|
|
66
66
|
bin/self-check.js (fail build) --init cài vào đây
|
|
67
67
|
```
|
|
68
68
|
|
|
69
|
-
**Vì sao slim (G45):** build inline `{{include:}}` vào **từng** file lệnh.
|
|
69
|
+
**Vì sao slim (G45):** build inline `{{include:}}` vào **từng** file lệnh. Đo lúc đó (32 lệnh), kết quả là
|
|
70
70
|
2069 KB mà chỉ 580 KB là nội dung riêng của chúng — **72% là vài step giống hệt nhau, chép 30 lần**.
|
|
71
71
|
`/generate-code` từng nặng 108 KB (≈27k token đọc **trước** khi làm gì), gần một nửa không nói gì về
|
|
72
72
|
việc sinh code. Cái giá thật không phải tiền: trên PRD nhiều UC nó làm tăng rủi ro **cạn context
|
|
@@ -86,6 +86,42 @@ Kết quả: `/generate-code` 108 KB → **69 KB**, `/refine-prd` 85 KB → **45
|
|
|
86
86
|
> **G50 gỡ hẳn legacy mode**, nên giờ mọi bản cài đều có `.agent/steps/` và nhánh build thứ hai
|
|
87
87
|
> biến mất. Hai nhánh build gần giống nhau là nợ chờ lệch.
|
|
88
88
|
|
|
89
|
+
### Tập publish — chỉ ship MỘT bản *(GAPS-v4 G59)*
|
|
90
|
+
|
|
91
|
+
`npm pack` chỉ mang **`bin/` · `core/` · `scripts/` · `docs/`**.
|
|
92
|
+
|
|
93
|
+
Trước G59, `files` có **10 mục**, và **7 trong 10** là bản sao của thứ đã có trong `core/` —
|
|
94
|
+
`commands/` (33/33 file `.md` **byte-identical** với `core/commands/`), cộng
|
|
95
|
+
`hooks/ modules/ rules/ skills/ steps/ templates/` (`diff -rq` không khác gì). Installer đọc
|
|
96
|
+
**chỉ `core/`** (`installCore(coreDir, agentDir, …)`), nên bản thứ hai không bao giờ được dùng.
|
|
97
|
+
|
|
98
|
+
| | Trước | Sau |
|
|
99
|
+
|---|---:|---:|
|
|
100
|
+
| Tarball nén | 1.2 MB | **710 kB** |
|
|
101
|
+
| Giải nén | 4.5 MB | **2.3 MB** |
|
|
102
|
+
| Số file | 395 | **215** |
|
|
103
|
+
|
|
104
|
+
**Nhưng cái đáng sửa hơn là một phép phân biệt bị vô hiệu.** `bin/index.js` dùng
|
|
105
|
+
`hasSources = exists(commands/generate-code.tmpl)` để biết *"đây là dev checkout hay bản cài từ
|
|
106
|
+
npm"*, và chú thích của nó viết thẳng: *"Chỉ nói trong DEV CHECKOUT. **Consumer không cần biết bước
|
|
107
|
+
này tồn tại**"*. Nhưng `commands/` được ship ⇒ `.tmpl` có mặt ⇒ phép thử **luôn đúng** ⇒ **mọi**
|
|
108
|
+
người dùng `npx` thấy `"Vừa sửa commands/*.tmpl ? Chạy npm run build trước"` — một câu họ không thể
|
|
109
|
+
làm gì với nó. *(Kiểm bằng cách `npm pack` rồi chạy tarball thật, không phải suy đoán.)*
|
|
110
|
+
|
|
111
|
+
Bốn nhánh sau khi sửa, `hasSources` đặt tên **một lần**:
|
|
112
|
+
|
|
113
|
+
| `corePrebuilt` | `hasSources` | Nghĩa | Làm gì |
|
|
114
|
+
|:---:|:---:|---|---|
|
|
115
|
+
| ✗ | ✓ | dev checkout, `core/` vắng/lệch | build từ nguồn |
|
|
116
|
+
| ✗ | ✗ | **bản cài npm bị thiếu/hỏng** | **lỗi rõ ràng + `exit 1`** — không cố build (G43: build ghi vào npx cache / global `node_modules`, có thể read-only, và hai `--init` song song sẽ đua nhau) |
|
|
117
|
+
| ✓ | ✓ | dev checkout, đã khớp version | in lời nhắc *"sửa `.tmpl` thì build lại"* |
|
|
118
|
+
| ✓ | ✗ | **bản cài npm, mọi thứ đúng** | **im lặng** ← đường của consumer |
|
|
119
|
+
|
|
120
|
+
Bất biến được `test/run.js` canh, viết theo **hình dạng** chứ không theo danh sách tên nên tự khớp
|
|
121
|
+
với dir thêm sau này: *không mục nào trong `files` được có bản mirror dưới `core/`*.
|
|
122
|
+
|
|
123
|
+
`scripts/` **phải giữ** — `bin/index.js` `require('../scripts/migrate-specs.js')` cho `--migrate-*`.
|
|
124
|
+
|
|
89
125
|
- Cơ chế `{{include:steps/...}}` → single source of truth ở `.tmpl` + `steps/`.
|
|
90
126
|
- **Không sửa tay** `commands/*.md` / `.agent/` — sửa `.tmpl`/`steps` rồi `node bin/build.js`. *(Quy ước + memory bảo vệ, không phải hook.)*
|
|
91
127
|
- **Sửa `steps/context-loader.md` hay `report-footer.md` giờ có hiệu lực NGAY** ở project đã cài — chúng được đọc lúc chạy, không còn phải build + publish + `/update-framework`.
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
```mermaid
|
|
12
12
|
flowchart TD
|
|
13
13
|
S["0 · Setup<br/>/setup-ai-first"] --> D["1 · Discovery<br/>/define-product"]
|
|
14
|
-
D --> SP["2 · Specification<br/>/generate-prd · /refine-prd · /review-context"]
|
|
14
|
+
D --> SP["2 · Specification<br/>/generate-prd · /extend-prd · /amend-prd<br/>/refine-prd · /review-context"]
|
|
15
15
|
SP --> DS["3 · Design-Spec<br/>(chỉ FE/App)"]
|
|
16
16
|
SP --> B["4 · BDD<br/>/generate-bdd · /review-context"]
|
|
17
17
|
DS --> B
|
|
@@ -3,15 +3,20 @@
|
|
|
3
3
|
# Bước 2 · Specification — Hình thành đặc tả (PRD)
|
|
4
4
|
|
|
5
5
|
> **Tóm tắt.** Biến khung intent thành **PRD** chuẩn nghiệp vụ, tinh chỉnh qua 3 lăng kính, rồi qua **gate chất lượng** để PO đóng dấu `approved`.
|
|
6
|
-
> **Commands:** `/generate-prd` (lần đầu) · `/extend-prd` (thêm vào PRD đã có) → `/refine-prd` → `/review-context`
|
|
6
|
+
> **Commands:** `/generate-prd` (lần đầu) · `/extend-prd` (**thêm** vào PRD đã có) · `/amend-prd` (**đổi** yêu cầu đã có) → `/refine-prd` → `/review-context`
|
|
7
7
|
|
|
8
|
-
> **Chọn lệnh nào —
|
|
8
|
+
> **Chọn lệnh nào — bốn nhánh, phân biệt bằng THAO TÁC GHI:**
|
|
9
9
|
>
|
|
10
|
-
> | Tình huống | Lệnh | Vì sao không dùng cái kia |
|
|
11
|
-
>
|
|
12
|
-
> | PRD **chưa tồn tại** | `/generate-prd` | — |
|
|
13
|
-
> | PRD đã có, **
|
|
14
|
-
> | PRD đã có, **
|
|
10
|
+
> | Tình huống | Lệnh | Ghi kiểu gì | Vì sao không dùng cái kia |
|
|
11
|
+
> |---|---|---|---|
|
|
12
|
+
> | PRD **chưa tồn tại** | `/generate-prd` | **Write** cả file | — |
|
|
13
|
+
> | PRD đã có, **THÊM** UC/AC/BR mới | **`/extend-prd`** | Edit **add-only** — output là **superset chặt** | `/generate-prd` **từ chối chạy** trên file đã có |
|
|
14
|
+
> | PRD đã có, **ĐỔI** một yêu cầu đang đúng cú pháp | **`/amend-prd`** | Edit **tại chỗ** — output **KHÔNG** phải superset | `/extend-prd` chỉ add-only; `/refine-prd` chỉ áp finding của chính nó |
|
|
15
|
+
> | PRD đã có, sửa **vấn đề review đã soi ra** | `/refine-prd` → Review Board → `--resume` | Edit trong phạm vi finding | `/refine-prd` **không thêm/đổi được** theo ý định mới — nó tự cấm đụng section ngoài findings |
|
|
16
|
+
>
|
|
17
|
+
> **Xoá hẳn một BR/AC → không có lệnh, và có chủ ý:** xoá row làm `@trace.business_rules` trong `.feature` trỏ vào ID không còn ⇒ `TRACE_ORPHAN` 🔴. Dùng `/amend-prd --retire {ID}` — khai tử **tại chỗ**, giữ nguyên row + ID.
|
|
18
|
+
>
|
|
19
|
+
> ⚠️ **Sửa tay file `.md` là điểm mù (GAPS-v4 G54).** Mọi drift detector so **nhãn version**, không so nội dung (0 content hash trong codebase) — sửa mà không bump version ⇒ **0 cờ**. `/validate-traces` Step 3.9 canh cửa sau bằng cờ 🔴 `PRD_UNTRACKED_EDIT`.
|
|
15
20
|
>
|
|
16
21
|
> **`/generate-prd` dừng hẳn (không hỏi Y/N) nếu file đã tồn tại.** Ghi đè sẽ mất `# Change Log` + rollover, Version/Status thật, và **đánh số lại BR từ đầu** — cái cuối lan **ra ngoài file**, phá mọi `@trace.business_rules` trong `bdd/` đã sinh. Ba mất mát đều không hoàn tác được từ trong lệnh, nên không đặt sau một phím bấm.
|
|
17
22
|
|
|
@@ -41,6 +46,7 @@ PRD là **hợp đồng nghiệp vụ** giữa PO ↔ Dev ↔ AI. Đây là **c
|
|
|
41
46
|
|------|---------|---------|
|
|
42
47
|
| `/generate-prd` | **Sinh** PRD draft từ product-definition. Từ chối chạy nếu PRD đã tồn tại | PRD `Status: draft` |
|
|
43
48
|
| `/extend-prd` | **Thêm** UC/AC/BR vào PRD đã duyệt — đánh số **nối tiếp**, ghi **add-only** + guard sau-ghi, drain `feedback/prd-change-requests/` | PRD v+1, `Status → draft` |
|
|
49
|
+
| `/amend-prd` | **Đổi tại chỗ** một AC/BR/UC đã duyệt — PO khai tường minh `amend_targets`, kiểm va chạm, guard sau-ghi **HAI CHIỀU** (Bảo toàn + Giới hạn). `--retire {ID}` khai tử tại chỗ | PRD v+1, `Status → draft` |
|
|
44
50
|
| `/refine-prd` | **Tinh chỉnh** qua 3 lăng kính DEV/SA/PO (fan-out per-UC) | Findings để PO accept/reject |
|
|
45
51
|
| `/review-context` | **Gate chất lượng** — findings P0–P5, phải sạch critical | PO đặt `Status: approved` |
|
|
46
52
|
|
|
@@ -24,6 +24,8 @@ Trước khi đẩy sang QC chính thức, Dev cần một vòng **kiểm nhanh
|
|
|
24
24
|
- Cho phép **thử tại chỗ** trên service/app đang chạy (`/dev-smoke-test`).
|
|
25
25
|
|
|
26
26
|
> **`dev_selftest` ≠ `qc_status`.** Hai trục **độc lập**: dev smoke (nhanh, tự kiểm) vs QC chính thức (Playwright, evidence). Không lấn quyền nhau.
|
|
27
|
+
>
|
|
28
|
+
> ⚠️ **Nhưng "độc lập" chỉ đúng với `status` về KẾT QUẢ CHẠY, không đúng về QUYỀN KHẲNG ĐỊNH** *(GAPS-v4 G55)*. `pass` mang nghĩa *"scenario này đã được nghiệm thu theo spec **hiện tại**"* — nên trên row `DRIFT`/`ORPHANED`, `/dev-run-test` và `/qc-run-test` **không được** ghi `pass`; chúng hạ về `not_run`. `fail`/`skip` thì ghi bình thường. `lint-trace` **T12** bắt trạng thái `DRIFT + pass` ở sổ thật, bất kể ai ghi ra.
|
|
27
29
|
|
|
28
30
|
---
|
|
29
31
|
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
|
|
22
22
|
- Phân rã yêu cầu thành test case bám scenario, phát hiện **gap tài liệu**.
|
|
23
23
|
- Chạy test thật, ghi **`qc_status` chính thức** + **evidence**.
|
|
24
|
+
⚠️ Nhưng `/qc-run-test` **đọc cột `status` trước khi ghi `pass`** *(GAPS-v4 G55)*: row `DRIFT`/`ORPHANED` + test xanh → hạ về `not_run`, và **không** đóng bug nào ở lần chạy đó. `fail`/`skip` ghi bình thường.
|
|
24
25
|
- Phân loại FAIL: **script-bug** (sửa script) vs **product-gap** (giữ FAIL + evidence, **không bao giờ fake-pass**).
|
|
25
26
|
- Đẩy **product-gap** ngược về PO/Dev.
|
|
26
27
|
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
# Bước 9 · Validate Traces — Ma trận độ phủ (Coverage Matrix)
|
|
4
4
|
|
|
5
|
-
> **Tóm tắt.** Check độ phủ giữa **spec ↔ code ↔ test** — 2 chiều quét, **6 tầng drift**, 4 cờ 🔴 chặn PR, 2 cờ ⓘ. Chỉ ra chỗ chưa phủ — mặc định **không sửa gì**.
|
|
5
|
+
> **Tóm tắt.** Check độ phủ giữa **spec ↔ code ↔ test** — 2 chiều quét, **6 tầng drift**, 4 cờ 🔴 chặn PR, 1 cờ 🔴 không-chặn (`PRD_UNTRACKED_EDIT`), 2 cờ ⓘ. Chỉ ra chỗ chưa phủ — mặc định **không sửa gì**.
|
|
6
|
+
> **Có phạm vi:** `--domain {d}` · `--prd {TICKET-ID}` · `--uc {UC-ID}`; không cờ nào = toàn bộ.
|
|
6
7
|
> **Command:** `/validate-traces` · `--realign-prd-version {UC-ID}` · `--realign-techdoc-revision {UC-ID}`
|
|
7
8
|
>
|
|
8
9
|
> *Lệnh **read-only** ở chế độ thường. Hai flag `--realign-*` là ngoại lệ có kiểm soát: chúng sửa **đúng dòng `@trace.*`** trong code, không đụng logic — xem [Realign](#realign--đường-ra-cho-cờ-ⓘ).*
|
|
@@ -41,7 +42,7 @@ Traceability chỉ có giá trị khi **kiểm được**. Bước này cho mộ
|
|
|
41
42
|
| Ma trận coverage spec ↔ code ↔ test | Trạng thái từng SC + `code_coverage` tổng |
|
|
42
43
|
| `{trace_dir}/trace-report.json` | Bản máy đọc cho **panel VS Code** ("Spec Driven Docs Tools") — bị **ghi đè** mỗi lần chạy |
|
|
43
44
|
| `{trace_dir}/trace-history.jsonl` | **Nhật ký append-only** — mỗi lần chạy ghi thêm 1 dòng *delta*. Đây là **dữ liệu**, không phải mirror: **phải commit**, mất là mất vĩnh viễn |
|
|
44
|
-
| Cờ audit | 6 cờ drift + 4 cờ 🔴 chặn PR + 2 cờ ⓘ (bảng dưới) |
|
|
45
|
+
| Cờ audit | 6 cờ drift + 4 cờ 🔴 chặn PR + `PRD_UNTRACKED_EDIT` 🔴 (không chặn) + 2 cờ ⓘ (bảng dưới) |
|
|
45
46
|
| Hàng đợi | Đếm PRD change request còn `Open` kèm **số ngày chờ** (Step 7b) |
|
|
46
47
|
|
|
47
48
|
---
|
|
@@ -68,6 +69,25 @@ Traceability chỉ có giá trị khi **kiểm được**. Bước này cho mộ
|
|
|
68
69
|
|
|
69
70
|
## Framework xử lý thế nào (Mechanics)
|
|
70
71
|
|
|
72
|
+
### Phạm vi audit — `--domain` / `--prd` / `--uc`
|
|
73
|
+
|
|
74
|
+
Đây là **lệnh đắt nhất** trong framework: ~24k token chỉ dẫn + ~9k `context-loader`, rồi đọc **mọi** PRD · `.feature` · tech-doc · design-spec · file source có tag · `.tsv`. Chi phí tăng **tuyến tính theo cả repo**, không theo phần việc đang làm.
|
|
75
|
+
|
|
76
|
+
| Cờ | `scope.kind` | Phạm vi |
|
|
77
|
+
|---|---|---|
|
|
78
|
+
| *(không có)* | `all` | Toàn bộ |
|
|
79
|
+
| `--domain {d}` | `domain` | Một domain |
|
|
80
|
+
| `--prd {TICKET-ID}` | `prd` | Một feature-package |
|
|
81
|
+
| `--uc {UC-ID}` | `uc` | Một UC — **mọi platform của nó** |
|
|
82
|
+
|
|
83
|
+
**`/sync` Step 1e nói cho bạn biết scope là gì**: nó liệt kê PRD nào vừa đổi *(so với lần pull)* và PRD nào đã đổi *kể từ lần audit gần nhất* — con số thứ hai tích luỹ đúng qua nhiều lần pull. Hai lệnh khớp nhau thành một vòng: `/sync` chỉ chỗ → audit scoped rẻ → sửa → audit **toàn bộ** một lần trước khi tạo PR.
|
|
84
|
+
|
|
85
|
+
⚠️ **Biên bản có scope KHÔNG BAO GIỜ được coi là đầy đủ.** Report mang field `scope`, và `gate-trace` **G2 fail** nếu `scope.kind !== "all"` — **không ngoại lệ**, không đếm xem trên đĩa có bao nhiêu domain. Muốn tạo PR thì phải có một lần audit **toàn bộ** đã commit.
|
|
86
|
+
|
|
87
|
+
> **Vì sao điều kiện phải tuyệt đối (GAPS-v4 G57):** bản cũ hỏi *"còn domain **nào khác** không"*, nên trong repo **một domain** thì không còn domain nào khác ⇒ **không fail** ⇒ một biên bản hẹp-theo-PRD được nhận là *"toàn bộ"*. Thêm cờ scope mà không siết G2 là **tự tay mở** đúng cái *"cấp giấy xanh cho thứ chưa ai xem"* mà chú thích của gate cảnh báo.
|
|
88
|
+
|
|
89
|
+
**Ba chỗ cố ý KHÔNG âm thầm:** `--prd`/`--uc` không phân giải được → **DỪNG** *(không rơi về `all` — chạy toàn bộ khi người ta xin một phần là đốt 30 phút; và không audit rỗng rồi báo "sạch" trên 0 row)* · nhiều cờ scope cùng lúc → **DỪNG** *(không tự ưu tiên)* · **lint vẫn chạy toàn bộ** dù audit có scope *(sổ hỏng ở domain khác vẫn là sổ hỏng, và lint rẻ vì không cần LLM)*.
|
|
90
|
+
|
|
71
91
|
### Phân loại `status` từng SC (thứ tự ưu tiên, rule sớm thắng)
|
|
72
92
|
|
|
73
93
|
| # | Trạng thái | Điều kiện |
|
|
@@ -97,6 +117,7 @@ Chiều ngược là cần thiết vì gen lại BDD có thể làm một SC bi
|
|
|
97
117
|
|
|
98
118
|
| Cờ | So cái gì | Step |
|
|
99
119
|
|---|---|:---:|
|
|
120
|
+
| `PRD_UNTRACKED_EDIT` 🔴 | **Nội dung PRD đổi mà nhãn `Version` KHÔNG đổi** — `git diff` **và** `git status` so với mốc `spec_baseline` của lần audit trước. Có người sửa ngoài đường chính thức | **3.9** |
|
|
100
121
|
| `PRD_DRIFT` | Version PRD vs cột `prd_version` vs `@trace.prd_version` trong code — **và** changelog **có** nêu UC này | 4 |
|
|
101
122
|
| `TECHDOC_DRIFT` · `FE_TECHDOC_DRIFT` | `@trace.revision` tech-doc vs cột đã lưu — **và** changelog nêu UC này | 5 |
|
|
102
123
|
| `BDD_DRIFT` | `@trace.bdd_version` trong code vs `.feature` hiện tại | 5c |
|
|
@@ -133,7 +154,17 @@ Chiều ngược là cần thiết vì gen lại BDD có thể làm một SC bi
|
|
|
133
154
|
|
|
134
155
|
Tệ hơn: **làm theo hướng dẫn cũng không tắt được.** `/generate-bdd` sạch được cột TSV, nhưng tag trong code chỉ `/generate-code` ghi — mà nó thấy row đang `OK` là **skip**. Vòng lặp đóng, và lối ra duy nhất là ép sinh lại code cho hàng loạt UC không hề thay đổi.
|
|
135
156
|
|
|
136
|
-
Bộ lọc đọc
|
|
157
|
+
Bộ lọc đọc **`{changelog_scope}` của row changelog** — một **contract máy đọc** (`bin/trace-schema.json` → `changelog_row_contract`) với **bốn** producer: `/refine-prd` Phase 3 · `/extend-prd` Bước 6 · `/amend-prd` Bước 5 · `/review-context` Fix/Resume Phase 3. `self-check` **R12** fail build nếu producer nào không có dòng template mang token.
|
|
158
|
+
|
|
159
|
+
Ba bước dựng tập bị ảnh hưởng:
|
|
160
|
+
|
|
161
|
+
1. **Tách mệnh đề** — ngăn bằng `;`, mỗi mệnh đề mở đầu bằng đơn vị sở hữu (`{UC-ID}:` hoặc `PRD-global:`).
|
|
162
|
+
2. **Chuẩn hoá về UC** — phép phân giải **`BR/AC → UC sở hữu`**: `BR{n}` → UC có BR đó trong bảng Business Rule (PRD §3) · `AC{n}` → UC có AC đó ở dòng `**AC liên quan:**`. **Không bỏ bước này**: phép thử là *"**UC** này có trong tập?"*, nên một row chỉ nêu `sửa BR8` làm UC sở hữu BR8 rơi vào ⓘ trong khi nội dung của nó vừa đổi — và ⓘ **mở cửa** cho `--realign-prd-version` dán nhãn lại (GAPS-v4 G53).
|
|
163
|
+
3. **Phân loại** *(first-match-wins)* — **row mơ hồ xét TRƯỚC**: nó là điều kiện **cấp row**, nên xét sau thì một UC có thể được xếp ⓘ trước khi ta biết là không suy đoán được gì.
|
|
164
|
+
|
|
165
|
+
**Row nào mơ hồ → 🟠 cho MỌI UC** — lưới an toàn: mất tính năng *lọc*, không mất tính năng *cảnh báo*. ⚠️ Nhưng nó **không phải cái cớ để producer ghi bừa**: đúng khi **thiếu** thông tin, sai khi producer **có** thông tin mà không ghi.
|
|
166
|
+
|
|
167
|
+
Mệnh đề mang hậu tố **`[no-behavior]`** → UC nêu trong đó ở lại ⓘ. Chỉ producer **chứng minh được** tính trung tính mới được dùng (`changelog_row_contract.neutral_checks`) — hiện chỉ `/review-context --fix` cho fix thuần cấu trúc (P4).
|
|
137
168
|
|
|
138
169
|
> Đây là bài mà framework **đã giải đúng ở cấp scenario**: `sc_version` chỉ bump khi thân scenario thực sự đổi, vì *"bump vô cớ sẽ tạo DRIFT giả, làm cờ mất giá trị"*. Hai cờ ⓘ là bản tương ứng ở cấp tài liệu.
|
|
139
170
|
|
|
@@ -37,7 +37,7 @@ Framework là pipeline **một chiều** — nhưng vẫn cần đường **ph
|
|
|
37
37
|
| `/learn` | Tất cả | Guardrail lesson | `project-lessons.md` (qua step `capture-lesson`) |
|
|
38
38
|
| `/fix-bug` | Dev | Sửa lỗi có root-cause + regression test | Code + `@trace.fixes/root_cause/regression` |
|
|
39
39
|
| `/extend-prd` | PO | **Drain** PRD change request → UC/AC/BR mới trong PRD | PRD v+1 · request → `archived/` |
|
|
40
|
-
| `/sync` | Lead (umbrella) | Pull + submodule + **nổi feedback** + làm mới Living Docs | Chạy hằng ngày |
|
|
40
|
+
| `/sync` | Lead (umbrella) | Pull + submodule + **nổi feedback** + **nổi spec delta** (Step 1e) + làm mới Living Docs | Chạy hằng ngày |
|
|
41
41
|
|
|
42
42
|
### Ba hàng đợi — mỗi cái phải có người lấy ra
|
|
43
43
|
|
|
@@ -48,6 +48,15 @@ Framework là pipeline **một chiều** — nhưng vẫn cần đường **ph
|
|
|
48
48
|
| `prd-change-requests/` | `/propose-scenario` B | **`/extend-prd`** | `/validate-traces` Step 7b — đếm `Status: Open` kèm **số ngày chờ** |
|
|
49
49
|
|
|
50
50
|
> **Vì sao cột "ai nhắc lại" quan trọng.** `/sync` chỉ hiện những gì về **trong đúng lần pull đó** (`git diff old..new`) — nó là **chuông cửa, không phải tồn kho**. Bỏ lỡ một lần là mất khỏi màn hình vĩnh viễn. Hai hàng đợi đầu không sao vì có lệnh **quét lại thư mục mỗi lần chạy**; riêng `prd-change-requests/` thì không — nên `/validate-traces` phải nhắc thay.
|
|
51
|
+
|
|
52
|
+
> **Cùng nguyên tắc đó áp cho SPEC — và đó là Step 1e (GAPS-v4 G56).** Trước đó `/sync` diff đúng ba đường dẫn `feedback/*` và **bỏ qua `specs/`**, tức hỏi *"có góp ý gì mới"* rồi bỏ qua chính tài liệu mà mọi lệnh downstream đọc. Giờ nó trả lời **hai** câu bằng **hai** mốc:
|
|
53
|
+
>
|
|
54
|
+
> | | Mốc | Trả lời | Vấn đề nếu chỉ có nó |
|
|
55
|
+
> |---|---|---|---|
|
|
56
|
+
> | **1e-A** | `{old_sha}..{new_sha}` | *"đổi gì kể từ lần **PULL**"* | **chuông cửa** — reset mỗi lần pull; pull 4 ngày liền không audit thì ngày thứ 5 chỉ thấy delta của **một** ngày |
|
|
57
|
+
> | **1e-B** | `spec_baseline.sha_at_audit` | *"đổi gì kể từ lần **AUDIT**"* | **tồn kho** — tích luỹ đúng |
|
|
58
|
+
>
|
|
59
|
+
> 1e-B đọc mốc mà `/validate-traces` Step 6b ghi (cùng khối dùng cho cờ `PRD_UNTRACKED_EDIT`). `/sync` **chỉ đọc, không bao giờ ghi** — nếu nó cũng ghi thì mốc audit trượt theo mỗi lần pull, tức 1e-B thoái hoá thành 1e-A. Và dòng `Next` giờ **rẽ nhánh theo dữ liệu**, không còn in một hằng số.
|
|
51
60
|
>
|
|
52
61
|
> Trước v0.4.3, hàng đợi thứ ba **không có người lấy ra**: có producer, có storage, có commit, có mặt trong `/sync` — nhưng 0 consumer, và **không gì báo**. Yêu cầu nghiệp vụ thật do tester phát hiện từ sản phẩm chạy thật rơi vào im lặng hoàn toàn. Từ v0.4.3, cả ba hàng đợi được khai vào `bin/trace-schema.json` §`queues` nên **self-check chặn build** nếu một hàng đợi mất consumer.
|
|
53
62
|
|