@educa-corp/sdd-framework 0.7.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/trace-schema.json +29 -3
- package/core/FRAMEWORK_VERSION +1 -1
- package/core/commands/amend-prd.md +3 -2
- package/core/commands/dev-run-test.md +1 -1
- package/core/commands/generate-bdd.md +9 -6
- package/core/commands/generate-code.md +2 -2
- package/core/commands/generate-tech-docs.md +2 -2
- package/core/commands/map-testids.md +1 -1
- package/core/commands/validate-traces.md +6 -6
- package/core/steps/context-loader.md +1 -1
- package/core/templates/project-context.yaml +3 -3
- package/core/templates/tech-design.template.md +2 -2
- package/docs/02-concepts/architecture.md +1 -1
- package/docs/02-concepts/overview.md +1 -1
- package/docs/02-concepts/pipeline-steps/02-specification.md +13 -7
- package/docs/02-concepts/pipeline-steps/07-dev-selftest.md +2 -0
- package/docs/02-concepts/pipeline-steps/08-qc-automation.md +1 -0
- package/docs/02-concepts/pipeline-steps/09-validate-traces.md +34 -3
- package/docs/02-concepts/pipeline-steps/10-feedback-loop.md +10 -1
- package/docs/02-concepts/traceability.md +187 -183
- package/docs/03-guides/architect.md +13 -4
- package/docs/03-guides/developer.md +1 -0
- package/docs/03-guides/product-owner.md +89 -72
- package/docs/03-guides/tester-qa.md +81 -81
- package/docs/04-reference/commands.md +1 -1
- package/docs/04-reference/trace-schema.md +6 -1
- package/docs/explain/02c-amend-prd.md +1 -1
- package/docs/explain/06-generate-bdd.md +1 -1
- package/docs/explain/13-dev-run-test.md +15 -1
- package/docs/explain/19-qc-run-test.md +91 -87
- package/docs/explain/21-validate-traces.md +79 -75
- package/package.json +1 -1
package/bin/trace-schema.json
CHANGED
|
@@ -1107,10 +1107,36 @@
|
|
|
1107
1107
|
"column": "status"
|
|
1108
1108
|
},
|
|
1109
1109
|
"platform": {
|
|
1110
|
+
"$comment": [
|
|
1111
|
+
"PLATFORM = DELIVERY SURFACE, không phải tech stack. `webview` là surface thứ tư có thật:",
|
|
1112
|
+
"một bundle web nhúng trong app native — không phải `web` (browser) và không phải `app`",
|
|
1113
|
+
"(native). Nó có BDD riêng (tương tác khác), design-spec riêng, và repo riêng.",
|
|
1114
|
+
"",
|
|
1115
|
+
"VÌ SAO PHẢI THÊM (báo cáo từ project thật, v0.7.0): framework DẠY `webview` ở BỐN chỗ —",
|
|
1116
|
+
" templates/project-context.yaml FORM C lấy webview mini-game làm ví dụ",
|
|
1117
|
+
" steps/context-loader.md 2c ví dụ đầy đủ: bdd/webview/UC1.feature",
|
|
1118
|
+
" commands/setup-ai-first prompt tự đưa ra `learning:webview:dap-chuot:phaser-game`",
|
|
1119
|
+
" modules/phaser-game stack-profile có mục build cho webview",
|
|
1120
|
+
"— rồi TỪ CHỐI nó ở tầng kiểm. lint-trace T5 là `err`, và validate-traces Step 1.0 DỪNG",
|
|
1121
|
+
"NGAY khi lint exit 1 ⇒ project dùng đúng ví dụ của framework mất TOÀN BỘ audit.",
|
|
1122
|
+
"",
|
|
1123
|
+
"Đổi tên sổ KHÔNG phải đường ra: nó phá khoá routing `by_prd_slug`, lệch với",
|
|
1124
|
+
"@trace.platform trong .feature, và gộp hai surface vào một sổ làm sc_id đụng nhau (mỗi",
|
|
1125
|
+
"platform đánh SC từ 1).",
|
|
1126
|
+
"",
|
|
1127
|
+
"NỢ CÒN LẠI — danh sách này vẫn ĐÓNG: project cần `desktop`/`tv`/`mini-program`/`cli` sẽ",
|
|
1128
|
+
"bị chặn y như vậy và phải chờ một bản release. Nguyên nhân gốc là `platform` được xử lý",
|
|
1129
|
+
"như enum ĐÓNG trong contract nhưng MỌI code path sinh ra nó đều MỞ (setup-ai-first nhận",
|
|
1130
|
+
"chuỗi bất kỳ · context-loader 2b đọc sub-key bất kỳ · generate-bdd ghi bdd/{platform}/",
|
|
1131
|
+
"không kiểm gì). Cách sửa đúng là cho project TỰ KHAI thêm platform trong",
|
|
1132
|
+
"project-context.yaml và để lint-trace đọc — giữ được tính năng bắt typo của T5 mà không",
|
|
1133
|
+
"cần release cho từng surface mới. Đang hoãn có chủ ý, làm ở đợt sau."
|
|
1134
|
+
],
|
|
1110
1135
|
"values": [
|
|
1111
1136
|
"web",
|
|
1112
1137
|
"app",
|
|
1113
|
-
"system"
|
|
1138
|
+
"system",
|
|
1139
|
+
"webview"
|
|
1114
1140
|
],
|
|
1115
1141
|
"filename_segment": "{UC-ID}-{platform}.tsv",
|
|
1116
1142
|
"$filename_note": "Tên sổ là nơi DUY NHẤT mang platform của row — validate-traces Step 2 lấy platform từ đây để tìm .feature đúng thư mục con. Sổ thiếu đoạn này thì cả sổ vô hình (đúng hình dạng G3/G8)."
|
|
@@ -1614,8 +1640,8 @@
|
|
|
1614
1640
|
"khớp sổ ⇒ PASS · require-fresh-audit thấy PR không chạm tag ⇒ không đòi audit. Cả ba",
|
|
1615
1641
|
"tầng xanh, và cả ba ĐÚNG theo định nghĩa của chính chúng.",
|
|
1616
1642
|
"",
|
|
1617
|
-
"Và G54 không chỉ CHO PHÉP sửa tay — nó ĐẨY người dùng về đó: /generate-prd
|
|
1618
|
-
"
|
|
1643
|
+
"Và G54 không chỉ CHO PHÉP sửa tay — nó ĐẨY người dùng về đó: /generate-prd DỪNG HẲN trên",
|
|
1644
|
+
"file đã có (§Guard: 'Tồn tại → DỪNG. KHÔNG ghi, KHÔNG hỏi Y/N') · /extend-prd chỉ",
|
|
1619
1645
|
"add-only · /refine-prd chỉ áp được finding do chính nó tìm ra. Trước /amend-prd, hành",
|
|
1620
1646
|
"vi hợp lý duy nhất còn lại LÀ mở file .md ra gõ. Thiết kế tự tạo ra con đường nó không",
|
|
1621
1647
|
"canh được.",
|
package/core/FRAMEWORK_VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.7.
|
|
1
|
+
0.7.1
|
|
@@ -10,8 +10,9 @@
|
|
|
10
10
|
> | **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 |
|
|
11
11
|
>
|
|
12
12
|
> **Vì sao phải là lệnh riêng (GAPS-v4 G54).** Ba lệnh kia đều **từ chối đúng việc này**:
|
|
13
|
-
> `/generate-prd`
|
|
14
|
-
>
|
|
13
|
+
> `/generate-prd` **DỪNG HẲN** trên file đã có (§Guard: *"Tồn tại → DỪNG. KHÔNG ghi, KHÔNG hỏi
|
|
14
|
+
> Y/N"* — vì ghi đè mất changelog, **đánh số lại BR**, phá `@trace.business_rules` trong mọi
|
|
15
|
+
> `.feature` đã sinh, cả ba không hoàn tác được) · `/extend-prd` chỉ **add-only**, luật
|
|
15
16
|
> Bước 5 §3 đòi output là *"superset chặt"* · `/refine-prd` tự cấm đụng section nào không được một
|
|
16
17
|
> finding trỏ tới, và findings sinh từ việc soi PRD hiện có nên **không có đường nào để một ý định
|
|
17
18
|
> MỚI của PO đi vào**.
|
|
@@ -338,7 +338,7 @@ Sau khi chạy, lưu kết quả vào **TSV authoritative** trong service để
|
|
|
338
338
|
report Living Docs ở spec module (qua `/sync` + `/validate-traces`). Các file test
|
|
339
339
|
ở lại trong service — chỉ *status* của lần chạy được report.
|
|
340
340
|
|
|
341
|
-
Cập nhật **sổ của platform đang test** `{paths.trace_dir}/{domain}/{prd-slug}/{UC-ID}-{platform}.tsv` (`{platform}` = platform của code/`.feature` đang test — `system` cho backend, `web`/`app
|
|
341
|
+
Cập nhật **sổ của platform đang test** `{paths.trace_dir}/{domain}/{prd-slug}/{UC-ID}-{platform}.tsv` (`{platform}` = platform của code/`.feature` đang test — `system` cho backend, mọi platform khác (`web`/`app`/`webview`/…) cho client; nếu `domain`/`prd_slug` không phân giải được từ spec target, định vị TSV bằng cách glob `{paths.trace_dir}/**/{UC-ID}-{platform}.tsv` — nó được tạo trước đó bởi `/generate-bdd`) — cho mỗi scenario row (khớp `sc_id` qua tag
|
|
342
342
|
`@trace.verifies={UC-ID}-SC{N}` của test). *(Umbrella + `spec_source`: `trace_dir` là `{spec_source}/.trace` — test chạy từ `service_root` nhưng update `dev_selftest` ghi vào **spec repo**; commit/push spec submodule cho nó.)*
|
|
343
343
|
|
|
344
344
|
### ĐỌC cột `status` của row TRƯỚC KHI GHI *(bắt buộc)*
|
|
@@ -222,11 +222,14 @@ Hỏi người dùng chọn platform target:
|
|
|
222
222
|
|
|
223
223
|
```
|
|
224
224
|
BDD này dành cho platform nào?
|
|
225
|
-
1. web
|
|
226
|
-
2. app
|
|
227
|
-
3.
|
|
225
|
+
1. web — FE/Web trong browser (React, Next.js, Angular, Vue, Nuxt)
|
|
226
|
+
2. app — Mobile native (Flutter, React Native, iOS, Android)
|
|
227
|
+
3. webview — Bundle web NHÚNG trong app native (Phaser game, mini-app)
|
|
228
|
+
4. system — System/BE BDD (tổng hợp từ BDD client có sẵn)
|
|
228
229
|
```
|
|
229
230
|
|
|
231
|
+
*Chỉ hiện những platform project thực sự dùng: nếu `services.{domain}` là map-theo-platform (context-loader 2b) thì lấy đúng các sub-key của nó làm danh sách; ngược lại hiện đủ bốn. `webview` là một **delivery surface** riêng — không phải `web` (browser) và không phải `app` (native) — nên nó có BDD, design-spec và sổ trace riêng.*
|
|
232
|
+
|
|
230
233
|
Chờ người dùng chọn. Set `active_platform` = giá trị đã chọn.
|
|
231
234
|
|
|
232
235
|
**Output path (spec repo mode):**
|
|
@@ -244,7 +247,7 @@ Chờ người dùng chọn. Set `active_platform` = giá trị đã chọn.
|
|
|
244
247
|
|
|
245
248
|
## System BDD Synthesis (active_platform = system)
|
|
246
249
|
|
|
247
|
-
*Chỉ áp dụng khi platform = system
|
|
250
|
+
*Chỉ áp dụng khi platform = `system`. Bỏ qua với mọi platform client (`web`/`app`/`webview`/…).*
|
|
248
251
|
|
|
249
252
|
### Step S0 — Brownfield Check
|
|
250
253
|
|
|
@@ -439,7 +442,7 @@ Umbrella mode không hỏi platform (khác spec repo mode) — nó **suy** từ
|
|
|
439
442
|
|
|
440
443
|
## Design Spec — Gate & Load (chỉ FE/App)
|
|
441
444
|
|
|
442
|
-
*Chỉ chạy khi target platform là FE/App — spec mode: `active_platform
|
|
445
|
+
*Chỉ chạy khi target platform là FE/App — spec mode: `active_platform` là platform client (mọi giá trị **trừ** `system` — `web`, `app`, `webview`, `app-ios`, `app-android`, …); umbrella mode: `active_module` là module FE/App (react/nextjs/vue/nuxt/angular/flutter/react-native/ios-swiftui/android-compose). Bỏ qua HOÀN TOÀN với `system` và backend/brownfield.*
|
|
443
446
|
|
|
444
447
|
**1. Định vị design-spec của platform:**
|
|
445
448
|
`{paths.specs_dir}/{domain}/{prd-slug}/design-spec/{TICKET-ID}-design-spec-{active_platform}-{slug}.md`
|
|
@@ -795,7 +798,7 @@ In danh sách SC được bump vào report cuối để người dùng biết c
|
|
|
795
798
|
|
|
796
799
|
## Write Trace State
|
|
797
800
|
|
|
798
|
-
Sau khi sinh tất cả file `.feature`, tạo hoặc cập nhật **sổ trace theo platform** `{paths.trace_dir}/{domain}/{prd-slug}/{UC-ID}-{active_platform}.tsv` cho mỗi UC — một sổ riêng cho `system` / `web` / `app
|
|
801
|
+
Sau khi sinh tất cả file `.feature`, tạo hoặc cập nhật **sổ trace theo platform** `{paths.trace_dir}/{domain}/{prd-slug}/{UC-ID}-{active_platform}.tsv` cho mỗi UC — một sổ riêng cho mỗi platform (`system` / `web` / `app` / `webview` / …). Vì `sc_id` = `{UC-ID}-SC{N}` chỉ độc nhất trong (UC × platform) (mỗi platform tự đánh số SC từ 1), **mỗi platform một file** để scenario platform này không đè/xoá platform khác. Lệnh luôn biết `active_platform` (từ Platform Selection / Service Detection) nên chỉ ghi đúng sổ của platform đang gen.
|
|
799
802
|
|
|
800
803
|
> **Umbrella + `spec_source`:** cả file `.feature` **và** trace `.tsv` đều ghi vào **spec repo** (`{spec_source}/specs/{domain}/{prd-slug}/bdd/…` và `{spec_source}/.trace/{domain}/{prd-slug}/…`, do context-loader phân giải) — một thao tác ghi **single-repo**, commit/push vào spec submodule. (Trace được gộp trong spec repo để PM quản lý mọi status ở một chỗ; các lệnh phía code cập nhật liên-repo sau.)
|
|
801
804
|
|
|
@@ -266,7 +266,7 @@ Lệnh này giới hạn nghiêm ngặt trong **một file feature** được tr
|
|
|
266
266
|
|
|
267
267
|
## Phase Detection
|
|
268
268
|
|
|
269
|
-
> **Nguồn chuẩn quyết BE/FE = `@trace.platform` của FILE FEATURE**
|
|
269
|
+
> **Nguồn chuẩn quyết BE/FE = `@trace.platform` của FILE FEATURE** — **`system` → BE · MỌI platform khác → FE** (`web`, `app`, `webview`, và bất kỳ surface nào project khai thêm). Luật viết bằng **phủ định**, không phải liệt kê: liệt kê `web`/`app` làm platform thứ tư không khớp nhánh nào, và lệnh sẽ phải tự đoán — sinh sai loại code mà không cờ nào báo. KHÔNG dùng `platform_type` (suy từ module) để quyết BE/FE — nó chỉ dùng cho **idiom stack/module** (cú pháp, layer, thư viện). Lý do: repo fullstack một-module (vd Next.js có API route) có `platform_type` cố định một giá trị, nhưng vẫn có cả feature `system` (BE) lẫn `web` (FE) — chỉ tag của chính feature mới đúng.
|
|
270
270
|
|
|
271
271
|
Parse `$ARGUMENTS` tìm flag `--phase` và `--force`:
|
|
272
272
|
|
|
@@ -275,7 +275,7 @@ Parse `$ARGUMENTS` tìm flag `--phase` và `--force`:
|
|
|
275
275
|
| `--phase=ui` | FE Phase 1 — sinh UI + layer mock API từ System BDD contract |
|
|
276
276
|
| `--phase=integration` | FE Phase 2 — thay mock adapter bằng lời gọi API thật từ tech docs |
|
|
277
277
|
| `--force` | "Gen lại tường minh" — **CHỈ** bỏ qua guard status ở §Read Trace State (không skip row đang `OK`). Xem định nghĩa hẹp bên dưới. |
|
|
278
|
-
| *(không có)* | Default — full:
|
|
278
|
+
| *(không có)* | Default — full: **`system`** → full backend; **mọi platform khác** (`web`/`app`/`webview`/…) → **FE full** (sinh UI + wire API thật trong một lần, không qua bước mock) |
|
|
279
279
|
|
|
280
280
|
> **`--force` có phạm vi HẸP — đây là ranh giới cứng, không phải khuyến nghị.**
|
|
281
281
|
> Nó bỏ qua **đúng một** thứ: luật "row `OK` thì skip" ở §Read Trace State. **Mọi guard khác giữ nguyên hiệu lực:** Scope Lock (cấm implement scenario của `.feature` khác) · quy tắc EXTEND phi-phá-huỷ (đọc lại trước khi ghi · CẤM full Write trên file đã tồn tại · output phải là superset chặt) · Guard sau-ghi · Fill-before-create · Build Verify.
|
|
@@ -421,7 +421,7 @@ Ghi/mở rộng `{output_path}` dùng template dưới đây, chỉ sinh **nội
|
|
|
421
421
|
@trace.ucs: {TICKET-ID}-UC1, {TICKET-ID}-UC2{, …}
|
|
422
422
|
@trace.service: {service — từ header BDD @trace.service}
|
|
423
423
|
@trace.module: {module liên quan — vd dotnet, angular}
|
|
424
|
-
@trace.platforms: {system | web | app — tuỳ thư mục BDD nào tồn tại}
|
|
424
|
+
@trace.platforms: {system | web | app | webview | … — tuỳ thư mục BDD nào tồn tại}
|
|
425
425
|
@trace.bdd_versions: {MAP theo từng platform — số nhiều, KHÁC @trace.bdd_version (scalar) của .feature — vd system=1.5, web=1.9, app=1.7; chỉ platform có mặt. Mỗi feature mang bdd_version riêng; đừng gộp về một số.}
|
|
426
426
|
@trace.api_source: {existing | —}
|
|
427
427
|
@trace.revision: 1
|
|
@@ -794,7 +794,7 @@ sequenceDiagram
|
|
|
794
794
|
|
|
795
795
|
| UC | Feature | Platforms | Section phủ | Trạng thái |
|
|
796
796
|
|----|---------|-----------|------------------|--------|
|
|
797
|
-
| {TICKET-ID}-UC1 | {title} | {system, web, app} | §… | ✅ Covered |
|
|
797
|
+
| {TICKET-ID}-UC1 | {title} | {system, web, app, webview…} | §… | ✅ Covered |
|
|
798
798
|
|
|
799
799
|
### Độ phủ Scenario UC1
|
|
800
800
|
|
|
@@ -180,7 +180,7 @@ placeholder bên dưới sẽ rỗng và lệnh sẽ đọc/ghi sai chỗ.
|
|
|
180
180
|
|
|
181
181
|
Phân giải `platform` từ `@trace.platform` / `platform_type`. Test-id là chuyện của **FE/App** — nếu `system` / backend → HALT:
|
|
182
182
|
```
|
|
183
|
-
❌ /map-testids chỉ áp dụng cho
|
|
183
|
+
❌ /map-testids chỉ áp dụng cho platform CLIENT (mọi platform trừ `system` — web/app/webview/…). BE không có UI test-id.
|
|
184
184
|
```
|
|
185
185
|
Phân giải attribute test-id từ `@trace.testid_attr` (hoặc theo module): web `data-testid` · React Native `testID` · Flutter `Key`/`Semantics(identifier:)` · native iOS `accessibilityIdentifier`.
|
|
186
186
|
|
|
@@ -828,7 +828,7 @@ Schema:
|
|
|
828
828
|
}
|
|
829
829
|
},
|
|
830
830
|
"by_platform": {
|
|
831
|
-
"<web | app | system
|
|
831
|
+
"<platform — web | app | system | webview | … ; CHỈ platform thực sự có scenario>": {
|
|
832
832
|
"total_scs": 0, "coded_scs": 0, "tested_scs": 0, "drift_count": 0
|
|
833
833
|
}
|
|
834
834
|
}
|
|
@@ -850,7 +850,7 @@ Schema:
|
|
|
850
850
|
"scenarios": [
|
|
851
851
|
{
|
|
852
852
|
"sc_id": "<e.g. PAY-UC01-SC1>",
|
|
853
|
-
"platform": "web | app | system",
|
|
853
|
+
"platform": "web | app | system | webview | …",
|
|
854
854
|
"sc_title": "<title>",
|
|
855
855
|
"spec_ver": "<current version from .feature>",
|
|
856
856
|
"gen_ver": "<version at codegen time>",
|
|
@@ -956,7 +956,7 @@ Schema:
|
|
|
956
956
|
"bdd_drift": [
|
|
957
957
|
{
|
|
958
958
|
"uc_id": "<UC-ID>",
|
|
959
|
-
"platform": "web | app | system",
|
|
959
|
+
"platform": "web | app | system | webview | …",
|
|
960
960
|
"code_bdd_version": "<@trace.bdd_version trong code>",
|
|
961
961
|
"current_bdd_version": "<@trace.bdd_version của .feature>",
|
|
962
962
|
"drifted_scs": ["<SC đang DRIFT của UC này>"],
|
|
@@ -966,7 +966,7 @@ Schema:
|
|
|
966
966
|
"techdoc_stale_vs_bdd": [
|
|
967
967
|
{
|
|
968
968
|
"uc_id": "<UC-ID>",
|
|
969
|
-
"platform": "web | app | system",
|
|
969
|
+
"platform": "web | app | system | webview | …",
|
|
970
970
|
"techdoc_bdd_version": "<entry trong map @trace.bdd_version của tech-doc>",
|
|
971
971
|
"current_bdd_version": "<@trace.bdd_version của .feature>",
|
|
972
972
|
"fix": "/generate-tech-docs <feature-file> then /review-tech-docs"
|
|
@@ -993,7 +993,7 @@ Schema:
|
|
|
993
993
|
"orphaned": [
|
|
994
994
|
{
|
|
995
995
|
"sc_id": "<SC-ID đã bị xoá khỏi .feature>",
|
|
996
|
-
"platform": "web | app | system",
|
|
996
|
+
"platform": "web | app | system | webview | …",
|
|
997
997
|
"implemented_by": "<ClassName.method còn tồn tại>",
|
|
998
998
|
"test_classes": ["<test còn trỏ vào SC này>"],
|
|
999
999
|
"fix": "xoá code + test, HOẶC đưa scenario trở lại .feature"
|
|
@@ -1037,7 +1037,7 @@ Schema:
|
|
|
1037
1037
|
"service_unrouted": [
|
|
1038
1038
|
{
|
|
1039
1039
|
"sc_id": "<SC-ID>",
|
|
1040
|
-
"platform": "web | app | system",
|
|
1040
|
+
"platform": "web | app | system | webview | …",
|
|
1041
1041
|
"domain": "<domain của PRD>",
|
|
1042
1042
|
"value": "unrouted | unresolved",
|
|
1043
1043
|
"reason": "<lý do context-loader đã ghi — vd: domain chưa có entry trong services:>",
|
|
@@ -403,7 +403,7 @@ Dict : {loaded — N canonical terms, M banned terms | missing}
|
|
|
403
403
|
Entities : {loaded — EntityA, EntityB, EntityC | missing}
|
|
404
404
|
Lessons : {loaded — {n} active cho lệnh này ({tổng} tổng) | chưa có}
|
|
405
405
|
{⚠️ CHỈ IN khi tổng ≥ 40: "{tổng} guardrail đang hoạt động — /learn --review để rà"}
|
|
406
|
-
Platform : {active_platform: system | web | app | — nếu chưa xác định}
|
|
406
|
+
Platform : {active_platform: system | web | app | webview | … | — nếu chưa xác định}
|
|
407
407
|
Service : {active_service} ({active_service_module}) [← domain{/platform}{/prd_slug} nếu route qua by_prd_slug] | multi (map-theo-platform hoặc map-theo-prd_slug, chốt khi target đủ platform/prd_slug) | single-service
|
|
408
408
|
Svc Root : {service_root} — đã nạp conventions + trace_dir từ config service | —
|
|
409
409
|
Status : {FULL | PARTIAL — thiếu: CLAUDE.md / business-dict / core-entities | MINIMAL}
|
|
@@ -26,7 +26,7 @@ project:
|
|
|
26
26
|
paths:
|
|
27
27
|
# Feature-Package Layout:
|
|
28
28
|
# specs/{domain}/{prd-slug}/{TICKET-ID}-{prd-slug}.md — PRD document
|
|
29
|
-
# specs/{domain}/{prd-slug}/bdd/{platform}/ — BDD .feature ({platform} = web | app | system)
|
|
29
|
+
# specs/{domain}/{prd-slug}/bdd/{platform}/ — BDD .feature ({platform} = web | app | system | webview)
|
|
30
30
|
# specs/{domain}/{prd-slug}/tech-docs/ — Technical design (ONE merged doc per PRD: {TICKET-ID}-tech-design.md)
|
|
31
31
|
# specs/{domain}/{prd-slug}/design-spec/ — Design specs (FE/App only)
|
|
32
32
|
# specs/{domain}/{prd-slug}/changelog/ — PRD changelog overflow (created once history exceeds 5 versions)
|
|
@@ -97,7 +97,7 @@ paths:
|
|
|
97
97
|
# {spec_source}/specs so FE/App read the contract via the spec submodule.
|
|
98
98
|
tech_docs_dir: "specs"
|
|
99
99
|
|
|
100
|
-
# Design Specs (
|
|
100
|
+
# Design Specs (client platforms only — every platform except `system`: web, app, webview).
|
|
101
101
|
# In the feature-package layout, design-specs live at specs/{domain}/{prd-slug}/design-spec/.
|
|
102
102
|
# This variable is no longer needed as a separate path — derived from specs_dir.
|
|
103
103
|
# design_spec_dir: "specs/design-spec" ← removed; use specs_dir instead
|
|
@@ -163,7 +163,7 @@ domains:
|
|
|
163
163
|
# #
|
|
164
164
|
# # FORM B — PER-PLATFORM MAP (one business-domain implemented on several platforms /
|
|
165
165
|
# # submodules — a merged monorepo/workspace). No direct `path`; instead one
|
|
166
|
-
# # sub-key per platform (system | web | app). context-loader routes by the
|
|
166
|
+
# # sub-key per platform (system | web | app | webview). context-loader routes by the
|
|
167
167
|
# # target .feature's @trace.platform → picks {path, module} for that platform.
|
|
168
168
|
# # The PRD keeps a SINGLE business @trace.domain (do NOT invent onboarding-web).
|
|
169
169
|
# {{DOMAIN_2}}:
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
@trace.ucs: {TICKET-ID}-UC1, {TICKET-ID}-UC2{, …}
|
|
40
40
|
@trace.service: {service — từ header BDD @trace.service}
|
|
41
41
|
@trace.module: {module liên quan — vd dotnet, angular}
|
|
42
|
-
@trace.platforms: {system | web | app — tuỳ thư mục BDD nào tồn tại}
|
|
42
|
+
@trace.platforms: {system | web | app | webview | … — tuỳ thư mục BDD nào tồn tại}
|
|
43
43
|
@trace.bdd_versions: {MAP theo từng platform — số nhiều, KHÁC @trace.bdd_version (scalar) của .feature — vd system=1.5, web=1.9, app=1.7; chỉ platform có mặt. Mỗi feature mang bdd_version riêng; đừng gộp về một số.}
|
|
44
44
|
@trace.api_source: {existing | —}
|
|
45
45
|
@trace.revision: 1
|
|
@@ -412,7 +412,7 @@ sequenceDiagram
|
|
|
412
412
|
|
|
413
413
|
| UC | Feature | Platforms | Section phủ | Trạng thái |
|
|
414
414
|
|----|---------|-----------|------------------|--------|
|
|
415
|
-
| {TICKET-ID}-UC1 | {title} | {system, web, app} | §… | ✅ Covered |
|
|
415
|
+
| {TICKET-ID}-UC1 | {title} | {system, web, app, webview…} | §… | ✅ Covered |
|
|
416
416
|
|
|
417
417
|
### Độ phủ Scenario UC1
|
|
418
418
|
|
|
@@ -66,7 +66,7 @@ Spec-driven thành/bại phụ thuộc **~80%** vào việc context được n
|
|
|
66
66
|
bin/self-check.js (fail build) --init cài vào đây
|
|
67
67
|
```
|
|
68
68
|
|
|
69
|
-
**Vì sao slim (G45):** build inline `{{include:}}` vào **từng** file lệnh.
|
|
69
|
+
**Vì sao slim (G45):** build inline `{{include:}}` vào **từng** file lệnh. Đo lúc đó (32 lệnh), kết quả là
|
|
70
70
|
2069 KB mà chỉ 580 KB là nội dung riêng của chúng — **72% là vài step giống hệt nhau, chép 30 lần**.
|
|
71
71
|
`/generate-code` từng nặng 108 KB (≈27k token đọc **trước** khi làm gì), gần một nửa không nói gì về
|
|
72
72
|
việc sinh code. Cái giá thật không phải tiền: trên PRD nhiều UC nó làm tăng rủi ro **cạn context
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
```mermaid
|
|
12
12
|
flowchart TD
|
|
13
13
|
S["0 · Setup<br/>/setup-ai-first"] --> D["1 · Discovery<br/>/define-product"]
|
|
14
|
-
D --> SP["2 · Specification<br/>/generate-prd · /refine-prd · /review-context"]
|
|
14
|
+
D --> SP["2 · Specification<br/>/generate-prd · /extend-prd · /amend-prd<br/>/refine-prd · /review-context"]
|
|
15
15
|
SP --> DS["3 · Design-Spec<br/>(chỉ FE/App)"]
|
|
16
16
|
SP --> B["4 · BDD<br/>/generate-bdd · /review-context"]
|
|
17
17
|
DS --> B
|
|
@@ -3,15 +3,20 @@
|
|
|
3
3
|
# Bước 2 · Specification — Hình thành đặc tả (PRD)
|
|
4
4
|
|
|
5
5
|
> **Tóm tắt.** Biến khung intent thành **PRD** chuẩn nghiệp vụ, tinh chỉnh qua 3 lăng kính, rồi qua **gate chất lượng** để PO đóng dấu `approved`.
|
|
6
|
-
> **Commands:** `/generate-prd` (lần đầu) · `/extend-prd` (thêm vào PRD đã có) → `/refine-prd` → `/review-context`
|
|
6
|
+
> **Commands:** `/generate-prd` (lần đầu) · `/extend-prd` (**thêm** vào PRD đã có) · `/amend-prd` (**đổi** yêu cầu đã có) → `/refine-prd` → `/review-context`
|
|
7
7
|
|
|
8
|
-
> **Chọn lệnh nào —
|
|
8
|
+
> **Chọn lệnh nào — bốn nhánh, phân biệt bằng THAO TÁC GHI:**
|
|
9
9
|
>
|
|
10
|
-
> | Tình huống | Lệnh | Vì sao không dùng cái kia |
|
|
11
|
-
>
|
|
12
|
-
> | PRD **chưa tồn tại** | `/generate-prd` | — |
|
|
13
|
-
> | PRD đã có, **
|
|
14
|
-
> | PRD đã có, **
|
|
10
|
+
> | Tình huống | Lệnh | Ghi kiểu gì | Vì sao không dùng cái kia |
|
|
11
|
+
> |---|---|---|---|
|
|
12
|
+
> | PRD **chưa tồn tại** | `/generate-prd` | **Write** cả file | — |
|
|
13
|
+
> | PRD đã có, **THÊM** UC/AC/BR mới | **`/extend-prd`** | Edit **add-only** — output là **superset chặt** | `/generate-prd` **từ chối chạy** trên file đã có |
|
|
14
|
+
> | PRD đã có, **ĐỔI** một yêu cầu đang đúng cú pháp | **`/amend-prd`** | Edit **tại chỗ** — output **KHÔNG** phải superset | `/extend-prd` chỉ add-only; `/refine-prd` chỉ áp finding của chính nó |
|
|
15
|
+
> | PRD đã có, sửa **vấn đề review đã soi ra** | `/refine-prd` → Review Board → `--resume` | Edit trong phạm vi finding | `/refine-prd` **không thêm/đổi được** theo ý định mới — nó tự cấm đụng section ngoài findings |
|
|
16
|
+
>
|
|
17
|
+
> **Xoá hẳn một BR/AC → không có lệnh, và có chủ ý:** xoá row làm `@trace.business_rules` trong `.feature` trỏ vào ID không còn ⇒ `TRACE_ORPHAN` 🔴. Dùng `/amend-prd --retire {ID}` — khai tử **tại chỗ**, giữ nguyên row + ID.
|
|
18
|
+
>
|
|
19
|
+
> ⚠️ **Sửa tay file `.md` là điểm mù (GAPS-v4 G54).** Mọi drift detector so **nhãn version**, không so nội dung (0 content hash trong codebase) — sửa mà không bump version ⇒ **0 cờ**. `/validate-traces` Step 3.9 canh cửa sau bằng cờ 🔴 `PRD_UNTRACKED_EDIT`.
|
|
15
20
|
>
|
|
16
21
|
> **`/generate-prd` dừng hẳn (không hỏi Y/N) nếu file đã tồn tại.** Ghi đè sẽ mất `# Change Log` + rollover, Version/Status thật, và **đánh số lại BR từ đầu** — cái cuối lan **ra ngoài file**, phá mọi `@trace.business_rules` trong `bdd/` đã sinh. Ba mất mát đều không hoàn tác được từ trong lệnh, nên không đặt sau một phím bấm.
|
|
17
22
|
|
|
@@ -41,6 +46,7 @@ PRD là **hợp đồng nghiệp vụ** giữa PO ↔ Dev ↔ AI. Đây là **c
|
|
|
41
46
|
|------|---------|---------|
|
|
42
47
|
| `/generate-prd` | **Sinh** PRD draft từ product-definition. Từ chối chạy nếu PRD đã tồn tại | PRD `Status: draft` |
|
|
43
48
|
| `/extend-prd` | **Thêm** UC/AC/BR vào PRD đã duyệt — đánh số **nối tiếp**, ghi **add-only** + guard sau-ghi, drain `feedback/prd-change-requests/` | PRD v+1, `Status → draft` |
|
|
49
|
+
| `/amend-prd` | **Đổi tại chỗ** một AC/BR/UC đã duyệt — PO khai tường minh `amend_targets`, kiểm va chạm, guard sau-ghi **HAI CHIỀU** (Bảo toàn + Giới hạn). `--retire {ID}` khai tử tại chỗ | PRD v+1, `Status → draft` |
|
|
44
50
|
| `/refine-prd` | **Tinh chỉnh** qua 3 lăng kính DEV/SA/PO (fan-out per-UC) | Findings để PO accept/reject |
|
|
45
51
|
| `/review-context` | **Gate chất lượng** — findings P0–P5, phải sạch critical | PO đặt `Status: approved` |
|
|
46
52
|
|
|
@@ -24,6 +24,8 @@ Trước khi đẩy sang QC chính thức, Dev cần một vòng **kiểm nhanh
|
|
|
24
24
|
- Cho phép **thử tại chỗ** trên service/app đang chạy (`/dev-smoke-test`).
|
|
25
25
|
|
|
26
26
|
> **`dev_selftest` ≠ `qc_status`.** Hai trục **độc lập**: dev smoke (nhanh, tự kiểm) vs QC chính thức (Playwright, evidence). Không lấn quyền nhau.
|
|
27
|
+
>
|
|
28
|
+
> ⚠️ **Nhưng "độc lập" chỉ đúng với `status` về KẾT QUẢ CHẠY, không đúng về QUYỀN KHẲNG ĐỊNH** *(GAPS-v4 G55)*. `pass` mang nghĩa *"scenario này đã được nghiệm thu theo spec **hiện tại**"* — nên trên row `DRIFT`/`ORPHANED`, `/dev-run-test` và `/qc-run-test` **không được** ghi `pass`; chúng hạ về `not_run`. `fail`/`skip` thì ghi bình thường. `lint-trace` **T12** bắt trạng thái `DRIFT + pass` ở sổ thật, bất kể ai ghi ra.
|
|
27
29
|
|
|
28
30
|
---
|
|
29
31
|
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
|
|
22
22
|
- Phân rã yêu cầu thành test case bám scenario, phát hiện **gap tài liệu**.
|
|
23
23
|
- Chạy test thật, ghi **`qc_status` chính thức** + **evidence**.
|
|
24
|
+
⚠️ Nhưng `/qc-run-test` **đọc cột `status` trước khi ghi `pass`** *(GAPS-v4 G55)*: row `DRIFT`/`ORPHANED` + test xanh → hạ về `not_run`, và **không** đóng bug nào ở lần chạy đó. `fail`/`skip` ghi bình thường.
|
|
24
25
|
- Phân loại FAIL: **script-bug** (sửa script) vs **product-gap** (giữ FAIL + evidence, **không bao giờ fake-pass**).
|
|
25
26
|
- Đẩy **product-gap** ngược về PO/Dev.
|
|
26
27
|
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
# Bước 9 · Validate Traces — Ma trận độ phủ (Coverage Matrix)
|
|
4
4
|
|
|
5
|
-
> **Tóm tắt.** Check độ phủ giữa **spec ↔ code ↔ test** — 2 chiều quét, **6 tầng drift**, 4 cờ 🔴 chặn PR, 2 cờ ⓘ. Chỉ ra chỗ chưa phủ — mặc định **không sửa gì**.
|
|
5
|
+
> **Tóm tắt.** Check độ phủ giữa **spec ↔ code ↔ test** — 2 chiều quét, **6 tầng drift**, 4 cờ 🔴 chặn PR, 1 cờ 🔴 không-chặn (`PRD_UNTRACKED_EDIT`), 2 cờ ⓘ. Chỉ ra chỗ chưa phủ — mặc định **không sửa gì**.
|
|
6
|
+
> **Có phạm vi:** `--domain {d}` · `--prd {TICKET-ID}` · `--uc {UC-ID}`; không cờ nào = toàn bộ.
|
|
6
7
|
> **Command:** `/validate-traces` · `--realign-prd-version {UC-ID}` · `--realign-techdoc-revision {UC-ID}`
|
|
7
8
|
>
|
|
8
9
|
> *Lệnh **read-only** ở chế độ thường. Hai flag `--realign-*` là ngoại lệ có kiểm soát: chúng sửa **đúng dòng `@trace.*`** trong code, không đụng logic — xem [Realign](#realign--đường-ra-cho-cờ-ⓘ).*
|
|
@@ -41,7 +42,7 @@ Traceability chỉ có giá trị khi **kiểm được**. Bước này cho mộ
|
|
|
41
42
|
| Ma trận coverage spec ↔ code ↔ test | Trạng thái từng SC + `code_coverage` tổng |
|
|
42
43
|
| `{trace_dir}/trace-report.json` | Bản máy đọc cho **panel VS Code** ("Spec Driven Docs Tools") — bị **ghi đè** mỗi lần chạy |
|
|
43
44
|
| `{trace_dir}/trace-history.jsonl` | **Nhật ký append-only** — mỗi lần chạy ghi thêm 1 dòng *delta*. Đây là **dữ liệu**, không phải mirror: **phải commit**, mất là mất vĩnh viễn |
|
|
44
|
-
| Cờ audit | 6 cờ drift + 4 cờ 🔴 chặn PR + 2 cờ ⓘ (bảng dưới) |
|
|
45
|
+
| Cờ audit | 6 cờ drift + 4 cờ 🔴 chặn PR + `PRD_UNTRACKED_EDIT` 🔴 (không chặn) + 2 cờ ⓘ (bảng dưới) |
|
|
45
46
|
| Hàng đợi | Đếm PRD change request còn `Open` kèm **số ngày chờ** (Step 7b) |
|
|
46
47
|
|
|
47
48
|
---
|
|
@@ -68,6 +69,25 @@ Traceability chỉ có giá trị khi **kiểm được**. Bước này cho mộ
|
|
|
68
69
|
|
|
69
70
|
## Framework xử lý thế nào (Mechanics)
|
|
70
71
|
|
|
72
|
+
### Phạm vi audit — `--domain` / `--prd` / `--uc`
|
|
73
|
+
|
|
74
|
+
Đây là **lệnh đắt nhất** trong framework: ~24k token chỉ dẫn + ~9k `context-loader`, rồi đọc **mọi** PRD · `.feature` · tech-doc · design-spec · file source có tag · `.tsv`. Chi phí tăng **tuyến tính theo cả repo**, không theo phần việc đang làm.
|
|
75
|
+
|
|
76
|
+
| Cờ | `scope.kind` | Phạm vi |
|
|
77
|
+
|---|---|---|
|
|
78
|
+
| *(không có)* | `all` | Toàn bộ |
|
|
79
|
+
| `--domain {d}` | `domain` | Một domain |
|
|
80
|
+
| `--prd {TICKET-ID}` | `prd` | Một feature-package |
|
|
81
|
+
| `--uc {UC-ID}` | `uc` | Một UC — **mọi platform của nó** |
|
|
82
|
+
|
|
83
|
+
**`/sync` Step 1e nói cho bạn biết scope là gì**: nó liệt kê PRD nào vừa đổi *(so với lần pull)* và PRD nào đã đổi *kể từ lần audit gần nhất* — con số thứ hai tích luỹ đúng qua nhiều lần pull. Hai lệnh khớp nhau thành một vòng: `/sync` chỉ chỗ → audit scoped rẻ → sửa → audit **toàn bộ** một lần trước khi tạo PR.
|
|
84
|
+
|
|
85
|
+
⚠️ **Biên bản có scope KHÔNG BAO GIỜ được coi là đầy đủ.** Report mang field `scope`, và `gate-trace` **G2 fail** nếu `scope.kind !== "all"` — **không ngoại lệ**, không đếm xem trên đĩa có bao nhiêu domain. Muốn tạo PR thì phải có một lần audit **toàn bộ** đã commit.
|
|
86
|
+
|
|
87
|
+
> **Vì sao điều kiện phải tuyệt đối (GAPS-v4 G57):** bản cũ hỏi *"còn domain **nào khác** không"*, nên trong repo **một domain** thì không còn domain nào khác ⇒ **không fail** ⇒ một biên bản hẹp-theo-PRD được nhận là *"toàn bộ"*. Thêm cờ scope mà không siết G2 là **tự tay mở** đúng cái *"cấp giấy xanh cho thứ chưa ai xem"* mà chú thích của gate cảnh báo.
|
|
88
|
+
|
|
89
|
+
**Ba chỗ cố ý KHÔNG âm thầm:** `--prd`/`--uc` không phân giải được → **DỪNG** *(không rơi về `all` — chạy toàn bộ khi người ta xin một phần là đốt 30 phút; và không audit rỗng rồi báo "sạch" trên 0 row)* · nhiều cờ scope cùng lúc → **DỪNG** *(không tự ưu tiên)* · **lint vẫn chạy toàn bộ** dù audit có scope *(sổ hỏng ở domain khác vẫn là sổ hỏng, và lint rẻ vì không cần LLM)*.
|
|
90
|
+
|
|
71
91
|
### Phân loại `status` từng SC (thứ tự ưu tiên, rule sớm thắng)
|
|
72
92
|
|
|
73
93
|
| # | Trạng thái | Điều kiện |
|
|
@@ -97,6 +117,7 @@ Chiều ngược là cần thiết vì gen lại BDD có thể làm một SC bi
|
|
|
97
117
|
|
|
98
118
|
| Cờ | So cái gì | Step |
|
|
99
119
|
|---|---|:---:|
|
|
120
|
+
| `PRD_UNTRACKED_EDIT` 🔴 | **Nội dung PRD đổi mà nhãn `Version` KHÔNG đổi** — `git diff` **và** `git status` so với mốc `spec_baseline` của lần audit trước. Có người sửa ngoài đường chính thức | **3.9** |
|
|
100
121
|
| `PRD_DRIFT` | Version PRD vs cột `prd_version` vs `@trace.prd_version` trong code — **và** changelog **có** nêu UC này | 4 |
|
|
101
122
|
| `TECHDOC_DRIFT` · `FE_TECHDOC_DRIFT` | `@trace.revision` tech-doc vs cột đã lưu — **và** changelog nêu UC này | 5 |
|
|
102
123
|
| `BDD_DRIFT` | `@trace.bdd_version` trong code vs `.feature` hiện tại | 5c |
|
|
@@ -133,7 +154,17 @@ Chiều ngược là cần thiết vì gen lại BDD có thể làm một SC bi
|
|
|
133
154
|
|
|
134
155
|
Tệ hơn: **làm theo hướng dẫn cũng không tắt được.** `/generate-bdd` sạch được cột TSV, nhưng tag trong code chỉ `/generate-code` ghi — mà nó thấy row đang `OK` là **skip**. Vòng lặp đóng, và lối ra duy nhất là ép sinh lại code cho hàng loạt UC không hề thay đổi.
|
|
135
156
|
|
|
136
|
-
Bộ lọc đọc
|
|
157
|
+
Bộ lọc đọc **`{changelog_scope}` của row changelog** — một **contract máy đọc** (`bin/trace-schema.json` → `changelog_row_contract`) với **bốn** producer: `/refine-prd` Phase 3 · `/extend-prd` Bước 6 · `/amend-prd` Bước 5 · `/review-context` Fix/Resume Phase 3. `self-check` **R12** fail build nếu producer nào không có dòng template mang token.
|
|
158
|
+
|
|
159
|
+
Ba bước dựng tập bị ảnh hưởng:
|
|
160
|
+
|
|
161
|
+
1. **Tách mệnh đề** — ngăn bằng `;`, mỗi mệnh đề mở đầu bằng đơn vị sở hữu (`{UC-ID}:` hoặc `PRD-global:`).
|
|
162
|
+
2. **Chuẩn hoá về UC** — phép phân giải **`BR/AC → UC sở hữu`**: `BR{n}` → UC có BR đó trong bảng Business Rule (PRD §3) · `AC{n}` → UC có AC đó ở dòng `**AC liên quan:**`. **Không bỏ bước này**: phép thử là *"**UC** này có trong tập?"*, nên một row chỉ nêu `sửa BR8` làm UC sở hữu BR8 rơi vào ⓘ trong khi nội dung của nó vừa đổi — và ⓘ **mở cửa** cho `--realign-prd-version` dán nhãn lại (GAPS-v4 G53).
|
|
163
|
+
3. **Phân loại** *(first-match-wins)* — **row mơ hồ xét TRƯỚC**: nó là điều kiện **cấp row**, nên xét sau thì một UC có thể được xếp ⓘ trước khi ta biết là không suy đoán được gì.
|
|
164
|
+
|
|
165
|
+
**Row nào mơ hồ → 🟠 cho MỌI UC** — lưới an toàn: mất tính năng *lọc*, không mất tính năng *cảnh báo*. ⚠️ Nhưng nó **không phải cái cớ để producer ghi bừa**: đúng khi **thiếu** thông tin, sai khi producer **có** thông tin mà không ghi.
|
|
166
|
+
|
|
167
|
+
Mệnh đề mang hậu tố **`[no-behavior]`** → UC nêu trong đó ở lại ⓘ. Chỉ producer **chứng minh được** tính trung tính mới được dùng (`changelog_row_contract.neutral_checks`) — hiện chỉ `/review-context --fix` cho fix thuần cấu trúc (P4).
|
|
137
168
|
|
|
138
169
|
> Đây là bài mà framework **đã giải đúng ở cấp scenario**: `sc_version` chỉ bump khi thân scenario thực sự đổi, vì *"bump vô cớ sẽ tạo DRIFT giả, làm cờ mất giá trị"*. Hai cờ ⓘ là bản tương ứng ở cấp tài liệu.
|
|
139
170
|
|
|
@@ -37,7 +37,7 @@ Framework là pipeline **một chiều** — nhưng vẫn cần đường **ph
|
|
|
37
37
|
| `/learn` | Tất cả | Guardrail lesson | `project-lessons.md` (qua step `capture-lesson`) |
|
|
38
38
|
| `/fix-bug` | Dev | Sửa lỗi có root-cause + regression test | Code + `@trace.fixes/root_cause/regression` |
|
|
39
39
|
| `/extend-prd` | PO | **Drain** PRD change request → UC/AC/BR mới trong PRD | PRD v+1 · request → `archived/` |
|
|
40
|
-
| `/sync` | Lead (umbrella) | Pull + submodule + **nổi feedback** + làm mới Living Docs | Chạy hằng ngày |
|
|
40
|
+
| `/sync` | Lead (umbrella) | Pull + submodule + **nổi feedback** + **nổi spec delta** (Step 1e) + làm mới Living Docs | Chạy hằng ngày |
|
|
41
41
|
|
|
42
42
|
### Ba hàng đợi — mỗi cái phải có người lấy ra
|
|
43
43
|
|
|
@@ -48,6 +48,15 @@ Framework là pipeline **một chiều** — nhưng vẫn cần đường **ph
|
|
|
48
48
|
| `prd-change-requests/` | `/propose-scenario` B | **`/extend-prd`** | `/validate-traces` Step 7b — đếm `Status: Open` kèm **số ngày chờ** |
|
|
49
49
|
|
|
50
50
|
> **Vì sao cột "ai nhắc lại" quan trọng.** `/sync` chỉ hiện những gì về **trong đúng lần pull đó** (`git diff old..new`) — nó là **chuông cửa, không phải tồn kho**. Bỏ lỡ một lần là mất khỏi màn hình vĩnh viễn. Hai hàng đợi đầu không sao vì có lệnh **quét lại thư mục mỗi lần chạy**; riêng `prd-change-requests/` thì không — nên `/validate-traces` phải nhắc thay.
|
|
51
|
+
|
|
52
|
+
> **Cùng nguyên tắc đó áp cho SPEC — và đó là Step 1e (GAPS-v4 G56).** Trước đó `/sync` diff đúng ba đường dẫn `feedback/*` và **bỏ qua `specs/`**, tức hỏi *"có góp ý gì mới"* rồi bỏ qua chính tài liệu mà mọi lệnh downstream đọc. Giờ nó trả lời **hai** câu bằng **hai** mốc:
|
|
53
|
+
>
|
|
54
|
+
> | | Mốc | Trả lời | Vấn đề nếu chỉ có nó |
|
|
55
|
+
> |---|---|---|---|
|
|
56
|
+
> | **1e-A** | `{old_sha}..{new_sha}` | *"đổi gì kể từ lần **PULL**"* | **chuông cửa** — reset mỗi lần pull; pull 4 ngày liền không audit thì ngày thứ 5 chỉ thấy delta của **một** ngày |
|
|
57
|
+
> | **1e-B** | `spec_baseline.sha_at_audit` | *"đổi gì kể từ lần **AUDIT**"* | **tồn kho** — tích luỹ đúng |
|
|
58
|
+
>
|
|
59
|
+
> 1e-B đọc mốc mà `/validate-traces` Step 6b ghi (cùng khối dùng cho cờ `PRD_UNTRACKED_EDIT`). `/sync` **chỉ đọc, không bao giờ ghi** — nếu nó cũng ghi thì mốc audit trượt theo mỗi lần pull, tức 1e-B thoái hoá thành 1e-A. Và dòng `Next` giờ **rẽ nhánh theo dữ liệu**, không còn in một hằng số.
|
|
51
60
|
>
|
|
52
61
|
> Trước v0.4.3, hàng đợi thứ ba **không có người lấy ra**: có producer, có storage, có commit, có mặt trong `/sync` — nhưng 0 consumer, và **không gì báo**. Yêu cầu nghiệp vụ thật do tester phát hiện từ sản phẩm chạy thật rơi vào im lặng hoàn toàn. Từ v0.4.3, cả ba hàng đợi được khai vào `bin/trace-schema.json` §`queues` nên **self-check chặn build** nếu một hàng đợi mất consumer.
|
|
53
62
|
|