@educa-corp/sdd-framework 0.9.2 → 0.9.3
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/core/FRAMEWORK_VERSION +1 -1
- package/core/commands/qc-analyze.md +189 -66
- package/core/commands/qc-design-test.md +141 -2
- package/core/commands/qc-plan.md +153 -7
- package/core/commands/qc-review.md +134 -1
- package/core/commands/qc-run-test.md +134 -1
- package/core/modules/qc-playwright/stack-profile.yaml +3 -3
- package/core/skills/qc/qa-analyst/DOC_GAP.template.md +47 -17
- package/core/skills/qc/qa-analyst/acceptance-criteria.md +1 -1
- package/core/skills/qc/qa-analyst/business-rules.md +2 -2
- package/core/skills/qc/qa-analyst/data-flow.md +2 -2
- package/core/skills/qc/qa-analyst/spec-breakdown.md +2 -2
- package/core/skills/qc/qa-analyst/spec-issue-reporter.md +14 -2
- package/core/skills/qc/qa-designer/e2e/journey.md +1 -1
- package/core/skills/qc/qa-designer/exploratory/explore-to-functional.md +1 -1
- package/core/skills/qc/qa-designer/functional/api.md +1 -1
- package/core/skills/qc/qa-designer/functional/gui-feature.md +1 -1
- package/core/skills/qc/qa-designer/functional/gui-screen.md +1 -1
- package/core/skills/qc/qa-designer/integration/api.md +1 -1
- package/core/skills/qc/qa-designer/integration/db.md +1 -1
- package/core/skills/qc/qa-designer/integration/gui.md +1 -1
- package/core/skills/qc/qa-designer/integration/kafka.md +1 -1
- package/core/skills/qc/qa-designer/non-functional.md +1 -1
- package/core/skills/qc/qa-planner/test-plan.md +24 -13
- package/core/skills/qc/qa-runner/exploratory/session.md +1 -1
- package/core/steps/context-loader.md +1 -1
- package/core/steps/qc-scope.md +119 -0
- package/core/templates/project-context.yaml +3 -1
- package/docs/02-concepts/pipeline-steps/08-qc-automation.md +1 -1
- package/docs/04-reference/configuration.md +146 -146
- package/docs/explain/15-qc-analyze.md +1 -1
- package/docs/explain/16-qc-plan.md +1 -1
- package/docs/explain/17-qc-design-test.md +1 -1
- package/docs/plans/qc-implementation-log.md +145 -4
- package/docs/plans/qc-sync-command.md +2 -1
- package/package.json +1 -1
- package/scripts/migrate-qc-docs.js +261 -0
package/core/FRAMEWORK_VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.9.
|
|
1
|
+
0.9.3
|
|
@@ -165,7 +165,7 @@ Mỗi dòng ⚠️/🔴 phải ứng với một trạng thái **context-loader
|
|
|
165
165
|
🔴/⚠️ (không chặn ≠ không báo — người đọc log sau này vẫn cần thấy).
|
|
166
166
|
|
|
167
167
|
|
|
168
|
-
*Lưu ý: Với lệnh này, target ở Bước 1 là một
|
|
168
|
+
*Lưu ý: Với lệnh này, target ở Bước 1 là một **TICKET-ID** (mã PRD), hoặc một UC-ID / file feature / file PRD — cả ba đều quy về TICKET-ID ở §Phạm vi QC. Trạm này chạy cho **cả PRD × một nền**. Đọc spec chính thức của **mọi UC trong phạm vi** — file `.feature` (mang `@trace.id={UC-ID}` và mỗi scenario `@trace.scenario={UC-ID}-SC{N}`), PRD, và design-spec — từ feature package `{paths.specs_dir}/{domain}/{prd-slug}/` (file `.feature` dưới `bdd/`, file PRD `{TICKET-ID}-{prd-slug}.md` ở gốc folder, và design-spec dưới `design-spec/`). Spec của framework CHÍNH LÀ source of truth; đừng suy lại các requirement đã có ở đó. **Ngoài ra đọc tech-doc gộp** `{paths.tech_docs_dir}/{domain}/{prd-slug}/tech-docs/{TICKET-ID}-tech-design.md` làm **nguồn thứ hai** — xem §Đối chiếu tài liệu kỹ thuật.*
|
|
169
169
|
|
|
170
170
|
## Context
|
|
171
171
|
**BẮT BUỘC — đọc `.agent/steps/context-loader.md` và thực thi TOÀN BỘ quy trình trong đó**,
|
|
@@ -177,60 +177,155 @@ placeholder bên dưới sẽ rỗng và lệnh sẽ đọc/ghi sai chỗ.
|
|
|
177
177
|
|
|
178
178
|
---
|
|
179
179
|
|
|
180
|
-
##
|
|
180
|
+
## Phạm vi QC — PRD nào, nền nào, những UC nào
|
|
181
181
|
|
|
182
|
-
|
|
183
|
-
> một UC đa nền có **nhiều file `.feature`** — `bdd/web/`, `bdd/app/`, `bdd/system/` — và mỗi
|
|
184
|
-
> file mang `@trace.status` **riêng**: bản web có thể `approved` trong khi bản app còn `draft`.
|
|
185
|
-
> Guard đọc "file `.feature` của UC" khi chưa biết platform là đọc một file **bất kỳ trong ba**:
|
|
186
|
-
> báo `approved` trong khi bản đang dùng còn nháp, hoặc chặn oan một bản đã duyệt.
|
|
187
|
-
> Chốt platform trước thì Guard mới có đúng một file để đọc.
|
|
182
|
+
# QC Scope — phân giải phạm vi cho mọi lệnh `qc-*`
|
|
188
183
|
|
|
189
|
-
|
|
184
|
+
**Chạy TRƯỚC phần logic riêng của lệnh, và SAU `steps/gate.md`.** Bước này chốt bốn thứ mà
|
|
185
|
+
cả 6 trạm QC đều cần, để chúng không tự suy mỗi trạm một kiểu:
|
|
190
186
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
187
|
+
| Biến | Là gì |
|
|
188
|
+
|---|---|
|
|
189
|
+
| `TICKET-ID` | mã PRD — **thư mục artifact QC mang tên này** |
|
|
190
|
+
| `active_platform` | `web` \| `app` \| `system` \| … — một QC pass khoá đúng MỘT nền |
|
|
191
|
+
| `qc_artifact_dir` | `{paths.qc_dir}/{TICKET-ID}/{active_platform}/` |
|
|
192
|
+
| `uc_list` | các UC của (PRD × nền) này, kèm trạng thái BDD từng UC |
|
|
193
|
+
|
|
194
|
+
> **Vì sao gom về một chỗ.** Luật phân giải nền từng được copy-paste ở 5 lệnh và câu chữ đã
|
|
195
|
+
> lệch nhau. Năm bản của một luật là nơi drift sống: sửa bốn, quên một, và trạm bị quên ghi
|
|
196
|
+
> artifact vào sai thư mục **trong im lặng**.
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## 1 — `TICKET-ID`
|
|
201
|
+
|
|
202
|
+
Artifact QC gom theo **PRD**, không theo UC. Nên mọi trạm phải quy được về `TICKET-ID`:
|
|
203
|
+
|
|
204
|
+
| `$ARGUMENTS` là | Cách lấy |
|
|
205
|
+
|---|---|
|
|
206
|
+
| **UC-ID** (`{TICKET-ID}-UC{N}`) | phần **trước** `-UC` — đúng luật `steps/gate.md` Bước 1 dùng để tìm tech-doc gộp |
|
|
207
|
+
| **TICKET-ID** | dùng trực tiếp |
|
|
208
|
+
| một **path file** (`.feature` / PRD / design-spec) | phân giải `{domain}` + `{prd-slug}` theo luật `context-loader` Bước 1, rồi lấy `TICKET-ID` từ tên file PRD `{TICKET-ID}-{prd-slug}.md` — file `.md` duy nhất ở gốc feature folder |
|
|
209
|
+
|
|
210
|
+
Đối chiếu: `TICKET-ID` suy ra phải khớp tên file PRD thật. Lệch → **DỪNG**, in cả hai giá
|
|
211
|
+
trị. (Suy sai `TICKET-ID` là ghi cả một PRD vào sai thư mục — không có bước nào phía sau bắt được.)
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## 2 — `active_platform`
|
|
216
|
+
|
|
217
|
+
> **PHẢI phân giải TRƯỚC mọi phép đọc `.feature`.** `{UC-ID}-SC{N}` chỉ độc nhất trong
|
|
218
|
+
> (UC × nền), nên một UC đa nền có **nhiều file `.feature`** — `bdd/web/`, `bdd/app/`,
|
|
219
|
+
> `bdd/system/` — và mỗi file mang `@trace.status` **riêng**: bản web có thể `approved`
|
|
220
|
+
> trong khi bản app còn `draft`. Đọc "file `.feature` của UC" khi chưa biết nền là đọc một
|
|
221
|
+
> file **bất kỳ trong ba**: báo `approved` trong khi bản đang dùng còn nháp, hoặc chặn oan
|
|
222
|
+
> một bản đã duyệt.
|
|
223
|
+
|
|
224
|
+
Theo thứ tự, dừng ở cái đầu tiên khớp:
|
|
225
|
+
|
|
226
|
+
1. `$ARGUMENTS` nêu nền (`web`/`app`/`system`/…) → dùng.
|
|
227
|
+
2. Target là một file `.feature` → đọc `# @trace.platform` của nó.
|
|
228
|
+
3. Glob `{paths.specs_dir}/{domain}/{prd-slug}/bdd/*/` — **đúng một** thư mục nền → dùng nó.
|
|
229
|
+
4. Glob `{paths.qc_dir}/{TICKET-ID}/*/` — **đúng một** thư mục nền đã có artifact → dùng nó.
|
|
230
|
+
*(chỉ dùng cho trạm 2–6; trạm `/qc-analyze` là trạm tạo ra thư mục đó nên không có gì để soi.)*
|
|
231
|
+
5. Nhiều nền mà không suy được → hỏi *"QC pass này cho nền nào? (web/app/system)"*.
|
|
232
|
+
**Có `--yes`:** không hỏi — DỪNG với lỗi rõ ràng, vì đoán bừa nền là ghi artifact vào sai
|
|
197
233
|
thư mục và ghi `qc_status` vào sai sổ trace:
|
|
198
234
|
```
|
|
199
|
-
❌ {
|
|
200
|
-
Chạy headless thì phải nêu tường minh: /
|
|
235
|
+
❌ {TICKET-ID} có {n} nền ({list}) — không suy được nền nào cho QC pass này.
|
|
236
|
+
Chạy headless thì phải nêu tường minh: /{lệnh} {TICKET-ID} web --yes
|
|
201
237
|
```
|
|
202
238
|
|
|
203
|
-
Lưu `active_platform`.
|
|
239
|
+
Lưu `active_platform`. Từ đây, **mọi** phép đọc `.feature` chỉ đọc thư mục
|
|
240
|
+
`bdd/{active_platform}/` — không trộn SC chéo nền.
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## 3 — `qc_artifact_dir`
|
|
245
|
+
|
|
246
|
+
```
|
|
247
|
+
qc_artifact_dir = {paths.qc_dir}/{TICKET-ID}/{active_platform}/
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
Chứa: `REQUIREMENT_ANALYSIS.md` · `DOC_GAP.md` · `TEST_PLAN.md` · `test-cases/*.Test.md`
|
|
251
|
+
— **mỗi loại đúng MỘT file cho cả PRD**, các UC là mục/hàng bên trong.
|
|
252
|
+
|
|
253
|
+
`{paths.qc_dir}` là folder top-level **nhìn thấy** trong repo QC (mặc định `docs/`, **không**
|
|
254
|
+
phải `.agent/` ẩn) để đội QC mở và xử lý output dễ dàng. Spec chính thức ở lại spec submodule
|
|
255
|
+
của PO — đừng ghi artifact QC vào đó.
|
|
256
|
+
|
|
257
|
+
> **Sổ trace KHÔNG theo layout này.** Nó vẫn là `{paths.trace_dir}/{domain}/{prd-slug}/{UC-ID}-{active_platform}.tsv`
|
|
258
|
+
> — một sổ cho mỗi (UC × nền), vì mỗi hàng là một scenario. Liên kết giữa hai bên đi qua
|
|
259
|
+
> **cột `UC`** của bảng gap, không qua đường dẫn file.
|
|
204
260
|
|
|
205
261
|
---
|
|
206
262
|
|
|
207
|
-
##
|
|
263
|
+
## 4 — `uc_list`
|
|
264
|
+
|
|
265
|
+
Glob `{paths.specs_dir}/{domain}/{prd-slug}/bdd/{active_platform}/*.feature`. Mỗi file → một
|
|
266
|
+
UC: đọc `# @trace.id` (mã UC) và `# @trace.status` từ header.
|
|
267
|
+
|
|
268
|
+
Chia hai nhóm:
|
|
269
|
+
|
|
270
|
+
| Nhóm | Điều kiện | Xử lý |
|
|
271
|
+
|---|---|---|
|
|
272
|
+
| **Trong phạm vi** | `@trace.status: approved` | phân tích / thiết kế / chạy bình thường |
|
|
273
|
+
| **Chưa xét** | khác `approved` | **KHÔNG** phân tích; vẫn ghi một hàng vào bảng phạm vi kèm trạng thái thật |
|
|
274
|
+
|
|
275
|
+
In bảng phạm vi ra trước khi làm gì:
|
|
276
|
+
```
|
|
277
|
+
Phạm vi QC — {TICKET-ID} / {active_platform}
|
|
278
|
+
✅ {UC-ID} {tên UC} approved
|
|
279
|
+
⏸ {UC-ID} {tên UC} draft → chưa xét
|
|
280
|
+
→ {n} UC trong phạm vi · {m} chưa xét
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
**Cờ `--include-draft`:** phân tích cả UC chưa duyệt, nhưng **vẫn in bảng trên** và đánh dấu
|
|
284
|
+
trong artifact là dựa trên BDD nháp.
|
|
285
|
+
|
|
286
|
+
**Không UC nào `approved` và không có `--include-draft` → DỪNG:**
|
|
287
|
+
```
|
|
288
|
+
❌ {TICKET-ID} ({active_platform}): 0/{n} UC có BDD approved — không có gì để chạy.
|
|
289
|
+
Cách đúng: người duyệt đặt `# @trace.status: approved` rồi chạy lại.
|
|
290
|
+
Muốn chạy sớm trên BDD nháp (prototype): thêm --include-draft
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
> **Vì sao có `--include-draft` chứ không chặn cứng.** QC sớm trên BDD nháp là một cách dùng
|
|
294
|
+
> **cố ý được cho phép** từ trước (guard cũ là cảnh báo mềm, không phải chặn). Bỏ hẳn nó là
|
|
295
|
+
> lấy đi một năng lực đang có mà không ai khai. Còn để mặc định `approved`-only thì cái
|
|
296
|
+
> thường gặp là cái an toàn, và cái sớm phải nói ra.
|
|
297
|
+
|
|
298
|
+
> **Vì sao `--yes` không thay được `--include-draft`.** `--yes` nghĩa *"tôi không ngồi đây để
|
|
299
|
+
> trả lời"*; `--include-draft` nghĩa *"tôi biết BDD còn nháp và vẫn muốn chạy"*. Gộp hai cái
|
|
300
|
+
> là để một lần chạy headless âm thầm phân tích spec chưa chốt rồi bàn giao như thể đã chốt.
|
|
208
301
|
|
|
209
|
-
*Chạy SAU Platform Resolution — xem lý do ở khối trên.*
|
|
210
302
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
⚠️ BDD của {UC-ID} ({active_platform}) đang ở @trace.status: {status} (chưa duyệt). QC chạy trên BDD chưa chốt có thể phải làm lại.
|
|
216
|
-
Khuyến nghị: review-context (BDD) sạch + người duyệt đặt `# @trace.status: approved` rồi mới chạy QC.
|
|
217
|
-
Vẫn chạy QC bây giờ? (Y/N)
|
|
218
|
-
```
|
|
219
|
-
Chỉ tiếp khi chọn Y — **trừ khi `$ARGUMENTS` có `--yes`**: coi như Y, **nhưng vẫn IN khối cảnh
|
|
220
|
-
báo** (không chặn ≠ không báo — người đọc log sau này vẫn cần thấy QC đã chạy trên BDD nháp).
|
|
303
|
+
> **QC chạy trên BDD chưa chốt có thể phải làm lại.** `qc-scope` mặc định chỉ lấy UC có
|
|
304
|
+
> `@trace.status: approved`; UC còn nháp vẫn vào bảng *Phạm vi phân tích* của `DOC_GAP.md`
|
|
305
|
+
> với dấu `⏸ Chưa xét` — **không im lặng bỏ khỏi bảng**, vì "chưa xét" khác "đã xét, sạch".
|
|
306
|
+
> Cố ý QC sớm thì thêm `--include-draft`, và artifact phải ghi rõ nó dựa trên BDD nháp.
|
|
221
307
|
|
|
222
|
-
> **Vì sao
|
|
223
|
-
>
|
|
224
|
-
>
|
|
225
|
-
>
|
|
226
|
-
>
|
|
308
|
+
> **Vì sao trạm này chạy CẢ PRD chứ không từng UC** *(B11)*. Ba lý do, theo thứ tự quan trọng:
|
|
309
|
+
>
|
|
310
|
+
> 1. **Mâu thuẫn chéo UC chỉ lộ ra khi đọc cùng lúc.** UC1 nói một kiểu, UC3 nói kiểu khác —
|
|
311
|
+
> chạy tách từng UC thì về **cấu trúc** là không thể thấy, không phải "khó thấy".
|
|
312
|
+
> 2. **Rẻ hơn.** PRD, bản thiết kế, tài liệu kỹ thuật là nguồn **dùng chung**; chạy per-UC là
|
|
313
|
+
> đọc lại chúng mỗi UC một lượt. Phần dùng chung chiếm đa số đầu vào.
|
|
314
|
+
> 3. **Một tài liệu cho một tính năng** là cách PO và QC vốn làm việc — file gốc của đội QC
|
|
315
|
+
> (`DOC_GAP_FEAT-02-3.md`) không có hậu tố UC, và `qa-planner/test-plan.md` vốn viết
|
|
316
|
+
> *"Test Plan cho một feature"*.
|
|
227
317
|
|
|
228
318
|
---
|
|
229
319
|
|
|
230
320
|
## Đối chiếu tài liệu kỹ thuật *(nguồn thứ hai — bắt lệch nghiệp vụ ↔ kỹ thuật)*
|
|
231
321
|
|
|
232
322
|
Định vị tech-doc gộp cấp PRD: `{paths.tech_docs_dir}/{domain}/{prd-slug}/tech-docs/{TICKET-ID}-tech-design.md`.
|
|
233
|
-
Nó phủ **nhiều UC** —
|
|
323
|
+
Nó phủ **nhiều UC** — và trạm này cũng phủ nhiều UC, nên đọc **mọi phần chạm `uc_list`**
|
|
324
|
+
(đối chiếu `@trace.ucs` ở header với `uc_list`). Phần thuộc UC ngoài phạm vi (`⏸ Chưa xét`) thì bỏ qua.
|
|
325
|
+
|
|
326
|
+
> **Đây là chỗ layout cấp PRD trả lãi rõ nhất.** Tech-doc gộp là **một** tài liệu phủ cả PRD.
|
|
327
|
+
> Chạy per-UC thì nó bị đọc lại N lần, mỗi lần lọc bỏ gần hết — và mâu thuẫn giữa hai UC trong
|
|
328
|
+
> **cùng** tài liệu đó không lần nào lộ ra, vì không lần nào thấy cả hai.
|
|
234
329
|
|
|
235
330
|
**Không tìm thấy → cảnh báo mềm, KHÔNG chặn** (dự án có thể chưa dựng tech-doc):
|
|
236
331
|
```
|
|
@@ -259,9 +354,9 @@ Nó phủ **nhiều UC** — lọc theo `@trace.ucs` ở header, chỉ đọc ph
|
|
|
259
354
|
Tech-doc có sổ ẩn số thiết kế riêng (`§12`), với vòng đời và người chịu trách nhiệm riêng, và
|
|
260
355
|
`/generate-code` đã canh nó. **Trạm này chỉ đọc, tuyệt đối không ghi vào.**
|
|
261
356
|
|
|
262
|
-
Với mỗi mục `open` trong §12 chạm `
|
|
357
|
+
Với mỗi mục `open` trong §12 chạm **bất kỳ UC trong `uc_list`**:
|
|
263
358
|
- **KHÔNG mở gap mới** trong `DOC_GAP.md` về cùng chuyện đó.
|
|
264
|
-
- Ghi vào `REQUIREMENT_ANALYSIS.md` mục *"Đang chờ chốt (từ §12 tech-doc)"*: `{id}` · điều chưa biết · owner · severity.
|
|
359
|
+
- Ghi vào `REQUIREMENT_ANALYSIS.md` mục *"Đang chờ chốt (từ §12 tech-doc)"*: `{id}` · **UC** · điều chưa biết · owner · severity.
|
|
265
360
|
- Test case chạm nó về sau sẽ bị chặn — nhưng bị chặn bởi **một mục đã có người xử lý**, không phải bởi một câu hỏi mới gửi PO.
|
|
266
361
|
|
|
267
362
|
> **Vì sao không ghi vào.** Một ẩn số đã nằm trong §12 nghĩa là **đã có người đang lo**: có
|
|
@@ -272,8 +367,8 @@ Với mỗi mục `open` trong §12 chạm `{UC-ID}`:
|
|
|
272
367
|
|
|
273
368
|
**Ngoại lệ — mục `spec-defect` là việc của PO.** §12 phân ba loại: `nội tại` (backend tự quyết) ·
|
|
274
369
|
`cross-service` (đội khác) · `spec-defect` (PRD/BDD sai hoặc thiếu). Hai loại đầu → ghi "đang chờ".
|
|
275
|
-
Loại thứ ba **đúng là gap tài liệu** → vẫn ghi vào `DOC_GAP.md
|
|
276
|
-
không đếm hai lần.
|
|
370
|
+
Loại thứ ba **đúng là gap tài liệu** → vẫn ghi vào `DOC_GAP.md` (cột `UC` = UC bị chạm), trỏ
|
|
371
|
+
ngược về `{id}` của §12 để không đếm hai lần.
|
|
277
372
|
|
|
278
373
|
---
|
|
279
374
|
|
|
@@ -301,7 +396,8 @@ Thứ tự điển hình: spec-breakdown → business-rules / data-flow → acce
|
|
|
301
396
|
|
|
302
397
|
File `.feature` chính thức đã định nghĩa scenario là `@trace.scenario={UC-ID}-SC{N}` với
|
|
303
398
|
`@trace.business_rules`. Map mọi `BR-xx` / `AC-xx` bạn tạo ra tới `{UC-ID}-SC{N}` sở hữu nó
|
|
304
|
-
và ghi lại mapping —
|
|
399
|
+
và ghi lại mapping — **làm cho từng UC trong `uc_list`**, và `BR`/`AC` phải mang rõ UC của nó
|
|
400
|
+
(một file phân tích giờ phủ nhiều UC, nên `BR-01` không còn tự phân biệt được là của UC nào) — qc-design-test và qc-run-test cần nó để gắn tag
|
|
305
401
|
`@trace.verifies` cho test và ghi `qc_status` theo từng scenario.
|
|
306
402
|
|
|
307
403
|
## Quét gap — hai nguồn, gộp rồi mới thẩm định
|
|
@@ -367,13 +463,23 @@ Gộp gap từ **cả hai nguồn** vào một tập trước khi sang bước t
|
|
|
367
463
|
|
|
368
464
|
## DOC_GAP (bắt buộc)
|
|
369
465
|
|
|
370
|
-
Luôn tạo
|
|
371
|
-
|
|
466
|
+
Luôn tạo **đúng MỘT** file gap cho cả (PRD × nền) theo
|
|
467
|
+
`{paths.qc_skills_dir}/qa-analyst/DOC_GAP.template.md` — các UC là các hàng bên trong, phân
|
|
468
|
+
biệt bằng cột `UC`:
|
|
469
|
+
- **Bảng 11 cột**, cột 2 là `UC`. ID gap `GAP-UC{N}-{nnn}` (vd `GAP-UC1-001`); gap thuộc cả
|
|
470
|
+
PRD → `GAP-GEN-{nnn}`. Đánh số **độc lập trong từng UC** — phân tích lại UC1 KHÔNG được làm
|
|
471
|
+
đổi số gap của UC2, vì test case đã có đang trỏ `🚫 Block: [GAP-UC2-003]`.
|
|
472
|
+
- **Section `Phạm vi phân tích`** — mỗi UC một hàng kèm `@trace.status`, đã phân tích chưa, số
|
|
473
|
+
gap. UC ngoài phạm vi ghi `⏸ Chưa xét`, **không bỏ khỏi bảng**.
|
|
474
|
+
- Mỗi gap phân loại MISSING / AMBIGUOUS / CONTRADICTORY / ASSUMPTION / OPEN QUESTION, với severity (🔴 Blocker → ⚪ Low) và function/BR/AC bị ảnh hưởng.
|
|
372
475
|
- Không bao giờ bịa câu trả lời; đánh dấu giả định là `ASSUMPTION` để PO/dev confirm.
|
|
373
|
-
- Bất kỳ `🔴 Blocker` nào còn `Open` ⇒ UC
|
|
476
|
+
- Bất kỳ `🔴 Blocker` nào còn `Open` ⇒ **UC ở cột `UC` của hàng đó** chưa sẵn sàng cho
|
|
477
|
+
qc-design-test — bàn giao cho qc-plan. *Chặn theo từng UC, KHÔNG chặn cả PRD:* một blocker ở
|
|
478
|
+
UC3 không có lý do gì dừng việc thiết kế test cho UC1. Ghi rõ UC nào bị chặn ở report.
|
|
374
479
|
- **Đẩy các defect spec thực sự lên PO (không chỉ giữ local).** Một blocker là lỗi thật
|
|
375
480
|
trong spec chính thức — `AMBIGUOUS` / `CONTRADICTORY` / `MISSING` trong PRD/BDD — phải tới
|
|
376
481
|
PO qua feedback flow, không chỉ nằm trong `DOC_GAP.md`: tạo `/report-bug {UC-ID} {desc}`
|
|
482
|
+
(`{UC-ID}` lấy từ cột `UC` của hàng gap — bug đi theo UC, không theo PRD)
|
|
377
483
|
(BUG_FLOW của nó phân loại PRD vs BDD), hoặc `/propose-scenario {UC-ID}` nếu gap là thiếu test
|
|
378
484
|
coverage. Gap `ASSUMPTION` / `OPEN QUESTION` được confirm qua questions-for-dev của qc-plan — không file thành bug.
|
|
379
485
|
|
|
@@ -399,18 +505,28 @@ nó bị loại. Cập nhật `Tổng số gap` + bảng ưu tiên sau khi áp v
|
|
|
399
505
|
|
|
400
506
|
## Output
|
|
401
507
|
|
|
402
|
-
Ghi **hai file** dưới `{paths.qc_dir}/{
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
508
|
+
Ghi **hai file** dưới `{qc_artifact_dir}` (= `{paths.qc_dir}/{TICKET-ID}/{active_platform}/`)
|
|
509
|
+
+ **một** dưới `{paths.refinement_dir}/`.
|
|
510
|
+
|
|
511
|
+
**Mỗi loại đúng MỘT file cho cả PRD** — đừng tách một-file-mỗi-UC, và cũng đừng tách
|
|
512
|
+
một-file-mỗi-bước (không có file spec-breakdown / business-rules / data-flow / AC riêng):
|
|
513
|
+
|
|
514
|
+
1. **`{qc_artifact_dir}REQUIREMENT_ANALYSIS.md`** — bản phân tích hợp nhất duy nhất cho cả PRD.
|
|
515
|
+
Mở đầu bằng **bảng `Phạm vi phân tích`** (cùng nội dung với bảng trong `DOC_GAP.md`), rồi
|
|
516
|
+
**một mục cho mỗi UC trong phạm vi**, mỗi mục theo thứ tự: phân rã requirement → bảng
|
|
517
|
+
business-rule (`BR-xx`) → data-flow → acceptance-criteria (`AC-xx`), mỗi `BR`/`AC` map tới
|
|
518
|
+
`{UC-ID}-SC{N}` (của `.feature` nền này) sở hữu nó.
|
|
519
|
+
Thêm một mục **"Mâu thuẫn chéo UC"** — chỗ hai UC của cùng PRD nói khác nhau. Rỗng thì ghi
|
|
520
|
+
"Không có". *Đây là thứ chỉ trạm cấp PRD nhìn thấy được; đừng bỏ mục.*
|
|
521
|
+
Cuối file thêm mục **"Đang chờ chốt (từ §12 tech-doc)"** — các ẩn số thiết kế `open` chạm
|
|
522
|
+
các UC trong phạm vi (`{id}` · UC · điều chưa biết · owner · severity). Rỗng thì ghi
|
|
523
|
+
"Không có"; **đừng bỏ mục**.
|
|
524
|
+
2. **`{qc_artifact_dir}DOC_GAP.md`** — file gap, theo
|
|
411
525
|
`{paths.qc_skills_dir}/qa-analyst/DOC_GAP.template.md` + luật viết ở
|
|
412
526
|
`{paths.qc_skills_dir}/qa-analyst/spec-issue-reporter.md`. Bắt buộc:
|
|
413
|
-
- **Bảng
|
|
527
|
+
- **Bảng 11 cột** đúng thứ tự, có cột **`UC`** (cột 2) và cột **Giao cho đội** (Dev / PO / BA / Design / Kiến trúc / Dữ liệu).
|
|
528
|
+
- Section **"Phạm vi phân tích"** ngay sau metadata — mỗi UC một hàng kèm `@trace.status`,
|
|
529
|
+
đã phân tích chưa, số gap. UC ngoài phạm vi ghi `⏸ Chưa xét`.
|
|
414
530
|
- Ô câu hỏi đủ **bốn phần** tách bằng `<br/>`: **Bối cảnh → Vấn đề → Tại sao quan trọng → Gợi ý**.
|
|
415
531
|
*Ba phần đầu cho PO xếp ưu tiên; phần cuối cho PO trả lời nhanh mà không phải nghĩ lại từ đầu.*
|
|
416
532
|
- Section **"Tài liệu đầu vào đã đọc để phân tích"** đặt ngay sau metadata — liệt kê **đủ** mọi
|
|
@@ -418,7 +534,7 @@ thành một-file-mỗi-bước (không có file spec-breakdown / business-rules
|
|
|
418
534
|
với *"chưa đọc"*.
|
|
419
535
|
- Mức nặng nhất dùng từ **`🔴 Blocker`** (không phải `Critical`) — `/qc-run-test` đọc đúng từ này
|
|
420
536
|
để đặt *"scenario đang chờ PO"* vào sổ trace.
|
|
421
|
-
3. **`{paths.refinement_dir}/{
|
|
537
|
+
3. **`{paths.refinement_dir}/{TICKET-ID}-qa-findings.yaml`** — **cùng dữ liệu gap**, ở định dạng Review Board đọc được. Xem §Bản findings dưới đây.
|
|
422
538
|
|
|
423
539
|
`{paths.qc_dir}` là folder top-level NHÌN THẤY trong QC repo (mặc định `docs/`, **không** phải
|
|
424
540
|
`.agent/review/` ẩn) để team QC mở và xử lý output dễ dàng. Spec chính thức ở lại
|
|
@@ -433,8 +549,10 @@ Dùng **đúng schema của `/refine-prd`** để Review Board đọc được c
|
|
|
433
549
|
|
|
434
550
|
```yaml
|
|
435
551
|
prd_source: "{paths.specs_dir}/{domain}/{prd-slug}/{TICKET-ID}-{prd-slug}.md"
|
|
436
|
-
|
|
552
|
+
ticket_id: "{TICKET-ID}"
|
|
437
553
|
platform: "{active_platform}"
|
|
554
|
+
ucs: ["{UC-ID}", "…"] # các UC TRONG phạm vi (approved) — theo thứ tự
|
|
555
|
+
ucs_skipped: ["{UC-ID}"] # UC chưa xét, kèm lý do ở DOC_GAP §Phạm vi phân tích
|
|
438
556
|
generated_at: "{ISO datetime}"
|
|
439
557
|
generated_by: "qc-analyze"
|
|
440
558
|
status: "pending_review"
|
|
@@ -452,7 +570,7 @@ findings:
|
|
|
452
570
|
auto_fixable: false # LUÔN false — xem cảnh báo dưới
|
|
453
571
|
status: "pending"
|
|
454
572
|
applied_via: ""
|
|
455
|
-
gap_ref: "GAP-
|
|
573
|
+
gap_ref: "GAP-UC1-001" # trỏ ngược về hàng trong DOC_GAP.md (ID mang UC)
|
|
456
574
|
|
|
457
575
|
summary:
|
|
458
576
|
total_findings: {N}
|
|
@@ -473,8 +591,9 @@ summary:
|
|
|
473
591
|
> Đường đúng vẫn là kênh đã có: `/report-bug` cho defect spec thật, `/propose-scenario` cho thiếu
|
|
474
592
|
> độ phủ. File `.yaml` này để **PO đọc và quyết trong một chỗ quen**, không phải để máy tự áp.
|
|
475
593
|
|
|
476
|
-
**File riêng, không ghi chung với `/refine-prd`.**
|
|
477
|
-
`{
|
|
594
|
+
**File riêng, không ghi chung với `/refine-prd`.** Cả hai giờ đều ở cấp PRD, nên khác biệt nằm
|
|
595
|
+
ở **hậu tố**: `{TICKET-ID}-qa-findings.yaml` (trạm này) vs `{prd-slug}-findings.yaml`
|
|
596
|
+
(`/refine-prd`). Đừng gộp. Ghi chung sẽ phá trường `applied_to_version` mà `/refine-prd` dùng để
|
|
478
597
|
phân biệt *"PRD đổi do chính tôi áp fix"* với *"có người lạ sửa"* — và nó sẽ mãi mãi tưởng có
|
|
479
598
|
người sửa sau lưng, mỗi lần chạy đều quét lại toàn bộ kèm cảnh báo giả.
|
|
480
599
|
|
|
@@ -486,17 +605,21 @@ người sửa sau lưng, mỗi lần chạy đều quét lại toàn bộ kèm
|
|
|
486
605
|
Output Artifacts · Next) cho report cuối, kèm khối bên dưới.
|
|
487
606
|
|
|
488
607
|
```
|
|
489
|
-
/qc-analyze Hoàn tất — {
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
608
|
+
/qc-analyze Hoàn tất — {TICKET-ID} ({active_platform})
|
|
609
|
+
Phạm vi: {n}/{N} UC phân tích{nếu có UC chưa xét: " · ⏸ {m} chưa xét: {danh sách UC-ID} (BDD chưa approved)"}
|
|
610
|
+
Files : {paths.qc_dir}/{TICKET-ID}/{active_platform}/REQUIREMENT_ANALYSIS.md + DOC_GAP.md (11 cột)
|
|
611
|
+
{paths.refinement_dir}/{TICKET-ID}-qa-findings.yaml ← mở bằng Review Board (chuột phải)
|
|
612
|
+
Nguồn : PRD · BDD({active_platform}, {n} UC) · design-spec · tech-doc{nếu thiếu tech-doc: " (THIẾU — không đối chiếu được nghiệp vụ ↔ kỹ thuật)"}
|
|
493
613
|
Quét : 4 kỹ năng phân tích + 4 lăng kính (xử lý lỗi · giao diện · dữ liệu & cấu hình
|
|
494
614
|
· đối chiếu chéo: PRD↔design-spec, bdd↔design-spec)
|
|
495
615
|
Verify: {raw} gap thô → {N} còn Open (❌ {invalid} bịa/đã-trả-lời · ⚠️ {reclass} không phải gap nghiệp vụ · 🔁 {merge} trùng)
|
|
496
|
-
Gaps : {N} ({blockers} blocker)
|
|
497
|
-
|
|
616
|
+
Gaps : {N} ({blockers} blocker) — theo UC: {UC1: n · UC2: n · …}{nếu có: " · toàn PRD: {n}"}
|
|
617
|
+
← blocker là spec-defect? → /report-bug {UC-ID của hàng đó} | coverage gap → /propose-scenario {UC-ID}
|
|
618
|
+
Chéo UC: {X} mâu thuẫn giữa các UC của cùng PRD (đã ghi vào REQUIREMENT_ANALYSIS §Mâu thuẫn chéo UC)
|
|
619
|
+
Chặn : {danh sách UC có 🔴 Blocker còn Open} — các UC còn lại vẫn thiết kế test được bình thường
|
|
620
|
+
Chờ chốt: {G} ẩn số §12 tech-doc đang open chạm các UC này (đã ghi vào REQUIREMENT_ANALYSIS, KHÔNG hỏi lại PO)
|
|
498
621
|
SC map: {M} BR/AC map tới {K} scenario
|
|
499
|
-
Next : /qc-plan {
|
|
622
|
+
Next : /qc-plan {TICKET-ID} {active_platform} ← rủi ro / what-if / câu hỏi cho dev
|
|
500
623
|
(giải quyết các gap 🔴 Blocker với PO/Dev trước)
|
|
501
624
|
```
|
|
502
625
|
|
|
@@ -162,7 +162,7 @@ Mỗi dòng ⚠️/🔴 phải ứng với một trạng thái **context-loader
|
|
|
162
162
|
🔴/⚠️ (không chặn ≠ không báo — người đọc log sau này vẫn cần thấy).
|
|
163
163
|
|
|
164
164
|
|
|
165
|
-
*Lưu ý: Với lệnh này, target ở Bước 1 là một UC-ID.
|
|
165
|
+
*Lưu ý: Với lệnh này, target ở Bước 1 là một UC-ID. Đọc output của qc-analyze + qc-plan (`REQUIREMENT_ANALYSIS.md`, `DOC_GAP.md`, `TEST_PLAN.md`) từ `{qc_artifact_dir}` — **cả ba đều ở cấp PRD, lọc theo cột `UC`** để lấy phần của UC này — và file `.feature` của đúng platform đó (với `@trace.scenario` mỗi scenario). Với layer GUI, cũng đọc bảng **Test Selectors** §4.5.6 (block platform) của tech-doc gộp tại `{paths.tech_docs_dir}/{domain}/{prd-slug}/tech-docs/{TICKET-ID}-tech-design.md` (nếu có — bảng gộp mọi UC của platform, **lọc theo cột "Serves SC" khớp SC của UC này**) — các test-id ổn định mà QC sẽ định vị theo.*
|
|
166
166
|
|
|
167
167
|
## Context
|
|
168
168
|
**BẮT BUỘC — đọc `.agent/steps/context-loader.md` và thực thi TOÀN BỘ quy trình trong đó**,
|
|
@@ -172,6 +172,139 @@ Bỏ qua bước này thì `{paths.*}`, `{tech_stack.*}`, `{conventions.*}`, gua
|
|
|
172
172
|
`project-lessons`, và routing service (chế độ umbrella) đều **chưa được phân giải** — mọi
|
|
173
173
|
placeholder bên dưới sẽ rỗng và lệnh sẽ đọc/ghi sai chỗ.
|
|
174
174
|
|
|
175
|
+
## Phạm vi QC
|
|
176
|
+
|
|
177
|
+
# QC Scope — phân giải phạm vi cho mọi lệnh `qc-*`
|
|
178
|
+
|
|
179
|
+
**Chạy TRƯỚC phần logic riêng của lệnh, và SAU `steps/gate.md`.** Bước này chốt bốn thứ mà
|
|
180
|
+
cả 6 trạm QC đều cần, để chúng không tự suy mỗi trạm một kiểu:
|
|
181
|
+
|
|
182
|
+
| Biến | Là gì |
|
|
183
|
+
|---|---|
|
|
184
|
+
| `TICKET-ID` | mã PRD — **thư mục artifact QC mang tên này** |
|
|
185
|
+
| `active_platform` | `web` \| `app` \| `system` \| … — một QC pass khoá đúng MỘT nền |
|
|
186
|
+
| `qc_artifact_dir` | `{paths.qc_dir}/{TICKET-ID}/{active_platform}/` |
|
|
187
|
+
| `uc_list` | các UC của (PRD × nền) này, kèm trạng thái BDD từng UC |
|
|
188
|
+
|
|
189
|
+
> **Vì sao gom về một chỗ.** Luật phân giải nền từng được copy-paste ở 5 lệnh và câu chữ đã
|
|
190
|
+
> lệch nhau. Năm bản của một luật là nơi drift sống: sửa bốn, quên một, và trạm bị quên ghi
|
|
191
|
+
> artifact vào sai thư mục **trong im lặng**.
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## 1 — `TICKET-ID`
|
|
196
|
+
|
|
197
|
+
Artifact QC gom theo **PRD**, không theo UC. Nên mọi trạm phải quy được về `TICKET-ID`:
|
|
198
|
+
|
|
199
|
+
| `$ARGUMENTS` là | Cách lấy |
|
|
200
|
+
|---|---|
|
|
201
|
+
| **UC-ID** (`{TICKET-ID}-UC{N}`) | phần **trước** `-UC` — đúng luật `steps/gate.md` Bước 1 dùng để tìm tech-doc gộp |
|
|
202
|
+
| **TICKET-ID** | dùng trực tiếp |
|
|
203
|
+
| một **path file** (`.feature` / PRD / design-spec) | phân giải `{domain}` + `{prd-slug}` theo luật `context-loader` Bước 1, rồi lấy `TICKET-ID` từ tên file PRD `{TICKET-ID}-{prd-slug}.md` — file `.md` duy nhất ở gốc feature folder |
|
|
204
|
+
|
|
205
|
+
Đối chiếu: `TICKET-ID` suy ra phải khớp tên file PRD thật. Lệch → **DỪNG**, in cả hai giá
|
|
206
|
+
trị. (Suy sai `TICKET-ID` là ghi cả một PRD vào sai thư mục — không có bước nào phía sau bắt được.)
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## 2 — `active_platform`
|
|
211
|
+
|
|
212
|
+
> **PHẢI phân giải TRƯỚC mọi phép đọc `.feature`.** `{UC-ID}-SC{N}` chỉ độc nhất trong
|
|
213
|
+
> (UC × nền), nên một UC đa nền có **nhiều file `.feature`** — `bdd/web/`, `bdd/app/`,
|
|
214
|
+
> `bdd/system/` — và mỗi file mang `@trace.status` **riêng**: bản web có thể `approved`
|
|
215
|
+
> trong khi bản app còn `draft`. Đọc "file `.feature` của UC" khi chưa biết nền là đọc một
|
|
216
|
+
> file **bất kỳ trong ba**: báo `approved` trong khi bản đang dùng còn nháp, hoặc chặn oan
|
|
217
|
+
> một bản đã duyệt.
|
|
218
|
+
|
|
219
|
+
Theo thứ tự, dừng ở cái đầu tiên khớp:
|
|
220
|
+
|
|
221
|
+
1. `$ARGUMENTS` nêu nền (`web`/`app`/`system`/…) → dùng.
|
|
222
|
+
2. Target là một file `.feature` → đọc `# @trace.platform` của nó.
|
|
223
|
+
3. Glob `{paths.specs_dir}/{domain}/{prd-slug}/bdd/*/` — **đúng một** thư mục nền → dùng nó.
|
|
224
|
+
4. Glob `{paths.qc_dir}/{TICKET-ID}/*/` — **đúng một** thư mục nền đã có artifact → dùng nó.
|
|
225
|
+
*(chỉ dùng cho trạm 2–6; trạm `/qc-analyze` là trạm tạo ra thư mục đó nên không có gì để soi.)*
|
|
226
|
+
5. Nhiều nền mà không suy được → hỏi *"QC pass này cho nền nào? (web/app/system)"*.
|
|
227
|
+
**Có `--yes`:** không hỏi — DỪNG với lỗi rõ ràng, vì đoán bừa nền là ghi artifact vào sai
|
|
228
|
+
thư mục và ghi `qc_status` vào sai sổ trace:
|
|
229
|
+
```
|
|
230
|
+
❌ {TICKET-ID} có {n} nền ({list}) — không suy được nền nào cho QC pass này.
|
|
231
|
+
Chạy headless thì phải nêu tường minh: /{lệnh} {TICKET-ID} web --yes
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Lưu `active_platform`. Từ đây, **mọi** phép đọc `.feature` chỉ đọc thư mục
|
|
235
|
+
`bdd/{active_platform}/` — không trộn SC chéo nền.
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## 3 — `qc_artifact_dir`
|
|
240
|
+
|
|
241
|
+
```
|
|
242
|
+
qc_artifact_dir = {paths.qc_dir}/{TICKET-ID}/{active_platform}/
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
Chứa: `REQUIREMENT_ANALYSIS.md` · `DOC_GAP.md` · `TEST_PLAN.md` · `test-cases/*.Test.md`
|
|
246
|
+
— **mỗi loại đúng MỘT file cho cả PRD**, các UC là mục/hàng bên trong.
|
|
247
|
+
|
|
248
|
+
`{paths.qc_dir}` là folder top-level **nhìn thấy** trong repo QC (mặc định `docs/`, **không**
|
|
249
|
+
phải `.agent/` ẩn) để đội QC mở và xử lý output dễ dàng. Spec chính thức ở lại spec submodule
|
|
250
|
+
của PO — đừng ghi artifact QC vào đó.
|
|
251
|
+
|
|
252
|
+
> **Sổ trace KHÔNG theo layout này.** Nó vẫn là `{paths.trace_dir}/{domain}/{prd-slug}/{UC-ID}-{active_platform}.tsv`
|
|
253
|
+
> — một sổ cho mỗi (UC × nền), vì mỗi hàng là một scenario. Liên kết giữa hai bên đi qua
|
|
254
|
+
> **cột `UC`** của bảng gap, không qua đường dẫn file.
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
## 4 — `uc_list`
|
|
259
|
+
|
|
260
|
+
Glob `{paths.specs_dir}/{domain}/{prd-slug}/bdd/{active_platform}/*.feature`. Mỗi file → một
|
|
261
|
+
UC: đọc `# @trace.id` (mã UC) và `# @trace.status` từ header.
|
|
262
|
+
|
|
263
|
+
Chia hai nhóm:
|
|
264
|
+
|
|
265
|
+
| Nhóm | Điều kiện | Xử lý |
|
|
266
|
+
|---|---|---|
|
|
267
|
+
| **Trong phạm vi** | `@trace.status: approved` | phân tích / thiết kế / chạy bình thường |
|
|
268
|
+
| **Chưa xét** | khác `approved` | **KHÔNG** phân tích; vẫn ghi một hàng vào bảng phạm vi kèm trạng thái thật |
|
|
269
|
+
|
|
270
|
+
In bảng phạm vi ra trước khi làm gì:
|
|
271
|
+
```
|
|
272
|
+
Phạm vi QC — {TICKET-ID} / {active_platform}
|
|
273
|
+
✅ {UC-ID} {tên UC} approved
|
|
274
|
+
⏸ {UC-ID} {tên UC} draft → chưa xét
|
|
275
|
+
→ {n} UC trong phạm vi · {m} chưa xét
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
**Cờ `--include-draft`:** phân tích cả UC chưa duyệt, nhưng **vẫn in bảng trên** và đánh dấu
|
|
279
|
+
trong artifact là dựa trên BDD nháp.
|
|
280
|
+
|
|
281
|
+
**Không UC nào `approved` và không có `--include-draft` → DỪNG:**
|
|
282
|
+
```
|
|
283
|
+
❌ {TICKET-ID} ({active_platform}): 0/{n} UC có BDD approved — không có gì để chạy.
|
|
284
|
+
Cách đúng: người duyệt đặt `# @trace.status: approved` rồi chạy lại.
|
|
285
|
+
Muốn chạy sớm trên BDD nháp (prototype): thêm --include-draft
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
> **Vì sao có `--include-draft` chứ không chặn cứng.** QC sớm trên BDD nháp là một cách dùng
|
|
289
|
+
> **cố ý được cho phép** từ trước (guard cũ là cảnh báo mềm, không phải chặn). Bỏ hẳn nó là
|
|
290
|
+
> lấy đi một năng lực đang có mà không ai khai. Còn để mặc định `approved`-only thì cái
|
|
291
|
+
> thường gặp là cái an toàn, và cái sớm phải nói ra.
|
|
292
|
+
|
|
293
|
+
> **Vì sao `--yes` không thay được `--include-draft`.** `--yes` nghĩa *"tôi không ngồi đây để
|
|
294
|
+
> trả lời"*; `--include-draft` nghĩa *"tôi biết BDD còn nháp và vẫn muốn chạy"*. Gộp hai cái
|
|
295
|
+
> là để một lần chạy headless âm thầm phân tích spec chưa chốt rồi bàn giao như thể đã chốt.
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
> **Trạm này vẫn gọi theo TỪNG UC** *(B11)* — thiết kế và chạy test **thật sự** làm tăng dần
|
|
299
|
+
> theo UC, nên giữ khả năng làm UC1 khi UC3 chưa xong là đúng. Chỉ **chỗ đọc/ghi** đổi: mọi
|
|
300
|
+
> artifact nằm chung ở `{qc_artifact_dir}` cấp PRD, không còn một thư mục mỗi UC.
|
|
301
|
+
>
|
|
302
|
+
> Nên `DOC_GAP.md` / `TEST_PLAN.md` đọc được ở đây phủ **cả PRD**: **lọc theo cột `UC`** để lấy
|
|
303
|
+
> phần của UC đang làm. Đừng coi toàn bộ bảng gap là của UC này — sẽ chặn oan.
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
|
|
175
308
|
---
|
|
176
309
|
|
|
177
310
|
## Role
|
|
@@ -211,7 +344,13 @@ qc-run-test ghi `qc_status` theo từng scenario.
|
|
|
211
344
|
|
|
212
345
|
## Output
|
|
213
346
|
|
|
214
|
-
Ghi các file `.Test.md` dưới `{
|
|
347
|
+
Ghi các file `.Test.md` dưới `{qc_artifact_dir}test-cases/`
|
|
348
|
+
(= `{paths.qc_dir}/{TICKET-ID}/{active_platform}/test-cases/`) — **một thư mục test-case dùng
|
|
349
|
+
chung cho cả PRD**. Tên file mang `<FEATURE>` nên các UC không đâm nhau; cột **Trace SC** là
|
|
350
|
+
chỗ phân biệt TC thuộc UC nào.
|
|
351
|
+
|
|
352
|
+
Dòng `🚫 Block: [GAP-UC{N}-{nnn}](DOC_GAP.md)` trỏ **liên kết tương đối một cấp lên**
|
|
353
|
+
(`DOC_GAP.md` nằm ở thư mục cha của `test-cases/`) — đúng như trước, layout đổi không ảnh hưởng.
|
|
215
354
|
|
|
216
355
|
## Report
|
|
217
356
|
|