spec-lite 1.6.0 → 1.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/README.md CHANGED
@@ -128,6 +128,9 @@ Tạo `.specs/integrations/{slug}/tech.md` sau khi `spec.md` được approve. C
128
128
  #### `/spec-test [number]`
129
129
  Tạo `.specs/integrations/{slug}/test.md` sau khi `spec.md` được approve. Chạy bởi **QC**, **song song / độc lập** với `/spec-tech` — cả hai chỉ phụ thuộc `spec.md`. Mechanical derive Test Scenarios + Test Cases từ frd.md (Flow → TS, US/AC → Functional TC, VR → positive + negative, FAC → E2E TC, NFR → Non-functional TC, DM → Data & Migration TC), priority deterministic. Cascade lên `feature/{F-XXX}/test-design.md` qua Changes blocks. Gate: integration phải có `features:` non-empty (component-thuần không áp dụng).
130
130
 
131
+ #### `/spec-test-exec [F-XXX]`
132
+ Sinh **bundle test-executions** (bản thực thi) cho một feature từ `test-design.md`. Layer EXECUTION — `test-design.md` là **source of truth**, skill đọc-xuống một chiều (không cascade, không sửa test-design), inherit `TC-F*` nguyên văn. Output: cycle bundle `.specs/test-executions/{F-XXX}-{slug}/{NNN}-{cycle-slug}/` (plane 2 tầng, ephemeral per chu kỳ test). Sinh tới 6 doc theo scope×harness — `func-manual`/`func-auto`, `e2e-manual`/`e2e-auto`, `nfr`, `dm` (nfr/dm bỏ nếu rỗng); team chọn harness theo kỹ năng. KHÔNG versioned. Feature-level, chạy sau khi có test-design (không thuộc per-integration pipeline).
133
+
131
134
  #### `/plan`
132
135
  Tạo `plan.md` và `todo.md` từ `spec.md` + `tech.md`.
133
136
 
@@ -177,9 +180,12 @@ Migrate **main artifact** lỗi thời lên structure mới (mọi main type). T
177
180
  | `/spec-new` | `.specs/integrations/{slug}/spec.md` |
178
181
  | `/spec-tech` | `.specs/integrations/{slug}/tech.md` |
179
182
  | `/spec-test` | `.specs/integrations/{slug}/test.md`, cascade: `feature/{F-XXX}/test-design.md` |
183
+ | `/spec-test-exec` | `.specs/test-executions/{F-XXX}-*/{NNN}-*/test-exec-*.md` (derived từ test-design) |
180
184
  | `/plan` | `.specs/integrations/{slug}/plan.md`, `todo.md` |
181
185
  | `/build` | *(implements tasks từ `plan.md`/`todo.md`)* |
182
186
  | `/review-integration` | *(findings report — không tạo file)* |
183
187
  | `/review-everything` | `.specs/integrations/{NNN}-{slug}/review-findings.md` *(qua /spec-new)* |
184
188
 
185
189
  Feature artifacts (`frd.md`) ở greenfield có thể author trước bằng `/spec-frd`, hoặc mọc dần qua **cascade proposals** từ integrations (`/spec-new` fallback). Component artifacts (`crd.md`/`cdd.md`) ở greenfield chỉ mọc qua cascade — không có skill author trực tiếp (`/spec-frd` chỉ reference component, không tạo crd/cdd).
190
+
191
+ Ngoài `main/` và `integrations/`, còn plane thứ ba **`.specs/test-executions/`** (execution layer): bundle thực thi *derived* từ `test-design.md` qua `/spec-test-exec`, đánh số per-feature 2 tầng (`{F-XXX}-{slug}/{NNN}-{cycle-slug}/`), ephemeral per chu kỳ test, không versioned. Xem `conventions.md` §8.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spec-lite",
3
- "version": "1.6.0",
3
+ "version": "1.7.1",
4
4
  "description": "Spec-driven development kit for Claude Code",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,116 +1,125 @@
1
1
  ---
2
2
  name: archive
3
- description: Archive một integration từ .specs/integrations sang .specs/archive. Dùng khi một integration đã hoàn thành hoặc không còn active và cần được lưu trữ ra khỏi thư mục làm việc chính.
3
+ description: Archive một integration hoặc một test-execution (cycle bundle / feature group) sang .specs/archive/ — namespaced theo loại (.specs/archive/integrations/ .specs/archive/test-executions/). Dùng khi integration đã hoàn thành hoặc một chu kỳ test đã xong và cần dọn ra khỏi thư mục làm việc chính.
4
4
  ---
5
5
 
6
6
  # archive
7
7
 
8
8
  ## Overview
9
9
 
10
- Di chuyển một integration từ `.specs/integrations/` sang `.specs/archive/` để dọn dẹp thư mục làm việc chính trong khi vẫn giữ nguyên toàn bộ nội dung integration đó.
10
+ Di chuyển một artifact bundle ra khỏi thư mục làm việc sang `.specs/archive/`, giữ nguyên nội dung. Hỗ trợ **hai plane**:
11
+
12
+ - **Integration**: `.specs/integrations/{id}-{slug}/` → `.specs/archive/integrations/{id}-{slug}/`
13
+ - **Test execution**: `.specs/test-executions/{F-XXX}-{slug}/{NNN}-{cycle-slug}/` → `.specs/archive/test-executions/{F-XXX}-{slug}/{NNN}-{cycle-slug}/`
14
+ - Đơn vị archive = **cycle bundle** (một chu kỳ test xong) hoặc **cả feature group** (`{F-XXX}-{slug}/`) khi feature retire.
15
+
16
+ `.specs/archive/` được **namespace theo loại** (`integrations/` + `test-executions/`) để không trộn lẫn hai plane. Cấu trúc nguồn được giữ nguyên dưới subfolder loại (test-exec giữ 2 tầng feature-group → cycle-bundle).
11
17
 
12
18
  ## When to Use
13
19
 
14
- - Integration đã hoàn thành (Done) không cần active nữa
15
- - Integration bị cancel hoặc deferred thời hạn
16
- - Muốn dọn dẹp `.specs/integrations/` khỏi các integration
20
+ - Integration đã hoàn thành (Done) / cancel / deferred vô thời hạn.
21
+ - Một **chu kỳ test** (cycle bundle test-exec) đã chạy xong, muốn lưu kết quả ra khỏi working set.
22
+ - Feature retire archive cả feature group test-executions của nó.
23
+ - Dọn dẹp `.specs/integrations/` hoặc `.specs/test-executions/` khỏi bundle cũ.
17
24
 
18
25
  ## When NOT to Use
19
26
 
20
- - Integration đang In Progress → chưa nên archive
21
- - Muốn xóa hoàn toàn đừng archive, thao tác thủ công sau khi confirm với team
27
+ - Integration đang In Progress → chưa nên archive.
28
+ - Cycle test đang chạy dở (Test Result chưa xong) chưa archive.
29
+ - Muốn xóa hoàn toàn → đừng archive, thao tác thủ công sau khi confirm với team.
22
30
 
23
31
  ---
24
32
 
25
33
  ## Process
26
34
 
27
- ### Bước 1: Kiểm tra thư mục archive
35
+ ### Bước 1: Chuẩn bị thư mục archive
28
36
 
29
- Kiểm tra `.specs/archive/` đã tồn tại chưa.
37
+ `.specs/archive/` chứa subfolder theo loại. **Tạo lazy** — chỉ tạo subfolder loại nào khi thực sự archive item thuộc loại đó:
30
38
 
31
- **Nếu chưa tồn tại** tạo thư mục `.specs/archive/`.
32
-
33
- **Nếu đã tồn tại** → tiếp tục.
39
+ - Archive integrationđảm bảo `.specs/archive/integrations/` tồn tại (tạo nếu chưa).
40
+ - Archive test-execution → đảm bảo `.specs/archive/test-executions/` tồn tại (tạo nếu chưa).
34
41
 
35
42
  ---
36
43
 
37
- ### Bước 2: Liệt kê integrations
38
-
39
- Quét `.specs/integrations/` để tìm tất cả các integration (mỗi integration là một thư mục con).
44
+ ### Bước 2: Liệt kê archivable từ cả hai plane
40
45
 
41
- **Nếu không integration nào:**
46
+ Quét `.specs/integrations/` và `.specs/test-executions/`. Hiển thị danh sách **chia section theo plane, đánh số liên tục**:
42
47
 
43
48
  ```
44
- Không có integration nào trong .specs/integrations/.
45
- ```
46
-
47
- Dừng lại.
48
-
49
- **Nếu có integrations**, hiển thị danh sách dạng numbered list, kèm trạng thái nếu đọc được từ `spec.md` (frontmatter `status` hoặc heading):
50
-
51
- ```
52
- Integrations trong .specs/integrations/:
49
+ Archivable:
53
50
 
51
+ Integrations (.specs/integrations/):
54
52
  [1] 001-user-authentication (approved)
55
- [2] 002-payment-integration (draft)
56
- [3] 003-notification-service (done)
57
- [4] 004-admin-panel (in-progress)
53
+ [2] 003-notification-service (done)
54
+
55
+ Test executions (.specs/test-executions/):
56
+ [3] F-012-bulk-import / 001-regression
57
+ [4] F-012-bulk-import / 002-release-2.0
58
+ [5] F-012-bulk-import (cả feature group — gồm 001, 002)
59
+ [6] F-031-checkout / 001-smoke
58
60
 
59
- Chọn số thứ tự integration để archive (hoặc nhập nhiều số cách nhau bởi dấu cách, ví dụ: 1 3):
61
+ Chọn số để archive (nhiều số cách nhau bởi dấu cách, ví dụ: 1 3):
60
62
  ```
61
63
 
62
- Với mỗi integration, cố gắng đọc `spec.md` để lấy status. Nếu không đọc được thì bỏ qua phần status.
64
+ - **Integration**: mỗi `{id}-{slug}/` 1 dòng. Cố đọc `spec.md` frontmatter `status` để hiển thị (bỏ qua nếu không đọc được).
65
+ - **Test execution**: mỗi **cycle bundle** `{F-XXX}-{slug}/{NNN}-{cycle-slug}/` là 1 dòng (qualified tên feature group). **Thêm 1 dòng cho cả feature group** `{F-XXX}-{slug}/` để archive trọn gói.
66
+ - Cả hai plane rỗng → `Không có gì để archive trong .specs/integrations/ và .specs/test-executions/.` → dừng.
63
67
 
64
68
  ---
65
69
 
66
70
  ### Bước 3: Xác nhận
67
71
 
68
- Sau khi user chọn, hiển thị xác nhận trước khi di chuyển:
72
+ Hiển thị source **namespaced dest** trước khi di chuyển:
69
73
 
70
74
  ```
71
- Sẽ archive các integration sau:
75
+ Sẽ archive:
72
76
 
73
- .specs/integrations/001-user-authentication/ → .specs/archive/001-user-authentication/
74
- .specs/integrations/003-notification-service/ → .specs/archive/003-notification-service/
77
+ .specs/integrations/001-user-authentication/
78
+ → .specs/archive/integrations/001-user-authentication/
79
+
80
+ .specs/test-executions/F-012-bulk-import/001-regression/
81
+ → .specs/archive/test-executions/F-012-bulk-import/001-regression/
75
82
 
76
83
  Xác nhận? (yes/no)
77
84
  ```
78
85
 
79
- Nếu user không confirmhủy, không làm gì.
86
+ - Nếu user chọn **cả feature group** lẫn một cycle con của nó cảnh báo trùng, chỉ giữ feature group (archive group bao trọn cycle).
87
+ - Không confirm → hủy, không làm gì.
80
88
 
81
89
  ---
82
90
 
83
91
  ### Bước 4: Di chuyển
84
92
 
85
- Với mỗi integration đã được confirm:
93
+ Với mỗi item đã confirm, di chuyển **giữ nguyên cấu trúc nguồn** dưới subfolder loại:
94
+
95
+ - Integration: `.specs/integrations/{id}-{slug}/` → `.specs/archive/integrations/{id}-{slug}/`
96
+ - Cycle bundle: `.specs/test-executions/{F-XXX}-{slug}/{NNN}-{cycle-slug}/` → `.specs/archive/test-executions/{F-XXX}-{slug}/{NNN}-{cycle-slug}/` (tạo feature group dưới archive nếu chưa có).
97
+ - Feature group: `.specs/test-executions/{F-XXX}-{slug}/` → `.specs/archive/test-executions/{F-XXX}-{slug}/`.
86
98
 
87
- - Di chuyển toàn bộ thư mục `.specs/integrations/{slug}/` sang `.specs/archive/{slug}/`
88
- - Giữ nguyên toàn bộ cấu trúc thư mục và file bên trong
99
+ Sau khi di chuyển cycle bundle, nếu feature group nguồn **rỗng** (không còn cycle nào) → xóa thư mục feature group rỗng ở `.specs/test-executions/` cho gọn.
89
100
 
90
- Nếu `.specs/archive/{slug}/` đã tồn tại (trùng tên) cảnh báo:
101
+ **No-overwrite guard:** nếu dest đã tồn tại → cảnh báo và **bỏ qua** item đó (không ghi đè frozen record):
91
102
 
92
103
  ```
93
- ⚠ .specs/archive/001-user-authentication/ đã tồn tại. Bỏ qua integration này để tránh ghi đè.
104
+ ⚠ .specs/archive/test-executions/F-012-bulk-import/001-regression/ đã tồn tại. Bỏ qua để tránh ghi đè.
94
105
  ```
95
106
 
96
- bỏ qua integration đó, tiếp tục với các integration còn lại.
107
+ Tiếp tục với các item còn lại.
97
108
 
98
109
  ---
99
110
 
100
111
  ### Bước 5: Kết quả
101
112
 
102
- Thông báo kết quả:
103
-
104
113
  ```
105
114
  ✓ Đã archive:
106
- .specs/archive/001-user-authentication/
107
- .specs/archive/003-notification-service/
115
+ .specs/archive/integrations/001-user-authentication/
116
+ .specs/archive/test-executions/F-012-bulk-import/001-regression/
108
117
 
109
- {nếu có lỗi}
118
+ {nếu có}
110
119
  ⚠ Bỏ qua (đã tồn tại):
111
- .specs/archive/005-foo/
120
+ .specs/archive/test-executions/F-031-checkout/001-smoke/
112
121
 
113
- .specs/integrations/ hiện còn {N} integration(s).
122
+ Còn lại: {N} integration(s), {M} test-execution cycle(s).
114
123
  ```
115
124
 
116
125
  ---
@@ -119,7 +128,9 @@ Thông báo kết quả:
119
128
 
120
129
  Trước khi di chuyển:
121
130
 
122
- - [ ] `.specs/archive/` đã tồn tại (tạo nếu chưa)
123
- - [ ] User đã chọn ít nhất 1 integration
124
- - [ ] User đã confirm trước khi di chuyển
125
- - [ ] Không ghi đè nếu slug đã tồn tại trong `.specs/archive/`
131
+ - [ ] Subfolder loại tương ứng (`.specs/archive/integrations/` hoặc `.specs/archive/test-executions/`) đã tồn tại (tạo lazy nếu chưa).
132
+ - [ ] User đã chọn ít nhất 1 item.
133
+ - [ ] User đã confirm; trùng feature-group cycle-con đã dedupe.
134
+ - [ ] Cấu trúc nguồn giữ nguyên dưới subfolder loại (test-exec giữ 2 tầng).
135
+ - [ ] Không ghi đè nếu dest đã tồn tại.
136
+ - [ ] Feature group nguồn rỗng sau khi archive cycle → dọn thư mục rỗng.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: artifact-audit
3
- description: Audit MAIN artifacts trong .specs/main/ xem có lỗi thời so với template không (chỉ main artifacts — prd/domain/sad/frd/fdd/test-design/crd/cdd; integration artifacts ngoài scope). So `template_version` của artifact với `template_version` hiện tại đọc thẳng từ template (.claude/templates/). Versioned khớp → up-to-date, lệch → out-dated (in vX → vY). Artifact thiếu version (sinh trước versioning) → đối chiếu structure với template: khớp thì stamp version, lệch thì flag out-dated. KHÔNG tự migrate — chỉ stamp khi chắc chắn khớp + báo cáo. Nhận tùy chọn 1 hay nhiều main type làm scope (vd `frd`, `frd,crd`); không có arg → audit mọi main type.
3
+ description: Audit MAIN artifacts trong .specs/main/ xem có lỗi thời so với template không (chỉ main artifacts — prd/domain/sad/frd/fdd/test-design/selector-contract/crd/cdd; integration artifacts ngoài scope). So `template_version` của artifact với `template_version` hiện tại đọc thẳng từ template (.claude/templates/). Versioned khớp → up-to-date, lệch → out-dated (in vX → vY). Artifact thiếu version (sinh trước versioning) → đối chiếu structure với template: khớp thì stamp version, lệch thì flag out-dated. KHÔNG tự migrate — chỉ stamp khi chắc chắn khớp + báo cáo. Nhận tùy chọn 1 hay nhiều main type làm scope (vd `frd`, `frd,crd`); không có arg → audit mọi main type.
4
4
  ---
5
5
 
6
6
  # artifact-audit
@@ -9,7 +9,7 @@ description: Audit MAIN artifacts trong .specs/main/ xem có lỗi thời so v
9
9
 
10
10
  Trả lời một câu hỏi: **main artifact nào trong `.specs/main/` đã lỗi thời so với template mới nhất?**
11
11
 
12
- > **Scope = chỉ main artifacts** (`prd`, `domain`, `sad`, `frd`, `fdd`, `test-design`, `crd`, `cdd` — đều nằm dưới `.specs/main/`). Integration artifacts (`spec`, `tech`, `test`, `plan`, `todo`, `techdebt` dưới `.specs/integrations/`) **không** thuộc scope của skill này — chúng là ephemeral và immutable sau khi `done`, không audit/migrate theo version.
12
+ > **Scope = chỉ main artifacts** (`prd`, `domain`, `sad`, `frd`, `fdd`, `test-design`, `selector-contract`, `crd`, `cdd` — đều nằm dưới `.specs/main/`). Integration artifacts (`spec`, `tech`, `test`, `plan`, `todo`, `techdebt` dưới `.specs/integrations/`) **không** thuộc scope của skill này — chúng là ephemeral và immutable sau khi `done`, không audit/migrate theo version.
13
13
 
14
14
  Cơ chế (xem `conventions.md` §7 Template Versioning):
15
15
  - **Nguồn sự thật** = `template_version` trong frontmatter template đang cài (`.claude/templates/...`). Đọc thẳng lúc chạy — không manifest, không cache.
@@ -44,6 +44,7 @@ Type của main artifact resolve theo **filename**. Mỗi type map tới đúng
44
44
  | `frd.md` | frd | `main/feature/frd-template.md` |
45
45
  | `fdd.md` | fdd | `main/feature/fdd-template.md` |
46
46
  | `test-design.md` | test-design | `main/feature/test-design-template.md` |
47
+ | `selector-contract.md` | selector-contract | `main/feature/selector-contract-template.md` |
47
48
  | `crd.md` | crd | `main/component/crd-template.md` |
48
49
  | `cdd.md` | cdd | `main/component/cdd-template.md` |
49
50
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: artifact-migrate
3
- description: Migrate MAIN artifact trong .specs/main/ lên structure template mới nhất (chỉ main artifacts — prd/domain/sad/frd/fdd/test-design/crd/cdd; integration artifacts ngoài scope). Tự chạy /artifact-audit (classify-only, scoped) để phát hiện out-dated, rồi áp delta từ block `migrations` của template — add section thiếu, remove section deprecated, update format section (vd ASCII→Mermaid) — set template_version = current. Tương tác: confirm add/remove/update, hỏi carry-over khi rename, section nội dung mới thì interview hoặc NEEDS_CLARIFY (không bịa). Single-artifact, KHÔNG cascade. Nhận tùy chọn 1 main artifact (path); không có arg → quét mọi main artifact, migrate từng cái có confirm + skip.
3
+ description: Migrate MAIN artifact trong .specs/main/ lên structure template mới nhất (chỉ main artifacts — prd/domain/sad/frd/fdd/test-design/selector-contract/crd/cdd; integration artifacts ngoài scope). Tự chạy /artifact-audit (classify-only, scoped) để phát hiện out-dated, rồi áp delta từ block `migrations` của template — add section thiếu, remove section deprecated, update format section (vd ASCII→Mermaid) — set template_version = current. Tương tác: confirm add/remove/update, hỏi carry-over khi rename, section nội dung mới thì interview hoặc NEEDS_CLARIFY (không bịa). Single-artifact, KHÔNG cascade. Nhận tùy chọn 1 main artifact (path); không có arg → quét mọi main artifact, migrate từng cái có confirm + skip.
4
4
  ---
5
5
 
6
6
  # artifact-migrate
@@ -9,7 +9,7 @@ description: Migrate MAIN artifact trong .specs/main/ lên structure template m
9
9
 
10
10
  Đưa một main artifact (hoặc toàn bộ main artifacts) **lỗi thời** lên đúng structure của template mới nhất, rồi cập nhật `template_version`. Đây là vế **fix** đối xứng với `/artifact-audit` (vế **detect**).
11
11
 
12
- > **Scope = chỉ main artifacts** (`prd`, `domain`, `sad`, `frd`, `fdd`, `test-design`, `crd`, `cdd` — đều dưới `.specs/main/`). Integration artifacts (`spec`, `tech`, `test`, `plan`, `todo`, `techdebt`) **không** thuộc scope — ephemeral + immutable sau `done`, không migrate theo version.
12
+ > **Scope = chỉ main artifacts** (`prd`, `domain`, `sad`, `frd`, `fdd`, `test-design`, `selector-contract`, `crd`, `cdd` — đều dưới `.specs/main/`). Integration artifacts (`spec`, `tech`, `test`, `plan`, `todo`, `techdebt`) **không** thuộc scope — ephemeral + immutable sau `done`, không migrate theo version.
13
13
 
14
14
  Cơ chế (xem `conventions.md` §7 Template Versioning):
15
15
  - **Required section hiện tại** = body `##` headings của template (deterministic theo level; `###` = instance).
@@ -34,7 +34,7 @@ Cơ chế (xem `conventions.md` §7 Template Versioning):
34
34
 
35
35
  Resolve type của main artifact theo **filename** (giống `/artifact-audit`). Mỗi type map tới đúng một template tại `.claude/templates/...`:
36
36
 
37
- `prd.md`→`main/prd-template.md` · `domain.md`→`main/domain-template.md` · `sad.md`→`main/sad-template.md` · `frd.md`→`main/feature/frd-template.md` · `fdd.md`→`main/feature/fdd-template.md` · `test-design.md`→`main/feature/test-design-template.md` · `crd.md`→`main/component/crd-template.md` · `cdd.md`→`main/component/cdd-template.md`
37
+ `prd.md`→`main/prd-template.md` · `domain.md`→`main/domain-template.md` · `sad.md`→`main/sad-template.md` · `frd.md`→`main/feature/frd-template.md` · `fdd.md`→`main/feature/fdd-template.md` · `test-design.md`→`main/feature/test-design-template.md` · `selector-contract.md`→`main/feature/selector-contract-template.md` · `crd.md`→`main/component/crd-template.md` · `cdd.md`→`main/component/cdd-template.md`
38
38
 
39
39
  **Chỉ main artifacts.** Integration artifacts (`spec`/`tech`/`test`/`plan`/`todo`/`techdebt`) ngoài scope → bỏ qua. File không khớp map → cũng bỏ qua.
40
40
 
@@ -85,6 +85,7 @@ Load:
85
85
 
86
86
  - `.specs/integrations/{slug}/spec.md` — Requirements, Acceptance Criteria (ghi chú số AC và IDs)
87
87
  - `.specs/integrations/{slug}/tech.md` — Technical Design, Interface Changes, Data Model Changes, Implementation Notes
88
+ - `.specs/main/feature/{F-XXX}-*/selector-contract.md` — cho mỗi feature có UI trong frontmatter `features` (nếu tồn tại): danh sách `data-testid` mà FE task PHẢI gắn (nguồn chung để test auto bám vào)
88
89
  - `.specs/main/domain.md` — Entities và Business Rules liên quan
89
90
 
90
91
  Surface tóm tắt để planning-and-task-breakdown có đủ context:
@@ -97,6 +98,7 @@ CONTEXT CHO PLANNING:
97
98
  - Yêu cầu chính: {tóm tắt từ spec.md — 2-4 bullet}
98
99
  - Acceptance Criteria: {tổng số AC — list IDs theo nhóm Feature/Component như spec.md}
99
100
  - Thay đổi kỹ thuật: {modules, data model, interfaces từ tech.md}
101
+ - Selector contract (testid FE phải gắn): {tổng testid theo feature có UI, hoặc "—" nếu không có}
100
102
  - Shared entities liên quan: {từ domain.md}
101
103
 
102
104
  ASSUMPTIONS:
@@ -112,6 +114,8 @@ ASSUMPTIONS:
112
114
 
113
115
  Invoke `planning-and-task-breakdown` với context đã load. Skill đó sẽ thực hiện: dependency graph, slicing, write tasks. Output phải theo **Output Format** định nghĩa bên dưới — không dùng format mặc định của `planning-and-task-breakdown`.
114
116
 
117
+ **Ràng buộc từ selector-contract (nếu feature có UI):** mỗi FE task (build/sửa component UI) PHẢI gắn đúng các `data-testid` khai trong `selector-contract.md` của feature tương ứng — đó là nguồn chung để e2e-auto/func-auto bám vào (`conventions.md` §3.3). Task `Verification` nên có checklist item "`data-testid {…}` hiện diện trong DOM". KHÔNG tự đặt testid lệch quy ước; brownfield có thể cần task **bổ sung testid còn thiếu** vào component cũ để đạt full coverage theo contract.
118
+
115
119
  ---
116
120
 
117
121
  ## Output Format
@@ -146,4 +150,5 @@ Nếu trong quá trình breakdown phát hiện delta cần cập nhật `sad.md`
146
150
  - [ ] plan.md có section **Dependency Graph**
147
151
  - [ ] Mỗi task có đủ: Mục tiêu / depends / Các bước / Verification
148
152
  - [ ] Không viết code trong suốt quá trình
153
+ - [ ] Nếu feature có UI: FE task gắn `data-testid` theo `selector-contract.md` (Verification kiểm testid hiện diện); brownfield gap → task bổ sung testid còn thiếu
149
154
  - [ ] plan.md + todo.md (integration) KHÔNG mang `template_version` (versioning chỉ cho main artifacts)
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: spec-brownfield-feature
3
- description: Discover features từ code, generate frd.md + fdd.md cho từng feature, điền Feature Index vào prd.md. Phải chạy /spec-brownfield-component trước vì fdd.md tham chiếu C-XXX từ Component Index.
3
+ description: Discover features từ code, generate frd.md + fdd.md (+ selector-contract.md nếu feature có UI) cho từng feature, điền Feature Index vào prd.md. Phải chạy /spec-brownfield-component trước vì fdd.md tham chiếu C-XXX từ Component Index.
4
4
  ---
5
5
 
6
6
  # spec-brownfield-feature
@@ -152,6 +152,16 @@ Convert mỗi rule sang **human-readable diễn đạt** (không copy regex ho
152
152
 
153
153
  **Auto-assign Rule ID** `VR-F{NNN}-{seq}` cho mỗi rule extract được — tăng dần toàn feature, không reset theo field. Sub-rule phức tạp → tách flat thành nhiều rule riêng, mỗi cái 1 ID.
154
154
 
155
+ **4f. Selector-contract — define ĐẦY ĐỦ từ flows (chỉ feature có UI):**
156
+
157
+ **KHÔNG harvest** testid rời rạc từ code. Code brownfield thường gắn testid **thiếu / không nhất quán** → harvest sẽ chép lại đúng cái thiếu đó, vĩnh viễn dưới coverage. Thay vào đó **define contract ĐẦY ĐỦ từ User Flows** (Bước 4a) theo quy ước `{feature-slug}-{element}[-{qualifier}]` (`conventions.md` §3.3) — **giống hệt greenfield**: mỗi bước tương tác/assert trong flow → một row testid. Contract là **trạng thái đích** (full coverage, đặt tên nhất quán), không phải ảnh chụp hiện trạng.
158
+
159
+ Hệ quả brownfield: code hiện tại nhiều khả năng **chưa gắn đủ** các testid này → đó là **việc implement** khi feature được chạm qua integration sau (`/spec-new` → `/plan` → `/build`: FE task gắn / bổ sung testid theo contract). Đây là gap *implementation*, KHÔNG phải câu hỏi clarify — contract tự nó đã đầy đủ.
160
+
161
+ (Tùy chọn) đối chiếu nhanh với `data-testid`/`getByTestId` đã có trong code để ước lượng gap còn bao nhiêu — nhưng testid nào lệch quy ước thì **code sửa theo contract**, KHÔNG phải contract chiều theo code.
162
+
163
+ Chỉ feature có **UI flows**. Feature thuần backend → bỏ qua, KHÔNG tạo selector-contract.
164
+
155
165
  **Quan trọng — flag cho BA review:**
156
166
  - Rule trong code có thể **thiếu** (validation chỉ chạy ở 1 layer, không cover hết) → list những field xuất hiện trong US nhưng không có validation → mark `NEEDS_CLARIFY`.
157
167
  - Rule trong code có thể **lệch business intent** → toàn bộ Verification Rules section nên có header note: *"Rules dưới đây reverse-engineer từ code hiện tại. BA cần review và confirm có match business intent không."*
@@ -206,8 +216,14 @@ Với mỗi feature, generate 2 files dùng templates tương ứng:
206
216
  - Orchestration: retry / timeout / fallback nếu detect được
207
217
  - Cross-component invariants: transaction boundaries nếu detect được
208
218
 
219
+ **`selector-contract.md`** — testid contract (dùng `.claude/templates/main/feature/selector-contract-template.md`) — **chỉ feature có UI flows**:
220
+ - Bảng Testid Contract từ Bước 4f: `testid | Element | Flow › Step | Interaction`. **Define ĐẦY ĐỦ từ flows** theo quy ước (KHÔNG harvest từng cái từ code).
221
+ - Contract là trạng thái đích full-coverage — gap "code chưa gắn đủ" là việc implement sau, **KHÔNG** mark NEEDS_CLARIFY trong contract.
222
+ - Thuần mô tả: KHÔNG track trạng thái implementation, KHÔNG chứa locator thô (xem template).
223
+
209
224
  **Nguyên tắc:**
210
225
  - fdd.md là **file mỏng** — chỉ mô tả tương tác giữa components, không lặp nội dung từ crd.md / cdd.md
226
+ - selector-contract chỉ tạo cho feature có UI; feature backend-only → bỏ qua
211
227
  - Mọi phần không detect được → NEEDS_CLARIFY, không bịa
212
228
 
213
229
  ---
@@ -225,9 +241,9 @@ Sẽ tạo {N} features ({2N} files):
225
241
  Ghi tất cả? [y] hoặc review từng file trước [r]:
226
242
  ```
227
243
 
228
- **Stamp `template_version`:** frontmatter mỗi `frd.md`/`fdd.md` lấy `template_version` từ template tương ứng (xem `conventions.md` §7).
244
+ **Stamp `template_version`:** frontmatter mỗi `frd.md`/`fdd.md`/`selector-contract.md` lấy `template_version` từ template tương ứng (xem `conventions.md` §7).
229
245
 
230
- **Change History:** Append entry vào section `## Change History` cuối mỗi `frd.md`/`fdd.md` vừa ghi (theo `conventions.md` §5.5):
246
+ **Change History:** Append entry vào section `## Change History` cuối mỗi `frd.md`/`fdd.md`/`selector-contract.md` vừa ghi (theo `conventions.md` §5.5):
231
247
 
232
248
  ```markdown
233
249
  ### {YYYY-MM-DD} — manual — create
@@ -309,5 +325,6 @@ grep "NEEDS_CLARIFY" để tìm và fill in khi có thêm context.
309
325
  - [ ] Feature không có tests → AC section có NEEDS_CLARIFY rõ ràng
310
326
  - [ ] Verification Rules: rule reverse-engineer từ code đã đánh dấu source; field thiếu validation đã NEEDS_CLARIFY; không chứa regex/code/error message
311
327
  - [ ] prd.md Feature Index đã được update
312
- - [ ] Mỗi frd.md/fdd.md có `template_version` copy từ template tương ứng
328
+ - [ ] FeatureUI: `selector-contract.md` đã **define ĐẦY ĐỦ từ flows** theo quy ước (full coverage, KHÔNG harvest rời rạc; neo Flow › Step; KHÔNG track implementation/locator); feature backend-only → KHÔNG tạo
329
+ - [ ] Mỗi frd.md/fdd.md/selector-contract.md có `template_version` copy từ template tương ứng
313
330
  - [ ] NEEDS_CLARIFY items được list đầy đủ trong summary
@@ -22,8 +22,9 @@ Skill này là cặp greenfield đối xứng với `/spec-brownfield-feature` (
22
22
  - ✅ *Reference* component frd phụ thuộc (Components Used) + ghi component cần-nhưng-chưa-có như **candidate**.
23
23
  - ✅ Nếu feature mục tiêu là feature mới chưa có trong Index → **register một row vào `prd.md > Features`** (side-effect hợp lệ lên prd).
24
24
  - ✅ **Cascade vocabulary lên `domain.md`** (Bước 4b — pha *mô tả hệ thống*/WHAT): glossary term + **định nghĩa entity đầy đủ** (attributes). `Owner` của entity để `TBD` cho `/spec-sad` điền ở pha *thiết kế hệ thống* (HOW). BA duyệt trước khi ghi. Đây là điểm khác với phiên bản trước (`/spec-frd` từng không đụng domain) — vocabulary sinh ra ở feature-authoring time nên seed luôn, thay vì để domain rỗng tới integration đầu tiên.
25
+ - ✅ **Derive `selector-contract.md`** (Bước 4c — chỉ khi feature có UI flows): skeleton testid từ User Flows theo quy ước. Thuần **cơ học** (không interview nặng), DEV/QC tinh chỉnh sau. KHÁC `fdd`/`test-design` ở dưới: nó chỉ là phép chiếu cơ học của flows BA vừa viết, không cần tư duy design/test của role khác.
25
26
  - ❌ KHÔNG tạo/sửa `crd.md`/`cdd.md` — component artifacts ra đời ở integration time qua `/spec-new` cascade.
26
- - ❌ KHÔNG tạo `fdd.md` (inter-component design) hay `test-design.md` (test) — để skill/role khác lo.
27
+ - ❌ KHÔNG tạo `fdd.md` (inter-component design) hay `test-design.md` (test) — để skill/role khác lo. (`selector-contract.md` thì CÓ — xem ✅ trên.)
27
28
  - ❌ KHÔNG carve component / quyết `Owner` của shared entity (để `/spec-sad`/`/spec-new`); KHÔNG đổi status feature đã có; KHÔNG đụng sad.
28
29
 
29
30
  ## When to Use
@@ -247,6 +248,20 @@ BA quyết **định nghĩa entity** (WHAT); `Owner` để `/spec-sad` cascade b
247
248
 
248
249
  ---
249
250
 
251
+ ### Bước 4c: Derive selector-contract (testid skeleton từ flows)
252
+
253
+ Selector-contract derive **thuần cơ học** từ User Flows (Bước 3 Phần 2) — không phải business decision như VR, không cần interview. Mục tiêu: seed một skeleton `data-testid` để DEV (gắn lúc code) + QC (viết POM lúc test) có **nguồn chung** ngay từ frd-time → drift bất khả thi. Xem `conventions.md` §3.3 > `selector-contract.md`.
254
+
255
+ **Điều kiện sinh:** chỉ khi User Flows có **bước tương tác UI** (user click/fill/select hoặc cần assert kết quả trên màn). Feature thuần backend / không UI → **bỏ qua, KHÔNG tạo file** (không có e2e-auto/func-auto UI test thì không cần testid).
256
+
257
+ **Cách derive:** rà mỗi bước trong flow; bước nào user **tương tác** (click/fill/select) hoặc test cần **assert** trên UI → một row:
258
+ - `testid` theo quy ước `{feature-slug}-{element}[-{qualifier}]` (`conventions.md` §3.3).
259
+ - `Element` = mô tả control; `Flow › Step` = neo về đúng bước (`{Flow N} › "{nhãn bước}"`); `Interaction` = `action`/`assert`/`nav`.
260
+
261
+ Đây là **skeleton mô tả** — chỉ liệt kê element flow nêu rõ; element mơ hồ / list động / element QC cần thêm để DEV-QC tinh chỉnh sau (section Notes). KHÔNG track trạng thái implementation, KHÔNG chứa locator thô. Surface ở Bước 5/6 để user duyệt cùng draft frd.
262
+
263
+ ---
264
+
250
265
  ### Bước 5: Write — sinh draft
251
266
 
252
267
  Dùng `.claude/templates/main/feature/frd-template.md` làm skeleton, điền nội dung từ interview.
@@ -259,6 +274,7 @@ Hiển thị **toàn bộ draft** cho user — chưa ghi file. Kèm:
259
274
  - danh sách component candidate (nếu có) và VR còn `TBD`;
260
275
  - **Open Questions** còn mở (câu hỏi clarify + component candidate) để BA xác nhận hoặc giải quyết trước khi save;
261
276
  - **danh sách domain vocabulary đề xuất** (Bước 4b): glossary term mới + định nghĩa shared entity (`Owner: TBD`), để BA duyệt trước khi cascade lên `domain.md`.
277
+ - **selector-contract skeleton** (Bước 4c, nếu feature có UI flows): bảng testid derive cơ học từ flows, để user liếc qua (DEV/QC tinh chỉnh sau — không phải quyết định của BA).
262
278
 
263
279
  #### Verification Rules — quy ước sinh
264
280
 
@@ -280,6 +296,7 @@ Hiển thị **toàn bộ draft** cho user — chưa ghi file. Kèm:
280
296
  > - Verification Rules đã confirm với BA chưa (không còn TBD ngoài ý muốn)?
281
297
  > - Components Used đúng chưa? Component candidate (nếu có) có hợp lý để chuyển cho /spec-sad không?
282
298
  > - Glossary term / định nghĩa shared entity đề xuất cascade lên domain đã đúng chưa? (term có phải vocabulary nghiệp vụ thật, entity có đáng là shared không, attributes đủ chưa?)
299
+ > - Selector-contract skeleton (nếu có) đã khớp các bước tương tác UI trong flows chưa? (testid đúng quy ước, neo đúng Flow › Step)
283
300
 
284
301
  Chỉ ghi file sau khi user confirm. Yêu cầu chỉnh → cập nhật draft → hỏi lại.
285
302
 
@@ -336,13 +353,17 @@ Append **một** Change History entry vào `domain.md`, operation = `manual` (au
336
353
 
337
354
  (Nếu domain.md đang là skeleton create lần đầu thì entry vẫn `manual`/`update` — file đã được `/spec-prd` scaffold với operation `create` từ trước.) Atomic với 7a: domain cascade fail → rollback cả frd. `Owner` của entity do `/spec-sad`/`/spec-new` cascade bổ sung sau (HOW phase) qua `[MODIFY Owner]`.
338
355
 
339
- **7c. KHÔNG đụng khác.** Không đổi status của các feature *đã có* (frd tồn tại integration bắt đầu; marker "→ frd.md tồn tại" derive từ file existence). Không thêm component vào Index (chỉ candidate). Không carve component / không tự quyết `Owner` của shared entity. Không tạo crd/cdd/fdd/test-design. Không đụng sad.
356
+ **7e. (Chỉ khi Bước 4c sinh selector-contract)** Ghi `.specs/main/feature/{F-XXX}-{slug}/selector-contract.md` từ `.claude/templates/main/feature/selector-contract-template.md` status `draft`, `template_version` copy từ template, `feature_id: F-XXX`. Điền bảng Testid Contract từ skeleton derive Bước 4c. Append Change History entry operation = `manual` / `create` ("Initial testid skeleton derive từ frd User Flows"). Atomic với 7a fail thì rollback cả frd. Re-derive về sau khi flows đổi đi qua `/spec-new`.
357
+
358
+ **7c. KHÔNG đụng gì khác.** Không đổi status của các feature *đã có* (frd tồn tại ≠ integration bắt đầu; marker "→ frd.md tồn tại" derive từ file existence). Không thêm component vào Index (chỉ candidate). Không carve component / không tự quyết `Owner` của shared entity. Không tạo crd/cdd/fdd/test-design (selector-contract thì có — xem 7e). Không đụng sad.
340
359
 
341
360
  **7d. Thông báo kết quả:**
342
361
 
343
362
  ```
344
363
  ✓ .specs/main/feature/{F-XXX}-{slug}/frd.md đã được tạo (status: draft)
345
364
 
365
+ {nếu feature có UI flows} ✓ selector-contract.md đã tạo (skeleton testid từ flows — DEV gắn lúc code, QC dùng lúc viết POM)
366
+
346
367
  {nếu có} Domain cascade (pha mô tả hệ thống):
347
368
  - Glossary: +{N} term
348
369
  - Shared Entities: +{N} entity (định nghĩa đầy đủ; Owner TBD — chờ /spec-sad gán ở pha thiết kế)
@@ -401,6 +422,7 @@ Bước tiếp theo:
401
422
  - [ ] Components Used reference C-XXX có sẵn; component mới ghi candidate + surface cho /spec-sad
402
423
  - [ ] Nếu register feature mới: prd Features có row [NEW] + Change History entry; status feature đã có KHÔNG đổi
403
424
  - [ ] Domain cascade (nếu có vocabulary mới, đã BA confirm): Glossary term ghi đủ định nghĩa; Shared Entity ghi đủ definition + attributes với `Owner: TBD` (KHÔNG tự gán C-XXX); domain.md có Change History entry operation = `manual`
404
- - [ ] KHÔNG tạo crd/cdd/fdd/test-design; KHÔNG carve component / gán Owner entity; KHÔNG đụng sad
425
+ - [ ] Nếu feature có UI flows: `selector-contract.md` đã derive (skeleton testid từ flows, quy ước tên `{slug}-{element}` đúng, neo Flow › Step, KHÔNG track implementation / locator thô); feature thuần backend không UI → KHÔNG tạo
426
+ - [ ] KHÔNG tạo crd/cdd/fdd/test-design (selector-contract là ngoại lệ — derive cơ học); KHÔNG carve component / gán Owner entity; KHÔNG đụng sad
405
427
  - [ ] Change History entry (frd) operation = `manual` (luôn `create`)
406
428
  - [ ] User đã confirm trước khi ghi file