@edupia-tutor/spec-driven-docs 0.14.0 → 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 (162) hide show
  1. package/bin/index.js +12 -1
  2. package/commands/debug.md +436 -436
  3. package/commands/debug.tmpl +111 -111
  4. package/commands/define-product.md +350 -345
  5. package/commands/define-product.tmpl +69 -64
  6. package/commands/dev-gen-test.md +365 -365
  7. package/commands/dev-gen-test.tmpl +63 -63
  8. package/commands/dev-run-test.md +376 -376
  9. package/commands/dev-run-test.tmpl +74 -74
  10. package/commands/dev-smoke-test.md +341 -341
  11. package/commands/dev-smoke-test.tmpl +60 -60
  12. package/commands/fix-bug.md +403 -403
  13. package/commands/fix-bug.tmpl +78 -78
  14. package/commands/generate-bdd.md +513 -513
  15. package/commands/generate-bdd.tmpl +211 -211
  16. package/commands/generate-code.md +481 -483
  17. package/commands/generate-code.tmpl +179 -181
  18. package/commands/generate-design-spec.md +497 -497
  19. package/commands/generate-design-spec.tmpl +220 -220
  20. package/commands/generate-prd.md +452 -400
  21. package/commands/generate-prd.tmpl +50 -200
  22. package/commands/generate-spec-manifest.md +340 -340
  23. package/commands/generate-spec-manifest.tmpl +59 -59
  24. package/commands/generate-tech-docs.md +365 -365
  25. package/commands/generate-tech-docs.tmpl +84 -84
  26. package/commands/learn.md +347 -347
  27. package/commands/learn.tmpl +22 -22
  28. package/commands/map-testids.md +322 -322
  29. package/commands/map-testids.tmpl +41 -41
  30. package/commands/propose-scenario.md +335 -335
  31. package/commands/propose-scenario.tmpl +54 -54
  32. package/commands/qc-analyze.md +323 -324
  33. package/commands/qc-analyze.tmpl +42 -43
  34. package/commands/qc-design-test.md +304 -304
  35. package/commands/qc-design-test.tmpl +23 -23
  36. package/commands/qc-plan.md +297 -297
  37. package/commands/qc-plan.tmpl +16 -16
  38. package/commands/qc-report.md +302 -302
  39. package/commands/qc-report.tmpl +21 -21
  40. package/commands/qc-review.md +298 -298
  41. package/commands/qc-review.tmpl +17 -17
  42. package/commands/qc-run-test.md +337 -337
  43. package/commands/qc-run-test.tmpl +35 -35
  44. package/commands/refine-prd.md +428 -430
  45. package/commands/refine-prd.tmpl +62 -62
  46. package/commands/report-bug.md +351 -351
  47. package/commands/report-bug.tmpl +70 -70
  48. package/commands/review-code.md +364 -364
  49. package/commands/review-code.tmpl +39 -39
  50. package/commands/review-context.md +578 -580
  51. package/commands/review-context.tmpl +212 -212
  52. package/commands/review-tech-docs.md +427 -427
  53. package/commands/review-tech-docs.tmpl +146 -146
  54. package/commands/setup-ai-first.md +239 -239
  55. package/commands/setup-ai-first.tmpl +133 -133
  56. package/commands/sync.md +145 -145
  57. package/commands/sync.tmpl +93 -93
  58. package/commands/update-framework.md +88 -88
  59. package/commands/update-framework.tmpl +36 -36
  60. package/commands/validate-traces.md +381 -381
  61. package/commands/validate-traces.tmpl +100 -100
  62. package/core/FRAMEWORK_VERSION +1 -1
  63. package/core/commands/debug.md +436 -436
  64. package/core/commands/define-product.md +350 -345
  65. package/core/commands/dev-gen-test.md +365 -365
  66. package/core/commands/dev-run-test.md +376 -376
  67. package/core/commands/dev-smoke-test.md +341 -341
  68. package/core/commands/fix-bug.md +403 -403
  69. package/core/commands/generate-bdd.md +513 -513
  70. package/core/commands/generate-code.md +481 -483
  71. package/core/commands/generate-design-spec.md +497 -497
  72. package/core/commands/generate-prd.md +452 -400
  73. package/core/commands/generate-spec-manifest.md +340 -340
  74. package/core/commands/generate-tech-docs.md +365 -365
  75. package/core/commands/learn.md +347 -347
  76. package/core/commands/map-testids.md +322 -322
  77. package/core/commands/propose-scenario.md +335 -335
  78. package/core/commands/qc-analyze.md +323 -324
  79. package/core/commands/qc-design-test.md +304 -304
  80. package/core/commands/qc-plan.md +297 -297
  81. package/core/commands/qc-report.md +302 -302
  82. package/core/commands/qc-review.md +298 -298
  83. package/core/commands/qc-run-test.md +337 -337
  84. package/core/commands/refine-prd.md +428 -430
  85. package/core/commands/report-bug.md +351 -351
  86. package/core/commands/review-code.md +364 -364
  87. package/core/commands/review-context.md +578 -580
  88. package/core/commands/review-tech-docs.md +427 -427
  89. package/core/commands/setup-ai-first.md +239 -239
  90. package/core/commands/sync.md +145 -145
  91. package/core/commands/update-framework.md +88 -88
  92. package/core/commands/validate-traces.md +381 -381
  93. package/core/skills/code/SKILL.md +389 -389
  94. package/core/skills/debug/SKILL.md +391 -391
  95. package/core/skills/design-spec/SKILL.md +318 -318
  96. package/core/skills/discovery/SKILL.md +7 -547
  97. package/core/skills/prd/SKILL.md +298 -394
  98. package/core/skills/setup-ai-first/SKILL.md +80 -80
  99. package/core/skills/spec/SKILL.md +178 -178
  100. package/core/skills/test/SKILL.md +604 -604
  101. package/core/steps/capture-lesson.md +44 -44
  102. package/core/steps/context-loader.md +175 -175
  103. package/core/steps/gate.md +54 -54
  104. package/core/steps/report-footer.md +52 -52
  105. package/core/steps/review-fanout.md +85 -87
  106. package/core/steps/spawn-agent.md +45 -45
  107. package/core/steps/trace-mirror.md +21 -21
  108. package/core/templates/architecture.template.md +37 -37
  109. package/core/templates/design-spec.template.md +77 -77
  110. package/core/templates/platform-guide.template.md +47 -47
  111. package/core/templates/prd.template.md +107 -232
  112. package/core/templates/product-definition.template.md +101 -88
  113. package/core/templates/project-context.yaml +2 -2
  114. package/docs/01-getting-started/core-concepts.md +1 -1
  115. package/docs/01-getting-started/quickstart.md +7 -7
  116. package/docs/02-guides/developer/bdd-and-trace.md +1 -1
  117. package/docs/02-guides/developer/scenarios.md +5 -5
  118. package/docs/02-guides/product-owner/handoff-checklist.md +1 -1
  119. package/docs/02-guides/product-owner/scenarios.md +23 -23
  120. package/docs/02-guides/tester/bug-reporting.md +2 -2
  121. package/docs/02-guides/tester/reading-specs.md +2 -2
  122. package/docs/02-guides/tester/scenarios.md +1 -1
  123. package/docs/02-guides/tester/spec-manifest.md +3 -3
  124. package/docs/02-guides/tester/workflow.md +1 -1
  125. package/docs/03-concepts/architecture.md +3 -3
  126. package/docs/03-concepts/pipeline.md +3 -3
  127. package/docs/04-operations/publishing.md +20 -3
  128. package/docs/04-operations/sync-and-update.md +5 -5
  129. package/docs/05-reference/command-cheatsheet.md +2 -2
  130. package/docs/05-reference/commands.md +8 -8
  131. package/package.json +1 -1
  132. package/scripts/migrate-specs.js +5 -3
  133. package/scripts/rename-prd-files.js +174 -0
  134. package/skills/code/SKILL.md +389 -389
  135. package/skills/code/SKILL.tmpl +56 -56
  136. package/skills/debug/SKILL.md +391 -391
  137. package/skills/debug/SKILL.tmpl +60 -60
  138. package/skills/design-spec/SKILL.md +318 -318
  139. package/skills/design-spec/SKILL.tmpl +37 -37
  140. package/skills/discovery/SKILL.md +7 -547
  141. package/skills/discovery/SKILL.tmpl +7 -140
  142. package/skills/prd/SKILL.md +298 -394
  143. package/skills/prd/SKILL.tmpl +40 -151
  144. package/skills/setup-ai-first/SKILL.md +80 -80
  145. package/skills/setup-ai-first/SKILL.tmpl +28 -28
  146. package/skills/spec/SKILL.md +178 -178
  147. package/skills/spec/SKILL.tmpl +20 -20
  148. package/skills/test/SKILL.md +604 -604
  149. package/skills/test/SKILL.tmpl +44 -44
  150. package/steps/capture-lesson.md +44 -44
  151. package/steps/context-loader.md +175 -175
  152. package/steps/gate.md +54 -54
  153. package/steps/report-footer.md +52 -52
  154. package/steps/review-fanout.md +85 -87
  155. package/steps/spawn-agent.md +45 -45
  156. package/steps/trace-mirror.md +21 -21
  157. package/templates/architecture.template.md +37 -37
  158. package/templates/design-spec.template.md +77 -77
  159. package/templates/platform-guide.template.md +47 -47
  160. package/templates/prd.template.md +107 -232
  161. package/templates/product-definition.template.md +101 -88
  162. package/templates/project-context.yaml +2 -2
@@ -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
@@ -48,13 +48,28 @@ npm whoami
48
48
  3. Điền:
49
49
  - Name: `publish-spec-driven-docs`
50
50
  - Expiration: 1 year
51
- - Packages: chọn `@edupia-tutor/spec-driven-docs` **Read and write**
51
+ - **Bypass 2FA**: **bật** (bắt buộc — nếu không, publish sẽ bị chặn với lỗi `403 ... Two-factor authentication ... is required`)
52
+ - Packages and scopes: chọn `@edupia-tutor/spec-driven-docs` (hoặc cả scope `@edupia-tutor`) → **Read and write**
52
53
  4. Copy token, lưu vào nơi an toàn
53
54
 
54
- Publish với token:
55
+ > ⚠️ **KHÔNG** có flag `npm publish --token <token>` — npm sẽ hiểu `<token>` là tên package và báo lỗi `404 Not Found`. Token phải nạp qua npm config/`.npmrc` như dưới.
56
+
57
+ Publish với token — nạp token vào config trước, rồi publish:
58
+
59
+ ```powershell
60
+ # Nạp token (ghi đè token đăng nhập hiện tại trong .npmrc)
61
+ npm config set //registry.npmjs.org/:_authToken <your-token>
62
+
63
+ npm publish --access public
64
+
65
+ # (tùy chọn) gỡ token khỏi .npmrc sau khi xong — sẽ phải npm login lại lần sau
66
+ npm config delete //registry.npmjs.org/:_authToken
67
+ ```
68
+
69
+ **Cách khác — dùng OTP (nếu account đã bật 2FA app, không cần token bypass):**
55
70
 
56
71
  ```powershell
57
- npm publish --token <your-token>
72
+ npm publish --access public --otp=<mã-6-số>
58
73
  ```
59
74
 
60
75
  ---
@@ -86,6 +101,8 @@ Lệnh này tự động cập nhật `version` trong `package.json` và tạo g
86
101
  npm publish
87
102
  ```
88
103
 
104
+ > Nếu gặp `403 ... Two-factor authentication ... is required`: thêm `--otp=<mã-6-số>`, hoặc dùng granular token có **Bypass 2FA** (xem mục **2.2 — Tạo Access Token**). Access `public` đã set sẵn trong `package.json` (`publishConfig`).
105
+
89
106
  ### Bước 4 — Push git (bao gồm tag vừa tạo)
90
107
 
91
108
  ```powershell
@@ -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.0",
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('');