@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.
- package/CLAUDE.md +2 -2
- package/README.en.md +6 -4
- package/README.md +5 -3
- package/dist/__tests__/wiring-integrity.test.d.ts +2 -0
- package/dist/__tests__/wiring-integrity.test.d.ts.map +1 -0
- package/dist/__tests__/wiring-integrity.test.js +160 -0
- package/dist/__tests__/wiring-integrity.test.js.map +1 -0
- package/dist/cli/commands/info.d.ts.map +1 -1
- package/dist/cli/commands/info.js +2 -1
- package/dist/cli/commands/info.js.map +1 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +4 -2
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/index.js +102 -128
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/postinstall/claude-agents.d.ts.map +1 -1
- package/dist/cli/postinstall/claude-agents.js +0 -5
- package/dist/cli/postinstall/claude-agents.js.map +1 -1
- package/dist/cli/postinstall/constants.d.ts +6 -0
- package/dist/cli/postinstall/constants.d.ts.map +1 -1
- package/dist/cli/postinstall/constants.js +42 -60
- package/dist/cli/postinstall/constants.js.map +1 -1
- package/dist/cli/postinstall/inline-skills.js +2 -2
- package/dist/cli/postinstall/inline-skills.js.map +1 -1
- package/dist/cli/postinstall/main.d.ts.map +1 -1
- package/dist/cli/postinstall/main.js +2 -0
- package/dist/cli/postinstall/main.js.map +1 -1
- package/dist/cli/postinstall.d.ts +6 -1
- package/dist/cli/postinstall.d.ts.map +1 -1
- package/dist/cli/postinstall.js +6 -1
- package/dist/cli/postinstall.js.map +1 -1
- package/dist/cli/setup/GlobalInstaller.d.ts +1 -15
- package/dist/cli/setup/GlobalInstaller.d.ts.map +1 -1
- package/dist/cli/setup/GlobalInstaller.js +16 -115
- package/dist/cli/setup/GlobalInstaller.js.map +1 -1
- package/dist/cli/setup/GlobalInstaller.test.d.ts +2 -0
- package/dist/cli/setup/GlobalInstaller.test.d.ts.map +1 -0
- package/dist/cli/setup/GlobalInstaller.test.js +16 -0
- package/dist/cli/setup/GlobalInstaller.test.js.map +1 -0
- package/dist/cli/setup/ProjectSetup.js +2 -2
- package/dist/cli/setup/ProjectSetup.js.map +1 -1
- package/dist/cli/setup.d.ts +1 -1
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +1 -1
- package/dist/cli/setup.js.map +1 -1
- package/dist/infra/lib/SkillRepository.js +1 -1
- package/dist/infra/lib/evolution/__tests__/integration.test.js +0 -42
- package/dist/infra/lib/evolution/__tests__/integration.test.js.map +1 -1
- package/hooks/scripts/__tests__/.vibe/command-log.txt +3 -78
- package/hooks/scripts/__tests__/clone-behaviors.test.js +97 -1
- package/hooks/scripts/__tests__/clone-merge-responsive.test.js +106 -0
- package/hooks/scripts/__tests__/code-check-memory-write.test.js +81 -0
- package/hooks/scripts/__tests__/step-counter.test.js +21 -0
- package/hooks/scripts/auto-format.js +2 -11
- package/hooks/scripts/auto-test.js +2 -11
- package/hooks/scripts/clone-extract.js +388 -38
- package/hooks/scripts/clone-merge-responsive.js +184 -0
- package/hooks/scripts/clone-spec.js +33 -8
- package/hooks/scripts/clone-validate.js +15 -9
- package/hooks/scripts/code-check.js +27 -55
- package/hooks/scripts/lib/glob.js +32 -0
- package/hooks/scripts/lib/hook-context.js +19 -2
- package/hooks/scripts/post-edit.js +2 -3
- package/hooks/scripts/prompt-dispatcher.js +1 -1
- package/hooks/scripts/scope-guard.js +3 -42
- package/hooks/scripts/sentinel-guard.js +5 -20
- package/hooks/scripts/session-start.js +2 -2
- package/hooks/scripts/step-counter.js +35 -57
- package/package.json +6 -4
- package/skills/clone/SKILL.md +74 -203
- package/skills/clone/references/capture-rules.md +48 -0
- package/skills/clone/references/legal-and-error-recovery.md +40 -0
- package/skills/clone/references/refine-rules.md +61 -0
- package/skills/clone/references/scaffold-phases.md +59 -0
- package/skills/clone/references/setup-and-layout.md +30 -0
- package/skills/docs/SKILL.md +39 -4
- package/skills/docs/references/api-docs-changelog.md +34 -0
- package/skills/docs/references/codemaps-output.md +23 -0
- package/{agents/diagrammer.md → skills/docs/references/diagram-spec.md} +2 -15
- package/skills/exec-plan/SKILL.md +1 -1
- package/skills/exec-plan/templates/plan.md +1 -1
- package/skills/handoff/SKILL.md +3 -3
- package/skills/handoff/templates/handoff.md +1 -1
- package/skills/vibe/SKILL.md +3 -2
- package/skills/vibe.analyze/SKILL.md +12 -249
- package/skills/vibe.analyze/references/output-templates.md +188 -0
- package/skills/vibe.analyze/references/quality-gate.md +93 -0
- package/skills/vibe.clone/SKILL.md +52 -19
- package/skills/vibe.continue/SKILL.md +32 -0
- package/skills/vibe.design/SKILL.md +23 -1
- package/skills/vibe.design/references/ui-preview.md +20 -0
- package/skills/vibe.docs/SKILL.md +4 -2
- package/skills/vibe.figma/SKILL.md +33 -260
- package/skills/vibe.figma/references/branch-phases.md +113 -0
- package/skills/vibe.figma/references/state-schema.md +42 -0
- package/skills/vibe.figma/references/step-algorithms.md +204 -0
- package/skills/vibe.image/SKILL.md +62 -0
- package/skills/vibe.image/references/image-generation-examples.md +39 -0
- package/skills/vibe.reason/SKILL.md +3 -183
- package/skills/vibe.reason/references/output-format-template.md +57 -0
- package/skills/vibe.reason/references/quality-rubrics.md +94 -0
- package/skills/vibe.reason/references/worked-example.md +45 -0
- package/skills/vibe.review/SKILL.md +13 -348
- package/skills/vibe.review/references/boundary-check.md +25 -0
- package/skills/vibe.review/references/output-template.md +74 -0
- package/skills/vibe.review/references/quality-gate.md +84 -0
- package/skills/vibe.review/references/race-mode.md +117 -0
- package/skills/vibe.review/references/worked-examples.md +94 -0
- package/vibe/templates/claudemd-template.md +1 -1
- package/agents/acceptance-tester.md +0 -56
- package/agents/documenter.md +0 -43
- package/agents/figma/figma-engineer.md +0 -76
- package/dist/cli/llm/gemini-commands.d.ts +0 -25
- package/dist/cli/llm/gemini-commands.d.ts.map +0 -1
- package/dist/cli/llm/gemini-commands.js +0 -143
- package/dist/cli/llm/gemini-commands.js.map +0 -1
- package/dist/cli/postinstall/codex-agents.d.ts +0 -24
- package/dist/cli/postinstall/codex-agents.d.ts.map +0 -1
- package/dist/cli/postinstall/codex-agents.js +0 -114
- package/dist/cli/postinstall/codex-agents.js.map +0 -1
- package/dist/cli/postinstall/codex-instruction.d.ts +0 -10
- package/dist/cli/postinstall/codex-instruction.d.ts.map +0 -1
- package/dist/cli/postinstall/codex-instruction.js +0 -56
- package/dist/cli/postinstall/codex-instruction.js.map +0 -1
- package/dist/cli/postinstall/gemini-agents.d.ts +0 -12
- package/dist/cli/postinstall/gemini-agents.d.ts.map +0 -1
- package/dist/cli/postinstall/gemini-agents.js +0 -80
- package/dist/cli/postinstall/gemini-agents.js.map +0 -1
- package/dist/cli/postinstall/gemini-instruction.d.ts +0 -10
- package/dist/cli/postinstall/gemini-instruction.d.ts.map +0 -1
- package/dist/cli/postinstall/gemini-instruction.js +0 -59
- package/dist/cli/postinstall/gemini-instruction.js.map +0 -1
- package/dist/cli/postinstall/index.d.ts +0 -23
- package/dist/cli/postinstall/index.d.ts.map +0 -1
- package/dist/cli/postinstall/index.js +0 -23
- package/dist/cli/postinstall/index.js.map +0 -1
- package/dist/cli/setup/index.d.ts +0 -9
- package/dist/cli/setup/index.d.ts.map +0 -1
- package/dist/cli/setup/index.js +0 -12
- package/dist/cli/setup/index.js.map +0 -1
- package/dist/infra/lib/ContextCompressor.d.ts +0 -104
- package/dist/infra/lib/ContextCompressor.d.ts.map +0 -1
- package/dist/infra/lib/ContextCompressor.js +0 -297
- package/dist/infra/lib/ContextCompressor.js.map +0 -1
- package/dist/infra/lib/ContextCompressor.test.d.ts +0 -2
- package/dist/infra/lib/ContextCompressor.test.d.ts.map +0 -1
- package/dist/infra/lib/ContextCompressor.test.js +0 -25
- package/dist/infra/lib/ContextCompressor.test.js.map +0 -1
- package/dist/infra/lib/ProgressTracker.d.ts +0 -73
- package/dist/infra/lib/ProgressTracker.d.ts.map +0 -1
- package/dist/infra/lib/ProgressTracker.js +0 -267
- package/dist/infra/lib/ProgressTracker.js.map +0 -1
- package/dist/infra/lib/TokenBudgetTracker.d.ts +0 -68
- package/dist/infra/lib/TokenBudgetTracker.d.ts.map +0 -1
- package/dist/infra/lib/TokenBudgetTracker.js +0 -191
- package/dist/infra/lib/TokenBudgetTracker.js.map +0 -1
- package/dist/infra/lib/autonomy/AuditStore.d.ts +0 -63
- package/dist/infra/lib/autonomy/AuditStore.d.ts.map +0 -1
- package/dist/infra/lib/autonomy/AuditStore.js +0 -185
- package/dist/infra/lib/autonomy/AuditStore.js.map +0 -1
- package/dist/infra/lib/autonomy/AutonomyConfig.d.ts +0 -84
- package/dist/infra/lib/autonomy/AutonomyConfig.d.ts.map +0 -1
- package/dist/infra/lib/autonomy/AutonomyConfig.js +0 -49
- package/dist/infra/lib/autonomy/AutonomyConfig.js.map +0 -1
- package/dist/infra/lib/autonomy/AutonomyOrchestrator.d.ts +0 -78
- package/dist/infra/lib/autonomy/AutonomyOrchestrator.d.ts.map +0 -1
- package/dist/infra/lib/autonomy/AutonomyOrchestrator.js +0 -246
- package/dist/infra/lib/autonomy/AutonomyOrchestrator.js.map +0 -1
- package/dist/infra/lib/autonomy/BackgroundMonitor.d.ts +0 -36
- package/dist/infra/lib/autonomy/BackgroundMonitor.d.ts.map +0 -1
- package/dist/infra/lib/autonomy/BackgroundMonitor.js +0 -138
- package/dist/infra/lib/autonomy/BackgroundMonitor.js.map +0 -1
- package/dist/infra/lib/autonomy/CollaborationProtocol.d.ts +0 -56
- package/dist/infra/lib/autonomy/CollaborationProtocol.d.ts.map +0 -1
- package/dist/infra/lib/autonomy/CollaborationProtocol.js +0 -122
- package/dist/infra/lib/autonomy/CollaborationProtocol.js.map +0 -1
- package/dist/infra/lib/autonomy/ConfirmationManager.d.ts +0 -42
- package/dist/infra/lib/autonomy/ConfirmationManager.d.ts.map +0 -1
- package/dist/infra/lib/autonomy/ConfirmationManager.js +0 -200
- package/dist/infra/lib/autonomy/ConfirmationManager.js.map +0 -1
- package/dist/infra/lib/autonomy/ConfirmationStore.d.ts +0 -55
- package/dist/infra/lib/autonomy/ConfirmationStore.d.ts.map +0 -1
- package/dist/infra/lib/autonomy/ConfirmationStore.js +0 -130
- package/dist/infra/lib/autonomy/ConfirmationStore.js.map +0 -1
- package/dist/infra/lib/autonomy/EventBus.d.ts +0 -20
- package/dist/infra/lib/autonomy/EventBus.d.ts.map +0 -1
- package/dist/infra/lib/autonomy/EventBus.js +0 -119
- package/dist/infra/lib/autonomy/EventBus.js.map +0 -1
- package/dist/infra/lib/autonomy/EventOutbox.d.ts +0 -32
- package/dist/infra/lib/autonomy/EventOutbox.d.ts.map +0 -1
- package/dist/infra/lib/autonomy/EventOutbox.js +0 -152
- package/dist/infra/lib/autonomy/EventOutbox.js.map +0 -1
- package/dist/infra/lib/autonomy/NotificationDispatcher.d.ts +0 -24
- package/dist/infra/lib/autonomy/NotificationDispatcher.d.ts.map +0 -1
- package/dist/infra/lib/autonomy/NotificationDispatcher.js +0 -112
- package/dist/infra/lib/autonomy/NotificationDispatcher.js.map +0 -1
- package/dist/infra/lib/autonomy/PolicyEngine.d.ts +0 -76
- package/dist/infra/lib/autonomy/PolicyEngine.d.ts.map +0 -1
- package/dist/infra/lib/autonomy/PolicyEngine.js +0 -208
- package/dist/infra/lib/autonomy/PolicyEngine.js.map +0 -1
- package/dist/infra/lib/autonomy/ProactiveAnalyzer.d.ts +0 -61
- package/dist/infra/lib/autonomy/ProactiveAnalyzer.d.ts.map +0 -1
- package/dist/infra/lib/autonomy/ProactiveAnalyzer.js +0 -236
- package/dist/infra/lib/autonomy/ProactiveAnalyzer.js.map +0 -1
- package/dist/infra/lib/autonomy/RiskClassifier.d.ts +0 -35
- package/dist/infra/lib/autonomy/RiskClassifier.d.ts.map +0 -1
- package/dist/infra/lib/autonomy/RiskClassifier.js +0 -147
- package/dist/infra/lib/autonomy/RiskClassifier.js.map +0 -1
- package/dist/infra/lib/autonomy/SecuritySentinel.d.ts +0 -51
- package/dist/infra/lib/autonomy/SecuritySentinel.d.ts.map +0 -1
- package/dist/infra/lib/autonomy/SecuritySentinel.js +0 -162
- package/dist/infra/lib/autonomy/SecuritySentinel.js.map +0 -1
- package/dist/infra/lib/autonomy/SuggestionStore.d.ts +0 -54
- package/dist/infra/lib/autonomy/SuggestionStore.d.ts.map +0 -1
- package/dist/infra/lib/autonomy/SuggestionStore.js +0 -144
- package/dist/infra/lib/autonomy/SuggestionStore.js.map +0 -1
- package/dist/infra/lib/autonomy/TaskDecomposer.d.ts +0 -38
- package/dist/infra/lib/autonomy/TaskDecomposer.d.ts.map +0 -1
- package/dist/infra/lib/autonomy/TaskDecomposer.js +0 -175
- package/dist/infra/lib/autonomy/TaskDecomposer.js.map +0 -1
- package/dist/infra/lib/autonomy/__tests__/audit-store.test.d.ts +0 -2
- package/dist/infra/lib/autonomy/__tests__/audit-store.test.d.ts.map +0 -1
- package/dist/infra/lib/autonomy/__tests__/audit-store.test.js +0 -198
- package/dist/infra/lib/autonomy/__tests__/audit-store.test.js.map +0 -1
- package/dist/infra/lib/autonomy/__tests__/event-bus.test.d.ts +0 -2
- package/dist/infra/lib/autonomy/__tests__/event-bus.test.d.ts.map +0 -1
- package/dist/infra/lib/autonomy/__tests__/event-bus.test.js +0 -225
- package/dist/infra/lib/autonomy/__tests__/event-bus.test.js.map +0 -1
- package/dist/infra/lib/autonomy/__tests__/event-core.test.d.ts +0 -2
- package/dist/infra/lib/autonomy/__tests__/event-core.test.d.ts.map +0 -1
- package/dist/infra/lib/autonomy/__tests__/event-core.test.js +0 -194
- package/dist/infra/lib/autonomy/__tests__/event-core.test.js.map +0 -1
- package/dist/infra/lib/autonomy/__tests__/governance.test.d.ts +0 -2
- package/dist/infra/lib/autonomy/__tests__/governance.test.d.ts.map +0 -1
- package/dist/infra/lib/autonomy/__tests__/governance.test.js +0 -540
- package/dist/infra/lib/autonomy/__tests__/governance.test.js.map +0 -1
- package/dist/infra/lib/autonomy/__tests__/integration.test.d.ts +0 -2
- package/dist/infra/lib/autonomy/__tests__/integration.test.d.ts.map +0 -1
- package/dist/infra/lib/autonomy/__tests__/integration.test.js +0 -480
- package/dist/infra/lib/autonomy/__tests__/integration.test.js.map +0 -1
- package/dist/infra/lib/autonomy/__tests__/proactive.test.d.ts +0 -2
- package/dist/infra/lib/autonomy/__tests__/proactive.test.d.ts.map +0 -1
- package/dist/infra/lib/autonomy/__tests__/proactive.test.js +0 -410
- package/dist/infra/lib/autonomy/__tests__/proactive.test.js.map +0 -1
- package/dist/infra/lib/autonomy/__tests__/sentinel.test.d.ts +0 -2
- package/dist/infra/lib/autonomy/__tests__/sentinel.test.d.ts.map +0 -1
- package/dist/infra/lib/autonomy/__tests__/sentinel.test.js +0 -486
- package/dist/infra/lib/autonomy/__tests__/sentinel.test.js.map +0 -1
- package/dist/infra/lib/autonomy/index.d.ts +0 -18
- package/dist/infra/lib/autonomy/index.d.ts.map +0 -1
- package/dist/infra/lib/autonomy/index.js +0 -22
- package/dist/infra/lib/autonomy/index.js.map +0 -1
- package/dist/infra/lib/autonomy/schemas.d.ts +0 -317
- package/dist/infra/lib/autonomy/schemas.d.ts.map +0 -1
- package/dist/infra/lib/autonomy/schemas.js +0 -90
- package/dist/infra/lib/autonomy/schemas.js.map +0 -1
- package/dist/infra/lib/claude/index.d.ts +0 -5
- package/dist/infra/lib/claude/index.d.ts.map +0 -1
- package/dist/infra/lib/claude/index.js +0 -5
- package/dist/infra/lib/claude/index.js.map +0 -1
- package/dist/infra/lib/claude/storage.d.ts +0 -12
- package/dist/infra/lib/claude/storage.d.ts.map +0 -1
- package/dist/infra/lib/claude/storage.js +0 -54
- package/dist/infra/lib/claude/storage.js.map +0 -1
- package/dist/infra/lib/gemini/auth.d.ts +0 -18
- package/dist/infra/lib/gemini/auth.d.ts.map +0 -1
- package/dist/infra/lib/gemini/auth.js +0 -32
- package/dist/infra/lib/gemini/auth.js.map +0 -1
- package/dist/infra/lib/gemini/capabilities.d.ts +0 -28
- package/dist/infra/lib/gemini/capabilities.d.ts.map +0 -1
- package/dist/infra/lib/gemini/capabilities.js +0 -178
- package/dist/infra/lib/gemini/capabilities.js.map +0 -1
- package/dist/infra/lib/gemini/chat.d.ts +0 -35
- package/dist/infra/lib/gemini/chat.d.ts.map +0 -1
- package/dist/infra/lib/gemini/chat.js +0 -161
- package/dist/infra/lib/gemini/chat.js.map +0 -1
- package/dist/infra/lib/gemini/completion.d.ts +0 -12
- package/dist/infra/lib/gemini/completion.d.ts.map +0 -1
- package/dist/infra/lib/gemini/completion.js +0 -13
- package/dist/infra/lib/gemini/completion.js.map +0 -1
- package/dist/infra/lib/gemini/constants.d.ts +0 -8
- package/dist/infra/lib/gemini/constants.d.ts.map +0 -1
- package/dist/infra/lib/gemini/constants.js +0 -11
- package/dist/infra/lib/gemini/constants.js.map +0 -1
- package/dist/infra/lib/gemini/index.d.ts +0 -13
- package/dist/infra/lib/gemini/index.d.ts.map +0 -1
- package/dist/infra/lib/gemini/index.js +0 -12
- package/dist/infra/lib/gemini/index.js.map +0 -1
- package/dist/infra/lib/gemini/models.d.ts +0 -11
- package/dist/infra/lib/gemini/models.d.ts.map +0 -1
- package/dist/infra/lib/gemini/models.js +0 -38
- package/dist/infra/lib/gemini/models.js.map +0 -1
- package/dist/infra/lib/gemini/orchestration.d.ts +0 -33
- package/dist/infra/lib/gemini/orchestration.d.ts.map +0 -1
- package/dist/infra/lib/gemini/orchestration.js +0 -62
- package/dist/infra/lib/gemini/orchestration.js.map +0 -1
- package/dist/infra/lib/gemini/types.d.ts +0 -115
- package/dist/infra/lib/gemini/types.d.ts.map +0 -1
- package/dist/infra/lib/gemini/types.js +0 -5
- package/dist/infra/lib/gemini/types.js.map +0 -1
- package/dist/infra/orchestrator/AgentAnnouncer.d.ts +0 -64
- package/dist/infra/orchestrator/AgentAnnouncer.d.ts.map +0 -1
- package/dist/infra/orchestrator/AgentAnnouncer.js +0 -127
- package/dist/infra/orchestrator/AgentAnnouncer.js.map +0 -1
- package/dist/infra/orchestrator/AgentAnnouncer.test.d.ts +0 -5
- package/dist/infra/orchestrator/AgentAnnouncer.test.d.ts.map +0 -1
- package/dist/infra/orchestrator/AgentAnnouncer.test.js +0 -119
- package/dist/infra/orchestrator/AgentAnnouncer.test.js.map +0 -1
- package/dist/infra/orchestrator/AgentExecutor.d.ts +0 -22
- package/dist/infra/orchestrator/AgentExecutor.d.ts.map +0 -1
- package/dist/infra/orchestrator/AgentExecutor.js +0 -272
- package/dist/infra/orchestrator/AgentExecutor.js.map +0 -1
- package/dist/infra/orchestrator/AgentManager.d.ts +0 -72
- package/dist/infra/orchestrator/AgentManager.d.ts.map +0 -1
- package/dist/infra/orchestrator/AgentManager.js +0 -183
- package/dist/infra/orchestrator/AgentManager.js.map +0 -1
- package/dist/infra/orchestrator/AgentManifestCache.d.ts +0 -54
- package/dist/infra/orchestrator/AgentManifestCache.d.ts.map +0 -1
- package/dist/infra/orchestrator/AgentManifestCache.js +0 -191
- package/dist/infra/orchestrator/AgentManifestCache.js.map +0 -1
- package/dist/infra/orchestrator/AgentRegistry.d.ts +0 -76
- package/dist/infra/orchestrator/AgentRegistry.d.ts.map +0 -1
- package/dist/infra/orchestrator/AgentRegistry.js +0 -217
- package/dist/infra/orchestrator/AgentRegistry.js.map +0 -1
- package/dist/infra/orchestrator/AgentRegistry.test.d.ts +0 -5
- package/dist/infra/orchestrator/AgentRegistry.test.d.ts.map +0 -1
- package/dist/infra/orchestrator/AgentRegistry.test.js +0 -122
- package/dist/infra/orchestrator/AgentRegistry.test.js.map +0 -1
- package/dist/infra/orchestrator/BackgroundManager.d.ts +0 -128
- package/dist/infra/orchestrator/BackgroundManager.d.ts.map +0 -1
- package/dist/infra/orchestrator/BackgroundManager.js +0 -620
- package/dist/infra/orchestrator/BackgroundManager.js.map +0 -1
- package/dist/infra/orchestrator/BackgroundManager.test.d.ts +0 -6
- package/dist/infra/orchestrator/BackgroundManager.test.d.ts.map +0 -1
- package/dist/infra/orchestrator/BackgroundManager.test.js +0 -162
- package/dist/infra/orchestrator/BackgroundManager.test.js.map +0 -1
- package/dist/infra/orchestrator/CheckpointManager.d.ts +0 -54
- package/dist/infra/orchestrator/CheckpointManager.d.ts.map +0 -1
- package/dist/infra/orchestrator/CheckpointManager.js +0 -121
- package/dist/infra/orchestrator/CheckpointManager.js.map +0 -1
- package/dist/infra/orchestrator/CodexAgentRuntime.d.ts +0 -12
- package/dist/infra/orchestrator/CodexAgentRuntime.d.ts.map +0 -1
- package/dist/infra/orchestrator/CodexAgentRuntime.js +0 -94
- package/dist/infra/orchestrator/CodexAgentRuntime.js.map +0 -1
- package/dist/infra/orchestrator/CodexAgentRuntime.test.d.ts +0 -2
- package/dist/infra/orchestrator/CodexAgentRuntime.test.d.ts.map +0 -1
- package/dist/infra/orchestrator/CodexAgentRuntime.test.js +0 -37
- package/dist/infra/orchestrator/CodexAgentRuntime.test.js.map +0 -1
- package/dist/infra/orchestrator/LLMCluster.d.ts +0 -82
- package/dist/infra/orchestrator/LLMCluster.d.ts.map +0 -1
- package/dist/infra/orchestrator/LLMCluster.js +0 -146
- package/dist/infra/orchestrator/LLMCluster.js.map +0 -1
- package/dist/infra/orchestrator/MultiLlmResearch.d.ts +0 -31
- package/dist/infra/orchestrator/MultiLlmResearch.d.ts.map +0 -1
- package/dist/infra/orchestrator/MultiLlmResearch.js +0 -160
- package/dist/infra/orchestrator/MultiLlmResearch.js.map +0 -1
- package/dist/infra/orchestrator/PhasePipeline.d.ts +0 -122
- package/dist/infra/orchestrator/PhasePipeline.d.ts.map +0 -1
- package/dist/infra/orchestrator/PhasePipeline.js +0 -385
- package/dist/infra/orchestrator/PhasePipeline.js.map +0 -1
- package/dist/infra/orchestrator/PhaseResultStore.d.ts +0 -39
- package/dist/infra/orchestrator/PhaseResultStore.d.ts.map +0 -1
- package/dist/infra/orchestrator/PhaseResultStore.js +0 -151
- package/dist/infra/orchestrator/PhaseResultStore.js.map +0 -1
- package/dist/infra/orchestrator/SessionStore.d.ts +0 -40
- package/dist/infra/orchestrator/SessionStore.d.ts.map +0 -1
- package/dist/infra/orchestrator/SessionStore.js +0 -116
- package/dist/infra/orchestrator/SessionStore.js.map +0 -1
- package/dist/infra/orchestrator/SmartRouter.d.ts +0 -90
- package/dist/infra/orchestrator/SmartRouter.d.ts.map +0 -1
- package/dist/infra/orchestrator/SmartRouter.js +0 -277
- package/dist/infra/orchestrator/SmartRouter.js.map +0 -1
- package/dist/infra/orchestrator/SmartRouter.test.d.ts +0 -5
- package/dist/infra/orchestrator/SmartRouter.test.d.ts.map +0 -1
- package/dist/infra/orchestrator/SmartRouter.test.js +0 -484
- package/dist/infra/orchestrator/SmartRouter.test.js.map +0 -1
- package/dist/infra/orchestrator/SwarmOrchestrator.d.ts +0 -143
- package/dist/infra/orchestrator/SwarmOrchestrator.d.ts.map +0 -1
- package/dist/infra/orchestrator/SwarmOrchestrator.js +0 -378
- package/dist/infra/orchestrator/SwarmOrchestrator.js.map +0 -1
- package/dist/infra/orchestrator/SwarmOrchestrator.test.d.ts +0 -5
- package/dist/infra/orchestrator/SwarmOrchestrator.test.d.ts.map +0 -1
- package/dist/infra/orchestrator/SwarmOrchestrator.test.js +0 -95
- package/dist/infra/orchestrator/SwarmOrchestrator.test.js.map +0 -1
- package/dist/infra/orchestrator/agentDiscovery.d.ts +0 -26
- package/dist/infra/orchestrator/agentDiscovery.d.ts.map +0 -1
- package/dist/infra/orchestrator/agentDiscovery.js +0 -175
- package/dist/infra/orchestrator/agentDiscovery.js.map +0 -1
- package/dist/infra/orchestrator/backgroundAgent.d.ts +0 -9
- package/dist/infra/orchestrator/backgroundAgent.d.ts.map +0 -1
- package/dist/infra/orchestrator/backgroundAgent.js +0 -10
- package/dist/infra/orchestrator/backgroundAgent.js.map +0 -1
- package/dist/infra/orchestrator/index.d.ts +0 -207
- package/dist/infra/orchestrator/index.d.ts.map +0 -1
- package/dist/infra/orchestrator/index.js +0 -362
- package/dist/infra/orchestrator/index.js.map +0 -1
- package/dist/infra/orchestrator/orchestrator.d.ts +0 -60
- package/dist/infra/orchestrator/orchestrator.d.ts.map +0 -1
- package/dist/infra/orchestrator/orchestrator.js +0 -214
- package/dist/infra/orchestrator/orchestrator.js.map +0 -1
- package/dist/infra/orchestrator/parallelResearch.d.ts +0 -27
- package/dist/infra/orchestrator/parallelResearch.d.ts.map +0 -1
- package/dist/infra/orchestrator/parallelResearch.js +0 -285
- package/dist/infra/orchestrator/parallelResearch.js.map +0 -1
- package/dist/infra/orchestrator/types.d.ts +0 -205
- package/dist/infra/orchestrator/types.d.ts.map +0 -1
- package/dist/infra/orchestrator/types.js +0 -87
- package/dist/infra/orchestrator/types.js.map +0 -1
- package/dist/infra/orchestrator/types.test.d.ts +0 -2
- package/dist/infra/orchestrator/types.test.d.ts.map +0 -1
- package/dist/infra/orchestrator/types.test.js +0 -57
- package/dist/infra/orchestrator/types.test.js.map +0 -1
- package/dist/tools/semantic/analyzeDependencyGraph.d.ts +0 -12
- package/dist/tools/semantic/analyzeDependencyGraph.d.ts.map +0 -1
- package/dist/tools/semantic/analyzeDependencyGraph.js +0 -359
- package/dist/tools/semantic/analyzeDependencyGraph.js.map +0 -1
- package/dist/tools/semantic/astGrep.d.ts +0 -25
- package/dist/tools/semantic/astGrep.d.ts.map +0 -1
- package/dist/tools/semantic/astGrep.js +0 -324
- package/dist/tools/semantic/astGrep.js.map +0 -1
- package/dist/tools/semantic/astGrep.test.d.ts +0 -2
- package/dist/tools/semantic/astGrep.test.d.ts.map +0 -1
- package/dist/tools/semantic/astGrep.test.js +0 -74
- package/dist/tools/semantic/astGrep.test.js.map +0 -1
- package/dist/tools/semantic/findReferences.d.ts +0 -9
- package/dist/tools/semantic/findReferences.d.ts.map +0 -1
- package/dist/tools/semantic/findReferences.js +0 -200
- package/dist/tools/semantic/findReferences.js.map +0 -1
- package/dist/tools/semantic/findSymbol.d.ts +0 -8
- package/dist/tools/semantic/findSymbol.d.ts.map +0 -1
- package/dist/tools/semantic/findSymbol.js +0 -204
- package/dist/tools/semantic/findSymbol.js.map +0 -1
- package/dist/tools/semantic/index.d.ts +0 -9
- package/dist/tools/semantic/index.d.ts.map +0 -1
- package/dist/tools/semantic/index.js +0 -11
- package/dist/tools/semantic/index.js.map +0 -1
- package/dist/tools/semantic/lsp.d.ts +0 -68
- package/dist/tools/semantic/lsp.d.ts.map +0 -1
- package/dist/tools/semantic/lsp.js +0 -561
- package/dist/tools/semantic/lsp.js.map +0 -1
- package/dist/tools/spec/e2eTestGenerator.d.ts +0 -61
- package/dist/tools/spec/e2eTestGenerator.d.ts.map +0 -1
- package/dist/tools/spec/e2eTestGenerator.js +0 -255
- package/dist/tools/spec/e2eTestGenerator.js.map +0 -1
- package/dist/tools/spec/specVersioning.d.ts +0 -76
- package/dist/tools/spec/specVersioning.d.ts.map +0 -1
- package/dist/tools/spec/specVersioning.js +0 -236
- package/dist/tools/spec/specVersioning.js.map +0 -1
- package/hooks/scripts/__tests__/.vibe/memories/memories.db +0 -0
- package/hooks/scripts/__tests__/.vibe/memories/memories.db-shm +0 -0
- package/hooks/scripts/__tests__/.vibe/memories/memories.db-wal +0 -0
- package/hooks/scripts/evolution-engine.js +0 -91
- package/hooks/scripts/hud-status.js +0 -321
- package/hooks/scripts/skill-injector.js +0 -83
- 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
|
-
|
|
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
|
-
|
|
656
|
-
|
|
732
|
+
// In-view 등장 애니메이션 diff props
|
|
733
|
+
const INVIEW_PROPS = ['opacity', 'transform', 'visibility', 'filter', 'clip-path'];
|
|
657
734
|
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
const
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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(
|
|
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
|
-
|
|
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
|
|
900
|
-
|
|
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
|
-
|
|
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 };
|