@su-record/vibe 3.0.0 → 3.2.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 (455) hide show
  1. package/CLAUDE.md +2 -2
  2. package/README.en.md +6 -4
  3. package/README.md +5 -3
  4. package/dist/__tests__/wiring-integrity.test.d.ts +2 -0
  5. package/dist/__tests__/wiring-integrity.test.d.ts.map +1 -0
  6. package/dist/__tests__/wiring-integrity.test.js +160 -0
  7. package/dist/__tests__/wiring-integrity.test.js.map +1 -0
  8. package/dist/cli/commands/info.d.ts.map +1 -1
  9. package/dist/cli/commands/info.js +2 -1
  10. package/dist/cli/commands/info.js.map +1 -1
  11. package/dist/cli/commands/init.d.ts.map +1 -1
  12. package/dist/cli/commands/init.js +4 -2
  13. package/dist/cli/commands/init.js.map +1 -1
  14. package/dist/cli/index.js +102 -128
  15. package/dist/cli/index.js.map +1 -1
  16. package/dist/cli/postinstall/claude-agents.d.ts.map +1 -1
  17. package/dist/cli/postinstall/claude-agents.js +0 -5
  18. package/dist/cli/postinstall/claude-agents.js.map +1 -1
  19. package/dist/cli/postinstall/constants.d.ts +6 -0
  20. package/dist/cli/postinstall/constants.d.ts.map +1 -1
  21. package/dist/cli/postinstall/constants.js +42 -60
  22. package/dist/cli/postinstall/constants.js.map +1 -1
  23. package/dist/cli/postinstall/inline-skills.js +2 -2
  24. package/dist/cli/postinstall/inline-skills.js.map +1 -1
  25. package/dist/cli/postinstall/main.d.ts.map +1 -1
  26. package/dist/cli/postinstall/main.js +2 -0
  27. package/dist/cli/postinstall/main.js.map +1 -1
  28. package/dist/cli/postinstall.d.ts +6 -1
  29. package/dist/cli/postinstall.d.ts.map +1 -1
  30. package/dist/cli/postinstall.js +6 -1
  31. package/dist/cli/postinstall.js.map +1 -1
  32. package/dist/cli/setup/GlobalInstaller.d.ts +1 -15
  33. package/dist/cli/setup/GlobalInstaller.d.ts.map +1 -1
  34. package/dist/cli/setup/GlobalInstaller.js +16 -115
  35. package/dist/cli/setup/GlobalInstaller.js.map +1 -1
  36. package/dist/cli/setup/GlobalInstaller.test.d.ts +2 -0
  37. package/dist/cli/setup/GlobalInstaller.test.d.ts.map +1 -0
  38. package/dist/cli/setup/GlobalInstaller.test.js +16 -0
  39. package/dist/cli/setup/GlobalInstaller.test.js.map +1 -0
  40. package/dist/cli/setup/ProjectSetup.js +2 -2
  41. package/dist/cli/setup/ProjectSetup.js.map +1 -1
  42. package/dist/cli/setup.d.ts +1 -1
  43. package/dist/cli/setup.d.ts.map +1 -1
  44. package/dist/cli/setup.js +1 -1
  45. package/dist/cli/setup.js.map +1 -1
  46. package/dist/infra/lib/SkillRepository.js +1 -1
  47. package/dist/infra/lib/evolution/__tests__/integration.test.js +0 -42
  48. package/dist/infra/lib/evolution/__tests__/integration.test.js.map +1 -1
  49. package/hooks/scripts/__tests__/.vibe/command-log.txt +3 -78
  50. package/hooks/scripts/__tests__/clone-behaviors.test.js +97 -1
  51. package/hooks/scripts/__tests__/clone-merge-responsive.test.js +106 -0
  52. package/hooks/scripts/__tests__/code-check-memory-write.test.js +81 -0
  53. package/hooks/scripts/__tests__/step-counter.test.js +21 -0
  54. package/hooks/scripts/auto-format.js +2 -11
  55. package/hooks/scripts/auto-test.js +2 -11
  56. package/hooks/scripts/clone-extract.js +388 -38
  57. package/hooks/scripts/clone-merge-responsive.js +184 -0
  58. package/hooks/scripts/clone-spec.js +33 -8
  59. package/hooks/scripts/clone-validate.js +15 -9
  60. package/hooks/scripts/code-check.js +27 -55
  61. package/hooks/scripts/lib/glob.js +32 -0
  62. package/hooks/scripts/lib/hook-context.js +19 -2
  63. package/hooks/scripts/post-edit.js +2 -3
  64. package/hooks/scripts/prompt-dispatcher.js +1 -1
  65. package/hooks/scripts/scope-guard.js +3 -42
  66. package/hooks/scripts/sentinel-guard.js +5 -20
  67. package/hooks/scripts/session-start.js +2 -2
  68. package/hooks/scripts/step-counter.js +35 -57
  69. package/package.json +6 -4
  70. package/skills/clone/SKILL.md +74 -203
  71. package/skills/clone/references/capture-rules.md +48 -0
  72. package/skills/clone/references/legal-and-error-recovery.md +40 -0
  73. package/skills/clone/references/refine-rules.md +61 -0
  74. package/skills/clone/references/scaffold-phases.md +59 -0
  75. package/skills/clone/references/setup-and-layout.md +30 -0
  76. package/skills/docs/SKILL.md +39 -4
  77. package/skills/docs/references/api-docs-changelog.md +34 -0
  78. package/skills/docs/references/codemaps-output.md +23 -0
  79. package/{agents/diagrammer.md → skills/docs/references/diagram-spec.md} +2 -15
  80. package/skills/exec-plan/SKILL.md +1 -1
  81. package/skills/exec-plan/templates/plan.md +1 -1
  82. package/skills/handoff/SKILL.md +3 -3
  83. package/skills/handoff/templates/handoff.md +1 -1
  84. package/skills/vibe/SKILL.md +3 -2
  85. package/skills/vibe.analyze/SKILL.md +12 -249
  86. package/skills/vibe.analyze/references/output-templates.md +188 -0
  87. package/skills/vibe.analyze/references/quality-gate.md +93 -0
  88. package/skills/vibe.clone/SKILL.md +52 -19
  89. package/skills/vibe.continue/SKILL.md +32 -0
  90. package/skills/vibe.design/SKILL.md +23 -1
  91. package/skills/vibe.design/references/ui-preview.md +20 -0
  92. package/skills/vibe.docs/SKILL.md +4 -2
  93. package/skills/vibe.figma/SKILL.md +33 -260
  94. package/skills/vibe.figma/references/branch-phases.md +113 -0
  95. package/skills/vibe.figma/references/state-schema.md +42 -0
  96. package/skills/vibe.figma/references/step-algorithms.md +204 -0
  97. package/skills/vibe.image/SKILL.md +62 -0
  98. package/skills/vibe.image/references/image-generation-examples.md +39 -0
  99. package/skills/vibe.reason/SKILL.md +3 -183
  100. package/skills/vibe.reason/references/output-format-template.md +57 -0
  101. package/skills/vibe.reason/references/quality-rubrics.md +94 -0
  102. package/skills/vibe.reason/references/worked-example.md +45 -0
  103. package/skills/vibe.review/SKILL.md +13 -348
  104. package/skills/vibe.review/references/boundary-check.md +25 -0
  105. package/skills/vibe.review/references/output-template.md +74 -0
  106. package/skills/vibe.review/references/quality-gate.md +84 -0
  107. package/skills/vibe.review/references/race-mode.md +117 -0
  108. package/skills/vibe.review/references/worked-examples.md +94 -0
  109. package/vibe/templates/claudemd-template.md +1 -1
  110. package/agents/acceptance-tester.md +0 -56
  111. package/agents/documenter.md +0 -43
  112. package/agents/figma/figma-engineer.md +0 -76
  113. package/dist/cli/llm/gemini-commands.d.ts +0 -25
  114. package/dist/cli/llm/gemini-commands.d.ts.map +0 -1
  115. package/dist/cli/llm/gemini-commands.js +0 -143
  116. package/dist/cli/llm/gemini-commands.js.map +0 -1
  117. package/dist/cli/postinstall/codex-agents.d.ts +0 -24
  118. package/dist/cli/postinstall/codex-agents.d.ts.map +0 -1
  119. package/dist/cli/postinstall/codex-agents.js +0 -114
  120. package/dist/cli/postinstall/codex-agents.js.map +0 -1
  121. package/dist/cli/postinstall/codex-instruction.d.ts +0 -10
  122. package/dist/cli/postinstall/codex-instruction.d.ts.map +0 -1
  123. package/dist/cli/postinstall/codex-instruction.js +0 -56
  124. package/dist/cli/postinstall/codex-instruction.js.map +0 -1
  125. package/dist/cli/postinstall/gemini-agents.d.ts +0 -12
  126. package/dist/cli/postinstall/gemini-agents.d.ts.map +0 -1
  127. package/dist/cli/postinstall/gemini-agents.js +0 -80
  128. package/dist/cli/postinstall/gemini-agents.js.map +0 -1
  129. package/dist/cli/postinstall/gemini-instruction.d.ts +0 -10
  130. package/dist/cli/postinstall/gemini-instruction.d.ts.map +0 -1
  131. package/dist/cli/postinstall/gemini-instruction.js +0 -59
  132. package/dist/cli/postinstall/gemini-instruction.js.map +0 -1
  133. package/dist/cli/postinstall/index.d.ts +0 -23
  134. package/dist/cli/postinstall/index.d.ts.map +0 -1
  135. package/dist/cli/postinstall/index.js +0 -23
  136. package/dist/cli/postinstall/index.js.map +0 -1
  137. package/dist/cli/setup/index.d.ts +0 -9
  138. package/dist/cli/setup/index.d.ts.map +0 -1
  139. package/dist/cli/setup/index.js +0 -12
  140. package/dist/cli/setup/index.js.map +0 -1
  141. package/dist/infra/lib/ContextCompressor.d.ts +0 -104
  142. package/dist/infra/lib/ContextCompressor.d.ts.map +0 -1
  143. package/dist/infra/lib/ContextCompressor.js +0 -297
  144. package/dist/infra/lib/ContextCompressor.js.map +0 -1
  145. package/dist/infra/lib/ContextCompressor.test.d.ts +0 -2
  146. package/dist/infra/lib/ContextCompressor.test.d.ts.map +0 -1
  147. package/dist/infra/lib/ContextCompressor.test.js +0 -25
  148. package/dist/infra/lib/ContextCompressor.test.js.map +0 -1
  149. package/dist/infra/lib/ProgressTracker.d.ts +0 -73
  150. package/dist/infra/lib/ProgressTracker.d.ts.map +0 -1
  151. package/dist/infra/lib/ProgressTracker.js +0 -267
  152. package/dist/infra/lib/ProgressTracker.js.map +0 -1
  153. package/dist/infra/lib/TokenBudgetTracker.d.ts +0 -68
  154. package/dist/infra/lib/TokenBudgetTracker.d.ts.map +0 -1
  155. package/dist/infra/lib/TokenBudgetTracker.js +0 -191
  156. package/dist/infra/lib/TokenBudgetTracker.js.map +0 -1
  157. package/dist/infra/lib/autonomy/AuditStore.d.ts +0 -63
  158. package/dist/infra/lib/autonomy/AuditStore.d.ts.map +0 -1
  159. package/dist/infra/lib/autonomy/AuditStore.js +0 -185
  160. package/dist/infra/lib/autonomy/AuditStore.js.map +0 -1
  161. package/dist/infra/lib/autonomy/AutonomyConfig.d.ts +0 -84
  162. package/dist/infra/lib/autonomy/AutonomyConfig.d.ts.map +0 -1
  163. package/dist/infra/lib/autonomy/AutonomyConfig.js +0 -49
  164. package/dist/infra/lib/autonomy/AutonomyConfig.js.map +0 -1
  165. package/dist/infra/lib/autonomy/AutonomyOrchestrator.d.ts +0 -78
  166. package/dist/infra/lib/autonomy/AutonomyOrchestrator.d.ts.map +0 -1
  167. package/dist/infra/lib/autonomy/AutonomyOrchestrator.js +0 -246
  168. package/dist/infra/lib/autonomy/AutonomyOrchestrator.js.map +0 -1
  169. package/dist/infra/lib/autonomy/BackgroundMonitor.d.ts +0 -36
  170. package/dist/infra/lib/autonomy/BackgroundMonitor.d.ts.map +0 -1
  171. package/dist/infra/lib/autonomy/BackgroundMonitor.js +0 -138
  172. package/dist/infra/lib/autonomy/BackgroundMonitor.js.map +0 -1
  173. package/dist/infra/lib/autonomy/CollaborationProtocol.d.ts +0 -56
  174. package/dist/infra/lib/autonomy/CollaborationProtocol.d.ts.map +0 -1
  175. package/dist/infra/lib/autonomy/CollaborationProtocol.js +0 -122
  176. package/dist/infra/lib/autonomy/CollaborationProtocol.js.map +0 -1
  177. package/dist/infra/lib/autonomy/ConfirmationManager.d.ts +0 -42
  178. package/dist/infra/lib/autonomy/ConfirmationManager.d.ts.map +0 -1
  179. package/dist/infra/lib/autonomy/ConfirmationManager.js +0 -200
  180. package/dist/infra/lib/autonomy/ConfirmationManager.js.map +0 -1
  181. package/dist/infra/lib/autonomy/ConfirmationStore.d.ts +0 -55
  182. package/dist/infra/lib/autonomy/ConfirmationStore.d.ts.map +0 -1
  183. package/dist/infra/lib/autonomy/ConfirmationStore.js +0 -130
  184. package/dist/infra/lib/autonomy/ConfirmationStore.js.map +0 -1
  185. package/dist/infra/lib/autonomy/EventBus.d.ts +0 -20
  186. package/dist/infra/lib/autonomy/EventBus.d.ts.map +0 -1
  187. package/dist/infra/lib/autonomy/EventBus.js +0 -119
  188. package/dist/infra/lib/autonomy/EventBus.js.map +0 -1
  189. package/dist/infra/lib/autonomy/EventOutbox.d.ts +0 -32
  190. package/dist/infra/lib/autonomy/EventOutbox.d.ts.map +0 -1
  191. package/dist/infra/lib/autonomy/EventOutbox.js +0 -152
  192. package/dist/infra/lib/autonomy/EventOutbox.js.map +0 -1
  193. package/dist/infra/lib/autonomy/NotificationDispatcher.d.ts +0 -24
  194. package/dist/infra/lib/autonomy/NotificationDispatcher.d.ts.map +0 -1
  195. package/dist/infra/lib/autonomy/NotificationDispatcher.js +0 -112
  196. package/dist/infra/lib/autonomy/NotificationDispatcher.js.map +0 -1
  197. package/dist/infra/lib/autonomy/PolicyEngine.d.ts +0 -76
  198. package/dist/infra/lib/autonomy/PolicyEngine.d.ts.map +0 -1
  199. package/dist/infra/lib/autonomy/PolicyEngine.js +0 -208
  200. package/dist/infra/lib/autonomy/PolicyEngine.js.map +0 -1
  201. package/dist/infra/lib/autonomy/ProactiveAnalyzer.d.ts +0 -61
  202. package/dist/infra/lib/autonomy/ProactiveAnalyzer.d.ts.map +0 -1
  203. package/dist/infra/lib/autonomy/ProactiveAnalyzer.js +0 -236
  204. package/dist/infra/lib/autonomy/ProactiveAnalyzer.js.map +0 -1
  205. package/dist/infra/lib/autonomy/RiskClassifier.d.ts +0 -35
  206. package/dist/infra/lib/autonomy/RiskClassifier.d.ts.map +0 -1
  207. package/dist/infra/lib/autonomy/RiskClassifier.js +0 -147
  208. package/dist/infra/lib/autonomy/RiskClassifier.js.map +0 -1
  209. package/dist/infra/lib/autonomy/SecuritySentinel.d.ts +0 -51
  210. package/dist/infra/lib/autonomy/SecuritySentinel.d.ts.map +0 -1
  211. package/dist/infra/lib/autonomy/SecuritySentinel.js +0 -162
  212. package/dist/infra/lib/autonomy/SecuritySentinel.js.map +0 -1
  213. package/dist/infra/lib/autonomy/SuggestionStore.d.ts +0 -54
  214. package/dist/infra/lib/autonomy/SuggestionStore.d.ts.map +0 -1
  215. package/dist/infra/lib/autonomy/SuggestionStore.js +0 -144
  216. package/dist/infra/lib/autonomy/SuggestionStore.js.map +0 -1
  217. package/dist/infra/lib/autonomy/TaskDecomposer.d.ts +0 -38
  218. package/dist/infra/lib/autonomy/TaskDecomposer.d.ts.map +0 -1
  219. package/dist/infra/lib/autonomy/TaskDecomposer.js +0 -175
  220. package/dist/infra/lib/autonomy/TaskDecomposer.js.map +0 -1
  221. package/dist/infra/lib/autonomy/__tests__/audit-store.test.d.ts +0 -2
  222. package/dist/infra/lib/autonomy/__tests__/audit-store.test.d.ts.map +0 -1
  223. package/dist/infra/lib/autonomy/__tests__/audit-store.test.js +0 -198
  224. package/dist/infra/lib/autonomy/__tests__/audit-store.test.js.map +0 -1
  225. package/dist/infra/lib/autonomy/__tests__/event-bus.test.d.ts +0 -2
  226. package/dist/infra/lib/autonomy/__tests__/event-bus.test.d.ts.map +0 -1
  227. package/dist/infra/lib/autonomy/__tests__/event-bus.test.js +0 -225
  228. package/dist/infra/lib/autonomy/__tests__/event-bus.test.js.map +0 -1
  229. package/dist/infra/lib/autonomy/__tests__/event-core.test.d.ts +0 -2
  230. package/dist/infra/lib/autonomy/__tests__/event-core.test.d.ts.map +0 -1
  231. package/dist/infra/lib/autonomy/__tests__/event-core.test.js +0 -194
  232. package/dist/infra/lib/autonomy/__tests__/event-core.test.js.map +0 -1
  233. package/dist/infra/lib/autonomy/__tests__/governance.test.d.ts +0 -2
  234. package/dist/infra/lib/autonomy/__tests__/governance.test.d.ts.map +0 -1
  235. package/dist/infra/lib/autonomy/__tests__/governance.test.js +0 -540
  236. package/dist/infra/lib/autonomy/__tests__/governance.test.js.map +0 -1
  237. package/dist/infra/lib/autonomy/__tests__/integration.test.d.ts +0 -2
  238. package/dist/infra/lib/autonomy/__tests__/integration.test.d.ts.map +0 -1
  239. package/dist/infra/lib/autonomy/__tests__/integration.test.js +0 -480
  240. package/dist/infra/lib/autonomy/__tests__/integration.test.js.map +0 -1
  241. package/dist/infra/lib/autonomy/__tests__/proactive.test.d.ts +0 -2
  242. package/dist/infra/lib/autonomy/__tests__/proactive.test.d.ts.map +0 -1
  243. package/dist/infra/lib/autonomy/__tests__/proactive.test.js +0 -410
  244. package/dist/infra/lib/autonomy/__tests__/proactive.test.js.map +0 -1
  245. package/dist/infra/lib/autonomy/__tests__/sentinel.test.d.ts +0 -2
  246. package/dist/infra/lib/autonomy/__tests__/sentinel.test.d.ts.map +0 -1
  247. package/dist/infra/lib/autonomy/__tests__/sentinel.test.js +0 -486
  248. package/dist/infra/lib/autonomy/__tests__/sentinel.test.js.map +0 -1
  249. package/dist/infra/lib/autonomy/index.d.ts +0 -18
  250. package/dist/infra/lib/autonomy/index.d.ts.map +0 -1
  251. package/dist/infra/lib/autonomy/index.js +0 -22
  252. package/dist/infra/lib/autonomy/index.js.map +0 -1
  253. package/dist/infra/lib/autonomy/schemas.d.ts +0 -317
  254. package/dist/infra/lib/autonomy/schemas.d.ts.map +0 -1
  255. package/dist/infra/lib/autonomy/schemas.js +0 -90
  256. package/dist/infra/lib/autonomy/schemas.js.map +0 -1
  257. package/dist/infra/lib/claude/index.d.ts +0 -5
  258. package/dist/infra/lib/claude/index.d.ts.map +0 -1
  259. package/dist/infra/lib/claude/index.js +0 -5
  260. package/dist/infra/lib/claude/index.js.map +0 -1
  261. package/dist/infra/lib/claude/storage.d.ts +0 -12
  262. package/dist/infra/lib/claude/storage.d.ts.map +0 -1
  263. package/dist/infra/lib/claude/storage.js +0 -54
  264. package/dist/infra/lib/claude/storage.js.map +0 -1
  265. package/dist/infra/lib/gemini/auth.d.ts +0 -18
  266. package/dist/infra/lib/gemini/auth.d.ts.map +0 -1
  267. package/dist/infra/lib/gemini/auth.js +0 -32
  268. package/dist/infra/lib/gemini/auth.js.map +0 -1
  269. package/dist/infra/lib/gemini/capabilities.d.ts +0 -28
  270. package/dist/infra/lib/gemini/capabilities.d.ts.map +0 -1
  271. package/dist/infra/lib/gemini/capabilities.js +0 -178
  272. package/dist/infra/lib/gemini/capabilities.js.map +0 -1
  273. package/dist/infra/lib/gemini/chat.d.ts +0 -35
  274. package/dist/infra/lib/gemini/chat.d.ts.map +0 -1
  275. package/dist/infra/lib/gemini/chat.js +0 -161
  276. package/dist/infra/lib/gemini/chat.js.map +0 -1
  277. package/dist/infra/lib/gemini/completion.d.ts +0 -12
  278. package/dist/infra/lib/gemini/completion.d.ts.map +0 -1
  279. package/dist/infra/lib/gemini/completion.js +0 -13
  280. package/dist/infra/lib/gemini/completion.js.map +0 -1
  281. package/dist/infra/lib/gemini/constants.d.ts +0 -8
  282. package/dist/infra/lib/gemini/constants.d.ts.map +0 -1
  283. package/dist/infra/lib/gemini/constants.js +0 -11
  284. package/dist/infra/lib/gemini/constants.js.map +0 -1
  285. package/dist/infra/lib/gemini/index.d.ts +0 -13
  286. package/dist/infra/lib/gemini/index.d.ts.map +0 -1
  287. package/dist/infra/lib/gemini/index.js +0 -12
  288. package/dist/infra/lib/gemini/index.js.map +0 -1
  289. package/dist/infra/lib/gemini/models.d.ts +0 -11
  290. package/dist/infra/lib/gemini/models.d.ts.map +0 -1
  291. package/dist/infra/lib/gemini/models.js +0 -38
  292. package/dist/infra/lib/gemini/models.js.map +0 -1
  293. package/dist/infra/lib/gemini/orchestration.d.ts +0 -33
  294. package/dist/infra/lib/gemini/orchestration.d.ts.map +0 -1
  295. package/dist/infra/lib/gemini/orchestration.js +0 -62
  296. package/dist/infra/lib/gemini/orchestration.js.map +0 -1
  297. package/dist/infra/lib/gemini/types.d.ts +0 -115
  298. package/dist/infra/lib/gemini/types.d.ts.map +0 -1
  299. package/dist/infra/lib/gemini/types.js +0 -5
  300. package/dist/infra/lib/gemini/types.js.map +0 -1
  301. package/dist/infra/orchestrator/AgentAnnouncer.d.ts +0 -64
  302. package/dist/infra/orchestrator/AgentAnnouncer.d.ts.map +0 -1
  303. package/dist/infra/orchestrator/AgentAnnouncer.js +0 -127
  304. package/dist/infra/orchestrator/AgentAnnouncer.js.map +0 -1
  305. package/dist/infra/orchestrator/AgentAnnouncer.test.d.ts +0 -5
  306. package/dist/infra/orchestrator/AgentAnnouncer.test.d.ts.map +0 -1
  307. package/dist/infra/orchestrator/AgentAnnouncer.test.js +0 -119
  308. package/dist/infra/orchestrator/AgentAnnouncer.test.js.map +0 -1
  309. package/dist/infra/orchestrator/AgentExecutor.d.ts +0 -22
  310. package/dist/infra/orchestrator/AgentExecutor.d.ts.map +0 -1
  311. package/dist/infra/orchestrator/AgentExecutor.js +0 -272
  312. package/dist/infra/orchestrator/AgentExecutor.js.map +0 -1
  313. package/dist/infra/orchestrator/AgentManager.d.ts +0 -72
  314. package/dist/infra/orchestrator/AgentManager.d.ts.map +0 -1
  315. package/dist/infra/orchestrator/AgentManager.js +0 -183
  316. package/dist/infra/orchestrator/AgentManager.js.map +0 -1
  317. package/dist/infra/orchestrator/AgentManifestCache.d.ts +0 -54
  318. package/dist/infra/orchestrator/AgentManifestCache.d.ts.map +0 -1
  319. package/dist/infra/orchestrator/AgentManifestCache.js +0 -191
  320. package/dist/infra/orchestrator/AgentManifestCache.js.map +0 -1
  321. package/dist/infra/orchestrator/AgentRegistry.d.ts +0 -76
  322. package/dist/infra/orchestrator/AgentRegistry.d.ts.map +0 -1
  323. package/dist/infra/orchestrator/AgentRegistry.js +0 -217
  324. package/dist/infra/orchestrator/AgentRegistry.js.map +0 -1
  325. package/dist/infra/orchestrator/AgentRegistry.test.d.ts +0 -5
  326. package/dist/infra/orchestrator/AgentRegistry.test.d.ts.map +0 -1
  327. package/dist/infra/orchestrator/AgentRegistry.test.js +0 -122
  328. package/dist/infra/orchestrator/AgentRegistry.test.js.map +0 -1
  329. package/dist/infra/orchestrator/BackgroundManager.d.ts +0 -128
  330. package/dist/infra/orchestrator/BackgroundManager.d.ts.map +0 -1
  331. package/dist/infra/orchestrator/BackgroundManager.js +0 -620
  332. package/dist/infra/orchestrator/BackgroundManager.js.map +0 -1
  333. package/dist/infra/orchestrator/BackgroundManager.test.d.ts +0 -6
  334. package/dist/infra/orchestrator/BackgroundManager.test.d.ts.map +0 -1
  335. package/dist/infra/orchestrator/BackgroundManager.test.js +0 -162
  336. package/dist/infra/orchestrator/BackgroundManager.test.js.map +0 -1
  337. package/dist/infra/orchestrator/CheckpointManager.d.ts +0 -54
  338. package/dist/infra/orchestrator/CheckpointManager.d.ts.map +0 -1
  339. package/dist/infra/orchestrator/CheckpointManager.js +0 -121
  340. package/dist/infra/orchestrator/CheckpointManager.js.map +0 -1
  341. package/dist/infra/orchestrator/CodexAgentRuntime.d.ts +0 -12
  342. package/dist/infra/orchestrator/CodexAgentRuntime.d.ts.map +0 -1
  343. package/dist/infra/orchestrator/CodexAgentRuntime.js +0 -94
  344. package/dist/infra/orchestrator/CodexAgentRuntime.js.map +0 -1
  345. package/dist/infra/orchestrator/CodexAgentRuntime.test.d.ts +0 -2
  346. package/dist/infra/orchestrator/CodexAgentRuntime.test.d.ts.map +0 -1
  347. package/dist/infra/orchestrator/CodexAgentRuntime.test.js +0 -37
  348. package/dist/infra/orchestrator/CodexAgentRuntime.test.js.map +0 -1
  349. package/dist/infra/orchestrator/LLMCluster.d.ts +0 -82
  350. package/dist/infra/orchestrator/LLMCluster.d.ts.map +0 -1
  351. package/dist/infra/orchestrator/LLMCluster.js +0 -146
  352. package/dist/infra/orchestrator/LLMCluster.js.map +0 -1
  353. package/dist/infra/orchestrator/MultiLlmResearch.d.ts +0 -31
  354. package/dist/infra/orchestrator/MultiLlmResearch.d.ts.map +0 -1
  355. package/dist/infra/orchestrator/MultiLlmResearch.js +0 -160
  356. package/dist/infra/orchestrator/MultiLlmResearch.js.map +0 -1
  357. package/dist/infra/orchestrator/PhasePipeline.d.ts +0 -122
  358. package/dist/infra/orchestrator/PhasePipeline.d.ts.map +0 -1
  359. package/dist/infra/orchestrator/PhasePipeline.js +0 -385
  360. package/dist/infra/orchestrator/PhasePipeline.js.map +0 -1
  361. package/dist/infra/orchestrator/PhaseResultStore.d.ts +0 -39
  362. package/dist/infra/orchestrator/PhaseResultStore.d.ts.map +0 -1
  363. package/dist/infra/orchestrator/PhaseResultStore.js +0 -151
  364. package/dist/infra/orchestrator/PhaseResultStore.js.map +0 -1
  365. package/dist/infra/orchestrator/SessionStore.d.ts +0 -40
  366. package/dist/infra/orchestrator/SessionStore.d.ts.map +0 -1
  367. package/dist/infra/orchestrator/SessionStore.js +0 -116
  368. package/dist/infra/orchestrator/SessionStore.js.map +0 -1
  369. package/dist/infra/orchestrator/SmartRouter.d.ts +0 -90
  370. package/dist/infra/orchestrator/SmartRouter.d.ts.map +0 -1
  371. package/dist/infra/orchestrator/SmartRouter.js +0 -277
  372. package/dist/infra/orchestrator/SmartRouter.js.map +0 -1
  373. package/dist/infra/orchestrator/SmartRouter.test.d.ts +0 -5
  374. package/dist/infra/orchestrator/SmartRouter.test.d.ts.map +0 -1
  375. package/dist/infra/orchestrator/SmartRouter.test.js +0 -484
  376. package/dist/infra/orchestrator/SmartRouter.test.js.map +0 -1
  377. package/dist/infra/orchestrator/SwarmOrchestrator.d.ts +0 -143
  378. package/dist/infra/orchestrator/SwarmOrchestrator.d.ts.map +0 -1
  379. package/dist/infra/orchestrator/SwarmOrchestrator.js +0 -378
  380. package/dist/infra/orchestrator/SwarmOrchestrator.js.map +0 -1
  381. package/dist/infra/orchestrator/SwarmOrchestrator.test.d.ts +0 -5
  382. package/dist/infra/orchestrator/SwarmOrchestrator.test.d.ts.map +0 -1
  383. package/dist/infra/orchestrator/SwarmOrchestrator.test.js +0 -95
  384. package/dist/infra/orchestrator/SwarmOrchestrator.test.js.map +0 -1
  385. package/dist/infra/orchestrator/agentDiscovery.d.ts +0 -26
  386. package/dist/infra/orchestrator/agentDiscovery.d.ts.map +0 -1
  387. package/dist/infra/orchestrator/agentDiscovery.js +0 -175
  388. package/dist/infra/orchestrator/agentDiscovery.js.map +0 -1
  389. package/dist/infra/orchestrator/backgroundAgent.d.ts +0 -9
  390. package/dist/infra/orchestrator/backgroundAgent.d.ts.map +0 -1
  391. package/dist/infra/orchestrator/backgroundAgent.js +0 -10
  392. package/dist/infra/orchestrator/backgroundAgent.js.map +0 -1
  393. package/dist/infra/orchestrator/index.d.ts +0 -207
  394. package/dist/infra/orchestrator/index.d.ts.map +0 -1
  395. package/dist/infra/orchestrator/index.js +0 -362
  396. package/dist/infra/orchestrator/index.js.map +0 -1
  397. package/dist/infra/orchestrator/orchestrator.d.ts +0 -60
  398. package/dist/infra/orchestrator/orchestrator.d.ts.map +0 -1
  399. package/dist/infra/orchestrator/orchestrator.js +0 -214
  400. package/dist/infra/orchestrator/orchestrator.js.map +0 -1
  401. package/dist/infra/orchestrator/parallelResearch.d.ts +0 -27
  402. package/dist/infra/orchestrator/parallelResearch.d.ts.map +0 -1
  403. package/dist/infra/orchestrator/parallelResearch.js +0 -285
  404. package/dist/infra/orchestrator/parallelResearch.js.map +0 -1
  405. package/dist/infra/orchestrator/types.d.ts +0 -205
  406. package/dist/infra/orchestrator/types.d.ts.map +0 -1
  407. package/dist/infra/orchestrator/types.js +0 -87
  408. package/dist/infra/orchestrator/types.js.map +0 -1
  409. package/dist/infra/orchestrator/types.test.d.ts +0 -2
  410. package/dist/infra/orchestrator/types.test.d.ts.map +0 -1
  411. package/dist/infra/orchestrator/types.test.js +0 -57
  412. package/dist/infra/orchestrator/types.test.js.map +0 -1
  413. package/dist/tools/semantic/analyzeDependencyGraph.d.ts +0 -12
  414. package/dist/tools/semantic/analyzeDependencyGraph.d.ts.map +0 -1
  415. package/dist/tools/semantic/analyzeDependencyGraph.js +0 -359
  416. package/dist/tools/semantic/analyzeDependencyGraph.js.map +0 -1
  417. package/dist/tools/semantic/astGrep.d.ts +0 -25
  418. package/dist/tools/semantic/astGrep.d.ts.map +0 -1
  419. package/dist/tools/semantic/astGrep.js +0 -324
  420. package/dist/tools/semantic/astGrep.js.map +0 -1
  421. package/dist/tools/semantic/astGrep.test.d.ts +0 -2
  422. package/dist/tools/semantic/astGrep.test.d.ts.map +0 -1
  423. package/dist/tools/semantic/astGrep.test.js +0 -74
  424. package/dist/tools/semantic/astGrep.test.js.map +0 -1
  425. package/dist/tools/semantic/findReferences.d.ts +0 -9
  426. package/dist/tools/semantic/findReferences.d.ts.map +0 -1
  427. package/dist/tools/semantic/findReferences.js +0 -200
  428. package/dist/tools/semantic/findReferences.js.map +0 -1
  429. package/dist/tools/semantic/findSymbol.d.ts +0 -8
  430. package/dist/tools/semantic/findSymbol.d.ts.map +0 -1
  431. package/dist/tools/semantic/findSymbol.js +0 -204
  432. package/dist/tools/semantic/findSymbol.js.map +0 -1
  433. package/dist/tools/semantic/index.d.ts +0 -9
  434. package/dist/tools/semantic/index.d.ts.map +0 -1
  435. package/dist/tools/semantic/index.js +0 -11
  436. package/dist/tools/semantic/index.js.map +0 -1
  437. package/dist/tools/semantic/lsp.d.ts +0 -68
  438. package/dist/tools/semantic/lsp.d.ts.map +0 -1
  439. package/dist/tools/semantic/lsp.js +0 -561
  440. package/dist/tools/semantic/lsp.js.map +0 -1
  441. package/dist/tools/spec/e2eTestGenerator.d.ts +0 -61
  442. package/dist/tools/spec/e2eTestGenerator.d.ts.map +0 -1
  443. package/dist/tools/spec/e2eTestGenerator.js +0 -255
  444. package/dist/tools/spec/e2eTestGenerator.js.map +0 -1
  445. package/dist/tools/spec/specVersioning.d.ts +0 -76
  446. package/dist/tools/spec/specVersioning.d.ts.map +0 -1
  447. package/dist/tools/spec/specVersioning.js +0 -236
  448. package/dist/tools/spec/specVersioning.js.map +0 -1
  449. package/hooks/scripts/__tests__/.vibe/memories/memories.db +0 -0
  450. package/hooks/scripts/__tests__/.vibe/memories/memories.db-shm +0 -0
  451. package/hooks/scripts/__tests__/.vibe/memories/memories.db-wal +0 -0
  452. package/hooks/scripts/evolution-engine.js +0 -91
  453. package/hooks/scripts/hud-status.js +0 -321
  454. package/hooks/scripts/skill-injector.js +0 -83
  455. package/skills/vibe.utils/SKILL.md +0 -415
@@ -78,6 +78,11 @@ const CSS_PROPS = [
78
78
  'mask-image', 'mask-size', 'mask-position', 'clip-path',
79
79
  ];
80
80
 
81
+ const SUB_URL_LIMIT = 200;
82
+ const SUB_EXCLUDE_TEXT_RE = /^(?:검색|search|top|home|kor|eng|chn|vtn|language|언어|개인정보|privacy|문의|제안|sitemap|사이트맵|youtube|뉴스룸|newsroom|cookie|닫기|partner|파트너)$/i;
83
+ const SUB_EXCLUDE_PATH_RE = /\/(?:search|sitemap|privacy|contact|inquiry|cookie|login|auth|policy)(?:\/|$)/i;
84
+ const SUB_EXCLUDE_EXT_RE = /\.(?:pdf|zip|jpe?g|png|gif|webp|svg|mp4|mov|avi|docx?|xlsx?|pptx?)$/i;
85
+
81
86
  // ─── CLI parse ──────────────────────────────────────────────────────
82
87
  function parseArgs(argv) {
83
88
  const [, , cmd, urlArg, ...rest] = argv;
@@ -104,6 +109,74 @@ function parseViewport(v) {
104
109
  };
105
110
  }
106
111
 
112
+ function localePrefixOf(rawUrl) {
113
+ const first = new URL(rawUrl).pathname.split('/').filter(Boolean)[0];
114
+ if (!first || !/^[a-z]{2,3}(?:-[a-z]{2})?$/i.test(first)) return null;
115
+ return `/${first}`;
116
+ }
117
+
118
+ function normalizeSubUrl(startUrl, href) {
119
+ if (!href || typeof href !== 'string') return null;
120
+ try {
121
+ const target = new URL(href, startUrl);
122
+ if (target.protocol !== 'http:' && target.protocol !== 'https:') return null;
123
+ target.hash = '';
124
+ target.search = '';
125
+ target.pathname = target.pathname.replace(/\/+$/, '') || '/';
126
+ return target;
127
+ } catch {
128
+ return null;
129
+ }
130
+ }
131
+
132
+ function isSameMenuScope(target, start, localePrefix) {
133
+ if (target.origin !== start.origin) return false;
134
+ if (!localePrefix) return true;
135
+ return target.pathname === localePrefix || target.pathname.startsWith(`${localePrefix}/`);
136
+ }
137
+
138
+ function isExcludedSubLink(target, text) {
139
+ const label = String(text || '').trim();
140
+ if (SUB_EXCLUDE_TEXT_RE.test(label)) return true;
141
+ if (SUB_EXCLUDE_PATH_RE.test(target.pathname)) return true;
142
+ return SUB_EXCLUDE_EXT_RE.test(target.pathname);
143
+ }
144
+
145
+ function collectSubUrls(startUrl, links, limit = SUB_URL_LIMIT) {
146
+ const start = normalizeSubUrl(startUrl, startUrl);
147
+ if (!start) return [];
148
+ const localePrefix = localePrefixOf(start.href);
149
+ const urls = [start.href];
150
+ const seen = new Set(urls);
151
+
152
+ for (const link of links) {
153
+ if (urls.length >= limit) break;
154
+ const target = normalizeSubUrl(start.href, link.href);
155
+ if (!target || seen.has(target.href)) continue;
156
+ if (!isSameMenuScope(target, start, localePrefix)) continue;
157
+ if (isExcludedSubLink(target, link.text)) continue;
158
+ seen.add(target.href);
159
+ urls.push(target.href);
160
+ }
161
+
162
+ return urls;
163
+ }
164
+
165
+ function findSitemapUrl(startUrl, links) {
166
+ const start = normalizeSubUrl(startUrl, startUrl);
167
+ if (!start) return null;
168
+ const localePrefix = localePrefixOf(start.href);
169
+
170
+ for (const link of links) {
171
+ const label = String(link.text || '').trim();
172
+ if (!/sitemap|사이트맵/i.test(`${label} ${link.href}`)) continue;
173
+ const target = normalizeSubUrl(start.href, link.href);
174
+ if (target && isSameMenuScope(target, start, localePrefix)) return target.href;
175
+ }
176
+
177
+ return null;
178
+ }
179
+
107
180
  // ─── Puppeteer dynamic loader (optional dep) ────────────────────────
108
181
  async function loadPuppeteer() {
109
182
  try {
@@ -650,34 +723,139 @@ const TAB_CONTENT_FP = `(function (g) {
650
723
  return (root.innerText || '').replace(/\\s+/g, ' ').trim().slice(0, 4000);
651
724
  })`;
652
725
 
653
- const wait = (ms) => new Promise((r) => setTimeout(r, ms));
726
+ // Hover diff props 색/그림자/변형 호버에서 실제로 바뀌는 것들
727
+ const HOVER_PROPS = [
728
+ 'color', 'background-color', 'border-color', 'box-shadow',
729
+ 'transform', 'opacity', 'text-decoration-line', 'filter', 'outline-width',
730
+ ];
654
731
 
655
- async function runInteractionSweep(page) {
656
- const behaviors = { scroll: [], interactive: [] };
732
+ // In-view 등장 애니메이션 diff props
733
+ const INVIEW_PROPS = ['opacity', 'transform', 'visibility', 'filter', 'clip-path'];
657
734
 
658
- // ── Scroll-triggered state (header/nav shrink, background, shadow on scroll) ──
659
- const candidates = await page.evaluate(`(${TAG_SCROLL_CANDIDATES})()`);
660
- if (candidates.length) {
661
- const before = await page.evaluate(`(${SNAP_PROBES})(${JSON.stringify(BEHAVIOR_PROPS)})`);
662
- const innerH = await page.evaluate('window.innerHeight');
663
- const triggerY = Math.min(700, Math.max(200, Math.round(innerH * 0.9)));
664
- await page.evaluate(`window.scrollTo(0, ${triggerY})`);
665
- await wait(500);
666
- const after = await page.evaluate(`(${SNAP_PROBES})(${JSON.stringify(BEHAVIOR_PROPS)})`);
667
- await page.evaluate('window.scrollTo(0, 0)');
668
- await wait(300);
669
- for (const c of candidates) {
670
- const changed = diffStyles(before[c.probe], after[c.probe]);
671
- if (Object.keys(changed).length) {
672
- behaviors.scroll.push({
673
- label: c.cls ? `${c.tag}.${c.cls}` : c.tag,
674
- tag: c.tag, cls: c.cls, triggerScrollY: triggerY, changed,
675
- });
735
+ // In-page: tag hover candidates. 같은 시그니처(tag+첫 클래스)는 1개만 샘플 nav 링크 30개 → 1개.
736
+ const TAG_HOVER_CANDIDATES = `(function () {
737
+ const els = Array.from(document.querySelectorAll('a, button, [role="button"], [class*="btn" i], [class*="card" i]'));
738
+ const seen = new Set(); const out = []; let i = 0;
739
+ for (const el of els) {
740
+ if (i >= 30) break;
741
+ const r = el.getBoundingClientRect();
742
+ if (r.width < 8 || r.height < 8) continue;
743
+ const cls = (el.getAttribute('class') || '').trim().split(/\\s+/).filter(Boolean)[0] || '';
744
+ const sig = el.tagName + '.' + cls;
745
+ if (seen.has(sig)) continue;
746
+ seen.add(sig);
747
+ el.setAttribute('data-clone-hover', 'h' + i);
748
+ out.push({ probe: 'h' + i, tag: el.tagName.toLowerCase(), cls, transition: getComputedStyle(el).transition });
749
+ i++;
750
+ }
751
+ return out;
752
+ })`;
753
+
754
+ // In-page: snapshot computed props of all elements tagged with an attribute.
755
+ const SNAP_ATTR = `(function (attr, props) {
756
+ const out = {};
757
+ document.querySelectorAll('[' + attr + ']').forEach((el) => {
758
+ const cs = getComputedStyle(el); const o = {};
759
+ for (const p of props) { const v = cs.getPropertyValue(p); if (v) o[p] = v.trim(); }
760
+ out[el.getAttribute(attr)] = o;
761
+ });
762
+ return out;
763
+ })`;
764
+
765
+ // In-page: tag below-the-fold elements that look "waiting to animate" (opacity 0 / transform offset).
766
+ const TAG_INVIEW = `(function () {
767
+ const innerH = window.innerHeight;
768
+ const all = Array.from(document.querySelectorAll('body *')).slice(0, 3000);
769
+ const out = []; let i = 0;
770
+ for (const el of all) {
771
+ if (i >= 20) break;
772
+ const r = el.getBoundingClientRect();
773
+ if (r.width < 40 || r.height < 40) continue;
774
+ if (r.top < innerH) continue;
775
+ const cs = getComputedStyle(el);
776
+ const hidden = parseFloat(cs.opacity) < 0.05;
777
+ const shifted = cs.transform && cs.transform !== 'none';
778
+ if (!hidden && !shifted) continue;
779
+ if (el.parentElement && el.parentElement.closest('[data-clone-inview]')) continue;
780
+ el.setAttribute('data-clone-inview', 'v' + i);
781
+ const cls = (el.getAttribute('class') || '').trim().split(/\\s+/).filter(Boolean)[0] || '';
782
+ out.push({ probe: 'v' + i, tag: el.tagName.toLowerCase(), cls, top: Math.round(r.top + window.scrollY) });
783
+ i++;
784
+ }
785
+ return out;
786
+ })`;
787
+
788
+ // In-page: observe class/style mutations for N ms with no input → time-driven candidates (carousels, cycling).
789
+ const OBSERVE_MUTATIONS = `(function (ms) {
790
+ return new Promise((resolve) => {
791
+ const counts = new Map();
792
+ const obs = new MutationObserver((muts) => {
793
+ for (const m of muts) {
794
+ const el = m.target;
795
+ if (!el || !el.tagName || el === document.body || el === document.documentElement) continue;
796
+ const tag = el.tagName.toLowerCase();
797
+ const cls = ((el.getAttribute && el.getAttribute('class')) || '').trim().split(/\\s+/).filter(Boolean)[0] || '';
798
+ const key = tag + (cls ? '.' + cls : '');
799
+ const e = counts.get(key) || { tag, cls, mutations: 0, kinds: new Set() };
800
+ e.mutations++; e.kinds.add(m.type === 'attributes' ? m.attributeName : m.type);
801
+ counts.set(key, e);
676
802
  }
803
+ });
804
+ obs.observe(document.body, { subtree: true, attributes: true, attributeFilter: ['class', 'style'], childList: true });
805
+ setTimeout(() => {
806
+ obs.disconnect();
807
+ resolve(Array.from(counts.entries())
808
+ .map(([label, e]) => ({ label, tag: e.tag, cls: e.cls, mutations: e.mutations, kinds: Array.from(e.kinds) }))
809
+ .sort((a, b) => b.mutations - a.mutations)
810
+ .slice(0, 10));
811
+ }, ms);
812
+ });
813
+ })`;
814
+
815
+ // In-page: smooth-scroll library detection (Lenis, Locomotive). 네이티브와 체감이 확연히 달라 놓치면 바로 티가 난다.
816
+ const DETECT_SCROLL_LIB = `(function () {
817
+ const checks = [
818
+ ['lenis', 'html.lenis, .lenis, [data-lenis]'],
819
+ ['locomotive-scroll', '.locomotive-scroll, [data-scroll-container]'],
820
+ ];
821
+ for (const [name, sel] of checks) {
822
+ if (document.querySelector(sel)) return { name, evidence: sel };
823
+ }
824
+ if (window.Lenis) return { name: 'lenis', evidence: 'window.Lenis' };
825
+ if (window.LocomotiveScroll || window.locomotive) return { name: 'locomotive-scroll', evidence: 'window.LocomotiveScroll' };
826
+ return null;
827
+ })`;
828
+
829
+ const wait = (ms) => new Promise((r) => setTimeout(r, ms));
830
+
831
+ // ── Scroll-triggered state (header/nav shrink, background, shadow on scroll) ──
832
+ async function sweepScrollState(page) {
833
+ const out = [];
834
+ const candidates = await page.evaluate(`(${TAG_SCROLL_CANDIDATES})()`);
835
+ if (!candidates.length) return out;
836
+ const before = await page.evaluate(`(${SNAP_PROBES})(${JSON.stringify(BEHAVIOR_PROPS)})`);
837
+ const innerH = await page.evaluate('window.innerHeight');
838
+ const triggerY = Math.min(700, Math.max(200, Math.round(innerH * 0.9)));
839
+ await page.evaluate(`window.scrollTo(0, ${triggerY})`);
840
+ await wait(500);
841
+ const after = await page.evaluate(`(${SNAP_PROBES})(${JSON.stringify(BEHAVIOR_PROPS)})`);
842
+ await page.evaluate('window.scrollTo(0, 0)');
843
+ await wait(300);
844
+ for (const c of candidates) {
845
+ const changed = diffStyles(before[c.probe], after[c.probe]);
846
+ if (Object.keys(changed).length) {
847
+ out.push({
848
+ label: c.cls ? `${c.tag}.${c.cls}` : c.tag,
849
+ tag: c.tag, cls: c.cls, triggerScrollY: triggerY, changed,
850
+ });
677
851
  }
678
852
  }
853
+ return out;
854
+ }
679
855
 
680
- // ── Click-driven tab groups (content swap detection) ──
856
+ // ── Click-driven tab groups (content swap detection) ──
857
+ async function sweepTabGroups(page) {
858
+ const out = [];
681
859
  const groups = await page.evaluate(`(${TAG_TAB_GROUPS})()`);
682
860
  for (const grp of groups) {
683
861
  try {
@@ -693,7 +871,7 @@ async function runInteractionSweep(page) {
693
871
  `(function (g) { const t = document.querySelector('[data-clone-tab="' + g + '_0"]'); if (t) t.click(); })(${grp.group})`
694
872
  );
695
873
  await wait(200);
696
- behaviors.interactive.push({
874
+ out.push({
697
875
  kind: 'tab-group',
698
876
  count: grp.count,
699
877
  tabLabels: grp.labels,
@@ -701,14 +879,113 @@ async function runInteractionSweep(page) {
701
879
  });
702
880
  } catch { /* one bad group must not abort the whole sweep */ }
703
881
  }
882
+ return out;
883
+ }
884
+
885
+ // ── Hover states set by JS (static :hover rules already land in states.json) ──
886
+ async function sweepHover(page) {
887
+ const out = [];
888
+ const candidates = await page.evaluate(`(${TAG_HOVER_CANDIDATES})()`);
889
+ for (const c of candidates) {
890
+ try {
891
+ const sel = `[data-clone-hover="${c.probe}"]`;
892
+ await page.evaluate(`document.querySelector('${sel}')?.scrollIntoView({ block: 'center' })`);
893
+ await wait(150);
894
+ const snap = `(${SNAP_ATTR})('data-clone-hover', ${JSON.stringify(HOVER_PROPS)})`;
895
+ const before = (await page.evaluate(snap))[c.probe];
896
+ await page.hover(sel);
897
+ await wait(350);
898
+ const after = (await page.evaluate(snap))[c.probe];
899
+ await page.mouse.move(0, 0);
900
+ await wait(150);
901
+ const changed = diffStyles(before, after);
902
+ if (Object.keys(changed).length) {
903
+ out.push({
904
+ label: c.cls ? `${c.tag}.${c.cls}` : c.tag,
905
+ tag: c.tag, cls: c.cls, transition: c.transition, changed,
906
+ });
907
+ }
908
+ } catch { /* fail-open: 요소 하나가 스윕 전체를 죽이면 안 된다 */ }
909
+ }
910
+ await page.evaluate('window.scrollTo(0, 0)');
911
+ await wait(200);
912
+ return out;
913
+ }
914
+
915
+ // ── In-view entrance animations (fade-up, slide-in) ──
916
+ // 1회성 등장 애니메이션은 lazy-load 스크롤에서 이미 발화했으므로 페이지를 새로 로드해 관찰한다.
917
+ async function sweepInView(page) {
918
+ const out = [];
919
+ await page.goto(page.url(), { waitUntil: 'networkidle2', timeout: 90000 });
920
+ await wait(800);
921
+ const candidates = await page.evaluate(`(${TAG_INVIEW})()`);
922
+ if (!candidates.length) return out;
923
+ const snap = `(${SNAP_ATTR})('data-clone-inview', ${JSON.stringify(INVIEW_PROPS)})`;
924
+ const before = await page.evaluate(snap);
925
+ for (const c of candidates) {
926
+ try {
927
+ await page.evaluate(`document.querySelector('[data-clone-inview="${c.probe}"]')?.scrollIntoView({ block: 'center' })`);
928
+ await wait(600);
929
+ } catch { /* fail-open */ }
930
+ }
931
+ const after = await page.evaluate(snap);
932
+ await page.evaluate('window.scrollTo(0, 0)');
933
+ await wait(300);
934
+ for (const c of candidates) {
935
+ const changed = diffStyles(before[c.probe], after[c.probe]);
936
+ if (Object.keys(changed).length) {
937
+ out.push({
938
+ label: c.cls ? `${c.tag}.${c.cls}` : c.tag,
939
+ tag: c.tag, cls: c.cls, triggerY: c.top, changed,
940
+ });
941
+ }
942
+ }
943
+ await page.evaluate('document.querySelectorAll("[data-clone-inview]").forEach((e) => e.removeAttribute("data-clone-inview"))');
944
+ return out;
945
+ }
946
+
947
+ async function runInteractionSweep(page) {
948
+ const behaviors = { scroll: [], interactive: [], hover: [], inview: [], timeDriven: [], scrollLib: null };
949
+
950
+ behaviors.scroll = await sweepScrollState(page);
951
+ behaviors.interactive = await sweepTabGroups(page);
952
+ behaviors.hover = await sweepHover(page);
953
+ // 무입력 3초 관찰 — 캐러셀/자동 사이클 후보
954
+ try { behaviors.timeDriven = await page.evaluate(`(${OBSERVE_MUTATIONS})(3000)`); } catch { /* fail-open */ }
955
+ try { behaviors.scrollLib = await page.evaluate(`(${DETECT_SCROLL_LIB})()`); } catch { /* fail-open */ }
704
956
 
705
957
  // Clean up probe attributes BEFORE static extraction so they don't pollute output.
706
958
  await page.evaluate(
707
- 'document.querySelectorAll("[data-clone-probe],[data-clone-tab]").forEach((e) => { e.removeAttribute("data-clone-probe"); e.removeAttribute("data-clone-tab"); })'
959
+ 'document.querySelectorAll("[data-clone-probe],[data-clone-tab],[data-clone-hover]").forEach((e) => { e.removeAttribute("data-clone-probe"); e.removeAttribute("data-clone-tab"); e.removeAttribute("data-clone-hover"); })'
708
960
  );
961
+
962
+ // 마지막: in-view 스윕은 리로드를 동반하므로 다른 스윕 뒤에 실행한다.
963
+ behaviors.inview = await sweepInView(page);
964
+ // 리로드로 lazy-load 상태가 초기화됐으니 정적 추출 전에 복원한다.
965
+ await scrollToBottom(page);
709
966
  return behaviors;
710
967
  }
711
968
 
969
+ // In-page: favicon / OG image / webmanifest URLs (Foundation 단계 — public/seo/ 배선용)
970
+ const SEO_EXTRACT = `(function () {
971
+ const abs = (u) => { try { return new URL(u, location.href).href; } catch { return null; } };
972
+ const icons = Array.from(document.querySelectorAll(
973
+ 'link[rel*="icon" i], link[rel="apple-touch-icon"], link[rel="manifest"]'
974
+ )).map((l) => abs(l.getAttribute('href'))).filter(Boolean);
975
+ const og = Array.from(document.querySelectorAll(
976
+ 'meta[property="og:image"], meta[name="twitter:image"]'
977
+ )).map((m) => abs(m.getAttribute('content'))).filter(Boolean);
978
+ return Array.from(new Set(icons.concat(og)));
979
+ })`;
980
+
981
+ const SUB_LINK_EXTRACT = `(function () {
982
+ const links = Array.from(document.querySelectorAll('a[href]')).map((a) => ({
983
+ href: a.getAttribute('href'),
984
+ text: (a.innerText || a.textContent || '').replace(/\\s+/g, ' ').trim(),
985
+ }));
986
+ return { links };
987
+ })`;
988
+
712
989
  // HTML sanitization: strip scripts/analytics before saving
713
990
  function sanitizeHtml(html) {
714
991
  return html
@@ -718,6 +995,65 @@ function sanitizeHtml(html) {
718
995
  .replace(/\son[a-z]+='[^']*'/gi, '');
719
996
  }
720
997
 
998
+ async function newClonePage(browser) {
999
+ const page = await browser.newPage();
1000
+ await page.setViewport({ width: 1440, height: 900, deviceScaleFactor: 1 });
1001
+ await page.setUserAgent(
1002
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 ' +
1003
+ '(KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
1004
+ );
1005
+ await page.setCacheEnabled(false);
1006
+ return page;
1007
+ }
1008
+
1009
+ async function discoverSubUrls({ url, opts }) {
1010
+ if (!url) throw new Error('URL is required');
1011
+ if (!opts.out) throw new Error('--out=<file> is required');
1012
+
1013
+ if (!opts.ignoreRobots) {
1014
+ const blocked = await checkRobots(url);
1015
+ if (blocked) {
1016
+ throw new Error(
1017
+ `robots.txt disallows ${url}. Pass --ignore-robots only with the site owner's permission.`,
1018
+ );
1019
+ }
1020
+ }
1021
+
1022
+ const puppeteer = await loadPuppeteer();
1023
+ const browser = await puppeteer.launch({
1024
+ headless: 'new',
1025
+ args: ['--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage'],
1026
+ });
1027
+
1028
+ try {
1029
+ const page = await newClonePage(browser);
1030
+ await page.goto(url, { waitUntil: 'networkidle2', timeout: 90000 });
1031
+ await wait(800);
1032
+
1033
+ let source = 'menu';
1034
+ let sourceUrl = url;
1035
+ let { links } = await page.evaluate(`(${SUB_LINK_EXTRACT})()`);
1036
+ const sitemapUrl = findSitemapUrl(url, links);
1037
+ if (sitemapUrl) {
1038
+ await page.goto(sitemapUrl, { waitUntil: 'networkidle2', timeout: 90000 });
1039
+ await wait(800);
1040
+ source = 'sitemap';
1041
+ sourceUrl = sitemapUrl;
1042
+ ({ links } = await page.evaluate(`(${SUB_LINK_EXTRACT})()`));
1043
+ }
1044
+
1045
+ const urls = collectSubUrls(url, links);
1046
+ fs.mkdirSync(path.dirname(opts.out), { recursive: true });
1047
+ fs.writeFileSync(
1048
+ opts.out,
1049
+ JSON.stringify({ meta: { url, source, sourceUrl, count: urls.length }, urls }, null, 2),
1050
+ );
1051
+ process.stdout.write(`[clone-extract] suburls ${urls.length} → ${opts.out}\n`);
1052
+ } finally {
1053
+ await browser.close();
1054
+ }
1055
+ }
1056
+
721
1057
  // ─── Main capture flow ──────────────────────────────────────────────
722
1058
  async function capture({ url, opts }) {
723
1059
  if (!url) throw new Error('URL is required');
@@ -739,8 +1075,10 @@ async function capture({ url, opts }) {
739
1075
  const assetsDir = path.join(opts.out, 'assets');
740
1076
  const imagesDir = path.join(assetsDir, 'images');
741
1077
  const fontsDir = path.join(assetsDir, 'fonts');
1078
+ const seoDir = path.join(assetsDir, 'seo');
742
1079
  fs.mkdirSync(imagesDir, { recursive: true });
743
1080
  fs.mkdirSync(fontsDir, { recursive: true });
1081
+ fs.mkdirSync(seoDir, { recursive: true });
744
1082
 
745
1083
  console.log(`[clone-extract] ${opts.bp || ''} ${viewport.width}x${viewport.height}@${viewport.deviceScaleFactor} ${url}`);
746
1084
 
@@ -756,14 +1094,8 @@ async function capture({ url, opts }) {
756
1094
  });
757
1095
 
758
1096
  try {
759
- const page = await browser.newPage();
1097
+ const page = await newClonePage(browser);
760
1098
  await page.setViewport(viewport);
761
- await page.setUserAgent(
762
- 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 ' +
763
- '(KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
764
- );
765
- // disable cache to get fresh assets
766
- await page.setCacheEnabled(false);
767
1099
 
768
1100
  await page.goto(url, { waitUntil: 'networkidle2', timeout: 90000 });
769
1101
  await scrollToBottom(page);
@@ -775,7 +1107,12 @@ async function capture({ url, opts }) {
775
1107
  if (opts.interact) {
776
1108
  try {
777
1109
  behaviors = await runInteractionSweep(page);
778
- console.log(`[clone-extract] interaction sweep: ${behaviors.scroll.length} scroll-state, ${behaviors.interactive.length} tab-group(s)`);
1110
+ console.log(
1111
+ `[clone-extract] interaction sweep: ${behaviors.scroll.length} scroll-state, ` +
1112
+ `${behaviors.interactive.length} tab-group(s), ${behaviors.hover.length} hover, ` +
1113
+ `${behaviors.inview.length} in-view, ${behaviors.timeDriven.length} time-driven` +
1114
+ `${behaviors.scrollLib ? `, scroll-lib: ${behaviors.scrollLib.name}` : ''}`
1115
+ );
779
1116
  } catch (e) {
780
1117
  console.log(`[clone-extract] interaction sweep skipped: ${e.message}`);
781
1118
  }
@@ -805,9 +1142,14 @@ async function capture({ url, opts }) {
805
1142
  if (sorted[1]) fontDownloadSet.add(sorted[1].url);
806
1143
  }
807
1144
 
808
- console.log(`[clone-extract] downloading ${extracted.assets.images.length} images, ${fontDownloadSet.size} fonts (filtered from ${extracted.assets.fonts.length})`);
1145
+ // Favicon / OG / webmanifest Foundation 단계에서 public/seo/ 로 배선한다
1146
+ let seoUrls = [];
1147
+ try { seoUrls = await page.evaluate(`(${SEO_EXTRACT})()`); } catch { /* fail-open */ }
1148
+
1149
+ console.log(`[clone-extract] downloading ${extracted.assets.images.length} images, ${fontDownloadSet.size} fonts (filtered from ${extracted.assets.fonts.length}), ${seoUrls.length} seo assets`);
809
1150
  const imageMap = await downloadAssets(extracted.assets.images, imagesDir, 8);
810
1151
  const fontMap = await downloadAssets(Array.from(fontDownloadSet), fontsDir, 4);
1152
+ const seoMap = await downloadAssets(seoUrls, seoDir, 4);
811
1153
 
812
1154
  const assetMap = {};
813
1155
  for (const [u, info] of Object.entries(imageMap)) {
@@ -820,6 +1162,11 @@ async function capture({ url, opts }) {
820
1162
  ? { local: `assets/fonts/${info.local}`, status: 'ok', bytes: info.bytes, kind: 'font' }
821
1163
  : { ...info, kind: 'font' };
822
1164
  }
1165
+ for (const [u, info] of Object.entries(seoMap)) {
1166
+ assetMap[u] = info.status === 'ok'
1167
+ ? { local: `assets/seo/${info.local}`, status: 'ok', bytes: info.bytes, kind: 'seo' }
1168
+ : { ...info, kind: 'seo' };
1169
+ }
823
1170
 
824
1171
  // Rewrite HTML — replace remote URLs with local paths
825
1172
  let html = sanitizeHtml(extracted.html);
@@ -896,8 +1243,9 @@ async function capture({ url, opts }) {
896
1243
  );
897
1244
  fs.writeFileSync(path.join(opts.out, 'asset-map.json'), JSON.stringify(assetMap, null, 2));
898
1245
  if (behaviors) {
899
- // Rewrite any remote asset URLs captured in scroll-state background-image diffs.
900
- for (const s of behaviors.scroll) {
1246
+ // Rewrite any remote asset URLs captured in behavior diffs (scroll/hover/inview).
1247
+ const diffed = [...behaviors.scroll, ...(behaviors.hover || []), ...(behaviors.inview || [])];
1248
+ for (const s of diffed) {
901
1249
  for (const ch of Object.values(s.changed)) {
902
1250
  if (typeof ch.from === 'string') ch.from = rewriteCssValue(ch.from);
903
1251
  if (typeof ch.to === 'string') ch.to = rewriteCssValue(ch.to);
@@ -926,16 +1274,18 @@ const isMain = process.argv[1] && process.argv[1].replace(/\\/g, '/').endsWith('
926
1274
  if (isMain) {
927
1275
  const { cmd, url, opts } = parseArgs(process.argv);
928
1276
 
929
- if (cmd !== 'capture') {
1277
+ if (cmd !== 'capture' && cmd !== 'suburls') {
930
1278
  console.error('Usage: node clone-extract.js capture <URL> --out=<dir> --viewport=WxH[@DPR] --bp=mo|pc [--stealth] [--ignore-robots] [--no-interact] [--wait=ms]');
1279
+ console.error(' node clone-extract.js suburls <URL> --out=<file> [--ignore-robots]');
931
1280
  process.exit(1);
932
1281
  }
933
1282
 
934
- capture({ url, opts }).catch((err) => {
1283
+ const run = cmd === 'suburls' ? discoverSubUrls : capture;
1284
+ run({ url, opts }).catch((err) => {
935
1285
  console.error(`[clone-extract] FAIL: ${err.message}`);
936
1286
  if (process.env.DEBUG) console.error(err.stack);
937
1287
  process.exit(1);
938
1288
  });
939
1289
  }
940
1290
 
941
- export { diffStyles };
1291
+ export { collectSubUrls, diffStyles };