@educa-corp/sdd-framework 0.9.4 → 0.9.5
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/lint-trace.js +230 -2
- package/bin/self-check.js +24 -0
- package/bin/trace-schema.json +58 -4
- package/core/FRAMEWORK_VERSION +1 -1
- package/core/commands/generate-bdd.md +1 -0
- package/core/commands/generate-code.md +39 -2
- package/core/commands/generate-tech-docs.md +21 -2
- package/core/commands/map-testids.md +88 -8
- package/core/commands/qc-analyze.md +424 -354
- package/core/commands/qc-design-test.md +246 -182
- package/core/commands/qc-plan.md +92 -79
- package/core/commands/qc-report.md +76 -60
- package/core/commands/qc-review.md +130 -114
- package/core/commands/qc-run-test.md +230 -156
- package/core/commands/review-tech-docs.md +20 -0
- package/core/modules/qc-playwright/stack-profile.yaml +1 -1
- package/core/rules/data-protection.md +52 -0
- package/core/skills/qc/_shared/self-review-principles.md +112 -0
- package/core/skills/qc/qa-runner/e2e.md +2 -2
- package/core/skills/qc/qa-runner/functional/gui-feature.md +9 -3
- package/core/skills/qc/qa-runner/functional/gui-screen.md +9 -3
- package/core/skills/qc/qa-runner/integration.md +1 -1
- package/core/skills/qc/qa-runner/non-functional.md +1 -1
- package/core/skills/spec/SKILL.md +1 -1
- package/core/steps/context-loader.md +7 -2
- package/core/steps/gap-verify.md +67 -0
- package/core/steps/report-footer.md +3 -3
- package/core/templates/feature.template +1 -0
- package/core/templates/tech-design.template.md +1 -0
- package/docs/04-reference/commands.md +1 -1
- package/docs/04-reference/trace-schema.md +38 -0
- package/docs/explain/11-map-testids.md +70 -69
- package/docs/plans/qc-surgery/00-nhat-ky.md +497 -0
- package/docs/plans/qc-surgery/01-checklist.md +92 -0
- package/docs/plans/qc-surgery/02-lo-trinh.md +266 -0
- package/docs/plans/qc-surgery/buoc/0-01-testid-attr-co-cho-o.md +157 -0
- package/docs/plans/qc-surgery/buoc/0-02-mot-nguon-cho-testid-attr.md +135 -0
- package/docs/plans/qc-surgery/buoc/0-03-skill-thoi-day-do-dom.md +167 -0
- package/docs/plans/qc-surgery/buoc/0-04-may-canh-hop-dong.md +173 -0
- package/docs/plans/qc-surgery/buoc/0-05-don-nhan-cot-va-2b.md +133 -0
- package/docs/plans/qc-surgery/buoc/0-06-hop-dong-truoc-code.md +226 -0
- package/docs/plans/qc-surgery/buoc/1-01-guard-br-tag.md +156 -0
- package/docs/plans/qc-surgery/buoc/1-02-guard-sc-coverage.md +153 -0
- package/docs/plans/qc-surgery/buoc/1-03-fail-3-nhan.md +176 -0
- package/docs/plans/qc-surgery/buoc/1-04-self-review-dung-chung.md +175 -0
- package/docs/plans/qc-surgery/buoc/1-05-spec-la-du-lieu.md +164 -0
- package/docs/plans/qc-surgery/buoc/1-06-gap-verify-du-bo.md +162 -0
- package/docs/plans/qc-surgery/buoc/README.md +85 -0
- package/docs/plans/qc-surgery/exec-d0-b1-testid-attr-header.md +147 -0
- package/docs/plans/qc-surgery/exec-d0-b2-thong-nhat-nguon-testid-attr.md +152 -0
- package/docs/plans/qc-surgery/exec-d0-b3-sua-skill-probe-dom.md +173 -0
- package/docs/plans/qc-surgery/exec-d0-b4-may-canh-4-5-6.md +168 -0
- package/docs/plans/qc-surgery/exec-d0-b5-don-nhan-lech.md +196 -0
- package/docs/plans/qc-surgery/exec-d0-b6-contract-truoc-code.md +350 -0
- package/docs/plans/qc-surgery/exec-d1-b1-guard-br-tag.md +129 -0
- package/docs/plans/qc-surgery/exec-d1-b2-guard-sc-coverage.md +159 -0
- package/docs/plans/qc-surgery/exec-d1-b3-fail-3-bucket.md +158 -0
- package/docs/plans/qc-surgery/exec-d1-b4-self-review-principles.md +145 -0
- package/docs/plans/qc-surgery/exec-d1-b5-noi-quy-spec-la-du-lieu.md +156 -0
- package/docs/plans/qc-surgery/exec-d1-b6-gap-verify-mo-rong.md +179 -0
- package/docs/plans/qc-surgery/exec-d2-b1-tach-qc-review.md +166 -0
- package/docs/plans/qc-surgery/exec-d2-b2-tach-qc-run-test-atomic.md +267 -0
- package/docs/plans/qc-surgery/exec-d2-b3-qc-automation-assess.md +198 -0
- package/docs/plans/qc-surgery/exec-d3-b1-qc-report-gate-decision.md +209 -0
- package/docs/plans/qc-surgery/exec-d4-b1-qc-design-testdata.md +146 -0
- package/docs/plans/qc-surgery/exec-d4-b2-qc-smoke-test.md +179 -0
- package/docs/plans/qc-surgery/exec-d4-b3-qc-metrics-va-lint.md +198 -0
- package/docs/plans/qc-surgery/exec-d4-b4-lint-spec-injection.md +199 -0
- package/package.json +1 -1
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
---
|
|
2
|
+
buoc: Đợt 0 — Bước 3
|
|
3
|
+
title: Sửa 2 skill qa-runner đang dạy dò DOM ngược với command
|
|
4
|
+
phu_thuoc: không (chạy song song b1/b2 được)
|
|
5
|
+
trang_thai: đã làm
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Đợt 0 · Bước 3 — Command nói "đừng dò DOM", skill nói "dò DOM đi"
|
|
9
|
+
|
|
10
|
+
← [`01-checklist.md`](01-checklist.md) · [`02-lo-trinh.md`](02-lo-trinh.md)
|
|
11
|
+
|
|
12
|
+
> ✅ **Đã làm rồi.** File này là bản **ĐỊNH làm**. Cái **ĐÃ xảy ra** — gồm chỗ lệch
|
|
13
|
+
> so với kế hoạch này và lý do — ghi ở [`buoc/0-03-skill-thoi-day-do-dom.md`](buoc/0-03-skill-thoi-day-do-dom.md).
|
|
14
|
+
|
|
15
|
+
> **Đây là nguyên nhân gốc của câu hỏi chị QC** *("có thể dùng prompt trích xuất element/locator
|
|
16
|
+
> từ source code thành 1 file không?")*. Đội QC tin là phải tự dò selector, vì **framework đang
|
|
17
|
+
> dạy họ làm vậy**.
|
|
18
|
+
|
|
19
|
+
## 1. Vì sao
|
|
20
|
+
|
|
21
|
+
Framework có hai tầng chỉ dẫn cho cùng một việc:
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
commands/qc-run-test.tmpl ← lệnh, agent đọc đầu tiên
|
|
25
|
+
└─ nạp ──→ skills/qc/qa-runner/functional/gui-screen.md ← skill, agent đọc khi làm
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Lệnh nói: lấy locator từ hợp đồng, **không** dò runtime.
|
|
29
|
+
Skill nói: **dò DOM thật trước khi viết selector**.
|
|
30
|
+
|
|
31
|
+
Agent đọc lệnh rồi nạp skill để làm việc. Skill là thứ nó đọc **sau** và **gần lúc viết code
|
|
32
|
+
nhất** — nên skill thắng. Kết quả: QC dò DOM, ghi selector kiểu `.login-form__submit`, và mọi
|
|
33
|
+
người kết luận "framework không có gì để dựa vào".
|
|
34
|
+
|
|
35
|
+
Cái giá của việc dò DOM: dev đổi tên class là test vỡ. Mà dev **không hề hứa** giữ tên class —
|
|
36
|
+
họ chỉ hứa giữ `data-testid` (nếu có hợp đồng). Selector dò được là selector không ai bảo hành.
|
|
37
|
+
|
|
38
|
+
## 2. Tình trạng hiện tại
|
|
39
|
+
|
|
40
|
+
**Lệnh nói không dò** — `commands/qc-run-test.tmpl:43`:
|
|
41
|
+
|
|
42
|
+
> *"**Locator từ test-id contract (không scan runtime).** Đọc bảng *Test Selectors* §4.5.6
|
|
43
|
+
> (block platform) của tech-doc gộp … và dựng mỗi Page Object locator từ test-id ổn định của
|
|
44
|
+
> nó. **Ưu tiên map; fallback** về role/label/text/CSS (scan chậm hơn) chỉ cho một element có
|
|
45
|
+
> action mà **không** có test-id trong §4.5.6 — và ghi chú để gap được thêm vào tech-design."*
|
|
46
|
+
|
|
47
|
+
**Skill nói dò** — `skills/qc/qa-runner/functional/gui-screen.md:26`:
|
|
48
|
+
|
|
49
|
+
> *"**Probe DOM thật trước khi viết selector** (SPA không `data-testid`): dump class/
|
|
50
|
+
> `aria-label`/role bằng script Playwright tạm → ghi selector đúng (BEM `feature__el`; element
|
|
51
|
+
> interactive có thể `role="tab/menuitem"` + class `--active`)."*
|
|
52
|
+
|
|
53
|
+
**Và skill thứ hai cũng vậy** — `skills/qc/qa-runner/functional/gui-feature.md:25`:
|
|
54
|
+
|
|
55
|
+
> *"**Probe DOM thật trước khi viết selector** (SPA React/Next không `data-testid`): dump class/
|
|
56
|
+
> `aria-label`/role → BEM `feature__el`, carousel dot thường `role="tab"` + class `--active`
|
|
57
|
+
> (không `aria-selected`)."*
|
|
58
|
+
|
|
59
|
+
Cả hai câu nằm ở **Phase 1 — Clarify**, tức là **bước đầu tiên** của việc viết script. Không
|
|
60
|
+
phải fallback, không phải "nếu thiếu test-id thì" — mà là việc đầu tiên phải làm.
|
|
61
|
+
|
|
62
|
+
Chú ý cụm trong ngoặc: *"(SPA không `data-testid`)"*. Câu này được viết cho **hoàn cảnh không có
|
|
63
|
+
hợp đồng test-id**, và ở hoàn cảnh đó nó **hợp lý**. Vấn đề là nó được viết như **mặc định**,
|
|
64
|
+
không như ngoại lệ — nên nó áp cả cho dự án đã có §4.5.6 đầy đủ.
|
|
65
|
+
|
|
66
|
+
## 3. Sẽ đổi thành gì
|
|
67
|
+
|
|
68
|
+
Đảo thứ tự, giữ lại kiến thức kỹ thuật (phần BEM / `role="tab"` là kinh nghiệm thật, đáng giữ),
|
|
69
|
+
nhưng đặt nó đúng vị trí là **fallback có ghi chú**:
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
Phase 1 — Clarify
|
|
73
|
+
Đọc `.Test.md` (confirm Reviewed) · platform · Page Object đã có chưa · fixture setup data?
|
|
74
|
+
|
|
75
|
+
**Locator: đọc hợp đồng TRƯỚC, dò DOM là bước cuối.**
|
|
76
|
+
1. Mở bảng §4.5.6 Test Selectors của tech-doc gộp, lọc theo cột "Serves SC" khớp SC của UC này
|
|
77
|
+
→ dựng locator từ test-id. Đọc `@trace.testid_attr` ở header để biết TÊN thuộc tính.
|
|
78
|
+
2. Element có action mà §4.5.6 KHÔNG có test-id → thử role + accessible name
|
|
79
|
+
(`getByRole('button', { name: 'Đăng nhập' })`).
|
|
80
|
+
3. Vẫn không định vị được → MỚI dò DOM (dump class/`aria-label`/role bằng script Playwright
|
|
81
|
+
tạm; BEM `feature__el`; element interactive có thể `role="tab/menuitem"` + class `--active`).
|
|
82
|
+
Mỗi lần phải dò tới bước này là **ghi một gap**: element nào, màn nào, thiếu test-id.
|
|
83
|
+
Đề nghị chạy `/map-testids {UC-ID}` để dev bổ sung, đừng im lặng sống với selector giòn.
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Điểm quan trọng của cách viết mới: **dò DOM không bị cấm** — nó vẫn cần cho dự án brownfield
|
|
87
|
+
chưa có hợp đồng. Nhưng mỗi lần dò là một **tín hiệu được ghi lại**, thay vì một thói quen. Nhờ
|
|
88
|
+
vậy số lần dò giảm dần theo thời gian (dev bổ sung test-id), chứ không giữ nguyên mãi.
|
|
89
|
+
|
|
90
|
+
Ở pipeline mới (Đợt 2), gap này thành `IMPROVE-{date}-{NN}` và được đẩy về spec repo cho dev —
|
|
91
|
+
nhưng câu chữ ở bước này chưa cần nhắc `IMPROVE`, vì lệnh đó chưa tồn tại.
|
|
92
|
+
|
|
93
|
+
## 3b. Ba ca dễ bị gộp nhầm — bậc 3 CHỈ dành cho ca B
|
|
94
|
+
|
|
95
|
+
Câu hỏi trong lúc review bước này: *"tự select locator này sẽ phục vụ QC trong việc có code, lấy
|
|
96
|
+
test-id nhưng trong bảng chưa có, đúng không?"* — **gần đúng, nhưng đó là ca A, không phải việc
|
|
97
|
+
của bậc 3.** Ba ca đi ba đường khác nhau:
|
|
98
|
+
|
|
99
|
+
| | Code có test-id? | §4.5.6 có? | Đường đúng |
|
|
100
|
+
|---|:---:|:---:|---|
|
|
101
|
+
| **A** | ✅ **có** | ❌ chưa | **`/map-testids`** — nhánh `existing` (`map-testids.tmpl:40`): *"Nếu element **đã** có test-id → **reverse-document** nó (dùng lại as-is)"*. Đưa id vào bảng rồi quay lại **bậc 1** |
|
|
102
|
+
| **B** | ❌ **không có gì** (chỉ class/role) | ❌ chưa | **Bậc 3** — dò DOM, ghi gap, đề nghị dev gắn test-id |
|
|
103
|
+
| **C** | ✅ có | ✅ có nhưng **LỆCH** | Không phải bậc 3 — là ca đối chiếu, người quyết bên nào đúng ([`exec-d0-b6`](exec-d0-b6-contract-truoc-code.md) §3.7) |
|
|
104
|
+
|
|
105
|
+
**Vì sao phải tách A khỏi B.** Bản nháp đầu của bước này viết bậc 3 thành một khối, nên nó sẽ
|
|
106
|
+
**nuốt luôn ca A mà không ai biết**:
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
§4.5.6 rỗng → bậc 1 trượt → bậc 2 trượt → bậc 3 dump DOM
|
|
110
|
+
→ thấy data-testid="login-submit-btn" → dùng luôn
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Trông có vẻ ổn (script vẫn bám test-id ổn định), nhưng mất ba thứ:
|
|
114
|
+
|
|
115
|
+
1. **Id không bao giờ vào §4.5.6** → lần sau lại phải đi khám phá lại từ đầu.
|
|
116
|
+
2. **Không ai review id đó** → nó không thành hợp đồng, dev chưa hề hứa giữ nó.
|
|
117
|
+
3. **Ca A bị nguỵ trang thành ca B** → nhìn script không phân biệt được "id từ hợp đồng" với
|
|
118
|
+
"id nhặt từ DOM".
|
|
119
|
+
|
|
120
|
+
Nên bậc 3 tách thành **3a** (đã có test-id → DỪNG, đẩy ngược về `/map-testids`) và **3b** (không
|
|
121
|
+
có gì → dùng class/role + ghi gap). Khác biệt thực tế: 3a **đẩy việc ngược về hợp đồng**, 3b
|
|
122
|
+
chấp nhận selector giòn nhưng để lại dấu vết.
|
|
123
|
+
|
|
124
|
+
> **Về thời điểm:** ở bước này `/map-testids` chưa có cờ `--from-code` (cờ đó thuộc
|
|
125
|
+
> [`exec-d0-b6`](exec-d0-b6-contract-truoc-code.md) §3.3), nhưng nhánh xử lý ca A **đã tồn tại
|
|
126
|
+
> sẵn** trong lệnh (`map-testids.tmpl:34-40`, phân loại `reused`/`existing`/`new`). Nên skill
|
|
127
|
+
> trỏ `/map-testids {UC-ID}` chung chung là chạy đúng ngay bây giờ; b6 sẽ làm nó tường minh hơn.
|
|
128
|
+
|
|
129
|
+
## 4. Sửa file nào
|
|
130
|
+
|
|
131
|
+
| File | Sửa gì |
|
|
132
|
+
|---|---|
|
|
133
|
+
| `skills/qc/qa-runner/functional/gui-screen.md` | Dòng `:26` — viết lại Phase 1 theo thứ tự 3 bậc ở trên |
|
|
134
|
+
| `skills/qc/qa-runner/functional/gui-feature.md` | Dòng `:25` — tương tự |
|
|
135
|
+
|
|
136
|
+
Rà thêm cho chắc (grep, sửa nếu cùng lỗi):
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
grep -rn "Probe DOM\|probe DOM\|dump class" skills/qc/
|
|
140
|
+
grep -rn "data-testid" skills/qc/qa-designer/ skills/qc/qa-reviewer/
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Hai chỗ đã biết là **không** cùng lỗi, chỉ là tiêu chí review, giữ nguyên:
|
|
144
|
+
- `skills/qc/qa-reviewer/script/functional.md:34` — *"XPath dài/phức tạp → đề xuất data-testid
|
|
145
|
+
/ role"*
|
|
146
|
+
- `skills/qc/qa-reviewer/shared/review-check-groups.md:110` — *"định vị element bằng chỉ số /
|
|
147
|
+
vị trí (`nth(3)`) thay vì test-id → `[FLAKY_RISK]`"*
|
|
148
|
+
|
|
149
|
+
## 5. Kiểm thế nào để biết đã xong
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
# 1. Không còn chỉ dẫn dò DOM ở vị trí "việc đầu tiên"
|
|
153
|
+
grep -n "Probe DOM" skills/qc/qa-runner/functional/gui-screen.md skills/qc/qa-runner/functional/gui-feature.md
|
|
154
|
+
# → nếu còn, phải nằm ở bậc 3 của thứ tự ưu tiên, kèm câu "ghi một gap"
|
|
155
|
+
|
|
156
|
+
# 2. Build + máy tự kiểm (R16(d) canh ref skill vẫn tồn tại)
|
|
157
|
+
node bin/build.js && node bin/self-check.js && node test/run.js
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Kiểm bằng tay — trên một UC **đã có** §4.5.6 đầy đủ:
|
|
161
|
+
|
|
162
|
+
Chạy `/qc-run-test {UC-ID}` và đọc script sinh ra. Locator phải là `getByTestId('...')` với giá
|
|
163
|
+
trị **trùng khớp** bảng §4.5.6. Nếu thấy `page.locator('.some-class')` hoặc thấy agent chạy
|
|
164
|
+
script dump DOM trong khi §4.5.6 có sẵn id cho element đó → chưa xong.
|
|
165
|
+
|
|
166
|
+
## 6. Nếu bỏ qua thì hỏng gì
|
|
167
|
+
|
|
168
|
+
Bước 1 và 2 sửa được **hợp đồng**, nhưng QC vẫn không dùng hợp đồng — vì skill vẫn bảo dò DOM.
|
|
169
|
+
Tức là làm b1 + b2 mà bỏ b3 thì đầu tư vào hợp đồng không thu lại gì: §4.5.6 đầy đủ, header có
|
|
170
|
+
`@trace.testid_attr`, và script vẫn bám class BEM.
|
|
171
|
+
|
|
172
|
+
Xa hơn: Đợt 2 sinh script tự động ở quy mô lớn hơn (`/qc-design-script` cho cả web + mobile).
|
|
173
|
+
Nếu thói quen dò DOM còn nguyên, ta chỉ đang **nhân bản selector giòn nhanh hơn**.
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
---
|
|
2
|
+
buoc: Đợt 0 — Bước 4
|
|
3
|
+
title: Thêm máy canh cho bảng §4.5.6 Test Selectors
|
|
4
|
+
phu_thuoc: d0-b1, d0-b2
|
|
5
|
+
trang_thai: đã làm
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Đợt 0 · Bước 4 — Bảng hợp đồng hiện không ai canh
|
|
9
|
+
|
|
10
|
+
← [`01-checklist.md`](01-checklist.md) · [`02-lo-trinh.md`](02-lo-trinh.md)
|
|
11
|
+
|
|
12
|
+
> ✅ **Đã làm rồi.** File này là bản **ĐỊNH làm**. Cái **ĐÃ xảy ra** — gồm chỗ lệch
|
|
13
|
+
> so với kế hoạch này và lý do — ghi ở [`buoc/0-04-may-canh-hop-dong.md`](buoc/0-04-may-canh-hop-dong.md).
|
|
14
|
+
|
|
15
|
+
## 1. Vì sao
|
|
16
|
+
|
|
17
|
+
Framework có một nguyên tắc đã học đúng 4 lần (G1, G28, G41, G55), và lần nào cũng cùng một
|
|
18
|
+
hình dạng:
|
|
19
|
+
|
|
20
|
+
> **Luật ĐÚNG, viết RÕ, và KHÔNG AI CANH.**
|
|
21
|
+
|
|
22
|
+
Bốn lần đó đều được chữa bằng cùng một cách: *khai tường minh + để máy canh*. Bảng §4.5.6 là
|
|
23
|
+
trường hợp thứ năm, chưa được chữa.
|
|
24
|
+
|
|
25
|
+
Ba kiểu hỏng có thể xảy ra hôm nay mà không có gì báo:
|
|
26
|
+
|
|
27
|
+
| Kiểu hỏng | Chuyện gì xảy ra | Ai phát hiện |
|
|
28
|
+
|---|---|---|
|
|
29
|
+
| **Bảng thiếu row** | Màn hình có 8 nút, bảng chỉ ghi 5. QC viết test cho 3 nút còn lại bằng cách dò DOM → 3 test giòn | Không ai. Đến khi test vỡ vài tuần sau |
|
|
30
|
+
| **Row trỏ SC không tồn tại** | Cột "Phục vụ SC" ghi `UC1 · SC7` nhưng `.feature` chỉ có SC1–SC5 (SC7 đã bị xoá/gộp) | Không ai. QC lọc theo cột này → không khớp row nào → tưởng element không có test-id |
|
|
31
|
+
| **Có §4.5 mà header thiếu attr** | Bảng có giá trị test-id đầy đủ, nhưng không ai biết *tên thuộc tính* chứa chúng | Không ai — cho tới khi test đỏ hàng loạt (xem `exec-d0-b1`) |
|
|
32
|
+
|
|
33
|
+
Điểm chung: cả ba đều hỏng **im lặng**, và cả ba đều **kiểm được bằng máy** — không cần agent
|
|
34
|
+
"để ý", chỉ cần đếm và so khớp.
|
|
35
|
+
|
|
36
|
+
## 2. Tình trạng hiện tại
|
|
37
|
+
|
|
38
|
+
**Không có script nào biết đến §4.5.6:**
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
grep -n "testid\|test_id\|4.5.6" bin/*.js
|
|
42
|
+
# → 0 kết quả (build.js, gate-trace.js, index.js, lint-trace.js, self-check.js)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**Các lệnh review cũng không kiểm:**
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
grep -n "Selector\|testid\|4.5.6" commands/review-tech-docs.tmpl commands/validate-traces.tmpl
|
|
49
|
+
# → 0 kết quả
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Tức là bảng này được **3 lệnh đọc** (`generate-code`, `qc-run-test`, `qc-design-test`) và
|
|
53
|
+
**2 lệnh ghi** (`generate-tech-docs`, `map-testids`), nhưng **0 nơi kiểm**.
|
|
54
|
+
|
|
55
|
+
## 3. Sẽ đổi thành gì
|
|
56
|
+
|
|
57
|
+
> ⚠️ **Ba chỗ dưới đây đã được sửa lại lúc triển khai (2026-09-11)** — bản gốc viết trước khi
|
|
58
|
+
> đọc kỹ `bin/lint-trace.js`. Giữ lại nguyên văn phần cũ để thấy vì sao đổi.
|
|
59
|
+
>
|
|
60
|
+
> **(1) Bỏ rule thứ ba.** Bản gốc đề xuất T15 = *"element có action trong step `When` mà không
|
|
61
|
+
> có row §4.5.6 → WARN"*. **Đã bỏ.** Nhận diện "element có action" từ văn xuôi Gherkin tiếng
|
|
62
|
+
> Việt là suy luận, không phải phép đếm — sẽ hoặc bỏ sót gần hết, hoặc báo loạn; mà báo loạn thì
|
|
63
|
+
> người ta thêm `--warn-only` vào CI và mất luôn hai rule kia. Ca nó nhắm đã có hai lớp phủ tốt
|
|
64
|
+
> hơn: [`exec-d0-b3`](exec-d0-b3-sua-skill-probe-dom.md) (skill bậc 3b bắt ghi gap mỗi lần phải
|
|
65
|
+
> dò DOM) và [`exec-d0-b6`](exec-d0-b6-contract-truoc-code.md) (`TESTID_UNDECLARED` so bảng với
|
|
66
|
+
> **code thật**). Phần còn lại — element không có id ở đâu cả — **không kiểm được bằng máy** ở
|
|
67
|
+
> tầng này (phải parse JSX/Vue/Flutter); câu trả lời đúng là gate `/review-tech-docs` ở b6.
|
|
68
|
+
> → Còn **2 rule**, đánh số **T15** (SC có thật) và **T16** (header attr).
|
|
69
|
+
>
|
|
70
|
+
> **(2) Không cần cờ `--tech-docs`.** `templates/project-context.yaml:100` khai
|
|
71
|
+
> `tech_docs_dir: "specs"` — trùng `specs_dir` trong layout feature-package. Cờ `--specs` sẵn có
|
|
72
|
+
> là đủ.
|
|
73
|
+
>
|
|
74
|
+
> **(3) T16 có HAI mức, không phải một.** Thiếu hẳn field → ERROR; field có nhưng còn placeholder
|
|
75
|
+
> `{…}` → **WARN**. Sau `exec-d0-b1`, tech-doc mới sinh ra **có** field ở dạng placeholder — đó
|
|
76
|
+
> là *"chưa chạy `/map-testids`"*, một trạng thái hợp lệ trong quy trình, không phải *"thiếu"*.
|
|
77
|
+
> Báo ERROR ở đó là làm mọi tech-doc mới đỏ ngay khi vừa tạo.
|
|
78
|
+
>
|
|
79
|
+
> **Hai chi tiết phát hiện lúc viết code:**
|
|
80
|
+
> - **`lint-trace` thoát sớm khi không có sổ trace** (`bin/lint-trace.js:881`). Hai rule mới
|
|
81
|
+
> không cần sổ → phải chạy ở **pass riêng, trước** khối đó, và sửa câu thông báo *"chưa có gì
|
|
82
|
+
> để kiểm"* → *"bỏ qua T1–T14"*.
|
|
83
|
+
> - **Dòng mẫu của template phải được bỏ qua.** Mọi tech-doc mang
|
|
84
|
+
> `| {uc}-{screen}-{element}-{type} | … | {UC1 · SC1, UC1 · SC3} |`. Không bỏ qua thì doc mới
|
|
85
|
+
> tinh đỏ ngay vì *"SC1 của UC1 không tồn tại"*.
|
|
86
|
+
> - **Biến thể định dạng → im lặng, không báo oan.** Cột "Phục vụ SC" parse được hai dạng
|
|
87
|
+
> (`UC1 · SC1` rút gọn và `FT-101-UC1-SC1` đầy đủ). Không parse được token nào → **bỏ qua**,
|
|
88
|
+
> không đoán.
|
|
89
|
+
|
|
90
|
+
*(Bản gốc, giữ để đối chiếu:)* Thêm 3 rule vào **`bin/lint-trace.js`**, đặt tên tiếp số hiện có
|
|
91
|
+
(T1–T14) → **T15, T16, T17**.
|
|
92
|
+
|
|
93
|
+
### Vì sao chọn `lint-trace.js` chứ không phải `self-check.js`
|
|
94
|
+
|
|
95
|
+
Hai file có phân vai rõ, ghi sẵn trong doc-comment của `self-check.js:47-49`:
|
|
96
|
+
|
|
97
|
+
- `self-check.js` canh **CONTRACT** — đọc file nguồn của framework, hỏi "lệnh có gọi đúng tên
|
|
98
|
+
cột không". Nó **không mở file dữ liệu của dự án**.
|
|
99
|
+
- `lint-trace.js` canh **DỮ LIỆU** — mở sổ `.tsv` thật, `.feature` thật của dự án.
|
|
100
|
+
|
|
101
|
+
§4.5.6 là dữ liệu của dự án → thuộc `lint-trace.js`.
|
|
102
|
+
|
|
103
|
+
Thuận lợi: `lint-trace.js` **đã** nhận `--specs DIR` (`bin/lint-trace.js:61`, mặc định `specs`)
|
|
104
|
+
và đã đọc `.feature` cho rule T9 (sổ mồ côi). Nên không phải dựng hạ tầng mới.
|
|
105
|
+
|
|
106
|
+
### Ba rule
|
|
107
|
+
|
|
108
|
+
| Rule | Kiểm gì | Mức | Vì sao mức đó |
|
|
109
|
+
|---|---|---|---|
|
|
110
|
+
| **T15** | Mỗi element có action xuất hiện trong step `When` của `.feature` phải có ≥1 row §4.5.6 trỏ tới SC đó | **WARN** | Nhận diện "element có action" từ prose Gherkin là **suy luận**, không phải phép đếm chắc chắn → WARN để không chặn oan. Vẫn in ra để người thấy |
|
|
111
|
+
| **T16** | Mọi giá trị trong cột "Phục vụ SC" của §4.5.6 phải là SC **có thật** trong `.feature` của platform đó | **ERROR** | Đây là **phép so khớp chuỗi**, không có chỗ cho suy luận. Row trỏ SC không tồn tại là sai dứt khoát |
|
|
112
|
+
| **T17** | Tech-doc có block §4.5 (platform client) mà header thiếu `@trace.testid_attr` → lỗi | **ERROR** | Cũng là phép kiểm có/không. Thiếu field là đảm bảo trượt locator (xem `exec-d0-b1`) |
|
|
113
|
+
|
|
114
|
+
**Tham số:** tech-doc nằm ở `{paths.tech_docs_dir}`, mặc định trùng `specs_dir` trong layout một
|
|
115
|
+
repo. Nếu dự án tách submodule thì khác → thêm cờ `--tech-docs DIR`, **mặc định lấy theo
|
|
116
|
+
`--specs`**, và nếu không tìm thấy thư mục `tech-docs/` nào thì **in một dòng nói rõ là đã bỏ
|
|
117
|
+
qua** — đúng cách T14 đang làm với `--code` (`bin/lint-trace.js:65`):
|
|
118
|
+
|
|
119
|
+
> *"KHÔNG truyền → T14 bị bỏ qua, và file này IN RA MỘT DÒNG nói rõ là đã bỏ qua. Im lặng rồi
|
|
120
|
+
> báo 'sạch' đúng là cách 910 row kia lọt qua."*
|
|
121
|
+
|
|
122
|
+
### Khai vào schema
|
|
123
|
+
|
|
124
|
+
`bin/trace-schema.json` phải khai 3 rule mới để R8 (rule canh "lint-trace tụt lại sau schema")
|
|
125
|
+
không báo lệch. Kiểm lại chỗ khai của T12/T14 rồi làm theo đúng khuôn đó.
|
|
126
|
+
|
|
127
|
+
## 4. Sửa file nào
|
|
128
|
+
|
|
129
|
+
| File | Sửa gì |
|
|
130
|
+
|---|---|
|
|
131
|
+
| `bin/lint-trace.js` | Thêm T15/T16/T17; thêm cờ `--tech-docs` (mặc định theo `--specs`); thêm dòng "đã bỏ qua" khi không tìm thấy tech-doc |
|
|
132
|
+
| `bin/trace-schema.json` | Khai 3 rule mới theo khuôn T12/T14 đã có |
|
|
133
|
+
| `templates/ci/trace-gate.yml` | Nếu file này liệt kê rule theo tên → thêm 3 rule mới (R10 trong `self-check.js` canh đúng chuyện này) |
|
|
134
|
+
| `docs/04-reference/trace-schema.md` | Cập nhật danh sách rule |
|
|
135
|
+
|
|
136
|
+
## 5. Kiểm thế nào để biết đã xong
|
|
137
|
+
|
|
138
|
+
Kiểm bằng **ca lỗi cố ý** — quan trọng hơn kiểm ca sạch, vì rule mới dễ viết thành "luôn xanh":
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
# Ca sạch → phải PASS
|
|
142
|
+
node bin/lint-trace.js --specs specs
|
|
143
|
+
|
|
144
|
+
# Ca T16: sửa 1 row §4.5.6 cho trỏ tới SC không tồn tại (vd UC1 · SC99) → phải ERROR
|
|
145
|
+
# Ca T17: xoá dòng @trace.testid_attr khỏi header 1 tech-doc có §4.5 → phải ERROR
|
|
146
|
+
# Ca T15: xoá 1 row §4.5.6 của element có trong step When → phải WARN (không ERROR)
|
|
147
|
+
# Ca bỏ qua: chạy trên repo không có thư mục tech-docs/ → phải IN DÒNG "đã bỏ qua", exit 0
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Rồi:
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
node bin/build.js && node bin/self-check.js && node test/run.js
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Nếu có test tự động trong `test/run.js` cho lint-trace (đã có cụm T2/T3/T4/T7 ở đó), thêm 3–4
|
|
157
|
+
test cho T15/T16/T17 theo cùng khuôn.
|
|
158
|
+
|
|
159
|
+
## 6. Nếu bỏ qua thì hỏng gì
|
|
160
|
+
|
|
161
|
+
Bước 1, 2, 3 sửa được hợp đồng và sửa được thói quen — nhưng **không có gì giữ nó không mục
|
|
162
|
+
dần**. Sáu tháng sau: SC bị gộp, row §4.5.6 trỏ vào SC đã xoá; màn hình thêm 3 nút, bảng không
|
|
163
|
+
ai cập nhật; một tech-doc mới tạo tay thiếu header. Từng chuyện nhỏ, không ai báo, và QC lại
|
|
164
|
+
quay về dò DOM vì "hợp đồng không đáng tin".
|
|
165
|
+
|
|
166
|
+
Đây đúng là cái vòng mà nguyên tắc số 3 của đợt mổ tồn tại để chặn: *"luật gì cũng phải có máy
|
|
167
|
+
canh — thêm luật mới thì thêm rule trong `bin/` cùng lúc, không để sau"*
|
|
168
|
+
([`00-nhat-ky.md` §6](00-nhat-ky.md)).
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
---
|
|
2
|
+
buoc: Đợt 0 — Bước 5
|
|
3
|
+
title: Dọn nhãn cột lệch và tên mục "§2b" cũ
|
|
4
|
+
phu_thuoc: d0-b1 → d0-b4
|
|
5
|
+
trang_thai: đã làm
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Đợt 0 · Bước 5 — Dọn phần lệch còn lại
|
|
9
|
+
|
|
10
|
+
← [`01-checklist.md`](01-checklist.md) · [`02-lo-trinh.md`](02-lo-trinh.md)
|
|
11
|
+
|
|
12
|
+
> ✅ **Đã làm rồi.** File này là bản **ĐỊNH làm**. Cái **ĐÃ xảy ra** — gồm chỗ lệch
|
|
13
|
+
> so với kế hoạch này và lý do — ghi ở [`buoc/0-05-don-nhan-cot-va-2b.md`](buoc/0-05-don-nhan-cot-va-2b.md).
|
|
14
|
+
|
|
15
|
+
> ⚠️ **Phạm vi đã thu hẹp sau vòng hỏi–đáp ngày 2026-09-11.** Hai phần vốn thuộc bước này —
|
|
16
|
+
> *"đưa `/map-testids` vào golden path"* (§3.3) và *"chặn cứng ở phía tiêu thụ"* — đã **chuyển
|
|
17
|
+
> hẳn** sang [`exec-d0-b6`](exec-d0-b6-contract-truoc-code.md) §3.2 + §3.4, vì ở đó chúng được
|
|
18
|
+
> giải quyết triệt để hơn (đổi thứ tự lệnh + gate ở `/review-tech-docs`, thay vì chỉ sửa tài
|
|
19
|
+
> liệu). **Làm b6 thì bỏ §3.3 của file này** — đừng sửa `steps/report-footer.md` hai lần theo
|
|
20
|
+
> hai hướng. Phần còn lại của bước này (§3.1 nhãn cột, §3.2 tên mục "§2b") vẫn giữ nguyên.
|
|
21
|
+
> Lý do đầy đủ: [`00-nhat-ky.md` §3.2](00-nhat-ky.md).
|
|
22
|
+
|
|
23
|
+
## 1. Vì sao
|
|
24
|
+
|
|
25
|
+
Bốn bước trước sửa phần *hoạt động*. Bước này sửa phần *cách gọi tên* và *vị trí trong quy
|
|
26
|
+
trình* — nghe nhỏ, nhưng cả hai đều đã gây hậu quả thật:
|
|
27
|
+
|
|
28
|
+
**Nhãn lệch** — cùng một bảng, hai chỗ mô tả cột thứ ba bằng hai cái tên khác nhau. Ai đọc một
|
|
29
|
+
chỗ rồi làm theo chỗ kia sẽ ghi sai định dạng, và không có gì báo (Bước 4 chỉ canh cột "Phục vụ
|
|
30
|
+
SC", không canh cột này).
|
|
31
|
+
|
|
32
|
+
**Tên mục cũ** — ba file vẫn gọi bảng này là "§2b Test Selectors". Số mục đã đổi thành §4.5.6 từ
|
|
33
|
+
lâu. Agent đọc "§2b" rồi đi tìm §2b trong tech-doc → không có → kết luận tech-doc không có bảng
|
|
34
|
+
test selector → dò DOM. Chính là vòng lỗi mà Bước 3 vừa chặn, nhưng qua một cửa khác.
|
|
35
|
+
|
|
36
|
+
**Không nằm trong golden path** — `/map-testids` là lệnh **duy nhất** biết đọc source code
|
|
37
|
+
brownfield để rút test-id. Nó không có trong danh sách bước bắt buộc, nên trong thực tế bị bỏ.
|
|
38
|
+
Chính tài liệu của framework đã thừa nhận điều này.
|
|
39
|
+
|
|
40
|
+
## 2. Tình trạng hiện tại
|
|
41
|
+
|
|
42
|
+
### 2.1 Nhãn cột thứ ba lệch nhau
|
|
43
|
+
|
|
44
|
+
| Nơi | Ghi cột 3 là |
|
|
45
|
+
|---|---|
|
|
46
|
+
| `templates/tech-design.template.md:276` | `Component (§4.5.1.x)` |
|
|
47
|
+
| `commands/map-testids.tmpl:64` | `Component (reused/existing/new)` |
|
|
48
|
+
|
|
49
|
+
Nguyên văn `map-testids.tmpl:64`:
|
|
50
|
+
|
|
51
|
+
> *"Mỗi row: `Test-ID | Element | Component (reused/existing/new) | Action | Serves SC`."*
|
|
52
|
+
|
|
53
|
+
Nguyên văn template (`:276`):
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
| Test-ID | Element | Component (§4.5.1.x) | Action | Phục vụ SC (UC · SC) |
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Hai cái này **không phải cùng thứ**: một cái muốn *tên component* (trỏ tới §4.5.1.x — cây
|
|
60
|
+
component), cái kia muốn *phân loại nguồn gốc* (reused/existing/new). Cả hai đều có ích, nhưng
|
|
61
|
+
phải chọn — hoặc tách thành 2 cột.
|
|
62
|
+
|
|
63
|
+
### 2.2 Tên mục cũ "§2b" còn sót 3 chỗ
|
|
64
|
+
|
|
65
|
+
| File:dòng | Nội dung |
|
|
66
|
+
|---|---|
|
|
67
|
+
| `skills/spec/SKILL.md:19` | gọi "§2b Test Selectors" |
|
|
68
|
+
| `modules/qc-playwright/stack-profile.yaml:22` | ghi **cả hai**: *"FE tech-design §2b Test Selectors contract (… bảng Test Selectors §4.5.6 …)"* |
|
|
69
|
+
| `specs/domain-knowledge/figma-components/react.md:91` | gọi "§2b" |
|
|
70
|
+
|
|
71
|
+
### 2.3 `/map-testids` không bắt buộc
|
|
72
|
+
|
|
73
|
+
Vị trí của nó trong pipeline **mâu thuẫn giữa 3 tài liệu**:
|
|
74
|
+
|
|
75
|
+
| Nơi | Đặt `/map-testids` ở đâu |
|
|
76
|
+
|---|---|
|
|
77
|
+
| `steps/report-footer.md:63` | Phase **Tech Design** (trước `/generate-code`) |
|
|
78
|
+
| `GAPS-v4.md:724` | trước `/generate-code --phase=ui` |
|
|
79
|
+
| `docs/explain/11-map-testids.md:1,69` | **sau** `/generate-code` + `/review-code` |
|
|
80
|
+
|
|
81
|
+
Và `docs/explain/11-map-testids.md:60` tự thừa nhận sự mờ này:
|
|
82
|
+
|
|
83
|
+
> *"vị trí pipeline hơi mờ (giữa Tech Design & Code). Chạy sớm quá thì UI chưa xong, muộn quá
|
|
84
|
+
> thì QC phải chờ."*
|
|
85
|
+
|
|
86
|
+
Rồi `:63` nói thẳng hậu quả:
|
|
87
|
+
|
|
88
|
+
> *"**Không bắt buộc trong golden path** — dễ bị bỏ qua, khiến QC selector giòn."*
|
|
89
|
+
|
|
90
|
+
## 3. Sẽ đổi thành gì
|
|
91
|
+
|
|
92
|
+
### 3.1 Chốt 5 cột, một định nghĩa
|
|
93
|
+
|
|
94
|
+
Giữ đúng 5 cột theo template (đang là bản chuẩn vì `generate-tech-docs` include nó), và **chuyển
|
|
95
|
+
phân loại `reused/existing/new` sang cột Ghi chú** thay vì cột Component:
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
| Test-ID | Element | Component (§4.5.1.x) | Action | Phục vụ SC (UC · SC) |
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Sửa `map-testids.tmpl:64` cho khớp, và nói rõ phân loại nguồn gốc ghi ở đâu (Ghi chú, hoặc
|
|
102
|
+
không ghi vào bảng — nó chỉ là phân loại nội bộ lúc chạy Step 1).
|
|
103
|
+
|
|
104
|
+
Lý do chọn template làm chuẩn thay vì `map-testids`: `templates/tech-design.template.md` được
|
|
105
|
+
`generate-tech-docs.tmpl:227` include trực tiếp, nên nó là thứ **sinh ra bảng lần đầu**.
|
|
106
|
+
`/map-testids` chỉ cập nhật bảng đã có → phải theo.
|
|
107
|
+
|
|
108
|
+
### 3.2 Đổi "§2b" → "§4.5.6"
|
|
109
|
+
|
|
110
|
+
Sửa 3 chỗ ở §2.2. Riêng `modules/qc-playwright/stack-profile.yaml:22` đang ghi cả hai tên —
|
|
111
|
+
bỏ tên cũ, giữ một.
|
|
112
|
+
|
|
113
|
+
> **Lưu ý thứ tự:** file `modules/qc-playwright/stack-profile.yaml` sẽ được **thay hẳn** ở Đợt 2
|
|
114
|
+
> bước 2 (Python → TypeScript). Nếu Đợt 2 chạy ngay sau Đợt 0 thì sửa ở đây là công cốc — cân
|
|
115
|
+
> nhắc bỏ qua chỗ này và ghi vào việc dọn của `exec-d2-b2`. Hai chỗ còn lại (`skills/spec/`,
|
|
116
|
+
> `specs/domain-knowledge/`) thì sửa bình thường.
|
|
117
|
+
|
|
118
|
+
### 3.3 Đưa `/map-testids` thành bắt buộc
|
|
119
|
+
|
|
120
|
+
Chốt vị trí: **sau `/generate-code --phase=ui`, trước `/qc-design-test`**. Lý do:
|
|
121
|
+
|
|
122
|
+
- Cần code UI tồn tại để nhánh `existing`/`reused` đọc được file component
|
|
123
|
+
(`map-testids.tmpl:40`, `:48`).
|
|
124
|
+
- Phải xong trước khi QC thiết kế test case, vì `/qc-design-test` đọc §4.5.6 để trích test-id
|
|
125
|
+
vào bước test (`commands/qc-design-test.tmpl:128`).
|
|
126
|
+
|
|
127
|
+
Hai việc:
|
|
128
|
+
|
|
129
|
+
1. Sửa `steps/report-footer.md` (bảng Phase `:63` + bảng Next `:98`) và
|
|
130
|
+
`docs/explain/11-map-testids.md` cho **cùng nói một vị trí**. Gỡ câu tự thừa nhận "vị trí hơi
|
|
131
|
+
mờ" ở `:60` sau khi đã chốt.
|
|
132
|
+
2. **Chặn cứng ở phía tiêu thụ** — đây là phần có hiệu lực thật, vì tài liệu thì đọc rồi bỏ
|
|
133
|
+
qua được: `/qc-design-test` (và `/qc-design-script` ở Đợt 2) khi thấy §4.5.6 **rỗng hoặc
|
|
134
|
+
không tồn tại** cho platform client thì **DỪNG** với thông báo rõ:
|
|
135
|
+
|
|
136
|
+
```
|
|
137
|
+
❌ §4.5.6 Test Selectors rỗng cho platform {platform} của {TICKET-ID}.
|
|
138
|
+
QC không có hợp đồng locator để bám → script sinh ra sẽ giòn.
|
|
139
|
+
Chạy /map-testids {UC-ID} trước, rồi chạy lại lệnh này.
|
|
140
|
+
(Cố ý bỏ qua để prototype: thêm --no-testid-contract, và artifact sẽ được đánh dấu
|
|
141
|
+
là dựa trên selector dò runtime.)
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Cờ `--no-testid-contract` theo đúng tinh thần `--include-draft` của `steps/qc-scope.md`:
|
|
145
|
+
*"cái thường gặp là cái an toàn, và cái sớm phải nói ra"*.
|
|
146
|
+
|
|
147
|
+
## 4. Sửa file nào
|
|
148
|
+
|
|
149
|
+
| File | Sửa gì |
|
|
150
|
+
|---|---|
|
|
151
|
+
| `commands/map-testids.tmpl` | `:64` — nhãn 5 cột khớp template; nói rõ phân loại `reused/existing/new` ghi ở đâu |
|
|
152
|
+
| `skills/spec/SKILL.md` | `:19` — "§2b" → "§4.5.6" |
|
|
153
|
+
| `specs/domain-knowledge/figma-components/react.md` | `:91` — "§2b" → "§4.5.6" |
|
|
154
|
+
| `modules/qc-playwright/stack-profile.yaml` | `:22` — bỏ tên cũ *(hoặc hoãn sang `exec-d2-b2`, xem §3.2)* |
|
|
155
|
+
| `steps/report-footer.md` | `:63` bảng Phase + `:98` bảng Next — chốt một vị trí cho `/map-testids` |
|
|
156
|
+
| `docs/explain/11-map-testids.md` | `:1`, `:60`, `:63`, `:69` — sửa vị trí pipeline, gỡ câu "vị trí hơi mờ" và "không bắt buộc" |
|
|
157
|
+
| `commands/qc-design-test.tmpl` | Thêm guard §4.5.6 rỗng → DỪNG + cờ `--no-testid-contract` |
|
|
158
|
+
|
|
159
|
+
## 5. Kiểm thế nào để biết đã xong
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
# 1. Không còn "§2b" nào
|
|
163
|
+
grep -rn "§2b\|section 2b" --include="*.md" --include="*.yaml" . | grep -v "^./GAPS"
|
|
164
|
+
# → 0 kết quả (trừ file GAPS lịch sử, không sửa)
|
|
165
|
+
|
|
166
|
+
# 2. Nhãn cột khớp nhau
|
|
167
|
+
grep -n "Test-ID | Element" templates/tech-design.template.md commands/map-testids.tmpl
|
|
168
|
+
# → 5 cột giống nhau
|
|
169
|
+
|
|
170
|
+
# 3. Vị trí /map-testids nhất quán
|
|
171
|
+
grep -rn "map-testids" steps/report-footer.md docs/explain/11-map-testids.md
|
|
172
|
+
# → cùng nói một vị trí
|
|
173
|
+
|
|
174
|
+
# 4. Build + máy tự kiểm
|
|
175
|
+
node bin/build.js && node bin/self-check.js && node test/run.js
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Kiểm bằng tay:
|
|
179
|
+
|
|
180
|
+
- Trên một UC **chưa** chạy `/map-testids`, chạy `/qc-design-test {UC-ID}` → phải **DỪNG** với
|
|
181
|
+
thông báo ở §3.3.
|
|
182
|
+
- Thêm `--no-testid-contract` → phải chạy được, và artifact phải có dấu ghi rõ là dựa trên
|
|
183
|
+
selector dò runtime.
|
|
184
|
+
|
|
185
|
+
## 6. Nếu bỏ qua thì hỏng gì
|
|
186
|
+
|
|
187
|
+
Ba hậu quả, giảm dần theo mức nghiêm trọng:
|
|
188
|
+
|
|
189
|
+
1. **Không chặn cứng ở phía tiêu thụ (§3.3) là mất phần lớn giá trị của cả Đợt 0.** Sửa hợp
|
|
190
|
+
đồng, sửa skill, thêm máy canh — nhưng nếu QC vẫn **chạy được** `/qc-design-test` khi §4.5.6
|
|
191
|
+
rỗng thì trong lúc gấp việc, người ta vẫn bỏ `/map-testids`. Tài liệu nói "nên chạy" thì đọc
|
|
192
|
+
rồi bỏ qua; lệnh dừng lại thì không.
|
|
193
|
+
2. **"§2b" còn sót** → agent đi tìm mục không tồn tại → kết luận tech-doc không có bảng → dò
|
|
194
|
+
DOM. Đúng vòng lỗi Bước 3 vừa chặn, đi qua cửa khác.
|
|
195
|
+
3. **Nhãn cột lệch** → hai người ghi bảng theo hai định dạng. Bước 4 chỉ canh cột "Phục vụ SC",
|
|
196
|
+
nên cột này lệch mà vẫn xanh.
|