improve BA skill

This commit is contained in:
Leonard-ThindPad-P50
2026-09-09 06:34:57 +07:00
parent 119792967c
commit 2c7bcde741
42 changed files with 5429 additions and 54 deletions

View File

@@ -20,7 +20,8 @@ Bạn là **kiểm toán viên độc lập** của quy trình BA. Bạn **khôn
- ☐ chưa bắt đầu.
**Đừng suy ra trạng thái từ tên file** — mở file, đọc `Status` và kiểm mục bắt buộc có nội dung thật.
3. **Blocker:** gate thấp nhất chưa ✅ là vị trí hiện tại. Blocker cứng (artifact thiếu/chưa ký), blocker mềm (`OQ` chưa trả lời, `CR` chưa quyết, `RISK` cao chưa có phương án). Grep `OQ-[0-9]|TBD|TODO|❓`; `OQ` quá 5 ngày làm việc (so với ngày trong prompt) ⇒ quá hạn, nêu người phải trả lời.
4. **Traceability (ba-traceability):** trích ID từ mọi artifact; chạy 6 phép kiểm coverage (RQ→US, US→AC, AC→test case, BR→AC/test, US không có nguồn = scope creep, RQ không có US) và 4 phép kiểm nhất quán (tham chiếu gãy, ID trùng, version lệch giữa tài liệu tham chiếu nhau, artifact khai profile khác PROFILE). Báo **con số** (VD "RQ→US 18/20 = 90%") và danh sách ID lệch. Theo skill, coverage thiếu có quyền **chặn G2, G3, G4** — ghi rõ kết luận chặn.
4. **Traceability (ba-traceability):** trích ID từ mọi artifact; chạy 6 phép kiểm coverage (RQ→US, US→AC, AC→test case, BR→AC/test, US không có nguồn = scope creep, RQ không có US) và 6 phép kiểm nhất quán (tham chiếu gãy/version lệch, ràng buộc SRS↔API, mã lỗi SRS↔API, trạng thái BR↔SRS/RBAC, **thành phần SRS↔WF hai chiều** và **quy ước SRS↔UICONV** — hai phép cuối chỉ khi `PRODUCT = screen`). Báo **con số** (VD "RQ→US 18/20 = 90%", "C-id lệch: C07 chỉ có trong WF") và danh sách ID lệch. Theo skill, coverage thiếu có quyền **chặn G2, G3, G4** — ghi rõ kết luận chặn.
Với `screen` ở G3 còn phải mở `00-index/UICONV_*.md` (tồn tại? còn ô "chọn một" chưa chọn? có chữ ký Designer hoặc DEC "không có Designer"?) và `03-specification/WF_*.md` (phủ mọi SCR của SRS? §5 có điền không? còn dòng Tồn tại/Hành vi ☐ không? chế độ 🎨 hay ✏️, ✏️ đã có Designer ký chưa?). WF thiếu §5 ⇒ báo "chưa đối chiếu prototype", **không** báo "không lệch".
5. **Cảnh báo bắt buộc:** `RIGOR = light` nhưng đã có người dùng thật ⇒ đề xuất nâng `standard` và chạy bù G1–G3. US có trong BACKLOG nhưng chưa có SRS. SRS tham chiếu `BR` không tồn tại.
## Không được làm

View File

@@ -23,6 +23,11 @@ Bạn là **người thực thi một bước của quy trình BA** theo đúng
- Không hỏi người dùng. Điều skill định hỏi ở Bước 0 mà prompt chưa trả lời ⇒ ghi vào `humanInputNeeded` {topic, question, suggestedDefault}; nếu ảnh hưởng nội dung ⇒ thêm `OQ-nnn` trong artifact và trong sổ `00-index/OQ_<PROJECT>.md` (tạo nếu chưa có).
- **Preflight gate:** đọc INDEX + header artifact của gate trước. Gate trước chưa `✅ Baselined` và prompt **không** có mục "Ngoại lệ gate" ⇒ **không ghi file**, trả `blocked=true` + `gateWarning` nêu rõ thiếu gì. Có ngoại lệ ⇒ làm tiếp và ghi ngoại lệ vào Open Questions của artifact + `DEC-nn`.
- Phạm vi: chỉ làm đúng giai đoạn/hoạt động được giao (`activity`). `ba-3` quá 3 US ⇒ chỉ làm 3 US đầu, báo phần còn lại trong `summary`.
- **`ba-3` với `PRODUCT = screen`** — hai activity thêm, theo `SKILL.md` Bước 8–9:
- `uiconv`: chưa có `00-index/UICONV_<PROJECT>_v*.md` ⇒ tạo từ `templates/ui-convention.md`; đã có ⇒ chỉ bổ sung §10–§12, version +0.1. Điền từ prototype/design system trong prompt; ô "chọn một" không có nguồn ⇒ **để nguyên các phương án và ghi `OQ`**, không tự chọn.
- `wf`: chạy sau `part2` + `errors` của cùng US. Ghi **hai file** `03-specification/WF_<US>_v1.0.md` (từ `templates/wireframe.md`) và `WF_<US>_v1.0.html` (từ `templates/wireframe.html` — giữ nguyên `<style>`/`<script>`, thay phần `<main>`; mỗi `SCR` một `<section id>`, mỗi thành phần `data-c` đúng C-id/F-id của SRS, mỗi trạng thái một khối `data-state`). Header ghi rõ chế độ 🎨 (có prototype trong prompt hoặc tự tìm được) hay ✏️. **Bắt buộc điền WF §5** (lệch prototype ↔ SRS) — kể cả khi rỗng thì ghi "đã đối chiếu n màn hình, không lệch". Không thêm thành phần vào SRS vì prototype có.
- Tự kiểm sau `wf`: trích tập `[CF][0-9]{2}` từ SRS và từ WF (.md + `data-c` trong .html), so hai chiều; lệch ⇒ báo trong `gateSelfCheck` với danh sách ID, không tự sửa SRS. Đếm dòng WF §5 theo loại và số dòng chưa có người quyết ⇒ `summary`.
- `ba-3` activity `uiconv`/`wf` với `PRODUCT ≠ screen` ⇒ không ghi file, trả `summary` "N/A theo PRODUCT".
- Prompt có "Ghi chú từ người duyệt" ⇒ đọc artifact hiện có, sửa đúng phần liên quan, version `+0.1` (hoặc `+1.0` nếu đổi phạm vi/tái cấu trúc), Change Log ghi rõ.
## Header, ID, version
@@ -47,4 +52,4 @@ Chỉ sửa header/Change Log/INDEX, không đổi nội dung:
- Sơ đồ Mermaid luôn kèm bảng (W13); sequence ở GĐ3 phải có nhánh lỗi.
## Kết quả trả về (structured output)
`filesWritten[]`, `artifacts[]` {code, path, version, status}, `blocked`, `gateWarning`, `gateSelfCheck[]` {item, ok, note}, `openQuestions[]` {id, question, askWho, blocks}, `humanInputNeeded[]` {topic, question, suggestedDefault}, `assumptions[]`, `decisions[]` {id, text}, `tbdCount`, `ambiguousCount`, `confidence` (low nếu blocked/nhiều OQ), `summary` (5–8 dòng: đã làm gì, cần người duyệt xem gì, ai phải trả lời gì).
`filesWritten[]`, `artifacts[]` {code, path, version, status}, `blocked`, `gateWarning`, `gateSelfCheck[]` {item, ok, note}, `openQuestions[]` {id, question, askWho, blocks}, `humanInputNeeded[]` {topic, question, suggestedDefault}, `assumptions[]`, `decisions[]` {id, text}, `tbdCount`, `ambiguousCount`, `confidence` (low nếu blocked/nhiều OQ), `summary` (5–8 dòng: đã làm gì, cần người duyệt xem gì, ai phải trả lời gì). Sau `wf`, `summary` phải có: chế độ 🎨/✏️ · số SCR phủ / tổng · C-id lệch hai chiều (danh sách, phải rỗng) · số lệch WF §5 theo loại và số chưa quyết · Designer có cần ký không.

View File

@@ -38,7 +38,7 @@ sống còn. Chi tiết và cách chọn khi lưỡng lự: [`ba-lifecycle/refer
| 0 | `ba-lifecycle` | *Điều phối* | "Tôi đang ở đâu, làm gì tiếp?" | Bảng trạng thái pipeline | — |
| 1 | `ba-1-discovery` | Khởi tạo | "Bài toán là gì, của ai, thành công là gì?" | `BRIEF`, `STAKEHOLDER`, `ELICITATION` | **G1** |
| 2 | `ba-2-analysis` | Phân tích | "Nghiệp vụ chạy thế nào, cần những gì?" | `PROCESS`, `BACKLOG`, `BR`, `RBAC`, `IMPACT` | **G2** |
| 3 | `ba-3-specification` | Đặc tả | "Dev code cái gì, QA test cái gì?" | `SRS`, `AC`, `API`, `NFR` | **G3** |
| 3 | `ba-3-specification` | Đặc tả | "Dev code cái gì, QA test cái gì, màn hình bố cục ra sao?" | `SRS`, `AC`, `API`, `NFR` (+ `UICONV`, `WF` khi `screen`) | **G3** |
| 4 | `ba-4-delivery-support` | Đồng hành dev | "Câu hỏi/thay đổi/UAT xử lý ra sao?" | `QLOG`, `CR`, `TCREVIEW`, `UAT` | **G4** |
| 5 | `ba-5-post-release` | Sau release | "Có đạt mục tiêu không, cải tiến gì?" | `RELNOTE`, `MANUAL`, `BENEFIT` | **G5** |
| ⊕ | `ba-traceability` | *Xuyên suốt* | "Có sót yêu cầu nào không?" | `RTM`, báo cáo coverage | Chặn G2–G4 |
@@ -95,7 +95,9 @@ D:\Kakao\Docs\.claude\skills\
│ ├── srs-part2/ ← 🔴 PART 2 cắm được theo PRODUCT
│ │ ├── screen.md · api-service.md · data-pipeline.md
│ │ └── ml-model.md · batch-job.md
│ └── acceptance-criteria.md · nfr-checklist.md · api-contract.md
│ ├── acceptance-criteria.md · nfr-checklist.md · api-contract.md
│ ├── ui-convention.md ← (screen) quy ước UI cấp project, một lần
│ └── wireframe.md · wireframe.html ← (screen) bố cục từng màn hình + render low-fi, đối chiếu prototype
├── ba-4-delivery-support/ …
├── ba-5-post-release/ …
└── ba-traceability/ …
@@ -114,10 +116,10 @@ Mặc định mọi artifact ghi vào thư mục làm việc hiện tại:
```
ba-output/<PROJECT>/
├── 00-index/ PROFILE, RTM, glossary, decision log, open questions
├── 00-index/ PROFILE, RTM, glossary, decision log, open questions, UICONV (screen)
├── 01-discovery/ BRIEF, STAKEHOLDER, ELICITATION, RISK
├── 02-analysis/ PROCESS, BACKLOG, BR, RBAC, IMPACT
├── 03-specification/ SRS, AC, API, NFR, WIREFRAME
├── 03-specification/ SRS, AC, API, NFR, WF (.md + .html, screen)
├── 04-delivery/ QLOG, CR, TCREVIEW, UAT
└── 05-post-release/ RELNOTE, MANUAL, BENEFIT
```
@@ -255,6 +257,22 @@ nhất để hai tài liệu lệch nhau sau ba lần sửa.
Ánh xạ chi tiết: [`sa-lifecycle/references/artifact-map.md`](sa-lifecycle/references/artifact-map.md) §7.
## 6d. Bộ BA thay được bao nhiêu phần việc design?
Chỉ áp dụng khi `PRODUCT = screen`. Hai artifact `UICONV` (quy ước toàn project) và `WF`
(bố cục từng màn hình, `.md` + `.html` low-fi) được thiết kế để **nhận prototype làm đầu vào
tham chiếu**:
| Đầu vào có sẵn | BA làm được | Design còn phải làm |
|---|---|---|
| Prototype đã duyệt + design system | Ghi lại bố cục, map thành phần, đối chiếu với SRS, liệt kê lệch (`WF` §5) — dev dựng UI từ SRS + WF + design system | Xử lý các dòng lệch ở `WF` §5 |
| Prototype đã duyệt, chưa có design system | Như trên | Chọn/dựng design system, visual |
| Chỉ có mô tả UI dạng văn bản (SAD §7) | Bố cục mức vùng; thứ tự, kích thước là đề xuất | Duyệt WF, làm visual |
| Không có gì | `WF` chế độ ✏️ — **đề xuất của BA**, Designer bắt buộc ký | Thiết kế bố cục thật hoặc duyệt đề xuất, rồi visual |
BA **không bao giờ** làm visual (màu, font, icon, motion). Designer là người ký `UICONV` và
`WF` ở G3; dự án không có Designer ⇒ PO ký thay và ghi `DEC-nn`.
## 7. Phạm vi áp dụng — cái gì chuyển được, cái gì không
| | |

230
.claude/skills/REAME-SAD.md Normal file
View File

@@ -0,0 +1,230 @@
# Hướng dẫn sử dụng — Bộ skill SAD (System Analysis & Design)
Tài liệu này giới thiệu và hướng dẫn sử dụng toàn bộ hệ thống skill/agent/workflow đã xây dựng trong dự án, dùng để đi từ **một mô tả dự án còn sơ sài** đến **tài liệu phân tích thiết kế hệ thống (SAD)**, rồi từ SAD ra **proposal gửi khách hàng**, **hồ sơ dự thầu hoàn chỉnh (kèm slide và PDF)**, và (khi cần đặc tả sâu tới mức code/test được) **quy trình BA/SA có gate ký duyệt**.
Đối tượng đọc: bất kỳ ai vận hành Claude Code trong dự án này (bạn, hoặc đồng nghiệp kế nhiệm) và cần biết gọi skill nào, theo thứ tự nào, cần chuẩn bị gì trước.
---
## 1. Triết lý thiết kế — đọc trước khi dùng
Toàn bộ hệ thống tuân theo 5 nguyên tắc xuyên suốt. Hiểu 5 nguyên tắc này quan trọng hơn nhớ tên từng agent:
1. **Một stage/agent = một trách nhiệm.** Không agent nào vừa viết nội dung vừa tính toán vừa duyệt. Ví dụ: `bid-estimator` chỉ ước lượng, không cộng tổng; workflow tính tổng bằng code thuần; `bid-reviewer` chỉ đọc và chấm, không sửa.
2. **Con số quan trọng không do LLM tính.** Effort (MM), chi phí, timeline, headcount trong hồ sơ thầu được tính bằng JavaScript thuần trong workflow, từ dữ liệu thô do agent cung cấp. LLM không cộng, không quy đổi, không làm tròn — tránh sai số cộng dồn và đảm bảo tái lập được.
3. **Có cổng phê duyệt giữa các bước (stage-gated).** Không skill nào chạy toàn bộ pipeline một lần không dừng (trừ khi bạn chủ động chọn chế độ `all` và được cảnh báo rõ). Mỗi bước dừng lại, trình bày kết quả trung thực, và chờ bạn **Duyệt / Sửa / Dừng**.
4. **Thiếu thông tin → hỏi hoặc để placeholder, không bịa.** Số liệu chưa có (đơn giá, ngày, tên người, chứng chỉ) luôn hiện dưới dạng `[[CẦN ĐIỀN: ...]]` hoặc `null`, không bao giờ được điền giá trị "nghe hợp lý".
5. **Tài liệu nội bộ và tài liệu gửi ra ngoài tách biệt tuyệt đối.** SAD, ghi chú rà soát, mã yêu cầu nội bộ (FR/NFR/OQ...) không bao giờ lọt vào proposal hay hồ sơ thầu — có agent `reviewer` chuyên rà soát rò rỉ trước khi bàn giao.
---
## 2. Bản đồ toàn hệ thống
```mermaid
flowchart TD
BRIEF["Ý tưởng / mô tả dự án\n(có thể rất sơ sài)"] --> SADP["/sad-pipeline/\nintake → requirements → architecture\n→ (api ∥ data ∥ uiux) → detailed\n→ security → testops → consolidate"]
SADP --> SAD["docs/SAD.md\n(tài liệu SAD đã duyệt)"]
SAD --> PROP["/sad-proposal/\ncontent → build → review"]
PROP --> PROPOUT["docs/proposal/\nindex.html · artifact.html"]
SAD --> BID["/sad-bid/\nintake → technical → estimate → plan\n→ financial → assemble → deck → export → review"]
BID --> BIDOUT["bid/\nHO-SO-THAU.pdf · deck.pdf"]
SAD -.seed & đối chiếu.-> BAP["/ba-pipeline/\ndiscovery → analysis → specification\n→ delivery → post-release"]
SAD -.seed & đối chiếu.-> SAP["/sa-pipeline/\ncontext → architecture → enablement → evolution"]
BAP <-.NFR↔QAS · API↔ICD· RBAC↔SEC.-> SAP
BAP --> DEVREADY["Đặc tả dev-ready\n(SRS, AC, mã lỗi, ADR, threat model...)"]
SAP --> DEVREADY
```
Bốn nhánh **độc lập với nhau**, đều xuất phát từ `docs/SAD.md`:
| Nhánh | Trả lời câu hỏi | Dùng khi |
|---|---|---|
| **sad-pipeline** | "Hệ thống này thiết kế như thế nào?" | Luôn chạy đầu tiên — mọi nhánh khác cần `docs/SAD.md` |
| **sad-proposal** | "Trình bày giải pháp cho khách hàng thế nào?" | Cần gửi đề xuất giải pháp (presales), chưa chắc đã thắng thầu |
| **sad-bid** | "Hồ sơ dự thầu đầy đủ, có giá, có kế hoạch, nộp được chưa?" | Có gói thầu cụ thể cần nộp hồ sơ (có/không có HSMT) |
| **ba-pipeline / sa-pipeline** | "Dev/QA có đủ đặc tả để code/test mà không phải hỏi lại không?" | SAD chỉ là thiết kế mức cao (HLD) — cần đặc tả sâu trước khi giao dev |
---
## 3. Cấu trúc thư mục dự án
```
sys-analysis-design/
├── introduction.md # khung 10 mục chuẩn của tài liệu SAD (tài liệu tham chiếu gốc)
├── HUONG-DAN-SU-DUNG.md # chính là tài liệu này
├── docs/
│ ├── 00-project-brief.md # do intake-analyst duy trì (brief + Q&A + profile + giả định)
│ ├── sections/01-…09-*.md # 9 mục SAD, mỗi mục có frontmatter status/version
│ ├── SAD.md # bản ráp hoàn chỉnh (do doc-consolidator sinh)
│ └── proposal/ # output của sad-proposal
│ ├── proposal-config.md # thông tin thương mại (khách hàng, giá, brand...)
│ ├── proposal-content.md
│ ├── index.html / artifact.html
├── bid/ # output của sad-bid
│ ├── inputs/ # HSMT/RFP nếu có
│ ├── bid-config.md # rate card, VAT, deadline, hồ sơ năng lực...
│ ├── 00-…40-*.md, estimate.json, estimate.computed.json
│ ├── HO-SO-THAU.md / .pdf, index.html
│ └── deck.html / deck.pdf
├── ba-output/<PROJECT>/ # output của ba-pipeline (theo chuẩn ba-lifecycle)
├── sa-output/<PROJECT>/ # output của sa-pipeline (theo chuẩn sa-lifecycle)
└── .claude/
├── agents/ # 24 subagent (xem mục 7)
├── workflows/ # 5 workflow (generate-sad.js, generate-proposal.js, generate-bid.js, ba-pipeline.js, sa-pipeline.js)
└── skills/
├── sad-pipeline/, sad-proposal/, sad-bid/ # 3 skill điều phối do ta xây
├── ba-pipeline/, sa-pipeline/ # 2 skill điều phối (lớp gate) cho BA/SA
└── ba-1…5-*, ba-lifecycle, ba-traceability, # bộ skill BA/SA gốc (đã có sẵn, không sửa)
sa-1…4-*, sa-lifecycle, sa-conformance
```
**docs/**, **bid/**, **ba-output/**, **sa-output/** đều **chưa tồn tại** — sẽ được tạo ở lần chạy đầu tiên.
---
## 4. Trước khi bắt đầu — 2 điều cần biết
### 4.1 Reload phiên sau khi thêm/sửa agent
Registry của Claude Code chỉ nạp `.claude/agents/*.md` **lúc phiên khởi động**. Sau bất kỳ lần agent mới được tạo (hoặc bạn tự sửa file agent), phải **khởi động lại phiên** (VS Code: `Ctrl+Shift+P` → *Developer: Reload Window*; CLI: thoát và mở lại `claude`) trước khi gọi agent đó — nếu không sẽ gặp lỗi `Agent type 'x' not found`. Skill và workflow thì **không cần reload**, nhận diện ngay.
### 4.2 Xuất PDF dùng trình duyệt sẵn có, không cần cài gì
Máy không có `pandoc`/`mermaid-cli`. Việc xuất PDF (proposal, hồ sơ thầu, slide) dùng **Microsoft Edge/Chrome ở chế độ headless** đã có sẵn trên máy — `bid-exporter` tự gọi, không cần bạn cài thêm phần mềm. Nếu chạy trên máy khác không có trình duyệt Chromium, agent sẽ báo `blocked` kèm hướng dẫn in thủ công (mở HTML → Ctrl+P → Save as PDF).
---
## 5. Hướng dẫn từng skill
### 5.1 `/sad-pipeline` — Sinh tài liệu SAD
**Khi nào dùng:** luôn là bước đầu tiên, khi có một ý tưởng/mô tả dự án cần chuyển thành SAD.
**8 stage** (mỗi lần gọi workflow là 1 stage, đều cần bạn duyệt trước khi sang stage kế):
| Stage | Agent | Việc chính |
|---|---|---|
| `intake` | `intake-analyst` | Đánh giá độ đủ thông tin của brief, đề xuất mô hình tham chiếu theo domain, hỏi tối đa 4 câu/vòng (≤3 vòng), ghi `docs/00-project-brief.md` |
| `requirements` | `requirements-analyst` | Mục 1–2: tổng quan, FR/NFR (mã FR-xx), use case, traceability |
| `architecture` | `architecture-designer` | Mục 3: kiến trúc, deployment, environment, tích hợp bên thứ ba |
| `fanout` | `api-designer` ∥ `data-modeler` ∥ `uiux-designer` | Mục 4/5/7 chạy **song song** vì độc lập nhau |
| `detailed` | `detailed-designer` | Mục 6: sequence/class/state diagram, business rule |
| `security` | `security-architect` | Mục 8: rà soát chéo bảo mật trên toàn bộ thiết kế |
| `testops` | `test-ops-planner` | Mục 9: test strategy, test case, CI/CD, monitoring, rollback/DR |
| `consolidate` | `doc-consolidator` | Mục 0 + ráp `docs/SAD.md` + kiểm tra nhất quán/traceability toàn tài liệu |
**Cách gọi mẫu (qua skill, không tự gọi Workflow trực tiếp):**
```
Dùng skill sad-pipeline để bắt đầu phân tích thiết kế cho: "<mô tả dự án>"
```
Claude sẽ tự chạy `intake`, hỏi bạn nếu thiếu thông tin, rồi lần lượt qua các stage, mỗi stage trình bày kết quả và hỏi Duyệt/Sửa/Dừng.
**Chế độ `all`:** workflow hỗ trợ chạy liền không dừng (không khuyến khích) — chỉ dùng khi bạn nói rõ "chạy hết không cần duyệt từng bước", có cảnh báo không kiểm soát trung gian.
---
### 5.2 `/sad-proposal` — Proposal gửi khách hàng
**Khi nào dùng:** sau khi `docs/SAD.md` đã có, cần bản trình bày giải pháp thuyết phục khách hàng (chưa chắc là hồ sơ thầu chính thức).
**3 stage:** `content` (`proposal-writer` — viết nội dung presales, loại bỏ mọi thông tin nội bộ) → `build` (`proposal-builder` — dựng `index.html` độc lập + `artifact.html` để publish Artifact xem trực quan) → `review` (`proposal-reviewer` — rà rò rỉ nội bộ, đối chiếu trung thực với SAD, kiểm chất lượng HTML).
**Thông tin cần chuẩn bị trước:** tên khách hàng, đơn vị đề xuất, ngày, mô hình giá — điền vào `docs/proposal/proposal-config.md` (skill sẽ hỏi và tạo giúp nếu chưa có).
**Chỉ được gọi là "gửi được"** khi `review` trả `canSend = true` (không leak, không placeholder còn sót).
---
### 5.3 `/sad-bid` — Hồ sơ dự thầu hoàn chỉnh
**Khi nào dùng:** có gói thầu cụ thể (có hoặc không có HSMT/RFP) cần nộp hồ sơ đầy đủ pháp lý + kỹ thuật + tài chính.
**9 stage:**
| Stage | Agent | Việc chính |
|---|---|---|
| `intake` | `bid-analyst` | Đọc HSMT (nếu có), lập bid-brief, **ma trận đáp ứng yêu cầu**, checklist tài liệu Phần A |
| `technical` | `bid-technical-writer` | Phần B: danh mục chức năng, sơ đồ hoạt động, tech stack, bảo mật, phương pháp luận (không có số MM/chi phí) |
| `estimate` | `bid-estimator` + **code tính** | WBS bottom-up + Use Case Points đối chiếu → workflow tính MD/MM/dự phòng/chi phí/timeline/staffing bằng JS thuần, ghi `bid/estimate.computed.json` |
| `plan` | `bid-planner` | B7 (Gantt ngày thật, mốc, tiêu chí nghiệm thu) + B8 (tổ chức nhân sự, staffing theo tháng) — số liệu lấy nguyên từ computed |
| `financial` | `bid-financial-writer` | Phần C: bảng effort, đơn giá, tổng giá trước/sau VAT, mốc thanh toán — không tính lại |
| `assemble` | `bid-builder` | Ráp `bid/HO-SO-THAU.md` + `bid/index.html` (A4, có bookmark/số trang khi in) |
| `deck` | `bid-deck-builder` | `bid/deck.html` — 15–25 slide 16:9 tự chứa cho buổi thuyết trình thầu |
| `export` | `bid-exporter` | Dùng Edge/Chrome headless in ra **`HO-SO-THAU.pdf`** và **`deck.pdf`**, kiểm Mermaid đã render, kiểm số trang |
| `review` | `bid-reviewer` | 6 lăng kính: đủ mục, đáp ứng yêu cầu bắt buộc, **số liệu khớp computed**, không rò rỉ, khả thi, chất lượng PDF/deck |
**Thông tin cần chuẩn bị trước** (điền `bid/bid-config.md`): rate card theo vai trò, VAT, deadline nộp/deadline thực hiện, chi phí phi nhân công đã biết, hồ sơ năng lực công ty sẵn có (`companyDocs`).
**Chỉ nộp khi** `review` trả `canSubmit = true`.
---
### 5.4 `/ba-pipeline` và `/sa-pipeline` — Đặc tả dev-ready + kiến trúc chi tiết
**Khi nào dùng:** SAD chỉ là thiết kế mức cao (HLD). Trước khi giao dev/QA thi công, cần đặc tả sâu hơn: bảng field, Acceptance Criteria 4 nhóm, mã lỗi, C4 diagram, threat model STRIDE, ADR... Đây là lớp **cổng phê duyệt (gate)** bọc quanh bộ skill BA/SA gốc đã có sẵn (`ba-1…5-*`, `sa-1…4-*`) — bộ gốc không bị sửa, chỉ được điều phối chặt chẽ hơn.
**Nguyên tắc chung của cả hai:** một lần gọi = một `stage` hoặc một `activity` cụ thể (không có chế độ chạy liền); mọi output có header chuẩn (`Version · Status · Approved by`); **agent không bao giờ tự đánh dấu ✅/🔵** — chỉ con người ký qua stage `sign`, có `role` đúng quy định (VD Gate G3 của BA cần PO + Tech Lead + QA; Gate AG2 của SA cần Tech Lead + Security + Ops/SRE).
| | `ba-pipeline` | `sa-pipeline` |
|---|---|---|
| Giai đoạn | discovery → analysis → specification → delivery → post-release | context → architecture → enablement → evolution |
| Gate | G1…G5 | AG1…AG4 |
| Auditor (chỉ đọc, chấm gate) | `ba-gate-auditor` | `sa-gate-auditor` |
| Runner (thực thi 1 activity) | `ba-stage-runner` | `sa-stage-runner` |
| Output | `ba-output/<PROJECT>/` | `sa-output/<PROJECT>/` |
**Liên kết BA ↔ SA:** Gate G2 của BA cần Gate AG1 của SA đã qua (Tech Lead ký "khả thi" dựa trên phương án kiến trúc). `QAS`/`ICD`/`SEC` của SA "thắng" `NFR`/`API`/`RBAC` do BA đề xuất — khi có lệch, quay lại BA sửa `specification` với ghi chú tương ứng.
**Đọc thêm:** `.claude/skills/README-BA.md` và `README-SA.md` giải thích chi tiết triết lý của hai bộ skill gốc (PROFILE 3 trục PRODUCT×LIFECYCLE×RIGOR, hệ ID RQ/BR/ADR/OQ...) — nên đọc trước khi dùng `ba-pipeline`/`sa-pipeline` lần đầu.
---
## 6. Kịch bản sử dụng đầu-cuối (ví dụ điển hình)
```
1. "Dùng sad-pipeline, tôi cần thiết kế hệ thống cho <ý tưởng>"
→ intake hỏi vài câu → requirements → architecture → fanout → detailed
→ security → testops → consolidate → có docs/SAD.md
2a. Cần trình bày cho khách hàng ngay:
"Dùng sad-proposal để làm proposal từ SAD này"
→ content → build → review → docs/proposal/index.html
2b. Có gói thầu cụ thể cần nộp:
"Dùng sad-bid, gói thầu <tên>, đây là HSMT..."
→ intake → technical → estimate (điền rate card khi được hỏi)
→ plan → financial → assemble → deck → export → review
→ bid/HO-SO-THAU.pdf + bid/deck.pdf
3. Trước khi giao dev, cần đặc tả sâu hơn:
"Dùng ba-pipeline cho project <tên>, bắt đầu discovery"
"Dùng sa-pipeline cho project <tên>, bắt đầu context"
→ lặp qua các gate, ký duyệt, tới khi Gate G3/AG2 (Ready for Dev/Build)
```
Ba nhánh 2a/2b/3 **độc lập**, có thể chạy song song hoặc chỉ chọn nhánh cần.
---
## 7. Bảng tổng hợp toàn bộ agent (24 agent, theo pipeline)
| Pipeline | Agent |
|---|---|
| sad-pipeline | `intake-analyst` · `requirements-analyst` · `architecture-designer` · `api-designer` · `data-modeler` · `uiux-designer` · `detailed-designer` · `security-architect` · `test-ops-planner` · `doc-consolidator` |
| sad-proposal | `proposal-writer` · `proposal-builder` · `proposal-reviewer` |
| sad-bid | `bid-analyst` · `bid-technical-writer` · `bid-estimator` · `bid-planner` · `bid-financial-writer` · `bid-builder` · `bid-deck-builder` · `bid-exporter` · `bid-reviewer` |
| ba-pipeline / sa-pipeline | `ba-stage-runner` · `ba-gate-auditor` · `sa-stage-runner` · `sa-gate-auditor` |
---
## 8. Trạng thái hiện tại & giới hạn đã biết
Trung thực về những gì **chưa** được kiểm chứng:
- Toàn bộ logic điều phối (thứ tự stage, truyền dữ liệu, tính toán số học ước lượng) đã được **kiểm thử bằng script mô phỏng** (stub test), **chưa chạy end-to-end với agent thật** trên một dự án hoàn chỉnh.
- Việc xuất PDF bằng Edge headless đã kiểm chứng thật trên máy này (render Mermaid, in ra PDF có outline) với 1 file mẫu nhỏ — chưa thử với hồ sơ dài thật.
- `ba-pipeline`/`sa-pipeline` mới build lớp điều phối; chưa chạy thử với dữ liệu SAD thật để xem chất lượng seed/đối chiếu ra sao.
- Máy không có `poppler` nên không tự xem trước nội dung PDF bằng công cụ — cần bạn mở file kiểm tra bằng mắt ở lần chạy đầu.
Khi có bản chạy thật đầu tiên, nên lưu lại nhận xét (đặc biệt về estimate/deck) để tinh chỉnh agent nếu cần.

View File

@@ -45,14 +45,15 @@ viết và đề xuất khung dựa trên biến thể gần nhất — không i
## Cú pháp
```
/ba-3-specification <US-id...> [--product <loại>] [--only srs|ac|nfr|api] [--lang vi,en,ko] [--out <path>] [go]
/ba-3-specification <US-id...> [--product <loại>] [--only srs|ac|nfr|api|uiconv|wf] [--proto <path|url>] [--lang vi,en,ko] [--out <path>] [go]
```
| Tham số | Ý nghĩa |
|---|---|
| `<US-id...>` | Một hoặc vài US. **Quá 3 US một lần thì chất lượng giảm rõ rệt** |
| `--product` | Ghi đè `PRODUCT` của profile cho lần chạy này. Nhiều loại: `--product screen,api-service` |
| `--only` | Chỉ sinh một loại tài liệu |
| `--only` | Chỉ sinh một loại tài liệu. `uiconv` và `wf` chỉ có với `screen` |
| `--proto` | Prototype tham chiếu: thư mục ảnh, file HTML, link Figma, hoặc mục SAD (`docs/sections/07-giao-dien.md`). Không có ⇒ skill tự tìm; vẫn không có ⇒ WF là đề xuất của BA |
| `--lang` | Ngôn ngữ text hiển thị. Bỏ qua nếu `PRODUCT` không có giao diện |
| `go` | Bỏ bước dừng xác nhận input |
@@ -71,15 +72,38 @@ Ví dụ:
- `BR` — quy tắc nghiệp vụ đã chốt
- `RBAC` — ma trận phân quyền
**Rất nên có:**
- Quy ước UI của dự án (nếu có) — để khỏi tự phát minh lại
**Rất nên có (với `screen`):**
- **Prototype tham chiếu** — Figma, HTML, ảnh, hoặc mục *Thiết kế giao diện* của SAD. Có nó,
WF của BA là bản ghi lại + đối chiếu, và **đội design không phải làm lại phần bố cục**
- Design system dự án dùng (tên + version) — để `UICONV` §11 map thành phần
- Quy ước UI sẵn có của dự án — `UICONV` chỉ bổ khuyết, không chép lại
- Danh sách mã lỗi đã dùng — để tiếp số, không mở dãy mới
- Glossary — để dùng đúng thuật ngữ
- Wireframe/prototype nếu đã có
**Nếu dự án có sẵn guideline** (như `GLOBAL_UI_CONVENTION.md`, `GLOBAL_NFR.md` của Berriz),
nói rõ đường dẫn khi gọi. Skill sẽ tuân thủ thay vì tự định nghĩa.
## `UICONV` và `WF` — phần "thay design" của bộ skill
Hai artifact chỉ sinh khi `PRODUCT = screen`:
| Artifact | Ở đâu | Sinh khi nào | Trả lời câu gì |
|---|---|---|---|
| `UICONV_<PROJECT>.md` | `00-index/` | **Một lần** ở lần chạy ba-3 đầu tiên; các lần sau bổ sung | Toàn project phân trang, toast, định dạng, trạng thái rỗng, từ vựng thành phần… thế nào |
| `WF_<US>.md` + `.html` | `03-specification/` | Mỗi US, sau bảng thành phần và bảng text | Từng màn hình: vùng nào chứa thành phần nào, trông ra sao ở từng trạng thái, khác prototype ở đâu |
Mức độ "thay design" tuỳ đầu vào:
| Đầu vào | WF là gì | Đội design còn làm gì |
|---|---|---|
| Prototype đã duyệt + design system | Bản ghi lại và đối chiếu — dev dựng UI từ WF + SRS + design system | Chỉ xử lý dòng lệch ở WF §5 |
| Prototype đã duyệt, chưa có design system | Như trên, nhưng `UICONV` §11 chưa map được component | Chọn/dựng design system, visual |
| Chỉ có mô tả UI dạng văn bản (SAD §7) | Bản ghi lại ở mức vùng; kích thước, thứ tự là đề xuất BA | Duyệt WF, làm visual |
| Không có gì | **Đề xuất của BA**, đánh dấu ✏️ | Thiết kế bố cục thật, hoặc duyệt đề xuất BA rồi làm visual |
WF **không bao giờ** thay phần visual (màu, font, icon, motion). Mục §6 của WF ghi rõ phần
Designer còn phải làm — để không ai tưởng "có WF là xong design".
## Quy trình 7 bước — bạn tham gia ở đâu
| Bước | Skill làm | Bạn làm |
@@ -91,6 +115,8 @@ nói rõ đường dẫn khi gọi. Skill sẽ tuân thủ thay vì tự định
| 5. Mã lỗi & text | Sinh bảng, đòi nguyên văn từng chuỗi | Chốt giọng văn với PO/thiết kế |
| 6. NFR | Rà 7 nhóm, đòi số đo + cách verify | Hỏi người dùng ngưỡng chấp nhận được |
| 7. API contract | Đề xuất contract, đánh dấu điểm cần BE chốt | Gửi BE xác nhận |
| 8. `UICONV` *(screen, lần đầu)* | Điền quy ước từ design system / prototype, đánh dấu ô chưa chọn | Chốt với Designer, ký |
| 9. `WF` *(screen)* | Bản đồ prototype ↔ màn hình, bảng vùng, HTML low-fi, **bảng lệch §5** | Đưa Designer duyệt (✏️) hoặc PO xác nhận bảng lệch (🎨) |
🔴 **Bước 3 và Bước 5 là hai bước cần bạn đi hỏi nhiều nhất.** Skill sẽ liệt kê chính xác
những gì còn thiếu dưới dạng `OQ` — đó là danh sách việc của bạn.
@@ -98,11 +124,15 @@ những gì còn thiếu dưới dạng `OQ` — đó là danh sách việc củ
## Bạn sẽ nhận được gì
```
ba-output/<PROJECT>/00-index/
└── UICONV_<PROJECT>_v1.0.md ← quy ước giao diện, một lần cho cả project (screen)
ba-output/<PROJECT>/03-specification/
├── SRS_<US-id>_v1.0.md ← tài liệu chính
├── AC_<US-id>_v1.0.md ← nếu tách riêng
├── NFR_<US-id>_v1.0.md
└── API_<US-id>_v1.0.md
├── API_<US-id>_v1.0.md
├── WF_<US-id>_v1.0.md ← bố cục từng màn hình + bảng lệch prototype ↔ SRS (screen)
└── WF_<US-id>_v1.0.html ← render low-fi, mở bằng trình duyệt, đổi khung nhìn/trạng thái (screen)
```
Cộng năm bảng in ra màn hình: truy vết US→AC→BR→field→mã lỗi · tự chấm G3 · checklist
@@ -184,6 +214,8 @@ Contract BA đề xuất là **giả định**, không phải sự thật.
4. **QA xác nhận mọi AC đều test được** — chữ ký hay bị bỏ qua nhất *(bỏ được ở `RIGOR = light`)*
5. Đã ký đủ theo `RIGOR`: `light` chỉ PO · `standard` PO + Tech Lead + QA · `strict` thêm
Bảo mật/Pháp chế, và API **phải do BE xác nhận**
6. *(screen)* `WF` §5 không còn lệch Tồn tại/Hành vi chưa quyết; tập `C-id` khớp hai chiều với
SRS; `UICONV` và `WF` (chế độ ✏️) có chữ ký Designer
Rồi bàn giao cho dev và chuyển sang `/ba-4-delivery-support`.

View File

@@ -1,6 +1,6 @@
---
name: ba-3-specification
description: Giai đoạn 3 của quy trình BA — viết đặc tả chi tiết tới mức dev code được và QA test được. Viết SRS/FRD cho một hoặc nhiều User Story, với PART 2 thay đổi theo loại sản phẩm - màn hình và bảng field (screen), endpoint và hợp đồng dữ liệu (api-service), luồng dữ liệu và data contract (data-pipeline), metric và ngưỡng chấp nhận (ml-model), lịch và idempotency (batch-job) - cộng acceptance criteria Given/When/Then đủ cả luồng lỗi, bảng mã lỗi, yêu cầu phi chức năng, API contract. Kích hoạt khi người dùng nói "viết SRS", "đặc tả US này", "viết acceptance criteria", "field spec", "bảng mã lỗi", "NFR", "API contract", "data contract", "spec cho dev", "ngưỡng chấp nhận cho mô hình". Input là BACKLOG đã qua G2; output vào ba-output/<PROJECT>/03-specification/ và phải qua Gate G3 (Ready for Dev) trước khi dev bắt đầu.
description: Giai đoạn 3 của quy trình BA — viết đặc tả chi tiết tới mức dev code được và QA test được. Viết SRS/FRD cho một hoặc nhiều User Story, với PART 2 thay đổi theo loại sản phẩm - màn hình và bảng field (screen), endpoint và hợp đồng dữ liệu (api-service), luồng dữ liệu và data contract (data-pipeline), metric và ngưỡng chấp nhận (ml-model), lịch và idempotency (batch-job) - cộng acceptance criteria Given/When/Then đủ cả luồng lỗi, bảng mã lỗi, yêu cầu phi chức năng, API contract; với sản phẩm có giao diện còn sinh quy ước giao diện cấp project (UICONV) và wireframe low-fi (WF markdown + HTML) đối chiếu với prototype nếu có. Kích hoạt khi người dùng nói "viết SRS", "đặc tả US này", "viết acceptance criteria", "field spec", "bảng mã lỗi", "NFR", "API contract", "data contract", "spec cho dev", "ngưỡng chấp nhận cho mô hình", "wireframe", "bố cục màn hình", "đối chiếu prototype", "quy ước UI". Input là BACKLOG đã qua G2 (+ prototype/design system nếu có); output vào ba-output/<PROJECT>/03-specification/ và phải qua Gate G3 (Ready for Dev) trước khi dev bắt đầu.
---
# GĐ3 · SPECIFICATION — Đặc tả chi tiết
@@ -10,7 +10,10 @@ Mục tiêu: **viết tới mức dev code được mà không phải đoán, QA
Đây là sản phẩm chính của nghề BA và là gate nghiêm nhất. Một chỗ mơ hồ lọt qua G3 sẽ
thành một bug hoặc một CR — với chi phí gấp nhiều lần chi phí làm rõ ở đây.
Output: `SRS` · `AC` · `NFR` · `API` (+ `WF` nếu có) trong `ba-output/<PROJECT>/03-specification/`
Output: `SRS` · `AC` · `NFR` · `API` trong `ba-output/<PROJECT>/03-specification/`.
Khi `PRODUCT = screen` thêm: `UICONV` (một lần cho cả project, ở `00-index/`) và `WF` (mỗi US,
gồm `.md` + `.html` low-fi) — hai artifact này là phần **thay vai trò design ở mức bố cục và
trạng thái** khi dự án có prototype tham chiếu, và là **đề xuất chờ Designer duyệt** khi không có.
## Bốn nguyên tắc bất di bất dịch
@@ -44,21 +47,34 @@ Ví dụ minh hoạ cho từng bước, ở nhiều domain khác nhau: `examples
4. **Phạm vi lần chạy** — liệt kê đích danh `US` sẽ đặc tả. **Quá 3 US một lần chạy thì
chất lượng giảm rõ rệt** — đề xuất chia.
5. **Biến thể PART 2 sẽ nạp** — theo `PRODUCT` (Bước 2). US có nhiều loại ⇒ nêu đủ.
6. **Guideline dự án cần tuân thủ** — tìm và nêu: quy ước UI, bộ NFR chuẩn, glossary, danh
sách mã lỗi đã dùng. Không có ⇒ nói rõ sẽ tự định nghĩa và cần ai duyệt.
6. **Guideline dự án cần tuân thủ** — tìm và nêu: `00-index/UICONV_<PROJECT>.md`, quy ước UI
sẵn có của dự án (vd `GLOBAL_UI_CONVENTION.md`), bộ NFR chuẩn, glossary, danh sách mã lỗi
đã dùng. **Chưa có `UICONV` mà `PRODUCT = screen` ⇒ lần chạy này phải sinh nó trước (Bước 8)**
và nêu ai duyệt (Designer + PO).
7. **Ngôn ngữ hiển thị** — chỉ hỏi khi `PRODUCT` có giao diện cho người. Không có ⇒ ghi N/A.
8. **Prototype / design system tham chiếu** — chỉ khi `PRODUCT = screen`. Tìm theo thứ tự:
tham số `--proto`, thư mục `design/` hoặc `prototype/` trong repo, mục *Thiết kế giao diện*
của SAD (`docs/sections/07-*.md`, `docs/SAD.md` §7), file Figma/HTML/ảnh người dùng đưa.
Trình bảng `Nguồn | Định dạng | Phiên bản | Phủ màn hình nào`. Không có ⇒ nói rõ **WF sẽ là
đề xuất của BA và cần Designer duyệt trước G3**; có ⇒ prototype là nguồn sự thật về bố cục.
Rồi **hỏi xác nhận** bảy điểm trên.
Rồi **hỏi xác nhận** tám điểm trên.
Bỏ qua khi lệnh có `go`.
## Thực hiện — 7 bước
## Thực hiện — 9 bước
Bước 1–7 cho mọi `PRODUCT`. Bước 8–9 chỉ khi `PRODUCT = screen`; loại khác ghi "N/A" trong
báo cáo cuối, không bỏ im lặng.
### Bước 1 — Khung SRS và tóm tắt nghiệp vụ
Dùng `templates/srs.md`. **Không bỏ mục nào** — mục không áp dụng thì ghi "N/A" kèm lý do,
đừng xoá; xoá mục làm người đọc không biết là đã cân nhắc hay đã quên.
Với `PRODUCT = screen`: §2.3.6 (trạng thái), §4.3 (định dạng) và mọi quy ước phân trang, toast,
vị trí nút **tham chiếu `UICONV`** thay vì định nghĩa lại. Muốn khác ⇒ ghi vào `UICONV` §12.
Viết mục **Tóm tắt nghiệp vụ** cho PO đọc: US này giải quyết `RQ` nào, người dùng được gì,
khác hiện tại chỗ nào. Ngôn ngữ nghiệp vụ, không có tên bảng dữ liệu, không có tên component.
Đây là hiện thực hoá quy tắc W10 — một tài liệu, ba người đọc.
@@ -215,9 +231,60 @@ Ba điểm phải chốt, hay bị bỏ:
- **Thời gian** dạng gì, múi giờ nào — UTC hay giờ địa phương?
- **Phân trang** offset hay cursor, có `hasNext`/`total` không?
### Bước 8 — Quy ước giao diện cấp project (`UICONV`) — chỉ `screen`
Dùng `templates/ui-convention.md`, ghi vào `00-index/UICONV_<PROJECT>.md`. **Sinh một lần** ở
lần chạy ba-3 đầu tiên của project; các lần sau chỉ đọc và bổ sung §10 (dãy mã lỗi), §11 (từ
vựng thành phần), §12 (ngoại lệ).
Nguồn điền, theo thứ tự ưu tiên: design system của dự án > prototype tham chiếu > guideline
sẵn có > **hỏi** (ghi `OQ`, không tự chọn). Mọi ô "chọn một" phải chọn xong — còn dấu `/`
giữa các phương án là chưa làm.
🔴 `UICONV` là **hợp đồng giữa BA và Design**: BA sở hữu text và trạng thái, Design sở hữu
layout và từ vựng thành phần. Cả hai ký. Dự án không có Designer ⇒ PO ký thay và ghi `DEC-nn`.
### Bước 9 — Wireframe & bố cục (`WF`) — chỉ `screen`
Dùng `templates/wireframe.md` (bảng) + `templates/wireframe.html` (render low-fi). Ghi
`WF_<US>_v1.0.md` và `WF_<US>_v1.0.html` vào `03-specification/`. Làm **sau** Bước 3 và 5, vì
WF chỉ sắp xếp những thành phần và text đã có trong SRS.
**Hai chế độ, phải khai rõ ở dòng `Nguồn bố cục` của header:**
| Chế độ | Khi nào | WF là gì | Ai duyệt |
|---|---|---|---|
| 🎨 **Prototype tham chiếu** | Có Figma / HTML / ảnh / mô tả UI đã duyệt | **Bản ghi lại** bố cục của prototype bằng bảng + đối chiếu với SRS | PO (Designer đã duyệt prototype) |
| ✏️ **BA tự dựng** | Không có prototype | **Đề xuất** bố cục theo `UICONV` | **Designer bắt buộc** ở `standard`+ |
Bốn việc, theo thứ tự:
1. **Bản đồ prototype ↔ SCR** (§1): mỗi màn hình trong `SRS` §2.1 có trong prototype không,
ở frame/trang nào. Màn hình prototype không có ⇒ BA tự dựng phần đó và đánh dấu.
2. **Bảng vùng + vị trí thành phần** (§3.x.1–2) cho **mọi** `SCR`, kể cả modal và trang lỗi.
🔴 Tập `C-id` phải **khớp hai chiều** với bảng thành phần `SRS` §2.3.1 — chạy
`grep -o "C[0-9][0-9]"` trên cả hai file và so tập. Thành phần có trong prototype mà SRS
không có ⇒ **không tự thêm vào SRS**, ghi lệch ở §5 cho PO quyết.
3. **Trạng thái, responsive, tương tác trình bày** (§3.x.3–6): hai trạng thái rỗng phải **trông**
khác nhau; mọi con số (ms, s, px) có nguồn `UICONV`/prototype, không có ⇒ `OQ`.
4. **Sinh HTML** từ bảng: mỗi `SCR` một `<section id>`, mỗi vùng `data-zone`, mỗi thành phần
`data-c` đúng C-id, mỗi trạng thái một khối `data-state`. Thành phần **chỉ có ở prototype**
(lệch loại Tồn tại ở §5) vẽ đúng chỗ prototype đặt nó bằng `<span class="proto-only"
data-ref="WF §5 #n">`, **không gán `data-c`** — khung đỏ đứt để PO nhìn thấy ngay quyết định
còn thiếu. Giữ nguyên `<style>`/`<script>` của template để mọi WF trong project trông giống
nhau. Không màu thương hiệu, không font.
**§5 Lệch prototype ↔ SRS là mục quan trọng nhất của WF.** Phân loại: Tồn tại · Hành vi · Bố
cục · Text · Trạng thái thiếu. Bên thắng theo W11: SRS thắng Tồn tại/Hành vi/Text; prototype
thắng Bố cục. Lệch Tồn tại/Hành vi chưa có người quyết ⇒ 🔴 chặn G3. Bảng rỗng vẫn phải ghi
"đã đối chiếu n màn hình, không lệch".
Điều **không** làm ở bước này: chọn màu, font, icon, khoảng cách chính xác, motion — ghi vào
§6 "Designer còn phải làm". Có prototype phủ hết ⇒ ghi "Không".
## Trước khi kết thúc
In năm thứ:
In năm thứ (sáu khi `PRODUCT = screen`):
**① Bảng truy vết** `US` → `AC` → `BR` → `field` → `mã lỗi`. Ô trống là chỗ chưa đặc tả xong.
@@ -234,10 +301,17 @@ bảng ràng buộc của PART 2 hoặc trong bảng mã lỗi ⇒ G3 không th
**⑤ `OQ` mở** — cái nào ảnh hưởng tới hành vi hệ thống thì đánh dấu 🔴 chặn G3.
**⑥ Đối chiếu WF ↔ SRS ↔ UICONV** *(chỉ `screen`)* — in: tập `C-id` lệch hai chiều (phải rỗng) ·
số dòng §5 của WF theo loại và số dòng chưa có người quyết · mục nào của SRS định nghĩa lại
thứ đã có trong `UICONV` mà không có dòng ở `UICONV` §12 · WF đang ở chế độ 🎨 hay ✏️ và
Designer đã ký chưa.
Nhắc chữ ký theo `RIGOR` (`../ba-lifecycle/references/workflow.md` §2 — G3):
`light` không cần chữ ký QA · `standard` cần **PO + Tech Lead + QA** · `strict` thêm
**Bảo mật/Pháp chế**, và API **phải do BE xác nhận**, không chấp nhận contract BA tự đề xuất.
Ở mức `standard` trở lên, QA phải xác nhận *mọi AC đều test được*.
`PRODUCT = screen` ở `standard`+ thêm **Designer** ký `UICONV` và `WF` (WF ở chế độ 🎨 thì
Designer đã duyệt prototype, chỉ cần PO xác nhận bản đồ §1 và §5 không còn lệch mở).
## Bẫy thường gặp
@@ -250,6 +324,15 @@ sai. Mỗi field phải truy về một `BR` hoặc một câu trả lời của
**Mô tả hành vi bằng ảnh.** Wireframe minh hoạ bố cục; hành vi nằm ở bảng thành phần và AC
(quy tắc W11). Viết "xem hình" ở cột hành vi là chưa đặc tả.
**Chép prototype vào SRS.** Prototype có nút mà backlog không có ⇒ đó là scope creep bằng hình
ảnh. Ghi vào WF §5, để PO quyết, không tự thêm thành phần vào bảng SRS.
**Mỗi SRS tự đặt quy ước.** Phân trang, vị trí toast, định dạng ngày phải tham chiếu `UICONV`.
Ba SRS với ba kiểu phân trang là ba màn hình người dùng phải học lại.
**WF không có bảng lệch.** WF chỉ có hình mà không có §5 là chưa đối chiếu — và đúng chỗ
prototype khác SRS là chỗ dev sẽ tự chọn một bên.
**Trộn "ẩn" với "disable".** Ba trạng thái khác nhau (W7), và người dùng phản ứng rất khác:
nút biến mất làm họ tưởng mất quyền, nút mờ có tooltip làm họ hiểu vì sao chưa bấm được.

View File

@@ -6,7 +6,9 @@
> **Tiêu chí G3 riêng của biến thể này** *(thay cho dòng "bảng field" và "wireframe" ở
> [workflow.md §2](../../../ba-lifecycle/references/workflow.md))*:
> mỗi màn hình có bảng thành phần đủ 8 cột · mỗi field có bảng field đủ 10 cột · hai trạng
> thái rỗng khác nhau · mọi thành phần có điều kiện ẩn/khoá/read-only rõ ràng.
> thái rỗng khác nhau · mọi thành phần có điều kiện ẩn/khoá/read-only rõ ràng · **có `WF_<US>`
> (md + html) phủ mọi `SCR`, tập `C-id` khớp hai chiều, bảng lệch prototype ↔ SRS không còn
> dòng Tồn tại/Hành vi chưa quyết** · quy ước chung tham chiếu `UICONV_<PROJECT>`.
---
@@ -47,7 +49,8 @@ quay lại có giữ trạng thái danh sách không, huỷ giữa chừng thì
## 2.3 SCR-01 — <Tên màn hình>
**Wireframe:** `WF_SCR-01.png` *(bố cục — hành vi xem bảng bên dưới)*
**Bố cục:** `WF_<US>_v1.0.md` §3.x · `WF_<US>_v1.0.html#SCR-01` · prototype: *(frame/trang,
hoặc "✏️ BA tự dựng")*. Hành vi xem bảng bên dưới, không suy từ hình (W11).
### 2.3.1 Bảng thành phần
@@ -147,9 +150,12 @@ lỗi trải nghiệm nghiêm trọng và rất hay xảy ra khi spec không nó
### 2.3.6 Trạng thái rỗng, đang tải, lỗi
*Cách trình bày (skeleton/spinner/banner) theo `UICONV` §6 — ở đây chỉ ghi **text riêng** cho
đối tượng của màn hình này và nút hành động. Trông thế nào, ở vùng nào: `WF` §3.x.3.*
| Trạng thái | Hiển thị gì | Text nguyên văn | Nút hành động |
|---|---|---|---|
| Đang tải | | | |
| Đang tải | theo UICONV §6 | | |
| **Chưa có dữ liệu nào** | | "Chưa có bản ghi nào. Tạo bản ghi đầu tiên?" | ✅ Tạo mới |
| **Bộ lọc không khớp** | | "Không tìm thấy kết quả phù hợp với bộ lọc." | ✅ Xoá lọc |
| Lỗi tải dữ liệu | | | ✅ Thử lại |

View File

@@ -6,8 +6,8 @@
| **Date** | YYYY-MM-DD |
| **Author** | <BA> (skill ba-3-specification) |
| **Status** | 🟡 Draft |
| **Approved by** | PO: — · Tech Lead: — · QA: — |
| **Source** | BACKLOG_… v1.0 · BR_… v1.0 · RBAC_… v1.0 · IMPACT_… v1.0 |
| **Approved by** | PO: — · Tech Lead: — · QA: — · Designer: — *(chỉ khi PRODUCT = screen)* |
| **Source** | BACKLOG_… v1.0 · BR_… v1.0 · RBAC_… v1.0 · IMPACT_… v1.0 · UICONV_… v1.0 *(screen)* |
| **Scope** | US-0nn |
| **Profile** | `screen · brownfield · standard` *(PRODUCT · LIFECYCLE · RIGOR)* |
| **Biến thể PART 2** | `srs-part2/screen.md` |
@@ -21,8 +21,10 @@
> **Quy ước đọc tài liệu này** *(quy tắc W11 — chỉ áp dụng khi `PRODUCT = screen`)*
> Bảng thành phần quyết định **một phần tử có tồn tại hay không** và **nó hành xử thế nào**.
> Wireframe quyết định **nó nằm ở đâu, to bằng nào**. Khi hai thứ mâu thuẫn: bảng thắng về
> sự tồn tại và hành vi, hình thắng về bố cục — và mâu thuẫn đó phải được báo cho BA.
> `WF_<US>.md` + `.html` (và prototype nó tham chiếu) quyết định **nó nằm ở đâu, to bằng nào,
> trông ra sao ở từng trạng thái**. `UICONV_<PROJECT>.md` quyết định **quy ước chung** (phân
> trang, toast, định dạng) — tài liệu này chỉ ghi phần khác. Khi mâu thuẫn: bảng thắng về sự
> tồn tại và hành vi, WF thắng về bố cục — và mâu thuẫn đó phải có dòng ở `WF` §5.
---
@@ -199,6 +201,8 @@ nội dung cảnh báo vận hành** — đặc tả ở PART 2 của biến th
| 8 | Không còn OQ mở ảnh hưởng hành vi | | |
| 9 | Không còn `TBD` trong bảng đặc tả PART 2 và bảng mã lỗi | | |
| 10 | Đã áp đúng bảng "Bớt ở light" / "Thêm ở strict" theo `RIGOR` | | |
| 11 | *(screen)* `WF` có cho mọi `SCR`, tập `C-id` khớp hai chiều, §5 không còn lệch Tồn tại/Hành vi chưa quyết | | |
| 12 | *(screen)* Quy ước chung tham chiếu `UICONV`; chỗ khác có dòng ở `UICONV` §12 | | |
**Quét bắt buộc trước khi nộp:**

View File

@@ -0,0 +1,211 @@
# UICONV — Quy ước giao diện — <PROJECT>
| | |
|---|---|
| **Version** | 1.0 |
| **Date** | YYYY-MM-DD |
| **Author** | <BA> (skill ba-3-specification, activity `uiconv`) |
| **Status** | 🟡 Draft |
| **Approved by** | Designer: — · PO: — |
| **Source** | <prototype / design system / SAD §7 / GLOBAL_UI_CONVENTION của dự án / DEC-nn> |
| **Scope** | Toàn project — mọi `SRS` và `WF` có `PRODUCT = screen` |
| **Profile** | `screen · … · …` |
## Change Log
| Version | Date | Người sửa | Thay đổi | CR |
|---|---|---|---|---|
| 1.0 | | | Bản đầu | — |
> **Vai trò của tài liệu này.** Một project có nhiều `SRS`, mỗi lần chạy tối đa 3 US. Không có
> tài liệu này thì mỗi `SRS` tự đặt một kiểu phân trang, một vị trí toast, một định dạng ngày.
> `SRS` và `WF` **tham chiếu** mục ở đây thay vì định nghĩa lại; muốn lệch phải ghi vào §12.
>
> **Thứ tự ưu tiên khi lệch:** Design system của dự án (nếu có) > Prototype đã duyệt > `UICONV`
> > `SRS` từng US. `SRS` chỉ được ghi khác `UICONV` khi có dòng ở §12.
---
## 0. Nguồn
| | |
|---|---|
| **Design system** | *(tên + version + link, hoặc "Chưa có — dev chọn theo NFR, quy ước ở đây là ràng buộc tối thiểu")* |
| **Prototype tham chiếu** | *(đường dẫn / URL / mục SAD, phiên bản, ngày)* |
| **Guideline sẵn có của dự án** | *(vd: GLOBAL_UI_CONVENTION.md — nếu có thì file này chỉ bổ khuyết, không chép lại)* |
| **Ai sở hữu quy ước** | BA đề xuất · **Designer duyệt** · PO duyệt phần text/giọng văn |
| **Nền tảng** | Web desktop / web responsive / app di động — *(theo BRIEF)* |
## 1. Khung layout
| | |
|---|---|
| **Grid** | *(số cột · gutter px · max-width px)* |
| **Header cố định** | Có / Không — chứa: *(logo, tìm kiếm toàn cục, ngôn ngữ, tài khoản…)* |
| **Sidebar / menu** | Trái cố định / thu gọn được / không có |
| **Footer** | Có / Không — chứa: |
| Breakpoint | Khoảng (px) | Sidebar | Bảng dữ liệu | Form |
|---|---|---|---|---|
| Desktop | ≥ 1024 | Hiện | Bảng | 2 cột |
| Tablet | 768–1023 | Thu gọn icon | Bảng cuộn ngang | 1 cột |
| Mobile | < 768 | Ẩn sau nút menu | **Card** | 1 cột |
## 2. Điều hướng
| Câu hỏi | Quy ước |
|---|---|
| Quay lại từ màn hình chi tiết/form | Nút Back **và** breadcrumb — cả hai |
| Quay lại có giữ trạng thái danh sách (trang, bộ lọc, sắp xếp)? | ✅ Giữ, qua query string |
| Vào bằng URL trực tiếp với id không tồn tại | Trang trạng thái "Không tìm thấy" + nút về danh sách |
| Vào bằng URL trực tiếp không có quyền | Trang "Không có quyền" + nút về trang chủ; **không** lộ tên bản ghi |
| Rời màn hình khi form đang dở | Modal xác nhận "Rời trang? Thay đổi chưa lưu sẽ mất." |
| Menu với chức năng không có quyền | ❌ Ẩn (W7) |
| Mở chi tiết | Cùng tab, đổi URL |
## 3. Danh sách
| | |
|---|---|
| **Kiểu phân trang** | Offset (`page`, `size`) / Cursor / Cuộn vô hạn |
| **Số dòng mỗi trang** | Mặc định … · tuỳ chọn … |
| **Sắp xếp mặc định** | *(vd: ngày tạo giảm dần)* |
| **Bấm vào dòng** | Mở chi tiết / Chỉ nút "Chi tiết" mới mở |
| **Cột hành động** | Cột cuối, icon + tooltip / Menu ⋯ |
| **Chọn nhiều dòng** | Checkbox cột đầu, thanh hành động hàng loạt xuất hiện phía trên |
| **Tìm kiếm** | Gõ rồi Enter / Gợi ý sau khi ngừng gõ … ms |
| **Bộ lọc** | Thanh ngang trên bảng (desktop) · nút "Lọc" mở bottom-sheet (mobile) |
| **Cột trên mobile** | Bảng → card; card hiện tối đa … trường: *(liệt kê thứ tự ưu tiên chung)* |
## 4. Form
| | |
|---|---|
| **Vị trí nút** | Lưu (nút chính) **bên phải**, Huỷ (nút phụ) bên trái nút Lưu |
| **Đánh dấu bắt buộc** | Dấu `*` màu cảnh báo sau nhãn |
| **Thời điểm validate** | Khi rời field (blur) **và** khi bấm Lưu |
| **Vị trí message lỗi** | Ngay dưới field, thay chỗ hint; field viền cảnh báo |
| **Lỗi nhiều field** | Focus vào field lỗi đầu tiên, cuộn tới nó |
| **Lỗi từ server không gắn field** | Banner đầu form |
| **Sau lỗi mạng/5xx** | 🔴 **Giữ nguyên dữ liệu đã nhập**, mở lại nút Lưu |
| **Đang gửi** | Khoá toàn form, spinner trong nút Lưu, nhãn đổi "Đang lưu…" |
| **Huỷ khi có thay đổi** | Modal xác nhận |
| **Nhãn field** | Trên field (không đặt cạnh trái) |
| **Nút Lưu khi form chưa hợp lệ** | Bấm được, hiện lỗi / 🔒 disable — *(chọn một)* |
## 5. Phản hồi hệ thống
| Loại | Dùng khi | Vị trí | Thời lượng | Có nút đóng |
|---|---|---|---|---|
| **Toast thành công** | Lưu/xoá thành công | Góc trên phải (desktop) · trên cùng (mobile) | 3 s tự đóng | ✅ |
| **Toast lỗi** | Lỗi không gắn field, có thể thử lại | Như trên | Không tự đóng | ✅ |
| **Modal xác nhận** | Hành động không hoàn tác được (xoá, gửi duyệt) | Giữa màn | — | Nút chính bên **phải**; hành động nguy hiểm dùng nút nguy hiểm |
| **Inline dưới field** | Lỗi validation | Dưới field | Tới khi sửa | — |
| **Banner trong vùng** | Lỗi tải một vùng dữ liệu | Trong vùng đó | Tới khi thử lại | Nút Thử lại |
| **Trang trạng thái** | 404 / 403 / lỗi toàn trang | Toàn trang | — | Nút về danh sách/trang chủ |
## 6. Trạng thái chuẩn
| Trạng thái | Hiển thị | Text mặc định (VI) | Text (EN) | Nút |
|---|---|---|---|---|
| Đang tải danh sách | Skeleton … dòng | — | — | — |
| Đang tải chi tiết/form | Skeleton theo bố cục | — | — | — |
| Đang tải cục bộ (dropdown, tính lại) | Spinner nhỏ tại chỗ | — | — | — |
| **Rỗng — chưa có dữ liệu nào** | Minh hoạ + câu dẫn + nút chính | "Chưa có <đối tượng> nào." | | Tạo mới |
| **Rỗng — bộ lọc không khớp** | Câu dẫn + nút phụ *(không minh hoạ, để khác loại trên)* | "Không tìm thấy kết quả phù hợp với bộ lọc." | | Xoá lọc |
| Lỗi tải | Banner trong vùng | "Không tải được dữ liệu." | | Thử lại |
| Không có quyền | Trang trạng thái | "Bạn không có quyền truy cập nội dung này." | | Về trang chủ |
| Không tìm thấy | Trang trạng thái | "Không tìm thấy nội dung yêu cầu." | | Về danh sách |
`SRS` §2.3.6 chỉ ghi **phần khác** với bảng này (vd: câu dẫn riêng cho đối tượng), còn lại tham chiếu.
## 7. Ẩn · khoá · read-only *(quy tắc W7)*
| Trạng thái | Trình bày | Bắt buộc kèm |
|---|---|---|
| `❌ ẩn` | Không render | — |
| `🔒 disable` | Mờ 45%, con trỏ mặc định | **Tooltip nêu lý do** khi hover/focus |
| `👁 read-only` | Giá trị dạng text, không viền ô nhập, nhãn giữ nguyên | — |
## 8. Định dạng hiển thị
*`SRS` §4.3 tham chiếu bảng này; chỉ ghi khác khi có dòng ở §12.*
| Loại | Định dạng | Ví dụ | Ghi chú |
|---|---|---|---|
| Ngày | `dd/MM/yyyy` | 30/08/2026 | |
| Ngày giờ | `dd/MM/yyyy HH:mm` | 30/08/2026 14:05 | **Múi giờ hiển thị:** … *(theo người dùng / cố định UTC+7)* |
| Lưu trữ thời gian | ISO-8601 UTC | | Khớp `API` §1 |
| Số | `#,##0` | 1.234.567 | Dấu phân cách: … |
| Tiền | `#,##0 ₫` | 1.234.567 ₫ | Làm tròn: … · đa tiền tệ: … |
| Phần trăm | `0,0 %` | 12,5 % | |
| Rỗng / null | `—` | | Thống nhất toàn hệ thống |
| Số lớn (id) | Hiển thị nguyên văn chuỗi | | Không format |
## 9. Ngôn ngữ và giọng văn
| | |
|---|---|
| **Ngôn ngữ hỗ trợ** | VI (mặc định) · EN · … — thiếu bản dịch ⇒ hiện **khoá** hay **VI**? *(chọn một)* |
| **Xưng hô** | "bạn" / không xưng hô |
| **Thông điệp lỗi** | Nói **vì sao** và **làm gì tiếp**; không mã kỹ thuật; kết thúc bằng dấu chấm |
| **Nhãn nút** | Động từ, viết hoa chữ đầu: "Tạo mới", "Lưu", "Huỷ" |
| **Tiêu đề màn hình** | Danh từ: "Danh sách cửa hàng" |
| **Độ dài nhãn tối đa** | … ký tự — để không vỡ ở ngôn ngữ dài (KO/DE) |
| **Khoá i18n** | `<scr>.<thành phần>.<thuộc tính>` — vd `scr01.search.ph` |
## 10. Dãy mã lỗi
| Dãy | Module / phạm vi | Số kế tiếp chưa dùng | Ai cấp |
|---|---|---|---|
| `E-<DOMAIN>-` | | 0001 | BA |
## 11. Từ vựng thành phần
*`WF` §3.x.2 cột "Kiểu trình bày" chỉ dùng từ ở cột đầu. Cột thứ hai map sang design system khi có.*
| Kiểu trình bày | Component trong design system | Dùng khi |
|---|---|---|
| Nút chính | | Một hành động chính mỗi màn hình |
| Nút phụ | | Huỷ, hành động thứ cấp |
| Nút nguy hiểm | | Xoá, huỷ đơn — luôn kèm modal xác nhận |
| Liên kết | | Điều hướng trong text |
| Ô nhập | | |
| Ô nhập số | | |
| Chọn 1 | | ≤ 7 lựa chọn: radio · > 7: dropdown có tìm |
| Chọn nhiều | | |
| Chọn ngày / khoảng ngày | | |
| Công tắc | | Bật/tắt có hiệu lực ngay |
| Bảng | | Desktop |
| Card | | Mobile, hoặc dữ liệu ít cột |
| Badge trạng thái | | Trạng thái vòng đời (BR §3) |
| Tab | | Nhóm nội dung cùng cấp trong một màn hình |
| Modal | | Form ngắn ≤ 6 field, xác nhận |
| Drawer | | Form dài, chi tiết nhanh |
| Bottom-sheet | | Bộ lọc trên mobile |
| Toast | | §5 |
| Skeleton | | §6 |
## 12. Ngoại lệ đã duyệt
*`SRS`/`WF` lệch quy ước ⇒ phải có dòng ở đây. Không có dòng ⇒ lệch là lỗi, không phải quyết định.*
| # | Tài liệu | Mục lệch | Quy ước | Thực tế | Vì sao | Ai duyệt | Ngày |
|---|---|---|---|---|---|---|---|
## 13. Open Questions
| ID | Câu hỏi | Hỏi ai | Từ ngày | Chặn gì |
|---|---|---|---|---|
---
## Tự chấm
| # | Tiêu chí | ☐/✅ |
|---|---|---|
| 1 | Mọi ô "chọn một" đã chọn, không còn dấu `/` giữa các phương án | |
| 2 | §6 có hai trạng thái rỗng **trông khác nhau** | |
| 3 | §8 có múi giờ hiển thị và quy tắc làm tròn tiền | |
| 4 | §11 mọi kiểu trình bày dùng trong `WF` hiện có đều có dòng | |
| 5 | Có chữ ký Designer (hoặc ghi rõ dự án không có Designer ⇒ PO ký thay, `DEC-nn`) | |

View File

@@ -0,0 +1,206 @@
<!--
WF_<US-id>_v1.0.html — wireframe low-fi tự chứa, sinh bởi skill ba-3-specification (activity wf).
QUY TẮC SINH FILE NÀY:
· Mỗi màn hình SCR-xx → một <section class="screen" id="SCR-xx">, theo đúng bảng WF §3.x.1 (vùng) và §3.x.2 (thành phần).
· Mỗi vùng Zn → <div class="zone" data-zone="Zn"> có nhãn vùng.
· Mỗi thành phần C-id → một phần tử có data-c="Cnn" và class theo kiểu trình bày (.btn-primary, .btn-secondary, .input, .select, .table, .card, .badge, .link, .label).
Tập data-c phải KHỚP HAI CHIỀU với bảng thành phần SRS §2.3.1 — đây là thứ ba-traceability kiểm.
· Trạng thái (WF §3.x.3) → các khối data-state="default|loading|empty-none|empty-filter|error|submitting" trong cùng vùng; thanh công cụ ở đầu file bật/tắt.
· Thành phần CHỈ CÓ Ở PROTOTYPE, chưa có trong SRS (WF §5 loại Tồn tại) → vẽ đúng chỗ prototype đặt nó, bọc <span class="proto-only" data-ref="WF §5 #n">…</span>,
KHÔNG gán data-c. Khung đỏ đứt để PO thấy ngay đang thiếu quyết định gì; PO quyết xong ⇒ hoặc gán C-id (SRS bổ sung) hoặc xoá khỏi WF.
· Bố cục nhiều cột (vd danh sách + sidebar tổng kết) → bọc các vùng trong <div class="cols">; ở khung nhìn mobile lớp này tự xếp chồng 1 cột (đúng WF §3.x.4). Không tự viết grid riêng.
· Không tô màu thương hiệu, không font riêng — đây là bố cục, không phải visual. Màu duy nhất được dùng: thang xám + một màu nhấn cho nút chính.
· Text hiển thị lấy nguyên văn từ SRS §4.2 (khoá i18n ghi ở data-key).
· Sửa nội dung mẫu bên dưới; giữ nguyên <style> và <script> để mọi WF trong dự án trông và thao tác giống nhau.
-->
<!doctype html>
<html lang="vi">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>WF — <US-id> — <Tên US></title>
<style>
:root{--ink:#222;--mute:#777;--line:#bbb;--fill:#eee;--fill2:#f7f7f7;--accent:#3b6ea5;--danger:#b23a3a;--bg:#fafafa}
*{box-sizing:border-box}
body{margin:0;font:14px/1.45 system-ui,Segoe UI,Roboto,sans-serif;color:var(--ink);background:var(--bg)}
header.toolbar{position:sticky;top:0;z-index:9;background:#fff;border-bottom:1px solid var(--line);padding:8px 16px;display:flex;gap:16px;align-items:center;flex-wrap:wrap}
header.toolbar h1{font-size:15px;margin:0 16px 0 0}
header.toolbar label{font-size:12px;color:var(--mute)}
header.toolbar select{font:inherit}
.legend{font-size:12px;color:var(--mute);margin-left:auto}
main{padding:24px 16px;display:grid;gap:40px;justify-items:center}
.screen{width:100%;max-width:1200px;background:#fff;border:1px solid var(--line);border-radius:6px;overflow:hidden}
.screen>h2{margin:0;padding:8px 12px;font-size:13px;font-weight:600;background:var(--fill2);border-bottom:1px dashed var(--line);color:var(--mute)}
.screen>h2 small{font-weight:400;margin-left:8px}
.body{padding:12px;display:grid;gap:12px}
.zone{border:1px dashed var(--line);border-radius:4px;padding:10px;position:relative;background:#fff;min-height:44px}
.zone::before{content:attr(data-zone) " · " attr(data-name);position:absolute;top:-8px;left:8px;background:#fff;padding:0 4px;font-size:10px;color:var(--mute);letter-spacing:.02em}
.row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.row.right{justify-content:flex-end}
.row.between{justify-content:space-between}
[data-c]{position:relative}
[data-c]::after{content:attr(data-c);position:absolute;top:-9px;right:-4px;font-size:9px;background:var(--ink);color:#fff;padding:0 4px;border-radius:3px;line-height:14px;opacity:.85}
.label{font-weight:600;font-size:16px}
.btn{display:inline-block;padding:6px 14px;border:1px solid var(--ink);border-radius:4px;background:#fff;cursor:default;white-space:nowrap}
.btn-primary{background:var(--accent);border-color:var(--accent);color:#fff}
.btn-secondary{background:#fff}
.btn-danger{border-color:var(--danger);color:var(--danger)}
.btn[aria-disabled="true"]{opacity:.45;border-style:dashed}
.link{color:var(--accent);text-decoration:underline}
.input,.select{display:inline-block;min-width:160px;padding:6px 8px;border:1px solid var(--line);border-radius:4px;background:#fff;color:var(--mute)}
.select::after{content:" ▾";float:right}
.field{display:grid;gap:4px}
.field>span{font-size:12px}
.field>span .req{color:var(--danger)}
.hint{font-size:12px;color:var(--mute)}
.table{width:100%;border-collapse:collapse}
.table th,.table td{border:1px solid var(--line);padding:6px 8px;text-align:left;font-size:13px}
.table th{background:var(--fill2)}
.card{border:1px solid var(--line);border-radius:4px;padding:10px;background:#fff}
.badge{display:inline-block;padding:0 8px;border:1px solid var(--line);border-radius:10px;font-size:12px;background:var(--fill2)}
.img{background:repeating-linear-gradient(45deg,var(--fill),var(--fill) 6px,var(--fill2) 6px,var(--fill2) 12px);border:1px solid var(--line);min-height:80px;display:grid;place-items:center;color:var(--mute);font-size:12px}
.skeleton{height:14px;background:linear-gradient(90deg,var(--fill),var(--fill2),var(--fill));border-radius:3px;margin:8px 0}
.state{padding:24px;text-align:center;color:var(--mute);border:1px dashed var(--line);border-radius:4px;display:grid;gap:10px;justify-items:center}
.state.error{border-color:var(--danger);color:var(--danger)}
.state .illus{width:80px;height:60px}
.spinner{display:inline-block;width:14px;height:14px;border:2px solid #fff;border-top-color:transparent;border-radius:50%;vertical-align:-2px;margin-right:6px}
.proto-only{display:inline-block;border:1.5px dashed var(--danger);border-radius:4px;padding:4px 8px;background:#fdf3f3;color:var(--danger);position:relative}
.proto-only::before{content:"chỉ ở prototype — " attr(data-ref);font-size:10px;border:1px solid var(--danger);border-radius:3px;padding:0 4px;margin-right:6px;vertical-align:1px}
.modal{max-width:520px;margin:0 auto;border:1px solid var(--ink);border-radius:6px;background:#fff;box-shadow:0 0 0 2000px rgba(0,0,0,.25)}
.modal .body{padding:16px}
[data-state]{display:none}
[data-state="default"]{display:block}
body[data-view="mobile"] .screen{max-width:390px}
body[data-view="mobile"] .m-hide{display:none!important}
body[data-view="mobile"] .body,body[data-view="mobile"] .cols{grid-template-columns:1fr!important;display:grid}
.cols{display:grid;grid-template-columns:2fr 1fr;gap:12px;align-items:start}
body[data-view="mobile"] .m-stack{flex-direction:column;align-items:stretch}
body[data-view="desktop"] .d-hide{display:none!important}
body[data-view="mobile"] .table{display:none}
body[data-view="mobile"] .cards{display:grid!important;gap:8px}
.cards{display:none}
footer.note{padding:16px;font-size:12px;color:var(--mute);text-align:center}
</style>
</head>
<body data-view="desktop">
<header class="toolbar">
<h1>WF — <US-id> · <Tên US></h1>
<label>Khung nhìn
<select id="view"><option value="desktop">Desktop ≥1024</option><option value="mobile">Mobile &lt;768</option></select>
</label>
<label>Trạng thái
<select id="state">
<option value="default">Mặc định (có dữ liệu)</option>
<option value="loading">Đang tải</option>
<option value="empty-none">Rỗng — chưa có dữ liệu nào</option>
<option value="empty-filter">Rỗng — bộ lọc không khớp</option>
<option value="error">Lỗi tải dữ liệu</option>
<option value="submitting">Đang gửi</option>
</select>
</label>
<span class="legend">Nhãn đen = C-id trong SRS §2.3.1 · khung đứt xám = vùng Zn trong WF §3.x.1 · <b style="color:var(--danger)">khung đứt đỏ</b> = chỉ có ở prototype, chưa có trong SRS (WF §5) · hành vi xem SRS, không suy từ hình</span>
</header>
<main>
<!-- ============================ SCR-01 (mẫu: màn hình danh sách) ============================ -->
<section class="screen" id="SCR-01">
<h2>SCR-01 · <Tên màn hình> <small>Danh sách · vào từ Menu · vai trò: ROLE-01, ROLE-02</small></h2>
<div class="body">
<div class="zone" data-zone="Z1" data-name="Header màn hình">
<div class="row between">
<span class="label" data-c="C01" data-key="scr01.title">Tiêu đề màn hình</span>
<span class="btn btn-primary" data-c="C02" data-key="btn.create">Tạo mới</span>
</div>
</div>
<div class="zone" data-zone="Z2" data-name="Thanh lọc">
<div class="row m-stack">
<span class="input" data-c="C03" data-key="scr01.search.ph">Nhập mã hoặc tên…</span>
<span class="select m-hide" data-c="C04" data-key="scr01.filter.status">Trạng thái: Tất cả</span>
<span class="btn btn-secondary d-hide" data-key="btn.filter">Lọc</span>
</div>
</div>
<div class="zone" data-zone="Z3" data-name="Dữ liệu">
<div data-state="default">
<table class="table" data-c="C05">
<thead><tr><th>Mã</th><th>Tên</th><th>Trạng thái</th><th>Ngày tạo</th><th></th></tr></thead>
<tbody>
<tr><td>STR-001</td><td>Cửa hàng A</td><td><span class="badge">Nháp</span></td><td>30/08/2026</td><td><span class="link">Chi tiết</span></td></tr>
<tr><td>STR-002</td><td>Cửa hàng B</td><td><span class="badge">Đã duyệt</span></td><td>29/08/2026</td><td><span class="link">Chi tiết</span></td></tr>
</tbody>
</table>
<div class="cards" data-c="C05">
<div class="card"><div class="row between"><b>STR-001</b><span class="badge">Nháp</span></div><div>Cửa hàng A</div><div class="hint">30/08/2026</div></div>
<div class="card"><div class="row between"><b>STR-002</b><span class="badge">Đã duyệt</span></div><div>Cửa hàng B</div><div class="hint">29/08/2026</div></div>
</div>
</div>
<div data-state="loading"><div class="skeleton"></div><div class="skeleton" style="width:85%"></div><div class="skeleton" style="width:92%"></div></div>
<div data-state="empty-none"><div class="state"><div class="img illus">minh hoạ</div><span data-key="empty.none">Chưa có bản ghi nào. Tạo bản ghi đầu tiên?</span><span class="btn btn-primary" data-key="btn.create">Tạo mới</span></div></div>
<div data-state="empty-filter"><div class="state"><span data-key="empty.filter">Không tìm thấy kết quả phù hợp với bộ lọc.</span><span class="btn btn-secondary" data-key="btn.clearFilter">Xoá lọc</span></div></div>
<div data-state="error"><div class="state error"><span data-key="error.load">Không tải được dữ liệu.</span><span class="btn btn-secondary" data-key="btn.retry">Thử lại</span></div></div>
</div>
<div class="zone" data-zone="Z4" data-name="Phân trang">
<div class="row between">
<span class="proto-only" data-ref="WF §5 #1">Nút "Xuất Excel" — prototype có, BACKLOG không có US ⇒ PO quyết</span>
<span class="row" data-c="C06"><span class="btn btn-secondary">‹</span><span>1 / 7</span><span class="btn btn-secondary">›</span><span class="select m-hide">20 dòng</span></span>
</div>
</div>
</div>
</section>
<!-- ============================ SCR-03 (mẫu: form trong modal) ============================ -->
<section class="screen" id="SCR-03">
<h2>SCR-03 · <Tên form> <small>Modal · mở từ C02 · vai trò: ROLE-01, ROLE-02</small></h2>
<div class="body">
<div class="modal">
<div class="body">
<div class="zone" data-zone="Z1" data-name="Tiêu đề modal">
<div class="row between"><span class="label" data-c="C01" data-key="scr03.title">Tạo mới</span><span class="link" data-c="C08" data-key="btn.close">✕</span></div>
</div>
<div class="zone" data-zone="Z2" data-name="Form">
<div class="body">
<label class="field"><span data-key="f01.label">Mã <b class="req">*</b></span><span class="input" data-c="F01" data-key="f01.ph">3–20 ký tự, A–Z 0–9 -</span><span class="hint" data-key="f01.hint">Không trùng với mã đã có</span></label>
<label class="field"><span data-key="f02.label">Loại <b class="req">*</b></span><span class="select" data-c="F02">Thường</span></label>
<label class="field"><span data-key="f03.label">Tên</span><span class="input" data-c="F03" data-key="f03.ph">Tên hiển thị</span></label>
</div>
</div>
<div class="zone" data-zone="Z3" data-name="Hành động">
<div class="row right">
<span class="btn btn-secondary" data-c="C07" data-key="btn.cancel">Huỷ</span>
<span data-state="default" style="display:inline"><span class="btn btn-primary" data-c="C09" data-key="btn.save">Lưu</span></span>
<span data-state="submitting"><span class="btn btn-primary" data-c="C09" aria-disabled="true"><i class="spinner"></i>Đang lưu…</span></span>
</div>
</div>
</div>
</div>
<p class="hint">Field F01–F03 tham chiếu bảng field SRS §2.3.3. Thất bại ⇒ giữ nguyên dữ liệu đã nhập (AC-09), lỗi hiện dưới field theo UICONV §4.</p>
</div>
</section>
</main>
<footer class="note">Wireframe low-fi · bố cục và trạng thái · không phải thiết kế visual · nguồn hành vi: SRS_<US-id> · nguồn quy ước: UICONV_<PROJECT></footer>
<script>
(function(){
var view=document.getElementById('view'),state=document.getElementById('state');
function apply(){
document.body.setAttribute('data-view',view.value);
var s=state.value;
document.querySelectorAll('[data-state]').forEach(function(el){
var on=el.getAttribute('data-state')===s || (s==='submitting'&&el.getAttribute('data-state')==='default'&&!el.closest('.zone[data-name="Hành động"]'));
el.style.display=on?(el.tagName==='SPAN'?'inline':'block'):'none';
});
}
view.addEventListener('change',apply);state.addEventListener('change',apply);apply();
})();
</script>
</body>
</html>

View File

@@ -0,0 +1,204 @@
# WF — Wireframe & bố cục — <US-id>
| | |
|---|---|
| **Version** | 1.0 |
| **Date** | YYYY-MM-DD |
| **Author** | <BA> (skill ba-3-specification, activity `wf`) |
| **Status** | 🟡 Draft |
| **Approved by** | Designer: — · PO: — |
| **Source** | SRS_… v1.0 · UICONV_<PROJECT> v1.0 · <prototype: đường dẫn/URL + phiên bản> |
| **Scope** | US-0nn · SCR-01, SCR-02, … |
| **Nguồn bố cục** | 🎨 **Prototype tham chiếu** `<path>` / ✏️ **BA tự dựng — chờ Designer duyệt** |
| **Tệp kèm** | `WF_<US-id>_v1.0.html` *(low-fi render, mở bằng trình duyệt)* |
## Change Log
| Version | Date | Người sửa | Thay đổi | CR |
|---|---|---|---|---|
| 1.0 | | | Bản đầu | — |
> **Quy ước đọc** *(quy tắc W11)*. Bảng thành phần trong `SRS` §2.3.1 quyết định **một phần tử
> có tồn tại không** và **hành xử thế nào**. Tài liệu này và tệp HTML kèm theo quyết định **nó
> nằm ở đâu, thứ tự nào, to bằng nào, trông ra sao ở từng trạng thái**. Mâu thuẫn ⇒ SRS thắng
> về tồn tại/hành vi, WF thắng về bố cục — và mâu thuẫn đó **phải được ghi ở §5**, không im lặng.
---
## 0. Nguồn bố cục và độ tin cậy
| | |
|---|---|
| **Prototype tham chiếu** | *(đường dẫn / URL Figma / thư mục ảnh / mục SAD §7 · phiên bản · ngày · ai cung cấp)* |
| **Định dạng** | Figma / HTML tương tác / ảnh tĩnh / mô tả văn bản / **không có** |
| **Mức phủ** | n / m màn hình của US này có trong prototype |
| **Design system** | *(tên + version, hoặc "chưa có — dùng `UICONV` §11")* |
| **Độ tin cậy** | 🎨 Prototype đã được PO/Design duyệt ⇒ WF là **bản ghi lại** · ✏️ Không có prototype ⇒ WF là **đề xuất của BA**, Designer phải duyệt trước G3 |
🔴 **Có prototype thì prototype là nguồn sự thật về bố cục**, WF chỉ ghi lại và đối chiếu với
SRS. Không có prototype thì WF là đề xuất, và dòng `Approved by: Designer` là **bắt buộc** khi
`PRODUCT = screen` ở mức `standard` trở lên.
## 1. Bản đồ prototype ↔ màn hình
*Một dòng cho mỗi `SCR` trong `SRS` §2.1. Màn hình không có trong prototype ⇒ ghi rõ, và mục
§3 tương ứng do BA tự dựng.*
| SCR | Tên màn hình | Có trong prototype | Frame / trang / mục trong prototype | Mức khớp với SRS | Ghi chú |
|---|---|---|---|---|---|
| SCR-01 | | ✅ / ❌ | *(vd: Figma frame "Cart / Desktop", hoặc SAD §7.1.1 SCR-04)* | ✅ khớp · 🟠 khác bố cục · 🔴 khác tồn tại/hành vi | → §5 nếu 🟠/🔴 |
## 2. Khung bố cục chung
*Lấy từ `UICONV` §1 nếu đã có. Chỉ ghi lại phần **khác** hoặc **bổ sung** cho US này.*
| | |
|---|---|
| **Grid** | *(số cột · gutter · max-width, đơn vị px — nguồn: UICONV / prototype)* |
| **Vùng cố định** | Header · Sidebar · Footer — *(có / không, nội dung, tham chiếu UICONV §1)* |
| Breakpoint | Khoảng (px) | Bố cục | Nguồn |
|---|---|---|---|
| Desktop | ≥ 1024 | | UICONV §1 |
| Tablet | 768–1023 | | |
| Mobile | < 768 | | |
---
## 3. Bố cục từng màn hình
*Lặp mục này cho **mọi** `SCR` của US, kể cả modal và trang lỗi.*
### 3.1 SCR-01 — <Tên màn hình>
| | |
|---|---|
| **Loại** | Danh sách / Chi tiết / Form / Modal / Trang trạng thái |
| **Prototype** | *(frame/trang cụ thể, hoặc "✏️ BA tự dựng")* |
| **HTML** | `WF_<US-id>_v1.0.html#SCR-01` |
| **Thành phần (SRS §2.3.1)** | C01 … C0n — *(số lượng phải khớp bảng thành phần)* |
#### 3.1.1 Bảng vùng
*Bảng này thay cho hình vẽ: mỗi vùng là một khối trên màn hình. Tệp HTML render đúng theo bảng này.*
| Vùng | Tên | Vị trí desktop | Vị trí mobile | Chứa thành phần | Chiều rộng | Ưu tiên hiển thị |
|---|---|---|---|---|---|---|
| Z1 | Header màn hình | Hàng 1, full | Hàng 1 | C01 (tiêu đề), C02 (nút Tạo mới) | 100% | 1 |
| Z2 | Thanh lọc | Hàng 2, full | Hàng 2, thu gọn thành nút "Lọc" | C03, C04 | 100% | 2 |
| Z3 | Bảng dữ liệu | Hàng 3, full | Hàng 3, dạng card | C05 | 100% | 1 |
| Z4 | Phân trang | Hàng 4, phải | Hàng 4, giữa | C06 | auto | 3 |
*Ưu tiên hiển thị: 1 = luôn hiện · 2 = có thể gộp/thu gọn ở mobile · 3 = có thể ẩn sau nút.*
#### 3.1.2 Vị trí thành phần
*Mọi `C-id` trong `SRS` §2.3.1 phải có ở đây. `C-id` có ở đây mà không có trong SRS ⇒ lỗi
(thành phần chưa được đặc tả hành vi).*
| C-id | Tên thành phần | Vùng | Thứ tự trong vùng | Kích thước / độ rộng | Kiểu trình bày | Phần tử trong prototype | Khớp |
|---|---|---|---|---|---|---|---|
| C01 | lbl_title | Z1 | 1 | auto | Tiêu đề cấp 1 | | ✅ |
| C02 | btn_create | Z1 | 2 (phải) | auto | **Nút chính** | | ✅ |
| C03 | txt_search | Z2 | 1 | 320px | Ô nhập có icon tìm | | 🟠 |
**Kiểu trình bày** dùng từ vựng của `UICONV` §11 (nút chính / nút phụ / nút nguy hiểm / liên
kết / ô nhập / chọn 1 / chọn nhiều / bảng / card / badge trạng thái …). Không tự đặt tên mới.
#### 3.1.3 Trạng thái hiển thị
*Hành vi và text lấy từ `SRS` §2.3.6 và §4.2. Ở đây chỉ nói **trông thế nào và ở vùng nào**.*
| Trạng thái | Vùng thay đổi | Hiển thị gì | Khoá text (SRS §4.2) | Nút hành động |
|---|---|---|---|---|
| Đang tải lần đầu | Z3 | Skeleton n dòng *(theo UICONV §6)* | — | — |
| **Chưa có dữ liệu nào** | Z3 | Minh hoạ + câu dẫn + nút chính | `empty.none` | C02 Tạo mới |
| **Bộ lọc không khớp** | Z3 | Câu dẫn + nút phụ | `empty.filter` | Xoá lọc |
| Lỗi tải dữ liệu | Z3 | Banner lỗi trong vùng + nút thử lại | `error.load` | Thử lại |
| Đang gửi (form) | Nút gửi | Spinner trong nút, khoá form | — | — |
🔴 Hai trạng thái rỗng **phải trông khác nhau**, không chỉ khác câu chữ.
#### 3.1.4 Responsive
| Breakpoint | Thay đổi so với desktop | Thành phần ẩn / gộp / đổi kiểu |
|---|---|---|
| Tablet | Z2 xuống 2 hàng | — |
| Mobile | Z3 đổi bảng → card; Z2 thu vào nút "Lọc" mở bottom-sheet | C04 gộp vào bottom-sheet |
#### 3.1.5 Tương tác trình bày
*Chỉ phần **trình bày** (hành vi nghiệp vụ đã ở SRS). Mọi con số phải có nguồn — không có ⇒ `OQ`.*
| Thành phần | Sự kiện | Phản hồi trình bày | Ngưỡng / thời lượng | Nguồn |
|---|---|---|---|---|
| C03 txt_search | Gõ | Gợi ý sau khi ngừng gõ | 300 ms | UICONV §4 |
| Toàn màn | Lưu thành công | Toast góc trên phải | 3 s, tự đóng | UICONV §5 |
| C05 bảng | Hover dòng | Đổi nền dòng | — | UICONV §11 |
#### 3.1.6 Thứ tự focus *(màn hình có nhập liệu)*
| Thứ tự | C-id | Ghi chú |
|---|---|---|
| 1 | C03 | Focus mặc định khi vào màn hình |
---
### 3.2 SCR-02 — <Tên màn hình>
*(lặp cấu trúc 3.1)*
---
## 4. Luồng màn hình theo prototype
*Chỉ khi prototype có tương tác. Đối chiếu với sơ đồ điều hướng `SRS` §2.2 — cạnh có trong
prototype mà SRS không có, hoặc ngược lại, ghi vào §5.*
| Từ | Hành động | Đến | Có trong SRS §2.2 | Có trong prototype |
|---|---|---|---|---|
| SCR-01 | Bấm dòng | SCR-02 | ✅ | ✅ |
| SCR-03 | Huỷ giữa chừng | SCR-01 | ✅ | ❌ *(prototype không vẽ nút Huỷ)* → §5 |
## 5. Lệch giữa prototype và SRS
*Bảng bắt buộc, kể cả khi rỗng (ghi "Không phát hiện lệch, đã đối chiếu n màn hình").*
| # | Màn hình | Prototype có | SRS nói | Loại lệch | Bên thắng theo W11 | Xử lý | Ai quyết | Trạng thái |
|---|---|---|---|---|---|---|---|---|
| 1 | SCR-03 | Không có nút Huỷ | C07 btn_cancel tồn tại | Tồn tại | **SRS** | Thêm vào WF, báo Design cập nhật prototype | Designer | ☐ |
| 2 | SCR-01 | Bộ lọc ở sidebar trái | Bảng vùng ghi hàng 2 | Bố cục | **Prototype** | Sửa WF theo prototype | — | ✅ |
| 3 | SCR-01 | Nút "Tạo" | Nhãn "Tạo mới" | Text | **SRS** (BA sở hữu text, W5) | Design đổi nhãn | Designer | ☐ |
Loại lệch: **Tồn tại** · **Hành vi** · **Bố cục** · **Text** · **Trạng thái thiếu**.
Lệch loại *Tồn tại* hoặc *Hành vi* chưa được quyết ⇒ 🔴 **chặn G3**.
## 6. Bàn giao
| | |
|---|---|
| **Designer còn phải làm** | *(visual: màu, typography, icon, minh hoạ trạng thái rỗng, motion… — hoặc "Không: prototype đã phủ toàn bộ")* |
| **Dev dùng WF để** | Dựng layout và chọn component theo §3.x.2; **không** suy ra hành vi từ WF |
| **Không được suy ra từ WF** | Khoảng cách/kích thước chính xác nếu chưa có design system; màu; font |
| **Khi prototype thay đổi** | Design báo BA ⇒ cập nhật §1, §5 và version WF; SRS chỉ đổi nếu lệch loại Tồn tại/Hành vi |
## 7. Open Questions
| ID | Câu hỏi | Hỏi ai | Từ ngày | Chặn gì | 🔴 chặn G3? |
|---|---|---|---|---|---|
---
## Tự chấm
| # | Tiêu chí | ☐/✅ | Ghi chú |
|---|---|---|---|
| 1 | Mọi `SCR` trong `SRS` §2.1 có một mục §3 | | |
| 2 | Mọi `C-id` khớp **hai chiều** giữa `SRS` §2.3.1 và WF §3.x.2 | | *chạy: grep -o "C[0-9][0-9]" cả hai file, so tập* |
| 3 | Mỗi màn hình có §3.x.3 với **hai trạng thái rỗng trông khác nhau** | | |
| 4 | Mỗi màn hình web có responsive ≥ 2 breakpoint | | |
| 5 | Mọi con số ở §3.x.5 có nguồn (UICONV / prototype / OQ) | | |
| 6 | §5 đã điền, mọi lệch Tồn tại/Hành vi có người quyết | | |
| 7 | Tệp HTML mở được, mỗi `SCR` một `<section id>`, mỗi thành phần có `data-c` khớp C-id | | |
| 8 | Kiểu trình bày chỉ dùng từ vựng `UICONV` §11 | | |
| 9 | Có chữ ký Designer *(bắt buộc ở `standard`+ khi WF do BA tự dựng)* | | |

View File

@@ -68,9 +68,11 @@ bảng "Thêm ở strict". Ghi mức đang chấm ngay đầu bảng pipeline.
Chấm **thật**: mở artifact và kiểm tra mục bắt buộc có nội dung hay chỉ là khung rỗng. Một
file tồn tại nhưng các mục còn `TBD` ⇒ **chưa đạt**, không được đánh ✅.
**Tiêu chí phụ thuộc `PRODUCT`**: dòng "bảng field" và "wireframe" của G3 chỉ áp cho
`PRODUCT = screen`. Loại khác dùng tiêu chí ghi ở đầu file
`ba-3-specification/templates/srs-part2/<loại>.md`.
**Tiêu chí phụ thuộc `PRODUCT`**: dòng "bảng field" và bốn dòng *(screen)* của G3 (`UICONV`
tồn tại và có chữ ký Designer · `WF` phủ mọi SCR, `C-id` khớp hai chiều · `WF` §5 không còn lệch
Tồn tại/Hành vi chưa quyết · WF ✏️ có Designer ký) chỉ áp cho `PRODUCT = screen`. Loại khác
dùng tiêu chí ghi ở đầu file `ba-3-specification/templates/srs-part2/<loại>.md`.
Khi chấm G3 cho `screen`, mở cả `00-index/UICONV_*.md` và `03-specification/WF_*.md`.
Ba trạng thái, không có trạng thái thứ tư:

View File

@@ -17,7 +17,8 @@
| `AC` | Acceptance Criteria (nếu tách khỏi SRS) | `03-specification/` | ba-3 | QA |
| `API` | API contract đề xuất | `03-specification/` | ba-3 | Dev BE/FE |
| `NFR` | Yêu cầu phi chức năng | `03-specification/` | ba-3 | Dev, Ops, QA |
| `WF` | Wireframe / Prototype | `03-specification/` | ba-3 | Dev, PO |
| `WF` | Wireframe & bố cục (`.md` bảng vùng/thành phần/lệch + `.html` low-fi) — chỉ `PRODUCT = screen` | `03-specification/` | ba-3 (activity `wf`) | Dev FE, Designer, PO |
| `UICONV` | Quy ước giao diện cấp project — chỉ `PRODUCT = screen`, sinh một lần | `00-index/` | ba-3 (activity `uiconv`) | Dev FE, Designer, mọi SRS/WF |
| `QLOG` | Clarification log | `04-delivery/` | ba-4 | Dev, QA |
| `CR` | Change Request | `04-delivery/` | ba-4 | PO, PM, Dev |
| `TCREVIEW` | Biên bản review test case | `04-delivery/` | ba-4 | QA |
@@ -128,14 +129,22 @@ flowchart LR
SRS --> AC["AC"]
SRS --> API["API"]
SRS --> NFR["NFR"]
SRS --> WF["WF"]
UICONV["UICONV"] --> SRS
UICONV --> WF["WF"]
SRS --> WF
PROTO[["Prototype / design system (ngoài bộ BA)"]] -.-> UICONV
PROTO -.-> WF
AC --> UAT["UAT"]
UAT --> BENEFIT["BENEFIT"]
UAT --> RELNOTE["RELNOTE"]
UAT --> MANUAL["MANUAL"]
```
**RTM đọc:** `BRIEF`(RQ) · `BACKLOG`(US) · `SRS`+`AC`(AC, field, mã lỗi) · `UAT`(test case) · `CR`
**RTM đọc:** `BRIEF`(RQ) · `BACKLOG`(US) · `SRS`+`AC`(AC, field, mã lỗi) · `WF`(C-id, SCR) · `UAT`(test case) · `CR`
`WF` và `UICONV` chỉ tồn tại khi `PRODUCT = screen`. `WF` **không** là nguồn sự thật về hành
vi — nó tham chiếu ngược về `SRS`; đổi prototype ⇒ đổi `WF`, `SRS` chỉ đổi khi lệch loại
Tồn tại/Hành vi được PO chấp nhận (qua `CR` nếu SRS đã Baselined).
Đọc xuôi mũi tên để biết **sửa cái này thì phải sửa tiếp cái nào**. Ví dụ sửa một `BR` ⇒
phải rà lại `SRS`, `AC`, test case, và cập nhật `RTM`.

View File

@@ -267,7 +267,7 @@ Ba trường hợp, và cách xử lý:
| Trường hợp | Làm gì |
|---|---|
| Bố cục màn hình | Wireframe ảnh — mermaid không phải công cụ vẽ UI |
| Bố cục màn hình | `WF_<US>.md` (bảng vùng + bảng vị trí thành phần) **và** `WF_<US>.html` low-fi sinh từ `ba-3-specification/templates/wireframe.html` — mermaid không phải công cụ vẽ UI, ASCII art càng không. Có prototype thì WF ghi lại và đối chiếu; không có thì WF là đề xuất của BA |
| Ma trận ≥ 3×3, bảng số liệu | Bảng markdown |
| Sơ đồ > 20 node | Tách thành nhiều sơ đồ theo phân vùng, mỗi cái một mục con |

View File

@@ -116,7 +116,7 @@ Quyết định **gate chặt tới đâu và ai phải ký**. `standard` là ba
| Giá trị | Dùng khi | Ký gate |
|---|---|---|
| `light` | POC, thử nghiệm, công cụ nội bộ ≤ 2 tuần, không đụng tiền/dữ liệu cá nhân | Chỉ PO |
| `standard` | Mặc định — sản phẩm thật, có người dùng thật | PO + Tech Lead + QA (theo từng gate) |
| `standard` | Mặc định — sản phẩm thật, có người dùng thật | PO + Tech Lead + QA (theo từng gate); `PRODUCT = screen` thêm **Designer ở G3** (`UICONV`, `WF`) |
| `strict` | Có tiền, dữ liệu cá nhân, yêu cầu pháp lý, chịu kiểm toán (tài chính, y tế, bảo hiểm) | Như standard **+ Bảo mật/Pháp chế ở G2 và G3** |
Chi tiết tiêu chí bớt/thêm theo từng gate: [workflow.md §2.0](workflow.md).

View File

@@ -15,7 +15,7 @@ flowchart TD
START --> GD1
GD1 -->|"G1 — PO ký: bài toán & phạm vi đã đúng"| GD2
GD2 -->|"G2 — PO + Tech Lead ký: khả thi, backlog đủ"| GD3
GD3 -->|"G3 — PO + Tech Lead + QA ký: Ready for Dev"| GD4
GD3 -->|"G3 — PO + Tech Lead + QA (+ Designer nếu screen) ký: Ready for Dev"| GD4
GD4 -->|"G4 — PO ký UAT pass: Go-live"| GD5
GD5 -->|"G5 — Benefit review"| END
@@ -91,7 +91,7 @@ giải quyết được pain point đã ghi ở G1.
| `IMPACT` rút gọn: chỉ trục dữ liệu và tích hợp | Mọi `ASM` phải chuyển sang **đã xác minh** trước khi qua G2 (thay vì trước G3) |
| Ký: chỉ PO | Ký: PO + Tech Lead + Bảo mật |
### G3 — Ready for Dev · duyệt bởi **PO + Tech Lead + QA**
### G3 — Ready for Dev · duyệt bởi **PO + Tech Lead + QA** (+ **Designer** khi `PRODUCT = screen`)
- [ ] `SRS` đủ mọi mục bắt buộc (xem `ba-3-specification/templates/srs.md`)
- [ ] Mỗi màn hình có bảng field: kiểu, bắt buộc, độ dài, default, validation, message lỗi
@@ -99,16 +99,20 @@ giải quyết được pain point đã ghi ở G1.
- [ ] Bảng mã lỗi `E-<DOMAIN>-nnnn` đầy đủ, mỗi mã có thông điệp hiển thị
- [ ] `NFR` đã chốt cho các nhóm áp dụng, mỗi cái có cách verify
- [ ] `API` contract có, hoặc ghi rõ là **giả định của BA** chờ BE xác nhận
- [ ] Wireframe/prototype khớp với bảng component
- [ ] *(screen)* `UICONV_<PROJECT>` tồn tại, không còn ô "chọn một" chưa chọn, có chữ ký Designer (hoặc PO + `DEC-nn` khi dự án không có Designer)
- [ ] *(screen)* `WF_<US>` (md + html) phủ **mọi** `SCR` của SRS; tập `C-id` khớp **hai chiều** với bảng thành phần
- [ ] *(screen)* `WF` §5 (lệch prototype ↔ SRS) đã điền; không còn lệch **Tồn tại/Hành vi** chưa có người quyết
- [ ] *(screen)* `WF` chế độ ✏️ (BA tự dựng) có chữ ký Designer; chế độ 🎨 (prototype tham chiếu) có PO xác nhận §1 và §5
- [ ] QA xác nhận **mọi AC đều test được** — AC không test được là AC chưa viết xong
- [ ] Không còn `OQ` mở nào ảnh hưởng tới hành vi hệ thống
- [ ] `ba-traceability` báo coverage US→AC và AC→test case ≥ 100%
- [ ] `ba-traceability` báo coverage US→AC và AC→test case ≥ 100%, và *(screen)* SRS↔WF `C-id` lệch = 0
**Chặn:** còn bất kỳ `TBD` nào trong bảng field hoặc bảng mã lỗi. Còn `OQ` mở về hành vi.
*(screen)* Còn lệch Tồn tại/Hành vi giữa prototype và SRS chưa quyết.
**Đây là gate nghiêm nhất** — một chỗ mơ hồ lọt qua G3 sẽ thành một bug hoặc một CR.
> Checklist trên viết theo `PRODUCT = screen`. Loại khác thì dòng "bảng field" và "wireframe"
> được thay bằng tiêu chí tương ứng của biến thể PART 2 — xem đầu file
> Checklist trên viết theo `PRODUCT = screen`. Loại khác thì dòng "bảng field" và bốn dòng
> *(screen)* được thay bằng tiêu chí tương ứng của biến thể PART 2 — xem đầu file
> `ba-3-specification/templates/srs-part2/<loại>.md`.
| Bớt ở `light` | Thêm ở `strict` |
@@ -116,7 +120,8 @@ giải quyết được pain point đã ghi ở G1.
| `AC` chỉ bắt buộc nhóm 1 (thành công) và 2 (validation). Nhóm 3–4 bắt buộc **nếu** có ghi/xoá dữ liệu hoặc có >1 vai trò | Bảng lưu vết (`NFR-AUD`) bắt buộc cho mọi hành động ghi |
| `NFR` chỉ bắt buộc nhóm áp dụng rõ ràng; các nhóm khác ghi "N/A — POC" | Mọi mã lỗi phải có bản dịch đủ mọi ngôn ngữ hỗ trợ, không được để sau |
| `API` được phép là phác thảo, không cần bảng đối chiếu mã lỗi | `API` phải do BE xác nhận, **không chấp nhận contract BA tự đề xuất** |
| Không cần chữ ký QA | Ký: PO + Tech Lead + QA + Bảo mật/Pháp chế |
| *(screen)* `WF` chỉ cần bảng vùng + bảng lệch, không cần HTML; `UICONV` chỉ cần §3–§6, §8 | *(screen)* `WF` phải có responsive đủ mọi breakpoint của `UICONV` §1 và thứ tự focus cho mọi form |
| Không cần chữ ký QA; Designer không bắt buộc (PO ký `WF`) | Ký: PO + Tech Lead + QA + Designer + Bảo mật/Pháp chế |
### G4 — UAT pass · duyệt bởi **PO**
@@ -162,11 +167,17 @@ cách một POC mang theo mọi thiếu sót của nó vào sản phẩm thật.
| **PO / Khách hàng** | Quyết ưu tiên và scope. Ký G1, G4, G5. Trả lời `OQ` nghiệp vụ |
| **Tech Lead** | Ký G2, G3 về mặt khả thi. Quyết kiến trúc. Trả lời `OQ` kỹ thuật |
| **QA** | Ký G3 về tính test được. Viết test case từ AC. Chủ trì thực thi UAT |
| **Dev** | Tiêu thụ SRS. Đặt `OQ` qua `QLOG` |
| **Designer** *(khi `PRODUCT = screen`)* | Sở hữu prototype, design system, visual. Ký `UICONV` và `WF` ở G3. Trả lời lệch loại *Bố cục* ở `WF` §5. Nhận từ BA: kho thành phần, text nguyên văn, trạng thái, phân quyền hiển thị — **không phải đi hỏi lại nghiệp vụ** |
| **Dev** | Tiêu thụ SRS + WF + UICONV. Đặt `OQ` qua `QLOG` |
| **PM** | Tiến độ, nguồn lực. Không ký gate nội dung |
BA **không** thay PO quyết ưu tiên, **không** thay Tech Lead chọn kiến trúc, **không** thay
PM quản tiến độ — nhưng phải cung cấp đủ thông tin để cả ba ra quyết định.
PM quản tiến độ, **không** thay Designer quyết visual — nhưng phải cung cấp đủ thông tin để
cả bốn ra quyết định. Riêng phần **bố cục và trạng thái**, BA làm được khi có prototype tham
chiếu (chế độ 🎨 của `WF`); không có thì BA đề xuất, Designer quyết (chế độ ✏️).
**Dự án không có Designer:** ghi `DEC-nn`, PO ký thay `UICONV`/`WF`, và mục §6 của `WF`
("Designer còn phải làm") chuyển thành việc của dev FE — nêu đích danh.
## 4. Khi nào được bỏ giai đoạn

View File

@@ -83,9 +83,12 @@ Một tài liệu, ba mục tiêu. Đừng viết SRS chỉ cho dev đọc.
## W11 — Ảnh không thay lời
Wireframe minh hoạ bố cục. Hành vi luôn nằm ở bảng component và AC. Khi ảnh và bảng mâu
thuẫn: **bảng thắng về việc "có tồn tại không"**, ảnh thắng về "nằm ở đâu, to bằng nào".
Ghi rõ quy tắc này trong mỗi tài liệu có ảnh.
Wireframe (`WF`) và prototype minh hoạ bố cục. Hành vi luôn nằm ở bảng component và AC. Khi
hình và bảng mâu thuẫn: **bảng thắng về "có tồn tại không" và "hành xử thế nào"**, hình thắng
về "nằm ở đâu, to bằng nào". Ghi rõ quy tắc này trong mỗi tài liệu có hình, và **ghi từng
mâu thuẫn vào `WF` §5** kèm người quyết — mâu thuẫn không ghi là mâu thuẫn dev sẽ tự xử.
Hệ quả: prototype có thành phần mà SRS không có ⇒ không tự thêm vào SRS; đó là scope creep
bằng hình ảnh, PO quyết.
## W12 — Ghi cả cái tài liệu KHÔNG nói
@@ -130,7 +133,7 @@ Sơ đồ mâu thuẫn bảng ⇒ **bảng thắng** (hệ quả của W11).
[ ] W8 Mọi chỗ chưa rõ là OQ, không phải quyết định ngầm
[ ] W9 Mọi AC/BR/field có tham chiếu ngược
[ ] W10 Có tóm tắt nghiệp vụ cho PO ở đầu
[ ] W11 Có câu quy định ảnh vs bảng
[ ] W11 Có câu quy định ảnh vs bảng; (screen) mọi lệch prototype ↔ SRS nằm ở WF §5
[ ] W12 Có mục "Ngoài phạm vi"
[ ] W13 Sơ đồ dùng mermaid (không ASCII), và mỗi sơ đồ có bảng đi kèm
```

View File

@@ -14,9 +14,10 @@ Engine: `Workflow({ scriptPath: "<abs>/.claude/workflows/ba-pipeline.js", args }
|---|---|---|
| `project`, `date` | luôn | tên project (1 project/lần), ngày hôm nay `YYYY-MM-DD` (header) |
| `stage` | luôn | `init` · `audit` · `discovery` · `analysis` · `specification` · `delivery` · `post-release` · `sign` · `sync` |
| `activity` | nên dùng | 1 hoạt động của stage (mặc định cả stage): discovery `stakeholder|elicitation|requirements|goals-scope|risks` · analysis `process|backlog|rules|rbac|impact` · specification `srs|part2|ac|errors|nfr|api` · delivery `clarification|cr|testcase-review|uat` · post-release `release-note|manual|feedback|benefit` |
| `activity` | nên dùng | 1 hoạt động của stage (mặc định cả stage): discovery `stakeholder|elicitation|requirements|goals-scope|risks` · analysis `process|backlog|rules|rbac|impact` · specification `uiconv|srs|part2|ac|errors|nfr|api|wf` (`uiconv`/`wf` chỉ khi `PRODUCT = screen`; `uiconv` chạy một lần đầu project) · delivery `clarification|cr|testcase-review|uat` · post-release `release-note|manual|feedback|benefit` |
| `scope` | specification/delivery | `US-012,US-013` (≤3 US) · `CR-004` · câu hỏi cụ thể |
| `profile` | init | `{product, lifecycle, rigor}` đã được người dùng xác nhận |
| `proto` | specification (screen) | Prototype tham chiếu: đường dẫn thư mục/file/URL hoặc mục SAD (`docs/sections/07-giao-dien.md`). Không có ⇒ runner tự tìm; vẫn không có ⇒ WF chạy chế độ ✏️ (đề xuất BA, cần Designer ký) |
| `inputs[]`, `answers`, `notes`, `override` | tuỳ | file người dùng đưa · trả lời OQ · ghi chú sửa · khẳng định chạy dù gate trước chưa qua |
| `approvals[]`, `gate`, `decisions[]` | sign | `{artifact, decision: approve|baseline|revise, approver, role, note}` · gate được ký · DEC-nn |
@@ -25,7 +26,7 @@ Hỏi bằng `AskUserQuestion` (≤4 câu/lượt), không hỏi lại điều
1. Project & phạm vi lần này (cả module hay US nào).
2. Profile: `PRODUCT` (screen | api-service | data-pipeline | ml-model | batch-job | process-only) · `LIFECYCLE` (greenfield | brownfield | enhancement) · `RIGOR` (light | standard | strict). Chưa có PROFILE ⇒ suy đoán từ tài liệu, nêu rõ là suy đoán, hỏi xác nhận.
3. Thư mục output: mặc định `ba-output/<PROJECT>/`; nếu repo đã có thư mục BA khác ⇒ hỏi dùng cái nào, **không tạo cấu trúc song song**.
4. Input đã tìm thấy (Glob `docs/`, `ba-output/`, `sa-output/`, file người dùng đưa) — trình bảng `File | Vai trò | Giai đoạn`.
4. Input đã tìm thấy (Glob `docs/`, `ba-output/`, `sa-output/`, `design/`, `prototype/`, file người dùng đưa) — trình bảng `File | Vai trò | Giai đoạn`. Với `screen` trước stage `specification`: hỏi **prototype/design system tham chiếu** là gì (→ `proto`) và **dự án có Designer không** (không có ⇒ PO ký thay `UICONV`/`WF`, ghi DEC).
Lấy ngày hôm nay từ ngữ cảnh → `date`.
## Vòng lặp chuẩn cho mỗi bước
@@ -35,11 +36,11 @@ Lấy ngày hôm nay từ ngữ cảnh → `date`.
- Duyệt ⇒ hỏi **tên + vai trò người duyệt** ⇒ `sign` với `decision: approve` cho từng artifact. Không có tên người ⇒ không sign.
- Sửa ⇒ `notes` → chạy lại đúng activity. Trả lời ⇒ gom `answers` (`OQ-012: …`) → chạy lại.
- `blocked` ⇒ trình `gateWarning`; hỏi có **khẳng định chạy ngoại lệ** không; có ⇒ chạy lại với `override: true` và ghi `decisions: ["DEC: chạy <stage> khi <gate> chưa qua vì …"]` ở lần `sign` kế.
4. **Ký gate** khi mọi artifact của stage đã 🔵 Approved: `audit` ⇒ gate 🟠 chỉ còn thiếu chữ ký và coverage đạt ⇒ hỏi **ai ký** đúng vai trò (G1 PO · G2 PO + Tech Lead · G3 PO + Tech Lead + QA · G4 PO · G5 PO + BA Lead; `strict` thêm Bảo mật/Pháp chế) ⇒ `sign` với `gate` + `decision: baseline` ⇒ `sync` ⇒ `audit` xác nhận ✅. Coverage fail / còn TBD / `refused[]` không rỗng ⇒ **không ký**, quay lại bước 2.
4. **Ký gate** khi mọi artifact của stage đã 🔵 Approved: `audit` ⇒ gate 🟠 chỉ còn thiếu chữ ký và coverage đạt ⇒ hỏi **ai ký** đúng vai trò (G1 PO · G2 PO + Tech Lead · G3 PO + Tech Lead + QA, `screen` thêm Designer cho `UICONV`/`WF` · G4 PO · G5 PO + BA Lead; `strict` thêm Bảo mật/Pháp chế) ⇒ `sign` với `gate` + `decision: baseline` ⇒ `sync` ⇒ `audit` xác nhận ✅. Coverage fail / còn TBD / `refused[]` không rỗng ⇒ **không ký**, quay lại bước 2.
5. Kết thúc mỗi lượt: tóm tắt gate ✅/🟠/☐, OQ mở (ai, quá hạn?), việc kế tiếp.
## Đặc thù
- `specification`: ≤3 US mỗi lần; QA phải xác nhận "mọi AC test được" trước G3 (`standard`+).
- `specification`: ≤3 US mỗi lần; QA phải xác nhận "mọi AC test được" trước G3 (`standard`+). Với `screen`: lần đầu của project chạy `uiconv` trước; `wf` chạy sau `part2` + `errors` của cùng US, truyền `proto`; trình riêng **bảng lệch WF §5** (Tồn tại/Hành vi chưa quyết = blocker) và chế độ 🎨/✏️ để người dùng biết cần Designer ký hay không.
- `delivery`: chạy theo từng câu hỏi/CR; CR phải qua 6 bước của ba-4, không sửa artifact Baselined trực tiếp.
- `post-release`: `benefit` cần KPI baseline từ G1 — không có ⇒ ghi bài học, không lấp liếm.
- **Liên kết SA:** G2 cần `AG1` của `sa-pipeline` (Tech Lead ký "khả thi" dựa trên OPT/ARISK). SA báo lệch `NFR↔QAS`, `API↔ICD`, `RBAC↔SEC` ⇒ chạy lại `specification` activity liên quan với `notes` (QAS/ICD thắng).

View File

@@ -95,7 +95,7 @@ một phần".
🔴 **Phép kiểm bị bỏ vì profile phải được ghi ra trong báo cáo**, kèm lý do — đừng lặng lẽ
tính coverage trên tập nhỏ hơn rồi báo 100%.
### Bước 3 — Bốn phép kiểm nhất quán
### Bước 3 — Sáu phép kiểm nhất quán
Ngoài coverage, kiểm tra tài liệu có mâu thuẫn nhau không:
@@ -105,8 +105,21 @@ Ngoài coverage, kiểm tra tài liệu có mâu thuẫn nhau không:
| 2 | **Ràng buộc lệch** | Bảng field trong `SRS` vs. bảng ràng buộc trong `API` | UI chặn 20 ký tự, API chặn 50 |
| 3 | **Mã lỗi lệch** | Mã trong `SRS` §4.1 vs. mã trong `API` §4 | Mã lỗi không endpoint nào sinh ra |
| 4 | **Trạng thái lệch** | Trạng thái trong `BR` vs. trạng thái dùng trong `SRS`/`RBAC` | RBAC phân quyền cho trạng thái không tồn tại |
| 5 | **Thành phần lệch** *(screen)* | Tập `C-id`/`F-id` trong `SRS` §2.3.1/§2.3.3 vs. `WF` §3.x.2 và `data-c` trong `WF.html` — **hai chiều** | Nút có trong WF (từ prototype) mà SRS không đặc tả hành vi; hoặc SRS có nút mà WF không đặt chỗ |
| 6 | **Quy ước lệch** *(screen)* | `SRS` §2.3.2/§2.3.6/§4.3 định nghĩa phân trang, trạng thái, định dạng khác `UICONV` mà `UICONV` §12 không có dòng | Hai SRS hai kiểu phân trang; múi giờ hiển thị khác nhau |
Phép 1 chạy được bằng máy: so `Source:` trong header với version thật của file được trích dẫn.
Phép 5 cũng vậy:
```bash
grep -oE "\b[CF][0-9]{2}\b" SRS_<US>*.md | sort -u > /tmp/srs_ids
grep -oE "\b[CF][0-9]{2}\b|data-c=\"[CF][0-9]{2}\"" WF_<US>*.md WF_<US>*.html | grep -oE "[CF][0-9]{2}" | sort -u > /tmp/wf_ids
comm -3 /tmp/srs_ids /tmp/wf_ids # phải rỗng
```
Ngoài ra với `screen`: đọc `WF` §5 — mỗi dòng loại **Tồn tại/Hành vi** có trạng thái ☐ là một
blocker G3, liệt kê đích danh. `WF` không có §5 hoặc §5 trống không ghi "đã đối chiếu" ⇒ báo
"chưa đối chiếu prototype", không phải "không lệch".
### Bước 4 — `OQ` và `CR` tồn đọng

View File

@@ -93,6 +93,14 @@ quyết**. Đó là cách một business rule bốc hơi khỏi sản phẩm.
| 2 | **Ràng buộc lệch** — field vs. API | F01 max 20 ký tự (SRS) vs. 50 (API) | 🔴 | |
| 3 | **Mã lỗi lệch** — SRS vs. API | `E-STL-0007` không endpoint nào sinh ra | 🟠 | |
| 4 | **Trạng thái lệch** — BR vs. SRS/RBAC | RBAC phân quyền cho trạng thái `LOCKED` không có trong BR | 🔴 | |
| 5 | **Thành phần lệch** *(screen)* — SRS §2.3.1 vs. WF §3.x.2 / `data-c` | `C07` có trong WF (prototype vẽ nút Xuất) nhưng SRS không đặc tả | 🔴 G3 | PO quyết ở WF §5 |
| 6 | **Quy ước lệch** *(screen)* — SRS vs. UICONV không có dòng §12 | SRS_US011 phân trang cursor, UICONV §3 offset | 🟠 | Sửa SRS hoặc thêm UICONV §12 |
**Lệch prototype ↔ SRS còn mở** *(screen — đọc từ `WF` §5, chỉ loại Tồn tại/Hành vi)*
| WF | # | Màn hình | Nội dung lệch | Ai quyết | Từ ngày | Chặn |
|---|---|---|---|---|---|---|
| `WF_US011` | 1 | SCR-03 | Prototype không có nút Huỷ, SRS có C07 | Designer | | 🔴 G3 |
---

View File

@@ -29,14 +29,14 @@ const TRACK = {
analysis: { phase: 'Analysis', skill: 'ba-2-analysis', dir: '02-analysis', gate: 'G2', prevGate: 'G1',
activities: ['process', 'backlog', 'rules', 'rbac', 'impact'] },
specification: { phase: 'Specification', skill: 'ba-3-specification', dir: '03-specification', gate: 'G3', prevGate: 'G2',
activities: ['srs', 'part2', 'ac', 'errors', 'nfr', 'api'], scopeHint: 'danh sách US (tối đa 3)' },
activities: ['uiconv', 'srs', 'part2', 'ac', 'errors', 'nfr', 'api', 'wf'], scopeHint: 'danh sách US (tối đa 3); uiconv/wf chỉ khi PRODUCT=screen, kèm args.proto nếu có prototype' },
delivery: { phase: 'Delivery', skill: 'ba-4-delivery-support', dir: '04-delivery', gate: 'G4', prevGate: 'G3',
activities: ['clarification', 'cr', 'testcase-review', 'uat'], scopeHint: 'US / câu hỏi / CR-nnn cụ thể' },
'post-release': { phase: 'Post-release', skill: 'ba-5-post-release', dir: '05-post-release', gate: 'G5', prevGate: 'G4',
activities: ['release-note', 'manual', 'feedback', 'benefit'] },
},
gates: {
G1: 'PO', G2: 'PO + Tech Lead', G3: 'PO + Tech Lead + QA', G4: 'PO', G5: 'PO + BA Lead',
G1: 'PO', G2: 'PO + Tech Lead', G3: 'PO + Tech Lead + QA (+ Designer khi PRODUCT=screen: UICONV, WF)', G4: 'PO', G5: 'PO + BA Lead',
},
profileFields: ['product', 'lifecycle', 'rigor'],
}
@@ -47,6 +47,7 @@ const TRACK = {
// activity : một hoạt động trong stage (mặc định: cả stage, theo thứ tự)
// scope : phạm vi (VD US-012,US-013 · CR-004 · --focus)
// inputs[] : file/nguồn người dùng cung cấp (ưu tiên cao nhất)
// proto : (specification, PRODUCT=screen) prototype/design system tham chiếu cho uiconv/wf — đường dẫn, URL, hoặc mục SAD
// answers : trả lời của người dùng cho OQ / humanInputNeeded
// notes : ghi chú người duyệt (Revise)
// override : true = người dùng khẳng định chạy dù gate trước chưa qua
@@ -132,6 +133,8 @@ lines.push(`Skill điều phối: ${skillsDir}/${TRACK.lifecycleSkill}/ (referen
if (a.profile) lines.push(`Profile đã được người dùng xác nhận: ${Object.keys(a.profile).map((k) => `${k}=${a.profile[k]}`).join(' · ')}.`)
else if (TRACK.profileFields.length) lines.push(`Profile: đọc ${root}/${TRACK.indexDir}/PROFILE_${project}.md; chưa có ⇒ dùng mặc định standard và NÓI RÕ điều đó.`)
if (Array.isArray(a.inputs) && a.inputs.length) lines.push(`Input bổ sung do người dùng cung cấp (ưu tiên cao nhất):\n${a.inputs.map((i) => `- ${i}`).join('\n')}`)
if (a.proto) lines.push(`## Prototype / design system tham chiếu (cho UICONV và WF, PRODUCT=screen)\n${a.proto}\nĐây là nguồn sự thật về BỐ CỤC: WF chạy chế độ 🎨 (ghi lại + đối chiếu với SRS, ghi mọi lệch vào WF §5). Thành phần có trong prototype mà SRS không có ⇒ KHÔNG tự thêm vào SRS, ghi lệch loại Tồn tại cho PO quyết.`)
else lines.push(`Prototype tham chiếu: không được cung cấp. Với PRODUCT=screen, tự tìm theo thứ tự design/, prototype/, docs/sections/07-*.md, docs/SAD.md §7; vẫn không có ⇒ WF chạy chế độ ✏️ (đề xuất của BA, cần Designer ký) và nói rõ trong summary.`)
if (a.answers) lines.push(`## Câu trả lời của người dùng cho OQ / humanInputNeeded vòng trước\n${a.answers}`)
if (a.notes) lines.push(`## Ghi chú từ người duyệt (bắt buộc xử lý trước, version +0.1 và Change Log)\n${a.notes}`)
if (a.override) lines.push(`## Ngoại lệ gate\nNgười dùng đã được cảnh báo gate trước chưa ✅ Baselined và KHẲNG ĐỊNH LẠI muốn tiếp tục. Làm tiếp, ghi ngoại lệ vào Open Questions + DEC-nn của artifact.`)