@educa-corp/sdd-framework
v0.10.2
Published
Spec Driven Development workflow framework for Claude Code
Maintainers
Readme
SDD Framework
An SDD Framework workflow framework for Claude Code.
Guides your team through a complete feature lifecycle — Discovery → PRD → Design-Spec → BDD → Tech Design → Code → Dev self-check → QC automation — with AI review gates at every transition and end-to-end traceability.
📚 Documentation
Toàn bộ tài liệu nằm trong docs/, chia theo vai trò và chủ đề:
| Bạn là… | Bắt đầu ở |
|---------|-----------|
| Người mới / cài đặt lần đầu | 01 · Getting Started |
| Muốn hiểu cách nó hoạt động | 02 · Concepts — pipeline từng bước · traceability |
| Product Owner / BA | Guide · Product Owner |
| Developer (FE / BE / App) | Guide · Developer |
| Tester / QA | Guide · Tester / QA — gồm cả pipeline QC tự động (/qc-*) |
| Kiến trúc sư / Lead | Guide · Architect |
| Tra cứu lệnh / schema / module | 04 · Reference |
| Muốn hiểu từng lệnh làm gì bên trong | explain/ — một trang cho mỗi lệnh |
Quick Start
Requires Node.js (check: node -v).
# 1. Install framework (--hooks bật data-guard: chặn AI đọc/ghi .env, *.key, secrets/…)
# Single-service:
npx @educa-corp/sdd-framework --init --module java-spring --hooks
# Multi-service monorepo:
npx @educa-corp/sdd-framework --init --hooks \
--services backend:java-spring,web-admin:react,app-mobile:flutter
# 2. Open the project in Claude Code, then:
/setup-ai-first
# 3. Fill in the generated config (CLAUDE.md, .agent/project-context.yaml,
# specs/domain-knowledge/*), then start your first feature:
/define-productFull install paths (upgrade, umbrella, uninstall) → Getting Started › Installation. First feature end-to-end → Getting Started › Quick Start. Mỗi phiên bản đổi gì, và phải làm gì khi nâng cấp → CHANGELOG.md (installer in phần liên quan khi bạn nâng cấp; quy trình phát hành ghi ở đầu file).
Workflow at a glance
Phase 0 Setup /setup-ai-first · /generate-architecture
Phase 1 Discovery /define-product
Phase 2 PRD /generate-prd (lần đầu)
/extend-prd (THÊM vào PRD đã duyệt)
/amend-prd (ĐỔI một yêu cầu đã duyệt)
/refine-prd · /review-context
Phase 2b Design Spec /generate-design-spec (FE/App only)
Phase 3 BDD /generate-bdd · /review-context
Phase 4 Tech Design /generate-tech-docs · /map-testids · /review-tech-docs
└─ §4.5.6 ĐÓNG BĂNG → rẽ HAI NHÁNH chạy song song ↓
Phase 5 Code (FE/BE) /generate-code · /review-code · /fix-bug · /debug
Phase 6 Dev self-check /dev-gen-test · /dev-run-test · /dev-smoke-test → dev_selftest
∥
Phase 5q QC design /qc-analyze → /qc-plan → /qc-design-test → /qc-review-testcase
→ /qc-automation-assess → [/qc-design-testdata] → /qc-design-script
→ /qc-review-script
Phase 6q QC run /qc-run-script ∥ /qc-run-manualtest → /qc-report
← hai nhánh gặp lại → qc_status
Phase 7 Trace /validate-traces · /generate-spec-manifest
Phase 8 Tester feedback /report-bug · /propose-scenario → /sync → /extend-prd
Cross-cutting /sync · /learn · /update-framework
QC utility (chạy lúc nào cũng được) /qc-smoke-test · /qc-metrics40 lệnh. Pipeline chi tiết → Concepts › Pipeline Steps. Bảng đầy đủ mọi command → Reference › Commands.
Vì sao Phase 5/6 và 5q/6q chạy SONG SONG.
/map-testidschốt hợp đồng test-id §4.5.6 trước khi có dòng code nào, rồi/review-tech-docsduyệt nó. Từ đó FE và QC đọc cùng một bản đã đóng băng, không đọc output của nhau — nên không phải chờ nhau. Các trạm QC design (qc-analyze→qc-review-script) chỉ cần tài liệu;/qc-run-script(automation) và/qc-run-manualtest(TCAutomatable: N) là hai trạm duy nhất cần sản phẩm chạy được, và đó là chỗ hai nhánh gặp lại.Cửa vào làn QC là
/qc-analyze— đừng trỏ thẳng/qc-design-test, nó tiêu thụ output của hai trạm đầu.
Bốn nhánh dễ chọn nhầm
| Tình huống | Lệnh đúng | Thao tác ghi | Vì sao không phải lệnh kia |
|---|---|---|---|
| PRD chưa có | /generate-prd | Write cả file | — |
| PRD đã có, thêm UC/AC/BR | /extend-prd | Edit add-only | /generate-prd DỪNG HẲN trên file đã có (§Guard — không hỏi Y/N) và chỉ sang đây — ghi đè sẽ mất changelog và đánh số lại BR, phá @trace.business_rules trong mọi .feature đã sinh |
| PRD đã có, sửa vấn đề review chỉ ra | /refine-prd → Review Board → --resume | Edit trong phạm vi finding | /refine-prd không thêm được yêu cầu mới; nó tự cấm đụng section ngoài findings |
| PRD đã có, PO muốn ĐỔI một yêu cầu đang đúng cú pháp | /amend-prd | Edit tại chỗ — output KHÔNG phải superset | Ba lệnh trên đều từ chối đúng việc này: /extend-prd chỉ add-only, /refine-prd chỉ áp finding do chính nó tìm ra, /generate-prd thì huỷ changelog |
Vì sao nhánh thứ tư quan trọng hơn nó trông (GAPS-v4 G54). Mọi drift detector so nhãn version, không so nội dung — 0 content hash trong toàn bộ codebase. Nên PRD bị sửa tay mà không bump version là điểm mù tuyệt đối:
/validate-tracesthấy version khớp ⇒ sạch ·gate-tracethấy report khớp sổ ⇒ PASS ·require-fresh-auditthấy PR không chạm tag ⇒ không đòi audit. Ba tầng xanh, và ba tầng đều đúng theo định nghĩa của chính chúng. Trước/amend-prd, ba lệnh có sẵn từ chối đúng việc PO cần làm — nên hành vi hợp lý duy nhất còn lại là mở file.mdra gõ. Thiết kế tự tạo ra con đường nó không canh được. Cửa sau giờ có chuông: cờ 🔴PRD_UNTRACKED_EDIT(schema →spec_edit_detection).
Traceability
Mỗi dòng code truy ngược về một scenario trong .feature. Trạng thái sống ở
.trace/{domain}/{prd-slug}/{UC-ID}-{platform}.tsv — một sổ cho mỗi UC × platform, 24 cột.
{platform} = delivery surface: system · web · app · webview (bundle web nhúng trong app native).
PRD ──► Scenario ──► Code ──► Test
│ │ │ │
└─ prd_version · sc_version · gen_ver · test_count ──► status: OK / DRIFT / GAP / UNTRACKED/validate-traces đối chiếu hai chiều (spec→code và code→spec) rồi phân tầng cảnh báo:
| Mức | Cờ | Nghĩa |
|:---:|---|---|
| 🔴 chặn PR | SEAM_UNWIRED · STUB_UNRESOLVED · ORPHANED · TRACE_ORPHAN | Code đang hỏng — luồng ghép chạy vào hàm rỗng, hoặc code trỏ vào scenario đã bị xoá. Build xanh + test từng-UC xanh không phát hiện được |
| 🔴 không chặn PR (có chủ ý) | PRD_UNTRACKED_EDIT | Tài liệu bị sửa ngoài đường chính thức — nội dung PRD đổi mà nhãn Version không đổi, nên mọi phán đoán version cho PRD đó đang dựa vào một nhãn không còn đúng. Cố ý không vào gate.blocking: nó nói về spec, không phải code hỏng, và mọi project đang chạy đều có nợ tồn ⇒ chặn ngay sẽ làm người ta tắt cổng, mất luôn 4 cờ trên |
| 🟠 không chặn | PRD_DRIFT · BDD_DRIFT · TECHDOC_DRIFT · DESIGNSPEC_DRIFT … | Code chưa theo kịp spec — nợ khác loại |
| ⓘ không phải lỗi | PRD_STALE_REF · TECHDOC_STALE_REF | Version lệch nhưng changelog không nêu UC này → chỉ con trỏ cũ. Sạch bằng --realign-prd-version |
Hết cờ 🔴 ≠ sạch.
Nó cũng append một dòng delta vào .trace/trace-history.jsonl mỗi lần chạy — thứ trả lời
"đang tiến hay lùi", không chỉ "hiện tại thế nào".
⚠️ .trace/ phải được commit; .trace-mirror/ thì không. Cái đầu là sổ gốc, không dựng lại
được. Kiểm dự án đang chạy: git -C {spec_source} check-ignore .trace — có kết quả là đang mất dữ liệu.
⚠️ Và nó cần luật merge. Sổ nằm trong git, được nhiều người ghi trên nhiều nhánh song song —
nên {trace_dir}/.gitattributes phải có *.tsv / *.jsonl → text eol=lf merge=union.
Không có: merge song song conflict, và giải bằng "take mine" là mất row của người kia, im lặng.
/setup-ai-first tạo sẵn · /sync Step 4c kiểm và tạo hộ. Playbook khi conflict →
Concepts › Traceability.
Chi tiết → Reference › Trace Schema · Concepts › Traceability.
Contract tự canh
Contract trace có một nguồn-sự-thật máy đọc: bin/trace-schema.json. Hai checker đọc nó,
canh hai thứ khác nhau:
| | Canh gì | Chạy khi nào |
|---|---|---|
| bin/self-check.js | Contract — lệnh có gọi đúng tên cột/field không | npm run build · fail build nếu lệch |
| bin/lint-trace.js | Dữ liệu — sổ .trace/** thật có đúng hình dạng đó không | --lint-trace · exit 1 nếu lệch |
| bin/gate-trace.js | Cổng — sổ có cờ 🔴 nào không, và report có còn tươi | --gate-trace · exit 1 nếu có |
✅ 42 tag + 24 cột TSV + 1 bảng phụ + 3 hàng đợi + 8 vocabulary — contract khớp mọi lệnh
+ sổ trace thật được canh bởi bin/lint-trace.js (13 rule) — R8 giữ nó theo kịp schemaself-check — 15 rule, mỗi rule sinh ra từ một lỗi có thật
| Rule | Bắt gì |
|---|---|
| R1 | field/hàng đợi có người đọc mà không ai ghi |
| R2 | có người ghi mà không ai đọc — field chết |
| R3 | schema khai một lệnh là producer/consumer mà file của nó không nhắc tới (chỉ canh "có nhắc" — xem R15 cho những field cần canh "có dùng") |
| R4 | {paths.X} dùng mà không khai — và ngược lại, key chết |
| R5 | pattern đã bị cấm quay trở lại |
| R6 | giá trị enum khai mà không xuất hiện ở đâu |
| R7 | audit flag thiếu counter trong Step 7 và summary → dashboard mù |
| R8 | lint-trace tụt lại sau schema — vocabulary không neo được, n trùng/hổng, bảng phụ ngoài phạm vi |
| R9 | cổng chặn PR neo vào counter không tồn tại → gate mù trong im lặng; cờ 🟠 lọt vào danh sách chặn; hoặc key ở cấp gốc biên bản có consumer mà không producer (R9(h) — report.domain từng có 1 consumer chặn-PR và 0 producer) |
| R10 | file CI tụt lại sau schema — job require-fresh-audit grep 7 tag; thiếu một tag ⇒ job luôn xanh |
| R11 | lệnh không tự khai mức chặn CHECKPOINT, hoặc nhãn lệch schema ⇒ agent tự suy, và suy nhẹ hơn thì --yes bỏ qua được cổng không bao giờ được bỏ |
| R24 | version trong package.json phải có mục CHANGELOG.md có ngày, không rỗng — installer in "Có gì mới" từ đó; thiếu mục thì người nâng cấp thấy "không có gì mới" kể cả khi bản đó đổi bố cục dự án của họ. prepublishOnly chạy self-check nên chặn đúng bước publish |
| R22 | mọi artifact được khai phải có ít nhất MỘT lệnh TẠO ra nó — artifact_writers trả lời "ai ghi gì", nhưng ghi ≠ tạo. mode: merge nói "tôi sửa một phần của file ĐÃ CÓ"; nếu mọi lệnh ghi một artifact đều chỉ merge thì không ai sinh ra nó, cả chuỗi trạm sau đứng chờ một file không bao giờ xuất hiện, và build vẫn xanh. Cờ creates: true ở cấp artifact là đường khai chính xác cho lệnh vừa tạo-khi-vắng vừa merge-khi-có (file findings của /refine-prd·/review-context·/review-tech-docs) — ép chúng khai overwrite là nói dối, vì chế độ delta GIỮ status của reviewer. Bắt được 2 lỗi thật ngay lần chạy đầu: AUTOMATION_ASSESSMENT.md không ai tạo, và _seams.tsv sót hẳn khỏi registry dù /generate-code tự nói "tạo file + header nếu chưa có" |
| R21 | mọi checked_by[].cmd phải trỏ vào lệnh CÓ THẬT — nhiều khối contract khai "ai canh điều kiện này". Khi một lệnh bị đổi tên hoặc tách đôi, danh sách đó lệch mà không máy nào bắt, và contract vẫn khai điều kiện "đã được canh" trong khi không ai canh — tệ hơn một lỗ hổng ai cũng biết là chưa canh. Cùng luật với R17, áp cho checked_by. Quét đệ quy, không liệt kê tên khối. Gặp thật khi tách /qc-review (Đợt 2 · b1): testid_fourth_leg.checked_by — chân thứ tư của hợp đồng test-id — suýt trỏ vào lệnh đã gỡ |
| R20 | mỗi cổng CỨNG phải khai ĐIỀU KIỆN nó nổ, và số cổng vô điều kiện có HẠN MỨC — --yes không bỏ qua được hard, nên khi hard quá phiền người ta không thêm --yes mà gỡ lệnh khỏi hard, mất luôn cổng đáng giữ. Mỗi mục checkpoint_levels.hard khai narrowing (chuỗi điều kiện) hoặc narrowing: null + narrowing_why bắt buộc — vì "cố ý không có điều kiện" và "quên nghĩ tới điều kiện" trông y hệt nhau (G79). Khai chuỗi ⇒ tmpl phải có câu *Mức cứng chỉ áp khi …* (agent đọc tmpl, không đọc schema — G41). unconditional_hard_budget.max là bánh cóc: vượt là build đỏ, nâng được nhưng phải kèm lý do, nên việc vượt là một lần sửa nhìn thấy trong diff. Đo 2026-09-16: 12 cổng cứng, 3 nổ vô điều kiện, 9 chỉ nổ khi đã có thứ để mất |
| R19 | bảng mức gate CHÉP TAY phải khớp schema — cùng một danh sách "lệnh nào chặn" tồn tại ở ba nơi (rules/workflow.md → steps/gate.md → bin/trace-schema.json), mỗi nơi trỏ sang nơi sau nói "kia mới là nguồn" mà vẫn chép cứng tên lệnh. Một con trỏ tới nguồn không ngăn được bản sao lệch. Quét theo dòng (giữ được ví dụ cụ thể mà buộc ví dụ phải đúng), cả hai chiều, và không quét skills/ — ở đó "read-only" nói về artifact đang xem, không nói về mức CHECKPOINT |
| R18 | đảo chiều allowlist của R11 — R11 duyệt từ schema ra file, nên lệnh chưa khai thì không vòng lặp nào chạm tới, và mặc định là normal (lỏng nhất) ⇒ quên = mở cửa (đã xảy ra 4 lần: G67·G77·G78·G79). R18 duyệt ngược: lệnh trong artifact_writers.enrolled phải khai writes + has_human_content + why — why bắt buộc cả khi false, vì ghi đè an toàn mà không ai khai là an toàn thì trông y hệt một chỗ sót. Hai luật ép hard: (A) has_human_content: true — cấp lệnh; (B) artifact nào mode ≠ append và regenerable: false và when: always — cấp artifact. Luật (B) có vì (A) không phủ được sổ tích luỹ: trace-history.jsonl không ai gõ tay vào nên (A) trả lời false đúng chữ, trong khi /validate-traces gọi nó là AUTHORITATIVE, không regenerate được. Và chỉ append/create được miễn (danh sách ở artifact_writers.safe_modes) — merge không, vì /amend-prd là merge và là thao tác ghi duy nhất được phép làm output không phải superset của bản cũ. human_content ở cấp artifact cho lệnh ghi nhiều thứ mà chỉ một thứ có người nhập tay (/fix-bug: 4 artifact, chỉ {lessons_path}, và nó nằm sau (Y/N)). non_writers ghi lệnh đã rà và kết luận không ghi gì — vắng mặt ở cả ba danh sách trông y hệt bị quên. Phủ 33/33 từ 2026-09-16. Trường when (always · confirm · --<cờ>) có vì hành vi ghi thuộc về chế độ, không thuộc về lệnh: đo 2026-09-16, 5 lệnh tự khai read-only và cả 5 đều có ghi. Ghi có điều kiện không bị ép hard — nhưng điều kiện phải kiểm chứng được: when là tên cờ thì tmpl phải nhắc đúng cờ đó, confirm thì tmpl phải có câu hỏi (Y/N) |
| R17 | cờ bỏ qua điều kiện chỉ được mang MỘT tên (--force) — mỗi lệnh một tên riêng thì người dùng gặp cổng chặn, không nhớ lệnh này dùng từ nào, rồi đi sửa spec cho hợp lệ giả. Là use-check: chỉ quét dòng định nghĩa cờ, bỏ qua blockquote — nếu không thì mọi câu giải thích "tên cũ đã bỏ" đều đỏ |
| R15 | "nhắc tên" ≠ "dùng" — R3 chỉ hỏi "file có nhắc tên field không", nên một câu tuyên bố cố ý bỏ qua ("dev_selftest trực giao với status") cũng thoả mãn nó: R3 xác nhận contract bằng đúng câu văn đang phủ nhận contract (đó là G55). R15 siết opt-in (strict_use_check) cho field mà trả lời sai gây hại im lặng — đòi field xuất hiện trong một dòng bảng, nơi framework này viết mọi luật rẽ nhánh |
| R14 | quyền khẳng định pass — chủ cột dev_selftest/qc_status không thực sự đọc status (R3 bị một câu "trực giao" thoả mãn); hoặc lint-trace không phát T12 / không đọc schema; hoặc fail bị nhét vào positive_values (che tin xấu) |
| R13 | phát hiện sửa spec ngoài đường — spec_baseline không được GHI như một key trong trace-report.json ⇒ cờ PRD_UNTRACKED_EDIT không bao giờ bật, mà R6/R7 vẫn ✅ (chúng chỉ canh nửa báo-cáo) |
| R12 | dòng changelog — producer không khai {changelog_scope} ⇒ row mơ hồ ⇒ 🟠 cho MỌI UC; hoặc consumer không hiểu [no-behavior] / phép phân giải BR/AC → UC sở hữu ⇒ UC đổi thật bị xếp ⓘ và --realign dán nhãn lại |
lint-trace — 13 rule trên sổ sách thật
npx @educa-corp/sdd-framework --lint-trace # exit 1 nếu sổ hỏng
npx @educa-corp/sdd-framework --lint-trace --warn-only # xem nợ tồn, chưa chặn
npx @educa-corp/sdd-framework --version # bản nào đang chạy? (npx cache theo version)Mọi output đều mang version.
Lint trace v0.7.5 …·Trace gate v0.7.5 …· vàframework_versiontrong--json. Vì sao cần:npxcache theo version, một biến CI rỗng làmpkg@${VAR}thànhpkg@⇒ resolve vềlatestmà log không nói gì. Nên câu "lỗi này sửa chưa?" trước đây không trả lời được từ log — đúng lúc cần nhất. Một cổng quyết định PR nào được merge thì phải nói nó là ai.
| Rule | Bắt gì |
|---|---|
| T1 | header lệch 24 cột (vắng ở đuôi là OK — backward-compat) |
| T2 | row sai số ô — một dấu tab thiếu dồn mọi ô sang trái, kèm chẩn đoán chỗ lệch |
| T3 | giá trị ngoài vocabulary (DRIFTED thay DRIFT · dev_selftest=passed · một ngày nằm trong ô status) |
| T4 | sc_id trùng trong một sổ |
| T5 | tên sổ không khớp {UC-ID}-{platform}.tsv → cả sổ vô hình với /validate-traces |
| T6 | ô ngày không parse được (2026-13-45) |
| T7 | marker conflict git còn trong sổ |
| T8 | trace-history.jsonl có dòng hỏng / thiếu key |
| T9 | sổ mồ côi — không có .feature tương ứng (warning) |
| T10 | sổ thiếu luật merge (merge=union + text eol=lf) — hỏi thẳng git check-attr (warning · gate nâng thành chặn) |
| T11 | sổ đang bị gitignore — hỏi thẳng git check-ignore (warning · gate nâng thành chặn) |
| T12 | row vừa status ∈ {DRIFT, ORPHANED} vừa mang dev_selftest/qc_status = pass — rule đầu tiên nhìn NHIỀU Ô cùng lúc: T1–T8 kiểm hình dạng từng ô, nên trạng thái này là một sổ hoàn toàn hợp lệ với 11 rule cũ (warning) |
| T13 | KHÔNG kiểm được T10/T11 — thiếu binary git, hoặc sổ ngoài mọi repo git. Loại thứ tư: không phải "có cái sai", không phải "nợ", không phải "bảo vệ đang tắt" — mà "không biết bảo vệ có bật hay không". Trước T13, ca này làm G0 in sổ được bảo vệ — 2/2 điều kiện trên bằng chứng chưa bao giờ thu (warning · gate nâng thành chặn) |
| T15–T18 | hợp đồng test-id §4.5.6 — bảng ↔ .feature (T15, error) · header phải khai @trace.testid_attr (T16) · bảng ↔ code (T17/T18, warning, cần --code) |
| T19 | chân thứ tư: §4.5.6 ↔ *.Test.md (warning · cần --qc). .Test.md là consumer duy nhất chép cứng giá trị id vào một artifact bền — /generate-code bake vào code (T17/T18 canh), script automation (/qc-design-script) dựng locator từ §4.5.6. /qc-review-testcase + /qc-design-script đã có guard cho chân này, nhưng do LLM thực thi nên không chặn được trước merge: "canh contract ≠ canh dữ liệu — cần cả hai" |
/validate-traces Step 1.0 tự chạy lint trước khi đọc, và dừng nếu sổ hỏng: Step 3 tính lại
status rồi Step 6 ghi ngược vào TSV, nên chạy tiếp trên row đã lệch cột sẽ nướng cái lệch đó
vào sổ vĩnh viễn — và sổ trace không regenerate được.
gate-trace — cổng chặn PR
npx @educa-corp/sdd-framework --gate-trace # exit 1 nếu có cờ 🔴Biên bản có scope không bao giờ là biên bản đầy đủ.
/validate-traces --domain/--prd/--ucghiscopevào report; G2 fail nếuscope.kind !== "all", không ngoại lệ — nó không đếm xem trên đĩa có bao nhiêu domain. Bản cũ hỏi "còn domain nào khác không", nên repo một domain thì một biên bản hẹp-theo-PRD lọt qua. Thêm cờ scope mà không siết G2 là biến cổng thành sân khấu.
Ba tầng, mỗi tầng vô nghĩa nếu tầng trước chưa xanh:
| | Tầng | Bắt gì |
|:---:|---|---|
| G0 | Sổ được bảo vệ? | Sổ có nằm trong git? Git có biết cách gộp sổ? Kiểm cấu trúc của một quyển sổ sắp mất thì vô nghĩa — nên hỏi trước |
| G1 | Sổ đúng hình dạng? (gọi lint-trace) | Phán trạng thái trên sổ lệch cột là phán trên dữ liệu rác |
| G2 | Report còn tươi? | Đối chiếu từng scenario theo khoá {sc_id, platform} ↔ sổ TSV. Không có tầng này thì cổng là sân khấu: chạy một lần, commit report, rồi sửa gì cũng được — CI đọc report cũ, cho qua mãi |
| G3 | Có cờ 🔴? | orphaned · trace_orphan · seam_unwired · stub_unresolved — nêu tên thủ phạm kèm câu fix |
Khoá phải gồm platform: sc_id một mình không định danh được scenario — "sc_id trùng số
giữa các platform là 2 scenario khác nhau". Và so từng SC, không chỉ tổng số, vì ca thường
gặp nhất khi spec tiến hoá là một SC bị xoá + một SC được thêm — tổng không đổi, report cũ vẫn
trông như tươi.
G0 là loại thứ ba, cố ý tách khỏi gate.blocking:
| | Nói gì | Ví như |
|---|---|---|
| 🔴 gate.blocking (4 cờ) | Đang có cái sai trong code | Động cơ đang hỏng |
| 🟠 cờ nợ | Code chưa theo kịp spec | Đến hạn thay dầu |
| G0 | Chưa có gì sai, nhưng bảo vệ đang tắt | Chưa cài dây an toàn |
Trộn G0 vào blocking là làm mờ đúng ranh giới mà R9(e) tồn tại để giữ.
Cả hai điều kiện G0 đã được lint-trace phát hiện dưới dạng ⚠️; gate nâng chúng thành lỗi
chặn — một implementation, hai mức: pre-push nhắc, CI chặn. Chặn git push vì một dòng cấu
hình sẽ dạy dev gõ --no-verify, và mất luôn phần lint thật.
Ba ca mà một cổng viết cẩu thả sẽ PASS im lặng, và ở đây đều FAIL:
| Ca | Vì sao phải fail |
|---|---|
| Counter bị đổi tên | summary[counter] là undefined, và undefined > 0 là false → ✅ trên code hỏng |
| Không có report | "chưa audit" ≠ "sạch" |
| Report chỉ phủ một domain | Cho qua là cấp giấy xanh cho thứ chưa ai xem |
Giới hạn — in ra mỗi lần chạy, kể cả khi xanh. Cổng chứng minh "report khớp SỔ". Chỉ
/validate-traceschứng minh được "sổ khớp CODE" (quét tag trong source, đọc.feature, so version). Nên nó bắt ca "quên chạy lại", không bắt ca "sửa code mà không đụng sổ" — bịt nốt bằng jobrequire-fresh-audittrong template.
Mẫu sẵn dùng: .agent/templates/ci/trace-gate.yml (GitHub Actions) · .agent/templates/ci/trace-gate.gitlab-ci.yml (GitLab CI) · .agent/templates/hooks/pre-push.
Bản GitLab đã vá bốn bẫy dịch — hai bẫy ỒN (tags: thiếu ⇒ job stuck · Node thiếu ⇒ npx: not found) và hai bẫy IM LẶNG: GIT_DEPTH: 0 thiếu ⇒ git diff rỗng ⇒ job xanh giả · image không có git (node:*-alpine/*-slim) ⇒ T10/T11 không chạy. self-check R10 canh cả hai file khớp danh sách 7 tag.
Chi tiết → Guide › Architect › Cắm vào CI.
Cờ 🟠 cố ý không chặn. Chúng là nợ, không phải code hỏng. Cổng đỏ liên tục sẽ bị tắt,
mất luôn cả phần 🔴 — nên R9 fail build nếu ai nhét một cờ 🟠 vào gate.blocking.
Đổi contract: sửa bin/trace-schema.json trước, rồi mới sửa lệnh.
Philosophy
Write the spec first. Generate the code from the spec. Trace everything.
- Humans define what — acceptance criteria, business rules, platform requirements.
- AI generates how — BDD scenarios, tech design, code, tests — adapted to the platform.
- Every artifact is reviewed before proceeding to the next phase.
- Every line of code traces back to a scenario in a
.featurefile. - In multi-service projects, each service evolves independently while sharing the same workflow.
- Một tín hiệu đã hết đúng phải bị hạ xuống, không được giữ. Đổi spec thì
dev_selftestvàqc_statuscũ mất hiệu lực — giữ mộtpasssinh ra từ spec đã bị sửa là báo cáo sai.
Companion
SDD Board — VS Code extension đọc .trace/ hoặc
.trace-mirror/: dashboard Living Documentation + Review Board cho findings.
Framework version: see npm — npm view @educa-corp/sdd-framework version. Build internals & directory map → Concepts › Architecture.
