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,625 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* calibrate-render.mjs — Stage 2.5: Render-equivalence calibration
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* node calibrate-render.mjs <calibration-dir> --device "iPhone 15 Pro"
|
|
7
|
+
* [--out calibration.json]
|
|
8
|
+
* [--ref <h5.png>] [--gen <swift.png>]
|
|
9
|
+
* [--sim-runtime <runtime>]
|
|
10
|
+
* [--browser <browser-id>]
|
|
11
|
+
* [--model-id <model>]
|
|
12
|
+
*
|
|
13
|
+
* Input resolution (in order of precedence):
|
|
14
|
+
* 1. Explicit --ref and --gen flags.
|
|
15
|
+
* 2. Auto-find in <calibration-dir>: first file matching *ref*.png as the H5
|
|
16
|
+
* reference, first file matching *gen*.png as the SwiftUI render.
|
|
17
|
+
* If neither path resolves, exits 1 with a clear error.
|
|
18
|
+
*
|
|
19
|
+
* Normalization pipeline (render-equivalence-calibration.md):
|
|
20
|
+
* 1. Crop simulator content rect: status-bar and home-indicator insets from
|
|
21
|
+
* the pinned device DEVICES table (below).
|
|
22
|
+
* 2. Resample BOTH sides to common logical raster (logical_pt × render_scale)
|
|
23
|
+
* using resampleLanczos3 — identical filter, both sides.
|
|
24
|
+
* 3. p3ToSrgb on the simulator (gen) side.
|
|
25
|
+
*
|
|
26
|
+
* Measurements:
|
|
27
|
+
* floor.ssim_global — whole-image SSIM after normalization
|
|
28
|
+
* floor.ssim_nontext — SSIM over non-text ROI (whole image if no bbox map)
|
|
29
|
+
* floor.deltaE_p95 — 95th-pct CIEDE2000 ΔE
|
|
30
|
+
* floor.text_iou — null (no bbox map provided at calibration time)
|
|
31
|
+
*
|
|
32
|
+
* Sanity bound (no-fake spine):
|
|
33
|
+
* If ssim_nontext < 0.95 (or text_iou < 0.9 when non-null), the toolchain
|
|
34
|
+
* is unmeasurable. Writes blocked.json next to --out and exits 1.
|
|
35
|
+
* Never emits calibration.json against an unproven metric.
|
|
36
|
+
*
|
|
37
|
+
* ADDITIONAL flat-image guard: SSIM is insensitive to a uniform mean shift
|
|
38
|
+
* on near-zero-variance (effectively flat) images — a clearly-divergent
|
|
39
|
+
* solid pair can still score ~0.95. If BOTH normalized images are
|
|
40
|
+
* effectively flat (luma variance below FLAT_VARIANCE_MAX on each side),
|
|
41
|
+
* the SSIM floor is unreliable ⇒ toolchain is treated as NOT MEASURABLE
|
|
42
|
+
* (blocked.json + exit 1), never a falsely-high floor. Bundled calibration
|
|
43
|
+
* content MUST be textured (text + multi-color region), see
|
|
44
|
+
* assets/calibration/README.md.
|
|
45
|
+
*
|
|
46
|
+
* Structured gate (consumed by evaluate-convergence.mjs WITHOUT a string
|
|
47
|
+
* parser): `gate.converged` / `gate.close` are numeric threshold objects
|
|
48
|
+
* computed from the measured floor (nontext floor-0.005, deltaE floor+0.4,
|
|
49
|
+
* text_iou floor-0.03; close = 2x band). A human-readable `gate_explain`
|
|
50
|
+
* string is kept for humans only — it is NEVER evaluated by code.
|
|
51
|
+
*
|
|
52
|
+
* Calibration honesty + provenance binding:
|
|
53
|
+
* calibration.twin_hashes = SHA-256 of the input ref + gen PNGs
|
|
54
|
+
* (non-security provenance metadata only — see twin_hashes note below).
|
|
55
|
+
* calibration.calibration_source = the bundled twin dirs this calibration
|
|
56
|
+
* was run against (relative to the skill root) + a deterministic
|
|
57
|
+
* SHA-256 source-tree hash of EACH bundled tree's SOURCE FILES
|
|
58
|
+
* (excluding build output/dotfiles). evaluate-convergence.mjs recomputes
|
|
59
|
+
* these source-tree hashes from the actual bundled assets and FAILS
|
|
60
|
+
* CLOSED on a mismatch — this binds the IDENTITY of the bundled twin
|
|
61
|
+
* source files. It does NOT bind the measured `floor` *value*: the
|
|
62
|
+
* grader separately asserts the `floor` satisfies this script's OWN
|
|
63
|
+
* sanity envelope (it writes blocked.json — not calibration.json — below
|
|
64
|
+
* ssim_nontext 0.95 / non-null text_iou 0.9), but a floor *within* that
|
|
65
|
+
* envelope yet looser than the true measured one is a disclosed
|
|
66
|
+
* irreducible residual (the grader cannot re-render to re-measure it).
|
|
67
|
+
*
|
|
68
|
+
* Outputs:
|
|
69
|
+
* calibration.json — schema h5-to-swiftui/calibration@1
|
|
70
|
+
* blocked.json — written instead when sanity bound fails (schema h5-to-swiftui/blocked@1)
|
|
71
|
+
*
|
|
72
|
+
* Exit codes:
|
|
73
|
+
* 0 — calibration.json written
|
|
74
|
+
* 1 — fatal error (bad args, file missing, sanity bound failed)
|
|
75
|
+
* 2 — pngjs not installed (actionable hint printed)
|
|
76
|
+
*
|
|
77
|
+
* Examples:
|
|
78
|
+
* node calibrate-render.mjs assets/calibration --device "iPhone 15 Pro"
|
|
79
|
+
* node calibrate-render.mjs assets/calibration --device "iPhone 15 Pro" --out dist/calibration.json
|
|
80
|
+
* node calibrate-render.mjs assets/calibration --device "iPhone 15 Pro" \
|
|
81
|
+
* --ref assets/calibration/h5-twin.png --gen assets/calibration/swiftui-twin.png
|
|
82
|
+
*/
|
|
83
|
+
|
|
84
|
+
import { existsSync, readdirSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
85
|
+
import { resolve, join, dirname } from 'node:path';
|
|
86
|
+
import { fileURLToPath } from 'node:url';
|
|
87
|
+
|
|
88
|
+
import { sourceTreeHash, sha256File } from './_provenance.mjs';
|
|
89
|
+
// Single source of truth for the sanity-envelope constants. The grader
|
|
90
|
+
// (evaluate-convergence.mjs) imports the SAME module, so the floor it
|
|
91
|
+
// asserts is identical to the floor this script refuses to emit below.
|
|
92
|
+
import { SSIM_NONTEXT_MIN, TEXT_IOU_MIN } from './_calib-consts.mjs';
|
|
93
|
+
|
|
94
|
+
import {
|
|
95
|
+
requirePng,
|
|
96
|
+
loadPng,
|
|
97
|
+
ssimWindow,
|
|
98
|
+
ciede2000Region,
|
|
99
|
+
resampleLanczos3,
|
|
100
|
+
p3ToSrgb,
|
|
101
|
+
cropRect,
|
|
102
|
+
quantile,
|
|
103
|
+
} from './_imglib.mjs';
|
|
104
|
+
|
|
105
|
+
// ── Device table (must match capture-reference.mjs DEVICES) ──────────────────
|
|
106
|
+
//
|
|
107
|
+
// Fields:
|
|
108
|
+
// logical_w, logical_h — logical point dimensions (pt)
|
|
109
|
+
// status_bar_pt — top inset (status bar + notch/island) in pt
|
|
110
|
+
// home_indicator_pt — bottom inset (home indicator) in pt
|
|
111
|
+
// render_scale — physical pixels per logical pt (@Nx)
|
|
112
|
+
//
|
|
113
|
+
// content_rect_pt = [0, status_bar_pt, logical_w, logical_h - status_bar_pt - home_indicator_pt]
|
|
114
|
+
// safe_area_offset_pt = [0, status_bar_pt]
|
|
115
|
+
|
|
116
|
+
const DEVICES = {
|
|
117
|
+
'iPhone 15 Pro': {
|
|
118
|
+
logical_w: 393, logical_h: 852,
|
|
119
|
+
status_bar_pt: 59, home_indicator_pt: 34,
|
|
120
|
+
render_scale: 3,
|
|
121
|
+
},
|
|
122
|
+
'iPhone 14 Pro': {
|
|
123
|
+
logical_w: 393, logical_h: 852,
|
|
124
|
+
status_bar_pt: 59, home_indicator_pt: 34,
|
|
125
|
+
render_scale: 3,
|
|
126
|
+
},
|
|
127
|
+
'iPhone 15': {
|
|
128
|
+
logical_w: 390, logical_h: 844,
|
|
129
|
+
status_bar_pt: 47, home_indicator_pt: 34,
|
|
130
|
+
render_scale: 3,
|
|
131
|
+
},
|
|
132
|
+
'iPhone SE': {
|
|
133
|
+
logical_w: 375, logical_h: 667,
|
|
134
|
+
status_bar_pt: 20, home_indicator_pt: 0,
|
|
135
|
+
render_scale: 2,
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
// ── CLI ───────────────────────────────────────────────────────────────────────
|
|
140
|
+
|
|
141
|
+
const args = process.argv.slice(2);
|
|
142
|
+
|
|
143
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
144
|
+
console.log(`calibrate-render.mjs — Stage 2.5 render-equivalence calibration
|
|
145
|
+
|
|
146
|
+
Usage:
|
|
147
|
+
node calibrate-render.mjs <calibration-dir> --device "iPhone 15 Pro"
|
|
148
|
+
[--out calibration.json]
|
|
149
|
+
[--ref <h5.png>] [--gen <swift.png>]
|
|
150
|
+
[--sim-runtime <runtime>]
|
|
151
|
+
[--browser <browser-id>]
|
|
152
|
+
[--model-id <model>]
|
|
153
|
+
|
|
154
|
+
Arguments:
|
|
155
|
+
<calibration-dir> Directory holding the known-correct H5/SwiftUI pair
|
|
156
|
+
--device <name> Target device (required); must match a known profile
|
|
157
|
+
--out <path> Output path for calibration.json (default: calibration.json
|
|
158
|
+
inside <calibration-dir>)
|
|
159
|
+
--ref <path> Explicit path to H5/Playwright reference PNG
|
|
160
|
+
--gen <path> Explicit path to SwiftUI simulator render PNG
|
|
161
|
+
--sim-runtime <runtime> Simulator runtime string to pin in output (e.g. "iOS 17.5")
|
|
162
|
+
--browser <id> Browser build string to pin (e.g. "chromium-1180")
|
|
163
|
+
--model-id <id> Model identifier to pin (e.g. "claude-sonnet-4-6")
|
|
164
|
+
|
|
165
|
+
Input resolution (precedence):
|
|
166
|
+
1. --ref / --gen flags if provided
|
|
167
|
+
2. Auto-find in <calibration-dir>: first *ref*.png = H5 side,
|
|
168
|
+
first *gen*.png = SwiftUI side (alphabetical within each glob)
|
|
169
|
+
|
|
170
|
+
Supported devices:
|
|
171
|
+
"iPhone 15 Pro" 393×852 pt status_bar=59pt home=34pt @3x
|
|
172
|
+
"iPhone 14 Pro" 393×852 pt status_bar=59pt home=34pt @3x
|
|
173
|
+
"iPhone 15" 390×844 pt status_bar=47pt home=34pt @3x
|
|
174
|
+
"iPhone SE" 375×667 pt status_bar=20pt home=0pt @2x
|
|
175
|
+
|
|
176
|
+
Normalization pipeline:
|
|
177
|
+
1. Crop simulator content rect via device safe-area insets
|
|
178
|
+
2. Resample BOTH sides to logical_pt × render_scale with Lanczos3
|
|
179
|
+
3. P3→sRGB (relative colorimetric) on the simulator side
|
|
180
|
+
|
|
181
|
+
Sanity bound:
|
|
182
|
+
If ssim_nontext < 0.95 (or text_iou < 0.9 when non-null), the toolchain is
|
|
183
|
+
unmeasurable. Writes blocked.json and exits 1. Never grades against an
|
|
184
|
+
unproven metric.
|
|
185
|
+
Flat-image guard: if BOTH normalized images are effectively flat (near-zero
|
|
186
|
+
luma variance), SSIM is unreliable for a mean shift ⇒ also blocked.json.
|
|
187
|
+
|
|
188
|
+
Structured gate (no string DSL):
|
|
189
|
+
gate.converged / gate.close are numeric threshold objects, evaluated by
|
|
190
|
+
evaluate-convergence.mjs WITHOUT a parser:
|
|
191
|
+
converged: { ssim_nontext_min, deltaE_p95_max, text_iou_min,
|
|
192
|
+
require_judge_yes: true }
|
|
193
|
+
close: { ...2x band... , require_judge_equiv: true }
|
|
194
|
+
gate_explain is a human-only string; code never evaluates it.
|
|
195
|
+
|
|
196
|
+
Calibration honesty + provenance binding:
|
|
197
|
+
twin_hashes = SHA-256 of the input ref + gen PNGs (non-security
|
|
198
|
+
provenance metadata; the security binding is
|
|
199
|
+
calibration_source).
|
|
200
|
+
calibration_source = bundled twin dirs (relative to skill root) +
|
|
201
|
+
deterministic SHA-256 source-tree hash of each tree's
|
|
202
|
+
SOURCE FILES (excluding build output/dotfiles).
|
|
203
|
+
evaluate-convergence.mjs recomputes these from the
|
|
204
|
+
shipped assets and FAILS CLOSED on a mismatch — this
|
|
205
|
+
binds the twin source IDENTITY, NOT the measured floor
|
|
206
|
+
value. The grader additionally asserts the floor is
|
|
207
|
+
within this script's own sanity envelope; a floor
|
|
208
|
+
within that envelope but looser than the true measured
|
|
209
|
+
one is a disclosed irreducible residual (grader cannot
|
|
210
|
+
re-render to re-measure it).
|
|
211
|
+
|
|
212
|
+
Outputs:
|
|
213
|
+
calibration.json schema: h5-to-swiftui/calibration@1
|
|
214
|
+
blocked.json written instead when sanity bound fails
|
|
215
|
+
|
|
216
|
+
Exit codes:
|
|
217
|
+
0 calibration.json written
|
|
218
|
+
1 fatal error / sanity bound failed
|
|
219
|
+
2 pngjs not installed
|
|
220
|
+
|
|
221
|
+
Examples:
|
|
222
|
+
node calibrate-render.mjs assets/calibration --device "iPhone 15 Pro"
|
|
223
|
+
node calibrate-render.mjs assets/calibration --device "iPhone 15 Pro" \\
|
|
224
|
+
--out dist/calibration.json --sim-runtime "iOS 17.5 (21F79)"
|
|
225
|
+
`);
|
|
226
|
+
process.exit(0);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Positional: first non-flag arg
|
|
230
|
+
let calibDir = null;
|
|
231
|
+
for (const a of args) {
|
|
232
|
+
if (!a.startsWith('--')) { calibDir = a; break; }
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if (!calibDir) {
|
|
236
|
+
console.error('Error: <calibration-dir> is required.\nRun with --help for usage.');
|
|
237
|
+
process.exit(1);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
calibDir = resolve(calibDir);
|
|
241
|
+
|
|
242
|
+
if (!existsSync(calibDir)) {
|
|
243
|
+
console.error(`Error: calibration-dir not found: ${calibDir}`);
|
|
244
|
+
process.exit(1);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function getFlag(flag, fallback = null) {
|
|
248
|
+
const idx = args.indexOf(flag);
|
|
249
|
+
if (idx === -1) return fallback;
|
|
250
|
+
const val = args[idx + 1];
|
|
251
|
+
if (val === undefined || val.startsWith('--')) {
|
|
252
|
+
console.error(`Error: ${flag} requires an argument.`);
|
|
253
|
+
process.exit(1);
|
|
254
|
+
}
|
|
255
|
+
return val;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
const deviceName = getFlag('--device');
|
|
259
|
+
const outFlagRaw = getFlag('--out');
|
|
260
|
+
const refFlagRaw = getFlag('--ref');
|
|
261
|
+
const genFlagRaw = getFlag('--gen');
|
|
262
|
+
const simRuntime = getFlag('--sim-runtime', 'unknown');
|
|
263
|
+
const browserStr = getFlag('--browser', 'unknown');
|
|
264
|
+
const modelId = getFlag('--model-id', 'unknown');
|
|
265
|
+
|
|
266
|
+
if (!deviceName) {
|
|
267
|
+
console.error('Error: --device is required.\nRun with --help for usage.');
|
|
268
|
+
process.exit(1);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const device = DEVICES[deviceName];
|
|
272
|
+
if (!device) {
|
|
273
|
+
const known = Object.keys(DEVICES).map(d => `"${d}"`).join(', ');
|
|
274
|
+
console.error(`Error: unknown device "${deviceName}".\nSupported: ${known}`);
|
|
275
|
+
process.exit(1);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Resolve output path
|
|
279
|
+
const defaultOut = join(calibDir, 'calibration.json');
|
|
280
|
+
const outPath = outFlagRaw ? resolve(outFlagRaw) : defaultOut;
|
|
281
|
+
const blockedPath = join(dirname(outPath), 'blocked.json');
|
|
282
|
+
|
|
283
|
+
// ── Resolve input PNGs ────────────────────────────────────────────────────────
|
|
284
|
+
|
|
285
|
+
function findPngGlob(dir, pattern) {
|
|
286
|
+
// pattern is a substring to match (e.g. 'ref', 'gen')
|
|
287
|
+
try {
|
|
288
|
+
const files = readdirSync(dir)
|
|
289
|
+
.filter(f => f.endsWith('.png') && f.toLowerCase().includes(pattern))
|
|
290
|
+
.sort();
|
|
291
|
+
return files.length > 0 ? join(dir, files[0]) : null;
|
|
292
|
+
} catch {
|
|
293
|
+
return null;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
let refPath = refFlagRaw ? resolve(refFlagRaw) : findPngGlob(calibDir, 'ref');
|
|
298
|
+
let genPath = genFlagRaw ? resolve(genFlagRaw) : findPngGlob(calibDir, 'gen');
|
|
299
|
+
|
|
300
|
+
if (!refPath) {
|
|
301
|
+
console.error(
|
|
302
|
+
'Error: could not find H5 reference PNG.\n' +
|
|
303
|
+
'Either pass --ref <path> or place a file matching *ref*.png in <calibration-dir>.'
|
|
304
|
+
);
|
|
305
|
+
process.exit(1);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
if (!genPath) {
|
|
309
|
+
console.error(
|
|
310
|
+
'Error: could not find SwiftUI render PNG.\n' +
|
|
311
|
+
'Either pass --gen <path> or place a file matching *gen*.png in <calibration-dir>.'
|
|
312
|
+
);
|
|
313
|
+
process.exit(1);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
if (!existsSync(refPath)) {
|
|
317
|
+
console.error(`Error: --ref file not found: ${refPath}`);
|
|
318
|
+
process.exit(1);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
if (!existsSync(genPath)) {
|
|
322
|
+
console.error(`Error: --gen file not found: ${genPath}`);
|
|
323
|
+
process.exit(1);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
console.error(`Device: ${deviceName}`);
|
|
327
|
+
console.error(`H5 ref: ${refPath}`);
|
|
328
|
+
console.error(`SwiftUI gen:${genPath}`);
|
|
329
|
+
console.error(`Output: ${outPath}`);
|
|
330
|
+
|
|
331
|
+
// ── Load PNG dependency early for clear error ────────────────────────────────
|
|
332
|
+
|
|
333
|
+
await requirePng();
|
|
334
|
+
|
|
335
|
+
// ── Load images ───────────────────────────────────────────────────────────────
|
|
336
|
+
|
|
337
|
+
let imgRef, imgGen;
|
|
338
|
+
try {
|
|
339
|
+
[imgRef, imgGen] = await Promise.all([loadPng(refPath), loadPng(genPath)]);
|
|
340
|
+
} catch (e) {
|
|
341
|
+
console.error(`Error: failed to load image: ${e.message}`);
|
|
342
|
+
process.exit(1);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
console.error(`H5 ref size: ${imgRef.width}×${imgRef.height}`);
|
|
346
|
+
console.error(`SwiftUI size: ${imgGen.width}×${imgGen.height}`);
|
|
347
|
+
|
|
348
|
+
// ── Normalization pipeline ────────────────────────────────────────────────────
|
|
349
|
+
|
|
350
|
+
// Derive content rect from device safe-area insets
|
|
351
|
+
const contentX = 0;
|
|
352
|
+
const contentY = device.status_bar_pt; // pt
|
|
353
|
+
const contentW = device.logical_w; // pt
|
|
354
|
+
const contentH = device.logical_h - device.status_bar_pt - device.home_indicator_pt; // pt
|
|
355
|
+
|
|
356
|
+
// Physical pixel dimensions for the crop on the simulator side
|
|
357
|
+
const cropX_px = Math.round(contentX * device.render_scale);
|
|
358
|
+
const cropY_px = Math.round(contentY * device.render_scale);
|
|
359
|
+
const cropW_px = Math.round(contentW * device.render_scale);
|
|
360
|
+
const cropH_px = Math.round(contentH * device.render_scale);
|
|
361
|
+
|
|
362
|
+
// Common logical raster target (logical pt × render_scale = physical px of content)
|
|
363
|
+
const targetW = cropW_px;
|
|
364
|
+
const targetH = cropH_px;
|
|
365
|
+
|
|
366
|
+
console.error(`Content rect (pt): [${contentX}, ${contentY}, ${contentW}, ${contentH}]`);
|
|
367
|
+
console.error(`Crop (px): [${cropX_px}, ${cropY_px}, ${cropW_px}, ${cropH_px}]`);
|
|
368
|
+
console.error(`Resample target: ${targetW}×${targetH}`);
|
|
369
|
+
|
|
370
|
+
// Step 1: Crop simulator side to content rect
|
|
371
|
+
// Only crop if the simulator image is taller than the content crop (has chrome)
|
|
372
|
+
let imgGenNorm = imgGen;
|
|
373
|
+
if (imgGen.height >= cropY_px + cropH_px && imgGen.width >= cropX_px + cropW_px) {
|
|
374
|
+
imgGenNorm = cropRect(imgGen, cropX_px, cropY_px, cropW_px, cropH_px);
|
|
375
|
+
console.error(`Cropped simulator side: ${imgGenNorm.width}×${imgGenNorm.height}`);
|
|
376
|
+
} else {
|
|
377
|
+
console.error(
|
|
378
|
+
`Warning: simulator image (${imgGen.width}×${imgGen.height}) is smaller than the ` +
|
|
379
|
+
`expected crop [${cropX_px},${cropY_px},${cropW_px},${cropH_px}] — skipping crop.`
|
|
380
|
+
);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// Step 2: Resample both sides to common logical raster (Lanczos3, identical filter)
|
|
384
|
+
const imgRefNorm = resampleLanczos3(imgRef, targetW, targetH);
|
|
385
|
+
imgGenNorm = resampleLanczos3(imgGenNorm, targetW, targetH);
|
|
386
|
+
console.error(`After resample — ref: ${imgRefNorm.width}×${imgRefNorm.height}, gen: ${imgGenNorm.width}×${imgGenNorm.height}`);
|
|
387
|
+
|
|
388
|
+
// Step 3: P3→sRGB on simulator (gen) side
|
|
389
|
+
p3ToSrgb(imgGenNorm);
|
|
390
|
+
console.error('P3→sRGB conversion applied to simulator side.');
|
|
391
|
+
|
|
392
|
+
// ── Measurements ─────────────────────────────────────────────────────────────
|
|
393
|
+
|
|
394
|
+
// ssim_global: whole-image SSIM
|
|
395
|
+
const ssim_global = ssimWindow(imgRefNorm, imgGenNorm, undefined, 8);
|
|
396
|
+
|
|
397
|
+
// ssim_nontext: without a bbox map we treat the whole image as non-text.
|
|
398
|
+
// The text_iou is null; we document this in the output.
|
|
399
|
+
const ssim_nontext = ssimWindow(imgRefNorm, imgGenNorm, undefined, 8);
|
|
400
|
+
|
|
401
|
+
// deltaE_p95: 95th-percentile CIEDE2000 ΔE over the whole image
|
|
402
|
+
const { p95: deltaE_p95 } = ciede2000Region(imgRefNorm, imgGenNorm);
|
|
403
|
+
|
|
404
|
+
// text_iou: null — no bbox map at calibration time
|
|
405
|
+
const text_iou = null;
|
|
406
|
+
|
|
407
|
+
// Luma variance per side (BT.601). A near-zero variance means the image is
|
|
408
|
+
// effectively flat — SSIM cannot distinguish a uniform mean shift there, so
|
|
409
|
+
// the floor it yields would be unreliable.
|
|
410
|
+
function lumaVariance(img) {
|
|
411
|
+
const d = img.data;
|
|
412
|
+
const n = img.width * img.height;
|
|
413
|
+
if (n === 0) return 0;
|
|
414
|
+
let sum = 0;
|
|
415
|
+
for (let i = 0; i < d.length; i += 4) {
|
|
416
|
+
sum += 0.299 * d[i] + 0.587 * d[i + 1] + 0.114 * d[i + 2];
|
|
417
|
+
}
|
|
418
|
+
const mean = sum / n;
|
|
419
|
+
let varSum = 0;
|
|
420
|
+
for (let i = 0; i < d.length; i += 4) {
|
|
421
|
+
const l = 0.299 * d[i] + 0.587 * d[i + 1] + 0.114 * d[i + 2];
|
|
422
|
+
varSum += (l - mean) * (l - mean);
|
|
423
|
+
}
|
|
424
|
+
return varSum / n;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
// Variance threshold below which a side is "effectively flat" (luma units²).
|
|
428
|
+
// ~9 ≈ a 3-luma-level stddev: anything below this has essentially no structure.
|
|
429
|
+
const FLAT_VARIANCE_MAX = 9;
|
|
430
|
+
const varRef = lumaVariance(imgRefNorm);
|
|
431
|
+
const varGen = lumaVariance(imgGenNorm);
|
|
432
|
+
const bothFlat = varRef < FLAT_VARIANCE_MAX && varGen < FLAT_VARIANCE_MAX;
|
|
433
|
+
|
|
434
|
+
console.error(`\nMeasured floor:`);
|
|
435
|
+
console.error(` ssim_global = ${ssim_global.toFixed(4)}`);
|
|
436
|
+
console.error(` ssim_nontext = ${ssim_nontext.toFixed(4)} (whole image, no bbox map)`);
|
|
437
|
+
console.error(` deltaE_p95 = ${deltaE_p95.toFixed(4)}`);
|
|
438
|
+
console.error(` text_iou = null (no bbox map provided)`);
|
|
439
|
+
console.error(` luma_variance = ref ${varRef.toFixed(2)}, gen ${varGen.toFixed(2)} ` +
|
|
440
|
+
`(flat threshold ${FLAT_VARIANCE_MAX})`);
|
|
441
|
+
|
|
442
|
+
// ── Sanity bound ──────────────────────────────────────────────────────────────
|
|
443
|
+
//
|
|
444
|
+
// If the known-correct pair cannot beat conservative bounds, the toolchain is
|
|
445
|
+
// not measurable. Write blocked.json and exit 1. Never fake convergence.
|
|
446
|
+
|
|
447
|
+
// SSIM_NONTEXT_MIN (0.95) and TEXT_IOU_MIN (0.9) are imported from
|
|
448
|
+
// ./_calib-consts.mjs — the SINGLE source of truth shared with
|
|
449
|
+
// evaluate-convergence.mjs. The numeric values are unchanged (byte-identical
|
|
450
|
+
// behavior): this script still writes blocked.json below these bounds.
|
|
451
|
+
const ssimFails = ssim_nontext < SSIM_NONTEXT_MIN;
|
|
452
|
+
// text_iou check is skipped when null (no bbox map)
|
|
453
|
+
const textIouFails = text_iou !== null && text_iou < TEXT_IOU_MIN;
|
|
454
|
+
// Flat-image guard: SSIM is insensitive to a uniform mean shift on
|
|
455
|
+
// near-zero-variance images, so a falsely-high floor is possible. If BOTH
|
|
456
|
+
// sides are flat, the floor is unreliable ⇒ not measurable.
|
|
457
|
+
const flatFails = bothFlat;
|
|
458
|
+
|
|
459
|
+
if (ssimFails || textIouFails || flatFails) {
|
|
460
|
+
const reasons = [];
|
|
461
|
+
if (ssimFails) reasons.push(`ssim_nontext=${ssim_nontext.toFixed(4)} < ${SSIM_NONTEXT_MIN}`);
|
|
462
|
+
if (textIouFails) reasons.push(`text_iou=${text_iou.toFixed(4)} < ${TEXT_IOU_MIN}`);
|
|
463
|
+
if (flatFails) reasons.push(
|
|
464
|
+
`both images effectively flat (luma variance ref=${varRef.toFixed(2)}, ` +
|
|
465
|
+
`gen=${varGen.toFixed(2)} < ${FLAT_VARIANCE_MAX}) — SSIM floor unreliable; ` +
|
|
466
|
+
`calibration content must be textured`);
|
|
467
|
+
|
|
468
|
+
const blocked = {
|
|
469
|
+
schema: 'h5-to-swiftui/blocked@1',
|
|
470
|
+
stage: '2.5',
|
|
471
|
+
reason: flatFails && !ssimFails && !textIouFails
|
|
472
|
+
? 'toolchain not measurable (flat calibration content)'
|
|
473
|
+
: 'toolchain not measurable',
|
|
474
|
+
detail: reasons.join('; '),
|
|
475
|
+
measured: {
|
|
476
|
+
ssim_global: Math.round(ssim_global * 10000) / 10000,
|
|
477
|
+
ssim_nontext: Math.round(ssim_nontext * 10000) / 10000,
|
|
478
|
+
deltaE_p95: Math.round(deltaE_p95 * 10000) / 10000,
|
|
479
|
+
text_iou,
|
|
480
|
+
luma_variance: {
|
|
481
|
+
ref: Math.round(varRef * 100) / 100,
|
|
482
|
+
gen: Math.round(varGen * 100) / 100,
|
|
483
|
+
flat_threshold: FLAT_VARIANCE_MAX,
|
|
484
|
+
},
|
|
485
|
+
},
|
|
486
|
+
device: deviceName,
|
|
487
|
+
measured_at: new Date().toISOString(),
|
|
488
|
+
};
|
|
489
|
+
|
|
490
|
+
mkdirSync(dirname(blockedPath), { recursive: true });
|
|
491
|
+
writeFileSync(blockedPath, JSON.stringify(blocked, null, 2) + '\n', 'utf8');
|
|
492
|
+
|
|
493
|
+
console.error(`\nSANITY BOUND FAILED: ${reasons.join('; ')}`);
|
|
494
|
+
console.error(`Toolchain is not measurable. Wrote: ${blockedPath}`);
|
|
495
|
+
console.error('calibration.json was NOT written. Fix the toolchain and re-run.');
|
|
496
|
+
process.exit(1);
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
// ── Twin hashes (calibration honesty) ─────────────────────────────────────────
|
|
500
|
+
// SHA-256 of the raw input PNGs so a downstream reader can detect a
|
|
501
|
+
// degraded/swapped twin before trusting the floor.
|
|
502
|
+
const twinHashes = {
|
|
503
|
+
ref_png: refPath,
|
|
504
|
+
ref_sha256: sha256File(refPath),
|
|
505
|
+
gen_png: genPath,
|
|
506
|
+
gen_sha256: sha256File(genPath),
|
|
507
|
+
};
|
|
508
|
+
|
|
509
|
+
// ── Calibration source provenance (binds the bundled twin SOURCE IDENTITY) ────
|
|
510
|
+
// Skill root = parent of this script's directory (scripts/ -> skill root).
|
|
511
|
+
// Resolved from the script's own location so it is correct from ANY cwd.
|
|
512
|
+
const SKILL_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
513
|
+
const REL_H5_TWIN = 'assets/calibration/h5-twin';
|
|
514
|
+
const REL_SWIFTUI_TWIN = 'assets/calibration/swiftui-twin';
|
|
515
|
+
const calibrationSource = {
|
|
516
|
+
// POSIX-relative bundled twin dirs this calibration must derive from.
|
|
517
|
+
h5_twin_dir: REL_H5_TWIN,
|
|
518
|
+
swiftui_twin_dir: REL_SWIFTUI_TWIN,
|
|
519
|
+
// Deterministic SHA-256 content hash of each shipped source tree's SOURCE
|
|
520
|
+
// FILES (excluding build output/dotfiles). The consumer recomputes these
|
|
521
|
+
// from the actual bundled assets and fails closed on a mismatch — this
|
|
522
|
+
// binds the IDENTITY of the bundled twin source files. It does NOT bind
|
|
523
|
+
// the measured `floor` *value*: keeping these (public, unmodified) hashes
|
|
524
|
+
// while writing a loose floor is caught only down to this script's own
|
|
525
|
+
// sanity envelope (the grader's FIX A check); a floor within that envelope
|
|
526
|
+
// yet looser than the true measured one is a disclosed irreducible
|
|
527
|
+
// residual (the grader cannot re-render to re-measure it).
|
|
528
|
+
h5_twin_source_sha256: sourceTreeHash(join(SKILL_ROOT, REL_H5_TWIN)),
|
|
529
|
+
swiftui_twin_source_sha256: sourceTreeHash(join(SKILL_ROOT, REL_SWIFTUI_TWIN)),
|
|
530
|
+
source_tree_hash_algo: 'sha256/sorted-relpath+filebytes/v1',
|
|
531
|
+
};
|
|
532
|
+
|
|
533
|
+
// ── Emit calibration.json ─────────────────────────────────────────────────────
|
|
534
|
+
|
|
535
|
+
// Structured numeric gate — evaluate-convergence.mjs reads these WITHOUT a
|
|
536
|
+
// string parser. Tolerances applied to the measured floor:
|
|
537
|
+
// ssim_nontext_min = floor - 0.005 (looser by 0.005)
|
|
538
|
+
// deltaE_p95_max = floor + 0.4 (looser by 0.4)
|
|
539
|
+
// text_iou_min = floor - 0.03 (looser by 0.03; null ⇒ skipped)
|
|
540
|
+
// `close` is a 2× band of each delta from the floor.
|
|
541
|
+
const round4 = (v) => Math.round(v * 10000) / 10000;
|
|
542
|
+
|
|
543
|
+
const floorSsimNontext = round4(ssim_nontext);
|
|
544
|
+
const floorDeltaE = round4(deltaE_p95);
|
|
545
|
+
const floorTextIou = text_iou; // null when no bbox map
|
|
546
|
+
|
|
547
|
+
const D_SSIM = 0.005;
|
|
548
|
+
const D_DELTAE = 0.4;
|
|
549
|
+
const D_IOU = 0.03;
|
|
550
|
+
|
|
551
|
+
const gateConverged = {
|
|
552
|
+
ssim_nontext_min: round4(floorSsimNontext - D_SSIM),
|
|
553
|
+
deltaE_p95_max: round4(floorDeltaE + D_DELTAE),
|
|
554
|
+
text_iou_min: floorTextIou === null ? null : round4(floorTextIou - D_IOU),
|
|
555
|
+
require_judge_yes: true,
|
|
556
|
+
};
|
|
557
|
+
const gateClose = {
|
|
558
|
+
ssim_nontext_min: round4(floorSsimNontext - 2 * D_SSIM),
|
|
559
|
+
deltaE_p95_max: round4(floorDeltaE + 2 * D_DELTAE),
|
|
560
|
+
text_iou_min: floorTextIou === null ? null : round4(floorTextIou - 2 * D_IOU),
|
|
561
|
+
require_judge_equiv: true,
|
|
562
|
+
};
|
|
563
|
+
const gateExplain =
|
|
564
|
+
`converged := ssim_nontext >= ${gateConverged.ssim_nontext_min} ` +
|
|
565
|
+
`AND deltaE_p95 <= ${gateConverged.deltaE_p95_max} ` +
|
|
566
|
+
(gateConverged.text_iou_min === null
|
|
567
|
+
? 'AND (text_iou gate skipped: no bbox map at calibration) '
|
|
568
|
+
: `AND text_iou >= ${gateConverged.text_iou_min} `) +
|
|
569
|
+
`AND judge=YES. close := same metrics at the 2x band ` +
|
|
570
|
+
`(ssim>=${gateClose.ssim_nontext_min}, deltaE<=${gateClose.deltaE_p95_max}` +
|
|
571
|
+
(gateClose.text_iou_min === null ? '' : `, text_iou>=${gateClose.text_iou_min}`) +
|
|
572
|
+
`) AND judge=visually-equivalent-residual-subperceptual. ` +
|
|
573
|
+
`Human-readable only — code reads gate.converged / gate.close numerically.`;
|
|
574
|
+
|
|
575
|
+
const calibration = {
|
|
576
|
+
schema: 'h5-to-swiftui/calibration@1',
|
|
577
|
+
pinned: {
|
|
578
|
+
sim_runtime: simRuntime,
|
|
579
|
+
device: deviceName,
|
|
580
|
+
logical_size: [device.logical_w, device.logical_h],
|
|
581
|
+
render_scale: device.render_scale,
|
|
582
|
+
browser: browserStr,
|
|
583
|
+
model_id: modelId,
|
|
584
|
+
temperature: 0,
|
|
585
|
+
},
|
|
586
|
+
transform: {
|
|
587
|
+
dom_to_screen_scale: 1.0,
|
|
588
|
+
safe_area_offset_pt: [0, device.status_bar_pt],
|
|
589
|
+
content_rect_pt: [contentX, contentY, contentW, contentH],
|
|
590
|
+
resample_filter: 'lanczos3',
|
|
591
|
+
color: 'p3->srgb-relative',
|
|
592
|
+
},
|
|
593
|
+
twin_hashes: twinHashes,
|
|
594
|
+
calibration_source: calibrationSource,
|
|
595
|
+
floor: {
|
|
596
|
+
ssim_global: round4(ssim_global),
|
|
597
|
+
ssim_nontext: floorSsimNontext,
|
|
598
|
+
deltaE_p95: floorDeltaE,
|
|
599
|
+
text_iou: floorTextIou,
|
|
600
|
+
luma_variance: {
|
|
601
|
+
ref: Math.round(varRef * 100) / 100,
|
|
602
|
+
gen: Math.round(varGen * 100) / 100,
|
|
603
|
+
flat_threshold: FLAT_VARIANCE_MAX,
|
|
604
|
+
},
|
|
605
|
+
_text_iou_note: text_iou === null
|
|
606
|
+
? 'No bbox map provided at calibration time; text_iou is null. ' +
|
|
607
|
+
'Stage 5 will skip the text_iou gate for this calibration.'
|
|
608
|
+
: undefined,
|
|
609
|
+
},
|
|
610
|
+
gate: {
|
|
611
|
+
converged: gateConverged,
|
|
612
|
+
close: gateClose,
|
|
613
|
+
gate_explain: gateExplain,
|
|
614
|
+
},
|
|
615
|
+
measured_at: new Date().toISOString(),
|
|
616
|
+
};
|
|
617
|
+
|
|
618
|
+
// Remove undefined keys (e.g. _text_iou_note when text_iou is not null)
|
|
619
|
+
const cleanCalib = JSON.parse(JSON.stringify(calibration));
|
|
620
|
+
|
|
621
|
+
mkdirSync(dirname(outPath), { recursive: true });
|
|
622
|
+
writeFileSync(outPath, JSON.stringify(cleanCalib, null, 2) + '\n', 'utf8');
|
|
623
|
+
|
|
624
|
+
console.error(`\nCalibration complete. Wrote: ${outPath}`);
|
|
625
|
+
process.exit(0);
|