@educa-corp/sdd-framework 0.9.5 → 0.9.6
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 +11 -1
- package/bin/lint-trace.js +397 -28
- package/bin/self-check.js +183 -12
- package/bin/trace-schema.json +2656 -1981
- package/core/FRAMEWORK_VERSION +1 -1
- package/core/commands/dev-gen-test.md +62 -0
- package/core/commands/generate-code.md +1 -1
- package/core/commands/generate-tech-docs.md +3 -3
- package/core/commands/map-testids.md +88 -11
- package/core/commands/qc-analyze.md +509 -425
- package/core/commands/qc-design-test.md +475 -247
- package/core/commands/qc-plan.md +134 -93
- package/core/commands/qc-review.md +216 -131
- package/core/commands/qc-run-test.md +346 -231
- package/core/commands/validate-traces.md +17 -2
- package/core/rules/workflow.md +40 -0
- package/core/skills/qc/qa-analyst/DOC_GAP.template.md +9 -1
- package/core/skills/qc/qa-designer/shared/duplicate-check-procedure.md +33 -5
- package/core/skills/qc/qa-designer/shared/tc-metadata-format.md +24 -0
- package/core/skills/qc/qa-planner/test-plan.md +7 -0
- package/core/skills/qc/qa-runner/functional/gui-feature.md +1 -1
- package/core/skills/qc/qa-runner/functional/gui-screen.md +1 -1
- package/core/steps/qc-scope.md +67 -11
- package/core/steps/qc-stamp.md +142 -0
- package/core/steps/report-footer.md +13 -5
- package/core/templates/tech-design.template.md +3 -3
- package/docs/01-getting-started/quickstart.md +4 -3
- package/docs/02-concepts/architecture.md +14 -0
- package/docs/02-concepts/glossary.md +8 -0
- package/docs/02-concepts/overview.md +3 -2
- package/docs/02-concepts/pipeline-steps/04-bdd.md +1 -1
- package/docs/02-concepts/pipeline-steps/05-tech-docs.md +21 -5
- package/docs/02-concepts/pipeline-steps/06-code.md +12 -2
- package/docs/02-concepts/pipeline-steps/08-qc-automation.md +60 -12
- package/docs/02-concepts/pipeline-steps/README.md +4 -3
- package/docs/02-concepts/traceability.md +2 -2
- package/docs/03-guides/architect.md +2 -2
- package/docs/03-guides/developer.md +5 -2
- package/docs/03-guides/tester-qa.md +17 -5
- package/docs/04-reference/commands.md +6 -3
- package/docs/04-reference/trace-schema.md +1 -1
- package/docs/explain/07-generate-tech-docs.md +5 -3
- package/docs/explain/08-review-tech-docs.md +15 -3
- package/docs/explain/09-generate-code.md +30 -4
- package/docs/explain/10-review-code.md +1 -1
- package/docs/explain/11-map-testids.md +72 -70
- package/docs/explain/12-dev-gen-test.md +1 -1
- package/docs/explain/15-qc-analyze.md +14 -2
- package/docs/explain/16-qc-plan.md +5 -1
- package/docs/explain/17-qc-design-test.md +26 -3
- package/docs/explain/18-qc-review.md +6 -2
- package/docs/explain/19-qc-run-test.md +29 -6
- package/docs/explain/20-qc-report.md +5 -2
- package/docs/explain/README.md +4 -1
- package/package.json +1 -1
package/core/FRAMEWORK_VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.9.
|
|
1
|
+
0.9.6
|
|
@@ -7,6 +7,11 @@
|
|
|
7
7
|
> **dev self-test** để QC thấy dev đã tự chạy check của mình.
|
|
8
8
|
|
|
9
9
|
## Gate
|
|
10
|
+
|
|
11
|
+
*Checkpoint: **chặn CỨNG** — ghi đè file test đã có → XOÁ bản sửa tay của dev (mock, fixture, expectation đã chỉnh) mà chính `/dev-run-test` bảo họ làm. `--yes` KHÔNG bỏ qua được (gate Bước 3a).*
|
|
12
|
+
|
|
13
|
+
*Mức cứng chỉ áp khi file test **đã tồn tại**. Lần sinh đầu đi thẳng. Xem §Chạy lại.*
|
|
14
|
+
|
|
10
15
|
# Gate — Quy trình vào chuẩn cho mọi lệnh
|
|
11
16
|
|
|
12
17
|
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ó.
|
|
@@ -684,6 +689,63 @@ bên trong từng sub-agent.
|
|
|
684
689
|
|
|
685
690
|
---
|
|
686
691
|
|
|
692
|
+
## Output — lệnh này ghi những gì, ở đâu
|
|
693
|
+
|
|
694
|
+
| Ghi gì | Người sửa tay? |
|
|
695
|
+
|---|:---:|
|
|
696
|
+
| File **unit / integration / E2E test** theo layout của `{active_module}` | ✅ **có** — xem §Chạy lại |
|
|
697
|
+
| Sổ trace: `test_count` · `test_classes` · `dev_selftest` | ❌ lệnh ghi |
|
|
698
|
+
|
|
699
|
+
> **Vì sao mục này tồn tại** *(G84)*. Trước đó §Output chỉ khai `Trace: …tsv updated` — **không
|
|
700
|
+
> khai file test nó ghi ra**. Một lệnh không khai mình ghi gì thì không ai nghĩ tới việc **bảo vệ
|
|
701
|
+
> thứ nó ghi**. Đúng lỗi gốc của G77 ở lane QC. Cột *"người sửa tay?"* là câu hỏi mà
|
|
702
|
+
> `bin/trace-schema.json` → `artifact_writers` ép mọi lệnh trả lời.
|
|
703
|
+
|
|
704
|
+
## Chạy lại — file test đã tồn tại *(GIỮ phần đã có, sinh phần THIẾU)*
|
|
705
|
+
|
|
706
|
+
**Dev SỬA TAY chính các file này.** `/dev-run-test` nói thẳng:
|
|
707
|
+
|
|
708
|
+
> `:260` — *"Test fail → `/fix-bug {TICKET_ID}` (bug thật) hoặc **fix test** (sai expectation)"*
|
|
709
|
+
> `:137` — *"`TimeoutError` | Test gọi LLM endpoint live | **Thêm mock; kiểm tra test fixture**"*
|
|
710
|
+
|
|
711
|
+
Nên chuỗi bình thường là **sinh → chạy → đỏ → dev sửa tay → chạy lại**, và lần sinh sau **không được**
|
|
712
|
+
là lần xoá.
|
|
713
|
+
|
|
714
|
+
| Tình huống | Xử lý |
|
|
715
|
+
|---|---|
|
|
716
|
+
| File test đã có, `.feature` **không đổi** | **Không sinh lại.** Không hỏi gì — ca thường nhất |
|
|
717
|
+
| `.feature` có SC **mới** | Sinh **chỉ** test cho SC mới; giữ nguyên file/class đã có |
|
|
718
|
+
| File test có **thay đổi chưa commit** | **DỪNG** — xem dưới |
|
|
719
|
+
|
|
720
|
+
**Nhận diện "đã sửa tay" bằng `git status` / `git diff`** trên các đường dẫn ở §Output. Không cần ai
|
|
721
|
+
đánh dấu gì, và nó bắt được **mọi** lần sửa — kể cả lần người sửa quên đánh dấu.
|
|
722
|
+
|
|
723
|
+
```
|
|
724
|
+
❌ {n} file test có thay đổi chưa commit — có thể là bản sửa tay của bạn
|
|
725
|
+
(mock, fixture, expectation đã chỉnh). Sinh lại sẽ XOÁ chúng.
|
|
726
|
+
Files: {danh sách}
|
|
727
|
+
Cách đúng: commit bản sửa trước, rồi chạy lại.
|
|
728
|
+
Cố ý bỏ hết và sinh từ trắng: thêm --force
|
|
729
|
+
```
|
|
730
|
+
|
|
731
|
+
**KHÔNG đoán.** Thấy thay đổi chưa commit thì lệnh **không tự phân biệt** *"dev vừa sửa"* với *"lần
|
|
732
|
+
sinh trước chưa commit"* — hai ca đó nhìn giống hệt nhau trên `git status`. **Dừng oan một lần rẻ
|
|
733
|
+
hơn xoá nhầm một lần.**
|
|
734
|
+
|
|
735
|
+
> **Vì sao mặc định là "sinh phần thiếu" chứ không phải "đừng sinh".** `/qc-run-test` (G77) có vòng
|
|
736
|
+
> đời **chạy nhiều / sinh ít** nên mặc định của nó là *"CHẠY, đừng sinh lại"*. Lệnh này **chỉ sinh**,
|
|
737
|
+
> không chạy gì — copy nguyên mặc định đó sang là **copy nhầm ngữ cảnh**. *Cùng khuôn không có nghĩa
|
|
738
|
+
> là cùng thuốc.*
|
|
739
|
+
>
|
|
740
|
+
> **Vì sao ca "không đổi gì" phải HOÀN TOÀN im lặng.** Sinh lại test là việc làm mỗi lần spec đổi.
|
|
741
|
+
> Bản vá nào làm nó hỏi mỗi lần thì người dùng sẽ thêm `--force` vào alias — và lúc đó mất sạch lớp
|
|
742
|
+
> bảo vệ này.
|
|
743
|
+
|
|
744
|
+
Có `--force` → report **bắt buộc** khai:
|
|
745
|
+
```
|
|
746
|
+
⚠️ --force: sinh lại từ trắng — đã xoá {n} file test có thay đổi chưa commit: {danh sách}
|
|
747
|
+
```
|
|
748
|
+
|
|
687
749
|
## Output
|
|
688
750
|
|
|
689
751
|
**Đọc `.agent/steps/report-footer.md`** và áp đúng khuôn footer trong đó (Status Badge ·
|
|
@@ -657,7 +657,7 @@ DTOs → Entity/Model → Repository → Service interface → Service impl →
|
|
|
657
657
|
|
|
658
658
|
Mỗi element **có action** (button, input, link, select, toggle, form-submit) PHẢI mang một **test-id ổn định** để QC định vị trực tiếp (không scan runtime):
|
|
659
659
|
|
|
660
|
-
1. **Nguồn id — bảng §4.5.6 là HỢP ĐỒNG, không phải gợi ý.** Đọc **§4.5.6 Test Selectors** cho platform này ở tech-doc gộp `{paths.tech_docs_dir}/{domain}/{prd-slug}/tech-docs/{TICKET-ID}-tech-design.md`, lọc theo cột "
|
|
660
|
+
1. **Nguồn id — bảng §4.5.6 là HỢP ĐỒNG, không phải gợi ý.** Đọc **§4.5.6 Test Selectors** cho platform này ở tech-doc gộp `{paths.tech_docs_dir}/{domain}/{prd-slug}/tech-docs/{TICKET-ID}-tech-design.md`, lọc theo cột "Serves SC" khớp SC của UC này, rồi lấy id **nguyên văn**. Bảng do `/map-testids` ghi ở phase Tech Design — **trước** lệnh này.
|
|
661
661
|
|
|
662
662
|
**Bảng rỗng hoặc không có row nào cho SC của UC này** → *không tự sinh id rồi đi tiếp*. Cảnh báo rồi **để người quyết**:
|
|
663
663
|
|
|
@@ -614,7 +614,7 @@ sở hữu (DB) vs lấy live (API ngoài), và thao tác ghi chính.}
|
|
|
614
614
|
trong CÙNG nhóm platform (không bao giờ tạo nhóm 4.5 thứ hai cho cùng platform).
|
|
615
615
|
• §4.5.2–§4.5.5 — tương tự theo màn hình/UC ở chỗ chúng khác nhau.
|
|
616
616
|
• §4.5.6 Test Selectors — MỘT bảng dùng chung cho cả nhóm platform; cột
|
|
617
|
-
"
|
|
617
|
+
"Serves SC" mang (UC · SC) để consumer per-UC lọc row của mình.
|
|
618
618
|
Append: platform mới → nhóm "### 4.5 — {platform}" mới; màn hình/UC mới trong
|
|
619
619
|
platform đã có → thêm sub-block + row vào §4.5.6 (đừng lặp nhóm).
|
|
620
620
|
Bỏ hẳn §4.5 với PRD backend-only. -->
|
|
@@ -670,11 +670,11 @@ sở hữu (DB) vs lấy live (API ngoài), và thao tác ghi chính.}
|
|
|
670
670
|
iOS accessibilityIdentifier. Dùng lại CÙNG giá trị id trên web/app cho cùng một
|
|
671
671
|
element logic.
|
|
672
672
|
MỘT bảng dùng chung cho cả nhóm platform (phủ mọi màn hình/UC của platform này).
|
|
673
|
-
Cột "
|
|
673
|
+
Cột "Serves SC" mang (UC · SC) để consumer per-UC (generate-code / qc) lọc row
|
|
674
674
|
của mình qua §10. Nhóm §4.5 này vốn đã theo platform, nên platform là ngầm định
|
|
675
675
|
(khối web → web · SC). -->
|
|
676
676
|
|
|
677
|
-
| Test-ID | Element | Component (§4.5.1.x) | Action |
|
|
677
|
+
| Test-ID | Element | Component (§4.5.1.x) | Action | Serves SC (UC · SC) |
|
|
678
678
|
|---------|---------|----------------------|--------|---------------------|
|
|
679
679
|
| `{uc}-{screen}-{element}-{type}` | {Nút submit} | {Component} | {submit} | {UC1 · SC1, UC1 · SC3} |
|
|
680
680
|
|
|
@@ -26,15 +26,25 @@ patch, mọi element đều là `new`. Chỉ chạy Step 1 → 2 → 5.
|
|
|
26
26
|
>
|
|
27
27
|
> ```
|
|
28
28
|
> /review-tech-docs (APPROVED)
|
|
29
|
-
> ├──→ /generate-code
|
|
30
|
-
> └──→ /qc-design-test
|
|
29
|
+
> ├──→ /generate-code FE gắn attribute theo hợp đồng
|
|
30
|
+
> └──→ /qc-analyze → /qc-plan → /qc-design-test QC viết test case theo CÙNG hợp đồng
|
|
31
31
|
> ```
|
|
32
32
|
>
|
|
33
|
+
> **Cửa vào làn QC là `/qc-analyze`, KHÔNG phải `/qc-design-test`.** Trạm 3 tiêu thụ output của
|
|
34
|
+
> trạm 1–2 (`REQUIREMENT_ANALYSIS.md` · `DOC_GAP.md` · `TEST_PLAN.md`); trỏ thẳng vào nó là chỉ
|
|
35
|
+
> người ta nhảy vào giữa dây chuyền. Cả ba trạm đầu **không cần code**, nên nhánh QC vẫn song song
|
|
36
|
+
> trọn vẹn với `/generate-code` — chỉ trạm 5 `/qc-run-test` mới cần code chạy được.
|
|
37
|
+
>
|
|
33
38
|
> Hai nhánh **không chờ nhau** vì cùng đọc một bản đã đóng băng, không đọc output của nhau.
|
|
34
39
|
> Chạy sau code thì QC phải xếp hàng, và `/generate-code` không có gì để đọc nên sẽ tự sinh id
|
|
35
40
|
> — hợp đồng thành thứ do code quyết định.
|
|
36
41
|
|
|
37
42
|
## Gate
|
|
43
|
+
|
|
44
|
+
*Checkpoint: **chặn CỨNG** — ghi đè §4.5.6 đã có → ĐỔI id hợp đồng mà SA viết tay, và kéo theo Step 5b hạ `qc_status` + bump `tech_doc_revision` cho một hợp đồng **chưa hỏng**. `--yes` KHÔNG bỏ qua được (gate Bước 3a).*
|
|
45
|
+
|
|
46
|
+
*Mức cứng chỉ áp khi §4.5.6 **đã có row**. Tech-doc chưa có bảng — brownfield thật, ca lệnh này **sinh ra để phục vụ** — đi thẳng, không CHECKPOINT cứng. Xem Step 2 §Bảng đã có id.*
|
|
47
|
+
|
|
38
48
|
# Gate — Quy trình vào chuẩn cho mọi lệnh
|
|
39
49
|
|
|
40
50
|
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ó.
|
|
@@ -188,7 +198,7 @@ Mỗi dòng ⚠️/🔴 phải ứng với một trạng thái **context-loader
|
|
|
188
198
|
🔴/⚠️ (không chặn ≠ không báo — người đọc log sau này vẫn cần thấy).
|
|
189
199
|
|
|
190
200
|
|
|
191
|
-
*Lưu ý: Với lệnh này, target ở Bước 1 là một UC-ID. Đọc `.feature` FE của UC (web/app), các màn Design Spec của nó, tech-doc gộp `{paths.tech_docs_dir}/{domain}/{prd-slug}/tech-docs/{TICKET-ID}-tech-design.md` (§4.5.6 của platform, nếu có — bảng này gộp mọi UC của platform, **lọc theo cột "
|
|
201
|
+
*Lưu ý: Với lệnh này, target ở Bước 1 là một UC-ID. Đọc `.feature` FE của UC (web/app), các màn Design Spec của nó, tech-doc gộp `{paths.tech_docs_dir}/{domain}/{prd-slug}/tech-docs/{TICKET-ID}-tech-design.md` (§4.5.6 của platform, nếu có — bảng này gộp mọi UC của platform, **lọc theo cột "Serves SC" khớp SC của UC này** qua §10), và figma-components catalog cho `active_module`.*
|
|
192
202
|
|
|
193
203
|
## Context
|
|
194
204
|
**BẮT BUỘC — đọc `.agent/steps/context-loader.md` và thực thi TOÀN BỘ quy trình trong đó**,
|
|
@@ -228,6 +238,47 @@ file tối thiểu) thì ghi tên component.
|
|
|
228
238
|
- **Reused:** id được áp ở **usage site** (không bake vào component dùng chung) → gán theo cùng quy ước.
|
|
229
239
|
- **Cross-platform:** nếu §4.5.6 của platform **kia** (block `web`/`app` trong cùng tech-doc gộp) đã có id cho cùng element logic, **dùng lại id value đó** (chỉ attribute khác theo platform) để web và app nhất quán và logic QC tái dùng được.
|
|
230
240
|
|
|
241
|
+
### Bảng §4.5.6 ĐÃ CÓ id cho element này → **DÙNG LẠI AS-IS** *(G83)*
|
|
242
|
+
|
|
243
|
+
Đối xứng với luật *reverse-document* cho code ở gạch đầu tiên. Chỉ gán id mới cho element **chưa có
|
|
244
|
+
row**. Quy ước `{uc-lower}-{screen}-{element}-{type}` là **mặc định cho id MỚI** — **không** phải
|
|
245
|
+
chuẩn để chuẩn-hoá lại id đã có.
|
|
246
|
+
|
|
247
|
+
| Tình huống | Xử lý |
|
|
248
|
+
|---|---|
|
|
249
|
+
| Element **đã có row** trong §4.5.6 | **Giữ nguyên id**. Cập nhật cột `Element`/`Component`/`Action` nếu thật sự đổi; **không đụng cột Test-ID** |
|
|
250
|
+
| Element **chưa có row** | Gán theo quy ước, thêm row mới |
|
|
251
|
+
| Row trong bảng mà element **không còn** trong design-spec/BDD | **Không xoá** — nêu ở report để người quyết *(có thể đang phục vụ UC khác)* |
|
|
252
|
+
|
|
253
|
+
> **Vì sao as-is chứ không chuẩn hoá.** Bảng là **HỢP ĐỒNG**, không phải output của lệnh này. Chuẩn
|
|
254
|
+
> hoá một hợp đồng mà **cả FE lẫn QC đang bám vào**, chỉ vì tên không theo ý lệnh, là đổi hợp đồng
|
|
255
|
+
> **mà không ai yêu cầu** — rồi Step 5b trung thành hạ `qc_status` và bump revision cho một thứ chưa
|
|
256
|
+
> hỏng gì.
|
|
257
|
+
>
|
|
258
|
+
> **Đây là lỗ hổng lâu nhất của lệnh này** *(G83)*. Luật *"đã có test-id → dùng lại as-is"* vốn đã có
|
|
259
|
+
> ở gạch đầu — nhưng **chỉ cho CODE**. Vế cho BẢNG bị thiếu, trong khi bảng mới là hợp đồng còn code
|
|
260
|
+
> là bên phải tuân theo nó. Đo trên dự án thật: **28/28 tech-doc** có §4.5.6 **viết tay**, quy ước
|
|
261
|
+
> riêng (`uc{n}-z2-region` · `uc1-z2-rank-avatar / uc1-z2-rank-name`) mà lệnh này không tái tạo được.
|
|
262
|
+
|
|
263
|
+
### `--force` — đổi tên hàng loạt *(ca hợp lệ, nhưng phải nói ra)*
|
|
264
|
+
|
|
265
|
+
Đổi convention toàn dự án là việc thật. Không có cờ → **DỪNG**:
|
|
266
|
+
|
|
267
|
+
```
|
|
268
|
+
❌ §4.5.6 của {TICKET-ID} ({platform}) đã có {n} id — giữ nguyên theo mặc định.
|
|
269
|
+
Muốn đặt lại tên toàn bộ theo quy ước framework: thêm --force
|
|
270
|
+
⚠️ --force sẽ đổi {n} id mà FE đang gắn và QC đang bám:
|
|
271
|
+
· code FE trượt locator cho tới khi gắn lại (lint T17/T18 sẽ kêu)
|
|
272
|
+
· .Test.md bám id cũ (lint T19 sẽ kêu)
|
|
273
|
+
· qc_status của mọi SC liên quan → not_run (Step 5b)
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
Có `--force` → report **bắt buộc** khai:
|
|
277
|
+
```
|
|
278
|
+
⚠️ --force: đã đổi {n} id hợp đồng — {danh sách id cũ → mới}
|
|
279
|
+
Chạy lại: /generate-code (FE gắn id mới) · /qc-design-test {UC-ID} (TC bám id mới)
|
|
280
|
+
```
|
|
281
|
+
|
|
231
282
|
## Step 3 — Đảm bảo component tái dùng forward được test-id (catalog) *(chỉ `--from-code`)*
|
|
232
283
|
|
|
233
284
|
Với mỗi component **reused** có action, tra section **`## Test-ID Forwarding`** của catalog (`{paths.domain_knowledge_dir}/figma-components/{active_module}.md`):
|
|
@@ -254,14 +305,14 @@ Tạo hoặc cập nhật §4.5.6 (block platform tương ứng) trong tech-doc
|
|
|
254
305
|
|
|
255
306
|
Mỗi row — **5 cột, đúng thứ tự của template** (`templates/tech-design.template.md` §4.5.6):
|
|
256
307
|
|
|
257
|
-
`Test-ID | Element | Component | Action |
|
|
308
|
+
`Test-ID | Element | Component | Action | Serves SC (UC · SC)`
|
|
258
309
|
|
|
259
310
|
- **Component** — trỏ `§4.5.1.x` nếu §4.5.1 đã vẽ; chưa có (ca brownfield ghi file tối thiểu) thì ghi tên component.
|
|
260
|
-
- **
|
|
311
|
+
- **Serves SC** — danh sách `(UC · SC)` mà id này phục vụ. Một id phục vụ nhiều UC là **bình thường**: tiền tố UC trong tên id chỉ nói UC nào giới thiệu element đó đầu tiên.
|
|
261
312
|
|
|
262
313
|
> **KHÔNG ghi phân loại `reused`/`existing`/`new` vào bảng.** Nó là phân loại **lúc chạy** của Step 1 (dùng để rẽ nhánh Step 2–4), và nó **đổi theo thời gian** — một element `new` thành `existing` ngay khi dev viết code. Nhét dữ liệu biến thiên vào bảng hợp đồng là làm bảng sai dần mà không ai cập nhật.
|
|
263
314
|
>
|
|
264
|
-
> **Thứ tự cột là load-bearing:** `lint-trace` **T15** đọc cột "
|
|
315
|
+
> **Thứ tự cột là load-bearing:** `lint-trace` **T15** đọc cột "Serves SC" theo **vị trí** (ô nội dung cuối cùng) để đối chiếu với `.feature`. Viết sai thứ tự là T15 đọc nhầm ô.
|
|
265
316
|
|
|
266
317
|
## Step 5b — Làm mất hiệu lực `qc_status` của SC bị ảnh hưởng *(chỉ khi ĐỔI id đã có)*
|
|
267
318
|
|
|
@@ -274,13 +325,33 @@ lực ≠ ghi đè"*: *"lệnh nào làm giá trị đó HẾT ĐÚNG thì BẮT
|
|
|
274
325
|
|
|
275
326
|
```
|
|
276
327
|
với mỗi id ĐỔI:
|
|
277
|
-
đọc cột "
|
|
328
|
+
đọc cột "Serves SC" của row đó → danh sách {UC-ID}-SC{N}
|
|
278
329
|
mở sổ {paths.trace_dir}/{domain}/{prd-slug}/{UC-ID}-{platform}.tsv
|
|
279
330
|
với mỗi SC trong danh sách:
|
|
280
|
-
qc_status
|
|
281
|
-
qc_run_at
|
|
331
|
+
qc_status → not_run (chỉ hạ từ `pass`/`fail`; đang `not_run`/`skip` thì để yên)
|
|
332
|
+
qc_run_at → —
|
|
333
|
+
tech_doc_revision → @trace.revision MỚI của tech-doc ← bump, xem dưới
|
|
282
334
|
```
|
|
283
335
|
|
|
336
|
+
### Bump `tech_doc_revision` — vì sao lệnh này cũng là một bumper *(G64)*
|
|
337
|
+
|
|
338
|
+
Tăng `@trace.revision` ở header tech-doc, rồi ghi số mới vào cột `tech_doc_revision` của **mọi row
|
|
339
|
+
trong các sổ vừa chạm**.
|
|
340
|
+
|
|
341
|
+
§4.5.6 là hợp đồng mà `/qc-design-test` **chép cứng giá trị id vào `.Test.md`** — một artifact **bền,
|
|
342
|
+
nằm lại**. Cơ chế phát hiện lỗi thời của tầng artifact QC (`steps/qc-stamp.md`) hoạt động theo **nhãn**:
|
|
343
|
+
`.Test.md` đóng dấu `tech_doc_revision`, trạm 4–5 so với hiện tại. **Sửa §4.5.6 mà không bump nhãn thì
|
|
344
|
+
cơ chế đó không nổ** — đúng ca quan trọng nhất.
|
|
345
|
+
|
|
346
|
+
> **Vì sao không dựa vào `Next` → `/review-tech-docs`.** Lệnh đó **có** bump (`:396` — set
|
|
347
|
+
> `tech_doc_revision` cho mọi row). Nhưng đường ấy chỉ đúng **khi người dùng đi theo `Next`**, mà
|
|
348
|
+
> Step 5b này tồn tại chính vì ca *"sửa nhanh một id rồi đi tiếp"*. Dựa vào `Next` là dựa vào **kỷ
|
|
349
|
+
> luật**, không phải vào máy — và `rules/workflow.md` gọi chỗ này là **điểm mù tuyệt đối**: *"mọi
|
|
350
|
+
> drift detector so **nhãn version**, không so **nội dung**"*. Không bump là tự tay đi vòng qua nhãn.
|
|
351
|
+
>
|
|
352
|
+
> **Thêm row MỚI thì KHÔNG bump** — cùng điều kiện với việc hạ `qc_status`: chưa `.Test.md` nào bám
|
|
353
|
+
> id mới, không gì hết đúng.
|
|
354
|
+
|
|
284
355
|
**KHÔNG đụng `qc_owner` và `qc_blocked_by`.** `rules/workflow.md` miễn trừ tường minh hai cột
|
|
285
356
|
này: chúng là **con trỏ tới bug**, và đổi một test-id không làm con bug biến mất. Xoá đi là mất
|
|
286
357
|
đường về bug đang mở.
|
|
@@ -289,10 +360,16 @@ này: chúng là **con trỏ tới bug**, và đổi một test-id không làm c
|
|
|
289
360
|
|
|
290
361
|
In ra ở report:
|
|
291
362
|
```
|
|
292
|
-
⚠️ {n} scenario có script QC bám id CŨ — qc_status hạ về not_run: {danh sách SC}
|
|
293
|
-
|
|
363
|
+
⚠️ {n} scenario có TC/script QC bám id CŨ — qc_status hạ về not_run: {danh sách SC}
|
|
364
|
+
tech_doc_revision bump → {rev mới} (để .Test.md lỗi thời bị phát hiện ở trạm 4-5)
|
|
365
|
+
Chạy /qc-design-test lại cho các UC đó.
|
|
294
366
|
```
|
|
295
367
|
|
|
368
|
+
> **Chỉ `/qc-design-test`, KHÔNG phải "hoặc `/qc-run-test`"** *(G64 — lời nhắc cũ chỉ sai đường)*.
|
|
369
|
+
> `/qc-run-test` dựng locator từ §4.5.6 **tươi** nên phần locator nó tự cứu — nhưng nó **không sửa**
|
|
370
|
+
> id cũ đã nằm trong `.Test.md`. Ai chọn vế đó sẽ thấy test xanh trở lại và tưởng xong, trong khi tài
|
|
371
|
+
> liệu test vẫn mô tả một element không còn mang id đó.
|
|
372
|
+
|
|
296
373
|
> **Vì sao hạ chứ không giữ.** `rules/workflow.md`: *"`pass` **không** mang nghĩa 'test đã chạy
|
|
297
374
|
> xanh' — nó mang nghĩa 'scenario này đã được nghiệm thu theo spec **hiện tại**'."* Một script
|
|
298
375
|
> định vị bằng id không còn tồn tại thì không nghiệm thu được gì cả. Và QC biết phải chạy lại
|