@su-record/vibe 2.8.48 → 2.8.50

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 (414) hide show
  1. package/.env.example +37 -37
  2. package/CLAUDE.md +169 -169
  3. package/LICENSE +21 -21
  4. package/README.md +694 -554
  5. package/agents/architect-low.md +41 -41
  6. package/agents/architect-medium.md +59 -59
  7. package/agents/architect.md +80 -80
  8. package/agents/build-error-resolver.md +115 -115
  9. package/agents/compounder.md +261 -261
  10. package/agents/diagrammer.md +178 -178
  11. package/agents/docs/api-documenter.md +99 -99
  12. package/agents/docs/changelog-writer.md +93 -93
  13. package/agents/e2e-tester.md +294 -294
  14. package/agents/event/event-comms.md +78 -78
  15. package/agents/event/event-content.md +68 -68
  16. package/agents/event/event-image.md +95 -95
  17. package/agents/event/event-ops.md +84 -84
  18. package/agents/event/event-scheduler.md +69 -69
  19. package/agents/event/event-speaker.md +86 -86
  20. package/agents/explorer-low.md +42 -42
  21. package/agents/explorer-medium.md +59 -59
  22. package/agents/explorer.md +48 -48
  23. package/agents/implementer-low.md +43 -43
  24. package/agents/implementer-medium.md +52 -52
  25. package/agents/implementer.md +54 -54
  26. package/agents/junior-mentor.md +141 -141
  27. package/agents/planning/requirements-analyst.md +84 -84
  28. package/agents/planning/ux-advisor.md +83 -83
  29. package/agents/qa/acceptance-tester.md +86 -86
  30. package/agents/qa/edge-case-finder.md +93 -93
  31. package/agents/qa/qa-coordinator.md +131 -131
  32. package/agents/refactor-cleaner.md +143 -143
  33. package/agents/research/best-practices-agent.md +199 -199
  34. package/agents/research/codebase-patterns-agent.md +157 -157
  35. package/agents/research/framework-docs-agent.md +188 -188
  36. package/agents/research/security-advisory-agent.md +213 -213
  37. package/agents/review/architecture-reviewer.md +107 -107
  38. package/agents/review/complexity-reviewer.md +116 -116
  39. package/agents/review/data-integrity-reviewer.md +88 -88
  40. package/agents/review/git-history-reviewer.md +103 -103
  41. package/agents/review/performance-reviewer.md +86 -86
  42. package/agents/review/python-reviewer.md +150 -150
  43. package/agents/review/rails-reviewer.md +139 -139
  44. package/agents/review/react-reviewer.md +144 -144
  45. package/agents/review/security-reviewer.md +80 -80
  46. package/agents/review/simplicity-reviewer.md +140 -140
  47. package/agents/review/test-coverage-reviewer.md +116 -116
  48. package/agents/review/typescript-reviewer.md +127 -127
  49. package/agents/searcher.md +54 -54
  50. package/agents/simplifier.md +120 -120
  51. package/agents/tester.md +49 -49
  52. package/agents/ui/ui-a11y-auditor.md +93 -93
  53. package/agents/ui/ui-antipattern-detector.md +102 -102
  54. package/agents/ui/ui-dataviz-advisor.md +69 -69
  55. package/agents/ui/ui-design-system-gen.md +57 -57
  56. package/agents/ui/ui-industry-analyzer.md +49 -49
  57. package/agents/ui/ui-layout-architect.md +65 -65
  58. package/agents/ui/ui-stack-implementer.md +68 -68
  59. package/agents/ui/ux-compliance-reviewer.md +81 -81
  60. package/agents/ui-previewer.md +258 -258
  61. package/commands/vibe.analyze.md +379 -379
  62. package/commands/vibe.docs.md +32 -32
  63. package/commands/vibe.event.md +163 -163
  64. package/commands/vibe.figma.md +69 -69
  65. package/commands/vibe.review.md +686 -686
  66. package/commands/vibe.run.md +2276 -2276
  67. package/commands/vibe.spec.md +1195 -1195
  68. package/commands/vibe.spec.review.md +609 -609
  69. package/commands/vibe.trace.md +259 -259
  70. package/commands/vibe.utils.md +413 -413
  71. package/commands/vibe.verify.md +510 -510
  72. package/dist/cli/collaborator.js +52 -52
  73. package/dist/cli/commands/config.js +9 -9
  74. package/dist/cli/commands/evolution.js +12 -12
  75. package/dist/cli/commands/figma.js +20 -20
  76. package/dist/cli/commands/info.js +53 -53
  77. package/dist/cli/commands/init.js +5 -5
  78. package/dist/cli/commands/remove.js +14 -14
  79. package/dist/cli/commands/sentinel.js +27 -27
  80. package/dist/cli/commands/skills.js +5 -5
  81. package/dist/cli/commands/slack.js +10 -10
  82. package/dist/cli/commands/stats.js +6 -6
  83. package/dist/cli/commands/telegram.js +12 -12
  84. package/dist/cli/detect.js +32 -32
  85. package/dist/cli/index.js +53 -53
  86. package/dist/cli/llm/claude-commands.js +16 -16
  87. package/dist/cli/llm/config.js +18 -18
  88. package/dist/cli/llm/gemini-commands.js +16 -16
  89. package/dist/cli/llm/gpt-commands.js +19 -19
  90. package/dist/cli/llm/help.js +21 -21
  91. package/dist/cli/postinstall/cursor-agents.js +32 -32
  92. package/dist/cli/postinstall/cursor-rules.js +83 -83
  93. package/dist/cli/postinstall/cursor-skills.js +743 -743
  94. package/dist/cli/setup/Provisioner.js +42 -42
  95. package/dist/infra/lib/DeepInit.js +24 -24
  96. package/dist/infra/lib/IterationTracker.js +11 -11
  97. package/dist/infra/lib/PythonParser.js +108 -108
  98. package/dist/infra/lib/ReviewRace.js +96 -96
  99. package/dist/infra/lib/SkillFrontmatter.js +28 -28
  100. package/dist/infra/lib/SkillQualityGate.js +9 -9
  101. package/dist/infra/lib/SkillRepository.js +159 -159
  102. package/dist/infra/lib/UltraQA.js +99 -99
  103. package/dist/infra/lib/autonomy/AuditStore.js +41 -41
  104. package/dist/infra/lib/autonomy/ConfirmationStore.js +30 -30
  105. package/dist/infra/lib/autonomy/EventOutbox.js +38 -38
  106. package/dist/infra/lib/autonomy/PolicyEngine.d.ts +3 -3
  107. package/dist/infra/lib/autonomy/PolicyEngine.js +18 -18
  108. package/dist/infra/lib/autonomy/SecuritySentinel.js +1 -1
  109. package/dist/infra/lib/autonomy/SuggestionStore.js +33 -33
  110. package/dist/infra/lib/embedding/VectorStore.js +22 -22
  111. package/dist/infra/lib/evolution/AgentAnalyzer.js +10 -10
  112. package/dist/infra/lib/evolution/DescriptionOptimizer.js +21 -21
  113. package/dist/infra/lib/evolution/GenerationRegistry.js +36 -36
  114. package/dist/infra/lib/evolution/InsightStore.js +90 -90
  115. package/dist/infra/lib/evolution/ParityTester.js +57 -57
  116. package/dist/infra/lib/evolution/RollbackManager.js +5 -5
  117. package/dist/infra/lib/evolution/SkillBenchmark.js +23 -23
  118. package/dist/infra/lib/evolution/SkillEvalRunner.js +50 -50
  119. package/dist/infra/lib/evolution/SkillGapDetector.js +10 -10
  120. package/dist/infra/lib/evolution/UsageTracker.js +28 -28
  121. package/dist/infra/lib/gemini/orchestration.js +5 -5
  122. package/dist/infra/lib/gpt/orchestration.js +4 -4
  123. package/dist/infra/lib/memory/KnowledgeGraph.js +4 -4
  124. package/dist/infra/lib/memory/MemorySearch.js +57 -57
  125. package/dist/infra/lib/memory/MemoryStorage.js +181 -181
  126. package/dist/infra/lib/memory/ObservationStore.js +28 -28
  127. package/dist/infra/lib/memory/ReflectionStore.js +30 -30
  128. package/dist/infra/lib/memory/SessionRAGRetriever.js +7 -7
  129. package/dist/infra/lib/memory/SessionRAGStore.js +225 -225
  130. package/dist/infra/lib/memory/SessionSummarizer.js +9 -9
  131. package/dist/infra/orchestrator/AgentManager.js +12 -12
  132. package/dist/infra/orchestrator/AgentRegistry.js +65 -65
  133. package/dist/infra/orchestrator/MultiLlmResearch.js +8 -8
  134. package/dist/infra/orchestrator/SwarmOrchestrator.test.js +16 -16
  135. package/dist/infra/orchestrator/parallelResearch.js +24 -24
  136. package/dist/tools/convention/analyzeComplexity.test.js +115 -115
  137. package/dist/tools/convention/validateCodeQuality.test.js +104 -104
  138. package/dist/tools/memory/createMemoryTimeline.js +10 -10
  139. package/dist/tools/memory/getMemoryGraph.js +12 -12
  140. package/dist/tools/memory/getSessionContext.js +9 -9
  141. package/dist/tools/memory/linkMemories.js +14 -14
  142. package/dist/tools/memory/listMemories.js +4 -4
  143. package/dist/tools/memory/recallMemory.js +4 -4
  144. package/dist/tools/memory/saveMemory.js +4 -4
  145. package/dist/tools/memory/searchMemoriesAdvanced.js +23 -23
  146. package/dist/tools/semantic/analyzeDependencyGraph.js +12 -12
  147. package/dist/tools/semantic/astGrep.test.js +6 -6
  148. package/dist/tools/spec/prdParser.test.js +171 -171
  149. package/dist/tools/spec/specGenerator.js +169 -169
  150. package/dist/tools/spec/traceabilityMatrix.js +64 -64
  151. package/dist/tools/spec/traceabilityMatrix.test.js +28 -28
  152. package/hooks/gemini-hooks.json +73 -73
  153. package/hooks/hooks.json +170 -170
  154. package/hooks/scripts/__tests__/keyword-detector.test.js +199 -199
  155. package/hooks/scripts/__tests__/pre-tool-guard.test.js +286 -286
  156. package/hooks/scripts/__tests__/sentinel-guard.test.js +210 -210
  157. package/hooks/scripts/auto-commit.js +97 -65
  158. package/hooks/scripts/auto-format.js +64 -64
  159. package/hooks/scripts/auto-test.js +81 -81
  160. package/hooks/scripts/code-check.js +268 -216
  161. package/hooks/scripts/codex-detect.js +46 -46
  162. package/hooks/scripts/codex-review-gate.js +80 -80
  163. package/hooks/scripts/command-log.js +32 -32
  164. package/hooks/scripts/context-save.js +353 -353
  165. package/hooks/scripts/evolution-engine.js +91 -91
  166. package/hooks/scripts/figma-extract.js +477 -477
  167. package/hooks/scripts/hud-status.js +321 -321
  168. package/hooks/scripts/keyword-detector.js +214 -214
  169. package/hooks/scripts/llm-orchestrate.js +572 -555
  170. package/hooks/scripts/post-edit.js +32 -32
  171. package/hooks/scripts/pr-test-gate.js +52 -52
  172. package/hooks/scripts/pre-tool-guard.js +159 -159
  173. package/hooks/scripts/prompt-dispatcher.js +185 -185
  174. package/hooks/scripts/sentinel-guard.js +131 -131
  175. package/hooks/scripts/session-start.js +177 -106
  176. package/hooks/scripts/skill-injector.js +83 -83
  177. package/hooks/scripts/stop-notify.js +209 -209
  178. package/hooks/scripts/utils.js +243 -186
  179. package/languages/csharp-unity.md +515 -515
  180. package/languages/gdscript-godot.md +470 -470
  181. package/languages/ruby-rails.md +489 -489
  182. package/languages/typescript-angular.md +433 -433
  183. package/languages/typescript-astro.md +416 -416
  184. package/languages/typescript-electron.md +406 -406
  185. package/languages/typescript-nestjs.md +524 -524
  186. package/languages/typescript-svelte.md +407 -407
  187. package/languages/typescript-tauri.md +365 -365
  188. package/package.json +101 -100
  189. package/skills/agents-md/SKILL.md +121 -121
  190. package/skills/agents-md/rubrics/what-to-keep.md +49 -49
  191. package/skills/agents-md/templates/agents-md.md +36 -36
  192. package/skills/arch-guard/SKILL.md +181 -181
  193. package/skills/arch-guard/agents/detector.md +48 -48
  194. package/skills/arch-guard/agents/reporter.md +48 -48
  195. package/skills/arch-guard/agents/rule-generator.md +49 -49
  196. package/skills/arch-guard/agents/violation-checker.md +51 -51
  197. package/skills/arch-guard/frameworks/clean-architecture.md +108 -108
  198. package/skills/arch-guard/frameworks/solid.md +102 -102
  199. package/skills/arch-guard/scripts/check-boundaries.js +90 -90
  200. package/skills/arch-guard/templates/arch-rules.json +47 -47
  201. package/skills/arch-guard/templates/violation-report.md +53 -53
  202. package/skills/brand-assets/SKILL.md +147 -147
  203. package/skills/brand-assets/rubrics/asset-checklist.md +98 -98
  204. package/skills/brand-assets/templates/brand-guide.md +161 -161
  205. package/skills/capability-loop/SKILL.md +168 -168
  206. package/skills/capability-loop/agents/capability-designer.md +61 -61
  207. package/skills/capability-loop/agents/failure-analyst.md +55 -55
  208. package/skills/capability-loop/agents/implementer.md +50 -50
  209. package/skills/capability-loop/agents/tester.md +53 -53
  210. package/skills/capability-loop/templates/capability-spec.md +118 -118
  211. package/skills/capability-loop/templates/failure-analysis.md +118 -118
  212. package/skills/characterization-test/SKILL.md +207 -207
  213. package/skills/characterization-test/agents/behavior-capturer.md +50 -50
  214. package/skills/characterization-test/agents/coverage-checker.md +54 -54
  215. package/skills/characterization-test/agents/reporter.md +50 -50
  216. package/skills/characterization-test/agents/test-writer.md +49 -49
  217. package/skills/characterization-test/rubrics/coverage-criteria.md +53 -53
  218. package/skills/characterization-test/templates/test-template.ts +101 -101
  219. package/skills/chub-usage/SKILL.md +115 -115
  220. package/skills/claude-md-guide/SKILL.md +351 -351
  221. package/skills/claude-md-guide/rubrics/anti-patterns.md +88 -88
  222. package/skills/claude-md-guide/templates/claude-md.md +54 -54
  223. package/skills/commerce-patterns/SKILL.md +64 -64
  224. package/skills/commerce-patterns/rubrics/checkout-flow.md +48 -48
  225. package/skills/commerce-patterns/templates/product-schema.md +85 -85
  226. package/skills/commit-push-pr/SKILL.md +77 -77
  227. package/skills/commit-push-pr/agents/change-analyzer.md +55 -55
  228. package/skills/commit-push-pr/agents/message-writer.md +50 -50
  229. package/skills/commit-push-pr/agents/pr-writer.md +58 -58
  230. package/skills/commit-push-pr/agents/reviewer.md +52 -52
  231. package/skills/commit-push-pr/rubrics/commit-message.md +73 -73
  232. package/skills/commit-push-pr/templates/pr-body.md +63 -63
  233. package/skills/context7-usage/SKILL.md +106 -106
  234. package/skills/context7-usage/rubrics/when-to-use.md +50 -50
  235. package/skills/create-prd/SKILL.md +90 -90
  236. package/skills/create-prd/agents/edge-case-finder.md +48 -48
  237. package/skills/create-prd/agents/prioritizer.md +60 -60
  238. package/skills/create-prd/agents/requirements-writer.md +48 -48
  239. package/skills/create-prd/agents/researcher.md +55 -55
  240. package/skills/create-prd/agents/reviewer.md +54 -54
  241. package/skills/create-prd/frameworks/jobs-to-be-done.md +96 -96
  242. package/skills/create-prd/frameworks/rice-scoring.md +97 -97
  243. package/skills/create-prd/orchestrator.md +70 -70
  244. package/skills/create-prd/rubrics/completeness.md +58 -58
  245. package/skills/create-prd/templates/prd.md +139 -139
  246. package/skills/design-audit/SKILL.md +152 -152
  247. package/skills/design-audit/agents/a11y-auditor.md +43 -43
  248. package/skills/design-audit/agents/performance-auditor.md +46 -46
  249. package/skills/design-audit/agents/responsive-auditor.md +46 -46
  250. package/skills/design-audit/agents/scorer.md +47 -47
  251. package/skills/design-audit/agents/slop-detector.md +47 -47
  252. package/skills/design-audit/frameworks/core-web-vitals.md +107 -107
  253. package/skills/design-audit/frameworks/wcag-checklist.md +64 -64
  254. package/skills/design-audit/orchestrator.md +64 -64
  255. package/skills/design-audit/rubrics/ai-slop-patterns.md +83 -83
  256. package/skills/design-audit/rubrics/scoring.md +63 -63
  257. package/skills/design-audit/templates/report.md +88 -88
  258. package/skills/design-critique/SKILL.md +139 -139
  259. package/skills/design-critique/rubrics/ux-heuristics.md +143 -143
  260. package/skills/design-critique/templates/critique-report.md +86 -86
  261. package/skills/design-distill/SKILL.md +130 -130
  262. package/skills/design-distill/templates/design-system.md +132 -132
  263. package/skills/design-normalize/SKILL.md +133 -133
  264. package/skills/design-normalize/rubrics/token-naming.md +117 -117
  265. package/skills/design-normalize/templates/token-audit.md +89 -89
  266. package/skills/design-polish/SKILL.md +131 -131
  267. package/skills/design-polish/rubrics/polish-checklist.md +68 -68
  268. package/skills/design-polish/templates/polish-report.md +64 -64
  269. package/skills/design-teach/SKILL.md +182 -182
  270. package/skills/design-teach/rubrics/brand-personality.md +73 -73
  271. package/skills/design-teach/templates/design-context.json +36 -36
  272. package/skills/e2e-commerce/SKILL.md +62 -62
  273. package/skills/e2e-commerce/templates/test-scenarios.md +170 -170
  274. package/skills/event-comms/SKILL.md +162 -162
  275. package/skills/event-comms/templates/email-invite.md +99 -99
  276. package/skills/event-comms/templates/sns-post.md +133 -133
  277. package/skills/event-ops/SKILL.md +198 -198
  278. package/skills/event-ops/rubrics/contingency.md +85 -85
  279. package/skills/event-ops/templates/d-day-checklist.md +65 -65
  280. package/skills/event-planning/SKILL.md +132 -132
  281. package/skills/event-planning/rubrics/timeline.md +70 -70
  282. package/skills/event-planning/templates/event-plan.md +91 -91
  283. package/skills/exec-plan/SKILL.md +149 -149
  284. package/skills/exec-plan/agents/decomposer.md +47 -47
  285. package/skills/exec-plan/agents/dependency-mapper.md +44 -44
  286. package/skills/exec-plan/agents/estimator.md +43 -43
  287. package/skills/exec-plan/agents/validator.md +55 -55
  288. package/skills/exec-plan/orchestrator.md +70 -70
  289. package/skills/exec-plan/rubrics/complexity-scoring.md +75 -75
  290. package/skills/exec-plan/templates/plan.md +147 -147
  291. package/skills/git-worktree/SKILL.md +73 -73
  292. package/skills/git-worktree/rubrics/when-to-use.md +55 -55
  293. package/skills/handoff/SKILL.md +110 -110
  294. package/skills/handoff/agents/context-summarizer.md +51 -51
  295. package/skills/handoff/agents/document-writer.md +63 -63
  296. package/skills/handoff/agents/state-collector.md +53 -53
  297. package/skills/handoff/agents/verifier.md +48 -48
  298. package/skills/handoff/rubrics/completeness.md +62 -62
  299. package/skills/handoff/templates/handoff.md +107 -107
  300. package/skills/parallel-research/SKILL.md +89 -89
  301. package/skills/parallel-research/agents/best-practices.md +43 -43
  302. package/skills/parallel-research/agents/codebase-patterns.md +46 -46
  303. package/skills/parallel-research/agents/framework-docs.md +45 -45
  304. package/skills/parallel-research/agents/security-advisory.md +46 -46
  305. package/skills/parallel-research/agents/synthesizer.md +52 -52
  306. package/skills/parallel-research/experts/best-practices.md +50 -50
  307. package/skills/parallel-research/experts/codebase-patterns.md +70 -70
  308. package/skills/parallel-research/experts/framework-docs.md +65 -65
  309. package/skills/parallel-research/experts/security-advisory.md +69 -69
  310. package/skills/parallel-research/orchestrator.md +65 -65
  311. package/skills/parallel-research/templates/synthesis.md +101 -101
  312. package/skills/prioritization-frameworks/SKILL.md +87 -87
  313. package/skills/prioritization-frameworks/rubrics/frameworks.md +79 -79
  314. package/skills/prioritization-frameworks/templates/scoring-matrix.md +69 -69
  315. package/skills/priority-todos/SKILL.md +64 -64
  316. package/skills/priority-todos/rubrics/prioritization.md +70 -70
  317. package/skills/priority-todos/templates/todo-board.md +59 -59
  318. package/skills/seo-checklist/SKILL.md +58 -58
  319. package/skills/seo-checklist/frameworks/structured-data.md +153 -153
  320. package/skills/seo-checklist/rubrics/content-seo.md +42 -42
  321. package/skills/seo-checklist/rubrics/technical-seo.md +48 -48
  322. package/skills/techdebt/SKILL.md +124 -124
  323. package/skills/techdebt/agents/analyzer.md +50 -50
  324. package/skills/techdebt/agents/fixer.md +41 -41
  325. package/skills/techdebt/agents/reviewer.md +47 -47
  326. package/skills/techdebt/agents/scanner.md +44 -44
  327. package/skills/techdebt/orchestrator.md +70 -70
  328. package/skills/techdebt/rubrics/severity.md +51 -51
  329. package/skills/techdebt/scripts/scan.js +90 -90
  330. package/skills/techdebt/templates/report.md +86 -86
  331. package/skills/tool-fallback/SKILL.md +104 -104
  332. package/skills/tool-fallback/rubrics/fallback-chain.md +58 -58
  333. package/skills/typescript-advanced-types/SKILL.md +67 -67
  334. package/skills/typescript-advanced-types/rubrics/type-patterns.md +109 -109
  335. package/skills/ui-ux-pro-max/SKILL.md +236 -236
  336. package/skills/ui-ux-pro-max/reference/color-and-contrast.md +517 -517
  337. package/skills/ui-ux-pro-max/reference/interaction-design.md +544 -544
  338. package/skills/ui-ux-pro-max/reference/motion-design.md +591 -591
  339. package/skills/ui-ux-pro-max/reference/responsive-design.md +463 -463
  340. package/skills/ui-ux-pro-max/reference/spatial-design.md +390 -390
  341. package/skills/ui-ux-pro-max/reference/typography.md +455 -455
  342. package/skills/ui-ux-pro-max/reference/ux-writing.md +469 -469
  343. package/skills/ui-ux-pro-max/rubrics/interaction-states.md +83 -83
  344. package/skills/ui-ux-pro-max/rubrics/responsive-breakpoints.md +99 -99
  345. package/skills/user-personas/SKILL.md +75 -75
  346. package/skills/user-personas/rubrics/research-methods.md +56 -56
  347. package/skills/user-personas/templates/persona.md +89 -89
  348. package/skills/vercel-react-best-practices/SKILL.md +60 -60
  349. package/skills/vercel-react-best-practices/rubrics/performance.md +82 -82
  350. package/skills/vercel-react-best-practices/rubrics/server-components.md +86 -86
  351. package/skills/vibe.docs/SKILL.md +171 -171
  352. package/skills/vibe.docs/templates/architecture.md +80 -80
  353. package/skills/vibe.docs/templates/readme.md +84 -84
  354. package/skills/vibe.docs/templates/release-notes.md +74 -74
  355. package/skills/vibe.figma/SKILL.md +982 -1064
  356. package/skills/vibe.figma/rubrics/extraction-checklist.md +51 -51
  357. package/skills/vibe.figma/templates/component-index.md +126 -126
  358. package/skills/vibe.figma/templates/figma-handoff.md +100 -100
  359. package/skills/vibe.figma/templates/remapped-tree.md +277 -277
  360. package/skills/vibe.figma.convert/SKILL.md +511 -553
  361. package/skills/vibe.figma.convert/rubrics/conversion-rules.md +113 -129
  362. package/skills/vibe.figma.convert/templates/component.md +140 -140
  363. package/skills/vibe.figma.extract/SKILL.md +300 -312
  364. package/skills/vibe.figma.extract/rubrics/image-rules.md +137 -145
  365. package/skills/video-production/SKILL.md +52 -52
  366. package/skills/video-production/rubrics/quality-checklist.md +58 -58
  367. package/skills/video-production/templates/production-plan.md +104 -104
  368. package/vibe/config.json +29 -29
  369. package/vibe/constitution.md +227 -227
  370. package/vibe/rules/principles/communication-guide.md +98 -98
  371. package/vibe/rules/principles/development-philosophy.md +52 -52
  372. package/vibe/rules/principles/quick-start.md +102 -102
  373. package/vibe/rules/quality/bdd-contract-testing.md +393 -393
  374. package/vibe/rules/quality/checklist.md +276 -276
  375. package/vibe/rules/quality/performance.md +236 -236
  376. package/vibe/rules/quality/testing-strategy.md +440 -440
  377. package/vibe/rules/standards/anti-patterns.md +541 -541
  378. package/vibe/rules/standards/code-structure.md +291 -291
  379. package/vibe/rules/standards/complexity-metrics.md +313 -313
  380. package/vibe/rules/standards/git-workflow.md +237 -237
  381. package/vibe/rules/standards/naming-conventions.md +198 -198
  382. package/vibe/rules/standards/security.md +305 -305
  383. package/vibe/rules/writing/document-style.md +74 -74
  384. package/vibe/setup.sh +31 -31
  385. package/vibe/templates/constitution-template.md +252 -252
  386. package/vibe/templates/contract-backend-template.md +526 -526
  387. package/vibe/templates/contract-frontend-template.md +599 -599
  388. package/vibe/templates/feature-template.md +96 -96
  389. package/vibe/templates/spec-template.md +221 -221
  390. package/vibe/ui-ux-data/charts.csv +26 -26
  391. package/vibe/ui-ux-data/colors.csv +97 -97
  392. package/vibe/ui-ux-data/icons.csv +101 -101
  393. package/vibe/ui-ux-data/landing.csv +31 -31
  394. package/vibe/ui-ux-data/products.csv +96 -96
  395. package/vibe/ui-ux-data/react-performance.csv +45 -45
  396. package/vibe/ui-ux-data/stacks/astro.csv +54 -54
  397. package/vibe/ui-ux-data/stacks/flutter.csv +53 -53
  398. package/vibe/ui-ux-data/stacks/html-tailwind.csv +56 -56
  399. package/vibe/ui-ux-data/stacks/jetpack-compose.csv +53 -53
  400. package/vibe/ui-ux-data/stacks/nextjs.csv +53 -53
  401. package/vibe/ui-ux-data/stacks/nuxt-ui.csv +51 -51
  402. package/vibe/ui-ux-data/stacks/nuxtjs.csv +59 -59
  403. package/vibe/ui-ux-data/stacks/react-native.csv +52 -52
  404. package/vibe/ui-ux-data/stacks/react.csv +54 -54
  405. package/vibe/ui-ux-data/stacks/shadcn.csv +61 -61
  406. package/vibe/ui-ux-data/stacks/svelte.csv +54 -54
  407. package/vibe/ui-ux-data/stacks/swiftui.csv +51 -51
  408. package/vibe/ui-ux-data/stacks/vue.csv +50 -50
  409. package/vibe/ui-ux-data/styles.csv +68 -68
  410. package/vibe/ui-ux-data/typography.csv +57 -57
  411. package/vibe/ui-ux-data/ui-reasoning.csv +101 -101
  412. package/vibe/ui-ux-data/ux-guidelines.csv +99 -99
  413. package/vibe/ui-ux-data/version.json +31 -31
  414. package/vibe/ui-ux-data/web-interface.csv +31 -31
@@ -1,1064 +1,982 @@
1
- ---
2
- name: vibe.figma
3
- description: Figma design to code — 트리 기반 구조적 코드 생성
4
- triggers: []
5
- tier: standard
6
- ---
7
-
8
- # vibe.figma — Structural Code Generation
9
-
10
- ## 핵심 원칙
11
-
12
- ```
13
- Figma 트리가 코드의 원천이다. 스크린샷은 검증용이다.
14
-
15
- ✅ Figma Auto Layout → CSS Flexbox 1:1 기계적 매핑
16
- ✅ Figma CSS 속성 → SCSS 직접 변환 (추정 없음)
17
- ✅ Claude는 시맨틱 판단만: 태그 선택, 컴포넌트 분리, 인터랙션
18
- ✅ 스크린샷은 생성이 아닌 검증에만 사용
19
- ```
20
-
21
- ## 불변 규칙 (이 규칙을 위반하면 전체 결과물이 무효)
22
-
23
- ```
24
- 규칙들은 어떤 상황에서도 예외 없이 적용된다.
25
- "복잡해서", "시간이 없어서", "렌더링이 돼서" 등의 이유로 우회할 수 없다.
26
-
27
- 1. screenshot 명령으로 콘텐츠를 이미지화하는 것은 금지한다.
28
- screenshot 명령의 허용 범위:
29
- BG 프레임 렌더링 (TEXT 자식이 없는 순수 배경)
30
- 벡터 글자 GROUP 렌더링 (웹폰트 없는 장식 타이틀)
31
- 섹션별 스크린샷 sections/ 폴더 (Phase 6 검증용)
32
- screenshot 명령의 금지 범위:
33
- ❌ TEXT 자식이 있는 프레임 → HTML로 구현
34
- ❌ INSTANCE 반복 패턴이 있는 프레임 → HTML v-for로 구현
35
- 버튼/가격/수량이 있는 프레임 → HTML로 구현
36
- ❌ "섹션 콘텐츠"를 통째 렌더링 → HTML로 구현
37
-
38
- 위반 시 발생하는 문제:
39
- exchange-section1.webp (카드 4개를 이미지 1장으로) → 가격 수정 불가, 버튼 클릭 불가
40
- daily-step2-list.webp (보상 목록을 이미지로) → 수량 변경 불가, 접근성 불가
41
-
42
- 2. BG를 <img> 태그로 넣는 것은 금지한다.
43
- ❌ <img src="bg.webp"> 또는 <div class="bg"><img src="bg.webp"></div>
44
- .section { background-image: url('bg.webp'); background-size: cover; }
45
-
46
- 3. Phase 4 코드 생성 새로운 screenshot 호출은 금지한다.
47
- Phase 2에서 확보한 재료만 사용한다.
48
- "이 부분이 복잡하니 screenshot으로 이미지화하자"는 금지된 사고방식이다.
49
- 복잡한 UI도 tree.json의 구조를 따라 HTML+CSS로 구현한다.
50
- ```
51
-
52
- ## 금지 사항
53
-
54
- ```
55
- 스크린샷을 보고 CSS 추정 (범용 LLM의 약점)
56
- ❌ Figma 레이어를 무분별하게 div soup로 변환
57
- ❌ CSS로 이미지 재현 (gradient/shape으로 그림 그리기)
58
- 이미지 다운로드 없이 코드 생성 진행
59
- placeholder / 빈 src="" 남기기
60
- tree.json에 없는 CSS 값을 추정하여 작성
61
- 컴포넌트 파일 안에 <style> 블록 / 인라인 style=""
62
- tree.json의 CSS 속성을 SCSS에 직접 매핑
63
- 외부 SCSS 파일에만 스타일 작성
64
-
65
- ━━━ 이미지 vs HTML 판별 (가장 흔한 실수) ━━━
66
-
67
- BG를 <img> 태그로 처리 → 반드시 CSS background-image
68
- 잘못된 예: <img src="hero-bg.webp" class="bg-img" />
69
- 올바른 예: .section { background-image: url('hero-bg.webp'); background-size: cover; }
70
-
71
- 카드/아이템 그리드를 통째 이미지 1장으로 렌더링
72
- 잘못된 예: <img src="exchange-section1.webp" /> (카드 4개가 한 이미지)
73
- 올바른 예: v-for로 개별 카드 HTML 생성 + 내부 아이콘만 <img>
74
-
75
- TEXT 자식이 있는 프레임을 이미지로 렌더링
76
- 잘못된 예: <img src="daily-step2-list.webp" /> (텍스트+카드 포함)
77
- 올바른 예: HTML로 텍스트/레이아웃 구현 + 순수 이미지 에셋만 <img>
78
-
79
- ✅ 이미지로 렌더링 가능한 것: 벡터 글자, 합성 BG(텍스트 미포함), 래스터 에셋, 복잡 벡터
80
- ```
81
-
82
- ## 전체 플로우
83
-
84
- ```
85
- /vibe.figma
86
- 입력: 모든 URL을 한번에 받는다
87
- Storyboard: https://figma.com/...?node-id=aaa (있으면)
88
- MO Design: https://figma.com/...?node-id=xxx
89
- PC Design: https://figma.com/...?node-id=yyy (있으면)
90
-
91
- Phase 0: Setup (스택 감지, 디렉토리 생성, 기존 자산 인덱싱)
92
- → Phase 1: 디자인 리소스 (URL 입력 → 스토리보드 분석 → 기능 스펙 문서)
93
- Phase 2: 재료 확보 (모든 BP의 트리 + 노드 렌더링 이미지 + 스크린샷)
94
- Phase 3: 리매핑 (tree.json remapped.json, BP 간 노드 매칭 + CSS diff)
95
- Phase 4: 순차 코드 생성 (remapped.json 섹션별 HTML+SCSS)
96
- → Phase 5: 컴파일 게이트 (tsc → build → dev 확인)
97
- Phase 6: 시각 검증 루프 (렌더링 vs 스크린샷 비교 → 수정)
98
-
99
- 작업 디렉토리 구조:
100
- Figma URL의 ROOT name에서 폴더명 추출 (kebab-case):
101
- "MO_Main ..." → /tmp/{feature}/mo-main/
102
- "PC_Main ..." → /tmp/{feature}/pc-main/
103
-
104
- /tmp/{feature}/
105
- ├── mo-main/ ← 모바일 Phase 2 추출 결과
106
- ├── tree.json
107
- │ ├── bg/ ← BG 프레임 렌더링
108
- │ ├── content/ 콘텐츠 노드 렌더링
109
- │ └── sections/ ← Phase 4 검증용 스크린샷
110
- ├── pc-main/ ← 데스크탑 Phase 2 추출 결과
111
- │ └── (동일 구조)
112
- └── remapped.json ← Phase 3 리매핑 결과 (모든 BP 통합)
113
-
114
- remapped.json이 Phase 4의 유일한 입력.
115
- BP 노드 매칭 완료
116
- CSS diff (mo/pc) 포함
117
- → 이미지 렌더링 파일 경로 포함
118
- Phase 4에서 바로 코드 생성 가능
119
-
120
- 코드 출력: 프로젝트 디렉토리에 직접 배치
121
- components/{feature}/HeroSection.vue
122
- styles/{feature}/layout/_hero.scss (모바일 기본 + @media PC)
123
- styles/{feature}/components/_hero.scss
124
- ```
125
-
126
- ---
127
-
128
- ## Phase 0: Setup
129
-
130
- ```
131
- 1. 프로젝트 스택 감지:
132
- - package.json → react/vue/svelte
133
- - next.config.* / nuxt.config.* → 프레임워크
134
- - *.scss / sass in deps → SCSS
135
- - tailwind.config.* → Tailwind
136
-
137
- 2. 기존 스타일 디렉토리 감지:
138
- - assets/scss/ or src/styles/ or styles/
139
-
140
- 3. 피처명 결정:
141
- - Figma 파일명에서 추출 kebab-case
142
- - 예: "PUBG 겨울 PC방 이벤트" → winter-pcbang
143
-
144
- 4. 디렉토리 생성:
145
- - components/{feature}/
146
- - public/images/{feature}/ (또는 static/images/{feature}/)
147
- - styles/{feature}/ (layout/, components/ 하위)
148
-
149
- 5. 기존 컴포넌트 스캔 + 인덱싱:
150
- - Glob "components/**/*.vue" or "components/**/*.tsx"
151
- - 재사용 가능한 컴포넌트 목록 수집 (GNB, Footer, Button 등)
152
-
153
- 5-1. 컴포넌트 상세 인덱싱 (50개 이하 스캔):
154
- 대상 파일 수집 (우선순위 순서, 합산 50개 이내):
155
- barrel file index.ts components/ui/ components/common/ components/shared/ 나머지
156
- 각 디렉토리 내에서는 1-depth 파일만 (하위 재귀 탐색 안 함)
157
-
158
- 각 파일에 대해 2단계 추출:
159
- a. Grep: defineProps|interface Props|<slot|@description|class=|className=
160
- → 시작 줄 번호 탐색
161
- b. Read: 시작줄 ~ +30줄 추출
162
- Vue/Svelte template+script 분리 파일: 첫 300줄 전체 Read
163
- barrel file (index.ts): 전체 Read
164
-
165
- 추출 항목:
166
- - Props/Interface: defineProps<{...}> 또는 interface Props {...} 에서 prop 이름+타입
167
- 외부 타입 참조 시 (defineProps<ButtonProps>()) → types 인덱스에서 교차 참조
168
- - Slots: <slot> 또는 {children} 패턴
169
- - 스타일 클래스: class="..." 또는 className={styles.xxx} 최상위 요소의 클래스명
170
- - 용도 힌트: JSDoc @description 또는 파일 첫 번째 주석
171
-
172
- 5-2. 인덱스 결과 저장:
173
- 저장 경로: /tmp/{feature}/component-index.json
174
- [
175
- { name: "BaseButton",
176
- path: "components/common/BaseButton.vue",
177
- props: [{ name: "label", type: "string" }, { name: "variant", type: "'primary'|'secondary'" }],
178
- slots: ["default"],
179
- classes: ["btn", "btn--primary"],
180
- description: "공통 버튼 컴포넌트" },
181
- ...
182
- ]
183
-
184
- 컨텍스트 관리:
185
- - 컴포넌트 20개 이하: 전체 인덱스를 프롬프트에 포함
186
- - 컴포넌트 20개 초과: 이름+설명+축약 props(이름만, 타입 생략)만 포함
187
- 매칭 후보 발견 해당 파일 Read로 상세 확인
188
- - classes 필드는 요약에서 제외 (매칭 시 파일 Read로 확인)
189
-
190
- 5-3. Hooks/Types/Constants 인덱싱:
191
- 추가 스캔 대상:
192
- - Composables/Hooks: composables/**/*.ts, hooks/**/*.ts
193
- export 함수명 + 파라미터 + 반환 타입
194
- - 타입 정의: types/**/*.ts, types.ts
195
- → export interface/type 이름 + 최상위 필드
196
- - 상수: constants/**/*.ts
197
- → export const 이름 + 값 (또는 타입)
198
-
199
- 저장: /tmp/{feature}/context-index.json (component-index와 별도)
200
- 컨텍스트 관리:
201
- - 항목 30개 이하: 전체 인덱스를 프롬프트에 포함
202
- - 항목 30개 초과: 이름+핵심 시그니처만 요약, 상세 필요 시 파일 Read로 지연 조회
203
-
204
- 타임아웃: 파일당 Read 최대 300줄, 전체 인덱싱 2분 이내 완료
205
-
206
- 6. 기존 디자인 토큰 스캔:
207
-
208
- SCSS 토큰:
209
- Glob: **/_variables.scss, **/_tokens.scss, **/_colors.scss, **/variables.scss
210
- 패턴: $변수명: 값; 추출
211
- → 결과: { name: "$color-primary", value: "#3b82f6", source: "styles/_variables.scss" }
212
-
213
- CSS Variables:
214
- Glob: **/global.css, **/variables.css, **/root.css, **/app.css
215
- Grep: "--[a-zA-Z].*:" 패턴
216
- 결과: { name: "--color-primary", value: "#3b82f6", source: "styles/global.css" }
217
-
218
- Tailwind:
219
- tailwind.config.{js,ts,mjs} 존재 Read
220
- theme.colors, theme.extend.colors 에서 커스텀 색상 추출
221
- theme.spacing, theme.fontSize 에서 커스텀 추출
222
- → Tailwind v4: global CSS에서 @theme 디렉티브 내 CSS variable도 스캔
223
- 결과: { name: "blue-500", value: "#3b82f6", type: "tailwind", category: "color" }
224
-
225
- CSS-in-JS:
226
- Glob: **/theme.{ts,js}, **/tokens.{ts,js}, **/design-tokens.{ts,js}
227
- export 객체에서 color/spacing/typography 키 추출
228
-
229
- 통합 결과 → /tmp/{feature}/project-tokens.json:
230
- {
231
- colors: [{ name, value, source }],
232
- spacing: [{ name, value, source }],
233
- typography: [{ name, value, source }],
234
- other: [{ name, value, source }]
235
- }
236
-
237
- 토큰 소스 우선순위 (복수 시스템 공존 시):
238
- Tailwind > CSS Variables > SCSS > CSS-in-JS
239
-
240
- 성능: 100개 파일 기준 5초 이내 완료
241
- 파싱 실패 시: 해당 파일 스킵 + 경고 로그 (전체 중단하지 않음)
242
- ```
243
-
244
- ---
245
-
246
- ## Phase 1: 디자인 리소스
247
-
248
- 사용자에게 질문한다:
249
- - question: "스토리보드, 디자인 리소스를 줄바꿈으로 입력해주세요. (순서 무관)"
250
- - 예시:
251
- https://figma.com/design/xxx/...?node-id=20-4964
252
- https://figma.com/design/yyy/...?node-id=641-78147
253
- https://figma.com/design/yyy/...?node-id=641-78200
254
- 또는:
255
- docs/storyboard.pdf
256
- https://figma.com/design/yyy/...?node-id=641-78147
257
- - options 제공 금지 — 자유 텍스트 입력만 허용
258
- - 디자인 URL 최소 1개 필수
259
-
260
- ### 입력 분류 (자동)
261
-
262
- ```
263
- 줄을 파싱하여 분류:
264
-
265
- 1. figma.com URL Figma 리소스
266
- → ROOT name으로 스토리보드/MO/PC 판별
267
- fileKey가 다르면 스토리보드 vs 디자인 구분
268
- ROOT name에 "MO" → 모바일, "PC" → 데스크탑
269
-
270
- 2. .pdf 파일 경로 → PDF 스토리보드
271
- Read 도구로 페이지별 분석
272
-
273
- 3. .png/.jpg/.webp 파일 경로 이미지 스토리보드
274
- → Read 도구로 시각 분석
275
- ```
276
-
277
- ### 1-1. 스토리보드 분석
278
-
279
- ```
280
- 입력 타입에 따라 분기:
281
-
282
- ■ Figma URL인 경우:
283
- URL에서 fileKey, nodeId 추출
284
-
285
- 1단계 (BLOCKING): 루트 depth=2로 전체 프레임 + nodeId 수집
286
- # [FIGMA_SCRIPT] = ~/.vibe/hooks/scripts/figma-extract.js
287
- node "[FIGMA_SCRIPT]" tree {fileKey} {nodeId} --depth=2
288
-
289
- 모든 자식 프레임의 name + nodeId + size 테이블로 출력
290
- nodeId가 빠진 프레임이 있으면
291
-
292
- 2단계: name 패턴으로 프레임 분류
293
- SPEC — "기능 정의서", "정책" → depth 높여서 텍스트 추출
294
- CONFIG "해상도", "브라우저" → designWidth, minWidth, breakpoint 확보
295
- SHARED — "공통", "GNB", "Footer", "Popup" → 공통 컴포넌트 파악
296
- PAGE — "화면설계", "메인 -" → 섹션 목록 + 인터랙션 스펙
297
-
298
- 핵심 프레임 선별 (전부 읽지 않음):
299
- 1순위: SPEC (기능 정의서) — 1개
300
- 2순위: CONFIG (해상도) — 1개
301
- 3순위: PAGE 메인 섹션만 (3.1, 3.2, 3.3, 3.4, 3.5, 3.6)
302
- 하위 케이스(3.1.1, 3.2.1 등)는 건너뜀
303
- 4순위: SHARED (공통 요소, Popup) — 필요 시
304
-
305
- ■ PDF 파일인 경우:
306
- Read 도구로 페이지별 분석 (pages: "1-5" → "6-10" → ...)
307
- 페이지에서 추출:
308
- - 섹션 목록 + 기능 정의
309
- - 해상도/브레이크포인트 정보 (CONFIG)
310
- - 인터랙션 흐름
311
- - 상태 정의
312
- Figma 스토리보드와 동일한 기능 스펙 문서 생성
313
-
314
- ■ 이미지 파일인 경우:
315
- Read 도구로 시각 분석
316
- → 와이어프레임/목업에서 섹션 구조 + 기능 추출
317
-
318
- 스토리보드 없음:
319
- 디자인 URL의 tree.json에서 섹션 목록만 추출
320
- 기능 정의는 디자인 name/구조에서 추정 (정확도 낮음)
321
- ```
322
-
323
- ### 1-2. 기능 스펙 문서 작성 (파일 생성 없음)
324
-
325
- ```
326
- ❌ Phase 1에서 코드 파일을 생성하지 않는다.
327
- → Phase 1 HTML 구조와 Phase 4 트리 매핑이 충돌하면 이중 작업
328
- → Phase 4에서 remapped.json 기반으로 코드를 생성
329
-
330
- Phase 1의 출력물은 기능 스펙 문서 (텍스트):
331
-
332
- 1. 섹션 목록:
333
- | # | 섹션 이름 | Figma 프레임 name | 높이 | 설명 |
334
- |---|----------|------------------|------|------|
335
- | 1 | Hero | Hero | 1280px | 키비주얼 + 이벤트 정보 |
336
- | 2 | DailyCheckIn | Daily | 3604px | 출석 미션 |
337
- | 3 | PlayTime | Frame 633371 | 11363px | 플레이타임 미션 |
338
-
339
- 2. 각 섹션의 기능 정의:
340
- /**
341
- * 일일 출석 미션 섹션
342
- *
343
- * [기능 정의]
344
- * - 매일 출석스노우 토큰 즉시 지급
345
- * - 누적 3/5/7일 달성 시 추가 보상
346
- *
347
- * [인터랙션]
348
- * 출석하기 클릭 API호출 토큰지급 표시
349
- * 누적 보상 클릭 보상 수령
350
- *
351
- * [상태] default, checked, reward-claimed
352
- */
353
-
354
- 3. 공통 컴포넌트 목록:
355
- 프로젝트에 이미 있는 컴포넌트 (GNB, Footer 등)
356
- → 새로 만들 공통 컴포넌트
357
-
358
- 4. TypeScript 인터페이스 초안:
359
- interface RewardItem { id: string; name: string; tokenAmount: number; status: 'locked'|'available'|'claimed' }
360
- ```
361
-
362
- ### 1-3. 검증
363
-
364
- ```
365
- Phase 1 완료 조건:
366
- 모든 섹션이 목록에 포함되어 있다
367
- □ 각 섹션에 [기능 정의] + [인터랙션] + [상태] 가 정의되어 있다
368
- TypeScript 인터페이스 초안이 작성되어 있다
369
- 공통 컴포넌트가 식별되어 있다
370
- 파일을 하나도 생성하지 않았다
371
-
372
- Phase 4에서 스펙 + remapped.json을 합쳐서 코드를 생성한다.
373
- ```
374
-
375
- ---
376
-
377
- ## Phase 2: 재료 확보
378
-
379
- Phase 1 컴포넌트가 준비된 상태에서, 디자인 URL로 시각 재료를 수집한다.
380
-
381
- 사용자에게 질문한다:
382
- - question: "디자인 Figma URL을 입력해주세요. 여러 페이지는 줄바꿈으로 구분."
383
- - options 제공 금지 자유 텍스트 입력만 허용
384
-
385
- ### 멀티 프레임 URL 검증
386
-
387
- ```
388
- URL 유효성 검증:
389
- - 모든 URL에서 fileKey 추출 동일한 fileKey인지 확인
390
- - 서로 다른 fileKey 발견 에러: "멀티 프레임은 동일 Figma 파일 내 다른 프레임만 지원합니다"
391
- - node-id 파라미터 누락 시 해당 URL 에러 보고
392
- - 최대 5개 URL까지 지원
393
-
394
- URL 개수에 따른 처리:
395
- 1개: 기존 방식 (변경 없음, 아래 2-1 그대로)
396
- 2개 이상: 멀티 프레임 모드 활성화 (2-1-multi 참조)
397
- ```
398
-
399
- ### 2-1. 디자인 재료 추출 (단일 URL)
400
-
401
- ```
402
- URL에서 fileKey, nodeId 추출
403
-
404
- 1단계 — 전체 스크린샷 (정답 사진):
405
- node "[FIGMA_SCRIPT]" screenshot {fileKey} {nodeId} --out=/tmp/{feature}/full-screenshot.webp
406
-
407
- 2단계 — 전체 트리 + CSS (수치 재료):
408
- node "[FIGMA_SCRIPT]" tree {fileKey} {nodeId} --depth=10
409
- /tmp/{feature}/tree.json 에 저장
410
-
411
- 3단계 — 전체 이미지 다운로드 (시각 재료):
412
- node "[FIGMA_SCRIPT]" images {fileKey} {nodeId} --out=/tmp/{feature}/images/ --depth=10
413
- 모든 이미지 에셋 확보. 누락 0건, 0byte 0건.
414
-
415
- 3.5단계 — 개별 에셋 노드 렌더링 (추가 시각 재료):
416
- tree.json에서 이미지 에셋 후보를 식별:
417
- - 아이콘: VECTOR/GROUP 크기 ≤ 64px
418
- - 아이템 썸네일: name에 "item", "icon", "reward", "token", "coin", "badge"
419
- - 크기 50~300px 범위의 독립 요소
420
- - fill 이미지가 없지만 시각적으로 의미 있는 노드
421
-
422
- 렌더링 TEXT 자식 검증 (BLOCKING):
423
- 후보 노드의 자식 트리에 TEXT 노드가 있으면 → 렌더링 대상에서 제외
424
- 후보 노드가 INSTANCE 반복 패턴의 부모이면 → 렌더링 대상에서 제외
425
- "카드", "리스트", "그리드" 등 복합 UI를 통째 렌더링하지 않는다
426
-
427
- 해당 노드를 개별 렌더링:
428
- node "[FIGMA_SCRIPT]" images {fileKey} {nodeId} --render --nodeIds={id1},{id2},... --out=/tmp/{feature}/images/
429
- 이미지 fill이 아닌 벡터/인스턴스 에셋도 webp로 확보
430
- Phase 4에서 카드 내부의 아이콘/썸네일로 사용
431
-
432
- 4단계 — 섹션별 스크린샷 (부분 정답):
433
- 트리의 1depth 자식 프레임 각각:
434
- node "[FIGMA_SCRIPT]" screenshot {fileKey} {child.nodeId} --out=/tmp/{feature}/sections/{child.name}.webp
435
- ```
436
-
437
- ### 2-1-multi. 멀티 프레임 재료 확보 (2개 이상 URL)
438
-
439
- ```
440
- URL에 대해 순차 추출 (Figma API rate limit: 요청 간 500ms 간격):
441
- URL 1 → /tmp/{feature}/frame-1/ (full-screenshot, tree, images, sections)
442
- URL 2 → /tmp/{feature}/frame-2/ (URL 1 완료 후 500ms 대기)
443
- URL 3 /tmp/{feature}/frame-3/ (URL 2 완료 후 500ms 대기)
444
- ※ 추출 완료 후 후처리(섹션 분할 등)는 병렬 가능
445
-
446
- 부분 실패 처리:
447
- - 개별 URL 추출 실패 해당 frame만 건너뛰고 나머지 진행
448
- - 실패한 frame은 사용자에게 즉시 보고: "frame-{N} 추출 실패: {에러 사유}" (API 에러, 권한 부족, 잘못된 nodeId 등)
449
- - 성공한 frame ≥ 2: Phase 3 계속 진행
450
- - 정확히 1개만 성공: 단일 프레임 모드로 폴백 (Phase 3 스킵)
451
- - 0개 성공: 전체 실패 보고
452
-
453
- 결과:
454
- /tmp/{feature}/
455
- ├── frame-1/ ← 메인 페이지
456
- │ ├── full-screenshot.webp
457
- │ ├── tree.json
458
- │ ├── images/
459
- │ └── sections/
460
- ├── frame-2/ ← 서브 페이지 1
461
- │ └── ...
462
- ├── frame-3/ ← 서브 페이지 2
463
- │ └── ...
464
- └── sections/ ← Phase 6 검증용 스크린샷
465
- ```
466
-
467
- ### 2-2. 추출 데이터 정리
468
-
469
- ```
470
- Phase 2 완료 /tmp/{feature}/ 다음이 준비되어야 함:
471
-
472
- 단일 URL:
473
- /tmp/{feature}/
474
- ├── full-screenshot.webp 전체 정답 사진
475
- ├── tree.json ← 노드 트리 + CSS 수치
476
- ├── images/ 모든 이미지 에셋
477
- │ ├── hero-bg.webp
478
- │ ├── hero-title.webp
479
- │ ├── card-item-1.webp
480
- └── ...
481
- └── sections/ ← 섹션별 정답 사진
482
- ├── hero.webp
483
- ├── daily-checkin.webp
484
- ├── playtime-mission.webp
485
- └── ...
486
-
487
- 멀티 URL: 위 2-1-multi 결과 구조 참조
488
-
489
- 재료 목록 (material-inventory):
490
- - 이미지: 파일명 + 크기 + 용도 추정 (BG/icon/title/decoration)
491
- - 색상: tree.json에서 추출한 모든 고유 색상값
492
- - 폰트: 사용된 font-family, size, weight 목록
493
- - 텍스트: 모든 TEXT 노드의 characters
494
- - 간격: padding, gap, margin 사용 빈도 높은 값
495
- ```
496
-
497
- ### 반응형 단위 (scaleFactor 사용하지 않음)
498
-
499
- ```
500
- 스토리보드 CONFIG에서 확보:
501
- designWidth: 디자인 너비 (예: 모바일 720px, PC 2560px)
502
- minWidth: 최소 지원 너비 (예: 340px)
503
- breakpoint: PC/모바일 분계 (예: 1025px)
504
-
505
- UI 요소 → vw 비례:
506
- vw값 = (Figma px / designWidth) × 100
507
- 예: gap: 24px → 24/720 × 100 = 3.33vw
508
- 예: width: 620px 620/720 = 86.11% (부모 대비)
509
-
510
- 폰트 clamp(최소, vw, 최대):
511
- 최소값 = 역할별 가독성 기준 (h1:16px, 본문:12px, 캡션:10px)
512
- vw값 = (Figma px / designWidth) × 100
513
- 최대값 = Figma 원본 px
514
- 예: 24px 본문 → clamp(12px, 3.33vw, 24px)
515
-
516
- 변환 안 함: color, opacity, font-weight, z-index, line-height(단위 없을 때)
517
- ```
518
-
519
- ---
520
-
521
- ## Phase 3: 리매핑 (tree.json → remapped.json)
522
-
523
- **URL 2개 이상일 때만 실행. 단일 URL이면 Phase 3으로 건너뜀.**
524
- **프레임 공통 요소를 식별하여 공유 컴포넌트로 추출한다.**
525
-
526
- ```
527
- 1. 시각 비교 — 각 프레임의 스크린샷을 순차 Read:
528
- - frame-1/full-screenshot.webp → frame-2/full-screenshot.webp → ...
529
- - 시각적으로 반복되는 요소 식별:
530
- 상단 영역 (GNB/Header), 하단 영역 (Footer),
531
- 카드 패턴, 버튼 스타일, 섹션 레이아웃
532
-
533
- 2. 구조 비교 각 tree.json의 1depth 자식 비교:
534
- - 동일한 name 또는 prefix 일치 (예: "GNB", "Header", "Footer", "Nav")
535
- - 동일한 size (width와 height 모두 ±10% 이내): 같은 컴포넌트 후보
536
- - 동일한 CSS 패턴: 같은 스타일 사용 (색상, 폰트, 레이아웃)
537
-
538
- 3. 공통 컴포넌트 후보 목록:
539
- shared-components:
540
- - name: GNB
541
- frames: [frame-1, frame-2, frame-3]
542
- consistency: 100% (모든 프레임에서 동일)
543
- action: 공유 컴포넌트로 1회만 생성
544
- - name: Footer
545
- frames: [frame-1, frame-3]
546
- consistency: 67% (2/3 프레임)
547
- action: 공유 컴포넌트 + frame-2는 다른 Footer
548
- - name: CardItem
549
- frames: [frame-1, frame-2]
550
- size-match: 95%
551
- action: 공유 컴포넌트 (props변형)
552
-
553
- 4. 공통 토큰 추출:
554
- - 모든 프레임의 색상 팔레트 합집합 공유 _tokens.scss
555
- - 모든 프레임의 폰트 목록 합집합
556
- - 모든 프레임의 간격 패턴 합집합
557
- 프레임별 고유 값만 프레임 로컬 토큰으로 분리
558
- ```
559
-
560
- ---
561
-
562
- ## Phase 4: 순차 코드 생성
563
-
564
- **remapped.json 기반으로 섹션별 순차 코드 생성.**
565
- **한 섹션 완료 → 브라우저 확인 → 다음 섹션. 병렬 금지.**
566
-
567
- **멀티 프레임 모드 조립 순서 변경:**
568
- ```
569
- 멀티 프레임 Phase 3 순서:
570
-
571
- 1단계: 공유 컴포넌트 먼저 생성
572
- - shared-components 목록의 컴포넌트를 components/shared/에 생성
573
- - 가장 일관적인 프레임(shared-components 매칭 수가 가장 많은 프레임) 기준으로 조립
574
- - 프레임별 변형은 props로 처리
575
-
576
- 2단계: 프레임별 고유 섹션 조립
577
- - frame-1 고유 섹션: 공유 컴포넌트 import + 고유 섹션 신규 생성
578
- - frame-2 고유 섹션: 동일
579
- - 프레임의 페이지 파일에서 공유 + 고유 컴포넌트 배치
580
-
581
- 3단계: 스타일 구조
582
- styles/{feature}/
583
- ├── _tokens.scss ← 공유 토큰 (합집합)
584
- ├── shared/ ← 공유 컴포넌트 스타일
585
- │ ├── layout/_gnb.scss
586
- │ └── components/_gnb.scss
587
- ├── frame-1/ ← 메인 고유 스타일
588
- │ ├── layout/
589
- │ └── components/
590
- └── frame-2/
591
-
592
- 단일 URL: 기존 방식 그대로 ( 멀티 프레임 순서 무시)
593
- ```
594
-
595
- ### 3-0. SCSS Setup + 등록 (첫 섹션 전)
596
-
597
- ```
598
- Phase 1에서 생성한 빈 SCSS 파일에 기본 내용 Write:
599
- styles/{feature}/index.scss ← @import 진입점
600
- styles/{feature}/_tokens.scss ← tree.json에서 추출한 디자인 토큰
601
- styles/{feature}/_mixins.scss ← breakpoint mixin
602
- styles/{feature}/_base.scss ← 루트 클래스
603
-
604
- 토큰 매핑 (기존 토큰 우선 사용):
605
- 1. /tmp/{feature}/project-tokens.json Read로 로드
606
- 2. Figma tree.json의 값에 대해 project-tokens에서 동일 값 검색:
607
- - 색상: hex 정규화 완전 일치 (Figma RGBA 0-1 → hex, 3자리→6자리, 대소문자 무시)
608
- ※ alpha < 1: 8자리 hex (#RRGGBBAA) 또는 rgba() 함수로 변환
609
- - 간격: px 완전 일치 (rem→px: 1rem=16px)
610
- - 폰트: family 이름 포함 매칭
611
- 3. 매칭됨 기존 토큰 참조:
612
- - SCSS: @use 'path' 로 기존 파일 import, $변수명 사용
613
- - Tailwind: 해당 유틸리티 클래스 사용 (bg-blue-500)
614
- - CSS Variables: var(--color-primary) 사용
615
- 4. 매칭 안 됨 → 새 토큰 생성 (기존 방식)
616
-
617
- _tokens.scss 구조:
618
- // ─── 기존 토큰 참조 ────────────────────
619
- @use '../../styles/variables' as v;
620
-
621
- // ─── 매핑 (기존 토큰피처 시맨틱) ────
622
- $color-bg-primary: v.$color-navy; // 기존 재사용
623
- $color-text-primary: v.$color-white; // 기존 재사용
624
-
625
- // ─── 새 토큰 (매칭 안 된 값만) ─────────
626
- $color-accent-gold: #ffd700; //
627
- $space-section-gap: 42px; //
628
-
629
- 매핑 결과 보고: "토큰 매핑: 12/18 매칭 (67%), 6개 새 토큰 생성"
630
-
631
- 기존 토큰 파일 수정 금지 — 참조만 함
632
- 같은 값의 토큰 중복 생성 금지
633
- 토큰은 피처 스코프 네이밍 ($feature-color-xxx)
634
-
635
- project-tokens.json 없는 경우 (기존 토큰 없음):
636
- 기존 방식으로 전체 생성:
637
- - 색상primitive ($color-navy: #0a1628) + semantic ($color-bg-primary)
638
- - 폰트 $font-pretendard, $font-size-md: 16px
639
- - 간격 → $space-sm: 8px, $space-md: 16px
640
-
641
- 스타일 등록 (BLOCKING):
642
- Grep "{feature}/index.scss" 이미 등록되어 있으면 건너뜀.
643
- 없으면 프로젝트 방식에 맞게 등록.
644
- ```
645
-
646
- ### 3-0.5. 컴포넌트 매칭 ( 섹션 조립 전)
647
-
648
- ```
649
- /tmp/{feature}/component-index.json Read로 로드한다.
650
-
651
- 섹션 스크린샷 분석 후, 기존 컴포넌트 매칭:
652
-
653
- 1. 스크린샷에서 식별된 UI 요소를 component-index와 대조
654
- 2. 매칭 판정 기준:
655
- - 필수: name/role 유사성 (시각적 역할 일치)
656
- 버튼 → BaseButton, 네비게이션 → GNB, 카드 → Card, 모달 → Modal
657
- - 보조: props 호환성 (필요 props가 기존 컴포넌트에 존재)
658
- - 보조: slots 호환성 (필요 slot이 존재)
659
- - 불일치: props/slots 50% 미만 호환이면 매칭 거부 새로 생성
660
- 3. 매칭된 컴포넌트: import하여 props 전달 (내부 수정 금지)
661
- 4. 매칭 됨: 새로 생성 (강제 재사용 금지)
662
-
663
- 재사용 스타일 충돌 방지:
664
- 기존 컴포넌트 import하여 사용
665
- props로 variant/size 커스터마이즈
666
- 래퍼 클래스로 position/size만 오버라이드
667
- 기존 컴포넌트 내부 스타일 수정 금지
668
- 90% 유사한데 새로 만들기 금지
669
- ```
670
-
671
- ### 3-1. 순차 블록 빌딩 (병렬 금지)
672
-
673
- ```
674
- 여러 섹션을 동시에 생성하지 않는다
675
- 병렬 생성 시 컨텍스트 분산 매핑 정확도 저하 → 품질 하락
676
- 섹션 결과를 확인하지 않으면 실수가 누적됨
677
-
678
- 섹션씩 순차적으로 블록을 쌓듯 만든다:
679
-
680
- 작업 폴더: ROOT name에서 추출 (Phase 2에서 결정)
681
- "MO_Main ..." /tmp/{feature}/mo-main/
682
- 코드 출력도 폴더 안에:
683
- /tmp/{feature}/mo-main/components/{feature}/
684
- /tmp/{feature}/mo-main/styles/{feature}/
685
- Phase 5에서 최종 프로젝트 디렉토리에 배치
686
-
687
- 섹션 1 (Hero):
688
- 1. tree.json에서 Hero 노드 Read
689
- 2. 코드 생성 (컴포넌트 + SCSS)
690
- 3. 브라우저에서 확인 (dev 서버)
691
- 4. OK 다음 섹션으로
692
- NG 수정 재확인
693
-
694
- 섹션 2 (KID):
695
- 1. tree.json에서 KID 노드 Read
696
- 2. 코드 생성
697
- 3. 브라우저에서 확인 (이전 섹션도 함께)
698
- 4. OK → 다음 섹션으로
699
-
700
- 섹션 3 (Daily) → ... 반복
701
-
702
- Phase 4에서 screenshot/render 호출 금지:
703
- Phase 2에서 확보한 이미지만 사용한다.
704
- "이 섹션이 복잡하니 screenshot으로 이미지화하자" 금지된 접근.
705
- 복잡한 섹션도 tree.json 구조를 따라 HTML+CSS로 구현한다.
706
- 섹션 내부에 카드 그리드/보상 목록이 있으면:
707
- → 카드 내부의 아이콘/썸네일(Phase 2에서 확보)만 <img>
708
- 가격, 수량, 버튼 텍스트, 제목은 모두 HTML
709
-
710
- 섹션 완료 시:
711
- - 해당 섹션의 컴포넌트 + SCSS가 동작하는 상태
712
- - pages/{feature}.vue에 해당 섹션이 추가된 상태
713
- - 브라우저에서 이전 섹션 + 현재 섹션이 모두 보이는 상태
714
- ```
715
-
716
- ### 3-2. 트리 기반 구조적 코드 생성
717
-
718
- ```
719
- 각 섹션에 대해 (vibe.figma.convert 참조):
720
-
721
- 1. 트리 구조 읽기 — tree.json에서 해당 섹션 노드를 Read
722
- → Auto Layout 속성(flex, gap, padding)이 코드의 기반
723
- → 스크린샷은 검증용으로만 참조
724
-
725
- 2. ⛔ 이미지 vs HTML 판별 (BLOCKING — 코드 작성 전 반드시 실행):
726
- 섹션의 모든 노드를 순회하여 각 노드가 이미지인지 HTML인지 판별한다.
727
- 판별하지 않고 코드를 작성하면 된다.
728
-
729
- 판별 결과 테이블을 먼저 작성한 후 코드 생성:
730
- | 노드 name | 타입 | 판별 | 근거 |
731
- |-----------|------|------|------|
732
- | BG | FRAME | CSS background-image | BG 프레임 |
733
- | Title | TEXT 포함 FRAME | HTML | TEXT 자식 보유 |
734
- | CardGrid | INSTANCE ×4 | HTML v-for | 반복 패턴 |
735
- | CoinIcon | RECTANGLE+imageRef | <img> | 순수 에셋 |
736
-
737
- 판별 규칙 (하나라도 YES HTML):
738
- Q1. TEXT 자식 있는가? YES HTML (텍스트를 이미지에 넣지 않는다)
739
- Q2. INSTANCE 반복 패턴인가? YES HTML v-for (내부 이미지 에셋만 <img>)
740
- Q3. 인터랙티브 요소인가? (btn, CTA) → YES → HTML <button>
741
- Q4. 동적 데이터인가? (가격, 수량, 기간) → YES → HTML 텍스트
742
- 모두 NO 이미지 렌더링 가능
743
-
744
- ⚠️ 특히 주의: 섹션을 통째로 이미지 렌더링하는 것은 절대 금지.
745
- 섹션 안의 개별 요소를 판별하여 이미지/HTML을 분리해야 한다.
746
-
747
- 3. 기계적 매핑 (추정 없음):
748
- a. 이미지: 판별에서 "이미지"로 확정된 노드만 static/images/{feature}/에 배치
749
- b. BG 프레임 처리:
750
- <img src="bg.webp"> 또는 <div><img src="bg.webp" class="bg"></div> 금지
751
- ✅ 부모에 CSS background-image만 사용:
752
- .section { background-image: url('/images/{feature}/bg.webp'); background-size: cover; }
753
- BG 프레임은 HTML에 아무 요소도 렌더링하지 않음
754
- c. 노드 HTML 매핑:
755
- - Auto Layout 있음 → <div> + flex (direction/gap/padding 직접)
756
- - Auto Layout 없음 → <div> + position:relative (자식 absolute)
757
- - TEXT 노드 → <span> (Claude가 h2/p/button으로 승격)
758
- - 순수 이미지 에셋 → <img src="렌더링된 파일">
759
- - 반복 패턴 (동일 구조 2+) → v-for (카드 내 이미지만 <img>, 나머지 HTML)
760
- d. CSS 직접 매핑:
761
- - node.css의 모든 속성을 SCSS에 1:1 매핑
762
- - vw/clamp 반응형 단위 변환 (vibe.figma.convert 참조)
763
- - tree.json에 없는 CSS 값은 작성하지 않음
764
- d. Phase 1의 JSDoc, 인터페이스, 핸들러 삽입
765
-
766
- 3. Claude 시맨틱 보강:
767
- - div → section/h2/p/button 태그 승격
768
- - 컴포넌트 분리 + props 설계
769
- - 접근성 (alt, aria)
770
- - 인터랙션 (클릭, 상태)
771
-
772
- 4. 브라우저 확인 (섹션별 게이트):
773
- - dev 서버에서 현재까지 만든 섹션이 모두 보이는지 확인
774
- - 이미지 로드, 레이아웃, 텍스트 확인
775
- - OK 다음 섹션 진행
776
- - NG 수정 재확인 (다음 섹션으로 넘어가지 않음)
777
- ```
778
-
779
- ### 3-3. 코드 작성 규칙
780
-
781
- ```
782
- 컴포넌트 (Vue 예시):
783
- <template>
784
- tree.json의 Auto Layout 구조를 HTML flex 레이아웃으로 직접 매핑.
785
- Claude가 시맨틱 태그로 승격 (div → section/h2/p/button).
786
- Phase 1의 기능 요소(v-for, @click, v-if) 보존.
787
- 이미지 경로: /images/{feature}/파일명.webp (실제 파일 존재 확인)
788
- 텍스트: tree.json의 TEXT 노드 characters 값 그대로.
789
-
790
- <script setup>
791
- Phase 1의 JSDoc + 인터페이스 + 핸들러 보존.
792
- 새로운 데이터/상태 추가 기존과 병합.
793
-
794
- <style> 블록 없음 — 외부 SCSS만.
795
-
796
- SCSS (vibe.figma.convert 참조):
797
- layout/ → position, display, flex, width, height, padding, gap
798
- components/ font, color, border, shadow, opacity
799
- 모든 수치는 tree.json의 정확한 vw/clamp 변환 (vibe.figma.convert 참조).
800
- 추정 금지 값이 없으면 tree.json에서 다시 찾는다.
801
- ```
802
-
803
- ### 반응형 (추가 URL)
804
-
805
- ```
806
- 완료 질문: "다음 브레이크포인트 디자인 URL을 입력해주세요. (없으면 '없음')"
807
-
808
- URL 있으면:
809
- 1. URL에서 재료 확보 (Phase 1 반복)
810
- 2. 스크린샷과 기존 코드 비교
811
- 3. @media (min-width: $bp-desktop) 오버라이드만 추가
812
- 4. 기존 모바일 코드 삭제 금지
813
- ```
814
-
815
- ---
816
-
817
- ## Phase 5: 컴파일 게이트
818
-
819
- **Phase 3 코드 생성 완료 후, 브라우저 검증 전에 컴파일 성공을 보장한다.**
820
- **컴파일 에러는 스킵 불가 반드시 수정 또는 사용자 보고.**
821
- **Phase 5 실패 Phase 4 진행 불가 (hard gate).**
822
-
823
- ```
824
- 자동 반복: 컴파일 성공까지. 최대 3라운드.
825
- ```
826
-
827
- ### 3.5-0. 베이스라인 캡처 (Phase 3 변경 전)
828
-
829
- ```
830
- Phase 3 시작 전에 기존 프로젝트의 에러를 캡처:
831
- 1. 타입 체크 베이스라인: (3.5-1에서 선택한 동일 명령 사용) > /tmp/{feature}/baseline-typecheck.txt 2>&1
832
- 2. 빌드 베이스라인: npm run build > /tmp/{feature}/baseline-build.txt 2>&1
833
-
834
- Phase 5에서는 baseline에 없는 **새로 발생한 에러만** 수정 대상.
835
- baseline에 존재하던 에러는 무시하고 별도 보고 ("기존 에러 {N}개 유지").
836
- vibe.figma가 생성/수정한 파일 외의 에러는 자동 수정 금지.
837
- ```
838
-
839
- ### 3.5-1. TypeScript 컴파일 체크
840
-
841
- ```
842
- 1. 프로젝트 타입 체커 감지 → 실행:
843
- - package.json scripts에 type-check 또는 typecheck 존재 → npm run type-check 사용
844
- - vue-tsc 설치 확인 (Vue 프로젝트) → npx vue-tsc --noEmit 2>&1
845
- - svelte-check 설치 확인 (Svelte 프로젝트) → npx svelte-check 2>&1
846
- - 위 해당 없음 → fallback: npx tsc --noEmit 2>&1
847
- 에러 0개: PASS 다음 단계
848
- 에러 있음: 에러 메시지 파싱 → 자동 수정
849
-
850
- 2. 에러 파싱:
851
- 각 에러에서 추출: 파일 경로, 줄 번호, 에러 코드, 메시지
852
- 예: "src/components/Hero.tsx(15,3): error TS2322: Type 'string' is not assignable to type 'number'"
853
-
854
- 3. 자동 수정 (에러 유형별):
855
- - TS2322 (타입 불일치): prop 타입을 올바르게 수정
856
- - TS2304 (이름 없음): import 추가
857
- - TS2339 (프로퍼티 없음): interface에 프로퍼티 추가
858
- - TS7006 (암시적 any): 타입 어노테이션 추가
859
- - 기타: Read로 해당 파일+줄 확인 컨텍스트 기반 수정
860
- ```
861
-
862
- ### 3.5-2. 빌드 체크
863
-
864
- ```
865
- 1. npm run build 실행:
866
- Bash: npm run build 2>&1
867
- 성공: PASS → 다음 단계
868
- → 실패: 에러 메시지 파싱 → 자동 수정
869
- → 타임아웃: 최대 120초 (초과 시 해당 라운드 실패 처리)
870
-
871
- 2. 일반적 빌드 에러 처리:
872
- - SCSS 컴파일 에러: 변수명/import 오류 수정
873
- - Module not found: import 경로 수정 (.js 확장자 등)
874
- - ESLint 에러 (--max-warnings 초과): 자동 수정 가능한 것 처리
875
- ```
876
-
877
- ### 3.5-3. dev 서버 시작 확인
878
-
879
- ```
880
- 1. dev 서버 시작 + PID 캡처:
881
- Bash: npm run dev & echo $! → DEV_PID 저장
882
- → localhost 포트 자동 감지: npm run dev stdout에서 localhost:\d+ 또는 port \d+ 파싱
883
- 감지 실패 기본값 3000, 5173, 4173 순서 시도
884
- 포트 폴링 (3초 간격, 최대 30초 대기)
885
- 성공: Phase 4 진행 (Phase 4 완료 후 정리)
886
- 실패: kill $DEV_PID → 에러 로그 확인 → 수정 → 재시도
887
-
888
- 2. 프로세스 정리 규칙:
889
- - Phase 4 완료 또는 3라운드 실패 시 반드시 정리
890
- - 정리 순서: kill $DEV_PID → 3 대기 kill -9 $DEV_PID (응답 없으면)
891
- - lsof -i :{port} -t 포트 점유 프로세스 확인 후 추가 정리
892
- spawned child process만 대상 관련 없는 프로세스 kill 금지
893
- - interrupt 시에도 cleanup 보장
894
- ```
895
-
896
- ### 3.5-4. 수정 루프
897
-
898
- ```
899
- 라운드 1~3:
900
- 1. tsc build → dev 순서로 체크
901
- 2. 번째 실패 단계의 에러 수정
902
- 3. 수정 해당 단계부터 재체크
903
- 4. 모든 단계 통과: Phase 4 진행
904
-
905
- 라운드 종료 조건:
906
- - 3라운드 후 실패: 에러 목록 + 시도한 수정을 사용자에게 보고
907
- - 같은 에러 반복: 해당 에러 스킵 불가 → 사용자 보고 (컴파일 에러는 스킵 불가)
908
-
909
- 컴파일 게이트 결과 보고:
910
-
911
- ✅ 통과:
912
- "Phase 5: 컴파일 게이트 PASS (라운드 {N})"
913
- - tsc: 0 errors
914
- - build: success
915
- - dev server: running on localhost:{port}
916
-
917
- ❌ 실패 (3라운드 후):
918
- "Phase 5: 컴파일 게이트 FAIL"
919
- - 남은 에러 목록 (파일, 줄, 메시지)
920
- - 시도한 수정 내역
921
- - 사용자 수동 수정 필요
922
- → Phase 4 진행하지 않음
923
- ```
924
-
925
- ---
926
-
927
- ## Phase 6: 시각 검증 루프
928
-
929
- **Puppeteer + CDP로 실제 렌더링 결과를 확인하며 자동 수정한다.**
930
- **사람이 브라우저 보면서 고치는 것과 동일한 루프.**
931
- **인프라: `src/infra/lib/browser/` (범용 UI 검증 도구)**
932
-
933
- ```
934
- 자동 반복: P1=0 될 때까지. 최대 3라운드.
935
- ```
936
-
937
- ### 4-0. 환경 준비
938
-
939
- ```
940
- 1. dev 서버 시작:
941
- Phase 5에서 이미 시작된 dev 서버 사용 (재시작 불필요)
942
- localhost:{port} 확인
943
-
944
- 2. Puppeteer 브라우저 시작:
945
- import { launchBrowser, openPage } from 'src/infra/lib/browser'
946
- const browser = await launchBrowser({ headless: true })
947
- const page = await openPage(browser, 'http://localhost:3000/{feature}', {
948
- width: 480, // 모바일 퍼스트 (또는 타겟 뷰포트)
949
- height: 960,
950
- })
951
- ```
952
-
953
- ### 4-1. 렌더링 스크린샷 vs Figma 스크린샷
954
-
955
- ```
956
- import { captureScreenshot, compareScreenshots } from 'src/infra/lib/browser'
957
-
958
- 섹션에 대해:
959
- 1. 렌더링 결과 스크린샷 캡처:
960
- await captureScreenshot(page, {
961
- outPath: '/tmp/{feature}/rendered-{section}.webp',
962
- selector: '.{section}Section', // Phase 1에서 만든 클래스
963
- })
964
-
965
- 2. Figma 원본과 픽셀 비교:
966
- const diff = await compareScreenshots(
967
- '/tmp/{feature}/sections/{section}.webp', // Figma 원본
968
- '/tmp/{feature}/rendered-{section}.webp', // 렌더링 결과
969
- '/tmp/{feature}/diff-{section}.webp', // 차이 시각화
970
- )
971
-
972
- 3. diff 이미지를 Read로 확인:
973
- → 빨간색 영역 = 차이 나는 부분
974
- diffRatio > 0.1 이면 P1 이슈
975
- ```
976
-
977
- ### 4-2. CSS 수치 정밀 비교
978
-
979
- ```
980
- import { getComputedStyles, compareStyles, diffsToIssues } from 'src/infra/lib/browser'
981
-
982
- 각 섹션의 주요 요소에 대해:
983
- 1. 렌더링된 computed CSS 추출:
984
- const actual = await getComputedStyles(page, '.heroTitle', [
985
- 'font-size', 'color', 'width', 'height', 'padding', 'margin',
986
- 'background-color', 'border-radius', 'gap',
987
- ])
988
-
989
- 2. Figma tree.json의 기대값과 비교:
990
- // tree.json에서 해당 노드의 CSS 수치 (vw/clamp 변환 후)
991
- const expected = { 'font-size': '16px', 'color': '#ffffff', 'width': '465px' }
992
- const diffs = compareStyles(expected, actual)
993
-
994
- 3. 차이 → 이슈 변환:
995
- const issues = diffsToIssues(diffs)
996
- → delta > 4px: P1 (레이아웃 영향)
997
- → delta ≤ 4px: P2 (미세 차이)
998
- ```
999
-
1000
- ### 4-3. 이미지·텍스트 누락 체크
1001
-
1002
- ```
1003
- import { extractImages, extractTextContent } from 'src/infra/lib/browser'
1004
-
1005
- 1. 이미지 로드 상태 확인:
1006
- const images = await extractImages(page)
1007
- images.filter(img => !img.loaded)
1008
- → 로드 실패 이미지 = P1 (이미지 누락)
1009
- → src="" 이미지 = P1 (빈 경로)
1010
-
1011
- 2. 텍스트 콘텐츠 확인:
1012
- const texts = await extractTextContent(page)
1013
- → tree.json의 TEXT 노드 characters와 대조
1014
- → 누락된 텍스트 = P1
1015
- ```
1016
-
1017
- ### 4-4. 자동 수정 루프
1018
-
1019
- ```
1020
- 라운드 1~3:
1021
- 1. 4-1 ~ 4-3 실행 → 이슈 목록 수집
1022
- 2. P1 이슈 우선 수정:
1023
- - 이미지 누락 → 이미지 경로 확인, static/ 에 파일 존재 확인
1024
- - 레이아웃 다름 → 스크린샷 diff 이미지 + computed CSS로 원인 파악
1025
- - 텍스트 누락 → tree.json의 정확한 텍스트 삽입
1026
- - CSS 수치 틀림 → tree.json(tree.json)의 정확한 값으로 교체
1027
- ⚠️ 추정으로 수정하지 않는다. 반드시 tree.json 참조.
1028
- 3. 수정 후 컴파일 재검증:
1029
- Bash: npx tsc --noEmit 2>&1 (또는 3.5-1에서 선택한 타입 체커)
1030
- → 시각 수정이 타입 에러를 유발하면 즉시 타입 에러 수정 후 진행
1031
- 4. 페이지 리로드 → 다시 캡처 → 비교
1032
- 5. P1=0 이면 종료
1033
-
1034
- 라운드 종료 조건:
1035
- - P1=0: 성공 → 브라우저 종료, 결과 보고
1036
- - 3라운드 후 P1 남음: TODO 목록으로 사용자에게 보고
1037
- - 같은 이슈가 반복: 해당 이슈 스킵, 다음 이슈로
1038
-
1039
- 결과 보고:
1040
- - 수정한 파일 목록
1041
- - 남은 P2 이슈 목록 (선택적 수정)
1042
- - 최종 diff 스크린샷 경로
1043
- ```
1044
-
1045
- ### 4-5. 반응형 검증 (추가 뷰포트)
1046
-
1047
- ```
1048
- 모바일 검증 완료 후, 추가 브레이크포인트가 있으면:
1049
-
1050
- await page.setViewport({ width: 1920, height: 1080 })
1051
- await page.reload({ waitUntil: 'networkidle0' })
1052
-
1053
- → 데스크탑 Figma 스크린샷과 동일한 4-1 ~ 4-4 루프 반복
1054
- ```
1055
-
1056
- ### 4-6. 브라우저 정리
1057
-
1058
- ```
1059
- import { closeBrowser } from 'src/infra/lib/browser'
1060
-
1061
- 검증 완료 후:
1062
- await closeBrowser()
1063
- dev 서버 종료 (필요 시)
1064
- ```
1
+ ---
2
+ name: vibe.figma
3
+ description: Figma design to code — 트리 기반 구조적 코드 생성
4
+ triggers: []
5
+ tier: standard
6
+ ---
7
+
8
+ # vibe.figma — Structural Code Generation
9
+
10
+ ## 핵심 원칙
11
+
12
+ ```
13
+ Figma 트리가 코드의 원천이다. 스크린샷은 검증용이다.
14
+
15
+ ✅ Figma Auto Layout → CSS Flexbox 1:1 기계적 매핑
16
+ ✅ Figma CSS 속성 → SCSS 직접 변환 (추정 없음)
17
+ ✅ Claude는 시맨틱 판단만: 태그 선택, 컴포넌트 분리, 인터랙션
18
+ ✅ 스크린샷은 생성이 아닌 검증에만 사용
19
+ ```
20
+
21
+ ## 금지 사항
22
+
23
+ ```
24
+ 스크린샷을 보고 CSS 추정 (범용 LLM의 약점)
25
+ Figma 레이어를 무분별하게 div soup로 변환
26
+ ❌ CSS로 이미지 재현 (gradient/shape으로 그림 그리기)
27
+ 이미지 다운로드 없이 코드 생성 진행
28
+ placeholder / 빈 src="" 남기기
29
+ tree.json에 없는 CSS 값을 추정하여 작성
30
+ 컴포넌트 파일 안에 <style> 블록 / 인라인 style=""
31
+ tree.json의 CSS 속성을 SCSS에 직접 매핑
32
+ 외부 SCSS 파일에만 스타일 작성
33
+ ```
34
+
35
+ ## 전체 플로우
36
+
37
+ ```
38
+ /vibe.figma
39
+ 입력: 모든 URL을 한번에 받는다
40
+ Storyboard: https://figma.com/...?node-id=aaa (있으면)
41
+ MO Design: https://figma.com/...?node-id=xxx
42
+ PC Design: https://figma.com/...?node-id=yyy (있으면)
43
+
44
+ Phase 0: Setup (스택 감지, 디렉토리 생성, 기존 자산 인덱싱)
45
+ → Phase 1: 디자인 리소스 (URL 입력 → 스토리보드 분석 → 기능 스펙 문서)
46
+ Phase 2: 재료 확보 (모든 BP의 트리 + 노드 렌더링 이미지 + 스크린샷)
47
+ Phase 3: 리매핑 (tree.json → remapped.json, BP 간 노드 매칭 + CSS diff)
48
+ Phase 4: 순차 코드 생성 (remapped.json → 섹션별 HTML+SCSS)
49
+ Phase 5: 컴파일 게이트 (tsc → build → dev 확인)
50
+ → Phase 6: 시각 검증 루프 (렌더링 vs 스크린샷 비교 → 수정)
51
+
52
+ 작업 디렉토리 구조:
53
+ 각 Figma URL의 ROOT name에서 폴더명 추출 (kebab-case):
54
+ "MO_Main ..." → /tmp/{feature}/mo-main/
55
+ "PC_Main ..." → /tmp/{feature}/pc-main/
56
+
57
+ /tmp/{feature}/
58
+ ├── mo-main/ ← 모바일 Phase 2 추출 결과
59
+ │ ├── tree.json
60
+ │ ├── bg/ ← BG 프레임 렌더링
61
+ │ ├── content/ ← 콘텐츠 노드 렌더링
62
+ │ └── sections/ ← Phase 4 검증용 스크린샷
63
+ ├── pc-main/ ← 데스크탑 Phase 2 추출 결과
64
+ │ └── (동일 구조)
65
+ └── remapped.json ← Phase 3 리매핑 결과 (모든 BP 통합)
66
+
67
+ remapped.json이 Phase 4의 유일한 입력.
68
+ BP 노드 매칭 완료
69
+ CSS diff (mo/pc) 포함
70
+ → 이미지 렌더링 파일 경로 포함
71
+ Phase 4에서 바로 코드 생성 가능
72
+
73
+ 코드 출력: 프로젝트 디렉토리에 직접 배치
74
+ components/{feature}/HeroSection.vue
75
+ styles/{feature}/layout/_hero.scss (모바일 기본 + @media PC)
76
+ styles/{feature}/components/_hero.scss
77
+ ```
78
+
79
+ ---
80
+
81
+ ## Phase 0: Setup
82
+
83
+ ```
84
+ 1. 프로젝트 스택 감지:
85
+ - package.json → react/vue/svelte
86
+ - next.config.* / nuxt.config.* → 프레임워크
87
+ - *.scss / sass in deps → SCSS
88
+ - tailwind.config.* → Tailwind
89
+
90
+ 2. 기존 스타일 디렉토리 감지:
91
+ - assets/scss/ or src/styles/ or styles/
92
+
93
+ 3. 피처명 결정:
94
+ - Figma 파일명에서 추출kebab-case
95
+ - 예: "PUBG 겨울 PC방 이벤트"winter-pcbang
96
+
97
+ 4. 디렉토리 생성:
98
+ - components/{feature}/
99
+ - public/images/{feature}/ (또는 static/images/{feature}/)
100
+ - styles/{feature}/ (layout/, components/ 하위)
101
+
102
+ 5. 기존 컴포넌트 스캔 + 인덱싱:
103
+ - Glob "components/**/*.vue" or "components/**/*.tsx"
104
+ - 재사용 가능한 컴포넌트 목록 수집 (GNB, Footer, Button 등)
105
+
106
+ 5-1. 컴포넌트 상세 인덱싱 (50개 이하 스캔):
107
+ 대상 파일 수집 (우선순위 순서, 합산 50개 이내):
108
+ barrel file index.ts → components/ui/ components/common/ → components/shared/ → 나머지
109
+ 디렉토리 내에서는 1-depth 파일만 (하위 재귀 탐색 안 함)
110
+
111
+ 파일에 대해 2단계 추출:
112
+ a. Grep: defineProps|interface Props|<slot|@description|class=|className=
113
+ → 시작 줄 번호 탐색
114
+ b. Read: 시작줄 ~ +30줄 추출
115
+ Vue/Svelte template+script 분리 파일: 300줄 전체 Read
116
+ barrel file (index.ts): 전체 Read
117
+
118
+ 추출 항목:
119
+ - Props/Interface: defineProps<{...}> 또는 interface Props {...} 에서 prop 이름+타입
120
+ 외부 타입 참조 (defineProps<ButtonProps>()) → types 인덱스에서 교차 참조
121
+ - Slots: <slot> 또는 {children} 패턴
122
+ - 스타일 클래스: class="..." 또는 className={styles.xxx} 최상위 요소의 클래스명
123
+ - 용도 힌트: JSDoc @description 또는 파일 첫 번째 주석
124
+
125
+ 5-2. 인덱스 결과 저장:
126
+ 저장 경로: /tmp/{feature}/component-index.json
127
+ [
128
+ { name: "BaseButton",
129
+ path: "components/common/BaseButton.vue",
130
+ props: [{ name: "label", type: "string" }, { name: "variant", type: "'primary'|'secondary'" }],
131
+ slots: ["default"],
132
+ classes: ["btn", "btn--primary"],
133
+ description: "공통 버튼 컴포넌트" },
134
+ ...
135
+ ]
136
+
137
+ 컨텍스트 관리:
138
+ - 컴포넌트 20개 이하: 전체 인덱스를 프롬프트에 포함
139
+ - 컴포넌트 20개 초과: 이름+설명+축약 props(이름만, 타입 생략)만 포함
140
+ 매칭 후보 발견 시 해당 파일 Read로 상세 확인
141
+ - classes 필드는 요약에서 제외 (매칭 시 파일 Read로 확인)
142
+
143
+ 5-3. Hooks/Types/Constants 인덱싱:
144
+ 추가 스캔 대상:
145
+ - Composables/Hooks: composables/**/*.ts, hooks/**/*.ts
146
+ export 함수명 + 파라미터 + 반환 타입
147
+ - 타입 정의: types/**/*.ts, types.ts
148
+ → export interface/type 이름 + 최상위 필드
149
+ - 상수: constants/**/*.ts
150
+ export const 이름 + 값 (또는 타입)
151
+
152
+ 저장: /tmp/{feature}/context-index.json (component-index와 별도)
153
+ 컨텍스트 관리:
154
+ - 항목 30개 이하: 전체 인덱스를 프롬프트에 포함
155
+ - 항목 30개 초과: 이름+핵심 시그니처만 요약, 상세 필요 파일 Read로 지연 조회
156
+
157
+ 타임아웃: 파일당 Read 최대 300줄, 전체 인덱싱 2분 이내 완료
158
+
159
+ 6. 기존 디자인 토큰 스캔:
160
+
161
+ SCSS 토큰:
162
+ Glob: **/_variables.scss, **/_tokens.scss, **/_colors.scss, **/variables.scss
163
+ 패턴: $변수명: 값; 추출
164
+ → 결과: { name: "$color-primary", value: "#3b82f6", source: "styles/_variables.scss" }
165
+
166
+ CSS Variables:
167
+ Glob: **/global.css, **/variables.css, **/root.css, **/app.css
168
+ Grep: "--[a-zA-Z].*:" 패턴
169
+ 결과: { name: "--color-primary", value: "#3b82f6", source: "styles/global.css" }
170
+
171
+ Tailwind:
172
+ tailwind.config.{js,ts,mjs} 존재 Read
173
+ theme.colors, theme.extend.colors 에서 커스텀 색상 추출
174
+ → theme.spacing, theme.fontSize 에서 커스텀 값 추출
175
+ Tailwind v4: global CSS에서 @theme 디렉티브 내 CSS variable도 스캔
176
+ → 결과: { name: "blue-500", value: "#3b82f6", type: "tailwind", category: "color" }
177
+
178
+ CSS-in-JS:
179
+ Glob: **/theme.{ts,js}, **/tokens.{ts,js}, **/design-tokens.{ts,js}
180
+ export 객체에서 color/spacing/typography 키 추출
181
+
182
+ 통합 결과 → /tmp/{feature}/project-tokens.json:
183
+ {
184
+ colors: [{ name, value, source }],
185
+ spacing: [{ name, value, source }],
186
+ typography: [{ name, value, source }],
187
+ other: [{ name, value, source }]
188
+ }
189
+
190
+ 토큰 소스 우선순위 (복수 시스템 공존 시):
191
+ Tailwind > CSS Variables > SCSS > CSS-in-JS
192
+
193
+ 성능: 100개 파일 기준 5초 이내 완료
194
+ 파싱 실패 시: 해당 파일 스킵 + 경고 로그 (전체 중단하지 않음)
195
+ ```
196
+
197
+ ---
198
+
199
+ ## Phase 1: 디자인 리소스
200
+
201
+ 사용자에게 질문한다:
202
+ - question: "스토리보드, 디자인 리소스를 줄바꿈으로 입력해주세요. (순서 무관)"
203
+ - 예시:
204
+ https://figma.com/design/xxx/...?node-id=20-4964
205
+ https://figma.com/design/yyy/...?node-id=641-78147
206
+ https://figma.com/design/yyy/...?node-id=641-78200
207
+ 또는:
208
+ docs/storyboard.pdf
209
+ https://figma.com/design/yyy/...?node-id=641-78147
210
+ - options 제공 금지 — 자유 텍스트 입력만 허용
211
+ - 디자인 URL 최소 1개 필수
212
+
213
+ ### 입력 분류 (자동)
214
+
215
+ ```
216
+ 줄을 파싱하여 분류:
217
+
218
+ 1. figma.com URL → Figma 리소스
219
+ ROOT name으로 스토리보드/MO/PC 판별
220
+ fileKey가 다르면 스토리보드 vs 디자인 구분
221
+ ROOT name에 "MO" 모바일, "PC" → 데스크탑
222
+
223
+ 2. .pdf 파일 경로 PDF 스토리보드
224
+ → Read 도구로 페이지별 분석
225
+
226
+ 3. .png/.jpg/.webp 파일 경로 → 이미지 스토리보드
227
+ Read 도구로 시각 분석
228
+ ```
229
+
230
+ ### 1-1. 스토리보드 분석
231
+
232
+ ```
233
+ 입력 타입에 따라 분기:
234
+
235
+ ■ Figma URL인 경우:
236
+ URL에서 fileKey, nodeId 추출
237
+
238
+ 1단계 (BLOCKING): 루트 depth=2로 전체 프레임 + nodeId 수집
239
+ # [FIGMA_SCRIPT] = ~/.vibe/hooks/scripts/figma-extract.js
240
+ node "[FIGMA_SCRIPT]" tree {fileKey} {nodeId} --depth=2
241
+
242
+ → 모든 자식 프레임의 name + nodeId + size 를 테이블로 출력
243
+ → nodeId가 빠진 프레임이 있으면 안 됨
244
+
245
+ 2단계: name 패턴으로 프레임 분류
246
+ SPEC — "기능 정의서", "정책" → depth 높여서 텍스트 추출
247
+ CONFIG — "해상도", "브라우저" → designWidth, minWidth, breakpoint 확보
248
+ SHARED — "공통", "GNB", "Footer", "Popup" → 공통 컴포넌트 파악
249
+ PAGE — "화면설계", "메인 -" 섹션 목록 + 인터랙션 스펙
250
+
251
+ 핵심 프레임 선별 (전부 읽지 않음):
252
+ 1순위: SPEC (기능 정의서) — 1개
253
+ 2순위: CONFIG (해상도) — 1개
254
+ 3순위: PAGE 중 메인 섹션만 (3.1, 3.2, 3.3, 3.4, 3.5, 3.6)
255
+ 하위 케이스(3.1.1, 3.2.1 등)는 건너뜀
256
+ 4순위: SHARED (공통 요소, Popup) — 필요 시
257
+
258
+ PDF 파일인 경우:
259
+ Read 도구로 페이지별 분석 (pages: "1-5" → "6-10" → ...)
260
+ 페이지에서 추출:
261
+ - 섹션 목록 + 기능 정의
262
+ - 해상도/브레이크포인트 정보 (CONFIG)
263
+ - 인터랙션 흐름
264
+ - 상태 정의
265
+ Figma 스토리보드와 동일한 기능 스펙 문서 생성
266
+
267
+ 이미지 파일인 경우:
268
+ Read 도구로 시각 분석
269
+ → 와이어프레임/목업에서 섹션 구조 + 기능 추출
270
+
271
+ 스토리보드 없음:
272
+ 디자인 URL의 tree.json에서 섹션 목록만 추출
273
+ 기능 정의는 디자인 name/구조에서 추정 (정확도 낮음)
274
+ ```
275
+
276
+ ### 1-2. 기능 스펙 문서 작성 (파일 생성 없음)
277
+
278
+ ```
279
+ ❌ Phase 1에서 코드 파일을 생성하지 않는다.
280
+ Phase 1 HTML 구조와 Phase 4 트리 매핑이 충돌하면 이중 작업
281
+ → Phase 4에서 remapped.json 기반으로 코드를 생성
282
+
283
+ Phase 1의 출력물은 기능 스펙 문서 (텍스트):
284
+
285
+ 1. 섹션 목록:
286
+ | # | 섹션 이름 | Figma 프레임 name | 높이 | 설명 |
287
+ |---|----------|------------------|------|------|
288
+ | 1 | Hero | Hero | 1280px | 키비주얼 + 이벤트 정보 |
289
+ | 2 | DailyCheckIn | Daily | 3604px | 출석 미션 |
290
+ | 3 | PlayTime | Frame 633371 | 11363px | 플레이타임 미션 |
291
+
292
+ 2. 섹션의 기능 정의:
293
+ /**
294
+ * 일일 출석 미션 섹션
295
+ *
296
+ * [기능 정의]
297
+ * - 매일 출석 시 스노우 토큰 즉시 지급
298
+ * - 누적 3/5/7일 달성 시 추가 보상
299
+ *
300
+ * [인터랙션]
301
+ * 출석하기 클릭 API호출 토큰지급 표시
302
+ * 누적 보상 클릭 → 보상 수령
303
+ *
304
+ * [상태] default, checked, reward-claimed
305
+ */
306
+
307
+ 3. 공통 컴포넌트 목록:
308
+ 프로젝트에 이미 있는 컴포넌트 (GNB, Footer 등)
309
+ 새로 만들 공통 컴포넌트
310
+
311
+ 4. TypeScript 인터페이스 초안:
312
+ interface RewardItem { id: string; name: string; tokenAmount: number; status: 'locked'|'available'|'claimed' }
313
+ ```
314
+
315
+ ### 1-3. 검증
316
+
317
+ ```
318
+ Phase 1 완료 조건:
319
+ 모든 섹션이 목록에 포함되어 있다
320
+ 각 섹션에 [기능 정의] + [인터랙션] + [상태] 가 정의되어 있다
321
+ □ TypeScript 인터페이스 초안이 작성되어 있다
322
+ □ 공통 컴포넌트가 식별되어 있다
323
+ 파일을 하나도 생성하지 않았다
324
+
325
+ Phase 4에서 이 스펙 + remapped.json을 합쳐서 코드를 생성한다.
326
+ ```
327
+
328
+ ---
329
+
330
+ ## Phase 2: 재료 확보
331
+
332
+ Phase 1 컴포넌트가 준비된 상태에서, 디자인 URL로 시각 재료를 수집한다.
333
+
334
+ 사용자에게 질문한다:
335
+ - question: "디자인 Figma URL을 입력해주세요. 여러 페이지는 줄바꿈으로 구분."
336
+ - options 제공 금지 자유 텍스트 입력만 허용
337
+
338
+ ### 멀티 프레임 URL 검증
339
+
340
+ ```
341
+ URL 유효성 검증:
342
+ - 모든 URL에서 fileKey 추출 → 동일한 fileKey인지 확인
343
+ - 서로 다른 fileKey 발견 시 에러: "멀티 프레임은 동일 Figma 파일 내 다른 프레임만 지원합니다"
344
+ - node-id 파라미터 누락해당 URL 에러 보고
345
+ - 최대 5 URL까지 지원
346
+
347
+ URL 개수에 따른 처리:
348
+ 1개: 기존 방식 (변경 없음, 아래 2-1 그대로)
349
+ 2개 이상: 멀티 프레임 모드 활성화 (2-1-multi 참조)
350
+ ```
351
+
352
+ ### 2-1. 디자인 재료 추출 (단일 URL)
353
+
354
+ ```
355
+ URL에서 fileKey, nodeId 추출
356
+
357
+ 1단계 — 전체 스크린샷 (정답 사진):
358
+ node "[FIGMA_SCRIPT]" screenshot {fileKey} {nodeId} --out=/tmp/{feature}/full-screenshot.webp
359
+
360
+ 2단계 — 전체 트리 + CSS (수치 재료):
361
+ node "[FIGMA_SCRIPT]" tree {fileKey} {nodeId} --depth=10
362
+ /tmp/{feature}/tree.json 에 저장
363
+
364
+ 3단계 — 전체 이미지 다운로드 (시각 재료):
365
+ node "[FIGMA_SCRIPT]" images {fileKey} {nodeId} --out=/tmp/{feature}/images/ --depth=10
366
+ 모든 이미지 에셋 확보. 누락 0건, 0byte 0건.
367
+
368
+ 3.5단계 아이템/아이콘 노드 렌더링 (추가 시각 재료):
369
+ tree.json에서 INSTANCE/COMPONENT 타입 아이템 후보를 식별:
370
+ - name에 "item", "icon", "reward", "token", "coin", "badge" 포함
371
+ - 크기 50~300px 범위의 독립 요소
372
+ - fill 이미지가 없지만 시각적으로 의미 있는 노드
373
+ 해당 노드를 개별 렌더링:
374
+ node "[FIGMA_SCRIPT]" images {fileKey} {nodeId} --render --nodeIds={id1},{id2},... --out=/tmp/{feature}/images/
375
+ → 이미지 fill이 아닌 벡터/인스턴스 에셋도 PNG로 확보
376
+ → Phase 3에서 목 데이터의 image 경로에 연결
377
+
378
+ 4단계 — 섹션별 스크린샷 (부분 정답):
379
+ 트리의 1depth 자식 프레임 각각:
380
+ node "[FIGMA_SCRIPT]" screenshot {fileKey} {child.nodeId} --out=/tmp/{feature}/sections/{child.name}.webp
381
+ ```
382
+
383
+ ### 2-1-multi. 멀티 프레임 재료 확보 (2개 이상 URL)
384
+
385
+ ```
386
+ 각 URL에 대해 순차 추출 (Figma API rate limit: 요청 간 500ms 간격):
387
+ URL 1 → /tmp/{feature}/frame-1/ (full-screenshot, tree, images, sections)
388
+ URL 2 → /tmp/{feature}/frame-2/ (URL 1 완료 후 500ms 대기)
389
+ URL 3 → /tmp/{feature}/frame-3/ (URL 2 완료 500ms 대기)
390
+ 추출 완료 후처리(섹션 분할 등)는 병렬 가능
391
+
392
+ 부분 실패 처리:
393
+ - 개별 URL 추출 실패 시 해당 frame만 건너뛰고 나머지 진행
394
+ - 실패한 frame은 사용자에게 즉시 보고: "frame-{N} 추출 실패: {에러 사유}" (API 에러, 권한 부족, 잘못된 nodeId 등)
395
+ - 성공한 frame 2: Phase 3 계속 진행
396
+ - 정확히 1개만 성공: 단일 프레임 모드로 폴백 (Phase 3 스킵)
397
+ - 0개 성공: 전체 실패 보고
398
+
399
+ 결과:
400
+ /tmp/{feature}/
401
+ ├── frame-1/ ← 메인 페이지
402
+ │ ├── full-screenshot.webp
403
+ │ ├── tree.json
404
+ │ ├── images/
405
+ │ └── sections/
406
+ ├── frame-2/ ← 서브 페이지 1
407
+ │ └── ...
408
+ ├── frame-3/ ← 서브 페이지 2
409
+ │ └── ...
410
+ └── sections/ ← Phase 6 검증용 스크린샷
411
+ ```
412
+
413
+ ### 2-2. 추출 데이터 정리
414
+
415
+ ```
416
+ Phase 2 완료 /tmp/{feature}/ 에 다음이 준비되어야 함:
417
+
418
+ 단일 URL:
419
+ /tmp/{feature}/
420
+ ├── full-screenshot.webp ← 전체 정답 사진
421
+ ├── tree.json ← 노드 트리 + CSS 수치
422
+ ├── images/ ← 모든 이미지 에셋
423
+ │ ├── hero-bg.webp
424
+ │ ├── hero-title.webp
425
+ │ ├── card-item-1.webp
426
+ │ └── ...
427
+ └── sections/ ← 섹션별 정답 사진
428
+ ├── hero.webp
429
+ ├── daily-checkin.webp
430
+ ├── playtime-mission.webp
431
+ └── ...
432
+
433
+ 멀티 URL: 2-1-multi 결과 구조 참조
434
+
435
+ 재료 목록 (material-inventory):
436
+ - 이미지: 파일명 + 크기 + 용도 추정 (BG/icon/title/decoration)
437
+ - 색상: tree.json에서 추출한 모든 고유 색상값
438
+ - 폰트: 사용된 font-family, size, weight 목록
439
+ - 텍스트: 모든 TEXT 노드의 characters 값
440
+ - 간격: padding, gap, margin 사용 빈도 높은
441
+ ```
442
+
443
+ ### 반응형 단위 (scaleFactor 사용하지 않음)
444
+
445
+ ```
446
+ 스토리보드 CONFIG에서 확보:
447
+ designWidth: 디자인 너비 (예: 모바일 720px, PC 2560px)
448
+ minWidth: 최소 지원 너비 (예: 340px)
449
+ breakpoint: PC/모바일 분계 (예: 1025px)
450
+
451
+ UI 요소 vw 비례:
452
+ vw값 = (Figma px / designWidth) × 100
453
+ 예: gap: 24px → 24/720 × 100 = 3.33vw
454
+ 예: width: 620px → 620/720 = 86.11% (부모 대비)
455
+
456
+ 폰트 → clamp(최소, vw, 최대):
457
+ 최소값 = 역할별 가독성 기준 (h1:16px, 본문:12px, 캡션:10px)
458
+ vw값 = (Figma px / designWidth) × 100
459
+ 최대값 = Figma 원본 px
460
+ 예: 24px 본문 clamp(12px, 3.33vw, 24px)
461
+
462
+ 변환 안 함: color, opacity, font-weight, z-index, line-height(단위 없을 때)
463
+ ```
464
+
465
+ ---
466
+
467
+ ## Phase 3: 리매핑 (tree.json remapped.json)
468
+
469
+ **URL 2개 이상일 때만 실행. 단일 URL이면 Phase 3으로 건너뜀.**
470
+ **프레임 공통 요소를 식별하여 공유 컴포넌트로 추출한다.**
471
+
472
+ ```
473
+ 1. 시각 비교 — 각 프레임의 스크린샷을 순차 Read:
474
+ - frame-1/full-screenshot.webp frame-2/full-screenshot.webp → ...
475
+ - 시각적으로 반복되는 요소 식별:
476
+ 상단 영역 (GNB/Header), 하단 영역 (Footer),
477
+ 카드 패턴, 버튼 스타일, 섹션 레이아웃
478
+
479
+ 2. 구조 비교 — 각 tree.json의 1depth 자식 비교:
480
+ - 동일한 name 또는 prefix 일치 (예: "GNB", "Header", "Footer", "Nav")
481
+ - 동일한 size (width와 height 모두 ±10% 이내): 같은 컴포넌트 후보
482
+ - 동일한 CSS 패턴: 같은 스타일 사용 (색상, 폰트, 레이아웃)
483
+
484
+ 3. 공통 컴포넌트 후보 목록:
485
+ shared-components:
486
+ - name: GNB
487
+ frames: [frame-1, frame-2, frame-3]
488
+ consistency: 100% (모든 프레임에서 동일)
489
+ action: 공유 컴포넌트로 1회만 생성
490
+ - name: Footer
491
+ frames: [frame-1, frame-3]
492
+ consistency: 67% (2/3 프레임)
493
+ action: 공유 컴포넌트 + frame-2는 다른 Footer
494
+ - name: CardItem
495
+ frames: [frame-1, frame-2]
496
+ size-match: 95%
497
+ action: 공유 컴포넌트 (props로 변형)
498
+
499
+ 4. 공통 토큰 추출:
500
+ - 모든 프레임의 색상 팔레트 합집합 → 공유 _tokens.scss
501
+ - 모든 프레임의 폰트 목록 합집합
502
+ - 모든 프레임의 간격 패턴 합집합
503
+ 프레임별 고유 값만 프레임 로컬 토큰으로 분리
504
+ ```
505
+
506
+ ---
507
+
508
+ ## Phase 4: 순차 코드 생성
509
+
510
+ **remapped.json 기반으로 섹션별 순차 코드 생성.**
511
+ **한 섹션 완료 브라우저 확인 다음 섹션. 병렬 금지.**
512
+
513
+ **멀티 프레임 모드 조립 순서 변경:**
514
+ ```
515
+ 멀티 프레임 Phase 3 순서:
516
+
517
+ 1단계: 공유 컴포넌트 먼저 생성
518
+ - shared-components 목록의 컴포넌트를 components/shared/에 생성
519
+ - 가장 일관적인 프레임(shared-components 매칭 수가 가장 많은 프레임) 기준으로 조립
520
+ - 프레임별 변형은 props로 처리
521
+
522
+ 2단계: 프레임별 고유 섹션 조립
523
+ - frame-1 고유 섹션: 공유 컴포넌트 import + 고유 섹션 신규 생성
524
+ - frame-2 고유 섹션: 동일
525
+ - 각 프레임의 페이지 파일에서 공유 + 고유 컴포넌트 배치
526
+
527
+ 3단계: 스타일 구조
528
+ styles/{feature}/
529
+ ├── _tokens.scss ← 공유 토큰 (합집합)
530
+ ├── shared/ 공유 컴포넌트 스타일
531
+ │ ├── layout/_gnb.scss
532
+ │ └── components/_gnb.scss
533
+ ├── frame-1/ ← 메인 고유 스타일
534
+ ├── layout/
535
+ └── components/
536
+ └── frame-2/
537
+
538
+ 단일 URL: 기존 방식 그대로 (위 멀티 프레임 순서 무시)
539
+ ```
540
+
541
+ ### 3-0. SCSS Setup + 등록 (첫 섹션 전)
542
+
543
+ ```
544
+ Phase 1에서 생성한 빈 SCSS 파일에 기본 내용 Write:
545
+ styles/{feature}/index.scss ← @import 진입점
546
+ styles/{feature}/_tokens.scss ← tree.json에서 추출한 디자인 토큰
547
+ styles/{feature}/_mixins.scss ← breakpoint mixin
548
+ styles/{feature}/_base.scss ← 루트 클래스
549
+
550
+ 토큰 매핑 (기존 토큰 우선 사용):
551
+ 1. /tmp/{feature}/project-tokens.json Read로드
552
+ 2. Figma tree.json의 각 값에 대해 project-tokens에서 동일 값 검색:
553
+ - 색상: hex 정규화 후 완전 일치 (Figma RGBA 0-1 → hex, 3자리→6자리, 대소문자 무시)
554
+ alpha < 1: 8자리 hex (#RRGGBBAA) 또는 rgba() 함수로 변환
555
+ - 간격: px 완전 일치 (rem→px: 1rem=16px)
556
+ - 폰트: family 이름 포함 매칭
557
+ 3. 매칭됨 기존 토큰 참조:
558
+ - SCSS: @use 'path' 로 기존 파일 import, $변수명 사용
559
+ - Tailwind: 해당 유틸리티 클래스 사용 (bg-blue-500)
560
+ - CSS Variables: var(--color-primary) 사용
561
+ 4. 매칭 안 됨 → 새 토큰 생성 (기존 방식)
562
+
563
+ _tokens.scss 구조:
564
+ // ─── 기존 토큰 참조 ────────────────────
565
+ @use '../../styles/variables' as v;
566
+
567
+ // ─── 매핑 (기존 토큰 피처 시맨틱) ────
568
+ $color-bg-primary: v.$color-navy; // 기존 재사용
569
+ $color-text-primary: v.$color-white; // 기존 재사용
570
+
571
+ // ─── 토큰 (매칭 안 된 값만) ─────────
572
+ $color-accent-gold: #ffd700; //
573
+ $space-section-gap: 42px; //
574
+
575
+ 매핑 결과 보고: "토큰 매핑: 12/18 매칭 (67%), 6개 새 토큰 생성"
576
+
577
+ 기존 토큰 파일 수정 금지 참조만
578
+ 같은 값의 토큰 중복 생성 금지
579
+ 토큰은 피처 스코프 네이밍 ($feature-color-xxx)
580
+
581
+ project-tokens.json 없는 경우 (기존 토큰 없음):
582
+ 기존 방식으로 전체 생성:
583
+ - 색상 primitive ($color-navy: #0a1628) + semantic ($color-bg-primary)
584
+ - 폰트 $font-pretendard, $font-size-md: 16px
585
+ - 간격 → $space-sm: 8px, $space-md: 16px
586
+
587
+ 스타일 등록 (BLOCKING):
588
+ Grep "{feature}/index.scss" → 이미 등록되어 있으면 건너뜀.
589
+ 없으면 프로젝트 방식에 맞게 등록.
590
+ ```
591
+
592
+ ### 3-0.5. 컴포넌트 매칭 ( 섹션 조립 )
593
+
594
+ ```
595
+ /tmp/{feature}/component-index.json Read로 로드한다.
596
+
597
+ 각 섹션 스크린샷 분석 후, 기존 컴포넌트 매칭:
598
+
599
+ 1. 스크린샷에서 식별된 UI 요소를 component-index와 대조
600
+ 2. 매칭 판정 기준:
601
+ - 필수: name/role 유사성 (시각적 역할 일치)
602
+ 버튼 BaseButton, 네비게이션 → GNB, 카드 → Card, 모달 → Modal
603
+ - 보조: props 호환성 (필요 props가 기존 컴포넌트에 존재)
604
+ - 보조: slots 호환성 (필요 slot이 존재)
605
+ - 불일치: props/slots 50% 미만 호환이면 매칭 거부 → 새로 생성
606
+ 3. 매칭된 컴포넌트: import하여 props 전달 (내부 수정 금지)
607
+ 4. 매칭 됨: 새로 생성 (강제 재사용 금지)
608
+
609
+ 재사용 스타일 충돌 방지:
610
+ 기존 컴포넌트 import하여 사용
611
+ props로 variant/size 커스터마이즈
612
+ 래퍼 클래스로 position/size만 오버라이드
613
+ 기존 컴포넌트 내부 스타일 수정 금지
614
+ 90% 유사한데 새로 만들기 금지
615
+ ```
616
+
617
+ ### 3-1. 순차 블록 빌딩 (병렬 금지)
618
+
619
+ ```
620
+ ❌ 여러 섹션을 동시에 생성하지 않는다
621
+ 병렬 생성 시 컨텍스트 분산 → 매핑 정확도 저하품질 하락
622
+ 섹션 결과를 확인하지 않으면 실수가 누적됨
623
+
624
+ ✅ 한 섹션씩 순차적으로 블록을 쌓듯 만든다:
625
+
626
+ 작업 폴더: ROOT name에서 추출 (Phase 2에서 결정)
627
+ "MO_Main ..." /tmp/{feature}/mo-main/
628
+ 코드 출력도 이 폴더 안에:
629
+ /tmp/{feature}/mo-main/components/{feature}/
630
+ /tmp/{feature}/mo-main/styles/{feature}/
631
+ Phase 5에서 최종 프로젝트 디렉토리에 배치
632
+
633
+ 섹션 1 (Hero):
634
+ 1. tree.json에서 Hero 노드 Read
635
+ 2. 코드 생성 (컴포넌트 + SCSS)
636
+ 3. 브라우저에서 확인 (dev 서버)
637
+ 4. OK다음 섹션으로
638
+ NG수정 재확인
639
+
640
+ 섹션 2 (KID):
641
+ 1. tree.json에서 KID 노드 Read
642
+ 2. 코드 생성
643
+ 3. 브라우저에서 확인 (이전 섹션도 함께)
644
+ 4. OK → 다음 섹션으로
645
+
646
+ 섹션 3 (Daily) ... 반복
647
+
648
+ 각 섹션 완료 시:
649
+ - 해당 섹션의 컴포넌트 + SCSS가 동작하는 상태
650
+ - pages/{feature}.vue에 해당 섹션이 추가된 상태
651
+ - 브라우저에서 이전 섹션 + 현재 섹션이 모두 보이는 상태
652
+ ```
653
+
654
+ ### 3-2. 트리 기반 구조적 코드 생성
655
+
656
+ ```
657
+ 섹션에 대해 (vibe.figma.convert 참조):
658
+
659
+ 1. 트리 구조 읽기 tree.json에서 해당 섹션 노드를 Read
660
+ Auto Layout 속성(flex, gap, padding)이 코드의 기반
661
+ 스크린샷은 검증용으로만 참조
662
+
663
+ 2. 기계적 매핑 (추정 없음):
664
+ a. 이미지 vs HTML 판별 (각 노드마다 — vibe.figma.convert 체크리스트 참조):
665
+ - TEXT 자식 있음 → HTML (이미지에 텍스트 포함 금지)
666
+ - INSTANCE 반복 패턴 → HTML 반복 구조 (내부 이미지 에셋만 추출)
667
+ - 인터랙티브 요소 (btn, CTA) HTML <button>
668
+ - 동적 데이터 (가격, 기간, 수량) → HTML 텍스트
669
+ - 위 모두 아님 → 이미지 렌더링 가능
670
+ b. 이미지: 판별 통과한 노드만 static/images/{feature}/에 배치
671
+ c. 노드 HTML 매핑:
672
+ - BG 프레임 → CSS background-image (img 태그 아님)
673
+ - Auto Layout 있음 → <div> + flex (direction/gap/padding 직접)
674
+ - Auto Layout 없음 <div> + position:relative (자식 absolute)
675
+ - TEXT 노드<span> (Claude가 h2/p/button으로 승격)
676
+ - 순수 이미지 에셋 <img src="렌더링된 파일">
677
+ - 반복 패턴 (동일 구조 2+) → v-for (카드 내 이미지만 <img>, 나머지 HTML)
678
+ c. CSS 직접 매핑:
679
+ - node.css의 모든 속성을 SCSS에 1:1 매핑
680
+ - vw/clamp 반응형 단위 변환 (vibe.figma.convert 참조)
681
+ - tree.json에 없는 CSS 값은 작성하지 않음
682
+ d. Phase 1의 JSDoc, 인터페이스, 핸들러 삽입
683
+
684
+ 3. Claude 시맨틱 보강:
685
+ - div section/h2/p/button 태그 승격
686
+ - 컴포넌트 분리 + props 설계
687
+ - 접근성 (alt, aria)
688
+ - 인터랙션 (클릭, 상태)
689
+
690
+ 4. 브라우저 확인 (섹션별 게이트):
691
+ - dev 서버에서 현재까지 만든 섹션이 모두 보이는지 확인
692
+ - 이미지 로드, 레이아웃, 텍스트 확인
693
+ - OK → 다음 섹션 진행
694
+ - NG → 수정 후 재확인 (다음 섹션으로 넘어가지 않음)
695
+ ```
696
+
697
+ ### 3-3. 코드 작성 규칙
698
+
699
+ ```
700
+ 컴포넌트 (Vue 예시):
701
+ <template>
702
+ tree.json의 Auto Layout 구조를 HTML flex 레이아웃으로 직접 매핑.
703
+ Claude가 시맨틱 태그로 승격 (div → section/h2/p/button).
704
+ Phase 1의 기능 요소(v-for, @click, v-if) 보존.
705
+ 이미지 경로: /images/{feature}/파일명.webp (실제 파일 존재 확인)
706
+ 텍스트: tree.json의 TEXT 노드 characters 값 그대로.
707
+
708
+ <script setup>
709
+ Phase 1의 JSDoc + 인터페이스 + 핸들러 보존.
710
+ 새로운 데이터/상태 추가 시 기존과 병합.
711
+
712
+ <style> 블록 없음 외부 SCSS만.
713
+
714
+ SCSS (vibe.figma.convert 참조):
715
+ layout/ → position, display, flex, width, height, padding, gap
716
+ components/ font, color, border, shadow, opacity
717
+ 모든 수치는 tree.json의 정확한 값 → vw/clamp 변환 (vibe.figma.convert 참조).
718
+ 추정 금지 — 값이 없으면 tree.json에서 다시 찾는다.
719
+ ```
720
+
721
+ ### 반응형 (추가 URL)
722
+
723
+ ```
724
+ 완료 후 질문: "다음 브레이크포인트 디자인 URL을 입력해주세요. (없으면 '없음')"
725
+
726
+ URL 있으면:
727
+ 1. URL에서 재료 확보 (Phase 1 반복)
728
+ 2. 새 스크린샷과 기존 코드 비교
729
+ 3. @media (min-width: $bp-desktop) 오버라이드만 추가
730
+ 4. 기존 모바일 코드 삭제 금지
731
+ ```
732
+
733
+ ---
734
+
735
+ ## Phase 5: 컴파일 게이트
736
+
737
+ **Phase 3 코드 생성 완료 후, 브라우저 검증 전에 컴파일 성공을 보장한다.**
738
+ **컴파일 에러는 스킵 불가 반드시 수정 또는 사용자 보고.**
739
+ **Phase 5 실패 Phase 4 진행 불가 (hard gate).**
740
+
741
+ ```
742
+ 자동 반복: 컴파일 성공까지. 최대 3라운드.
743
+ ```
744
+
745
+ ### 3.5-0. 베이스라인 캡처 (Phase 3 변경 전)
746
+
747
+ ```
748
+ Phase 3 시작 전에 기존 프로젝트의 에러를 캡처:
749
+ 1. 타입 체크 베이스라인: (3.5-1에서 선택한 동일 명령 사용) > /tmp/{feature}/baseline-typecheck.txt 2>&1
750
+ 2. 빌드 베이스라인: npm run build > /tmp/{feature}/baseline-build.txt 2>&1
751
+
752
+ Phase 5에서는 baseline에 없는 **새로 발생한 에러만** 수정 대상.
753
+ baseline에 존재하던 에러는 무시하고 별도 보고 ("기존 에러 {N}개 유지").
754
+ vibe.figma가 생성/수정한 파일 외의 에러는 자동 수정 금지.
755
+ ```
756
+
757
+ ### 3.5-1. TypeScript 컴파일 체크
758
+
759
+ ```
760
+ 1. 프로젝트 타입 체커 감지 → 실행:
761
+ - package.json scripts에 type-check 또는 typecheck 존재 → npm run type-check 사용
762
+ - vue-tsc 설치 확인 (Vue 프로젝트) → npx vue-tsc --noEmit 2>&1
763
+ - svelte-check 설치 확인 (Svelte 프로젝트) → npx svelte-check 2>&1
764
+ - 해당 없음 fallback: npx tsc --noEmit 2>&1
765
+ → 에러 0개: PASS → 다음 단계
766
+ 에러 있음: 에러 메시지 파싱 → 자동 수정
767
+
768
+ 2. 에러 파싱:
769
+ 에러에서 추출: 파일 경로, 줄 번호, 에러 코드, 메시지
770
+ 예: "src/components/Hero.tsx(15,3): error TS2322: Type 'string' is not assignable to type 'number'"
771
+
772
+ 3. 자동 수정 (에러 유형별):
773
+ - TS2322 (타입 불일치): prop 타입을 올바르게 수정
774
+ - TS2304 (이름 없음): import 추가
775
+ - TS2339 (프로퍼티 없음): interface에 프로퍼티 추가
776
+ - TS7006 (암시적 any): 타입 어노테이션 추가
777
+ - 기타: Read로 해당 파일+줄 확인 → 컨텍스트 기반 수정
778
+ ```
779
+
780
+ ### 3.5-2. 빌드 체크
781
+
782
+ ```
783
+ 1. npm run build 실행:
784
+ Bash: npm run build 2>&1
785
+ 성공: PASS 다음 단계
786
+ 실패: 에러 메시지 파싱 자동 수정
787
+ 타임아웃: 최대 120초 (초과 해당 라운드 실패 처리)
788
+
789
+ 2. 일반적 빌드 에러 처리:
790
+ - SCSS 컴파일 에러: 변수명/import 오류 수정
791
+ - Module not found: import 경로 수정 (.js 확장자 등)
792
+ - ESLint 에러 (--max-warnings 초과): 자동 수정 가능한 것 처리
793
+ ```
794
+
795
+ ### 3.5-3. dev 서버 시작 확인
796
+
797
+ ```
798
+ 1. dev 서버 시작 + PID 캡처:
799
+ Bash: npm run dev & echo $! DEV_PID 저장
800
+ localhost 포트 자동 감지: npm run dev stdout에서 localhost:\d+ 또는 port \d+ 파싱
801
+ 감지 실패 시 기본값 3000, 5173, 4173 순서 시도
802
+ → 포트 폴링 (3초 간격, 최대 30초 대기)
803
+ 성공: Phase 4 진행 (Phase 4 완료 후 정리)
804
+ → 실패: kill $DEV_PID → 에러 로그 확인 → 수정 → 재시도
805
+
806
+ 2. 프로세스 정리 규칙:
807
+ - Phase 4 완료 또는 3라운드 실패 시 반드시 정리
808
+ - 정리 순서: kill $DEV_PID → 3초 대기 → kill -9 $DEV_PID (응답 없으면)
809
+ - lsof -i :{port} -t 포트 점유 프로세스 확인 후 추가 정리
810
+ spawned child process만 대상 — 관련 없는 프로세스 kill 금지
811
+ - interrupt 시에도 cleanup 보장
812
+ ```
813
+
814
+ ### 3.5-4. 수정 루프
815
+
816
+ ```
817
+ 라운드 1~3:
818
+ 1. tsc → build → dev 순서로 체크
819
+ 2. 번째 실패 단계의 에러 수정
820
+ 3. 수정 해당 단계부터 재체크
821
+ 4. 모든 단계 통과: Phase 4 진행
822
+
823
+ 라운드 종료 조건:
824
+ - 3라운드 실패: 에러 목록 + 시도한 수정을 사용자에게 보고
825
+ - 같은 에러 반복: 해당 에러 스킵 불가 → 사용자 보고 (컴파일 에러는 스킵 불가)
826
+
827
+ 컴파일 게이트 결과 보고:
828
+
829
+ ✅ 통과:
830
+ "Phase 5: 컴파일 게이트 PASS (라운드 {N})"
831
+ - tsc: 0 errors
832
+ - build: success
833
+ - dev server: running on localhost:{port}
834
+
835
+ 실패 (3라운드 ):
836
+ "Phase 5: 컴파일 게이트 FAIL"
837
+ - 남은 에러 목록 (파일, 줄, 메시지)
838
+ - 시도한 수정 내역
839
+ - 사용자 수동 수정 필요
840
+ → Phase 4 진행하지 않음
841
+ ```
842
+
843
+ ---
844
+
845
+ ## Phase 6: 시각 검증 루프
846
+
847
+ **Puppeteer + CDP로 실제 렌더링 결과를 확인하며 자동 수정한다.**
848
+ **사람이 브라우저 보면서 고치는 것과 동일한 루프.**
849
+ **인프라: `src/infra/lib/browser/` (범용 UI 검증 도구)**
850
+
851
+ ```
852
+ 자동 반복: P1=0 때까지. 최대 3라운드.
853
+ ```
854
+
855
+ ### 4-0. 환경 준비
856
+
857
+ ```
858
+ 1. dev 서버 시작:
859
+ Phase 5에서 이미 시작된 dev 서버 사용 (재시작 불필요)
860
+ → localhost:{port} 확인
861
+
862
+ 2. Puppeteer 브라우저 시작:
863
+ import { launchBrowser, openPage } from 'src/infra/lib/browser'
864
+ const browser = await launchBrowser({ headless: true })
865
+ const page = await openPage(browser, 'http://localhost:3000/{feature}', {
866
+ width: 480, // 모바일 퍼스트 (또는 타겟 뷰포트)
867
+ height: 960,
868
+ })
869
+ ```
870
+
871
+ ### 4-1. 렌더링 스크린샷 vs Figma 스크린샷
872
+
873
+ ```
874
+ import { captureScreenshot, compareScreenshots } from 'src/infra/lib/browser'
875
+
876
+ 각 섹션에 대해:
877
+ 1. 렌더링 결과 스크린샷 캡처:
878
+ await captureScreenshot(page, {
879
+ outPath: '/tmp/{feature}/rendered-{section}.webp',
880
+ selector: '.{section}Section', // Phase 1에서 만든 클래스
881
+ })
882
+
883
+ 2. Figma 원본과 픽셀 비교:
884
+ const diff = await compareScreenshots(
885
+ '/tmp/{feature}/sections/{section}.webp', // Figma 원본
886
+ '/tmp/{feature}/rendered-{section}.webp', // 렌더링 결과
887
+ '/tmp/{feature}/diff-{section}.webp', // 차이 시각화
888
+ )
889
+
890
+ 3. diff 이미지를 Read로 확인:
891
+ 빨간색 영역 = 차이 나는 부분
892
+ diffRatio > 0.1 이면 P1 이슈
893
+ ```
894
+
895
+ ### 4-2. CSS 수치 정밀 비교
896
+
897
+ ```
898
+ import { getComputedStyles, compareStyles, diffsToIssues } from 'src/infra/lib/browser'
899
+
900
+ 섹션의 주요 요소에 대해:
901
+ 1. 렌더링된 computed CSS 추출:
902
+ const actual = await getComputedStyles(page, '.heroTitle', [
903
+ 'font-size', 'color', 'width', 'height', 'padding', 'margin',
904
+ 'background-color', 'border-radius', 'gap',
905
+ ])
906
+
907
+ 2. Figma tree.json의 기대값과 비교:
908
+ // tree.json에서 해당 노드의 CSS 수치 (vw/clamp 변환 후)
909
+ const expected = { 'font-size': '16px', 'color': '#ffffff', 'width': '465px' }
910
+ const diffs = compareStyles(expected, actual)
911
+
912
+ 3. 차이 이슈 변환:
913
+ const issues = diffsToIssues(diffs)
914
+ delta > 4px: P1 (레이아웃 영향)
915
+ delta ≤ 4px: P2 (미세 차이)
916
+ ```
917
+
918
+ ### 4-3. 이미지·텍스트 누락 체크
919
+
920
+ ```
921
+ import { extractImages, extractTextContent } from 'src/infra/lib/browser'
922
+
923
+ 1. 이미지 로드 상태 확인:
924
+ const images = await extractImages(page)
925
+ images.filter(img => !img.loaded)
926
+ → 로드 실패 이미지 = P1 (이미지 누락)
927
+ src="" 이미지 = P1 (빈 경로)
928
+
929
+ 2. 텍스트 콘텐츠 확인:
930
+ const texts = await extractTextContent(page)
931
+ tree.json의 TEXT 노드 characters와 대조
932
+ → 누락된 텍스트 = P1
933
+ ```
934
+
935
+ ### 4-4. 자동 수정 루프
936
+
937
+ ```
938
+ 라운드 1~3:
939
+ 1. 4-1 ~ 4-3 실행 → 이슈 목록 수집
940
+ 2. P1 이슈 우선 수정:
941
+ - 이미지 누락 이미지 경로 확인, static/ 에 파일 존재 확인
942
+ - 레이아웃 다름 스크린샷 diff 이미지 + computed CSS로 원인 파악
943
+ - 텍스트 누락 → tree.json의 정확한 텍스트 삽입
944
+ - CSS 수치 틀림 → tree.json(tree.json)의 정확한 값으로 교체
945
+ ⚠️ 추정으로 수정하지 않는다. 반드시 tree.json 참조.
946
+ 3. 수정 컴파일 재검증:
947
+ Bash: npx tsc --noEmit 2>&1 (또는 3.5-1에서 선택한 타입 체커)
948
+ 시각 수정이 타입 에러를 유발하면 즉시 타입 에러 수정 후 진행
949
+ 4. 페이지 리로드 → 다시 캡처 → 비교
950
+ 5. P1=0 이면 종료
951
+
952
+ 라운드 종료 조건:
953
+ - P1=0: 성공 브라우저 종료, 결과 보고
954
+ - 3라운드 후 P1 남음: TODO 목록으로 사용자에게 보고
955
+ - 같은 이슈가 반복: 해당 이슈 스킵, 다음 이슈로
956
+
957
+ 결과 보고:
958
+ - 수정한 파일 목록
959
+ - 남은 P2 이슈 목록 (선택적 수정)
960
+ - 최종 diff 스크린샷 경로
961
+ ```
962
+
963
+ ### 4-5. 반응형 검증 (추가 뷰포트)
964
+
965
+ ```
966
+ 모바일 검증 완료 후, 추가 브레이크포인트가 있으면:
967
+
968
+ await page.setViewport({ width: 1920, height: 1080 })
969
+ await page.reload({ waitUntil: 'networkidle0' })
970
+
971
+ → 데스크탑 Figma 스크린샷과 동일한 4-1 ~ 4-4 루프 반복
972
+ ```
973
+
974
+ ### 4-6. 브라우저 정리
975
+
976
+ ```
977
+ import { closeBrowser } from 'src/infra/lib/browser'
978
+
979
+ 검증 완료 후:
980
+ await closeBrowser()
981
+ dev 서버 종료 (필요 시)
982
+ ```