@edupia-tutor/spec-driven-docs 0.14.1 → 0.14.2

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.
Files changed (115) hide show
  1. package/bin/index.js +12 -1
  2. package/commands/debug.md +5 -5
  3. package/commands/define-product.md +38 -36
  4. package/commands/define-product.tmpl +33 -31
  5. package/commands/dev-gen-test.md +5 -5
  6. package/commands/dev-run-test.md +5 -5
  7. package/commands/dev-smoke-test.md +5 -5
  8. package/commands/fix-bug.md +5 -5
  9. package/commands/generate-bdd.md +5 -5
  10. package/commands/generate-code.md +5 -5
  11. package/commands/generate-design-spec.md +7 -7
  12. package/commands/generate-design-spec.tmpl +2 -2
  13. package/commands/generate-prd.md +19 -16
  14. package/commands/generate-prd.tmpl +10 -7
  15. package/commands/generate-spec-manifest.md +7 -7
  16. package/commands/generate-spec-manifest.tmpl +2 -2
  17. package/commands/generate-tech-docs.md +5 -5
  18. package/commands/learn.md +5 -5
  19. package/commands/map-testids.md +5 -5
  20. package/commands/propose-scenario.md +5 -5
  21. package/commands/qc-analyze.md +6 -6
  22. package/commands/qc-analyze.tmpl +1 -1
  23. package/commands/qc-design-test.md +5 -5
  24. package/commands/qc-plan.md +5 -5
  25. package/commands/qc-report.md +5 -5
  26. package/commands/qc-review.md +5 -5
  27. package/commands/qc-run-test.md +5 -5
  28. package/commands/refine-prd.md +8 -8
  29. package/commands/refine-prd.tmpl +3 -3
  30. package/commands/report-bug.md +5 -5
  31. package/commands/review-code.md +5 -5
  32. package/commands/review-context.md +9 -9
  33. package/commands/review-context.tmpl +4 -4
  34. package/commands/review-tech-docs.md +5 -5
  35. package/commands/setup-ai-first.md +5 -5
  36. package/commands/setup-ai-first.tmpl +3 -3
  37. package/commands/sync.md +1 -1
  38. package/commands/sync.tmpl +1 -1
  39. package/commands/validate-traces.md +7 -7
  40. package/commands/validate-traces.tmpl +2 -2
  41. package/core/FRAMEWORK_VERSION +1 -1
  42. package/core/commands/debug.md +5 -5
  43. package/core/commands/define-product.md +38 -36
  44. package/core/commands/dev-gen-test.md +5 -5
  45. package/core/commands/dev-run-test.md +5 -5
  46. package/core/commands/dev-smoke-test.md +5 -5
  47. package/core/commands/fix-bug.md +5 -5
  48. package/core/commands/generate-bdd.md +5 -5
  49. package/core/commands/generate-code.md +5 -5
  50. package/core/commands/generate-design-spec.md +7 -7
  51. package/core/commands/generate-prd.md +19 -16
  52. package/core/commands/generate-spec-manifest.md +7 -7
  53. package/core/commands/generate-tech-docs.md +5 -5
  54. package/core/commands/learn.md +5 -5
  55. package/core/commands/map-testids.md +5 -5
  56. package/core/commands/propose-scenario.md +5 -5
  57. package/core/commands/qc-analyze.md +6 -6
  58. package/core/commands/qc-design-test.md +5 -5
  59. package/core/commands/qc-plan.md +5 -5
  60. package/core/commands/qc-report.md +5 -5
  61. package/core/commands/qc-review.md +5 -5
  62. package/core/commands/qc-run-test.md +5 -5
  63. package/core/commands/refine-prd.md +8 -8
  64. package/core/commands/report-bug.md +5 -5
  65. package/core/commands/review-code.md +5 -5
  66. package/core/commands/review-context.md +9 -9
  67. package/core/commands/review-tech-docs.md +5 -5
  68. package/core/commands/setup-ai-first.md +5 -5
  69. package/core/commands/sync.md +1 -1
  70. package/core/commands/validate-traces.md +7 -7
  71. package/core/skills/code/SKILL.md +5 -5
  72. package/core/skills/debug/SKILL.md +3 -3
  73. package/core/skills/design-spec/SKILL.md +6 -6
  74. package/core/skills/prd/SKILL.md +8 -8
  75. package/core/skills/setup-ai-first/SKILL.md +1 -1
  76. package/core/skills/spec/SKILL.md +4 -4
  77. package/core/skills/test/SKILL.md +8 -8
  78. package/core/steps/context-loader.md +3 -3
  79. package/core/steps/gate.md +2 -2
  80. package/core/templates/prd.template.md +4 -4
  81. package/core/templates/project-context.yaml +2 -2
  82. package/docs/01-getting-started/core-concepts.md +1 -1
  83. package/docs/01-getting-started/quickstart.md +7 -7
  84. package/docs/02-guides/developer/bdd-and-trace.md +1 -1
  85. package/docs/02-guides/developer/scenarios.md +5 -5
  86. package/docs/02-guides/product-owner/handoff-checklist.md +1 -1
  87. package/docs/02-guides/product-owner/scenarios.md +23 -23
  88. package/docs/02-guides/tester/bug-reporting.md +2 -2
  89. package/docs/02-guides/tester/reading-specs.md +2 -2
  90. package/docs/02-guides/tester/scenarios.md +1 -1
  91. package/docs/02-guides/tester/spec-manifest.md +3 -3
  92. package/docs/02-guides/tester/workflow.md +1 -1
  93. package/docs/03-concepts/architecture.md +3 -3
  94. package/docs/03-concepts/pipeline.md +3 -3
  95. package/docs/04-operations/sync-and-update.md +5 -5
  96. package/docs/05-reference/command-cheatsheet.md +2 -2
  97. package/docs/05-reference/commands.md +8 -8
  98. package/package.json +1 -1
  99. package/scripts/migrate-specs.js +5 -3
  100. package/scripts/rename-prd-files.js +174 -0
  101. package/skills/code/SKILL.md +5 -5
  102. package/skills/debug/SKILL.md +3 -3
  103. package/skills/design-spec/SKILL.md +6 -6
  104. package/skills/design-spec/SKILL.tmpl +1 -1
  105. package/skills/prd/SKILL.md +8 -8
  106. package/skills/prd/SKILL.tmpl +2 -2
  107. package/skills/setup-ai-first/SKILL.md +1 -1
  108. package/skills/setup-ai-first/SKILL.tmpl +1 -1
  109. package/skills/spec/SKILL.md +4 -4
  110. package/skills/spec/SKILL.tmpl +2 -2
  111. package/skills/test/SKILL.md +8 -8
  112. package/steps/context-loader.md +3 -3
  113. package/steps/gate.md +2 -2
  114. package/templates/prd.template.md +4 -4
  115. package/templates/project-context.yaml +2 -2
@@ -20,11 +20,11 @@ Output: `specs/product-definition/FEAT-01-login.md`
20
20
  ```
21
21
  Agent tự động: đọc product definition · expand thành PRD đầy đủ với UC, AC, BR · nhắc nếu bạn viết UI details · kiểm tra terminology với business-dictionary.
22
22
 
23
- Output: `specs/auth/FEAT-01-login/prd.md`
23
+ Output: `specs/auth/FEAT-01-login/FEAT-01-login.md`
24
24
 
25
25
  **Bước 3 — Review nội dung:**
26
26
  ```
27
- /refine-prd specs/auth/FEAT-01-login/prd.md
27
+ /refine-prd specs/auth/FEAT-01-login/FEAT-01-login.md
28
28
  ```
29
29
  Agent fan-out 4 lens (QA/DEV/SA/PO) chạy song song, rồi chạy completeness-critic loop cho đến khi một vòng không tìm ra finding mới, cuối cùng dedup + resolve conflict. Findings đầy đủ trong 1 lần chạy.
30
30
 
@@ -33,12 +33,12 @@ Mở findings file, xem xét từng finding: `accepted` → apply · `modified`
33
33
  > **Finding khó hiểu? Bấm 💬 Giải thích.** Nếu một finding mô tả nặng tính kỹ thuật, dùng nút **💬 Giải thích** trên Review Board (extension Spec Driven Docs Tools). Claude sẽ giải thích lại bằng ngôn ngữ no-tech + đề xuất phương án cụ thể (cover cả edge case) ngay trong terminal, và **chờ bạn confirm trước khi apply** vào PRD — tránh refine nhiều vòng. Prompt sửa được qua setting `reviewBoard.clarifyPrompt` (không cần cài lại extension).
34
34
 
35
35
  ```
36
- /review-context --resume specs/auth/FEAT-01-login/prd.md
36
+ /review-context --resume specs/auth/FEAT-01-login/FEAT-01-login.md
37
37
  ```
38
38
 
39
39
  **Bước 4 — Final check:**
40
40
  ```
41
- /review-context specs/auth/FEAT-01-login/prd.md
41
+ /review-context specs/auth/FEAT-01-login/FEAT-01-login.md
42
42
  ```
43
43
  Kiểm tra: `@trace.status`, `@trace.domain`, completeness.
44
44
 
@@ -51,7 +51,7 @@ Kiểm tra: `@trace.status`, `@trace.domain`, completeness.
51
51
 
52
52
  **Bước 6 — Tạo Design Spec (FE/App):**
53
53
  ```
54
- /generate-design-spec specs/auth/FEAT-01-login/prd.md
54
+ /generate-design-spec specs/auth/FEAT-01-login/FEAT-01-login.md
55
55
  ```
56
56
  Agent hỏi platform (web / app). PO phải cung cấp **Figma link node-level** (URL chứa `?node-id=`, lấy bằng right-click vào frame → "Copy link to selection") cho **mỗi screen**. Screen nào thiếu link → bị flag ❌ Missing, Status giữ `draft`, `/generate-bdd` bị BLOCKED cho đến khi đủ link.
57
57
 
@@ -59,7 +59,7 @@ Sau khi Designer review + confirm đủ Figma node-id links → `@trace.status:
59
59
 
60
60
  **Bước 7 — Generate BDD:**
61
61
  ```
62
- /generate-bdd specs/auth/FEAT-01-login/prd.md
62
+ /generate-bdd specs/auth/FEAT-01-login/FEAT-01-login.md
63
63
  ```
64
64
  Agent hỏi: **"Platform? (1) web (2) app (3) system"**
65
65
  - Chọn `web` → `specs/auth/FEAT-01-login/bdd/web/FEAT-01-UC1-login-web.feature`
@@ -111,7 +111,7 @@ git push
111
111
 
112
112
  **Bước 1 — Design Spec:**
113
113
  ```
114
- /generate-design-spec specs/auth/FEAT-01-login/prd.md
114
+ /generate-design-spec specs/auth/FEAT-01-login/FEAT-01-login.md
115
115
  ```
116
116
  Output: `specs/auth/FEAT-01-login/design-spec/FEAT-01-design-spec-web.md`
117
117
 
@@ -119,7 +119,7 @@ Mỗi screen cần Figma link node-id. Screen thiếu → flag ❌ Missing, BLOC
119
119
 
120
120
  **Bước 2 — Generate BDD:**
121
121
  ```
122
- /generate-bdd specs/auth/FEAT-01-login/prd.md
122
+ /generate-bdd specs/auth/FEAT-01-login/FEAT-01-login.md
123
123
  ```
124
124
 
125
125
  | Lần | Platform | Output |
@@ -147,12 +147,12 @@ cat .agent/review/FEAT-01-login-prd-review-context-findings.yaml
147
147
 
148
148
  **Bước 3 — Apply:**
149
149
  ```
150
- /review-context --resume specs/auth/FEAT-01-login/prd.md
150
+ /review-context --resume specs/auth/FEAT-01-login/FEAT-01-login.md
151
151
  ```
152
152
 
153
153
  **Bước 4 — Re-review:**
154
154
  ```
155
- /review-context specs/auth/FEAT-01-login/prd.md
155
+ /review-context specs/auth/FEAT-01-login/FEAT-01-login.md
156
156
  ```
157
157
  Lặp lại cho đến khi `recommendation: APPROVED`.
158
158
 
@@ -167,12 +167,12 @@ Lặp lại cho đến khi `recommendation: APPROVED`.
167
167
 
168
168
  **Bước 2 — Sửa nội dung:**
169
169
  ```
170
- /refine-prd specs/auth/FEAT-01-login/prd.md "Thêm yêu cầu: hỗ trợ đăng nhập bằng OTP"
170
+ /refine-prd specs/auth/FEAT-01-login/FEAT-01-login.md "Thêm yêu cầu: hỗ trợ đăng nhập bằng OTP"
171
171
  ```
172
172
 
173
173
  **Bước 3 — Review lại:**
174
174
  ```
175
- /review-context specs/auth/FEAT-01-login/prd.md
175
+ /review-context specs/auth/FEAT-01-login/FEAT-01-login.md
176
176
  /review-context --resume (nếu cần fix)
177
177
  ```
178
178
 
@@ -183,7 +183,7 @@ Lặp lại cho đến khi `recommendation: APPROVED`.
183
183
  # major bump (2.0) nếu thay đổi cơ bản
184
184
  ```
185
185
  ```bash
186
- git add specs/auth/FEAT-01-login/prd.md
186
+ git add specs/auth/FEAT-01-login/FEAT-01-login.md
187
187
  git commit -m "feat(auth): update FEAT-01 PRD v1.1 — add OTP login AC"
188
188
  git push
189
189
  ```
@@ -239,7 +239,7 @@ services:
239
239
  2. Quyết định PRD nào đúng.
240
240
  3. Sửa file:
241
241
  ```
242
- /review-context --resume specs/auth/FEAT-01-login/prd.md
242
+ /review-context --resume specs/auth/FEAT-01-login/FEAT-01-login.md
243
243
  # với finding P3: modified: "session timeout cập nhật thành 2 giờ theo FEAT-05"
244
244
  ```
245
245
  4. Cả 2 PRD phải nhất quán trước khi dev team generate BDD.
@@ -268,20 +268,20 @@ git push
268
268
  ```
269
269
  specs/
270
270
  ├── auth/
271
- │ ├── FEAT-01-login/prd.md (approved)
272
- │ └── FEAT-08-sso/prd.md (draft)
271
+ │ ├── FEAT-01-login/FEAT-01-login.md (approved)
272
+ │ └── FEAT-08-sso/FEAT-08-sso.md (draft)
273
273
  ├── payment/
274
- │ ├── FEAT-03-checkout/prd.md (approved)
275
- │ └── FEAT-11-refund/prd.md (draft)
274
+ │ ├── FEAT-03-checkout/FEAT-03-checkout.md (approved)
275
+ │ └── FEAT-11-refund/FEAT-11-refund.md (draft)
276
276
  └── loyalty/
277
- └── FEAT-06-points/prd.md (in-review)
277
+ └── FEAT-06-points/FEAT-06-points.md (in-review)
278
278
  ```
279
279
 
280
280
  **Gợi ý:** Hoàn thiện 1 PRD đến `approved` trước khi bắt đầu PRD tiếp theo. Chỉ PRD `approved` mới được dev team sử dụng.
281
281
 
282
282
  ```bash
283
283
  # Xem nhanh tất cả PRDs và status:
284
- grep -r "@trace.status" specs/ --include="prd.md"
284
+ grep -r "@trace.status" specs/ --include="*.md"
285
285
  ```
286
286
 
287
287
  ---
@@ -297,7 +297,7 @@ grep -r "@trace.status" specs/ --include="prd.md"
297
297
  ```
298
298
 
299
299
  ```
300
- /review-context specs/auth/FEAT-01-login/prd.md
300
+ /review-context specs/auth/FEAT-01-login/FEAT-01-login.md
301
301
  → Phải thấy recommendation: APPROVED và 0 critical findings
302
302
  ```
303
303
 
@@ -306,13 +306,13 @@ grep -r "@trace.status" specs/ --include="prd.md"
306
306
  [FEAT-01] PRD Login đã approved — sẵn sàng implement
307
307
 
308
308
  Domain: auth
309
- File: my-project-specs/specs/auth/FEAT-01-login/prd.md
309
+ File: my-project-specs/specs/auth/FEAT-01-login/FEAT-01-login.md
310
310
  Version: 1.0
311
311
  Design Spec (Web): my-project-specs/specs/auth/FEAT-01-login/design-spec/FEAT-01-design-spec-web.md
312
312
 
313
313
  Lệnh để bắt đầu:
314
314
  git submodule update --remote my-project-specs
315
- /review-context my-project-specs/specs/auth/FEAT-01-login/prd.md
315
+ /review-context my-project-specs/specs/auth/FEAT-01-login/FEAT-01-login.md
316
316
  ```
317
317
 
318
318
  ---
@@ -45,7 +45,7 @@ Service : BE / Web / App
45
45
  Severity : Critical / Major / Minor
46
46
 
47
47
  Spec context:
48
- PRD : specs/{domain}/{prd-slug}/prd.md (v{x.x})
48
+ PRD : specs/{domain}/{prd-slug}/{TICKET-ID}-{prd-slug}.md (v{x.x})
49
49
  BDD : {bdd path} → Scenario: "{scenario title}"
50
50
  Tech Doc : {tech_docs path}
51
51
 
@@ -77,7 +77,7 @@ Service : BE
77
77
  Severity : Major
78
78
 
79
79
  Spec context:
80
- PRD : specs/auth/FT-001-login/prd.md (v1.0)
80
+ PRD : specs/auth/FT-001-login/FT-001-login.md (v1.0)
81
81
  BDD : free-trial-specs/specs/auth/FT-001-login/bdd/system/FT-001-login.feature
82
82
  → Scenario: "Lock account after 5 failed attempts"
83
83
  Tech Doc : free-trial-specs/specs/auth/FT-001-login/tech-docs/FT-001-auth-api.md
@@ -18,7 +18,7 @@ Sau khi chạy `/generate-spec-manifest`, tra manifest để lấy paths:
18
18
  ```yaml
19
19
  # spec-manifest.yaml
20
20
  FT-001:
21
- prd: "my-project-specs/specs/auth/FT-001-login/prd.md"
21
+ prd: "my-project-specs/specs/auth/FT-001-login/FT-001-login.md"
22
22
  bdd:
23
23
  be: "my-project-specs/specs/auth/FT-001-login/bdd/system/FT-001-UC1-login-system.feature"
24
24
  web: "my-project-specs/specs/auth/FT-001-login/bdd/web/FT-001-UC1-login-web.feature"
@@ -26,7 +26,7 @@ FT-001:
26
26
  be: "my-project-specs/specs/auth/FT-001-login/tech-docs/FT-001-auth-api.md"
27
27
  ```
28
28
 
29
- **Bước 1: Đọc PRD** tại `my-project-specs/specs/auth/FT-001-login/prd.md`
29
+ **Bước 1: Đọc PRD** tại `my-project-specs/specs/auth/FT-001-login/FT-001-login.md`
30
30
  *(nằm trong spec submodule — shared repo của PO)*
31
31
 
32
32
  ```markdown
@@ -16,7 +16,7 @@ git pull && git submodule update --remote --recursive
16
16
  # 3. Kiểm tra status
17
17
  # FT-042:
18
18
  # status: approved ← ✅ có thể test
19
- # prd: "specs/payment/FT-042-checkout/prd.md"
19
+ # prd: "specs/payment/FT-042-checkout/FT-042-checkout.md"
20
20
  # bdd:
21
21
  # be: "free-trial-specs/specs/payment/FT-042-checkout/bdd/system/FT-042-UC1-checkout-system.feature"
22
22
  # web: "free-trial-specs/specs/payment/FT-042-checkout/bdd/web/FT-042-UC1-checkout-web.feature"
@@ -4,14 +4,14 @@
4
4
 
5
5
  ## Spec-Manifest Là Gì Và Tại Sao Cần
6
6
 
7
- Trong umbrella repo (có `spec_source`), **mọi spec đều nằm trong spec submodule** — gom theo feature-package: mỗi PRD có một thư mục `specs/{domain}/{prd-slug}/` chứa tất cả artifact (`prd.md`, `bdd/{platform}/`, `tech-docs/`, `design-spec/`), trải trên nhiều domain:
7
+ Trong umbrella repo (có `spec_source`), **mọi spec đều nằm trong spec submodule** — gom theo feature-package: mỗi PRD có một thư mục `specs/{domain}/{prd-slug}/` chứa tất cả artifact (`{TICKET-ID}-{prd-slug}.md`, `bdd/{platform}/`, `tech-docs/`, `design-spec/`), trải trên nhiều domain:
8
8
 
9
9
  ```
10
10
  free-trial-umbrella/ ← umbrella (Claude Code mở ở đây)
11
11
  ├── free-trial-specs/ ← SPEC submodule — TẤT CẢ spec ở đây
12
12
  │ └── specs/
13
13
  │ └── auth/FT-001-login/ ← feature-package (1 PRD = 1 thư mục)
14
- │ ├── prd.md ← PRD
14
+ │ ├── {TICKET-ID}-{prd-slug}.md ← PRD
15
15
  │ ├── design-spec/... ← Design Spec
16
16
  │ ├── bdd/system/... ← BDD System (BE)
17
17
  │ ├── bdd/web/... ← BDD Web (FE)
@@ -30,7 +30,7 @@ features:
30
30
  FT-001:
31
31
  domain: auth
32
32
  status: approved
33
- prd: "specs/auth/FT-001-login/prd.md"
33
+ prd: "specs/auth/FT-001-login/FT-001-login.md"
34
34
  pdd: "specs/product-definition/auth/FT-001-def.md"
35
35
  tech_docs:
36
36
  be: "free-trial-specs/specs/auth/FT-001-login/tech-docs/FT-001-UC1-auth-api.md"
@@ -16,7 +16,7 @@ git pull && git submodule update --remote --recursive
16
16
  Lookup FT-042 trong spec-manifest.yaml
17
17
  → status: approved? ✅ (nếu draft → dừng, báo PO)
18
18
  → ghi lại paths (tất cả đều nằm trong submodule):
19
- prd: {spec_source}/specs/{domain}/{prd-slug}/prd.md
19
+ prd: {spec_source}/specs/{domain}/{prd-slug}/{TICKET-ID}-{prd-slug}.md
20
20
  bdd.system: {spec_source}/specs/{domain}/{prd-slug}/bdd/system/FT-042-*.feature
21
21
  bdd.web: {spec_source}/specs/{domain}/{prd-slug}/bdd/web/FT-042-*.feature
22
22
  tech_docs.be: {spec_source}/specs/{domain}/{prd-slug}/tech-docs/FT-042-*.md
@@ -58,7 +58,7 @@ LAYER 5 — OUTPUT (artifacts in consumer proj)
58
58
  Spec module (cross-team, via {spec_source}):
59
59
  specs/product-definition/
60
60
  specs/{domain}/{prd-slug}/ — feature package gom mọi artifact của một PRD:
61
- prd.md · bdd/ (web/app/system) · tech-docs/ (API contract + FE tech-design) · design-spec/
61
+ {TICKET-ID}-{prd-slug}.md · bdd/ (web/app/system) · tech-docs/ (API contract + FE tech-design) · design-spec/
62
62
  feedback/
63
63
  .trace/{domain}/{prd-slug}/*.tsv (authoritative, committed — một chỗ cho PM) · .living-docs/ (gitignored)
64
64
  Service submodule (per-service):
@@ -76,10 +76,10 @@ LAYER 5 — OUTPUT (artifacts in consumer proj)
76
76
 
77
77
  ## Data flow — một command chạy như thế nào
78
78
 
79
- Ví dụ `/generate-bdd specs/payment/process-payment/prd.md`:
79
+ Ví dụ `/generate-bdd specs/payment/process-payment/{TICKET-ID}-process-payment.md`:
80
80
 
81
81
  ```
82
- User types: /generate-bdd specs/payment/process-payment/prd.md
82
+ User types: /generate-bdd specs/payment/process-payment/{TICKET-ID}-process-payment.md
83
83
 
84
84
  [L0] data-guard.js check tool calls real-time → đọc .env/*.key → BLOCK + warn
85
85
 
@@ -24,7 +24,7 @@ Vòng đời feature đi qua các phase, mỗi transition có một **AI review
24
24
  |-------|-----|----------|--------|
25
25
  | **0. Setup** *(one-time)* | Tech Lead | `/setup-ai-first`, `/sync`, `/sync-figma-*` | Config files, submodules, component catalog |
26
26
  | **1. Discovery** | PO + AI | `/define-product` | `specs/product-definition/{TICKET-ID}-{slug}.md` |
27
- | **2. PRD** | AI → SA/PO review | `/generate-prd`, `/refine-prd`, `/review-context` | `specs/{domain}/{prd-slug}/prd.md` |
27
+ | **2. PRD** | AI → SA/PO review | `/generate-prd`, `/refine-prd`, `/review-context` | `specs/{domain}/{prd-slug}/{TICKET-ID}-{prd-slug}.md` |
28
28
  | **2b. Design Spec** *(FE/App only)* | AI → Designer/PO sign-off | `/generate-design-spec` | `specs/{domain}/{prd-slug}/design-spec/{TICKET-ID}-design-spec-{platform}.md` |
29
29
  | **3. BDD Spec** | AI → SA/Dev review | `/generate-bdd`, `/review-context` | `specs/{domain}/{prd-slug}/bdd/{UC-ID}.feature` |
30
30
  | **4. Tech Design** *(platform-aware)* | AI → SA/Lead review | `/generate-tech-docs`, `/review-tech-docs` | BE: `specs/{domain}/{prd-slug}/tech-docs/{UC-ID}-tech-design.md` (API contract) · FE/App: `{UC-ID}-tech-design-{platform}.md` (client design — **gated** trên System BDD + BE contract) |
@@ -48,7 +48,7 @@ Phase 1: Discovery
48
48
  business rules → business logic → AC → validation matrix)
49
49
 
50
50
  Phase 2: PRD
51
- /generate-prd ────────────→ specs/{domain}/{prd-slug}/prd.md
51
+ /generate-prd ────────────→ specs/{domain}/{prd-slug}/{TICKET-ID}-{prd-slug}.md
52
52
  /refine-prd ──────────────→ .agent/review/{prd-slug}-findings.yaml
53
53
  [Review Board: Accept/Modify/Reject]
54
54
  /refine-prd --resume → apply + bump version
@@ -180,7 +180,7 @@ Mọi command bắt đầu ở đây, theo thứ tự:
180
180
  ```
181
181
  CHECKPOINT
182
182
  -----------
183
- Target : specs/auth/FEAT-042-login/prd.md
183
+ Target : specs/auth/FEAT-042-login/FEAT-042-login.md
184
184
  Project : My App
185
185
  Tech stack : TypeScript / React 18
186
186
  Module : react
@@ -100,7 +100,7 @@ npx @edupia-tutor/spec-driven-docs --migrate-specs --apply
100
100
  ```
101
101
 
102
102
  Lệnh sẽ:
103
- - Di chuyển `specs/prd/{domain}/{slug}.md` → `specs/{domain}/{slug}/prd.md`, và `specs/bdd|tech-docs|design-spec/{domain}/…` → `specs/{domain}/{prd-slug}/{bdd|tech-docs|design-spec}/…`; flat `.trace/{UC-ID}.tsv` → `.trace/{domain}/{prd-slug}/{UC-ID}.tsv`.
103
+ - Di chuyển `specs/prd/{domain}/{slug}.md` → `specs/{domain}/{slug}/{TICKET-ID}-{slug}.md`, và `specs/bdd|tech-docs|design-spec/{domain}/…` → `specs/{domain}/{prd-slug}/{bdd|tech-docs|design-spec}/…`; flat `.trace/{UC-ID}.tsv` → `.trace/{domain}/{prd-slug}/{UC-ID}.tsv`.
104
104
  - Suy ra `{prd-slug}` cho mỗi file BDD/tech-doc/design-spec/trace bằng cách đọc header `@trace.source` (PRD nguồn) hoặc tag `@trace.uc` (map qua index `.feature`).
105
105
  - Dùng `git mv` cho file đã track (giữ history), `fs.rename` cho phần còn lại.
106
106
  - Rewrite các tham chiếu nội bộ (`@trace.source`, đường dẫn `specs/…`) trong những file vừa move.
@@ -130,7 +130,7 @@ Claude Code luôn mở ở **umbrella repo** (không mở trong service submodul
130
130
  SPEC SUBMODULE SERVICE SUBMODULE(s)
131
131
  (PO sở hữu · origin riêng) (Dev sở hữu · origin riêng)
132
132
  specs/{domain}/{prd-slug}/ src/ (chỉ code + tooling)
133
- prd.md · bdd/ (web/app/system)
133
+ {TICKET-ID}-{prd-slug}.md · bdd/ (web/app/system)
134
134
  design-spec/ · tech-docs/
135
135
  feedback/ (bug · proposal · prd-change)
136
136
  .trace/{domain}/{prd-slug}/*.tsv (qc_status + dev_selftest — write area của dev/QC)
@@ -257,7 +257,7 @@ Topology giả định cho mọi ví dụ dưới đây:
257
257
  ```bash
258
258
  cd my-project-specs && git pull
259
259
  # /generate-prd · /generate-design-spec · /generate-bdd (web/app/system) · set @trace.status: approved
260
- git add specs/payment/checkout/prd.md \
260
+ git add specs/payment/checkout/{TICKET-ID}-checkout.md \
261
261
  specs/payment/checkout/design-spec/FT-042-checkout-design.md \
262
262
  specs/payment/checkout/bdd/system/FT-042-UC1-checkout-system.feature \
263
263
  specs/payment/checkout/bdd/web/FT-042-UC1-checkout-web.feature \
@@ -416,7 +416,7 @@ cd my-project-web
416
416
  /sync # pull + submodule + Living Docs
417
417
  git add my-project-specs && git commit -m "chore: sync specs" && git push
418
418
 
419
- /review-context my-project-specs/specs/{domain}/{prd-slug}/prd.md
419
+ /review-context my-project-specs/specs/{domain}/{prd-slug}/{TICKET-ID}-{prd-slug}.md
420
420
  # → P0: @trace.domain khớp services config? @trace.status: approved?
421
421
  # Đọc Web BDD do PO generate (KHÔNG tự generate BDD):
422
422
  # my-project-specs/specs/{domain}/{prd-slug}/bdd/web/{TICKET-ID}-UC*.feature
@@ -449,7 +449,7 @@ cd my-project-be
449
449
  /sync
450
450
  # → cũng liệt kê "📥 New tester feedback" → /fix-bug · promote proposal · báo PO
451
451
 
452
- /review-context my-project-specs/specs/{domain}/{prd-slug}/prd.md
452
+ /review-context my-project-specs/specs/{domain}/{prd-slug}/{TICKET-ID}-{prd-slug}.md
453
453
  # Đọc System BDD: my-project-specs/specs/{domain}/{prd-slug}/bdd/system/{TICKET-ID}-UC*.feature
454
454
 
455
455
  /generate-tech-docs {domain}/{TICKET-ID}-UC1
@@ -62,8 +62,8 @@ Có **4 lệnh review** cho **4 loại artifact khác nhau**. Đây là điểm
62
62
 
63
63
  | Tôi muốn review… | Cách dùng (ví dụ) | Nó kiểm cái gì | Ai chạy |
64
64
  |---|---|---|---|
65
- | **PRD — nội dung & độ đầy đủ** | `/refine-prd specs/auth/login/prd.md` | 4 lens QA·DEV·SA·PO: AC có test được? edge case? scope rõ? | PO |
66
- | **PRD — chất lượng trước khi approve** | `/review-context specs/auth/login/prd.md` | P-checks: banned term, mơ hồ, mâu thuẫn PRD khác, thiếu section, routing `@trace.domain` | PO |
65
+ | **PRD — nội dung & độ đầy đủ** | `/refine-prd specs/auth/login/{TICKET-ID}-login.md` | 4 lens QA·DEV·SA·PO: AC có test được? edge case? scope rõ? | PO |
66
+ | **PRD — chất lượng trước khi approve** | `/review-context specs/auth/login/{TICKET-ID}-login.md` | P-checks: banned term, mơ hồ, mâu thuẫn PRD khác, thiếu section, routing `@trace.domain` | PO |
67
67
  | **BDD `.feature`** | `/review-context specs/auth/login/bdd/system/FEAT-01-UC1-login.feature` | B-checks: mỗi AC/BR → có ≥1 scenario? Gherkin R1–R10, compliance C1–C5 | SA/Dev |
68
68
  | **Tech design** | `/review-tech-docs specs/auth/login/tech-docs/FEAT-01-UC1-tech-design.md` | T-checks: đúng layer/architecture, entity, trace BDD, cross-team API sign-off | Dev/SA |
69
69
  | **Code** | `/review-code FEAT-01-UC1` | 4 lens: Security · Performance · Architecture · Test coverage | Dev |
@@ -56,12 +56,12 @@
56
56
 
57
57
  | Command | Cách dùng (ví dụ) | Output | When to use |
58
58
  |---------|-------------------|--------|-------------|
59
- | `/generate-prd` | `/generate-prd specs/product-definition/FEAT-01-login.md` | `specs/{domain}/{prd-slug}/prd.md` | After define-product. Thêm `API Source: existing` + section "Existing API Contract" cho feature brownfield. |
60
- | `/refine-prd` | `/refine-prd specs/auth/login/prd.md` | `.agent/review/{prd-slug}-findings.yaml` | After generate-prd — fan-out 4 review lens + completeness-critic loop, mở Review Board. |
61
- | `/refine-prd --resume` | `/refine-prd --resume specs/auth/login/prd.md` | Applied findings + bumped version | Sau khi review trong Review Board (nút ⚡ Apply tự chạy lệnh này). |
62
- | `/review-context` (PRD) | `/review-context specs/auth/login/prd.md` | `.agent/review/{prd-slug}-review-context-findings.yaml` | Quality gate bắt buộc trước Phase 3. Checks: banned terms (P1), ambiguity (P2), conflicts (P3), completeness (P4). |
63
- | `/review-context --fix` | `/review-context --fix specs/auth/login/prd.md` | Applies all auto-fixable findings immediately | Dev quick-fix, không cần Review Board. |
64
- | `/review-context --resume` | `/review-context --resume specs/auth/login/prd.md` | Applies accepted findings + bump version | PO/SA review — human quyết từng finding. |
59
+ | `/generate-prd` | `/generate-prd specs/product-definition/FEAT-01-login.md` | `specs/{domain}/{prd-slug}/{TICKET-ID}-{prd-slug}.md` | After define-product. Thêm `API Source: existing` + section "Existing API Contract" cho feature brownfield. |
60
+ | `/refine-prd` | `/refine-prd specs/auth/login/{TICKET-ID}-login.md` | `.agent/review/{prd-slug}-findings.yaml` | After generate-prd — fan-out 4 review lens + completeness-critic loop, mở Review Board. |
61
+ | `/refine-prd --resume` | `/refine-prd --resume specs/auth/login/{TICKET-ID}-login.md` | Applied findings + bumped version | Sau khi review trong Review Board (nút ⚡ Apply tự chạy lệnh này). |
62
+ | `/review-context` (PRD) | `/review-context specs/auth/login/{TICKET-ID}-login.md` | `.agent/review/{prd-slug}-review-context-findings.yaml` | Quality gate bắt buộc trước Phase 3. Checks: banned terms (P1), ambiguity (P2), conflicts (P3), completeness (P4). |
63
+ | `/review-context --fix` | `/review-context --fix specs/auth/login/{TICKET-ID}-login.md` | Applies all auto-fixable findings immediately | Dev quick-fix, không cần Review Board. |
64
+ | `/review-context --resume` | `/review-context --resume specs/auth/login/{TICKET-ID}-login.md` | Applies accepted findings + bump version | PO/SA review — human quyết từng finding. |
65
65
 
66
66
  ---
67
67
 
@@ -69,7 +69,7 @@
69
69
 
70
70
  | Command | Cách dùng (ví dụ) | Output | When to use |
71
71
  |---------|-------------------|--------|-------------|
72
- | `/generate-design-spec` | `/generate-design-spec specs/auth/login/prd.md` | `specs/{domain}/{prd-slug}/design-spec/{TICKET-ID}-design-spec-{platform}.md` | FE/App: sau khi PRD approved, trước BDD. PO phải cấp **node-level Figma frame link** (URL có `?node-id=`) cho mỗi screen; AI fetch từng frame qua Figma MCP. Screen thiếu link → ❌ Missing, spec ở draft và chặn sign-off + `/generate-bdd`. |
72
+ | `/generate-design-spec` | `/generate-design-spec specs/auth/login/{TICKET-ID}-login.md` | `specs/{domain}/{prd-slug}/design-spec/{TICKET-ID}-design-spec-{platform}.md` | FE/App: sau khi PRD approved, trước BDD. PO phải cấp **node-level Figma frame link** (URL có `?node-id=`) cho mỗi screen; AI fetch từng frame qua Figma MCP. Screen thiếu link → ❌ Missing, spec ở draft và chặn sign-off + `/generate-bdd`. |
73
73
 
74
74
  > BE teams bỏ qua Phase 2b — đọc PRD trực tiếp rồi `/generate-bdd`.
75
75
 
@@ -79,7 +79,7 @@
79
79
 
80
80
  | Command | Cách dùng (ví dụ) | Output | When to use |
81
81
  |---------|-------------------|--------|-------------|
82
- | `/generate-bdd` | `/generate-bdd specs/auth/login/prd.md` | `specs/{domain}/{prd-slug}/bdd/{UC-ID}.feature` (multi-service: `{prd-slug}/bdd/{service}/{UC-ID}.feature`) | After PRD approved (+ Design Spec sign-off cho FE/App). Đọc Service/Module từ PRD metadata, áp platform vocabulary, hiện SC outline chờ confirm. **Thứ tự outside-in: web → app → system**; `system` **tổng hợp từ web+app BDD** (web&app lệch contract → CHECKPOINT chọn union/platform-hint/separate-endpoints, ghi `@system.resolution:`; chỉ-BE → từ PRD). PRD lớn (>3 UC hoặc >300 dòng) → orchestration mode (1 sub-agent / UC). |
82
+ | `/generate-bdd` | `/generate-bdd specs/auth/login/{TICKET-ID}-login.md` | `specs/{domain}/{prd-slug}/bdd/{UC-ID}.feature` (multi-service: `{prd-slug}/bdd/{service}/{UC-ID}.feature`) | After PRD approved (+ Design Spec sign-off cho FE/App). Đọc Service/Module từ PRD metadata, áp platform vocabulary, hiện SC outline chờ confirm. **Thứ tự outside-in: web → app → system**; `system` **tổng hợp từ web+app BDD** (web&app lệch contract → CHECKPOINT chọn union/platform-hint/separate-endpoints, ghi `@system.resolution:`; chỉ-BE → từ PRD). PRD lớn (>3 UC hoặc >300 dòng) → orchestration mode (1 sub-agent / UC). |
83
83
  | `/review-context` (BDD) | `/review-context specs/auth/login/bdd/system/FEAT-01-UC1-login.feature` | `.agent/review/{uc-id}-review-bdd-findings.yaml` | Quality gate bắt buộc trước Phase 4. Checks: PRD coverage (mỗi AC + BR → ≥1 SC), Gherkin R1–R10, compliance C1–C5. |
84
84
  | `/review-context --fix` | `/review-context --fix specs/auth/login/bdd/web/FEAT-01-UC1-login.feature` | Auto-fix terminology, metadata, coverage matrix | Dev quick-fix. |
85
85
  | `/review-context --resume` | `/review-context --resume specs/auth/login/bdd/system/FEAT-01-UC1-login.feature` | Applies accepted findings + bump bdd_version | SA review. |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@edupia-tutor/spec-driven-docs",
3
- "version": "0.14.1",
3
+ "version": "0.14.2",
4
4
  "description": "AI-First Spec-Driven Development workflow framework for Claude Code",
5
5
  "bin": {
6
6
  "spec-driven-docs": "./bin/index.js"
@@ -5,7 +5,7 @@
5
5
  * artifact-type-first layout to the FEATURE-PACKAGE layout.
6
6
  *
7
7
  * OLD NEW
8
- * specs/prd/{domain}/{slug}.md specs/{domain}/{slug}/prd.md
8
+ * specs/prd/{domain}/{slug}.md specs/{domain}/{slug}/{TICKET-ID}-{slug}.md
9
9
  * specs/bdd/{domain}/{rest} specs/{domain}/{prd-slug}/bdd/{rest}
10
10
  * specs/tech-docs/{domain}/{file} specs/{domain}/{prd-slug}/tech-docs/{file}
11
11
  * specs/design-spec/{domain}/{file} specs/{domain}/{prd-slug}/design-spec/{file}
@@ -83,7 +83,7 @@ const ticketToSlug = {}; // `${domain}/${TICKET}` -> slug (from PRD metadata)
83
83
  const addSlug = (domain, slug) => { (prdByDomain[domain] = prdByDomain[domain] || new Set()).add(slug); };
84
84
  const onlySlug = domain => { const s = prdByDomain[domain]; return s && s.size === 1 ? [...s][0] : null; };
85
85
 
86
- // ── Phase 1 — PRDs: specs/prd/{domain}/{slug}.md → specs/{domain}/{slug}/prd.md ──
86
+ // ── Phase 1 — PRDs: specs/prd/{domain}/{slug}.md → specs/{domain}/{slug}/{TICKET-ID}-{slug}.md ──
87
87
  const prdRoot = path.join(specsAbs, 'prd');
88
88
  for (const file of walk(prdRoot).filter(f => f.endsWith('.md'))) {
89
89
  const parts = rel(file).split('/'); // [SPECS, 'prd', domain, ...rest, name.md]
@@ -98,7 +98,9 @@ for (const file of walk(prdRoot).filter(f => f.endsWith('.md'))) {
98
98
  if (ticket) ticketToSlug[`${domain}/${ticket}`] = slug;
99
99
  let m; const reUcG = new RegExp(reUcName.source, 'g');
100
100
  while ((m = reUcG.exec(body))) ucToSlug[`${domain}/${m[1]}`] = ucToSlug[`${domain}/${m[1]}`] || slug;
101
- moves.push({ from: file, to: path.join(specsAbs, domain, slug, 'prd.md'), type: 'prd' });
101
+ // PRD file name follows the {TICKET-ID}-{slug}.md convention (falls back to {slug}.md if no ticket found)
102
+ const prdFile = ticket ? `${ticket}-${slug}.md` : `${slug}.md`;
103
+ moves.push({ from: file, to: path.join(specsAbs, domain, slug, prdFile), type: 'prd' });
102
104
  }
103
105
 
104
106
  // ── Phase 2 — BDD: specs/bdd/{domain}/{rest} → specs/{domain}/{prd-slug}/bdd/{rest}
@@ -0,0 +1,174 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * rename-prd-files.js — rename feature-package PRD files from the old fixed
5
+ * name `prd.md` to the `{TICKET-ID}-{slug}.md` convention.
6
+ *
7
+ * OLD NEW
8
+ * specs/{domain}/{slug}/prd.md specs/{domain}/{slug}/{TICKET-ID}-{slug}.md
9
+ *
10
+ * For each `specs/{domain}/{slug}/prd.md`:
11
+ * - slug = the feature-package folder name (parent dir)
12
+ * - TICKET-ID is read from the PRD body — the Metadata table row
13
+ * (| **PRD ID** | … | / | **Ticket** | … |) or, failing that, the leading
14
+ * token of the H1 title (`# SEG01-…`). PRDs where no ticket can be resolved
15
+ * are LEFT IN PLACE and listed in the report — never renamed to a guess.
16
+ *
17
+ * After moving, any reference to the old `…/{slug}/prd.md` path inside other
18
+ * spec / trace files (.md, .feature, .tsv, .yaml) is rewritten to the new path.
19
+ *
20
+ * DRY-RUN by default (prints the plan, changes nothing). Pass --apply to execute.
21
+ * Tracked files move with `git mv` to preserve history; the rest with fs.rename.
22
+ *
23
+ * Usage (from the consumer project root):
24
+ * node scripts/rename-prd-files.js # dry-run, prints plan
25
+ * node scripts/rename-prd-files.js --apply # execute the rename
26
+ * node scripts/rename-prd-files.js --specs specs --trace .trace --root .
27
+ */
28
+
29
+ const fs = require('fs');
30
+ const path = require('path');
31
+ const { execSync } = require('child_process');
32
+
33
+ // ── args ────────────────────────────────────────────────────────────────────
34
+ const argv = process.argv.slice(2);
35
+ const has = f => argv.includes(f);
36
+ const flag = (f, d) => { const i = argv.indexOf(f); return i !== -1 ? argv[i + 1] : d; };
37
+
38
+ const APPLY = has('--apply');
39
+ const ROOT = path.resolve(flag('--root', '.'));
40
+ const SPECS = flag('--specs', 'specs');
41
+ const TRACE = flag('--trace', '.trace');
42
+
43
+ const specsAbs = path.join(ROOT, SPECS);
44
+ const traceAbs = path.join(ROOT, TRACE);
45
+
46
+ // ── git tracked set (for `git mv`) ────────────────────────────────────────────
47
+ let tracked = null;
48
+ try {
49
+ const out = execSync('git ls-files', { cwd: ROOT, encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] });
50
+ tracked = new Set(out.split('\n').filter(Boolean).map(p => p.replace(/\\/g, '/')));
51
+ } catch { tracked = null; }
52
+
53
+ const rel = abs => path.relative(ROOT, abs).replace(/\\/g, '/');
54
+ const isTracked = abs => !!(tracked && tracked.has(rel(abs)));
55
+
56
+ // ── helpers ───────────────────────────────────────────────────────────────────
57
+ function walk(dir) {
58
+ const out = [];
59
+ if (!fs.existsSync(dir)) return out;
60
+ for (const e of fs.readdirSync(dir, { withFileTypes: true })) {
61
+ const p = path.join(dir, e.name);
62
+ if (e.isDirectory()) out.push(...walk(p));
63
+ else out.push(p);
64
+ }
65
+ return out;
66
+ }
67
+ const head = (file, n = 16384) => { try { return fs.readFileSync(file, 'utf8').slice(0, n); } catch { return ''; } };
68
+
69
+ // Extract the TICKET-ID from a PRD body. Tries the Metadata table first, then the H1 title.
70
+ function extractTicket(body) {
71
+ // | **PRD ID** | SEG01 | / | **Ticket** | [SEG01](...) | / | **TICKET-ID** | SEG01 |
72
+ let m = body.match(/\|\s*\*\*\s*(?:PRD ID|Ticket(?:\s*ID)?|TICKET-ID|Mã(?:\s*ticket)?)\s*\*\*\s*\|\s*\[?\s*([A-Za-z][A-Za-z0-9_.-]*?)\s*\]?\s*(?:\]\([^)]*\))?\s*\|/i);
73
+ if (m) return m[1];
74
+ // H1 title: "# SEG01-segment-scoring-service ..." or "# SEG01 Feature Name"
75
+ m = body.match(/^#\s+([A-Za-z][A-Za-z0-9_.]*(?:-?\d+)?)\b/m);
76
+ if (m) return m[1];
77
+ return null;
78
+ }
79
+
80
+ // ── plan ───────────────────────────────────────────────────────────────────────
81
+ const moves = []; // { from(abs), to(abs) }
82
+ const unresolved = []; // { file(rel), reason }
83
+
84
+ // Scan specs/{domain}/{slug}/prd.md (PRD lives directly in the feature-package folder)
85
+ for (const file of walk(specsAbs).filter(f => path.basename(f) === 'prd.md')) {
86
+ const parts = rel(file).split('/'); // [SPECS, domain, slug, 'prd.md']
87
+ if (parts.length < 4) { unresolved.push({ file: rel(file), reason: `not a feature-package PRD (expected ${SPECS}/{domain}/{slug}/prd.md)` }); continue; }
88
+ const slug = parts[parts.length - 2];
89
+ const ticket = extractTicket(head(file));
90
+ if (!ticket) { unresolved.push({ file: rel(file), reason: 'no TICKET-ID found (add a Metadata "PRD ID"/"Ticket" row or an H1 title, then re-run)' }); continue; }
91
+ const to = path.join(path.dirname(file), `${ticket}-${slug}.md`);
92
+ if (rel(to) === rel(file)) continue; // already correctly named (shouldn't happen for prd.md)
93
+ moves.push({ from: file, to });
94
+ }
95
+
96
+ // ── old→new ref map (repo-root-relative, forward slashes) ──────────────────────
97
+ const refMap = new Map();
98
+ for (const m of moves) refMap.set(rel(m.from), rel(m.to));
99
+
100
+ // ── report ──────────────────────────────────────────────────────────────────────
101
+ console.log('');
102
+ console.log('╔════════════════════════════════════════════╗');
103
+ console.log(`║ rename-prd-files — ${APPLY ? 'APPLY' : 'DRY RUN'}${' '.repeat(APPLY ? 16 : 14)}║`);
104
+ console.log('╚════════════════════════════════════════════╝');
105
+ console.log(`Root : ${ROOT}`);
106
+ console.log(`Specs : ${SPECS}/ Trace: ${TRACE}/ Git: ${tracked ? 'yes (git mv)' : 'no (fs move)'}`);
107
+ console.log('');
108
+ if (moves.length === 0 && unresolved.length === 0) {
109
+ console.log(`Nothing to rename — no ${SPECS}/{domain}/{slug}/prd.md files found (already on the {TICKET-ID}-{slug}.md convention?).`);
110
+ process.exit(0);
111
+ }
112
+ console.log(`Planned renames: ${moves.length}`);
113
+ console.log('');
114
+ for (const m of moves) console.log(` ${rel(m.from)}\n → ${rel(m.to)}`);
115
+ if (unresolved.length) {
116
+ console.log('');
117
+ console.log('⚠️ Left in place (fix the PRD, then re-run):');
118
+ for (const u of unresolved) console.log(` ${u.file}\n ${u.reason}`);
119
+ }
120
+ console.log('');
121
+
122
+ // ── apply ────────────────────────────────────────────────────────────────────────
123
+ function gitMv(from, to) {
124
+ fs.mkdirSync(path.dirname(to), { recursive: true });
125
+ execSync(`git mv -k "${rel(from)}" "${rel(to)}"`, { cwd: ROOT, stdio: ['ignore', 'ignore', 'pipe'] });
126
+ }
127
+ function fsMv(from, to) {
128
+ fs.mkdirSync(path.dirname(to), { recursive: true });
129
+ fs.renameSync(from, to);
130
+ }
131
+ function rewriteRefs(absFile) {
132
+ if (!/\.(md|feature|tsv|ya?ml)$/.test(absFile)) return 0;
133
+ let txt; try { txt = fs.readFileSync(absFile, 'utf8'); } catch { return 0; }
134
+ let n = 0, out = txt;
135
+ for (const [oldRef, newRef] of refMap) {
136
+ if (out.includes(oldRef)) { out = out.split(oldRef).join(newRef); n++; }
137
+ }
138
+ if (n) fs.writeFileSync(absFile, out, 'utf8');
139
+ return n;
140
+ }
141
+
142
+ if (!APPLY) {
143
+ console.log('DRY RUN — nothing changed. Re-run with --apply to execute.');
144
+ process.exit(0);
145
+ }
146
+
147
+ let moved = 0, failed = 0;
148
+ for (const m of moves) {
149
+ try {
150
+ if (fs.existsSync(m.to)) throw new Error('target already exists');
151
+ (isTracked(m.from) ? gitMv : fsMv)(m.from, m.to);
152
+ moved++;
153
+ } catch (e) {
154
+ failed++;
155
+ console.log(` ❌ ${rel(m.from)} — ${e.message}`);
156
+ }
157
+ }
158
+
159
+ // rewrite references to the old prd.md paths across specs/ and .trace/
160
+ let rewritten = 0;
161
+ const scanForRefs = [...walk(specsAbs), ...walk(traceAbs)];
162
+ for (const f of scanForRefs) rewritten += rewriteRefs(f) > 0 ? 1 : 0;
163
+
164
+ console.log('');
165
+ console.log(`✅ Renamed ${moved}/${moves.length} PRD file(s)${failed ? ` (${failed} failed)` : ''}.`);
166
+ console.log(`✅ Rewrote internal references in ${rewritten} file(s).`);
167
+ if (unresolved.length) console.log(`⚠️ ${unresolved.length} file(s) left in place (see list above).`);
168
+ console.log('');
169
+ console.log('Next:');
170
+ console.log(' 1. Review the renames (git status / git diff).');
171
+ console.log(' 2. Grep your CODE for stale `…/prd.md` refs the move did not touch.');
172
+ console.log(' 3. Run /validate-traces to confirm coverage still resolves.');
173
+ console.log(' 4. Commit.');
174
+ console.log('');