@educa-corp/sdd-framework 0.8.1 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/lint-trace.js +200 -1
- package/bin/self-check.js +0 -146
- package/bin/trace-schema.json +12 -3
- package/core/FRAMEWORK_VERSION +1 -1
- package/core/commands/generate-code.md +45 -2
- package/core/commands/propose-scenario.md +1 -1
- package/core/commands/qc-analyze.md +22 -260
- package/core/commands/qc-design-test.md +1 -1
- package/core/commands/qc-plan.md +4 -7
- package/core/commands/qc-run-test.md +1 -1
- package/core/commands/refine-prd.md +20 -47
- package/core/commands/report-bug.md +1 -1
- package/core/commands/review-context.md +1 -27
- package/core/commands/validate-traces.md +178 -3
- package/core/skills/qc/qa-analyst/DOC_GAPS.template.md +63 -0
- package/core/skills/qc/qa-analyst/acceptance-criteria.md +2 -4
- package/core/skills/qc/qa-analyst/business-rules.md +4 -38
- package/core/skills/qc/qa-analyst/data-flow.md +3 -5
- package/core/skills/qc/qa-analyst/spec-breakdown.md +7 -9
- package/core/skills/qc/qa-designer/e2e/journey.md +2 -2
- package/core/skills/qc/qa-designer/exploratory/charter.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 +2 -2
- package/core/skills/qc/qa-designer/functional/gui-feature.md +2 -2
- package/core/skills/qc/qa-designer/functional/gui-screen.md +2 -2
- package/core/skills/qc/qa-designer/integration/api.md +2 -2
- package/core/skills/qc/qa-designer/integration/db.md +2 -2
- package/core/skills/qc/qa-designer/integration/gui.md +2 -2
- package/core/skills/qc/qa-designer/integration/kafka.md +2 -2
- package/core/skills/qc/qa-designer/non-functional.md +2 -2
- package/core/skills/qc/qa-planner/test-plan.md +10 -13
- package/core/skills/qc/qa-reviewer/script/e2e.md +1 -1
- package/core/skills/qc/qa-reviewer/script/exploratory.md +1 -1
- package/core/skills/qc/qa-reviewer/script/functional.md +1 -1
- package/core/skills/qc/qa-reviewer/script/integration.md +1 -1
- package/core/skills/qc/qa-reviewer/script/non-functional.md +1 -1
- package/core/skills/qc/qa-reviewer/test-case/e2e.md +1 -1
- package/core/skills/qc/qa-reviewer/test-case/exploratory.md +1 -1
- package/core/skills/qc/qa-reviewer/test-case/functional.md +1 -1
- package/core/skills/qc/qa-reviewer/test-case/integration.md +2 -2
- package/core/skills/qc/qa-reviewer/test-case/non-functional.md +1 -1
- package/core/skills/qc/qa-runner/e2e.md +1 -1
- package/core/skills/qc/qa-runner/exploratory/session.md +1 -1
- package/core/skills/qc/qa-runner/functional/api.md +1 -1
- 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/skills/qc/qa-runner/integration.md +1 -1
- package/core/skills/qc/qa-runner/non-functional.md +1 -1
- package/core/skills/qc/qa-runner/report/report.md +1 -1
- package/core/steps/review-fanout.md +1 -27
- package/core/templates/project-context.yaml +2 -2
- package/docs/02-concepts/pipeline-steps/08-qc-automation.md +2 -2
- package/docs/04-reference/commands.md +1 -1
- package/docs/explain/03-refine-prd.md +6 -8
- package/docs/explain/15-qc-analyze.md +7 -10
- package/docs/explain/16-qc-plan.md +2 -2
- package/package.json +3 -2
- package/bin/qc-base-map.json +0 -595
- package/core/skills/qc/qa-analyst/DOC_GAP.template.md +0 -117
- package/core/skills/qc/qa-analyst/exhaustive-gap-scanner.md +0 -174
- package/core/skills/qc/qa-analyst/spec-issue-reporter.md +0 -100
- package/core/skills/qc/qa-planner/risk-model.md +0 -106
- package/core/steps/gap-verify.md +0 -231
- package/docs/plans/qc-implementation-log.md +0 -1446
- package/docs/plans/qc-merge-plan.md +0 -502
- package/docs/plans/qc-sync-command.md +0 -358
|
@@ -9,9 +9,6 @@ ported_from: ai-automation-qc-base
|
|
|
9
9
|
> Stage 1 của QC automation pipeline native (qc-analyze → qc-plan → qc-design-test → qc-review → qc-run-test → qc-report). Port từ qa-analyst của team QC. Markdown-first: không có script ở đây.
|
|
10
10
|
|
|
11
11
|
## Gate
|
|
12
|
-
|
|
13
|
-
*Checkpoint: **chặn thường** — lệnh ghi 2 file artifact. `--yes` bỏ qua được (gate Bước 3a).*
|
|
14
|
-
|
|
15
12
|
# Gate — Quy trình vào chuẩn cho mọi lệnh
|
|
16
13
|
|
|
17
14
|
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ó.
|
|
@@ -165,7 +162,7 @@ Mỗi dòng ⚠️/🔴 phải ứng với một trạng thái **context-loader
|
|
|
165
162
|
🔴/⚠️ (không chặn ≠ không báo — người đọc log sau này vẫn cần thấy).
|
|
166
163
|
|
|
167
164
|
|
|
168
|
-
*Lưu ý: Với lệnh này, target ở Bước 1 là một UC-ID hoặc file feature/PRD. Đọc spec chính thức của UC đó — 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ó ở
|
|
165
|
+
*Lưu ý: Với lệnh này, target ở Bước 1 là một UC-ID hoặc file feature/PRD. Đọc spec chính thức của UC đó — 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ó ở đó.*
|
|
169
166
|
|
|
170
167
|
## Context
|
|
171
168
|
**BẮT BUỘC — đọc `.agent/steps/context-loader.md` và thực thi TOÀN BỘ quy trình trong đó**,
|
|
@@ -177,103 +174,30 @@ placeholder bên dưới sẽ rỗng và lệnh sẽ đọc/ghi sai chỗ.
|
|
|
177
174
|
|
|
178
175
|
---
|
|
179
176
|
|
|
180
|
-
## Platform Resolution *(thiết lập cho cả QC pass — mọi stage sau kế thừa)*
|
|
181
|
-
|
|
182
|
-
> **PHẢI chạy TRƯỚC Guard bên dưới.** `{UC-ID}-SC{N}` chỉ độc nhất trong (UC × platform), nên
|
|
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.
|
|
188
|
-
|
|
189
|
-
`{UC-ID}-SC{N}` chỉ độc nhất trong (UC × platform) — `web SC3` và `app SC3` là hai scenario khác nhau, và sổ trace tách theo `{UC-ID}-{platform}.tsv`. Nên **một QC pass khoá đúng MỘT platform**, và mọi artifact QC nằm dưới `{paths.qc_dir}/{UC-ID}/{active_platform}/`.
|
|
190
|
-
|
|
191
|
-
Phân giải `active_platform` — theo thứ tự, dừng ở cái đầu tiên khớp:
|
|
192
|
-
1. `$ARGUMENTS` nêu platform (`web`/`app`/`system`) → dùng.
|
|
193
|
-
2. Target ở Bước 1 là một file `.feature` → đọc `# @trace.platform` của nó.
|
|
194
|
-
3. Glob `{paths.specs_dir}/{domain}/{prd-slug}/bdd/*/` — **đúng một** thư mục platform tồn tại → dùng nó.
|
|
195
|
-
4. Nhiều platform mà không suy được → hỏi *"QC pass này cho platform nào? (web/app/system)"*.
|
|
196
|
-
**Có `--yes`:** không hỏi — dừng với lỗi rõ ràng, vì đoán bừa platform là ghi artifact vào sai
|
|
197
|
-
thư mục và ghi `qc_status` vào sai sổ trace:
|
|
198
|
-
```
|
|
199
|
-
❌ {UC-ID} có {n} platform ({list}) — không suy được platform nào cho QC pass này.
|
|
200
|
-
Chạy headless thì phải nêu tường minh: /qc-analyze {UC-ID} web --yes
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
Lưu `active_platform`. Đọc **đúng file `.feature` của platform đó** (`{paths.specs_dir}/{domain}/{prd-slug}/bdd/{active_platform}/{UC-ID}*.feature`) làm nguồn SC — không trộn SC chéo platform.
|
|
204
|
-
|
|
205
|
-
---
|
|
206
|
-
|
|
207
177
|
## Guard — BDD đã duyệt chưa
|
|
208
178
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
Đọc `# @trace.status:` từ header file `.feature` **của `{active_platform}` đã phân giải**:
|
|
179
|
+
Đọc `# @trace.status:` từ header file `.feature` của UC target:
|
|
212
180
|
- `approved` → tiếp tục bình thường.
|
|
213
181
|
- `draft` (hoặc khác `approved`) → **CHECKPOINT cảnh báo mềm** (không chặn cứng — cho phép QC sớm/prototype):
|
|
214
182
|
```
|
|
215
|
-
⚠️ BDD của {UC-ID}
|
|
183
|
+
⚠️ BDD của {UC-ID} đ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
184
|
Khuyến nghị: review-context (BDD) sạch + người duyệt đặt `# @trace.status: approved` rồi mới chạy QC.
|
|
217
185
|
Vẫn chạy QC bây giờ? (Y/N)
|
|
218
186
|
```
|
|
219
|
-
Chỉ tiếp khi chọn Y
|
|
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).
|
|
221
|
-
|
|
222
|
-
> **Vì sao `--yes` phải phủ cả guard mềm này.** `steps/gate.md` mở đường chạy headless
|
|
223
|
-
> (`claude -p "… --yes"`), nhưng `--yes` chỉ khai là bỏ qua CHECKPOINT của gate. Guard mềm ở đây
|
|
224
|
-
> là một `(Y/N)` thứ hai — nên lệnh vẫn treo vô hạn ở chế độ không có người trả lời, và đường
|
|
225
|
-
> headless mà gate hứa bị bít cho đúng lệnh này. Một cổng chỉ chặn được khi có người ngồi đó
|
|
226
|
-
> thì ở chế độ headless nó không phải cổng, nó là treo.
|
|
187
|
+
Chỉ tiếp khi chọn Y.
|
|
227
188
|
|
|
228
189
|
---
|
|
229
190
|
|
|
230
|
-
##
|
|
231
|
-
|
|
232
|
-
Đị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** — lọc theo `@trace.ucs` ở header, chỉ đọc phần chạm `{UC-ID}` đang xét.
|
|
234
|
-
|
|
235
|
-
**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
|
-
```
|
|
237
|
-
⚠️ Không có tech-doc cho {TICKET-ID} — phân tích chỉ dựa trên PRD + BDD + design-spec.
|
|
238
|
-
Lệch giữa yêu cầu nghiệp vụ và hợp đồng kỹ thuật (enum, mã lỗi, ràng buộc field) sẽ KHÔNG được phát hiện ở trạm này.
|
|
239
|
-
```
|
|
240
|
-
|
|
241
|
-
**Có → đối chiếu các mục sau với PRD/BDD, mỗi chỗ vênh là một gap `CONTRADICTORY`:**
|
|
242
|
-
|
|
243
|
-
| Mục tech-doc | Đối chiếu gì với PRD/BDD |
|
|
244
|
-
|---|---|
|
|
245
|
-
| §3 Mô hình dữ liệu | thực thể/field/quan hệ PRD nhắc tới có khớp không |
|
|
246
|
-
| **§4 Hợp đồng API** | **enum & tập giá trị hợp lệ** · ràng buộc field (độ dài, định dạng, bắt buộc) · **mã lỗi** — PRD nêu bao nhiêu nhánh lỗi, contract định nghĩa bao nhiêu |
|
|
247
|
-
| §4.5 Ánh xạ component UI | màn/component PRD·design-spec mô tả có mặt đủ không |
|
|
248
|
-
| §5 Luồng chính | thứ tự bước, nhánh rẽ có khớp scenario `.feature` không |
|
|
249
|
-
| §6 Điểm tích hợp | side-effect PRD nêu (gửi sự kiện, gọi dịch vụ khác) có được định nghĩa không |
|
|
250
|
-
| §8 Xử lý lỗi & biên | trường hợp biên PRD nêu có đường xử lý không, và ngược lại |
|
|
251
|
-
|
|
252
|
-
> **Vì sao mục này tồn tại.** Có một lớp gap **chỉ lộ ra khi so hai loại tài liệu với nhau** —
|
|
253
|
-
> đọc riêng bên nào cũng thấy hợp lý. Ca điển hình: PRD viết *"chọn lớp 1–6"*, contract định
|
|
254
|
-
> nghĩa enum `1..9`. Không ai đọc cả hai thì không ai thấy, và nó ra tận lúc chạy thật.
|
|
255
|
-
> **Đây là lý do trạm này đọc tech-doc — không phải để hiểu kỹ thuật, mà để bắt chỗ hai bên nói khác nhau.**
|
|
256
|
-
|
|
257
|
-
### §12 GAP Register — ĐỌC, KHÔNG GHI
|
|
258
|
-
|
|
259
|
-
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
|
-
`/generate-code` đã canh nó. **Trạm này chỉ đọc, tuyệt đối không ghi vào.**
|
|
191
|
+
## Platform Resolution *(thiết lập cho cả QC pass — mọi stage sau kế thừa)*
|
|
261
192
|
|
|
262
|
-
|
|
263
|
-
- **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.
|
|
265
|
-
- 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.
|
|
193
|
+
`{UC-ID}-SC{N}` chỉ độc nhất trong (UC × platform) — `web SC3` và `app SC3` là hai scenario khác nhau, và sổ trace tách theo `{UC-ID}-{platform}.tsv`. Nên **một QC pass khoá đúng MỘT platform**, và mọi artifact QC nằm dưới `{paths.qc_dir}/{UC-ID}/{active_platform}/`.
|
|
266
194
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
> khác chưa?"*), chỉ mở rộng phạm vi "tài liệu khác" thêm một nguồn.
|
|
195
|
+
Phân giải `active_platform`:
|
|
196
|
+
- Target ở Bước 1 là một file `.feature` → đọc `# @trace.platform` của nó.
|
|
197
|
+
- `$ARGUMENTS` nêu platform (`web`/`app`/`system`) → dùng.
|
|
198
|
+
- Ngược lại → hỏi: *"QC pass này cho platform nào? (web/app/system)"* và chờ chọn.
|
|
272
199
|
|
|
273
|
-
|
|
274
|
-
`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`, trỏ ngược về `{id}` của §12 để
|
|
276
|
-
không đếm hai lần.
|
|
200
|
+
Lưu `active_platform`. Đọc **đúng file `.feature` của platform đó** (`{paths.specs_dir}/{domain}/{prd-slug}/bdd/{active_platform}/{UC-ID}*.feature`) làm nguồn SC — không trộn SC chéo platform.
|
|
277
201
|
|
|
278
202
|
---
|
|
279
203
|
|
|
@@ -304,204 +228,42 @@ File `.feature` chính thức đã định nghĩa scenario là `@trace.scenario=
|
|
|
304
228
|
và ghi lại mapping — qc-design-test và qc-run-test cần nó để gắn tag
|
|
305
229
|
`@trace.verifies` cho test và ghi `qc_status` theo từng scenario.
|
|
306
230
|
|
|
307
|
-
##
|
|
308
|
-
|
|
309
|
-
Gap đến từ **hai chỗ**, và chúng bổ sung nhau chứ không thay thế:
|
|
310
|
-
|
|
311
|
-
| Nguồn | Trả lời câu | Gap là |
|
|
312
|
-
|---|---|---|
|
|
313
|
-
| **4 kỹ năng phân tích** ở trên | *"yêu cầu là gì?"* | sản phẩm phụ — đang bóc luật nghiệp vụ thì gặp chỗ mâu thuẫn |
|
|
314
|
-
| **Quét theo lăng kính** *(dưới đây)* | *"còn thiếu gì?"* | mục tiêu chính |
|
|
315
|
-
|
|
316
|
-
### Quét theo lăng kính
|
|
317
|
-
|
|
318
|
-
Chạy `steps/review-fanout.md` với:
|
|
231
|
+
## DOC_GAPS (bắt buộc)
|
|
319
232
|
|
|
320
|
-
|
|
321
|
-
|---|---|
|
|
322
|
-
| `DIMENSIONS` | **4 lăng kính** — `D2 Xử lý lỗi` · `D3 Giao diện` · `D4 Dữ liệu & cấu hình` · `D5 Đối chiếu chéo` **(thu hẹp — xem dưới)** *(định nghĩa ở `{paths.qc_skills_dir}/qa-analyst/exhaustive-gap-scanner.md`)* |
|
|
323
|
-
| `FINDINGS SCHEMA` | như §Output dưới đây |
|
|
324
|
-
| `GRANULARITY` | **`auto`** — chia theo ngưỡng kích thước, KHÔNG ép mịn theo từng UC |
|
|
325
|
-
| `VERIFY` | **`off`** — thẩm định chạy MỘT lần ở bước sau, trên tập đã gộp |
|
|
326
|
-
|
|
327
|
-
**`D5` chạy ở dạng THU HẸP — chỉ 2 trong 4 cặp tài liệu:**
|
|
328
|
-
|
|
329
|
-
| Cặp | |
|
|
330
|
-
|---|---|
|
|
331
|
-
| `PRD ↔ design-spec/` | ✅ **SO** — không ai đối chiếu nội dung. `/generate-bdd` chỉ kiểm `Built from PRD` (số phiên bản); cùng phiên bản mà nội dung lệch thì lọt |
|
|
332
|
-
| `bdd/{platform}/ ↔ design-spec/` | ✅ **SO** — không ai |
|
|
333
|
-
| `PRD ↔ bdd/` | ❌ bỏ — `/review-context` **B1** đã làm |
|
|
334
|
-
| `PRD·bdd/ ↔ tech-docs/` | ❌ bỏ — §Đối chiếu tài liệu kỹ thuật **ở trên** đã làm |
|
|
335
|
-
|
|
336
|
-
> **Cả hai cặp SO đều dính `design-spec/`** — artifact duy nhất trong feature package mà **không
|
|
337
|
-
> tài liệu nào đối chiếu nội dung với nó**. Đừng lẫn với `tech-docs/`: `design-spec/` là *giao diện
|
|
338
|
-
> Designer vẽ*, `tech-docs/` là *hợp đồng hệ thống* — và `tech-docs/` đã được phủ ở §trên.
|
|
339
|
-
>
|
|
340
|
-
> Trạm này **đã đọc `design-spec/`** từ trước (nó nằm trong danh sách nguồn ở Gate), nên `D5`
|
|
341
|
-
> không nạp thêm file nào — chỉ bắt nó **so** thay vì chỉ **đọc**. Rẻ hơn một lăng kính thường.
|
|
342
|
-
|
|
343
|
-
**`D1 Luật nghiệp vụ` là lăng kính duy nhất KHÔNG bật:** `qa-analyst/business-rules.md` đã hỏi
|
|
344
|
-
4/5 câu của nó, và hỏi cụ thể hơn — *"min/max · ký tự cho phép · trim · định dạng"* thay vì
|
|
345
|
-
*"ngưỡng đã chốt chưa"*.
|
|
346
|
-
|
|
347
|
-
> **Ghi lại vì sao `D5` từng bị tắt:** lý do ban đầu là *"trùng nhiều"* — **đúng một nửa**. Nó phủ
|
|
348
|
-
> **bốn** cặp, chỉ **hai** cặp đã có người làm. Sai vì suy từ ấn tượng thay vì đếm danh sách; bảng
|
|
349
|
-
> kiểm chứng 31 câu hỏi (`docs/plans/qc-implementation-log.md`) là thứ đáng lẽ phải làm **trước**
|
|
350
|
-
> khi quyết. Đừng tắt lại `D5` mà không đọc bảng đó.
|
|
351
|
-
|
|
352
|
-
> **`GRANULARITY = auto`, không phải `per-uc`.** `/refine-prd` ép mịn theo từng UC vì ở tầng PRD
|
|
353
|
-
> một gap bỏ sót **im lặng đi tiếp** tới tận lúc chạy thật. Ở đây khác: gap bỏ sót còn **bốn lớp
|
|
354
|
-
> chặn phía sau** — trạm 3 bật ngược khi không viết nổi giá trị mong đợi, trạm 4 soát độ phủ,
|
|
355
|
-
> trạm 5 phân loại lỗi thật vs script sai. Ép mịn ở đây tốn gấp ~3 lần cho tính năng nhỏ mà đổi
|
|
356
|
-
> lấy một lưới an toàn đã có sẵn ba lớp khác.
|
|
357
|
-
|
|
358
|
-
### Gộp trước, thẩm định sau
|
|
359
|
-
|
|
360
|
-
Gộp gap từ **cả hai nguồn** vào một tập trước khi sang bước thẩm định.
|
|
361
|
-
|
|
362
|
-
> **Không thẩm định từng nguồn riêng.** Phép kiểm `T6` của `gap-verify` là *"hai gap cùng gốc
|
|
363
|
-
> thì gộp lại"* — nó chỉ chạy được khi **thấy toàn bộ** tập. Thẩm định hai lần trên hai tập rời
|
|
364
|
-
> thì không bắt được trùng lặp chéo nguồn, và PO nhận hai câu hỏi giống nhau.
|
|
365
|
-
|
|
366
|
-
---
|
|
367
|
-
|
|
368
|
-
## DOC_GAP (bắt buộc)
|
|
369
|
-
|
|
370
|
-
Luôn tạo một file gaps theo `{paths.qc_skills_dir}/qa-analyst/DOC_GAP.template.md`:
|
|
233
|
+
Luôn tạo một file gaps theo `{paths.qc_skills_dir}/qa-analyst/DOC_GAPS.template.md`:
|
|
371
234
|
- Mỗi gap `GAP-xx`, phân loại MISSING / AMBIGUOUS / CONTRADICTORY / ASSUMPTION / OPEN QUESTION, với severity (🔴 Blocker → 🟢 Low) và function/BR/AC bị ảnh hưởng.
|
|
372
235
|
- Không bao giờ bịa câu trả lời; đánh dấu giả định là `ASSUMPTION` để PO/dev confirm.
|
|
373
236
|
- Bất kỳ `🔴 Blocker` nào còn `Open` ⇒ UC chưa sẵn sàng cho qc-design-test — bàn giao cho qc-plan.
|
|
374
237
|
- **Đẩ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
238
|
trong spec chính thức — `AMBIGUOUS` / `CONTRADICTORY` / `MISSING` trong PRD/BDD — phải tới
|
|
376
|
-
PO qua feedback flow, không chỉ nằm trong `
|
|
239
|
+
PO qua feedback flow, không chỉ nằm trong `DOC_GAPS.md`: tạo `/report-bug {UC-ID} {desc}`
|
|
377
240
|
(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
241
|
coverage. Gap `ASSUMPTION` / `OPEN QUESTION` được confirm qua questions-for-dev của qc-plan — không file thành bug.
|
|
379
242
|
|
|
380
|
-
### Thẩm định trước khi bàn giao *(bắt buộc)*
|
|
381
|
-
|
|
382
|
-
Sinh xong `DOC_GAP.md`, **đọc `.agent/steps/gap-verify.md` và chạy toàn bộ quy trình trong đó**
|
|
383
|
-
với:
|
|
384
|
-
- `FINDINGS` = mọi gap đang `Open` trong `DOC_GAP.md`
|
|
385
|
-
- `EVIDENCE_ROOT` = `{paths.specs_dir}` — spec repo của PO, **không** phải `{paths.qc_dir}`
|
|
386
|
-
- `VERDICT_FIELD` = cột `Trạng thái` + `Câu trả lời` của bảng gap
|
|
387
|
-
- `RERATE` = `on`
|
|
388
|
-
|
|
389
|
-
Gap rớt thẩm định được **đóng kèm lý do**, KHÔNG xoá — người đọc phải kiểm chứng được vì sao
|
|
390
|
-
nó bị loại. Cập nhật `Tổng số gap` + bảng ưu tiên sau khi áp verdict, và in khối
|
|
391
|
-
`[GAP VERIFY]` + cam kết cuối vào report.
|
|
392
|
-
|
|
393
|
-
> **Vì sao bắt buộc, không phải tuỳ chọn.** Bước phân tích ở trên chỉ có lực **tìm thêm** —
|
|
394
|
-
> bốn skill lần lượt quét spec và mỗi cái đều được khuyến khích ghi ra chỗ nghi ngờ. Không có
|
|
395
|
-
> bước nào hỏi ngược *"cái vừa ghi có thật không?"*. Hệ quả đo được ở đội QC: phần lớn gap sinh
|
|
396
|
-
> ra là gap ảo — spec đã trả lời ở tài liệu khác, hoặc trích dẫn sai, hoặc là chuyện QC tự quyết
|
|
397
|
-
> được. Mà gap ảo không chỉ tốn thời gian PO: nó **làm PO mất tin vào cả danh sách**, và lúc đó
|
|
398
|
-
> những gap thật cũng chết theo. `gap-verify` là bộ lọc duy nhất đứng giữa hai chuyện đó.
|
|
399
|
-
|
|
400
243
|
## Output
|
|
401
244
|
|
|
402
|
-
Ghi
|
|
245
|
+
Ghi **đúng HAI file** dưới `{paths.qc_dir}/{UC-ID}/{active_platform}/` — **đừng** tách phân tích
|
|
403
246
|
thành một-file-mỗi-bước (không có file spec-breakdown / business-rules / data-flow / AC riêng):
|
|
404
247
|
|
|
405
248
|
1. **`{paths.qc_dir}/{UC-ID}/{active_platform}/REQUIREMENT_ANALYSIS.md`** — bản phân tích hợp nhất duy nhất.
|
|
406
249
|
Section theo thứ tự: phân rã requirement → bảng business-rule (`BR-xx`) → data-flow →
|
|
407
250
|
acceptance-criteria (`AC-xx`), mỗi `BR`/`AC` map tới `{UC-ID}-SC{N}` (của `.feature` platform này) sở hữu nó.
|
|
408
|
-
|
|
409
|
-
(`{id}` · điều chưa biết · owner · severity). Rỗng thì ghi "Không có"; **đừng bỏ mục**.
|
|
410
|
-
2. **`{paths.qc_dir}/{UC-ID}/{active_platform}/DOC_GAP.md`** — file gap, theo
|
|
411
|
-
`{paths.qc_skills_dir}/qa-analyst/DOC_GAP.template.md` + luật viết ở
|
|
412
|
-
`{paths.qc_skills_dir}/qa-analyst/spec-issue-reporter.md`. Bắt buộc:
|
|
413
|
-
- **Bảng 10 cột** đúng thứ tự, có cột **Giao cho đội** (Dev / PO / BA / Design / Kiến trúc / Dữ liệu).
|
|
414
|
-
- Ô 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
|
-
*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
|
-
- Section **"Tài liệu đầu vào đã đọc để phân tích"** đặt ngay sau metadata — liệt kê **đủ** mọi
|
|
417
|
-
file đã mở. Đây là căn cứ độ phủ: không có nó thì không ai phân biệt được *"đã đọc và không thấy"*
|
|
418
|
-
với *"chưa đọc"*.
|
|
419
|
-
- Mức nặng nhất dùng từ **`🔴 Blocker`** (không phải `Critical`) — `/qc-run-test` đọc đúng từ này
|
|
420
|
-
để đặt *"scenario đang chờ PO"* vào sổ trace.
|
|
421
|
-
3. **`{paths.refinement_dir}/{UC-ID}-qa-findings.yaml`** — **cùng dữ liệu gap**, ở định dạng Review Board đọc được. Xem §Bản findings dưới đây.
|
|
251
|
+
2. **`{paths.qc_dir}/{UC-ID}/{active_platform}/DOC_GAPS.md`** — file gaps (theo `{paths.qc_skills_dir}/qa-analyst/DOC_GAPS.template.md`).
|
|
422
252
|
|
|
423
253
|
`{paths.qc_dir}` là folder top-level NHÌN THẤY trong QC repo (mặc định `docs/`, **không** phải
|
|
424
254
|
`.agent/review/` ẩn) để team QC mở và xử lý output dễ dàng. Spec chính thức ở lại
|
|
425
255
|
spec submodule của PO — đừng ghi phân tích vào đó.
|
|
426
256
|
|
|
427
|
-
### Bản findings — một nguồn, hai mặt
|
|
428
|
-
|
|
429
|
-
File `.yaml` và `DOC_GAP.md` là **cùng một tập gap**, không phải hai tập. Sinh `DOC_GAP.md`
|
|
430
|
-
trước (nó là bản người đọc), rồi **render** sang `.yaml` — đừng phân tích lại lần hai.
|
|
431
|
-
|
|
432
|
-
Dùng **đúng schema của `/refine-prd`** để Review Board đọc được cả hai loại file:
|
|
433
|
-
|
|
434
|
-
```yaml
|
|
435
|
-
prd_source: "{paths.specs_dir}/{domain}/{prd-slug}/{TICKET-ID}-{prd-slug}.md"
|
|
436
|
-
uc_id: "{UC-ID}"
|
|
437
|
-
platform: "{active_platform}"
|
|
438
|
-
generated_at: "{ISO datetime}"
|
|
439
|
-
generated_by: "qc-analyze"
|
|
440
|
-
status: "pending_review"
|
|
441
|
-
|
|
442
|
-
findings:
|
|
443
|
-
- id: "F001"
|
|
444
|
-
lens: "QA" # LUÔN là QA — file này chỉ có một lăng kính
|
|
445
|
-
severity: "critical" # critical | major | minor ← map từ 🔴/🟠/🟡⚪ của DOC_GAP
|
|
446
|
-
section: "{section PRD/BDD chứa vấn đề}"
|
|
447
|
-
uc_id: "{UC-ID}"
|
|
448
|
-
quote: "{trích nguyên văn ≤120 ký tự từ spec tại đúng chỗ}"
|
|
449
|
-
finding: "{gap là gì}"
|
|
450
|
-
suggestion: "{cần PO/BA làm rõ điều gì}"
|
|
451
|
-
resolution_edge_cases: [] # để [] — phân tích bậc-hai là việc của /refine-prd
|
|
452
|
-
auto_fixable: false # LUÔN false — xem cảnh báo dưới
|
|
453
|
-
status: "pending"
|
|
454
|
-
applied_via: ""
|
|
455
|
-
gap_ref: "GAP-xx" # trỏ ngược về hàng trong DOC_GAP.md
|
|
456
|
-
|
|
457
|
-
summary:
|
|
458
|
-
total_findings: {N}
|
|
459
|
-
by_severity: { critical: {N}, major: {N}, minor: {N} }
|
|
460
|
-
by_lens: { QA: {N} }
|
|
461
|
-
recommendation: "APPROVED_WITH_MINOR_CHANGES | NEEDS_REVISION | BLOCKED"
|
|
462
|
-
```
|
|
463
|
-
|
|
464
|
-
> **`auto_fixable` LUÔN `false`, và KHÔNG có `--resume` cho file này.**
|
|
465
|
-
>
|
|
466
|
-
> Review Board có nút *"chấp nhận rồi tự sửa PRD"*. Với gap của `/refine-prd` thì đúng — nó chạy
|
|
467
|
-
> ở **thời điểm PRD**, sửa PRD lúc đó là sửa đúng chỗ đúng lúc.
|
|
468
|
-
>
|
|
469
|
-
> Gap của lệnh này phát hiện **sau khi code đã xong**. Tự sửa PRD ở thời điểm đó là **sửa sau lưng
|
|
470
|
-
> cả dây chuyền**: BDD sinh từ PRD cũ, code sinh từ BDD đó, sổ kết quả kiểm thử neo vào scenario
|
|
471
|
-
> của BDD đó. Đổi PRD mà không đi lại đường ấy thì mọi thứ phía sau nói dối.
|
|
472
|
-
>
|
|
473
|
-
> Đường đúng vẫn là kênh đã có: `/report-bug` cho defect spec thật, `/propose-scenario` cho thiếu
|
|
474
|
-
> độ phủ. File `.yaml` này để **PO đọc và quyết trong một chỗ quen**, không phải để máy tự áp.
|
|
475
|
-
|
|
476
|
-
**File riêng, không ghi chung với `/refine-prd`.** Tên có `{UC-ID}` nên không đụng
|
|
477
|
-
`{prd-slug}-findings.yaml`. Ghi chung sẽ phá trường `applied_to_version` mà `/refine-prd` dùng để
|
|
478
|
-
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
|
-
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
|
-
|
|
481
|
-
---
|
|
482
|
-
|
|
483
257
|
## Report
|
|
484
258
|
|
|
485
259
|
**Đọc `.agent/steps/report-footer.md`** và áp đúng khuôn footer trong đó (Status Badge ·
|
|
486
260
|
Output Artifacts · Next) cho report cuối, kèm khối bên dưới.
|
|
487
261
|
|
|
488
262
|
```
|
|
489
|
-
/qc-analyze Hoàn tất — {UC-ID}
|
|
490
|
-
Files
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
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) ← blocker là spec-defect? → /report-bug {UC-ID} | coverage gap → /propose-scenario {UC-ID}
|
|
497
|
-
Chờ chốt: {G} ẩn số §12 tech-doc đang open chạm UC này (đã ghi vào REQUIREMENT_ANALYSIS, KHÔNG hỏi lại PO)
|
|
498
|
-
SC map: {M} BR/AC map tới {K} scenario
|
|
499
|
-
Next : /qc-plan {UC-ID} {active_platform} ← rủi ro / what-if / câu hỏi cho dev
|
|
500
|
-
(giải quyết các gap 🔴 Blocker với PO/Dev trước)
|
|
263
|
+
/qc-analyze Hoàn tất — {UC-ID}
|
|
264
|
+
Files: {paths.qc_dir}/{UC-ID}/{active_platform}/REQUIREMENT_ANALYSIS.md + DOC_GAPS.md (2 files)
|
|
265
|
+
Gaps: {N} ({blockers} blocker) ← blocker là spec-defect? → /report-bug {UC-ID} | coverage gap → /propose-scenario {UC-ID}
|
|
266
|
+
SC mapping: {M} BR/AC map tới {K} scenario
|
|
267
|
+
Next: /qc-plan {UC-ID} ← risk / what-if / questions-for-dev
|
|
268
|
+
(giải quyết các gap 🔴 Blocker với PO/Dev trước)
|
|
501
269
|
```
|
|
502
|
-
|
|
503
|
-
> **Dòng `Next` là bắt buộc in, không phải trang trí.** Dây gốc của đội QC ra **cả** file gap
|
|
504
|
-
> **và** kế hoạch test trong một lần chạy (13/14 lần đo được ở repo của họ). Ở framework đó là
|
|
505
|
-
> **hai lệnh**. Người quen dây cũ sẽ dừng lại ở đây và tưởng đã xong — dòng này là chỗ duy nhất
|
|
506
|
-
> nói cho họ biết còn một bước nữa.
|
|
507
|
-
|
|
@@ -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. **Phân giải `active_platform`** (QC pass khoá 1 platform): nếu `$ARGUMENTS` nêu platform → dùng; else glob `{paths.qc_dir}/{UC-ID}/*/` — đúng 1 folder platform → dùng nó, nhiều folder → hỏi. Đọc output của qc-analyze + qc-plan (`REQUIREMENT_ANALYSIS.md`, `
|
|
165
|
+
*Lưu ý: Với lệnh này, target ở Bước 1 là một UC-ID. **Phân giải `active_platform`** (QC pass khoá 1 platform): nếu `$ARGUMENTS` nêu platform → dùng; else glob `{paths.qc_dir}/{UC-ID}/*/` — đúng 1 folder platform → dùng nó, nhiều folder → hỏi. Đọc output của qc-analyze + qc-plan (`REQUIREMENT_ANALYSIS.md`, `DOC_GAPS.md`, `TEST_PLAN.md`) từ `{paths.qc_dir}/{UC-ID}/{active_platform}/` 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 đó**,
|
package/core/commands/qc-plan.md
CHANGED
|
@@ -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. **Phân giải `active_platform`** (QC pass khoá 1 platform — artifact dưới `{paths.qc_dir}/{UC-ID}/{active_platform}/`): nếu `$ARGUMENTS` nêu platform (web/app/system) → dùng; else glob `{paths.qc_dir}/{UC-ID}/*/` — đúng 1 folder platform → dùng nó, nhiều folder → hỏi platform nào. Đọc output của qc-analyze (`REQUIREMENT_ANALYSIS.md` + `
|
|
165
|
+
*Lưu ý: Với lệnh này, target ở Bước 1 là một UC-ID. **Phân giải `active_platform`** (QC pass khoá 1 platform — artifact dưới `{paths.qc_dir}/{UC-ID}/{active_platform}/`): nếu `$ARGUMENTS` nêu platform (web/app/system) → dùng; else glob `{paths.qc_dir}/{UC-ID}/*/` — đúng 1 folder platform → dùng nó, nhiều folder → hỏi platform nào. Đọc output của qc-analyze (`REQUIREMENT_ANALYSIS.md` + `DOC_GAPS.md`) từ `{paths.qc_dir}/{UC-ID}/{active_platform}/` và file `.feature` của đúng platform đó.*
|
|
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 đó**,
|
|
@@ -183,12 +183,9 @@ thiết kế test case cụ thể (đó là qc-design-test).
|
|
|
183
183
|
|
|
184
184
|
## Skills (`{paths.qc_skills_dir}/qa-planner/`)
|
|
185
185
|
|
|
186
|
-
- `test-plan.md` —
|
|
187
|
-
e2e / non-functional),
|
|
188
|
-
suy ra từ `
|
|
189
|
-
- `risk-model.md` — **cách tính** mức rủi ro: 7 nguồn rủi ro · khả năng × thiệt hại → P0–P3 ·
|
|
190
|
-
và dùng mức đó chia **độ sâu** test. `test-plan.md` có khung bảng `§6`; file này là cách điền.
|
|
191
|
-
Nạp cùng lúc, không phải thay thế.
|
|
186
|
+
- `test-plan.md` — tự đủ: risk matrix, what-if, scope theo từng test layer
|
|
187
|
+
(functional / integration / e2e / non-functional), entry/exit criteria, và
|
|
188
|
+
danh sách questions-for-dev suy ra từ `DOC_GAPS.md`.
|
|
192
189
|
|
|
193
190
|
## Output
|
|
194
191
|
|
|
@@ -225,7 +225,7 @@ Sau khi chạy, cập nhật **sổ của platform đang test** `{paths.trace_di
|
|
|
225
225
|
| `qc_status` | Đọc cột `status` của row **TRƯỚC** — xem §Guard ngay dưới bảng. Row `OK`/`GAP`/`UNTRACKED`: `pass` nếu mọi QC test của SC này pass · `fail` nếu có cái fail · `skip` nếu tất cả skip/xfail · `not_run` nếu không QC test nào phủ nó. Row **`DRIFT`/`ORPHANED`**: **không bao giờ ghi `pass`** — hạ về `not_run` |
|
|
226
226
|
| `qc_run_at` | hôm nay `YYYY-MM-DD` |
|
|
227
227
|
| `last_updated` | hôm nay `YYYY-MM-DD` |
|
|
228
|
-
| `qc_owner` | **SC đang chờ ai** (view "pending" của PM/PO): `dev` nếu FAIL = product-gap (defect thật → dev fix) · `po` nếu `skip`/`not_run` vì một **`
|
|
228
|
+
| `qc_owner` | **SC đang chờ ai** (view "pending" của PM/PO): `dev` nếu FAIL = product-gap (defect thật → dev fix) · `po` nếu `skip`/`not_run` vì một **`DOC_GAPS` 🔴 Blocker đang open** chặn test (PO phải làm rõ PRD/BDD) · `—` nếu `pass`, hoặc FAIL = script-bug (QC tự fix — tạm thời) |
|
|
229
229
|
| `qc_blocked_by` | artifact liên kết: `GAP-{id}` khi bị chặn bởi spec gap (set ở đây) · `BUG-{id}` khi `/report-bug` đã được file cho product-gap (backfill bởi `/report-bug`) · `—` ngược lại |
|
|
230
230
|
|
|
231
231
|
Set `qc_owner`/`qc_blocked_by` cùng với `qc_status`. Khi `pass`, **clear** cả hai về `—` — nhưng **PHẢI chạy §Đóng bug đã verify bên dưới TRƯỚC**, vì `qc_blocked_by` chính là con trỏ tới bug và clear xong là mất đường về.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# /refine-prd — Phân tích PRD qua
|
|
1
|
+
# /refine-prd — Phân tích PRD qua 3 lăng kính review
|
|
2
2
|
|
|
3
3
|
> **Ranh giới — lệnh này chỉ áp được fix cho vấn đề mà CHÍNH NÓ tìm ra.** Resume Mode Phase 2 tự
|
|
4
4
|
> cấm đụng bất kỳ section nào không được một finding chấp nhận trỏ tới, và findings sinh từ việc soi
|
|
@@ -259,11 +259,10 @@ vòng không sinh thêm gì mới, *trước khi* ghi file findings.
|
|
|
259
259
|
|
|
260
260
|
Lệnh gọi cung cấp hai thứ bắt buộc + hai tuỳ chọn:
|
|
261
261
|
- **DIMENSIONS** — danh sách các chiều review để fan out
|
|
262
|
-
(`/refine-prd` →
|
|
262
|
+
(`/refine-prd` → 3 lăng kính; `/review-context` → các P-check hoặc B-check).
|
|
263
263
|
- **FINDINGS SCHEMA** — dạng YAML mà mỗi finding phải theo (định nghĩa trong lệnh).
|
|
264
264
|
- **GRANULARITY** *(tuỳ chọn, mặc định `auto`)* — `auto`: chọn độ mịn fan-out theo bảng ngưỡng kích thước ở Phase 1 (hành vi cũ). `per-uc`: **LUÔN** fan-out theo từng UC, **bỏ qua ngưỡng** — dùng cho review cần độ đầy đủ cao (`/refine-prd` truyền cái này để lần đầu đã quét sâu). Lệnh không truyền → `auto` → hành vi không đổi.
|
|
265
265
|
- **CHANGED_SCOPE** *(tuỳ chọn)* — danh sách UC/section đã thay đổi (review **delta**). Nếu được truyền, Phase 1 chỉ fan-out trên các phạm vi này + PRD-global; Phase 2 critic vẫn quét **toàn doc** làm lưới an toàn. Không truyền → quét toàn bộ như thường.
|
|
266
|
-
- **VERIFY** *(tuỳ chọn, mặc định `off`)* — `on` chèn **Phase 2.5** (`steps/gap-verify.md`) giữa critic và dedup: mỗi finding phải mở lại tài liệu nguồn tự chứng minh trước khi được giữ. Không truyền → hành vi không đổi.
|
|
267
266
|
|
|
268
267
|
> **Bỏ qua ở chế độ sub-agent:** Nếu Gate Bước 0 đã set `_agent_mode: true`, toàn bộ
|
|
269
268
|
> quy trình này bị **bỏ qua** — orchestrator đã chạy sẵn một dimension/UC cho mỗi
|
|
@@ -382,31 +381,6 @@ Ghi lại `convergence_rounds` (số vòng critic đã chạy) cho report.
|
|
|
382
381
|
|
|
383
382
|
---
|
|
384
383
|
|
|
385
|
-
## Phase 2.5 — Thẩm định *(chỉ chạy khi `VERIFY = on`)*
|
|
386
|
-
|
|
387
|
-
**Vì sao có bước này.** Phase 1 và Phase 2 chỉ có **một chiều lực**: fan-out mở rộng bề
|
|
388
|
-
ngang, critic lặp cho tới khi không còn gì mới — cả hai đều hỏi *"còn thiếu gì nữa?"*.
|
|
389
|
-
Không có gì hỏi ngược lại *"cái vừa tìm ra có thật không?"*. Nên quy trình này đẩy **recall**
|
|
390
|
-
lên mà **không có gì kéo precision lại**, và càng lặp critic thì tỉ lệ finding bịa càng cao —
|
|
391
|
-
đúng thứ nó tự sinh ra: khẳng định hành vi tài liệu không nêu, trích evidence sai, hoặc gắn
|
|
392
|
-
nhãn vấn đề cho thứ thực ra là chuyện làm-kỹ-hơn.
|
|
393
|
-
|
|
394
|
-
Chạy `steps/gap-verify.md` trên `ALL_FINDINGS` với:
|
|
395
|
-
- `FINDINGS` = `ALL_FINDINGS` (sau Phase 2)
|
|
396
|
-
- `EVIDENCE_ROOT` = `{paths.specs_dir}` — hoặc giá trị lệnh gọi chỉ định
|
|
397
|
-
- `VERDICT_FIELD` = trường trạng thái của FINDINGS SCHEMA mà lệnh định nghĩa
|
|
398
|
-
- `RERATE` = `on`
|
|
399
|
-
|
|
400
|
-
Finding bị `❌ INVALID` / `⚠️ RECLASSIFY` / `🔁 MERGE` **không đi tiếp sang Phase 3** — nhưng
|
|
401
|
-
**KHÔNG bị xoá**: chúng vào file findings với trạng thái đóng + lý do, để người đọc kiểm chứng
|
|
402
|
-
được vì sao chúng bị loại. Ghi lại số liệu verdict cho report.
|
|
403
|
-
|
|
404
|
-
> **Chạy TRƯỚC Phase 3, không phải sau.** Dedup và giải quyết xung đột là việc tốn suy luận;
|
|
405
|
-
> làm nó trên một tập còn lẫn finding bịa là vừa phí, vừa nguy hiểm — một finding ảo có thể
|
|
406
|
-
> "thắng" một finding thật ở bước giữ-cái-severity-cao-hơn.
|
|
407
|
-
|
|
408
|
-
---
|
|
409
|
-
|
|
410
384
|
## Phase 3 — Dedup, giải quyết xung đột, merge
|
|
411
385
|
|
|
412
386
|
Các sub-agent chạy **mù với nhau** (độc lập = độ phủ đa dạng). Chúng không bao giờ
|
|
@@ -438,7 +412,7 @@ Convergence: {convergence_rounds} vòng critic — file findings đã đầy đ
|
|
|
438
412
|
|
|
439
413
|
---
|
|
440
414
|
|
|
441
|
-
## Phân tích —
|
|
415
|
+
## Phân tích — 3 lăng kính (fan out cả ba, rồi hội tụ)
|
|
442
416
|
|
|
443
417
|
Chạy review qua **Quy trình Review** ở trên (`steps/review-fanout.md`).
|
|
444
418
|
|
|
@@ -457,23 +431,22 @@ Chạy review qua **Quy trình Review** ở trên (`steps/review-fanout.md`).
|
|
|
457
431
|
- **`applied_to_version` có mặt VÀ `==` version PRD hiện tại** → PRD đổi đúng bằng phần lệnh này tự áp, không actor khác động vào → **DELTA**: `CHANGED_SCOPE` = { `uc_id`/`section` của các finding `status: applied` trong findings cũ } ∪ { UC có trong PRD hiện tại nhưng chưa từng xuất hiện ở findings cũ }. Truyền `CHANGED_SCOPE` này vào Quy trình Review.
|
|
458
432
|
- **`applied_to_version` vắng mặt HOẶC `≠` version hiện tại** → PRD đã bị sửa bởi **actor khác** (lệnh `/review-context`, sửa tay…) sau lần resume này → KHÔNG tin được phạm vi hẹp → **FULL** (KHÔNG truyền `CHANGED_SCOPE`), kèm cảnh báo: `"PRD đổi ngoài tầm theo dõi của findings (applied_to_version={A} ≠ hiện tại={C}); quét lại toàn bộ để khỏi sót UC do người/lệnh khác sửa."`
|
|
459
433
|
|
|
460
|
-
**DIMENSIONS** =
|
|
434
|
+
**DIMENSIONS** = 3 lăng kính dưới đây — fan out một sub-agent cho mỗi lăng kính, mỗi cái quét
|
|
461
435
|
toàn bộ PRD qua đúng lăng kính của nó:
|
|
462
436
|
|
|
463
|
-
|
|
437
|
+
<!-- ─────────────────────────────────────────────────────────────────────────────
|
|
438
|
+
LĂNG KÍNH BỊ TẮT (DISABLED — KHÔNG dùng, KHÔNG fan-out agent cho lăng kính này):
|
|
464
439
|
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
> gỡ `QA` khỏi enum `lens:` + `by_lens` + ghi chú `phán đoán QA/DEV/SA/PO` · sửa
|
|
476
|
-
> `docs/explain/03-refine-prd.md` cho khớp · rebuild `node bin/build.js`.
|
|
440
|
+
- **Lăng kính QA (tầng nghiệm thu)**: AC có nêu **outcome quan sát/kiểm được** chưa? — **KHÔNG** hỏi "AC đủ chi tiết chưa" (câu đó kéo cơ chế vào AC). Chi tiết cơ chế (số lần retry, timeout, tên/chủ cờ, nhánh lỗi vụn) thuộc **BR/BL**: nếu gap là cơ chế → suggestion phải **route sang BR/BL + AC ref**, KHÔNG phình AC. AC có lặp lại nội dung BR (trùng tầng) không → nếu có, đề xuất làm mỏng AC.
|
|
441
|
+
|
|
442
|
+
CÁCH THÊM LẠI QA (khi cần bật lại giai đoạn sau):
|
|
443
|
+
1. Chuyển bullet QA ở trên ra khỏi block comment này, đặt lên đầu danh sách DIMENSIONS.
|
|
444
|
+
2. Đổi "3 lăng kính"/"cả ba" → "4 lăng kính"/"cả bốn" ở: dòng tiêu đề (# /refine-prd),
|
|
445
|
+
heading "## Phân tích", câu "DIMENSIONS = N lăng kính", và steps/review-fanout.md.
|
|
446
|
+
3. Thêm "QA" lại vào enum của `lens:` trong FINDINGS SCHEMA + vào `by_lens`.
|
|
447
|
+
4. Thêm "QA" lại vào ghi chú "phán đoán DEV/SA/PO" ở LƯU Ý của schema.
|
|
448
|
+
5. Rebuild: node bin/build.js
|
|
449
|
+
───────────────────────────────────────────────────────────────────────────── -->
|
|
477
450
|
|
|
478
451
|
> **Nguyên tắc chung cho DEV & SA — đọc bằng mắt kỹ thuật, VIẾT bằng lời nghiệp vụ.**
|
|
479
452
|
> Hai lăng kính này dùng con mắt kỹ thuật để **phát hiện chỗ nghiệp vụ mô tả thiếu/mơ hồ/mâu thuẫn đến mức sẽ chặn triển khai** — mục tiêu là **làm rõ vấn đề nghiệp vụ để sau này xử lý được về mặt kỹ thuật**. **KHÔNG** đưa góc nhìn kỹ thuật vào PRD, **KHÔNG** đề xuất giải pháp/cơ chế kỹ thuật. Mọi `finding` và `suggestion` phải **thuần nghiệp vụ** (tuân Business Language Guard): mô tả *cái nghiệp vụ còn thiếu/chưa rõ* và *hỏi cần làm rõ gì*, chứ không nói *làm thế nào về kỹ thuật*.
|
|
@@ -510,7 +483,7 @@ status: "pending_review"
|
|
|
510
483
|
|
|
511
484
|
findings:
|
|
512
485
|
- id: "F001"
|
|
513
|
-
lens: "DEV" #
|
|
486
|
+
lens: "DEV" # DEV | SA | PO
|
|
514
487
|
severity: "major" # critical | major | minor
|
|
515
488
|
section: "§2. Acceptance Criteria" # nhãn heading/section dạng người đọc
|
|
516
489
|
uc_id: "{TICKET-ID}-UC{N}" # UC mà finding thuộc về; "" nếu PRD-global (scope, metrics, problem statement)
|
|
@@ -526,8 +499,8 @@ findings:
|
|
|
526
499
|
# true = AI tự tin cao vào suggestion này; Review Board có thể hiển thị nút "quick accept"
|
|
527
500
|
# false = cần human đọc kỹ và ghi quyết định trước khi accept
|
|
528
501
|
# Resume Mode luôn áp dụng theo status (accepted|modified), bất kể auto_fixable.
|
|
529
|
-
# LƯU Ý: /refine-prd CỐ Ý không có `--fix` mode (khác /review-context) — finding
|
|
530
|
-
# là phán đoán
|
|
502
|
+
# LƯU Ý: /refine-prd CỐ Ý không có `--fix` mode (khác /review-context) — finding 3 lăng kính
|
|
503
|
+
# là phán đoán DEV/SA/PO, phải qua người duyệt ở Board; auto_fixable ở đây CHỈ là gợi ý
|
|
531
504
|
# quick-accept cho Board, KHÔNG để máy tự áp.
|
|
532
505
|
status: "pending"
|
|
533
506
|
applied_via: ""
|
|
@@ -543,7 +516,7 @@ findings:
|
|
|
543
516
|
summary:
|
|
544
517
|
total_findings: {N}
|
|
545
518
|
by_severity: { critical: {N}, major: {N}, minor: {N} }
|
|
546
|
-
by_lens: {
|
|
519
|
+
by_lens: { DEV: {N}, SA: {N}, PO: {N} }
|
|
547
520
|
recommendation: "APPROVED_WITH_MINOR_CHANGES | NEEDS_REVISION | BLOCKED"
|
|
548
521
|
# Rule: critical ≥ 1 → BLOCKED
|
|
549
522
|
# critical = 0, major ≥ 1 → NEEDS_REVISION
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# /report-bug — File một Bug có trace-spec (cho Tester & QC)
|
|
2
2
|
|
|
3
3
|
Dành cho **tester và QC** — gồm cả **product-gap** lòi ra từ pipeline `/qc-*`
|
|
4
|
-
(`/qc-run-test` FAIL phân loại product-gap, hoặc một spec-defect blocker `
|
|
4
|
+
(`/qc-run-test` FAIL phân loại product-gap, hoặc một spec-defect blocker `DOC_GAPS` từ
|
|
5
5
|
`/qc-analyze`). Sinh một bug report có cấu trúc với đầy đủ spec context, phân loại layer
|
|
6
6
|
khả nghi, và lưu lại để handoff cho team dev.
|
|
7
7
|
|
|
@@ -267,11 +267,10 @@ vòng không sinh thêm gì mới, *trước khi* ghi file findings.
|
|
|
267
267
|
|
|
268
268
|
Lệnh gọi cung cấp hai thứ bắt buộc + hai tuỳ chọn:
|
|
269
269
|
- **DIMENSIONS** — danh sách các chiều review để fan out
|
|
270
|
-
(`/refine-prd` →
|
|
270
|
+
(`/refine-prd` → 3 lăng kính; `/review-context` → các P-check hoặc B-check).
|
|
271
271
|
- **FINDINGS SCHEMA** — dạng YAML mà mỗi finding phải theo (định nghĩa trong lệnh).
|
|
272
272
|
- **GRANULARITY** *(tuỳ chọn, mặc định `auto`)* — `auto`: chọn độ mịn fan-out theo bảng ngưỡng kích thước ở Phase 1 (hành vi cũ). `per-uc`: **LUÔN** fan-out theo từng UC, **bỏ qua ngưỡng** — dùng cho review cần độ đầy đủ cao (`/refine-prd` truyền cái này để lần đầu đã quét sâu). Lệnh không truyền → `auto` → hành vi không đổi.
|
|
273
273
|
- **CHANGED_SCOPE** *(tuỳ chọn)* — danh sách UC/section đã thay đổi (review **delta**). Nếu được truyền, Phase 1 chỉ fan-out trên các phạm vi này + PRD-global; Phase 2 critic vẫn quét **toàn doc** làm lưới an toàn. Không truyền → quét toàn bộ như thường.
|
|
274
|
-
- **VERIFY** *(tuỳ chọn, mặc định `off`)* — `on` chèn **Phase 2.5** (`steps/gap-verify.md`) giữa critic và dedup: mỗi finding phải mở lại tài liệu nguồn tự chứng minh trước khi được giữ. Không truyền → hành vi không đổi.
|
|
275
274
|
|
|
276
275
|
> **Bỏ qua ở chế độ sub-agent:** Nếu Gate Bước 0 đã set `_agent_mode: true`, toàn bộ
|
|
277
276
|
> quy trình này bị **bỏ qua** — orchestrator đã chạy sẵn một dimension/UC cho mỗi
|
|
@@ -390,31 +389,6 @@ Ghi lại `convergence_rounds` (số vòng critic đã chạy) cho report.
|
|
|
390
389
|
|
|
391
390
|
---
|
|
392
391
|
|
|
393
|
-
## Phase 2.5 — Thẩm định *(chỉ chạy khi `VERIFY = on`)*
|
|
394
|
-
|
|
395
|
-
**Vì sao có bước này.** Phase 1 và Phase 2 chỉ có **một chiều lực**: fan-out mở rộng bề
|
|
396
|
-
ngang, critic lặp cho tới khi không còn gì mới — cả hai đều hỏi *"còn thiếu gì nữa?"*.
|
|
397
|
-
Không có gì hỏi ngược lại *"cái vừa tìm ra có thật không?"*. Nên quy trình này đẩy **recall**
|
|
398
|
-
lên mà **không có gì kéo precision lại**, và càng lặp critic thì tỉ lệ finding bịa càng cao —
|
|
399
|
-
đúng thứ nó tự sinh ra: khẳng định hành vi tài liệu không nêu, trích evidence sai, hoặc gắn
|
|
400
|
-
nhãn vấn đề cho thứ thực ra là chuyện làm-kỹ-hơn.
|
|
401
|
-
|
|
402
|
-
Chạy `steps/gap-verify.md` trên `ALL_FINDINGS` với:
|
|
403
|
-
- `FINDINGS` = `ALL_FINDINGS` (sau Phase 2)
|
|
404
|
-
- `EVIDENCE_ROOT` = `{paths.specs_dir}` — hoặc giá trị lệnh gọi chỉ định
|
|
405
|
-
- `VERDICT_FIELD` = trường trạng thái của FINDINGS SCHEMA mà lệnh định nghĩa
|
|
406
|
-
- `RERATE` = `on`
|
|
407
|
-
|
|
408
|
-
Finding bị `❌ INVALID` / `⚠️ RECLASSIFY` / `🔁 MERGE` **không đi tiếp sang Phase 3** — nhưng
|
|
409
|
-
**KHÔNG bị xoá**: chúng vào file findings với trạng thái đóng + lý do, để người đọc kiểm chứng
|
|
410
|
-
được vì sao chúng bị loại. Ghi lại số liệu verdict cho report.
|
|
411
|
-
|
|
412
|
-
> **Chạy TRƯỚC Phase 3, không phải sau.** Dedup và giải quyết xung đột là việc tốn suy luận;
|
|
413
|
-
> làm nó trên một tập còn lẫn finding bịa là vừa phí, vừa nguy hiểm — một finding ảo có thể
|
|
414
|
-
> "thắng" một finding thật ở bước giữ-cái-severity-cao-hơn.
|
|
415
|
-
|
|
416
|
-
---
|
|
417
|
-
|
|
418
392
|
## Phase 3 — Dedup, giải quyết xung đột, merge
|
|
419
393
|
|
|
420
394
|
Các sub-agent chạy **mù với nhau** (độc lập = độ phủ đa dạng). Chúng không bao giờ
|