@longph2102/v-flow 1.5.0

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 (247) hide show
  1. package/AGENTS.md +265 -0
  2. package/CHANGELOG.md +318 -0
  3. package/LICENSE +21 -0
  4. package/README.md +326 -0
  5. package/agents/ba-agent.md +437 -0
  6. package/agents/ba-critic-agent.md +156 -0
  7. package/agents/ba-to-ptyc-agent.md +112 -0
  8. package/agents/bugfix-analyst-agent.md +221 -0
  9. package/agents/constitute-agent.md +155 -0
  10. package/agents/help-agent.md +168 -0
  11. package/agents/implement-agent.md +220 -0
  12. package/agents/import-ba-docs-agent.md +164 -0
  13. package/agents/master-check-agent.md +228 -0
  14. package/agents/metrics-agent.md +180 -0
  15. package/agents/operations-agent.md +123 -0
  16. package/agents/plan-agent.md +218 -0
  17. package/agents/prototype-agent.md +191 -0
  18. package/agents/retrospective-agent.md +196 -0
  19. package/agents/review-agent.md +210 -0
  20. package/agents/sprint-agent.md +191 -0
  21. package/agents/status-agent.md +186 -0
  22. package/agents/sync-agent.md +201 -0
  23. package/agents/test-agent.md +166 -0
  24. package/agents/understand-agent.md +339 -0
  25. package/cli/commands/check.js +96 -0
  26. package/cli/commands/dev-quiz.js +107 -0
  27. package/cli/commands/doctor.js +348 -0
  28. package/cli/commands/feature.js +259 -0
  29. package/cli/commands/hooks.js +163 -0
  30. package/cli/commands/init.js +189 -0
  31. package/cli/commands/log.js +199 -0
  32. package/cli/commands/plugin.js +230 -0
  33. package/cli/commands/score-card.js +203 -0
  34. package/cli/commands/status.js +269 -0
  35. package/cli/commands/sync.js +59 -0
  36. package/cli/commands/upgrade.js +150 -0
  37. package/cli/commands/validate.js +1259 -0
  38. package/cli/commands/watch.js +151 -0
  39. package/cli/index.js +46 -0
  40. package/cli/lib/ac-test-gate.js +89 -0
  41. package/cli/lib/activity-log.js +209 -0
  42. package/cli/lib/cli-error.js +183 -0
  43. package/cli/lib/constitution-lint.js +561 -0
  44. package/cli/lib/dev-quiz-grade.js +127 -0
  45. package/cli/lib/governance.js +78 -0
  46. package/cli/lib/hook-targets.js +167 -0
  47. package/cli/lib/i18n.js +375 -0
  48. package/cli/lib/knowledge-oracle.js +379 -0
  49. package/cli/lib/logger.js +203 -0
  50. package/cli/lib/module-card-lint.js +304 -0
  51. package/cli/lib/module-card-score.js +223 -0
  52. package/cli/lib/plugins.js +481 -0
  53. package/cli/lib/scanner.js +692 -0
  54. package/cli/lib/sync-core.js +232 -0
  55. package/cli/lib/sync-targets.js +84 -0
  56. package/cli/lib/templates.js +268 -0
  57. package/cli/lib/yaml-parser.js +203 -0
  58. package/commands/v.ba-critic.md +101 -0
  59. package/commands/v.ba-to-ptyc.md +71 -0
  60. package/commands/v.bugfix.md +86 -0
  61. package/commands/v.check.md +131 -0
  62. package/commands/v.constitute.md +87 -0
  63. package/commands/v.constitution.md +84 -0
  64. package/commands/v.fork.md +127 -0
  65. package/commands/v.help.md +73 -0
  66. package/commands/v.hotfix.md +200 -0
  67. package/commands/v.implement.md +92 -0
  68. package/commands/v.import-ba-docs.md +222 -0
  69. package/commands/v.metrics.md +74 -0
  70. package/commands/v.operations.md +70 -0
  71. package/commands/v.plan.md +78 -0
  72. package/commands/v.prototype.md +121 -0
  73. package/commands/v.quickfix.md +169 -0
  74. package/commands/v.retrospective.md +80 -0
  75. package/commands/v.review.md +78 -0
  76. package/commands/v.rewind.md +127 -0
  77. package/commands/v.specify.md +118 -0
  78. package/commands/v.sprint.md +75 -0
  79. package/commands/v.status.md +62 -0
  80. package/commands/v.sync.md +81 -0
  81. package/commands/v.test.md +67 -0
  82. package/commands/v.understand.md +112 -0
  83. package/package.json +65 -0
  84. package/skills/_shared/constitution-reader/SKILL.md +109 -0
  85. package/skills/_shared/constitution-reader/config.json +52 -0
  86. package/skills/_shared/constitution-reader/examples/good/b1-phase-output.md +48 -0
  87. package/skills/_shared/constitution-reader/gotchas.md +46 -0
  88. package/skills/_shared/context-reader/SKILL.md +111 -0
  89. package/skills/_shared/context-reader/config.json +54 -0
  90. package/skills/_shared/context-reader/examples/good/legacy-nodejs-output.md +35 -0
  91. package/skills/_shared/context-reader/gotchas.md +49 -0
  92. package/skills/_shared/ears-notation/SKILL.md +63 -0
  93. package/skills/_shared/ears-notation/config.json +55 -0
  94. package/skills/_shared/ears-notation/examples/good/plan-test-interpretation.md +29 -0
  95. package/skills/_shared/ears-notation/gotchas.md +43 -0
  96. package/skills/check/cross-validator/SKILL.md +206 -0
  97. package/skills/check/cross-validator/config.json +33 -0
  98. package/skills/check/cross-validator/examples/good/validation-report-pass-with-concerns.md +105 -0
  99. package/skills/check/cross-validator/gotchas.md +43 -0
  100. package/skills/implement/constitution-enforcer/SKILL.md +134 -0
  101. package/skills/implement/constitution-enforcer/config.json +16 -0
  102. package/skills/implement/constitution-enforcer/examples/bad/vague-report.md +42 -0
  103. package/skills/implement/constitution-enforcer/examples/good/compliance-report.md +57 -0
  104. package/skills/implement/constitution-enforcer/gotchas.md +26 -0
  105. package/skills/implement/constitution-enforcer/scripts/check-constitution.sh +88 -0
  106. package/skills/implement/no-go-zone-guard/SKILL.md +173 -0
  107. package/skills/implement/no-go-zone-guard/config.json +28 -0
  108. package/skills/implement/no-go-zone-guard/examples/good/adapter-workaround.md +46 -0
  109. package/skills/implement/no-go-zone-guard/gotchas.md +27 -0
  110. package/skills/implement/no-go-zone-guard/scripts/check-nogo-zones.sh +148 -0
  111. package/skills/implement/no-go-zone-guard/scripts/nogo-precommit.sh +96 -0
  112. package/skills/implement/tdd-driver/SKILL.md +159 -0
  113. package/skills/implement/tdd-driver/config.json +33 -0
  114. package/skills/implement/tdd-driver/examples/good/tdd-cycle-product-repo.md +81 -0
  115. package/skills/implement/tdd-driver/gotchas.md +34 -0
  116. package/skills/metrics/metrics-collector/SKILL.md +133 -0
  117. package/skills/metrics/metrics-collector/config.json +16 -0
  118. package/skills/metrics/metrics-collector/examples/bad/incomplete-report.md +48 -0
  119. package/skills/metrics/metrics-collector/examples/good/full-metrics-report.md +101 -0
  120. package/skills/metrics/metrics-collector/gotchas.md +26 -0
  121. package/skills/operations/incident-runbook/SKILL.md +167 -0
  122. package/skills/operations/incident-runbook/config.json +21 -0
  123. package/skills/operations/incident-runbook/examples/bad/vague-incident-report.md +48 -0
  124. package/skills/operations/incident-runbook/examples/good/p1-hotfix-response.md +119 -0
  125. package/skills/operations/incident-runbook/gotchas.md +26 -0
  126. package/skills/plan/architecture-designer/SKILL.md +228 -0
  127. package/skills/plan/architecture-designer/config.json +32 -0
  128. package/skills/plan/architecture-designer/examples/bad/vague-plan.md +62 -0
  129. package/skills/plan/architecture-designer/examples/good/expand-contract-migration.md +56 -0
  130. package/skills/plan/architecture-designer/examples/good/plan-structure.md +58 -0
  131. package/skills/plan/architecture-designer/gotchas.md +45 -0
  132. package/skills/plan/task-breakdown/SKILL.md +208 -0
  133. package/skills/plan/task-breakdown/config.json +26 -0
  134. package/skills/plan/task-breakdown/examples/bad/vague-tasks.md +77 -0
  135. package/skills/plan/task-breakdown/examples/good/spike-clarify-tasks.md +66 -0
  136. package/skills/plan/task-breakdown/examples/good/tasks-login-feature.md +111 -0
  137. package/skills/plan/task-breakdown/gotchas.md +39 -0
  138. package/skills/prototype/LOGIC.md +240 -0
  139. package/skills/prototype/SKILL.md +185 -0
  140. package/skills/prototype/UI.md +407 -0
  141. package/skills/prototype/config.json +104 -0
  142. package/skills/prototype/examples/bad/prototype-notes.md +68 -0
  143. package/skills/prototype/examples/good/prototype-notes-ui.md +109 -0
  144. package/skills/prototype/examples/good/prototype-notes.md +67 -0
  145. package/skills/prototype/gotchas.md +128 -0
  146. package/skills/prototype/scripts/check-flow-state.ps1 +112 -0
  147. package/skills/prototype/scripts/check-flow-state.sh +104 -0
  148. package/skills/prototype/scripts/check-prototype-cleanup.ps1 +124 -0
  149. package/skills/prototype/scripts/check-prototype-cleanup.sh +109 -0
  150. package/skills/prototype/scripts/check-prototype-notes.ps1 +107 -0
  151. package/skills/prototype/scripts/check-prototype-notes.sh +102 -0
  152. package/skills/review/adversarial-reviewer/SKILL.md +137 -0
  153. package/skills/review/adversarial-reviewer/config.json +32 -0
  154. package/skills/review/adversarial-reviewer/examples/good/review-report-template.md +56 -0
  155. package/skills/review/adversarial-reviewer/gotchas.md +46 -0
  156. package/skills/review/adversarial-reviewer/scripts/quick-security-scan.sh +52 -0
  157. package/skills/specify/ba-bpmn-doc-gen/SKILL.md +108 -0
  158. package/skills/specify/ba-bpmn-doc-gen/reference/reference-bpmn-generation.md +528 -0
  159. package/skills/specify/ba-bpmn-doc-gen/reference/reference-drawio-flowchart.md +466 -0
  160. package/skills/specify/ba-critic/SKILL.md +172 -0
  161. package/skills/specify/ba-critic/config.json +32 -0
  162. package/skills/specify/ba-critic/examples/good/critic-report-round1.md +51 -0
  163. package/skills/specify/ba-critic/gotchas.md +40 -0
  164. package/skills/specify/ba-critic/scripts/check-spec-quality.sh +72 -0
  165. package/skills/specify/ba-doc-generator/SKILL.md +102 -0
  166. package/skills/specify/ba-doc-generator/references/template-clevel.md +84 -0
  167. package/skills/specify/ba-doc-generator/references/template-compliance.md +83 -0
  168. package/skills/specify/ba-doc-generator/references/template-dev.md +138 -0
  169. package/skills/specify/ba-doc-generator/references/template-partner.md +167 -0
  170. package/skills/specify/ba-doc-generator/references/template-pm.md +92 -0
  171. package/skills/specify/ba-doc-generator/references/template-review.md +114 -0
  172. package/skills/specify/ba-doc-generator/references/template-tester.md +108 -0
  173. package/skills/specify/ba-doc-generator/references/template-user.md +98 -0
  174. package/skills/specify/bugfix-analyst/SKILL.md +296 -0
  175. package/skills/specify/bugfix-analyst/config.json +41 -0
  176. package/skills/specify/bugfix-analyst/examples/bad/common-mistakes.md +71 -0
  177. package/skills/specify/bugfix-analyst/examples/good/email-validation-bugfix.md +53 -0
  178. package/skills/specify/bugfix-analyst/gotchas.md +51 -0
  179. package/skills/specify/ears-writer/SKILL.md +129 -0
  180. package/skills/specify/ears-writer/config.json +20 -0
  181. package/skills/specify/ears-writer/examples/bad/common-mistakes.md +17 -0
  182. package/skills/specify/ears-writer/examples/good/login-requirements.md +41 -0
  183. package/skills/specify/ears-writer/gotchas.md +43 -0
  184. package/skills/specify/ears-writer/scripts/check-ears-compliance.sh +51 -0
  185. package/skills/test/test-case-generator/SKILL.md +161 -0
  186. package/skills/test/test-case-generator/config.json +33 -0
  187. package/skills/test/test-case-generator/examples/good/test-cases-login.md +104 -0
  188. package/skills/test/test-case-generator/gotchas.md +43 -0
  189. package/skills/understand/ba-docs-scanner/SKILL.md +239 -0
  190. package/skills/understand/ba-docs-scanner/config.json +47 -0
  191. package/skills/understand/ba-docs-scanner/examples/good/work-order-br-extract.md +28 -0
  192. package/skills/understand/ba-docs-scanner/gotchas.md +44 -0
  193. package/skills/understand/ba-docs-scanner/merge-rules.md +47 -0
  194. package/skills/understand/codebase-scanner/SKILL.md +260 -0
  195. package/skills/understand/codebase-scanner/config.json +56 -0
  196. package/skills/understand/codebase-scanner/examples/good/menu-module-output.md +44 -0
  197. package/skills/understand/codebase-scanner/gotchas.md +42 -0
  198. package/skills/understand/codebase-scanner/scripts/scan-project-structure.sh +64 -0
  199. package/templates/DESIGN.md +456 -0
  200. package/templates/agent-command-template.yaml +240 -0
  201. package/templates/agent-config-template.md +170 -0
  202. package/templates/agent-definition-template.md +145 -0
  203. package/templates/agent-metrics-template.md +150 -0
  204. package/templates/api-contract-template.md +72 -0
  205. package/templates/bugfix-report-template.md +195 -0
  206. package/templates/bugfix-spec-template.md +134 -0
  207. package/templates/code-review-report-template.md +119 -0
  208. package/templates/constitution-template.md +234 -0
  209. package/templates/context-template.md +94 -0
  210. package/templates/data-model-template.md +95 -0
  211. package/templates/decision-log-template.md +92 -0
  212. package/templates/flow-state-template.yaml +208 -0
  213. package/templates/github/workflows/v-flow-validate.yml +30 -0
  214. package/templates/knowledge/adr-template.md +70 -0
  215. package/templates/knowledge/api-contract-template.md +140 -0
  216. package/templates/knowledge/domain-glossary.md +29 -0
  217. package/templates/knowledge/golden-tests-readme.md +115 -0
  218. package/templates/knowledge/lessons-learned.md +41 -0
  219. package/templates/knowledge/patterns.md +103 -0
  220. package/templates/module-card/SKILL.md +85 -0
  221. package/templates/module-card/api-specs.md +96 -0
  222. package/templates/module-card/business-quiz.md +119 -0
  223. package/templates/module-card/cross-service.md +125 -0
  224. package/templates/module-card/db.md +85 -0
  225. package/templates/module-card/dev-quiz.md +62 -0
  226. package/templates/module-card/permissions.md +83 -0
  227. package/templates/module-card/state-diagram.md +64 -0
  228. package/templates/module-card/tech-context.md +90 -0
  229. package/templates/module-card/ui-flows.md +91 -0
  230. package/templates/module-card/use-cases.md +142 -0
  231. package/templates/module-template.yaml +161 -0
  232. package/templates/operations-report-template.md +108 -0
  233. package/templates/plan-template.md +308 -0
  234. package/templates/prototype-notes-template.md +116 -0
  235. package/templates/ptyc/PTYC.template.docx +0 -0
  236. package/templates/ptyc/ptyc.meta.example.yaml +44 -0
  237. package/templates/retrospective-report-template.md +136 -0
  238. package/templates/security-review-template.md +84 -0
  239. package/templates/session-template.md +167 -0
  240. package/templates/spec-review-log-template.md +75 -0
  241. package/templates/spec-template.md +229 -0
  242. package/templates/sprint-status-template.md +101 -0
  243. package/templates/tasks-template.md +275 -0
  244. package/templates/test-cases-template.md +124 -0
  245. package/templates/ux-checklist-template.md +79 -0
  246. package/templates/validation-report-template.md +125 -0
  247. package/templates/vflow-config-template.yaml +22 -0
@@ -0,0 +1,407 @@
1
+ # UI Prototype
2
+
3
+ Generate **several radically different UI variations** on a single route, switchable from a floating bottom bar. User flips between variants in the browser, picks one (or steals bits from each), then throws the rest away.
4
+
5
+ If the question is about logic/state rather than what something looks like — wrong branch. Use [LOGIC.md](LOGIC.md).
6
+
7
+ ---
8
+
9
+ ## Hai mode: Reproduce vs Explore
10
+
11
+ UI branch có hai mode — Prototype Agent chọn ở Bước 1a:
12
+
13
+ | Mode | Khi nào | Output | Throwaway? |
14
+ |------|---------|--------|-----------|
15
+ | **Reproduce** (`--from-mockup`) | UC đã có mockup định hướng (`ui/mockups/`) | **1** render trung thực qua DESIGN.md → `ui/approved/UC-NN.*` | KHÔNG — là contract |
16
+ | **Explore** (mặc định) | Chưa có giao diện, cần khám phá | Nhiều variant switchable → chọn 1 | Có — xóa sau verdict |
17
+
18
+ Phần lớn tài liệu dưới đây mô tả **Explore mode** (multi-variant). Reproduce mode xem ngay §dưới.
19
+
20
+ ---
21
+
22
+ ## Mode: Reproduce (`--from-mockup`)
23
+
24
+ Biến mockup định hướng (ảnh khách/BA đưa) thành **một** bản render bằng design system thật, chốt làm contract trước khi code.
25
+
26
+ **Nguyên tắc tách tầng** (nên không mâu thuẫn):
27
+ - **Mockup quản cấu trúc** — layout, vùng, thành phần nào, luồng tương tác. Lấy *ý đồ* từ ảnh.
28
+ - **DESIGN.md quản style** — màu, spacing, typography, component thật. KHÔNG copy màu/spacing/font từ ảnh.
29
+
30
+ **Quy trình:**
31
+ 1. Đọc UI Intent của UC trong `spec.md §2`: `Mockup nguồn`, `Bố cục`, `Kế thừa trang`, `Mức ràng buộc`. **Lấy ảnh mockup** theo con trỏ `Mockup nguồn`: `figma:<link>` → **Figma MCP** (`get_design_context` + `get_screenshot`); `docs/*.pdf#p<trang>` → đọc trang PDF; `ui/mockups/*.png|svg` → đọc file. Không có Figma MCP / không đọc được ảnh → yêu cầu human export ảnh vào `ui/mockups/`, KHÔNG bịa.
32
+ 2. Đọc `DESIGN.md` tokens (lookup order ở §DESIGN.md dưới).
33
+ 3. Nếu `Kế thừa trang` trỏ trang cũ → đọc/đối chiếu để render đồng bộ phong cách (tinh thần Sub-shape A: reuse shell, chỉ dựng body).
34
+ 4. Dựng **1** render (không variant) khớp cấu trúc mockup, style từ tokens. `Mức ràng buộc = Định hướng` → ưu tiên đúng layout/thành phần/luồng, không cần pixel; `= Bắt buộc` → bám sát mockup hơn.
35
+ 5. **Verify (§4.5)** — compile/serve không lỗi.
36
+ 6. Handover cho stakeholder duyệt → sửa theo feedback.
37
+ 7. Lưu render đã duyệt vào `ui/approved/UC-NN.*` (**GIỮ**). Ghi `prototype-notes.md` + cập nhật spec UI Intent "Render đã chốt".
38
+
39
+ > ⚠️ **Dựng lại khi `ui/approved/` đã có**: hỏi rõ ý định trước — *làm mới bản chốt* (reproduce → ghi đè + reset `verdict`/`approved_by` về null, phải duyệt lại) **hay** *explore hướng khác* (→ `prototype/ui/` throwaway, KHÔNG đụng `ui/approved/`).
40
+
41
+ **Verdict (reproduce):**
42
+ - `VALIDATED` — render khớp ý đồ + dùng đúng DESIGN.md + **stakeholder duyệt (ghi tên + vai trò người duyệt vào prototype-notes / flow-state `approved_by`)** → `ui/approved/` là contract.
43
+ - `REJECTED` — mockup mâu thuẫn DESIGN.md / không khả thi / stakeholder bác → ghi lý do, route `/v.specify` chỉnh UI Intent.
44
+ - `INCONCLUSIVE` — mockup mờ / thiếu state → hỏi stakeholder.
45
+
46
+ **Khác Explore:** không floating switcher, không multi-variant, **KHÔNG xóa** output (render là contract, không phải throwaway).
47
+
48
+ ---
49
+
50
+ ## When this is the right shape (Explore mode)
51
+
52
+ - "Màn hình này nên trông như thế nào?"
53
+ - "Cho tôi xem vài options cho dashboard này trước khi commit."
54
+ - "Thử layout khác cho settings screen."
55
+ - Bất cứ khi nào user sẽ mất thời gian chọn giữa 3 mockup mơ hồ trong đầu.
56
+
57
+ ---
58
+
59
+ ## Hai Sub-shape — Luôn ưu tiên Sub-shape A
60
+
61
+ UI prototype phán xét tốt nhất khi đặt trong **context thật** — real header, real sidebar, real data, real density. Một variant đứng riêng trong vacuum: mọi cái trông đều ổn. Đặt vào existing page mới lộ ra design problems.
62
+
63
+ > [!IMPORTANT]
64
+ > **Default là Sub-shape A.** Chỉ dùng Sub-shape B khi thực sự không có existing page phù hợp.
65
+
66
+ ### Sub-shape A — Gắn vào existing page (preferred)
67
+
68
+ Route đã tồn tại. Variants được render **trên cùng route**, gated bởi `?variant=` URL search param. Data fetching, auth, params đều giữ nguyên — chỉ swap phần rendering.
69
+
70
+ **Áp dụng cả khi** feature chưa có page riêng nhưng _sẽ tự nhiên nằm trong_ một page có sẵn (section mới trong dashboard, card mới trong settings, bước mới trong existing flow) → mount variants bên trong host page.
71
+
72
+ ```
73
+ Existing route: /dashboard
74
+ Variants mount vào: <DashboardLayout> → swap <DashboardBody variant={v}>
75
+ Switcher float bottom: ?variant=A | B | C
76
+ ```
77
+
78
+ ### Sub-shape B — Tạo route mới (last resort)
79
+
80
+ Chỉ dùng khi feature **genuinely không có existing page** để đặt vào — ví dụ: top-level surface hoàn toàn mới, flow không embed được ở đâu hợp lý.
81
+
82
+ Trước khi chọn Sub-shape B, kiểm tra: "Có thực sự không có existing page nào host được không?" — một route empty ẩn đi design problems mà populated route sẽ expose.
83
+
84
+ Tạo **throwaway route** theo routing convention của project. Đặt tên rõ là prototype (vd: `/prototype/feature-name`, `_prototype_FeatureName`). Same `?variant=` pattern.
85
+
86
+ > Cả hai sub-shapes đều dùng chung floating bottom bar.
87
+
88
+ ---
89
+
90
+ ## DESIGN.md — Design System Source
91
+
92
+ Trước khi generate variants, load design tokens:
93
+
94
+ ```
95
+ Lookup order:
96
+ 1. [project-root]/DESIGN.md ← project override (user đặt thủ công)
97
+ 2. [project-root]/.v-flow/DESIGN.md ← fallback (auto-copy lúc v-flow init)
98
+
99
+ Nếu cả hai không tồn tại: báo lỗi + hướng dẫn chạy v-flow init
100
+ ```
101
+
102
+ Đọc YAML frontmatter của `DESIGN.md` để lấy: colors, typography, spacing, rounded, components. Dùng khi generate variant styles.
103
+
104
+ ---
105
+
106
+ ## Output format
107
+
108
+ ### Mặc định: HTML + CSS + JS thuần
109
+
110
+ Vì prototype chạy ở **S.1.5 — trước khi có bất kỳ code thật nào** (Sub-shape B), hoặc khi team muốn xem nhanh không cần dev server (Sub-shape A mockup):
111
+
112
+ ```
113
+ .v-flow/features/NNN/prototype/ui/
114
+ ├── index.html ← JS được inline để chạy được khi double-click (file:// safe)
115
+ ├── styles.css ← design tokens từ DESIGN.md
116
+ ├── app.js ← bản JS riêng sạch hơn (dùng khi chạy qua dev server)
117
+ └── README.md ← câu hỏi + sub-shape + 2 cách chạy
118
+ ```
119
+
120
+ **Cách 1 — Double-click `index.html`** (không cần gì):
121
+ JS được inline trực tiếp trong `<script>` của HTML. Mở ngay trên trình duyệt.
122
+
123
+ **Cách 2 — Dev server** (tùy chọn, nếu cần):
124
+ ```bash
125
+ npx serve . # Node (có sẵn trong hầu hết môi trường)
126
+ python -m http.server # Python
127
+ ```
128
+
129
+ ### Override: `--framework <name>`
130
+
131
+ Khi user chỉ định framework (thường dùng với Sub-shape A — embed vào existing app):
132
+
133
+ | Flag | Output | Cấu trúc |
134
+ |------|--------|---------|
135
+ | (không có) | HTML + CSS + JS thuần | `index.html`, `styles.css`, `app.js`, `README.md` |
136
+ | `--framework react` | TSX + CSS Module | `VariantA.tsx`, `VariantB.tsx`, `VariantC.tsx`, `*.module.css` |
137
+ | `--framework vue` | Vue SFC | `VariantA.vue`, `VariantB.vue`, `VariantC.vue` |
138
+ | `--framework angular` | Angular Component | `variant-a/`, `variant-b/`, `variant-c/` |
139
+ | `--framework next` | Next.js page | `page.tsx`, tương thích App Router |
140
+
141
+ Với framework mode: user cần có dev server của project chạy. Run command phải được ghi rõ trong `prototype-notes.md`.
142
+
143
+ ---
144
+
145
+ ## Process
146
+
147
+ ### 1. State the question, chọn Sub-shape, và pick N (từ spec.md)
148
+
149
+ Đọc `spec.md` — tìm REQ-xxx có UI ambiguity (hoặc dùng `--req REQ-xxx` để chỉ định). Default: **3 variants**. Không quá 5.
150
+
151
+ **Chọn Sub-shape:**
152
+ ```
153
+ Có existing page phù hợp host variants? → Sub-shape A (embed)
154
+ ↳ Tìm route/page gần nhất với feature đang prototype
155
+ ↳ Xác nhận với user: "Tôi sẽ embed variants vào /settings — OK không?"
156
+
157
+ Không có existing page? → Sub-shape B (new route)
158
+ ↳ Confirm: "Không tìm được page phù hợp, sẽ tạo /prototype/NNN — OK không?"
159
+ ```
160
+
161
+ Ghi rõ ở đầu `README.md` của prototype:
162
+
163
+ ```
164
+ # PROTOTYPE — [Feature NNN]
165
+ # Question: [lấy từ spec REQ-xxx]
166
+ # Sub-shape: A — embedded in /settings | B — new route at /prototype/NNN
167
+ # Plan: 3 variants, switchable via ?variant=
168
+ # Output: [HTML+CSS | React | Vue | Angular | Next]
169
+ # Delete after: verdict captured in prototype-notes.md
170
+ ```
171
+
172
+ ### 2. Generate radically different variants
173
+
174
+ Đọc `DESIGN.md` tokens. Draft mỗi variant. Mỗi variant phải:
175
+
176
+ - Đúng với purpose của page và data có sẵn
177
+ - Dùng đúng design system từ `DESIGN.md` (colors, typography, spacing, components)
178
+ - Có exported component name rõ ràng: `VariantA`, `VariantB`, `VariantC`
179
+
180
+ Variants phải **structurally different** — different layout, different information hierarchy, different primary affordance. Ba card grid hơi khác màu **không phải** UI prototype. Nếu 2 drafts quá giống nhau: redo một cái với explicit "no card grid" constraint.
181
+
182
+ ### 3. Wire them together
183
+
184
+ **Sub-shape A (existing page) — React / Next.js:**
185
+
186
+ ```tsx
187
+ // Trong existing page component — chỉ swap phần render, giữ nguyên data fetching
188
+ const variant = searchParams.get('variant') ?? 'A';
189
+ return (
190
+ <>
191
+ {/* Giữ nguyên existing page wrapper, header, etc. */}
192
+ {variant === 'A' && <VariantA {...existingData} />}
193
+ {variant === 'B' && <VariantB {...existingData} />}
194
+ {variant === 'C' && <VariantC {...existingData} />}
195
+ <PrototypeSwitcher variants={['A','B','C']} current={variant} />
196
+ </>
197
+ );
198
+ ```
199
+
200
+ **Sub-shape A (existing page) — Angular:**
201
+
202
+ ```typescript
203
+ // existing-page.component.ts — inject ActivatedRoute, không thay đổi data fetching
204
+ import { ActivatedRoute } from '@angular/router';
205
+ import { map } from 'rxjs/operators';
206
+
207
+ @Component({ /* ... */ })
208
+ export class ExistingPageComponent {
209
+ variant$ = this.route.queryParamMap.pipe(
210
+ map(params => params.get('variant') ?? 'A')
211
+ );
212
+
213
+ constructor(private route: ActivatedRoute) {}
214
+ }
215
+ ```
216
+
217
+ ```html
218
+ <!-- existing-page.component.html — giữ nguyên page wrapper, chỉ swap body -->
219
+ <app-page-shell>
220
+ <ng-container [ngSwitch]="variant$ | async">
221
+ <app-variant-a *ngSwitchCase="'A'" [data]="existingData$ | async" />
222
+ <app-variant-b *ngSwitchCase="'B'" [data]="existingData$ | async" />
223
+ <app-variant-c *ngSwitchDefault [data]="existingData$ | async" />
224
+ </ng-container>
225
+ <app-prototype-switcher [variants]="['A','B','C']" [current]="variant$ | async" />
226
+ </app-page-shell>
227
+ ```
228
+
229
+ ```typescript
230
+ // prototype-switcher.component.ts — shared cho cả Sub-shape A và B
231
+ import { Router, ActivatedRoute } from '@angular/router';
232
+
233
+ @Component({
234
+ selector: 'app-prototype-switcher',
235
+ template: `
236
+ <div class="proto-switcher">
237
+ <button (click)="cycle(-1)">←</button>
238
+ <span>{{ current }}</span>
239
+ <button (click)="cycle(1)">→</button>
240
+ </div>
241
+ `,
242
+ styles: [`
243
+ .proto-switcher {
244
+ position: fixed; bottom: 16px; left: 50%; transform: translateX(-50%);
245
+ background: #111; color: #fff; padding: 8px 20px; border-radius: 999px;
246
+ display: flex; gap: 16px; align-items: center; font-family: monospace;
247
+ box-shadow: 0 4px 12px rgba(0,0,0,.3); z-index: 9999;
248
+ }
249
+ button { background: none; border: none; color: #fff; font-size: 18px; cursor: pointer; }
250
+ `]
251
+ })
252
+ export class PrototypeSwitcherComponent {
253
+ @Input() variants: string[] = ['A', 'B', 'C'];
254
+ @Input() current = 'A';
255
+
256
+ constructor(private router: Router, private route: ActivatedRoute) {}
257
+
258
+ cycle(dir: number) {
259
+ const idx = (this.variants.indexOf(this.current) + dir + this.variants.length) % this.variants.length;
260
+ this.router.navigate([], {
261
+ relativeTo: this.route,
262
+ queryParams: { variant: this.variants[idx] },
263
+ queryParamsHandling: 'merge'
264
+ });
265
+ }
266
+ }
267
+ // Lưu ý: Declare component này trong một PrototypeModule riêng (không import vào AppModule production)
268
+ ```
269
+
270
+ > [!IMPORTANT]
271
+ > Angular: Dùng `queryParamsHandling: 'merge'` để không xóa các query params khác của page.
272
+ > Không import `PrototypeSwitcherComponent` vào bất kỳ production module nào.
273
+
274
+ **Sub-shape B (new route) — HTML mode (mặc định):**
275
+
276
+ `index.html` chứa cả 3 variants, JS được **inline** trong `<script>` để chạy được qua `file://` protocol:
277
+
278
+ ```html
279
+ <!-- index.html -->
280
+ <!DOCTYPE html>
281
+ <html lang="vi">
282
+ <head>
283
+ <meta charset="UTF-8">
284
+ <title>Prototype — [Feature NNN]</title>
285
+ <link rel="stylesheet" href="styles.css">
286
+ </head>
287
+ <body>
288
+ <!-- Variants — chỉ hiện 1 cái tại một thời điểm -->
289
+ <div data-variant="A"><!-- Variant A markup --></div>
290
+ <div data-variant="B" hidden><!-- Variant B markup --></div>
291
+ <div data-variant="C" hidden><!-- Variant C markup --></div>
292
+
293
+ <!-- Floating switcher -->
294
+ <div id="switcher">...</div>
295
+
296
+ <!-- Inline JS: works on file:// AND http:// -->
297
+ <script>
298
+ /* app.js inlined — see app.js for editable version */
299
+ const variants = ['A','B','C'];
300
+ function showVariant(v) {
301
+ document.querySelectorAll('[data-variant]').forEach(el => {
302
+ el.hidden = el.dataset.variant !== v;
303
+ });
304
+ document.getElementById('variant-label').textContent = v;
305
+ history.replaceState(null, '', '?variant=' + v);
306
+ }
307
+ const initial = new URLSearchParams(location.search).get('variant') ?? 'A';
308
+ showVariant(initial);
309
+ function switchVariant(dir) {
310
+ const cur = new URLSearchParams(location.search).get('variant') ?? 'A';
311
+ const idx = (variants.indexOf(cur) + dir + variants.length) % variants.length;
312
+ showVariant(variants[idx]);
313
+ }
314
+ document.addEventListener('keydown', e => {
315
+ if (['INPUT','TEXTAREA'].includes(document.activeElement.tagName)) return;
316
+ if (e.key === 'ArrowLeft') switchVariant(-1);
317
+ if (e.key === 'ArrowRight') switchVariant(1);
318
+ });
319
+ </script>
320
+ </body>
321
+ </html>
322
+ ```
323
+
324
+ `app.js` là bản JS riêng giống hệt nhưng không inline — dùng khi chạy qua dev server và muốn edit JS sạch hơn.
325
+
326
+ ### 4. Build the floating switcher
327
+
328
+ Small fixed-position bar at bottom-centre với ba thành phần:
329
+
330
+ - **Left arrow** — cycles previous variant (wraps around)
331
+ - **Variant label** — current variant key + name nếu có. e.g. `B — Sidebar layout`
332
+ - **Right arrow** — cycles forward (wraps around)
333
+
334
+ Behavior:
335
+ - Click arrow → update URL search param (framework router hoặc `history.replaceState`) — URL shareable + reload-stable
336
+ - Keyboard: `←` `→` cycle variants. KHÔNG intercept khi `<input>`, `<textarea>`, `[contenteditable]` đang focused
337
+ - Visually distinct — high-contrast pill, subtle shadow — rõ ràng không phải part of design
338
+ - Hidden in production (`process.env.NODE_ENV !== 'production'` hoặc equivalent)
339
+
340
+ **HTML mode:**
341
+ ```html
342
+ <div id="switcher" style="
343
+ position:fixed; bottom:16px; left:50%; transform:translateX(-50%);
344
+ background:#111; color:#fff; padding:8px 20px; border-radius:999px;
345
+ display:flex; gap:16px; align-items:center; font-family:monospace;
346
+ box-shadow:0 4px 12px rgba(0,0,0,0.3); z-index:9999;
347
+ ">
348
+ <button onclick="switchVariant(-1)" style="background:none;border:none;color:#fff;font-size:18px;cursor:pointer">←</button>
349
+ <span id="variant-label" style="font-size:13px;letter-spacing:1px">A</span>
350
+ <button onclick="switchVariant(1)" style="background:none;border:none;color:#fff;font-size:18px;cursor:pointer">→</button>
351
+ </div>
352
+ ```
353
+
354
+ **Framework mode:** Build `<PrototypeSwitcher>` component — 1 component dùng cho cả Sub-shape A và B.
355
+
356
+ ### 4.5. Runtime Verification (Verify before handover)
357
+
358
+ Trước khi gửi URL hoặc hướng dẫn chạy cho người dùng, Agent **BẮT BUỘC** phải:
359
+ - Chạy thử compile lệnh để đảm bảo tất cả UI variants không bị lỗi compile (TypeScript/Sass/Vue/React errors).
360
+ - Nếu sử dụng framework (Sub-shape A/B), đảm bảo server khởi chạy thành công mà không bị crash render ban đầu.
361
+ - Nếu là HTML thuần, đảm bảo file `index.html` và các file CSS/JS liên quan tồn tại và link đúng đường dẫn tương đối.
362
+
363
+ ### 5. Hand it over
364
+
365
+ **HTML mode:** Cung cấp 2 cách chạy trong `README.md`:
366
+
367
+ ```md
368
+ ## Chạy prototype
369
+
370
+ **Cách 1 — Double-click** (nhanh nhất):
371
+ Mở file `index.html` trực tiếp trong browser.
372
+
373
+ **Cách 2 — Local dev server** (nếu cần load app.js riêng):
374
+ ```bash
375
+ npx serve . # chạy tại .v-flow/features/NNN/prototype/ui/
376
+ python -m http.server
377
+ ```
378
+ Rồi mở http://localhost:3000
379
+ ```
380
+
381
+ **Framework mode (Sub-shape A):** Surface URL của existing page + `?variant=` keys. User flip trong khi dev server đang chạy.
382
+
383
+ Interesting feedback: **"Tôi muốn header của B với sidebar của C"** — đó là actual design họ muốn.
384
+
385
+ ### 6. Capture the answer → prototype-notes.md
386
+
387
+ Khi variant đã được chọn:
388
+
389
+ 1. Điền verdict vào `prototype-notes.md` (VALIDATED / REJECTED / INCONCLUSIVE)
390
+ 2. Ghi rõ variant nào thắng, tại sao, và sub-shape đã dùng
391
+ 3. Map về REQ-xxx — finding này ảnh hưởng requirement nào?
392
+ 4. Append execution trace vào `_session.md`
393
+ 5. Update `artifacts.prototype.*` trong `.flow-state.yaml`
394
+ 6. **Sub-shape A**: Xóa variant components và switcher — fold winner vào existing page
395
+ 7. **Sub-shape B**: Promote winning variant → real route, xóa throwaway route và switcher
396
+
397
+ Đừng để variant components hoặc switcher nằm lại trong repo. Chúng rot nhanh và confuse người đọc tiếp theo.
398
+
399
+ ---
400
+
401
+ ## Anti-patterns
402
+
403
+ - **Variants chỉ khác màu hoặc copy** — đó là tweak, không phải prototype. Real variants disagree về structure.
404
+ - **Share quá nhiều code giữa variants** — `<Header>` share được; `<Layout>` share là thất bại. Mỗi variant phải tự do throw out layout.
405
+ - **Bỏ qua Sub-shape A** — luôn hỏi "có existing page không?" trước khi tạo route mới. Xem Gotcha G-005.
406
+ - **Wire variants to real mutations** — read-only prototypes là fine. Nếu cần mutate, dùng stub.
407
+ - **Promote prototype trực tiếp lên production** — variant code viết dưới prototype constraints (no tests, minimal error handling). Rewrite properly khi fold vào real code.
@@ -0,0 +1,104 @@
1
+ {
2
+ "_comment": "Prototype Skill Configuration — override per-project bằng cách copy file này vào [project-root]/.v-flow/skill-config/prototype.json",
3
+
4
+ "branch_selection": {
5
+ "default_for_ambiguous": "auto",
6
+ "_comment_default_for_ambiguous": "auto | logic | ui — khi câu hỏi không rõ branch nào và user AFK",
7
+
8
+ "auto_rules": {
9
+ "_comment": "Khi default_for_ambiguous = 'auto', agent dùng bảng này để chọn branch dựa trên context signal (theo thứ tự ưu tiên)",
10
+ "priority_order": [
11
+ {
12
+ "signal": "REQ type là E (Event) hoặc S (State) — ví dụ REQ-E01, REQ-S03",
13
+ "branch": "LOGIC",
14
+ "reason": "State/event REQs thường có behavior phức tạp cần validate qua real cases"
15
+ },
16
+ {
17
+ "signal": "Ambiguity marker nằm trong UI section của spec (section 'Màn hình', 'UI', 'Layout', 'Wireframe')",
18
+ "branch": "UI",
19
+ "reason": "Ambiguity ở UI section → câu hỏi về giao diện"
20
+ },
21
+ {
22
+ "signal": "Ambiguity marker nằm trong AC section có từ khóa state/flow ('trạng thái', 'transition', 'khi nào', 'nếu', 'sau khi')",
23
+ "branch": "LOGIC",
24
+ "reason": "AC phức tạp về flow/state → cần validate behavior"
25
+ },
26
+ {
27
+ "signal": "Module context là backend service / API / domain logic",
28
+ "branch": "LOGIC",
29
+ "reason": "Backend context → behavior question nhiều hơn UI"
30
+ },
31
+ {
32
+ "signal": "Module context là frontend page / component / screen",
33
+ "branch": "UI",
34
+ "reason": "Frontend context → layout/UX question nhiều hơn logic"
35
+ },
36
+ {
37
+ "signal": "Không detect được signal nào rõ ràng",
38
+ "branch": "LOGIC",
39
+ "reason": "LOGIC prototype an toàn hơn khi không chắc — TUI ít side-effects hơn UI variant"
40
+ }
41
+ ]
42
+ },
43
+
44
+ "afk_handling": {
45
+ "_comment": "Khi user không available để xác nhận branch/question",
46
+ "wait_before_default_seconds": 0,
47
+ "_comment_wait": "0 = không chờ, default ngay theo auto_rules. Tăng lên nếu muốn agent chờ user trả lời trước.",
48
+ "always_log_assumption": true,
49
+ "_comment_log": "Luôn ghi rõ assumption vào đầu prototype README và prototype-notes.md: 'User AFK — defaulted to LOGIC based on [signal]'"
50
+ },
51
+
52
+ "multi_marker_priority": {
53
+ "_comment": "Khi spec có nhiều REQ với ambiguity markers, agent chọn theo thứ tự này",
54
+ "priority_order": [
55
+ "REQ được chỉ định qua --req flag (override tất cả)",
56
+ "REQ type S (State) — state machine thường block nhiều REQ khác nhất",
57
+ "REQ type E (Event) — event handling thường có side effects phức tạp",
58
+ "REQ type U (Ubiquitous) — nếu core business rule chưa rõ",
59
+ "REQ type O (Optional) — ít priority nhất",
60
+ "Nếu nhiều REQ cùng priority — chọn REQ đầu tiên trong spec (top-down)"
61
+ ],
62
+ "max_questions_per_prototype": 1,
63
+ "_comment_max": "Mỗi prototype chỉ trả lời 1 câu hỏi. Nếu cần nhiều → chạy /v.prototype nhiều lần (xem prototype-agent.md §Scope giới hạn)"
64
+ }
65
+ },
66
+
67
+ "ui_branch": {
68
+ "default_variants": 3,
69
+ "max_variants": 5,
70
+ "default_framework": "html",
71
+ "_comment_default_framework": "html | react | vue | angular | next",
72
+ "default_subshape": "A",
73
+ "_comment_default_subshape": "A = embed in existing page (preferred) | B = new throwaway route (last resort)"
74
+ },
75
+
76
+ "logic_branch": {
77
+ "preferred_runtime_order": ["detect", "ask"],
78
+ "_comment_preferred_runtime_order": "detect = auto-detect từ project files; ask = hỏi user nếu không detect được"
79
+ },
80
+
81
+ "ambiguity_markers": {
82
+ "keywords_vi": [
83
+ "chưa rõ", "cần thảo luận", "phụ thuộc", "có thể là",
84
+ "TBD", "tùy thiết kế", "xem mockup", "unclear", "to be decided",
85
+ "cần xác nhận", "đang xem xét", "chờ feedback"
86
+ ],
87
+ "keywords_en": [
88
+ "TBD", "unclear", "to be decided", "pending", "to discuss",
89
+ "needs clarification", "may be", "tbc"
90
+ ],
91
+ "patterns": [
92
+ "Acceptance Criteria trống",
93
+ "State transitions chưa được validate",
94
+ "UI section không có wireframe"
95
+ ]
96
+ },
97
+
98
+ "output": {
99
+ "prototype_dir": ".v-flow/features/{NNN}/prototype/",
100
+ "notes_file": ".v-flow/features/{NNN}/prototype-notes.md",
101
+ "cleanup_after_verdict": true,
102
+ "_comment_cleanup": "Tự động gợi ý xóa prototype/ sau khi ghi verdict"
103
+ }
104
+ }
@@ -0,0 +1,68 @@
1
+ # Mẫu Prototype Notes — ❌ Thiếu thông tin
2
+
3
+ > Đây là mẫu `prototype-notes.md` **KHÔNG ĐẠT** — thiếu các thông tin quan trọng.
4
+ > Xem `good/prototype-notes.md` để biết format chuẩn.
5
+
6
+ ---
7
+
8
+ ## ❌ Ví dụ xấu
9
+
10
+ ```markdown
11
+ # Prototype Notes — Order Cancellation
12
+
13
+ Đã chạy prototype. State machine hoạt động ổn.
14
+
15
+ Verdict: VALIDATED
16
+
17
+ → Tiếp tục /v.plan
18
+ ```
19
+
20
+ ## Tại sao đây là thiếu thông tin
21
+
22
+ | Thiếu | Hậu quả |
23
+ |---|---|
24
+ | Không ghi **câu hỏi cụ thể** được trả lời | Plan Agent không biết prototype kiểm tra gì |
25
+ | Không ghi **REQ refs** | Không trace được finding về spec |
26
+ | Không ghi **run command** | Không ai có thể reproduce |
27
+ | Không ghi **kết quả interact** cụ thể | Verdict không có evidence — không đáng tin |
28
+ | Không ghi **spec impact** | BA Agent không biết cần sửa REQ nào |
29
+ | Không ghi **decisions to carry-forward** | Plan Agent mất context quan trọng |
30
+ | Không có **cleanup checklist** | flow-state.yaml có thể không được update |
31
+
32
+ ---
33
+
34
+ ## ❌ Ví dụ xấu thứ 2 — Verdict thiếu context
35
+
36
+ ```markdown
37
+ # Prototype Notes — Dashboard UI
38
+
39
+ Branch: UI
40
+ Variants thử: A (card grid), B (table), C (kanban)
41
+ Winner: B
42
+
43
+ Verdict: VALIDATED
44
+ ```
45
+
46
+ ## Tại sao đây cũng thiếu
47
+
48
+ | Thiếu | Hậu quả |
49
+ |---|---|
50
+ | Không ghi **lý do tại sao B thắng** | Next engineer không hiểu decision rationale |
51
+ | Không ghi **Sub-shape** đã dùng (A hay B) | Không biết prototype có real context không |
52
+ | Không ghi **spec impact** | Có cần update UI spec/wireframe không? |
53
+ | Không ghi **"tôi muốn header của B với sidebar của C"** type feedback | Mất design insight quan trọng |
54
+
55
+ ---
56
+
57
+ ## Checklist tự kiểm tra trước khi submit
58
+
59
+ ```
60
+ [ ] Có câu hỏi cụ thể (lấy từ spec REQ-xxx)
61
+ [ ] Có REQ refs (REQ-xxx, REQ-yyy)
62
+ [ ] Có run command cụ thể
63
+ [ ] Có mô tả kết quả interact (không chỉ "hoạt động ổn")
64
+ [ ] Có verdict rõ ràng: VALIDATED / REJECTED / INCONCLUSIVE
65
+ [ ] Có spec impact (no change | update REQ-xxx AC | new REQ needed)
66
+ [ ] Có decisions to carry-forward
67
+ [ ] Có cleanup checklist (_session, flow-state, prototype/ folder)
68
+ ```