spec-lite 1.7.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spec-lite",
3
- "version": "1.7.0",
3
+ "version": "1.7.1",
4
4
  "description": "Spec-driven development kit for Claude Code",
5
5
  "type": "module",
6
6
  "bin": {
@@ -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
@@ -164,9 +164,11 @@ Với mỗi doc cần sinh, copy từ `templates/test-executions/test-exec-{...}
164
164
  - `TC-F*` ID, `Covers`, `Type`, `Priority`, `Preconditions`, `Steps`, `Expected` → copy **nguyên văn** từ test-design vào bảng Coverage + Test Cases của doc.
165
165
  - `Autoable` (func) → copy y nguyên; func-auto chỉ chứa YES/MAYBE.
166
166
 
167
+ **Testid cho doc automation (chủ yếu e2e-auto):** đọc `.specs/main/feature/{F-XXX}-{slug}/selector-contract.md` (nếu có) — đây là **nguồn testid chung** mà code đã/đang gắn theo cùng contract. Khi điền **POM index §7.1 của e2e-auto** (và func-auto nếu có UI component test dùng testid): dùng **đúng** testid handle trong contract, neo theo `Flow › Step`. **KHÔNG tự đặt testid mới** ở đây (lệch nguồn → vỡ "một-nguồn-hai-bên-đọc"). Biểu thức locator `getByTestId(...)` + file POM `.ts` vẫn do owner viết ở source tree. Feature không có selector-contract → để placeholder + note "feature chưa có selector-contract".
168
+
167
169
  **Placeholder cho owner điền khi chạy** (KHÔNG tự bịa):
168
170
  - **Test Result / Status (CI)** → `—` (chưa chạy).
169
- - **Execution Locators / Test File / POM** → `_Pending — {owner}_`.
171
+ - **Test File / POM file path + biểu thức locator** → `_Pending — {owner}_` (sống ở source tree). *(Testid handle thì đã có từ selector-contract — xem trên, không để trống.)*
170
172
  - **Tool / Command / Layer** (nfr/auto) → gợi ý theo Type nếu suy được (vd NFR performance → `k6`), còn lại để placeholder.
171
173
  - Account/Role matrix, Env tiers, Seed, Fixtures → giữ skeleton template để owner điền theo môi trường.
172
174
 
@@ -243,7 +245,8 @@ Trước khi ghi bundle:
243
245
  - [ ] **Completeness**: mọi `TC-F*` ở Traceability Matrix routed đúng 1 scope bucket — không lọt/trùng.
244
246
  - [ ] Inherit `TC-F*` + fields nguyên văn; KHÔNG ID mới, KHÔNG renumber.
245
247
  - [ ] Frontmatter: `id/type/feature_id/test_design_ref/alt_harness_*` đúng; KHÔNG `template_version`.
246
- - [ ] Test Result/Status/Locators = placeholder, không bịa.
248
+ - [ ] Test Result/Status/biểu thức locator + file POM = placeholder, không bịa.
249
+ - [ ] Doc automation (e2e-auto, func-auto): testid trong POM §7.1 / locator reference lấy từ `selector-contract.md` (nếu feature có), KHÔNG tự đặt testid mới; feature thiếu contract → placeholder + note.
247
250
 
248
251
  Sau khi ghi:
249
252
 
@@ -0,0 +1,88 @@
1
+ ---
2
+ id: selector-contract-{feature}
3
+ type: selector-contract
4
+ status: draft
5
+ owner: "{DEV / QC}"
6
+ feature_id: "{Feature ID}"
7
+ template_version: 1
8
+ migrations:
9
+ - to: 1
10
+ note: "baseline"
11
+ referenced_by:
12
+ - conventions.md > 3. Main Artifacts > 3.3 Feature level > selector-contract.md
13
+ - skills/spec-frd/SKILL.md > Process > Bước 4c (derive) + Bước 7e (save)
14
+ - skills/spec-brownfield-feature/SKILL.md > Process > Bước 4f (define từ flows) + Bước 6 (generate)
15
+ - skills/plan/SKILL.md > Process > Bước 2 (load) + Bước 3 (ràng buộc FE task gắn testid)
16
+ - skills/spec-test-exec/SKILL.md > Process > Bước 5 (testid cho POM automation)
17
+ - templates/test-executions/test-exec-e2e-auto-template.md > §1 Context (Testid source) + §7.1 Page Object Index
18
+ ---
19
+
20
+ <!--
21
+ Canonical format cho .specs/main/feature/{F-XXX}-{slug}/selector-contract.md.
22
+
23
+ SELECTOR CONTRACT — hợp đồng `data-testid` giữa CODE (FE gắn) và AUTOMATION TEST (QC/SE dùng).
24
+ Đây là MỘT loại trong họ "*-contract.md". Sau này có thể thêm api-contract.md, seed-contract.md…
25
+ Mỗi loại = file riêng (một nguồn, một consumer rõ ràng) — KHÔNG gộp chung một contract.md.
26
+
27
+ NGUỒN — derive HOÀN TOÀN từ frd.md > User Flows:
28
+ - Mỗi element user TƯƠNG TÁC (click/fill) hoặc test ASSERT trong flow → một row testid.
29
+ - Mỗi element neo vào một BƯỚC (step) của flow → cột "Flow › Step". KHÔNG neo theo màn hình:
30
+ bước ↔ màn KHÔNG 1:1 (nhiều bước chung một màn, hoặc một flow đi qua nhiều màn) → step mới là khóa chính xác.
31
+ - testid đặt theo QUY ƯỚC (conventions.md §3.3): {feature-slug}-{element}[-{qualifier}].
32
+ - fdd KHÔNG phải nguồn — fdd là tech design của module C-XXX, không mô tả UI element.
33
+
34
+ MỘT NGUỒN — HAI BÊN ĐỌC (⇒ drift bất khả thi):
35
+ - CODE (qua /plan → /build): FE gắn ĐÚNG các data-testid trong bảng này.
36
+ - TEST AUTO (qua /spec-test-exec): POM của test-exec-e2e-auto / func-auto dùng ĐÚNG các testid này.
37
+ Vì cả hai trích CÙNG MỘT file → testid code-gắn và testid test-tìm KHÔNG THỂ lệch nhau.
38
+
39
+ CHỈ phục vụ nhánh AUTOMATION. Manual buckets (func-manual, e2e-manual) dùng mắt người
40
+ điều hướng qua sản phẩm — KHÔNG cần testid, bỏ qua file này.
41
+
42
+ THUẦN MÔ TẢ (main spec): file này khai báo testid CẦN CÓ, KHÔNG track trạng thái implementation
43
+ ("FE gắn chưa" thuộc tầng code/execution — plan/todo + test-exec, không phải ở đây).
44
+ LOCATOR THÔ cũng KHÔNG ở đây: file chứa GIÁ TRỊ testid (cái handle ổn định), KHÔNG chứa biểu thức
45
+ `page.getByTestId(...)` — biểu thức locator sống trong POM `.ts` ở repo code thật.
46
+
47
+ RE-DERIVE khi frd User Flows đổi (element mới → thêm row). Vì thuần mô tả, không có trạng thái
48
+ implementation cần giữ → re-derive là overwrite sạch.
49
+
50
+ VERSIONED: là main artifact nên MANG template_version + migrations, thuộc scope /artifact-audit +
51
+ /artifact-migrate như mọi main artifact khác.
52
+ -->
53
+
54
+ # Selector Contract: {Feature Name}
55
+
56
+ **Feature**: {F-XXX} | **Derived from**: frd.md › User Flows | **Status**: {status}
57
+
58
+ > Hợp đồng `data-testid` cho các element mà automation test (e2e-auto / func-auto) **tương tác** hoặc **assert**.
59
+ > Đây là nguồn DUY NHẤT cho cả FE (gắn testid lúc code) lẫn POM (dùng testid lúc viết test) → hai bên không thể lệch.
60
+ > **Quy ước tên** (conventions.md §3.3): `{feature-slug}-{element}[-{qualifier}]` — vd `order-customer`, `order-submit`, `order-row-{id}`.
61
+
62
+ ## Testid Contract
63
+
64
+ > Mỗi row = một element trong frd User Flows mà test auto chạm tới. Element manual-only / không-tương-tác KHÔNG cần ở đây.
65
+ > Chỉ liệt kê element test thật sự dùng — đừng gắn testid tràn lan (testid là API công khai cho test; gắn thừa = đóng băng cả thứ đáng được tự do đổi).
66
+
67
+ | **testid** | **Element** | **Flow › Step** | **Interaction** |
68
+ |---|---|---|---|
69
+ | `{slug}-{element}` | {mô tả element, vd: input tên khách} | {Flow 1 › "nhập tên khách"} | action |
70
+ | `{slug}-{element}` | {vd: badge đếm đơn} | {Flow 1 › "xem danh sách đơn"} | assert |
71
+
72
+ > **Flow › Step**: neo testid vào đúng bước trong frd User Flows (`{Flow N} › "{nhãn bước}"`). Một màn nhiều bước thì mỗi bước là một row riêng.
73
+ > **Interaction**: `action` (click/fill/select — test tương tác) · `assert` (đọc/verify — test khẳng định) · `nav` (điều hướng).
74
+
75
+ ## Notes *(nếu có)*
76
+
77
+ > Ghi chú để DEV + QC thống nhất các trường hợp quy ước chưa phủ:
78
+ > - Element mơ hồ (vd hai nút cùng nhãn "Lưu") → cần qualifier phân biệt.
79
+ > - List động → testid kèm id: `{slug}-row-{id}`.
80
+ > - Element QC cần assert nhưng frd flow chưa nêu rõ → thêm row + ghi lý do.
81
+
82
+ ## Change History
83
+
84
+ > Derive từ frd User Flows — re-derive (overwrite) khi flows đổi. Operation = `manual` (sinh kèm `/spec-frd`/`/spec-brownfield-feature`, ngoài integration).
85
+
86
+ | **Date** | **Integration** | **Operation** | **Summary** |
87
+ |---|---|---|---|
88
+ | {YYYY-MM-DD} | manual | create | Initial testid skeleton derive từ frd User Flows |
@@ -62,6 +62,7 @@ Kết quả = CI run. Cột Status (CI) ở §5 phản ánh CI run gần nhất
62
62
  | **Method** | automation — Playwright, Page Object Model, real seeded backend (no API mocking) |
63
63
  | **NOT in E2E Scope** | Validation format/length đơn lẻ (→ test-exec-func) · NFR (→ test-exec-nfr) · DM (→ test-exec-dm) |
64
64
  | **Source** | [test-design.md](../../../main/feature/{F-XXX}-{slug}/test-design.md) — TC IDs (E2E Test Cases) + Traceability Matrix |
65
+ | **Testid source** | [selector-contract.md](../../../main/feature/{F-XXX}-{slug}/selector-contract.md) — nguồn `data-testid` chung (code gắn + POM dùng cùng nguồn) |
65
66
  | **Alt harness** | [test-exec-e2e-manual.md](./test-exec-e2e-manual.md) — bản manual (team chọn 1, không chạy song song) |
66
67
 
67
68
  ---
@@ -241,7 +242,7 @@ flowchart TD
241
242
  | {UI Area} | `{action}(arg): Promise<void>` | void | {action} |
242
243
 
243
244
  > **Selector Strategy** (thứ tự ưu tiên): `getByTestId` → `getByRole` → `getByLabel` → `locator([data-attr])`.
244
- > Element cần `data-testid` → request FE add attribute.
245
+ > **Testid lấy từ `selector-contract.md`** của feature — nguồn CHUNG: code gắn + test dùng cùng một nguồn nên không lệch (xem `conventions.md` §3.3). Element cần testid mà contract chưa có **bổ sung vào selector-contract** rồi để FE gắn, KHÔNG tự đặt testid rời ở đây. (Biểu thức `getByTestId(...)` sống trong POM `.ts`; file này chỉ index method.)
245
246
 
246
247
  ### 7.2 Automation Artifacts
247
248