claudecode-omc 5.6.5 → 5.6.7
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/.local/commands/code-review.md +416 -0
- package/.local/commands/pr.md +250 -0
- package/.local/commands/prp-pr.md +244 -0
- package/.local/guidelines/CLAUDE.md +47 -0
- package/.local/skills/h5-to-swiftui/SKILL.md +201 -0
- package/.local/skills/h5-to-swiftui/assets/calibration/README.md +176 -0
- package/.local/skills/h5-to-swiftui/assets/calibration/h5-twin/index.html +52 -0
- package/.local/skills/h5-to-swiftui/assets/calibration/h5-twin/style.css +133 -0
- package/.local/skills/h5-to-swiftui/assets/calibration/swiftui-twin/Package.swift +26 -0
- package/.local/skills/h5-to-swiftui/assets/calibration/swiftui-twin/Sources/CalibrationScreen/CalibrationScreen.swift +142 -0
- package/.local/skills/h5-to-swiftui/assets/calibration/swiftui-twin-divergent/Package.swift +32 -0
- package/.local/skills/h5-to-swiftui/assets/calibration/swiftui-twin-divergent/Sources/CalibrationScreenDivergent/CalibrationScreenDivergent.swift +122 -0
- package/.local/skills/h5-to-swiftui/assets/calibration/tokens.json +42 -0
- package/.local/skills/h5-to-swiftui/assets/sample-h5-react/index.html +14 -0
- package/.local/skills/h5-to-swiftui/assets/sample-h5-react/package.json +20 -0
- package/.local/skills/h5-to-swiftui/assets/sample-h5-react/public/api/articles/001.json +96 -0
- package/.local/skills/h5-to-swiftui/assets/sample-h5-react/public/api/articles/index.json +89 -0
- package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/App.jsx +22 -0
- package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/App.module.css +11 -0
- package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/components/ArticleCard.jsx +53 -0
- package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/components/ArticleCard.module.css +139 -0
- package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/components/NavBar.jsx +37 -0
- package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/components/NavBar.module.css +72 -0
- package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/components/TagCloud.jsx +30 -0
- package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/components/TagCloud.module.css +50 -0
- package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/components/TrendChart.jsx +159 -0
- package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/components/TrendChart.module.css +21 -0
- package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/main.jsx +12 -0
- package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/screens/ArticleScreen.jsx +182 -0
- package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/screens/ArticleScreen.module.css +294 -0
- package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/screens/FeedScreen.jsx +147 -0
- package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/screens/FeedScreen.module.css +161 -0
- package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/styles/global.css +50 -0
- package/.local/skills/h5-to-swiftui/assets/sample-h5-react/src/styles/tokens.css +103 -0
- package/.local/skills/h5-to-swiftui/assets/sample-h5-react/vite.config.js +6 -0
- package/.local/skills/h5-to-swiftui/assets/sample-h5-vanilla/data/tasks.js +67 -0
- package/.local/skills/h5-to-swiftui/assets/sample-h5-vanilla/index.html +26 -0
- package/.local/skills/h5-to-swiftui/assets/sample-h5-vanilla/router.js +73 -0
- package/.local/skills/h5-to-swiftui/assets/sample-h5-vanilla/screens/detail.js +164 -0
- package/.local/skills/h5-to-swiftui/assets/sample-h5-vanilla/screens/home.js +53 -0
- package/.local/skills/h5-to-swiftui/assets/sample-h5-vanilla/screens/list.js +87 -0
- package/.local/skills/h5-to-swiftui/assets/sample-h5-vanilla/styles/app.css +342 -0
- package/.local/skills/h5-to-swiftui/assets/sample-h5-vanilla/styles/tokens.css +68 -0
- package/.local/skills/h5-to-swiftui/references/css-to-swiftui-map.md +205 -0
- package/.local/skills/h5-to-swiftui/references/design-token-extraction.md +209 -0
- package/.local/skills/h5-to-swiftui/references/high-risk-triage.md +209 -0
- package/.local/skills/h5-to-swiftui/references/render-equivalence-calibration.md +193 -0
- package/.local/skills/h5-to-swiftui/references/stack-detection.md +160 -0
- package/.local/skills/h5-to-swiftui/references/visual-diff-loop-protocol.md +365 -0
- package/.local/skills/h5-to-swiftui/scripts/_calib-consts.mjs +150 -0
- package/.local/skills/h5-to-swiftui/scripts/_imglib.mjs +547 -0
- package/.local/skills/h5-to-swiftui/scripts/_provenance.mjs +123 -0
- package/.local/skills/h5-to-swiftui/scripts/calibrate-render.mjs +625 -0
- package/.local/skills/h5-to-swiftui/scripts/capture-reference.mjs +386 -0
- package/.local/skills/h5-to-swiftui/scripts/detect-stack.mjs +305 -0
- package/.local/skills/h5-to-swiftui/scripts/evaluate-convergence.mjs +1093 -0
- package/.local/skills/h5-to-swiftui/scripts/extract-tokens.mjs +600 -0
- package/.local/skills/h5-to-swiftui/scripts/mark-overlay.mjs +379 -0
- package/.local/skills/h5-to-swiftui/scripts/pixel-diff.mjs +530 -0
- package/.local/skills/h5-to-swiftui/scripts/sim-screenshot.sh +544 -0
- package/bundled/manifest.json +4 -4
- package/bundled/upstream/anthropic-skills/skills/algorithmic-art/LICENSE.txt +1 -1
- package/bundled/upstream/anthropic-skills/skills/brand-guidelines/LICENSE.txt +1 -1
- package/bundled/upstream/anthropic-skills/skills/canvas-design/LICENSE.txt +1 -1
- package/bundled/upstream/anthropic-skills/skills/claude-api/LICENSE.txt +1 -1
- package/bundled/upstream/anthropic-skills/skills/claude-api/SKILL.md +120 -58
- package/bundled/upstream/anthropic-skills/skills/claude-api/curl/examples.md +9 -9
- package/bundled/upstream/anthropic-skills/skills/claude-api/curl/managed-agents.md +336 -0
- package/bundled/upstream/anthropic-skills/skills/claude-api/go/managed-agents/README.md +561 -0
- package/bundled/upstream/anthropic-skills/skills/claude-api/java/claude-api.md +2 -2
- package/bundled/upstream/anthropic-skills/skills/claude-api/java/managed-agents/README.md +442 -0
- package/bundled/upstream/anthropic-skills/skills/claude-api/php/claude-api.md +10 -10
- package/bundled/upstream/anthropic-skills/skills/claude-api/php/managed-agents/README.md +435 -0
- package/bundled/upstream/anthropic-skills/skills/claude-api/python/claude-api/README.md +16 -16
- package/bundled/upstream/anthropic-skills/skills/claude-api/python/claude-api/batches.md +3 -3
- package/bundled/upstream/anthropic-skills/skills/claude-api/python/claude-api/files-api.md +3 -3
- package/bundled/upstream/anthropic-skills/skills/claude-api/python/claude-api/streaming.md +7 -7
- package/bundled/upstream/anthropic-skills/skills/claude-api/python/claude-api/tool-use.md +19 -19
- package/bundled/upstream/anthropic-skills/skills/claude-api/python/managed-agents/README.md +332 -0
- package/bundled/upstream/anthropic-skills/skills/claude-api/ruby/claude-api.md +4 -4
- package/bundled/upstream/anthropic-skills/skills/claude-api/ruby/managed-agents/README.md +389 -0
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/agent-design.md +101 -0
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/error-codes.md +11 -4
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/live-sources.md +60 -48
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/managed-agents-api-reference.md +372 -0
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/managed-agents-client-patterns.md +209 -0
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/managed-agents-core.md +220 -0
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/managed-agents-environments.md +211 -0
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/managed-agents-events.md +195 -0
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/managed-agents-memory.md +197 -0
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/managed-agents-multiagent.md +99 -0
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/managed-agents-onboarding.md +114 -0
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/managed-agents-outcomes.md +106 -0
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/managed-agents-overview.md +67 -0
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/managed-agents-tools.md +315 -0
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/managed-agents-webhooks.md +110 -0
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/model-migration.md +779 -0
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/models.md +16 -14
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/prompt-caching.md +45 -2
- package/bundled/upstream/anthropic-skills/skills/claude-api/shared/tool-use-concepts.md +28 -6
- package/bundled/upstream/anthropic-skills/skills/claude-api/typescript/claude-api/README.md +15 -15
- package/bundled/upstream/anthropic-skills/skills/claude-api/typescript/claude-api/batches.md +2 -2
- package/bundled/upstream/anthropic-skills/skills/claude-api/typescript/claude-api/files-api.md +1 -1
- package/bundled/upstream/anthropic-skills/skills/claude-api/typescript/claude-api/streaming.md +5 -5
- package/bundled/upstream/anthropic-skills/skills/claude-api/typescript/claude-api/tool-use.md +15 -15
- package/bundled/upstream/anthropic-skills/skills/claude-api/typescript/managed-agents/README.md +359 -0
- package/bundled/upstream/anthropic-skills/skills/internal-comms/LICENSE.txt +1 -1
- package/bundled/upstream/anthropic-skills/skills/mcp-builder/LICENSE.txt +1 -1
- package/bundled/upstream/anthropic-skills/skills/skill-creator/LICENSE.txt +1 -1
- package/bundled/upstream/anthropic-skills/skills/slack-gif-creator/LICENSE.txt +1 -1
- package/bundled/upstream/anthropic-skills/skills/theme-factory/LICENSE.txt +1 -1
- package/bundled/upstream/anthropic-skills/skills/web-artifacts-builder/LICENSE.txt +1 -1
- package/bundled/upstream/anthropic-skills/skills/webapp-testing/LICENSE.txt +1 -1
- package/bundled/upstream/ecc/.omc-source/bundle.json +2 -3
- package/bundled/upstream/ecc/.omc-source/manifests/.claude-plugin/marketplace.json +4 -4
- package/bundled/upstream/ecc/agents/a11y-architect.md +10 -2
- package/bundled/upstream/ecc/agents/architect.md +9 -0
- package/bundled/upstream/ecc/agents/build-error-resolver.md +9 -0
- package/bundled/upstream/ecc/agents/chief-of-staff.md +9 -0
- package/bundled/upstream/ecc/agents/code-architect.md +9 -0
- package/bundled/upstream/ecc/agents/code-explorer.md +10 -1
- package/bundled/upstream/ecc/agents/code-reviewer.md +87 -1
- package/bundled/upstream/ecc/agents/code-simplifier.md +9 -0
- package/bundled/upstream/ecc/agents/comment-analyzer.md +10 -1
- package/bundled/upstream/ecc/agents/conversation-analyzer.md +9 -0
- package/bundled/upstream/ecc/agents/cpp-build-resolver.md +9 -0
- package/bundled/upstream/ecc/agents/cpp-reviewer.md +9 -0
- package/bundled/upstream/ecc/agents/csharp-reviewer.md +9 -0
- package/bundled/upstream/ecc/agents/dart-build-resolver.md +9 -0
- package/bundled/upstream/ecc/agents/database-reviewer.md +9 -0
- package/bundled/upstream/ecc/agents/django-build-resolver.md +252 -0
- package/bundled/upstream/ecc/agents/django-reviewer.md +169 -0
- package/bundled/upstream/ecc/agents/doc-updater.md +9 -0
- package/bundled/upstream/ecc/agents/docs-lookup.md +9 -0
- package/bundled/upstream/ecc/agents/e2e-runner.md +9 -0
- package/bundled/upstream/ecc/agents/fastapi-reviewer.md +79 -0
- package/bundled/upstream/ecc/agents/flutter-reviewer.md +9 -0
- package/bundled/upstream/ecc/agents/fsharp-reviewer.md +109 -0
- package/bundled/upstream/ecc/agents/gan-evaluator.md +9 -0
- package/bundled/upstream/ecc/agents/gan-generator.md +9 -0
- package/bundled/upstream/ecc/agents/gan-planner.md +9 -0
- package/bundled/upstream/ecc/agents/go-build-resolver.md +9 -0
- package/bundled/upstream/ecc/agents/go-reviewer.md +9 -0
- package/bundled/upstream/ecc/agents/harmonyos-app-resolver.md +182 -0
- package/bundled/upstream/ecc/agents/harness-optimizer.md +9 -0
- package/bundled/upstream/ecc/agents/healthcare-reviewer.md +9 -0
- package/bundled/upstream/ecc/agents/homelab-architect.md +107 -0
- package/bundled/upstream/ecc/agents/java-build-resolver.md +133 -11
- package/bundled/upstream/ecc/agents/java-reviewer.md +130 -32
- package/bundled/upstream/ecc/agents/kotlin-build-resolver.md +9 -0
- package/bundled/upstream/ecc/agents/kotlin-reviewer.md +9 -0
- package/bundled/upstream/ecc/agents/loop-operator.md +9 -0
- package/bundled/upstream/ecc/agents/mle-reviewer.md +162 -0
- package/bundled/upstream/ecc/agents/network-architect.md +106 -0
- package/bundled/upstream/ecc/agents/network-config-reviewer.md +106 -0
- package/bundled/upstream/ecc/agents/network-troubleshooter.md +128 -0
- package/bundled/upstream/ecc/agents/opensource-forker.md +9 -0
- package/bundled/upstream/ecc/agents/opensource-packager.md +9 -0
- package/bundled/upstream/ecc/agents/opensource-sanitizer.md +9 -0
- package/bundled/upstream/ecc/agents/performance-optimizer.md +9 -0
- package/bundled/upstream/ecc/agents/planner.md +9 -0
- package/bundled/upstream/ecc/agents/pr-test-analyzer.md +9 -0
- package/bundled/upstream/ecc/agents/python-reviewer.md +9 -0
- package/bundled/upstream/ecc/agents/pytorch-build-resolver.md +12 -3
- package/bundled/upstream/ecc/agents/refactor-cleaner.md +9 -0
- package/bundled/upstream/ecc/agents/rust-build-resolver.md +9 -0
- package/bundled/upstream/ecc/agents/rust-reviewer.md +9 -0
- package/bundled/upstream/ecc/agents/security-reviewer.md +9 -0
- package/bundled/upstream/ecc/agents/seo-specialist.md +10 -1
- package/bundled/upstream/ecc/agents/silent-failure-hunter.md +9 -0
- package/bundled/upstream/ecc/agents/swift-build-resolver.md +170 -0
- package/bundled/upstream/ecc/agents/swift-reviewer.md +116 -0
- package/bundled/upstream/ecc/agents/tdd-guide.md +9 -0
- package/bundled/upstream/ecc/agents/type-design-analyzer.md +10 -1
- package/bundled/upstream/ecc/agents/typescript-reviewer.md +9 -0
- package/bundled/upstream/ecc/commands/auto-update.md +28 -0
- package/bundled/upstream/ecc/commands/build-fix.md +4 -0
- package/bundled/upstream/ecc/commands/checkpoint.md +4 -0
- package/bundled/upstream/ecc/commands/code-review.md +3 -3
- package/bundled/upstream/ecc/commands/cost-report.md +107 -0
- package/bundled/upstream/ecc/commands/cpp-build.md +1 -1
- package/bundled/upstream/ecc/commands/cpp-test.md +1 -1
- package/bundled/upstream/ecc/commands/ecc-guide.md +93 -0
- package/bundled/upstream/ecc/commands/fastapi-review.md +39 -0
- package/bundled/upstream/ecc/commands/flutter-build.md +1 -1
- package/bundled/upstream/ecc/commands/flutter-test.md +1 -1
- package/bundled/upstream/ecc/commands/gan-build.md +4 -0
- package/bundled/upstream/ecc/commands/gan-design.md +4 -0
- package/bundled/upstream/ecc/commands/go-build.md +1 -1
- package/bundled/upstream/ecc/commands/go-test.md +1 -1
- package/bundled/upstream/ecc/commands/harness-audit.md +4 -0
- package/bundled/upstream/ecc/commands/jira.md +2 -2
- package/bundled/upstream/ecc/commands/kotlin-build.md +1 -1
- package/bundled/upstream/ecc/commands/kotlin-test.md +1 -1
- package/bundled/upstream/ecc/commands/learn.md +4 -0
- package/bundled/upstream/ecc/commands/loop-start.md +4 -0
- package/bundled/upstream/ecc/commands/loop-status.md +54 -1
- package/bundled/upstream/ecc/commands/model-route.md +4 -0
- package/bundled/upstream/ecc/commands/multi-backend.md +4 -0
- package/bundled/upstream/ecc/commands/multi-execute.md +4 -0
- package/bundled/upstream/ecc/commands/multi-frontend.md +4 -0
- package/bundled/upstream/ecc/commands/multi-plan.md +4 -0
- package/bundled/upstream/ecc/commands/multi-workflow.md +4 -0
- package/bundled/upstream/ecc/commands/plan-prd.md +160 -0
- package/bundled/upstream/ecc/commands/plan.md +96 -13
- package/bundled/upstream/ecc/commands/pm2.md +4 -0
- package/bundled/upstream/ecc/commands/pr.md +184 -0
- package/bundled/upstream/ecc/commands/project-init.md +86 -0
- package/bundled/upstream/ecc/commands/python-review.md +1 -1
- package/bundled/upstream/ecc/commands/quality-gate.md +4 -0
- package/bundled/upstream/ecc/commands/refactor-clean.md +4 -0
- package/bundled/upstream/ecc/commands/rust-build.md +1 -1
- package/bundled/upstream/ecc/commands/rust-test.md +1 -1
- package/bundled/upstream/ecc/commands/security-scan.md +92 -0
- package/bundled/upstream/ecc/commands/sessions.md +6 -6
- package/bundled/upstream/ecc/commands/skill-health.md +3 -3
- package/bundled/upstream/ecc/commands/test-coverage.md +4 -0
- package/bundled/upstream/ecc/commands/update-codemaps.md +4 -0
- package/bundled/upstream/ecc/commands/update-docs.md +4 -0
- package/bundled/upstream/ecc/skills/accessibility/SKILL.md +1 -1
- package/bundled/upstream/ecc/skills/agent-architecture-audit/SKILL.md +256 -0
- package/bundled/upstream/ecc/skills/agent-payment-x402/SKILL.md +49 -3
- package/bundled/upstream/ecc/skills/agentic-os/SKILL.md +387 -0
- package/bundled/upstream/ecc/skills/angular-developer/SKILL.md +154 -0
- package/bundled/upstream/ecc/skills/angular-developer/references/angular-animations.md +160 -0
- package/bundled/upstream/ecc/skills/angular-developer/references/angular-aria.md +410 -0
- package/bundled/upstream/ecc/skills/angular-developer/references/cli.md +86 -0
- package/bundled/upstream/ecc/skills/angular-developer/references/component-harnesses.md +59 -0
- package/bundled/upstream/ecc/skills/angular-developer/references/component-styling.md +91 -0
- package/bundled/upstream/ecc/skills/angular-developer/references/components.md +117 -0
- package/bundled/upstream/ecc/skills/angular-developer/references/creating-services.md +97 -0
- package/bundled/upstream/ecc/skills/angular-developer/references/data-resolvers.md +69 -0
- package/bundled/upstream/ecc/skills/angular-developer/references/define-routes.md +67 -0
- package/bundled/upstream/ecc/skills/angular-developer/references/defining-providers.md +72 -0
- package/bundled/upstream/ecc/skills/angular-developer/references/di-fundamentals.md +120 -0
- package/bundled/upstream/ecc/skills/angular-developer/references/e2e-testing.md +56 -0
- package/bundled/upstream/ecc/skills/angular-developer/references/effects.md +83 -0
- package/bundled/upstream/ecc/skills/angular-developer/references/hierarchical-injectors.md +43 -0
- package/bundled/upstream/ecc/skills/angular-developer/references/host-elements.md +80 -0
- package/bundled/upstream/ecc/skills/angular-developer/references/injection-context.md +63 -0
- package/bundled/upstream/ecc/skills/angular-developer/references/inputs.md +101 -0
- package/bundled/upstream/ecc/skills/angular-developer/references/linked-signal.md +59 -0
- package/bundled/upstream/ecc/skills/angular-developer/references/loading-strategies.md +61 -0
- package/bundled/upstream/ecc/skills/angular-developer/references/mcp.md +108 -0
- package/bundled/upstream/ecc/skills/angular-developer/references/navigate-to-routes.md +69 -0
- package/bundled/upstream/ecc/skills/angular-developer/references/outputs.md +86 -0
- package/bundled/upstream/ecc/skills/angular-developer/references/reactive-forms.md +122 -0
- package/bundled/upstream/ecc/skills/angular-developer/references/rendering-strategies.md +44 -0
- package/bundled/upstream/ecc/skills/angular-developer/references/resource.md +77 -0
- package/bundled/upstream/ecc/skills/angular-developer/references/route-animations.md +56 -0
- package/bundled/upstream/ecc/skills/angular-developer/references/route-guards.md +52 -0
- package/bundled/upstream/ecc/skills/angular-developer/references/router-lifecycle.md +45 -0
- package/bundled/upstream/ecc/skills/angular-developer/references/router-testing.md +87 -0
- package/bundled/upstream/ecc/skills/angular-developer/references/show-routes-with-outlets.md +68 -0
- package/bundled/upstream/ecc/skills/angular-developer/references/signal-forms.md +795 -0
- package/bundled/upstream/ecc/skills/angular-developer/references/signals-overview.md +94 -0
- package/bundled/upstream/ecc/skills/angular-developer/references/tailwind-css.md +69 -0
- package/bundled/upstream/ecc/skills/angular-developer/references/template-driven-forms.md +114 -0
- package/bundled/upstream/ecc/skills/angular-developer/references/testing-fundamentals.md +65 -0
- package/bundled/upstream/ecc/skills/autonomous-agent-harness/SKILL.md +6 -0
- package/bundled/upstream/ecc/skills/backend-patterns/SKILL.md +8 -45
- package/bundled/upstream/ecc/skills/cisco-ios-patterns/SKILL.md +163 -0
- package/bundled/upstream/ecc/skills/configure-ecc/SKILL.md +31 -14
- package/bundled/upstream/ecc/skills/continuous-learning/SKILL.md +10 -2
- package/bundled/upstream/ecc/skills/continuous-learning-v2/SKILL.md +19 -5
- package/bundled/upstream/ecc/skills/continuous-learning-v2/agents/observer-loop.sh +44 -4
- package/bundled/upstream/ecc/skills/continuous-learning-v2/agents/observer.md +4 -4
- package/bundled/upstream/ecc/skills/continuous-learning-v2/agents/start-observer.sh +5 -1
- package/bundled/upstream/ecc/skills/continuous-learning-v2/hooks/observe.sh +21 -5
- package/bundled/upstream/ecc/skills/continuous-learning-v2/scripts/detect-project.sh +58 -13
- package/bundled/upstream/ecc/skills/continuous-learning-v2/scripts/instinct-cli.py +97 -4
- package/bundled/upstream/ecc/skills/continuous-learning-v2/scripts/lib/homunculus-dir.sh +31 -0
- package/bundled/upstream/ecc/skills/continuous-learning-v2/scripts/migrate-homunculus.sh +62 -0
- package/bundled/upstream/ecc/skills/continuous-learning-v2/scripts/test_parse_instinct.py +34 -0
- package/bundled/upstream/ecc/skills/cost-tracking/SKILL.md +147 -0
- package/bundled/upstream/ecc/skills/deep-research/SKILL.md +4 -0
- package/bundled/upstream/ecc/skills/defi-amm-security/SKILL.md +6 -0
- package/bundled/upstream/ecc/skills/django-celery/SKILL.md +457 -0
- package/bundled/upstream/ecc/skills/ecc-guide/SKILL.md +189 -0
- package/bundled/upstream/ecc/skills/error-handling/SKILL.md +376 -0
- package/bundled/upstream/ecc/skills/exa-search/SKILL.md +4 -0
- package/bundled/upstream/ecc/skills/fal-ai-media/SKILL.md +4 -0
- package/bundled/upstream/ecc/skills/fastapi-patterns/SKILL.md +327 -0
- package/bundled/upstream/ecc/skills/flox-environments/SKILL.md +496 -0
- package/bundled/upstream/ecc/skills/frontend-design-direction/SKILL.md +92 -0
- package/bundled/upstream/ecc/skills/frontend-slides/animation-patterns.md +122 -0
- package/bundled/upstream/ecc/skills/frontend-slides/html-template.md +419 -0
- package/bundled/upstream/ecc/skills/frontend-slides/scripts/export-pdf.sh +418 -0
- package/bundled/upstream/ecc/skills/frontend-slides/scripts/extract-pptx.py +96 -0
- package/bundled/upstream/ecc/skills/frontend-slides/viewport-base.css +153 -0
- package/bundled/upstream/ecc/skills/fsharp-testing/SKILL.md +280 -0
- package/bundled/upstream/ecc/skills/gateguard/SKILL.md +4 -0
- package/bundled/upstream/ecc/skills/hermes-imports/SKILL.md +88 -0
- package/bundled/upstream/ecc/skills/homelab-network-readiness/SKILL.md +169 -0
- package/bundled/upstream/ecc/skills/homelab-network-setup/SKILL.md +129 -0
- package/bundled/upstream/ecc/skills/homelab-pihole-dns/SKILL.md +274 -0
- package/bundled/upstream/ecc/skills/homelab-vlan-segmentation/SKILL.md +311 -0
- package/bundled/upstream/ecc/skills/homelab-wireguard-vpn/SKILL.md +305 -0
- package/bundled/upstream/ecc/skills/ios-icon-gen/SKILL.md +157 -0
- package/bundled/upstream/ecc/skills/ios-icon-gen/scripts/generate_icons.swift +258 -0
- package/bundled/upstream/ecc/skills/ios-icon-gen/scripts/iconify_gen.sh +235 -0
- package/bundled/upstream/ecc/skills/java-coding-standards/SKILL.md +241 -5
- package/bundled/upstream/ecc/skills/make-interfaces-feel-better/SKILL.md +151 -0
- package/bundled/upstream/ecc/skills/mle-workflow/SKILL.md +346 -0
- package/bundled/upstream/ecc/skills/motion-advanced/SKILL.md +596 -0
- package/bundled/upstream/ecc/skills/motion-foundations/SKILL.md +299 -0
- package/bundled/upstream/ecc/skills/motion-patterns/SKILL.md +435 -0
- package/bundled/upstream/ecc/skills/motion-ui/SKILL.md +575 -0
- package/bundled/upstream/ecc/skills/mysql-patterns/SKILL.md +412 -0
- package/bundled/upstream/ecc/skills/netmiko-ssh-automation/SKILL.md +173 -0
- package/bundled/upstream/ecc/skills/network-bgp-diagnostics/SKILL.md +167 -0
- package/bundled/upstream/ecc/skills/network-config-validation/SKILL.md +210 -0
- package/bundled/upstream/ecc/skills/network-interface-health/SKILL.md +152 -0
- package/bundled/upstream/ecc/skills/openclaw-persona-forge/SKILL.md +1 -9
- package/bundled/upstream/ecc/skills/plan-orchestrate/SKILL.md +262 -0
- package/bundled/upstream/ecc/skills/prisma-patterns/SKILL.md +371 -0
- package/bundled/upstream/ecc/skills/production-audit/SKILL.md +206 -0
- package/bundled/upstream/ecc/skills/prompt-optimizer/SKILL.md +24 -400
- package/bundled/upstream/ecc/skills/quarkus-patterns/SKILL.md +722 -0
- package/bundled/upstream/ecc/skills/quarkus-security/SKILL.md +467 -0
- package/bundled/upstream/ecc/skills/quarkus-tdd/SKILL.md +811 -0
- package/bundled/upstream/ecc/skills/quarkus-verification/SKILL.md +479 -0
- package/bundled/upstream/ecc/skills/redis-patterns/SKILL.md +403 -0
- package/bundled/upstream/ecc/skills/scientific-db-pubmed-database/SKILL.md +175 -0
- package/bundled/upstream/ecc/skills/scientific-db-uspto-database/SKILL.md +177 -0
- package/bundled/upstream/ecc/skills/scientific-pkg-gget/SKILL.md +166 -0
- package/bundled/upstream/ecc/skills/scientific-thinking-literature-review/SKILL.md +192 -0
- package/bundled/upstream/ecc/skills/scientific-thinking-scholar-evaluation/SKILL.md +160 -0
- package/bundled/upstream/ecc/skills/search-first/SKILL.md +23 -2
- package/bundled/upstream/ecc/skills/security-review/SKILL.md +10 -2
- package/bundled/upstream/ecc/skills/skill-comply/scripts/runner.py +28 -3
- package/bundled/upstream/ecc/skills/skill-comply/tests/test_runner.py +172 -0
- package/bundled/upstream/ecc/skills/skill-scout/SKILL.md +140 -0
- package/bundled/upstream/ecc/skills/skill-stocktake/SKILL.md +1 -0
- package/bundled/upstream/ecc/skills/strategic-compact/SKILL.md +2 -2
- package/bundled/upstream/ecc/skills/tinystruct-patterns/SKILL.md +203 -0
- package/bundled/upstream/ecc/skills/tinystruct-patterns/references/architecture.md +90 -0
- package/bundled/upstream/ecc/skills/tinystruct-patterns/references/data-handling.md +60 -0
- package/bundled/upstream/ecc/skills/tinystruct-patterns/references/database.md +99 -0
- package/bundled/upstream/ecc/skills/tinystruct-patterns/references/routing.md +64 -0
- package/bundled/upstream/ecc/skills/tinystruct-patterns/references/system-usage.md +97 -0
- package/bundled/upstream/ecc/skills/tinystruct-patterns/references/testing.md +72 -0
- package/bundled/upstream/ecc/skills/ui-to-vue/SKILL.md +134 -0
- package/bundled/upstream/ecc/skills/vite-patterns/SKILL.md +449 -0
- package/bundled/upstream/ecc/skills/windows-desktop-e2e/SKILL.md +788 -0
- package/bundled/upstream/ecc/skills/x-api/SKILL.md +4 -0
- package/bundled/upstream/oh-my-claudecode/.omc-source/bundle.json +20 -0
- package/bundled/upstream/oh-my-claudecode/agents/analyst.md +2 -1
- package/bundled/upstream/oh-my-claudecode/agents/architect.md +2 -1
- package/bundled/upstream/oh-my-claudecode/agents/code-reviewer.md +26 -7
- package/bundled/upstream/oh-my-claudecode/agents/critic.md +2 -1
- package/bundled/upstream/oh-my-claudecode/agents/debugger.md +2 -1
- package/bundled/upstream/oh-my-claudecode/agents/designer.md +14 -1
- package/bundled/upstream/oh-my-claudecode/agents/document-specialist.md +1 -1
- package/bundled/upstream/oh-my-claudecode/agents/executor.md +2 -1
- package/bundled/upstream/oh-my-claudecode/agents/explore.md +2 -1
- package/bundled/upstream/oh-my-claudecode/agents/git-master.md +2 -1
- package/bundled/upstream/oh-my-claudecode/agents/planner.md +2 -1
- package/bundled/upstream/oh-my-claudecode/agents/qa-tester.md +2 -1
- package/bundled/upstream/oh-my-claudecode/agents/scientist.md +2 -1
- package/bundled/upstream/oh-my-claudecode/agents/security-reviewer.md +2 -1
- package/bundled/upstream/oh-my-claudecode/agents/test-engineer.md +2 -1
- package/bundled/upstream/oh-my-claudecode/agents/tracer.md +2 -1
- package/bundled/upstream/oh-my-claudecode/agents/verifier.md +2 -1
- package/bundled/upstream/oh-my-claudecode/agents/writer.md +2 -1
- package/bundled/upstream/oh-my-claudecode/skills/AGENTS.md +4 -3
- package/bundled/upstream/oh-my-claudecode/skills/ai-slop-cleaner/SKILL.md +12 -0
- package/bundled/upstream/oh-my-claudecode/skills/deep-dive/SKILL.md +69 -13
- package/bundled/upstream/oh-my-claudecode/skills/deep-interview/SKILL.md +176 -63
- package/bundled/upstream/oh-my-claudecode/skills/learner/SKILL.md +3 -1
- package/bundled/upstream/oh-my-claudecode/skills/omc-doctor/SKILL.md +22 -3
- package/bundled/upstream/oh-my-claudecode/skills/omc-reference/SKILL.md +1 -1
- package/bundled/upstream/oh-my-claudecode/skills/omc-setup/phases/01-install-claude-md.md +2 -2
- package/bundled/upstream/oh-my-claudecode/skills/omc-setup/phases/02-configure.md +45 -2
- package/bundled/upstream/oh-my-claudecode/skills/omc-setup/phases/03-integrations.md +46 -5
- package/bundled/upstream/oh-my-claudecode/skills/plan/SKILL.md +19 -17
- package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/lib/config.sh +1 -1
- package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/lib/parse.sh +1 -1
- package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/lib/providers/azure-devops.sh +1 -1
- package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/lib/providers/bitbucket.sh +1 -1
- package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/lib/providers/gitea.sh +1 -1
- package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/lib/providers/github.sh +1 -1
- package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/lib/providers/gitlab.sh +1 -1
- package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/lib/providers/interface.sh +1 -1
- package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/lib/providers/jira.sh +1 -1
- package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/lib/session.sh +1 -1
- package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/lib/tmux.sh +1 -1
- package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/lib/worktree.sh +1 -1
- package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/psm.sh +1 -1
- package/bundled/upstream/oh-my-claudecode/skills/project-session-manager/tests/test-psm-prompt-injection.sh +1 -1
- package/bundled/upstream/oh-my-claudecode/skills/ralph/SKILL.md +8 -8
- package/bundled/upstream/oh-my-claudecode/skills/ralplan/SKILL.md +9 -5
- package/bundled/upstream/oh-my-claudecode/skills/skill/SKILL.md +6 -6
- package/bundled/upstream/oh-my-claudecode/skills/skillify/SKILL.md +19 -3
- package/bundled/upstream/oh-my-claudecode/skills/trace/SKILL.md +3 -1
- package/bundled/upstream/oh-my-claudecode/skills/ultrawork/SKILL.md +20 -7
- package/bundled/upstream/superpowers/.omc-source/bundle.json +21 -0
- package/bundled/upstream/superpowers/hooks/hooks-cursor.json +1 -1
- package/bundled/upstream/superpowers/skills/executing-plans/SKILL.md +1 -1
- package/bundled/upstream/superpowers/skills/finishing-a-development-branch/SKILL.md +93 -42
- package/bundled/upstream/superpowers/skills/requesting-code-review/SKILL.md +7 -9
- package/bundled/upstream/superpowers/skills/requesting-code-review/code-reviewer.md +107 -85
- package/bundled/upstream/superpowers/skills/subagent-driven-development/SKILL.md +3 -1
- package/bundled/upstream/superpowers/skills/subagent-driven-development/code-quality-reviewer-prompt.md +2 -3
- package/bundled/upstream/superpowers/skills/systematic-debugging/CREATION-LOG.md +1 -1
- package/bundled/upstream/superpowers/skills/systematic-debugging/root-cause-tracing.md +1 -1
- package/bundled/upstream/superpowers/skills/using-git-worktrees/SKILL.md +95 -98
- package/bundled/upstream/superpowers/skills/using-superpowers/references/codex-tools.md +7 -48
- package/bundled/upstream/superpowers/skills/using-superpowers/references/copilot-tools.md +1 -11
- package/bundled/upstream/superpowers/skills/using-superpowers/references/gemini-tools.md +21 -3
- package/bundled/upstream/superpowers/skills/writing-plans/SKILL.md +1 -1
- package/package.json +1 -1
- package/bundled/upstream/anthropic-skills/skills/claude-api/python/agent-sdk/README.md +0 -355
- package/bundled/upstream/anthropic-skills/skills/claude-api/python/agent-sdk/patterns.md +0 -359
- package/bundled/upstream/anthropic-skills/skills/claude-api/typescript/agent-sdk/README.md +0 -297
- package/bundled/upstream/anthropic-skills/skills/claude-api/typescript/agent-sdk/patterns.md +0 -209
- package/bundled/upstream/ecc/commands/agent-sort.md +0 -23
- package/bundled/upstream/ecc/commands/claw.md +0 -23
- package/bundled/upstream/ecc/commands/context-budget.md +0 -23
- package/bundled/upstream/ecc/commands/devfleet.md +0 -23
- package/bundled/upstream/ecc/commands/docs.md +0 -23
- package/bundled/upstream/ecc/commands/e2e.md +0 -268
- package/bundled/upstream/ecc/commands/eval.md +0 -23
- package/bundled/upstream/ecc/commands/orchestrate.md +0 -135
- package/bundled/upstream/ecc/commands/prompt-optimize.md +0 -23
- package/bundled/upstream/ecc/commands/rules-distill.md +0 -20
- package/bundled/upstream/ecc/commands/tdd.md +0 -231
- package/bundled/upstream/ecc/commands/verify.md +0 -23
- package/bundled/upstream/ecc/skills/claude-api/SKILL.md +0 -337
- package/bundled/upstream/ecc/skills/frontend-design/SKILL.md +0 -145
- package/bundled/upstream/superpowers/agents/code-reviewer.md +0 -48
- package/bundled/upstream/superpowers/commands/brainstorm.md +0 -5
- package/bundled/upstream/superpowers/commands/execute-plan.md +0 -5
- package/bundled/upstream/superpowers/commands/write-plan.md +0 -5
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* capture-reference.mjs — Stage 2: Playwright reference screenshot capture
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* node capture-reference.mjs <h5-url-or-build> --device "iPhone 15 Pro" --out <dir>
|
|
7
|
+
* [--screen <name>] [--mask x,y,w,h] [--settle-ms <ms>]
|
|
8
|
+
*
|
|
9
|
+
* Outputs under <dir>/reference/:
|
|
10
|
+
* <screen>/full.png — full-page screenshot (animations frozen)
|
|
11
|
+
* <screen>/<component>.png — per-landmark crops by getBoundingClientRect()
|
|
12
|
+
* manifest.json — schema:"h5-to-swiftui/reference@1", device, logical_size,
|
|
13
|
+
* screens:[{name,components:[{name,bbox_css_px,selector}]}], masks
|
|
14
|
+
*
|
|
15
|
+
* Exit codes:
|
|
16
|
+
* 0 — screenshots written, manifest.json produced
|
|
17
|
+
* 1 — fatal error (bad args, navigation failed)
|
|
18
|
+
* 2 — playwright not installed (actionable hint printed)
|
|
19
|
+
*
|
|
20
|
+
* Examples:
|
|
21
|
+
* node capture-reference.mjs http://localhost:5173 --device "iPhone 15 Pro" --out ./artifacts
|
|
22
|
+
* node capture-reference.mjs http://localhost:5173 --device "iPhone 15 Pro" --out ./artifacts --screen home --mask 0,0,393,50
|
|
23
|
+
* node capture-reference.mjs http://localhost:5173 --device "iPhone 15 Pro" --out ./artifacts --settle-ms 1500
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'node:fs';
|
|
27
|
+
import { resolve, join } from 'node:path';
|
|
28
|
+
|
|
29
|
+
// ── Device profiles (logical px, deviceScaleFactor) ──────────────────────────
|
|
30
|
+
|
|
31
|
+
const DEVICES = {
|
|
32
|
+
'iPhone 15 Pro': { width: 393, height: 852, deviceScaleFactor: 3, userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1' },
|
|
33
|
+
'iPhone 14 Pro': { width: 393, height: 852, deviceScaleFactor: 3, userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1' },
|
|
34
|
+
'iPhone 15': { width: 390, height: 844, deviceScaleFactor: 3, userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1' },
|
|
35
|
+
'iPhone SE': { width: 375, height: 667, deviceScaleFactor: 2, userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1' },
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// Landmark selectors for per-component crops
|
|
39
|
+
const LANDMARK_SELECTORS = [
|
|
40
|
+
{ name: 'nav', selector: 'nav, [role="navigation"]' },
|
|
41
|
+
{ name: 'header', selector: 'header, [role="banner"]' },
|
|
42
|
+
{ name: 'main', selector: 'main, [role="main"]' },
|
|
43
|
+
{ name: 'footer', selector: 'footer, [role="contentinfo"]' },
|
|
44
|
+
{ name: 'hero', selector: '[class*="hero"], [class*="banner"], [class*="jumbotron"]' },
|
|
45
|
+
{ name: 'cta', selector: '[class*="cta"], [class*="call-to-action"]' },
|
|
46
|
+
{ name: 'card', selector: '[class*="card"]:first-of-type' },
|
|
47
|
+
{ name: 'list', selector: 'ul:first-of-type, ol:first-of-type, [class*="list"]:first-of-type' },
|
|
48
|
+
{ name: 'form', selector: 'form:first-of-type' },
|
|
49
|
+
{ name: 'button', selector: 'button:first-of-type, [class*="btn"]:first-of-type' },
|
|
50
|
+
];
|
|
51
|
+
|
|
52
|
+
// ── CLI parsing ───────────────────────────────────────────────────────────────
|
|
53
|
+
|
|
54
|
+
const args = process.argv.slice(2);
|
|
55
|
+
|
|
56
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
57
|
+
console.log(`capture-reference.mjs — Stage 2 Playwright reference capture
|
|
58
|
+
|
|
59
|
+
Usage:
|
|
60
|
+
node capture-reference.mjs <h5-url-or-build> --device "iPhone 15 Pro" --out <dir>
|
|
61
|
+
[--screen <name>] [--mask x,y,w,h] [--settle-ms <ms>]
|
|
62
|
+
|
|
63
|
+
Arguments:
|
|
64
|
+
<h5-url-or-build> Running URL (http://...) or build directory
|
|
65
|
+
--device <name> Device profile (required)
|
|
66
|
+
--out <dir> Output directory (required)
|
|
67
|
+
--screen <name> Screen name for the manifest (default: "main")
|
|
68
|
+
--mask x,y,w,h Mask rectangle in CSS px — repeatable
|
|
69
|
+
--settle-ms <ms> Additional settle delay after networkidle (default: 300)
|
|
70
|
+
|
|
71
|
+
Supported devices:
|
|
72
|
+
"iPhone 15 Pro" 393×852 @3x (default)
|
|
73
|
+
"iPhone 14 Pro" 393×852 @3x
|
|
74
|
+
"iPhone 15" 390×844 @3x
|
|
75
|
+
"iPhone SE" 375×667 @2x
|
|
76
|
+
|
|
77
|
+
Prerequisites:
|
|
78
|
+
playwright must be installed:
|
|
79
|
+
npm install --save-dev playwright && npx playwright install chromium
|
|
80
|
+
|
|
81
|
+
Outputs:
|
|
82
|
+
<out>/reference/<screen>/full.png Full-page screenshot
|
|
83
|
+
<out>/reference/<screen>/<component>.png Per-landmark crops
|
|
84
|
+
<out>/reference/manifest.json Capture manifest
|
|
85
|
+
|
|
86
|
+
Exit codes:
|
|
87
|
+
0 Success
|
|
88
|
+
1 Fatal error (bad args / navigation failed)
|
|
89
|
+
2 playwright not installed
|
|
90
|
+
|
|
91
|
+
Examples:
|
|
92
|
+
node capture-reference.mjs http://localhost:5173 --device "iPhone 15 Pro" --out ./artifacts
|
|
93
|
+
node capture-reference.mjs http://localhost:5173 --device "iPhone 15 Pro" --out ./artifacts \\
|
|
94
|
+
--screen home --mask 0,0,393,50 --settle-ms 1000
|
|
95
|
+
`);
|
|
96
|
+
process.exit(0);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Parse positional: first non-flag arg
|
|
100
|
+
let h5Target = null;
|
|
101
|
+
for (const a of args) {
|
|
102
|
+
if (!a.startsWith('--')) { h5Target = a; break; }
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (!h5Target) {
|
|
106
|
+
console.error('Error: <h5-url-or-build> is required.\nRun with --help for usage.');
|
|
107
|
+
process.exit(1);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function getFlag(flag, fallback = null) {
|
|
111
|
+
const idx = args.indexOf(flag);
|
|
112
|
+
if (idx === -1) return fallback;
|
|
113
|
+
const val = args[idx + 1];
|
|
114
|
+
if (!val || val.startsWith('--')) {
|
|
115
|
+
console.error(`Error: ${flag} requires an argument.`);
|
|
116
|
+
process.exit(1);
|
|
117
|
+
}
|
|
118
|
+
return val;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function getAllFlags(flag) {
|
|
122
|
+
const results = [];
|
|
123
|
+
for (let i = 0; i < args.length; i++) {
|
|
124
|
+
if (args[i] === flag && args[i + 1] && !args[i + 1].startsWith('--')) {
|
|
125
|
+
results.push(args[i + 1]);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return results;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const deviceName = getFlag('--device', 'iPhone 15 Pro');
|
|
132
|
+
const outDirRaw = getFlag('--out');
|
|
133
|
+
const screenName = getFlag('--screen', 'main');
|
|
134
|
+
const settleMsRaw = getFlag('--settle-ms', '300');
|
|
135
|
+
const maskStrings = getAllFlags('--mask');
|
|
136
|
+
|
|
137
|
+
if (!outDirRaw) {
|
|
138
|
+
console.error('Error: --out <dir> is required.\nRun with --help for usage.');
|
|
139
|
+
process.exit(1);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const outDir = resolve(outDirRaw);
|
|
143
|
+
const settleMs = parseInt(settleMsRaw, 10);
|
|
144
|
+
|
|
145
|
+
if (isNaN(settleMs) || settleMs < 0) {
|
|
146
|
+
console.error(`Error: --settle-ms must be a non-negative integer, got: ${settleMsRaw}`);
|
|
147
|
+
process.exit(1);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const device = DEVICES[deviceName];
|
|
151
|
+
if (!device) {
|
|
152
|
+
console.error(`Error: unknown device "${deviceName}".\nSupported: ${Object.keys(DEVICES).map(d => `"${d}"`).join(', ')}`);
|
|
153
|
+
process.exit(1);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Parse mask strings: "x,y,w,h"
|
|
157
|
+
const masks = [];
|
|
158
|
+
for (const ms of maskStrings) {
|
|
159
|
+
const parts = ms.split(',').map(p => parseFloat(p.trim()));
|
|
160
|
+
if (parts.length !== 4 || parts.some(isNaN)) {
|
|
161
|
+
console.error(`Error: --mask must be "x,y,w,h" (CSS px), got: "${ms}"`);
|
|
162
|
+
process.exit(1);
|
|
163
|
+
}
|
|
164
|
+
masks.push({ x: parts[0], y: parts[1], w: parts[2], h: parts[3] });
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Resolve URL: if it looks like a path, serve via file URL or note static serve needed
|
|
168
|
+
let targetUrl = h5Target;
|
|
169
|
+
if (!h5Target.startsWith('http://') && !h5Target.startsWith('https://')) {
|
|
170
|
+
const absPath = resolve(h5Target);
|
|
171
|
+
if (!existsSync(absPath)) {
|
|
172
|
+
console.error(`Error: path "${h5Target}" does not exist. Provide a running URL or an existing build directory.`);
|
|
173
|
+
process.exit(1);
|
|
174
|
+
}
|
|
175
|
+
// For a directory, construct a file URL to index.html — may not work for all apps
|
|
176
|
+
const indexHtml = join(absPath, 'index.html');
|
|
177
|
+
if (!existsSync(indexHtml)) {
|
|
178
|
+
console.error(`Error: no index.html found in "${absPath}". Start a dev server and pass its URL instead.`);
|
|
179
|
+
process.exit(1);
|
|
180
|
+
}
|
|
181
|
+
targetUrl = `file://${indexHtml}`;
|
|
182
|
+
console.warn(`Warning: using file:// URL. Some apps may require a running dev server for correct rendering.`);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// ── Playwright check ──────────────────────────────────────────────────────────
|
|
186
|
+
|
|
187
|
+
let playwright;
|
|
188
|
+
try {
|
|
189
|
+
playwright = await import('playwright');
|
|
190
|
+
} catch {
|
|
191
|
+
console.error(
|
|
192
|
+
'\nError: playwright is not installed. capture-reference.mjs requires it.\n\n' +
|
|
193
|
+
'Install with:\n' +
|
|
194
|
+
' npm install --save-dev playwright && npx playwright install chromium\n\n' +
|
|
195
|
+
'Then re-run this script.'
|
|
196
|
+
);
|
|
197
|
+
process.exit(2);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// ── Setup output dirs ─────────────────────────────────────────────────────────
|
|
201
|
+
|
|
202
|
+
const refDir = join(outDir, 'reference');
|
|
203
|
+
const screenDir = join(refDir, screenName);
|
|
204
|
+
mkdirSync(screenDir, { recursive: true });
|
|
205
|
+
|
|
206
|
+
// ── Browser launch + capture ──────────────────────────────────────────────────
|
|
207
|
+
|
|
208
|
+
console.log(`Device: ${deviceName} (${device.width}×${device.height} @${device.deviceScaleFactor}x)`);
|
|
209
|
+
console.log(`URL: ${targetUrl}`);
|
|
210
|
+
console.log(`Output: ${screenDir}`);
|
|
211
|
+
console.log(`Masks: ${masks.length} region(s)`);
|
|
212
|
+
console.log(`Settle: ${settleMs}ms`);
|
|
213
|
+
|
|
214
|
+
const { chromium } = playwright;
|
|
215
|
+
|
|
216
|
+
const browser = await chromium.launch();
|
|
217
|
+
const context = await browser.newContext({
|
|
218
|
+
viewport: { width: device.width, height: device.height },
|
|
219
|
+
deviceScaleFactor: device.deviceScaleFactor,
|
|
220
|
+
userAgent: device.userAgent,
|
|
221
|
+
colorScheme: 'light',
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
const page = await context.newPage();
|
|
225
|
+
|
|
226
|
+
// ── Freeze animations per render-equivalence-calibration.md ──────────────────
|
|
227
|
+
|
|
228
|
+
await page.addInitScript(() => {
|
|
229
|
+
const style = document.createElement('style');
|
|
230
|
+
style.textContent = `
|
|
231
|
+
*, *::before, *::after {
|
|
232
|
+
animation: none !important;
|
|
233
|
+
transition: none !important;
|
|
234
|
+
caret-color: transparent !important;
|
|
235
|
+
}
|
|
236
|
+
`;
|
|
237
|
+
document.head.appendChild(style);
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
// Navigate
|
|
241
|
+
console.log(`\nNavigating...`);
|
|
242
|
+
try {
|
|
243
|
+
await page.goto(targetUrl, { waitUntil: 'networkidle', timeout: 60_000 });
|
|
244
|
+
} catch (e) {
|
|
245
|
+
await browser.close();
|
|
246
|
+
console.error(`Error: navigation failed: ${e.message}`);
|
|
247
|
+
process.exit(1);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Wait for fonts (render-equivalence-calibration.md: webfont/async settle)
|
|
251
|
+
try {
|
|
252
|
+
await page.waitForFunction(() => document.fonts.ready, { timeout: 10_000 });
|
|
253
|
+
} catch {
|
|
254
|
+
console.warn('Warning: fonts.ready timed out — continuing');
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Additional settle
|
|
258
|
+
if (settleMs > 0) {
|
|
259
|
+
await new Promise(r => setTimeout(r, settleMs));
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// Inject animation freeze again after page load (catches dynamically added styles)
|
|
263
|
+
await page.addStyleTag({
|
|
264
|
+
content: `*, *::before, *::after { animation: none !important; transition: none !important; caret-color: transparent !important; }`,
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
// ── Apply masks (draw opaque rects over sensitive regions) ───────────────────
|
|
268
|
+
|
|
269
|
+
if (masks.length > 0) {
|
|
270
|
+
await page.evaluate((maskList) => {
|
|
271
|
+
for (const m of maskList) {
|
|
272
|
+
const div = document.createElement('div');
|
|
273
|
+
Object.assign(div.style, {
|
|
274
|
+
position: 'fixed',
|
|
275
|
+
left: `${m.x}px`,
|
|
276
|
+
top: `${m.y}px`,
|
|
277
|
+
width: `${m.w}px`,
|
|
278
|
+
height: `${m.h}px`,
|
|
279
|
+
background: '#000',
|
|
280
|
+
zIndex: '2147483647',
|
|
281
|
+
pointerEvents: 'none',
|
|
282
|
+
});
|
|
283
|
+
document.body.appendChild(div);
|
|
284
|
+
}
|
|
285
|
+
}, masks);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// ── Full-page screenshot ──────────────────────────────────────────────────────
|
|
289
|
+
|
|
290
|
+
const fullPath = join(screenDir, 'full.png');
|
|
291
|
+
await page.screenshot({ path: fullPath, fullPage: true });
|
|
292
|
+
console.log(`\nFull screenshot: ${fullPath}`);
|
|
293
|
+
|
|
294
|
+
// ── Per-component crops ───────────────────────────────────────────────────────
|
|
295
|
+
|
|
296
|
+
const components = [];
|
|
297
|
+
|
|
298
|
+
for (const { name: compName, selector } of LANDMARK_SELECTORS) {
|
|
299
|
+
let bbox = null;
|
|
300
|
+
try {
|
|
301
|
+
bbox = await page.evaluate((sel) => {
|
|
302
|
+
const el = document.querySelector(sel);
|
|
303
|
+
if (!el) return null;
|
|
304
|
+
const rect = el.getBoundingClientRect();
|
|
305
|
+
return { x: rect.x, y: rect.y, width: rect.width, height: rect.height };
|
|
306
|
+
}, selector);
|
|
307
|
+
} catch {
|
|
308
|
+
continue;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
if (!bbox || bbox.width <= 0 || bbox.height <= 0) continue;
|
|
312
|
+
|
|
313
|
+
// Clip must be within the logical viewport
|
|
314
|
+
const clip = {
|
|
315
|
+
x: Math.max(0, Math.floor(bbox.x)),
|
|
316
|
+
y: Math.max(0, Math.floor(bbox.y)),
|
|
317
|
+
width: Math.min(device.width - Math.max(0, Math.floor(bbox.x)), Math.ceil(bbox.width)),
|
|
318
|
+
height: Math.min(device.height - Math.max(0, Math.floor(bbox.y)), Math.ceil(bbox.height)),
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
if (clip.width <= 0 || clip.height <= 0) continue;
|
|
322
|
+
|
|
323
|
+
const compPath = join(screenDir, `${compName}.png`);
|
|
324
|
+
try {
|
|
325
|
+
await page.screenshot({ path: compPath, clip });
|
|
326
|
+
console.log(` Component "${compName}": bbox=${JSON.stringify(bbox)} → ${compPath}`);
|
|
327
|
+
components.push({
|
|
328
|
+
name: compName,
|
|
329
|
+
bbox_css_px: { x: bbox.x, y: bbox.y, width: bbox.width, height: bbox.height },
|
|
330
|
+
selector,
|
|
331
|
+
file: `${screenName}/${compName}.png`,
|
|
332
|
+
});
|
|
333
|
+
} catch (e) {
|
|
334
|
+
console.warn(` Warning: could not crop "${compName}": ${e.message}`);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
await browser.close();
|
|
339
|
+
|
|
340
|
+
// ── Manifest ──────────────────────────────────────────────────────────────────
|
|
341
|
+
|
|
342
|
+
const manifestPath = join(refDir, 'manifest.json');
|
|
343
|
+
|
|
344
|
+
// Load existing manifest if present (multiple screen runs)
|
|
345
|
+
let manifest;
|
|
346
|
+
try {
|
|
347
|
+
manifest = JSON.parse(readFileSync(manifestPath, 'utf8'));
|
|
348
|
+
} catch {
|
|
349
|
+
manifest = {
|
|
350
|
+
schema: 'h5-to-swiftui/reference@1',
|
|
351
|
+
device: deviceName,
|
|
352
|
+
logical_size: [device.width, device.height],
|
|
353
|
+
device_scale_factor: device.deviceScaleFactor,
|
|
354
|
+
screens: [],
|
|
355
|
+
masks: [],
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// Update masks list (union)
|
|
360
|
+
for (const m of masks) {
|
|
361
|
+
const dup = manifest.masks.some(e => e.x === m.x && e.y === m.y && e.w === m.w && e.h === m.h);
|
|
362
|
+
if (!dup) manifest.masks.push(m);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// Update or append screen entry
|
|
366
|
+
const existingIdx = manifest.screens.findIndex(s => s.name === screenName);
|
|
367
|
+
const screenEntry = {
|
|
368
|
+
name: screenName,
|
|
369
|
+
full_screenshot: `${screenName}/full.png`,
|
|
370
|
+
components,
|
|
371
|
+
captured_at: new Date().toISOString(),
|
|
372
|
+
settle_ms: settleMs,
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
if (existingIdx !== -1) {
|
|
376
|
+
manifest.screens[existingIdx] = screenEntry;
|
|
377
|
+
} else {
|
|
378
|
+
manifest.screens.push(screenEntry);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + '\n', 'utf8');
|
|
382
|
+
|
|
383
|
+
console.log(`\nManifest: ${manifestPath}`);
|
|
384
|
+
console.log(` Screens: ${manifest.screens.length}, components this run: ${components.length}`);
|
|
385
|
+
console.log('\nCapture complete.');
|
|
386
|
+
process.exit(0);
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* detect-stack.mjs — Stage 0: H5 stack detection + v1 scope gate
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* node detect-stack.mjs <h5-src> [--out <dir>]
|
|
7
|
+
*
|
|
8
|
+
* Outputs:
|
|
9
|
+
* <h5-src>/stack-report.json (or --out dir)
|
|
10
|
+
*
|
|
11
|
+
* Exit codes:
|
|
12
|
+
* 0 — report written (check in_v1_scope for gate result)
|
|
13
|
+
* 1 — fatal error (bad args, unreadable source)
|
|
14
|
+
*
|
|
15
|
+
* Examples:
|
|
16
|
+
* node detect-stack.mjs ./my-app
|
|
17
|
+
* node detect-stack.mjs ./my-app --out ./artifacts
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { readFileSync, writeFileSync, existsSync, readdirSync, statSync } from 'node:fs';
|
|
21
|
+
import { resolve, join } from 'node:path';
|
|
22
|
+
import { fileURLToPath } from 'node:url';
|
|
23
|
+
|
|
24
|
+
// ── CLI ──────────────────────────────────────────────────────────────────────
|
|
25
|
+
|
|
26
|
+
const args = process.argv.slice(2);
|
|
27
|
+
|
|
28
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
29
|
+
console.log(`detect-stack.mjs — H5 stack detection and v1 scope gate
|
|
30
|
+
|
|
31
|
+
Usage:
|
|
32
|
+
node detect-stack.mjs <h5-src> [--out <dir>]
|
|
33
|
+
|
|
34
|
+
Arguments:
|
|
35
|
+
<h5-src> Path to the H5 project root (required)
|
|
36
|
+
--out <dir> Directory to write stack-report.json (default: <h5-src>)
|
|
37
|
+
|
|
38
|
+
Exit codes:
|
|
39
|
+
0 Report written (check in_v1_scope field for gate result)
|
|
40
|
+
1 Fatal error
|
|
41
|
+
|
|
42
|
+
Output schema (stack-report.json):
|
|
43
|
+
{
|
|
44
|
+
"schema": "h5-to-swiftui/stack@1",
|
|
45
|
+
"framework": "vanilla" | "react" | "vue" | "angular" | "svelte" | "unknown",
|
|
46
|
+
"buildTool": "vite" | "webpack" | "parcel" | "rollup" | "none" | "unknown",
|
|
47
|
+
"styling": "tailwind" | "css-modules" | "styled-components" | "emotion" | "sass" | "plain-css" | "unknown",
|
|
48
|
+
"router": "react-router" | "vue-router" | "tanstack-router" | "history" | "none" | "unknown",
|
|
49
|
+
"confidence": 0.0–1.0,
|
|
50
|
+
"in_v1_scope": true | false
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
Examples:
|
|
54
|
+
node detect-stack.mjs ./my-vanilla-app
|
|
55
|
+
node detect-stack.mjs ./my-react-app --out ./artifacts
|
|
56
|
+
`);
|
|
57
|
+
process.exit(0);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (args.length === 0 || args[0].startsWith('--')) {
|
|
61
|
+
console.error('Error: <h5-src> is required.\nRun with --help for usage.');
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const h5Src = resolve(args[0]);
|
|
66
|
+
let outDir = h5Src;
|
|
67
|
+
|
|
68
|
+
const outIdx = args.indexOf('--out');
|
|
69
|
+
if (outIdx !== -1) {
|
|
70
|
+
if (!args[outIdx + 1]) {
|
|
71
|
+
console.error('Error: --out requires a directory argument.');
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
outDir = resolve(args[outIdx + 1]);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (!existsSync(h5Src)) {
|
|
78
|
+
console.error(`Error: h5-src path does not exist: ${h5Src}`);
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (!statSync(h5Src).isDirectory()) {
|
|
83
|
+
console.error(`Error: h5-src must be a directory, got: ${h5Src}`);
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// ── helpers ──────────────────────────────────────────────────────────────────
|
|
88
|
+
|
|
89
|
+
function readJson(p) {
|
|
90
|
+
try { return JSON.parse(readFileSync(p, 'utf8')); } catch { return null; }
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function readText(p) {
|
|
94
|
+
try { return readFileSync(p, 'utf8'); } catch { return null; }
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Recursively collect file paths up to maxDepth, skipping heavy dirs.
|
|
99
|
+
*/
|
|
100
|
+
function collectFiles(dir, maxDepth = 4, _depth = 0) {
|
|
101
|
+
const skip = new Set(['node_modules', '.git', 'dist', 'build', '.next', '.nuxt', 'out', 'coverage']);
|
|
102
|
+
if (_depth > maxDepth) return [];
|
|
103
|
+
const results = [];
|
|
104
|
+
let entries;
|
|
105
|
+
try { entries = readdirSync(dir, { withFileTypes: true }); } catch { return results; }
|
|
106
|
+
for (const e of entries) {
|
|
107
|
+
if (skip.has(e.name)) continue;
|
|
108
|
+
const full = join(dir, e.name);
|
|
109
|
+
if (e.isDirectory()) {
|
|
110
|
+
results.push(...collectFiles(full, maxDepth, _depth + 1));
|
|
111
|
+
} else {
|
|
112
|
+
results.push(full);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return results;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function fileContains(path, patterns) {
|
|
119
|
+
const text = readText(path);
|
|
120
|
+
if (!text) return false;
|
|
121
|
+
return patterns.some(p => (typeof p === 'string' ? text.includes(p) : p.test(text)));
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// ── detection ────────────────────────────────────────────────────────────────
|
|
125
|
+
|
|
126
|
+
const pkgPath = join(h5Src, 'package.json');
|
|
127
|
+
const pkg = readJson(pkgPath);
|
|
128
|
+
const allDeps = Object.assign({}, pkg?.dependencies, pkg?.devDependencies, pkg?.peerDependencies);
|
|
129
|
+
const depNames = new Set(Object.keys(allDeps));
|
|
130
|
+
|
|
131
|
+
const files = collectFiles(h5Src);
|
|
132
|
+
const srcFiles = files.filter(f => /\.(js|jsx|ts|tsx|mjs|cjs|html|css|scss|sass|vue|svelte)$/.test(f));
|
|
133
|
+
|
|
134
|
+
// Helper: match dep name prefix or contains
|
|
135
|
+
const hasDep = (...names) => names.some(n => depNames.has(n) || [...depNames].some(k => k.startsWith(n)));
|
|
136
|
+
|
|
137
|
+
// ── Framework ────────────────────────────────────────────────────────────────
|
|
138
|
+
|
|
139
|
+
let framework = 'unknown';
|
|
140
|
+
let frameworkConf = 0;
|
|
141
|
+
|
|
142
|
+
const signals = { react: 0, vue: 0, angular: 0, svelte: 0, vanilla: 0 };
|
|
143
|
+
|
|
144
|
+
// Dep-based signals
|
|
145
|
+
if (hasDep('react', 'react-dom', 'react-scripts', 'next')) { signals.react += 3; }
|
|
146
|
+
if (hasDep('vue', '@vue/core', 'nuxt')) { signals.vue += 3; }
|
|
147
|
+
if (hasDep('@angular/core', '@angular/common')) { signals.angular += 3; }
|
|
148
|
+
if (hasDep('svelte', '@sveltejs/kit')) { signals.svelte += 3; }
|
|
149
|
+
|
|
150
|
+
// Source-based signals — sample up to 60 files to keep it fast
|
|
151
|
+
const sample = srcFiles.slice(0, 60);
|
|
152
|
+
for (const f of sample) {
|
|
153
|
+
const t = readText(f) ?? '';
|
|
154
|
+
if (/from ['"]react['"]|require\(['"]react['"]\)|jsx|\.tsx?$/.test(t)) signals.react += 1;
|
|
155
|
+
if (/from ['"]vue['"]|<template>|\.vue$/.test(t) || f.endsWith('.vue')) signals.vue += 1;
|
|
156
|
+
if (/@Component\(|@NgModule\(|platformBrowserDynamic/.test(t)) signals.angular += 1;
|
|
157
|
+
if (/from ['"]svelte['"]|<script.*svelte|\.svelte$/.test(t) || f.endsWith('.svelte')) signals.svelte += 1;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// HTML-only / no framework
|
|
161
|
+
const hasHtmlEntry = files.some(f => f.endsWith('.html'));
|
|
162
|
+
const hasNoJsFrameworkDep = !hasDep('react', 'vue', '@angular', 'svelte');
|
|
163
|
+
if (hasHtmlEntry && hasNoJsFrameworkDep) signals.vanilla += 1;
|
|
164
|
+
// Extra: if package.json missing entirely, lean vanilla
|
|
165
|
+
if (!pkg) signals.vanilla += 2;
|
|
166
|
+
|
|
167
|
+
const topSignal = Object.entries(signals).sort((a, b) => b[1] - a[1])[0];
|
|
168
|
+
const totalSignals = Object.values(signals).reduce((s, v) => s + v, 0);
|
|
169
|
+
|
|
170
|
+
if (topSignal[1] === 0 && hasHtmlEntry) {
|
|
171
|
+
framework = 'vanilla';
|
|
172
|
+
frameworkConf = 0.5;
|
|
173
|
+
} else if (topSignal[1] > 0) {
|
|
174
|
+
framework = topSignal[0];
|
|
175
|
+
frameworkConf = Math.min(0.95, totalSignals > 0 ? topSignal[1] / Math.max(totalSignals, 1) * 1.5 : 0.3);
|
|
176
|
+
if (framework === 'vanilla') frameworkConf = Math.min(0.8, frameworkConf);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// ── Build tool ───────────────────────────────────────────────────────────────
|
|
180
|
+
|
|
181
|
+
let buildTool = 'unknown';
|
|
182
|
+
let buildConf = 0;
|
|
183
|
+
|
|
184
|
+
if (hasDep('vite') || files.some(f => /vite\.config\.(js|ts|mjs)$/.test(f))) {
|
|
185
|
+
buildTool = 'vite'; buildConf = 0.95;
|
|
186
|
+
} else if (hasDep('webpack') || files.some(f => /webpack\.config\.(js|ts)$/.test(f))) {
|
|
187
|
+
buildTool = 'webpack'; buildConf = 0.9;
|
|
188
|
+
} else if (hasDep('parcel')) {
|
|
189
|
+
buildTool = 'parcel'; buildConf = 0.9;
|
|
190
|
+
} else if (hasDep('rollup') || files.some(f => /rollup\.config\.(js|ts|mjs)$/.test(f))) {
|
|
191
|
+
buildTool = 'rollup'; buildConf = 0.85;
|
|
192
|
+
} else if (hasDep('react-scripts')) {
|
|
193
|
+
buildTool = 'webpack'; buildConf = 0.8; // CRA uses webpack
|
|
194
|
+
} else if (!pkg) {
|
|
195
|
+
buildTool = 'none'; buildConf = 0.7;
|
|
196
|
+
} else {
|
|
197
|
+
buildTool = 'none'; buildConf = 0.4;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// ── Styling ──────────────────────────────────────────────────────────────────
|
|
201
|
+
|
|
202
|
+
let styling = 'unknown';
|
|
203
|
+
let stylingConf = 0;
|
|
204
|
+
|
|
205
|
+
const stylingSignals = { tailwind: 0, 'css-modules': 0, 'styled-components': 0, emotion: 0, sass: 0, 'plain-css': 0 };
|
|
206
|
+
|
|
207
|
+
if (hasDep('tailwindcss') || files.some(f => /tailwind\.config\.(js|ts|cjs|mjs)$/.test(f))) {
|
|
208
|
+
stylingSignals.tailwind += 3;
|
|
209
|
+
}
|
|
210
|
+
if (hasDep('styled-components')) stylingSignals['styled-components'] += 3;
|
|
211
|
+
if (hasDep('@emotion/react', '@emotion/styled', 'emotion')) stylingSignals.emotion += 3;
|
|
212
|
+
if (hasDep('sass', 'node-sass', 'sass-loader') || srcFiles.some(f => /\.(scss|sass)$/.test(f))) {
|
|
213
|
+
stylingSignals.sass += 2;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// CSS modules check: look for *.module.css imports
|
|
217
|
+
const cssModuleHit = sample.some(f => fileContains(f, [/\.module\.css['"]/, /\.module\.scss['"]/]));
|
|
218
|
+
if (cssModuleHit) stylingSignals['css-modules'] += 3;
|
|
219
|
+
|
|
220
|
+
const hasCss = srcFiles.some(f => f.endsWith('.css'));
|
|
221
|
+
if (hasCss) stylingSignals['plain-css'] += 1;
|
|
222
|
+
|
|
223
|
+
const topStyle = Object.entries(stylingSignals).sort((a, b) => b[1] - a[1])[0];
|
|
224
|
+
if (topStyle[1] > 0) {
|
|
225
|
+
styling = topStyle[0];
|
|
226
|
+
stylingConf = Math.min(0.95, 0.5 + topStyle[1] * 0.1);
|
|
227
|
+
} else {
|
|
228
|
+
styling = 'plain-css';
|
|
229
|
+
stylingConf = 0.3;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// ── Router ───────────────────────────────────────────────────────────────────
|
|
233
|
+
|
|
234
|
+
let router = 'none';
|
|
235
|
+
let routerConf = 0.6;
|
|
236
|
+
|
|
237
|
+
if (hasDep('react-router', 'react-router-dom')) { router = 'react-router'; routerConf = 0.95; }
|
|
238
|
+
else if (hasDep('@tanstack/react-router', '@tanstack/router')) { router = 'tanstack-router'; routerConf = 0.95; }
|
|
239
|
+
else if (hasDep('vue-router')) { router = 'vue-router'; routerConf = 0.95; }
|
|
240
|
+
else if (hasDep('history')) { router = 'history'; routerConf = 0.85; }
|
|
241
|
+
else {
|
|
242
|
+
// Check source for router usage
|
|
243
|
+
const routerUsage = sample.some(f =>
|
|
244
|
+
fileContains(f, ['BrowserRouter', 'HashRouter', 'createBrowserRouter', 'useNavigate', 'useRouter'])
|
|
245
|
+
);
|
|
246
|
+
if (routerUsage) { router = 'react-router'; routerConf = 0.6; }
|
|
247
|
+
else { router = 'none'; routerConf = 0.7; }
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// ── Aggregate confidence ──────────────────────────────────────────────────────
|
|
251
|
+
|
|
252
|
+
const confidence = Math.round(
|
|
253
|
+
(frameworkConf * 0.5 + buildConf * 0.2 + stylingConf * 0.15 + routerConf * 0.15) * 100
|
|
254
|
+
) / 100;
|
|
255
|
+
|
|
256
|
+
// ── v1 scope gate ────────────────────────────────────────────────────────────
|
|
257
|
+
|
|
258
|
+
const V1_FRAMEWORKS = new Set(['vanilla', 'react']);
|
|
259
|
+
const inV1Scope = V1_FRAMEWORKS.has(framework);
|
|
260
|
+
|
|
261
|
+
// ── Write report ─────────────────────────────────────────────────────────────
|
|
262
|
+
|
|
263
|
+
const report = {
|
|
264
|
+
schema: 'h5-to-swiftui/stack@1',
|
|
265
|
+
framework,
|
|
266
|
+
buildTool,
|
|
267
|
+
styling,
|
|
268
|
+
router,
|
|
269
|
+
confidence,
|
|
270
|
+
in_v1_scope: inV1Scope,
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
// Ensure outDir exists
|
|
274
|
+
try {
|
|
275
|
+
const { mkdirSync } = await import('node:fs');
|
|
276
|
+
mkdirSync(outDir, { recursive: true });
|
|
277
|
+
} catch (e) {
|
|
278
|
+
console.error(`Error: cannot create output directory ${outDir}: ${e.message}`);
|
|
279
|
+
process.exit(1);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
const reportPath = join(outDir, 'stack-report.json');
|
|
283
|
+
try {
|
|
284
|
+
writeFileSync(reportPath, JSON.stringify(report, null, 2) + '\n', 'utf8');
|
|
285
|
+
} catch (e) {
|
|
286
|
+
console.error(`Error: cannot write ${reportPath}: ${e.message}`);
|
|
287
|
+
process.exit(1);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// ── Output ───────────────────────────────────────────────────────────────────
|
|
291
|
+
|
|
292
|
+
console.log(`Stack detection complete → ${reportPath}`);
|
|
293
|
+
console.log(JSON.stringify(report, null, 2));
|
|
294
|
+
|
|
295
|
+
if (!inV1Scope) {
|
|
296
|
+
console.log('');
|
|
297
|
+
console.log('╔══════════════════════════════════════════════════════════════╗');
|
|
298
|
+
console.log(`║ STOP — framework "${framework}" is outside v1 scope. `);
|
|
299
|
+
console.log('║ v1 supports: vanilla, react only. ');
|
|
300
|
+
console.log('║ Conversion pipeline will NOT proceed. ');
|
|
301
|
+
console.log('║ stack-report.json written with in_v1_scope: false. ');
|
|
302
|
+
console.log('╚══════════════════════════════════════════════════════════════╝');
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
process.exit(0);
|