@hybridlabor-api/aos 4.6.5 → 4.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/agents.md +1 -0
- package/.agents/nodes.json +5 -1
- package/.agents/state.schema.json +2 -1
- package/.agents/vendor-manifest.json +50 -0
- package/.claude/agents/architect.md +4 -0
- package/.claude/agents/security-reviewer.md +1 -1
- package/.claude/hooks/memb-inject.mjs +257 -135
- package/.claude/hooks/trail-relay.mjs +18 -0
- package/.claude/settings.json +70 -0
- package/.claude/workflows/startcycle-dispatch.mjs +29 -1
- package/.opencode/agents/architect.md +4 -0
- package/.opencode/plugins/bdb-aos.js +75 -0
- package/THIRD_PARTY_NOTICES.md +48 -0
- package/bin/aos-config.mjs +3 -1
- package/bin/aos-uninstall.mjs +55 -1
- package/docs/handover/agenttrail-for-ao.md +58 -0
- package/docs/handover/deja-for-ao.md +51 -0
- package/installer.js +257 -56
- package/mcp_config.json +4 -0
- package/mcps/mcsc/README.md +24 -0
- package/mcps/mcsc/package-lock.json +1234 -0
- package/mcps/mcsc/package.json +14 -0
- package/mcps/mcsc/packages/core/bin/mcsc.js +162 -0
- package/mcps/mcsc/packages/core/rulebook.default.yaml +49 -0
- package/mcps/mcsc/packages/core/schema/rulebook.schema.json +56 -0
- package/mcps/mcsc/packages/core/src/adapters/agy.js +107 -0
- package/mcps/mcsc/packages/core/src/adapters/codex.js +56 -0
- package/mcps/mcsc/packages/core/src/adapters/native.js +14 -0
- package/mcps/mcsc/packages/core/src/adapters/opencode.js +183 -0
- package/mcps/mcsc/packages/core/src/adapters/types.js +21 -0
- package/mcps/mcsc/packages/core/src/capabilities/buildOfferTable.js +34 -0
- package/mcps/mcsc/packages/core/src/capabilities/registry.js +99 -0
- package/mcps/mcsc/packages/core/src/capabilities/types.js +24 -0
- package/mcps/mcsc/packages/core/src/detect/cache.js +47 -0
- package/mcps/mcsc/packages/core/src/detect/inventory.js +73 -0
- package/mcps/mcsc/packages/core/src/detect/probes.js +158 -0
- package/mcps/mcsc/packages/core/src/detect/types.js +26 -0
- package/mcps/mcsc/packages/core/src/rulebook/load.js +53 -0
- package/mcps/mcsc/packages/core/src/rulebook/resolve.js +227 -0
- package/mcps/mcsc/packages/core/src/rulebook/rulebook.types.js +89 -0
- package/mcps/mcsc/packages/core/src/trail.js +17 -0
- package/mcps/mcsc/packages/mcp/server.js +302 -0
- package/mcps/mcsc/server.js +2 -0
- package/package.json +3 -1
- package/skills/basic/bdbmediastorm/SKILL.md +1 -1
- package/skills/basic/godmode-ui-ux/SKILL.md +2 -2
- package/skills/basic/godmode-ui-ux/references/anti-slop-rules.md +44 -40
- package/skills/basic/godmode-ui-ux/references/taste-archetypes.md +49 -0
- package/skills/basic/startcycle/SKILL.md +7 -0
- package/skills/basic/startcycle-graph/SKILL.md +12 -0
- package/skills/basic/startcycle-graph-user/SKILL.md +3 -0
- package/skills/basic/teamwork-preview/SKILL.md +2 -0
- package/skills/bdbrainstorm/SKILL.md +1 -0
- package/skills/global_config/agenttrail/LICENSE +21 -0
- package/skills/global_config/agenttrail/SKILL.md +48 -0
- package/skills/global_config/agenttrail/bin/agenttrail.mjs +1002 -0
- package/skills/global_config/agenttrail/public/index.html +661 -0
- package/skills/global_config/aos-project-init/SKILL.md +25 -5
- package/skills/global_config/aos-project-init/scripts/aos-project-doctor.mjs +11 -0
- package/skills/global_config/aos-setup/SKILL.md +34 -1
- package/skills/global_config/aos-setup/scripts/aos-doctor.mjs +115 -1
- package/skills/global_config/archify/LICENSE +22 -0
- package/skills/global_config/archify/SKILL.md +140 -0
- package/skills/global_config/archify/THIRD_PARTY_NOTICES.md +69 -0
- package/skills/global_config/archify/assets/JetBrainsMono-OFL.txt +93 -0
- package/skills/global_config/archify/assets/template.html +14937 -0
- package/skills/global_config/archify/bin/archify.mjs +2139 -0
- package/skills/global_config/archify/bin/open-artifact.mjs +86 -0
- package/skills/global_config/archify/bin/preview.mjs +653 -0
- package/skills/global_config/archify/bin/visual-check.mjs +829 -0
- package/skills/global_config/archify/brand-marks/README.md +31 -0
- package/skills/global_config/archify/brand-marks/catalog.json +131 -0
- package/skills/global_config/archify/delta/architecture-delta.mjs +1232 -0
- package/skills/global_config/archify/examples/agent-run.lifecycle.json +60 -0
- package/skills/global_config/archify/examples/agent-tool-call.workflow.json +94 -0
- package/skills/global_config/archify/examples/async-job-roundtrip.sequence.json +61 -0
- package/skills/global_config/archify/examples/brand-aware-delivery.architecture.json +47 -0
- package/skills/global_config/archify/examples/cache-miss-request.sequence.json +82 -0
- package/skills/global_config/archify/examples/checkout-platform.base.architecture.json +31 -0
- package/skills/global_config/archify/examples/checkout-platform.head.architecture.json +31 -0
- package/skills/global_config/archify/examples/deployment-release.lifecycle.json +49 -0
- package/skills/global_config/archify/examples/event-stream.dataflow.json +57 -0
- package/skills/global_config/archify/examples/incident-response.workflow.json +64 -0
- package/skills/global_config/archify/examples/product-analytics.dataflow.json +76 -0
- package/skills/global_config/archify/examples/production-deployment.architecture.json +71 -0
- package/skills/global_config/archify/examples/release-delivery.workflow.json +62 -0
- package/skills/global_config/archify/examples/web-app.architecture.json +46 -0
- package/skills/global_config/archify/migrations/workflow-v2.mjs +279 -0
- package/skills/global_config/archify/package.json +39 -0
- package/skills/global_config/archify/recipes/scenarios.mjs +391 -0
- package/skills/global_config/archify/references/authoring-contract.md +247 -0
- package/skills/global_config/archify/references/brand-marks.md +65 -0
- package/skills/global_config/archify/references/delivery-contract.md +138 -0
- package/skills/global_config/archify/references/viewer-runtime.md +45 -0
- package/skills/global_config/archify/renderers/architecture/grid.mjs +62 -0
- package/skills/global_config/archify/renderers/architecture/render-architecture.mjs +1078 -0
- package/skills/global_config/archify/renderers/dataflow/README.md +104 -0
- package/skills/global_config/archify/renderers/dataflow/render-dataflow.mjs +483 -0
- package/skills/global_config/archify/renderers/lifecycle/README.md +115 -0
- package/skills/global_config/archify/renderers/lifecycle/render-lifecycle.mjs +561 -0
- package/skills/global_config/archify/renderers/sequence/README.md +114 -0
- package/skills/global_config/archify/renderers/sequence/render-sequence.mjs +464 -0
- package/skills/global_config/archify/renderers/shared/brand-marks.mjs +563 -0
- package/skills/global_config/archify/renderers/shared/cli.mjs +218 -0
- package/skills/global_config/archify/renderers/shared/desktop-readability.mjs +26 -0
- package/skills/global_config/archify/renderers/shared/diagnostics.mjs +160 -0
- package/skills/global_config/archify/renderers/shared/engineering-profiles.mjs +157 -0
- package/skills/global_config/archify/renderers/shared/generated-brand-marks.mjs +2003 -0
- package/skills/global_config/archify/renderers/shared/generated-validators.mjs +13 -0
- package/skills/global_config/archify/renderers/shared/geometry.mjs +1423 -0
- package/skills/global_config/archify/renderers/shared/i18n.mjs +595 -0
- package/skills/global_config/archify/renderers/shared/layout-report.mjs +40 -0
- package/skills/global_config/archify/renderers/shared/legend.mjs +217 -0
- package/skills/global_config/archify/renderers/shared/output-path.mjs +340 -0
- package/skills/global_config/archify/renderers/shared/repository-evidence.mjs +239 -0
- package/skills/global_config/archify/renderers/shared/repository-location.mjs +58 -0
- package/skills/global_config/archify/renderers/shared/text-fit.mjs +49 -0
- package/skills/global_config/archify/renderers/shared/utils.mjs +232 -0
- package/skills/global_config/archify/renderers/shared/validator.mjs +86 -0
- package/skills/global_config/archify/renderers/workflow/README.md +223 -0
- package/skills/global_config/archify/renderers/workflow/render-workflow.mjs +35 -0
- package/skills/global_config/archify/renderers/workflow/workflow-compiler.mjs +4400 -0
- package/skills/global_config/archify/renderers/workflow/workflow-migration-geometry.mjs +144 -0
- package/skills/global_config/archify/schemas/README.md +211 -0
- package/skills/global_config/archify/schemas/architecture.schema.json +178 -0
- package/skills/global_config/archify/schemas/common.schema.json +115 -0
- package/skills/global_config/archify/schemas/dataflow.schema.json +243 -0
- package/skills/global_config/archify/schemas/lifecycle.schema.json +266 -0
- package/skills/global_config/archify/schemas/sequence.schema.json +223 -0
- package/skills/global_config/archify/schemas/workflow.schema.json +428 -0
- package/skills/global_config/archify/scripts/check-render-output.mjs +916 -0
- package/skills/global_config/archify/scripts/generate-brand-marks.mjs +141 -0
- package/skills/global_config/archify/scripts/generate-validators.mjs +66 -0
- package/skills/global_config/archify/scripts/render-examples.mjs +26 -0
- package/skills/global_config/archify/skill-release.json +10 -0
- package/skills/global_config/bdb-security-audit/SKILL.md +109 -0
- package/skills/global_config/bdb-security-audit/references/audit-checklists.md +172 -0
- package/skills/global_config/bdb-security-audit/references/skylos-guide.md +139 -0
- package/skills/global_config/bdb-security-audit/references/xalgorix-bridge.md +110 -0
- package/skills/global_config/bdbdesignpro/SKILL.md +4 -4
- package/skills/global_config/bdbdesignpro/references/bdb-motion-tokens.md +52 -31
- package/skills/global_config/bdbresilience/SKILL.md +10 -0
- package/skills/global_config/brag/SKILL.md +179 -0
- package/skills/global_config/brag/assets/music/README.md +20 -0
- package/skills/global_config/brag/assets/music/cues/happy-beats-business-moves-vol-1-by-ende-dot-app.music-cues.json +3846 -0
- package/skills/global_config/brag/assets/music/cues/happy-beats-business-moves-vol-1-by-ende-dot-app.music-cues.md +35 -0
- package/skills/global_config/brag/assets/music/cues/happy-beats-business-moves-vol-10-by-ende-dot-app.music-cues.json +1826 -0
- package/skills/global_config/brag/assets/music/cues/happy-beats-business-moves-vol-10-by-ende-dot-app.music-cues.md +35 -0
- package/skills/global_config/brag/assets/music/cues/happy-beats-business-moves-vol-11-by-ende-dot-app.music-cues.json +2266 -0
- package/skills/global_config/brag/assets/music/cues/happy-beats-business-moves-vol-11-by-ende-dot-app.music-cues.md +35 -0
- package/skills/global_config/brag/assets/music/cues/happy-beats-business-moves-vol-12-by-ende-dot-app.music-cues.json +2806 -0
- package/skills/global_config/brag/assets/music/cues/happy-beats-business-moves-vol-12-by-ende-dot-app.music-cues.md +35 -0
- package/skills/global_config/brag/assets/music/cues/happy-beats-business-moves-vol-9-by-ende-dot-app.music-cues.json +2796 -0
- package/skills/global_config/brag/assets/music/cues/happy-beats-business-moves-vol-9-by-ende-dot-app.music-cues.md +35 -0
- package/skills/global_config/brag/assets/music/happy-beats-business-moves-vol-1-by-ende-dot-app.mp3 +0 -0
- package/skills/global_config/brag/assets/music/happy-beats-business-moves-vol-10-by-ende-dot-app.mp3 +0 -0
- package/skills/global_config/brag/assets/music/happy-beats-business-moves-vol-11-by-ende-dot-app.mp3 +0 -0
- package/skills/global_config/brag/assets/music/happy-beats-business-moves-vol-12-by-ende-dot-app.mp3 +0 -0
- package/skills/global_config/brag/assets/music/happy-beats-business-moves-vol-9-by-ende-dot-app.mp3 +0 -0
- package/skills/global_config/brag/assets/sfx/casino/card-fan-1.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/card-fan-2.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/card-place-1.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/card-place-2.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/card-place-3.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/card-place-4.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/card-shove-1.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/card-shove-2.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/card-shove-3.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/card-shove-4.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/card-shuffle.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/card-slide-1.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/card-slide-2.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/card-slide-3.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/card-slide-4.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/card-slide-5.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/card-slide-6.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/card-slide-7.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/card-slide-8.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/cards-pack-open-1.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/cards-pack-open-2.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/chip-lay-1.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/chip-lay-2.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/chip-lay-3.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/chips-collide-1.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/chips-collide-2.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/chips-collide-3.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/chips-collide-4.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/chips-handle-1.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/chips-handle-2.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/chips-handle-3.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/chips-handle-4.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/chips-handle-6.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/chips-stack-1.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/chips-stack-2.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/chips-stack-3.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/chips-stack-4.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/chips-stack-5.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/chips-stack-6.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/dice-grab-1.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/dice-grab-2.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/dice-shake-1.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/dice-shake-2.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/dice-shake-3.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/dice-throw-1.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/dice-throw-2.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/dice-throw-3.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/die-throw-1.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/die-throw-2.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/die-throw-3.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/die-throw-4.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_carpet_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_carpet_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_carpet_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_concrete_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_concrete_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_concrete_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_concrete_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_concrete_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_grass_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_grass_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_grass_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_grass_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_grass_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_snow_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_snow_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_snow_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_snow_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_snow_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_wood_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_wood_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_wood_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_wood_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_wood_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactBell_heavy_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactBell_heavy_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactBell_heavy_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactGeneric_light_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactGeneric_light_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactGeneric_light_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactGeneric_light_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactGeneric_light_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactGlass_heavy_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactGlass_light_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactGlass_light_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactGlass_light_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactGlass_medium_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactGlass_medium_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactGlass_medium_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactMetal_heavy_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactMetal_heavy_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactMetal_heavy_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactMetal_light_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactMetal_light_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactMetal_medium_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactMetal_medium_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactMetal_medium_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactMetal_medium_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactMetal_medium_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactMining_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPlank_medium_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPlank_medium_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPlank_medium_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPlank_medium_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPlank_medium_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPlate_heavy_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPlate_heavy_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPlate_heavy_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPlate_heavy_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPlate_heavy_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPlate_light_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPlate_light_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPlate_light_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPlate_light_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPlate_light_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPlate_medium_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPlate_medium_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPlate_medium_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPlate_medium_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPlate_medium_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPunch_heavy_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPunch_heavy_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPunch_heavy_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPunch_heavy_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPunch_heavy_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPunch_medium_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPunch_medium_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPunch_medium_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPunch_medium_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPunch_medium_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactSoft_heavy_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactSoft_heavy_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactSoft_heavy_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactSoft_heavy_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactSoft_heavy_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactSoft_medium_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactSoft_medium_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactSoft_medium_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactSoft_medium_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactSoft_medium_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactTin_medium_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactTin_medium_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactTin_medium_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactTin_medium_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactTin_medium_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactWood_heavy_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactWood_heavy_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactWood_heavy_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactWood_heavy_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactWood_heavy_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactWood_light_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactWood_light_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactWood_light_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactWood_light_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactWood_light_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactWood_medium_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactWood_medium_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactWood_medium_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactWood_medium_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactWood_medium_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/interface/bong_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/interface/click_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/interface/click_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/interface/click_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/interface/click_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/interface/click_005.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/interface/drop_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/interface/drop_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/interface/drop_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/interface/error_005.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/interface/error_006.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/interface/glitch_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/interface/glitch_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/interface/select_008.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/interface/switch_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/interface/switch_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/interface/switch_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/interface/switch_005.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/interface/switch_006.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/interface/switch_007.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-001.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-002.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-003.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-004.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-005.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-006.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-007.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-008.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-009.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-010.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-011.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-012.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-013.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-014.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-015.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-016.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-017.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-018.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-019.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-020.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-021.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-022.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-023.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-024.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-025.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-026.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-027.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-028.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-029.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-030.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-031.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-032.wav +0 -0
- package/skills/global_config/brag/assets/sfx/sfx-analysis.json +15584 -0
- package/skills/global_config/brag/assets/sfx/sfx-analysis.md +75 -0
- package/skills/global_config/brag/assets/sfx/ui/click1.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/click2.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/click3.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/click4.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/click5.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/mouseclick1.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/rollover1.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/rollover2.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/rollover4.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/rollover5.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch1.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch10.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch11.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch12.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch13.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch14.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch15.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch16.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch17.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch18.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch19.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch2.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch20.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch21.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch22.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch23.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch24.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch25.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch26.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch27.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch28.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch29.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch3.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch30.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch31.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch32.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch33.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch34.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch35.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch36.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch37.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch38.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch4.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch5.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch6.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch7.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch8.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch9.ogg +0 -0
- package/skills/global_config/brag/references/audio.md +307 -0
- package/skills/global_config/brag/references/step-1-inspect.md +133 -0
- package/skills/global_config/brag/references/step-2-plan.md +234 -0
- package/skills/global_config/brag/references/step-3-compose.md +210 -0
- package/skills/global_config/brag/references/step-4-deliver.md +168 -0
- package/skills/global_config/brag/references/tones.md +231 -0
- package/skills/global_config/brag/scripts/analyze_music_cues.py +309 -0
- package/skills/global_config/brag/scripts/pyproject.toml +14 -0
- package/skills/global_config/brag/scripts/uv.lock +819 -0
- package/skills/global_config/deja-memory/SKILL.md +42 -0
- package/skills/global_config/editable-design/LICENSE +202 -0
- package/skills/global_config/editable-design/README.md +34 -0
- package/skills/global_config/editable-design/SKILL.md +630 -0
- package/skills/global_config/editable-design/THIRD_PARTY_NOTICES.md +10 -0
- package/skills/global_config/editable-design/agents/openai.yaml +4 -0
- package/skills/global_config/editable-design/assets/editor/layer-editor.css +262 -0
- package/skills/global_config/editable-design/assets/editor/layer-editor.js +1929 -0
- package/skills/global_config/editable-design/assets/poster-starter/README.md +92 -0
- package/skills/global_config/editable-design/assets/poster-starter/assets/.gitkeep +0 -0
- package/skills/global_config/editable-design/assets/poster-starter/index.html +91 -0
- package/skills/global_config/editable-design/assets/poster-starter/poster.json +6 -0
- package/skills/global_config/editable-design/assets/poster-starter/reference/.gitkeep +1 -0
- package/skills/global_config/editable-design/assets/replay/icons/assets.png +0 -0
- package/skills/global_config/editable-design/assets/replay/icons/html.png +0 -0
- package/skills/global_config/editable-design/assets/replay/icons/input.png +0 -0
- package/skills/global_config/editable-design/assets/replay/icons/layers.png +0 -0
- package/skills/global_config/editable-design/assets/replay/icons/plan.png +0 -0
- package/skills/global_config/editable-design/assets/replay/icons/reference.png +0 -0
- package/skills/global_config/editable-design/assets/replay/icons/review.png +0 -0
- package/skills/global_config/editable-design/assets/replay/index.html +59 -0
- package/skills/global_config/editable-design/assets/replay/replay-motion.js +410 -0
- package/skills/global_config/editable-design/assets/replay/replay.css +380 -0
- package/skills/global_config/editable-design/assets/replay/replay.js +374 -0
- package/skills/global_config/editable-design/font-kit/package-lock.json +115 -0
- package/skills/global_config/editable-design/font-kit/package.json +19 -0
- package/skills/global_config/editable-design/pack.sh +20 -0
- package/skills/global_config/editable-design/references/asset-architecture.md +72 -0
- package/skills/global_config/editable-design/references/editor-pitfalls.md +70 -0
- package/skills/global_config/editable-design/references/editor-runtime.md +131 -0
- package/skills/global_config/editable-design/references/font-system.md +89 -0
- package/skills/global_config/editable-design/references/imagery.md +145 -0
- package/skills/global_config/editable-design/references/layout-typography.md +116 -0
- package/skills/global_config/editable-design/references/replay-contract.md +169 -0
- package/skills/global_config/editable-design/scripts/_browser.mjs +247 -0
- package/skills/global_config/editable-design/scripts/bake.mjs +87 -0
- package/skills/global_config/editable-design/scripts/build-replay.mjs +316 -0
- package/skills/global_config/editable-design/scripts/check-contract.mjs +293 -0
- package/skills/global_config/editable-design/scripts/check-fonts.sh +252 -0
- package/skills/global_config/editable-design/scripts/check-poster.sh +70 -0
- package/skills/global_config/editable-design/scripts/doctor.sh +78 -0
- package/skills/global_config/editable-design/scripts/explode.mjs +115 -0
- package/skills/global_config/editable-design/scripts/font-kit.mjs +187 -0
- package/skills/global_config/editable-design/scripts/import-asset.sh +23 -0
- package/skills/global_config/editable-design/scripts/init-poster.sh +64 -0
- package/skills/global_config/editable-design/scripts/install-font-kit.sh +13 -0
- package/skills/global_config/editable-design/scripts/package-lock.json +334 -0
- package/skills/global_config/editable-design/scripts/package.json +14 -0
- package/skills/global_config/editable-design/scripts/remove-chroma-key.py +201 -0
- package/skills/global_config/editable-design/scripts/render-poster.sh +202 -0
- package/skills/global_config/editable-design/scripts/trace.sh +159 -0
- package/skills/global_config/editable-design/scripts/verify-replay.mjs +97 -0
- package/skills/global_config/editable-design/scripts/verify.mjs +782 -0
- package/skills/global_config/editable-design/scripts/wire-editor.mjs +104 -0
- package/skills/global_config/editable-design/tests/fixtures/small-explode/index.html +86 -0
- package/skills/global_config/plan-canvas/SKILL.md +8 -0
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# Agent design replay contract
|
|
2
|
+
|
|
3
|
+
Read this only when recording, generating, or diagnosing a poster Replay.
|
|
4
|
+
The Replay is a deterministic view of the actual run, not a second design task.
|
|
5
|
+
|
|
6
|
+
## Seven story stages
|
|
7
|
+
|
|
8
|
+
Production may use more steps, but the viewer always groups evidence into:
|
|
9
|
+
|
|
10
|
+
1. Input — the user's original request and supplied attachments.
|
|
11
|
+
2. Reference — the exact enhanced art-direction prompt and its generated image.
|
|
12
|
+
3. Plan — composition notes, zones, asset topology, and slot geometry.
|
|
13
|
+
4. Assets — each shipping prompt paired with its imported result.
|
|
14
|
+
5. HTML — real source code and the rendered poster.
|
|
15
|
+
6. Review — concrete findings, changes, and rerender outcomes.
|
|
16
|
+
7. Layers — the verified editor or standalone exploded view and contract counts.
|
|
17
|
+
|
|
18
|
+
Canvas choice, font checks, cleanup, imports, and command logs remain in
|
|
19
|
+
`.trace`; they are metadata inside these stages rather than separate story nodes.
|
|
20
|
+
|
|
21
|
+
## Evidence files
|
|
22
|
+
|
|
23
|
+
- `brief.md` — the original user request verbatim. Include attachment paths, but
|
|
24
|
+
do not copy ambient UI state, system instructions, or hidden context into it.
|
|
25
|
+
- `reference/composition-prompt.md` — the exact prompt sent to the image model
|
|
26
|
+
for the non-shipping art-direction reference.
|
|
27
|
+
- `reference/composition-reference.png` — the generated reference image.
|
|
28
|
+
- `design-plan.md` — the single integrated decision for live wording,
|
|
29
|
+
hierarchy, asset topology, regions, layer order, palette, typography, and
|
|
30
|
+
geometry.
|
|
31
|
+
- `asset-plan.json` — asset IDs, target rectangles, topology, prompt IDs, and
|
|
32
|
+
dependencies when more than one shipping asset is used.
|
|
33
|
+
- `prompts.md` — exact shipping prompts. Every `##` heading used by an asset
|
|
34
|
+
must equal that asset's `prompt` value in `asset-plan.json`.
|
|
35
|
+
- `assets/*` — imported shipping results. Prefer an asset filename stem equal to
|
|
36
|
+
its `id` in `asset-plan.json`.
|
|
37
|
+
- `index.html` and `out/poster.png` — source and current render.
|
|
38
|
+
- `render-review.md` — the agent's real visual review, not a retrospective
|
|
39
|
+
marketing explanation.
|
|
40
|
+
- `editor.html` and `layers.html` — editable and standalone exploded results.
|
|
41
|
+
|
|
42
|
+
Record each file under its existing trace step as soon as it becomes stable.
|
|
43
|
+
Do not write generic sections such as “why this was done” or “what this node is
|
|
44
|
+
doing”. The viewer exposes the agent's actual prompt, plan, code, findings,
|
|
45
|
+
changes, and outputs.
|
|
46
|
+
|
|
47
|
+
## Review format
|
|
48
|
+
|
|
49
|
+
Use one section per real review pass when more than one pass occurs:
|
|
50
|
+
|
|
51
|
+
```markdown
|
|
52
|
+
# Render review
|
|
53
|
+
|
|
54
|
+
## Pass 01
|
|
55
|
+
|
|
56
|
+
### Findings
|
|
57
|
+
- Concrete visible defect.
|
|
58
|
+
|
|
59
|
+
### Changes
|
|
60
|
+
- Concrete edit applied to address it.
|
|
61
|
+
|
|
62
|
+
### Result
|
|
63
|
+
- What the rerender confirmed.
|
|
64
|
+
|
|
65
|
+
### Optimization
|
|
66
|
+
- The one highest-impact enhancement applied, or `none` when the approved
|
|
67
|
+
render already preserves scanning, recall, and reference fidelity.
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Do not invent a pass merely to make the Replay look active. A clean first render
|
|
71
|
+
may have one review section with no defects and `Optimization: none`. Keep all
|
|
72
|
+
real review and optimization activity in this one file, then record the
|
|
73
|
+
consolidated `render-review.md` once under `P16_read_render` after the final
|
|
74
|
+
render.
|
|
75
|
+
|
|
76
|
+
## Generation
|
|
77
|
+
|
|
78
|
+
After the poster, editor, and exploded behavior pass verification:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
node scripts/build-replay.mjs .
|
|
82
|
+
node scripts/verify-replay.mjs replay/index.html
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
For a project created before the Replay runtime was added, call the equivalent
|
|
86
|
+
scripts from the installed `poster-building` skill and pass the project path.
|
|
87
|
+
Do not rerun the project initializer over an existing poster.
|
|
88
|
+
|
|
89
|
+
The builder emits `replay/index.html`, `data.js`, CSS, JS, and local icons. It
|
|
90
|
+
embeds text evidence in `data.js`, so opening the result over `file://` does not
|
|
91
|
+
depend on `fetch`. Media paths remain relative to the poster project.
|
|
92
|
+
|
|
93
|
+
The fixed viewer keeps three persistent phase controls visible: 理解与规划
|
|
94
|
+
(01—03), 生成与构建 (04—05), and 观察与修正 (06—07). Those controls live in
|
|
95
|
+
the scalable canvas world rather than in a fixed screen-space overlay, so fit
|
|
96
|
+
view cannot stack them over evidence nodes. Each phase card uses a 210 × 210px
|
|
97
|
+
world-space footprint with a 56px icon and a 19px label, so the controls remain
|
|
98
|
+
legible after fit-view scaling. A plain open finishes on the clean
|
|
99
|
+
overview with no stage detail expanded. An explicit `?stage=` query remains a
|
|
100
|
+
supported deep link, and closing a detail removes that query. Flow-arrow markers
|
|
101
|
+
use user-space sizing so their heads remain visually bounded when stroke widths
|
|
102
|
+
change.
|
|
103
|
+
|
|
104
|
+
The Design Plan, final rendered PNG, and editable layer animation share the same
|
|
105
|
+
right-column x-position. The generated reference is centered in the open space
|
|
106
|
+
between the Visual Reference and Design Plan stages. A single straight dashed
|
|
107
|
+
blue connector runs from stage 02, behind the centered reference, and into stage
|
|
108
|
+
03; no solid blue route loops above the image. The render lightbox loads the
|
|
109
|
+
original PNG directly and aspect-fits it within the available viewport; it must
|
|
110
|
+
show the full image without cropping or substituting a partial viewport capture.
|
|
111
|
+
|
|
112
|
+
The viewer has three motion states. On load it reconstructs the complete path
|
|
113
|
+
in 4.7 seconds: canvas settle, rapid node placement, ordered line drawing,
|
|
114
|
+
one phase pulse, final-output settle, and completion-light activation. The
|
|
115
|
+
detail panel stays fully hidden until this reconstruction completes. The
|
|
116
|
+
finished overview then uses no moving dashes; its first main pulse appears after
|
|
117
|
+
about 0.4 seconds and its first repair pulse after about 1.1 seconds, followed by
|
|
118
|
+
clearly visible energy packets on main paths every 1.8–3 seconds and repair paths
|
|
119
|
+
every 2.6–4 seconds, with at most two packets alive at once. Ambient packets
|
|
120
|
+
cross their paths in about 1.15 seconds. The playback control pauses ambient
|
|
121
|
+
motion and runs stronger
|
|
122
|
+
600–800ms causal pulses while synchronizing node focus, artifacts, and the
|
|
123
|
+
detail panel. Ambient motion pauses when the document is hidden or the canvas is
|
|
124
|
+
zoomed below 0.20 scale. `prefers-reduced-motion` disables all three motion
|
|
125
|
+
layers without hiding evidence.
|
|
126
|
+
|
|
127
|
+
The main-canvas Assets previews also use a quiet gallery cycle only in the
|
|
128
|
+
finished overview: each visible card brightens, rises 2–3px, gains a slightly
|
|
129
|
+
stronger shadow, and scales its image to 1.015 for about 700ms. After all visible
|
|
130
|
+
cards have been featured once, the gallery rests for a random 4–6 seconds. This
|
|
131
|
+
cycle pauses with ambient motion and never competes with formal playback.
|
|
132
|
+
|
|
133
|
+
The Assets detail begins with a compact visual overview of every recorded
|
|
134
|
+
shipping result before its Prompt/result accordions. The main canvas uses a
|
|
135
|
+
2540×1780 world: the Assets node shows only a short Prompt summary and balances
|
|
136
|
+
with the surrounding stage cards. Up to four shipping results appear beside it.
|
|
137
|
+
Exactly one result expands across the entire former 2×2 footprint and uses one
|
|
138
|
+
short dashed connector. Two to four results use the 2×2 matrix, with one
|
|
139
|
+
connector per visible result and no connector branches for empty slots. Every
|
|
140
|
+
result remains available in the detail overview.
|
|
141
|
+
Design Plan uses recorded rectangles when all slots provide valid geometry. If
|
|
142
|
+
the plan records semantic asset slots but no rectangles, the viewer lays those
|
|
143
|
+
real slots out as a compact matrix with their IDs and recorded roles; it never
|
|
144
|
+
stacks them into an apparently blank placeholder. If no slots were recorded at
|
|
145
|
+
all, it states that evidence is missing rather than inventing a composition.
|
|
146
|
+
The generated reference sits centered between the Visual Reference and Design
|
|
147
|
+
Plan stages at a slightly smaller scale, with their dashed connector visually
|
|
148
|
+
entering and leaving the image. The final render and layer output use large cards
|
|
149
|
+
in the right output column.
|
|
150
|
+
The 反馈修正 label sits on the green observation path, while the red return
|
|
151
|
+
path remains the visible repair loop. This keeps evidence readable without
|
|
152
|
+
placing an artifact between flow nodes or over their connectors.
|
|
153
|
+
|
|
154
|
+
When the layer output is `layers.html`, Replay embeds its live HTML animation,
|
|
155
|
+
not a GIF and not its `?motion=0` screenshot state. Do not load its iframe at
|
|
156
|
+
page startup: start it when the intro reaches the Layers output, and restart it
|
|
157
|
+
whenever formal playback reaches Layers or the user opens that stage. This keeps
|
|
158
|
+
the layer motion synchronized with the surrounding Replay instead of letting it
|
|
159
|
+
finish behind the 4.7-second intro. The lightbox reloads it on every open.
|
|
160
|
+
|
|
161
|
+
The stage detail panel is a wide, independently scrolling surface; wheel input
|
|
162
|
+
inside it never changes canvas zoom. Clicking the reference or final-render
|
|
163
|
+
artifact opens an image lightbox instead of stage details. Clicking the layer
|
|
164
|
+
artifact opens a large live-HTML lightbox and reloads it so its animation starts
|
|
165
|
+
from the beginning on every open.
|
|
166
|
+
|
|
167
|
+
The builder may derive ordering, time, canvas size, layer counts, and asset
|
|
168
|
+
pairings from recorded files. It must never reconstruct a missing prompt or
|
|
169
|
+
decision from memory. Missing evidence stays visibly missing.
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* _browser.mjs —— 编辑、固化、拆解与验收脚本共用的 headless 浏览器封装
|
|
3
|
+
*
|
|
4
|
+
* 为什么必须用真浏览器:图层坐标只能由布局引擎算出。jsdom / cheerio
|
|
5
|
+
* 没有布局引擎,getBoundingClientRect() 恒返回 0,纯文本方案不可行。
|
|
6
|
+
*/
|
|
7
|
+
import { existsSync, mkdtempSync, rmSync, readFileSync, writeFileSync, copyFileSync, unlinkSync } from 'node:fs';
|
|
8
|
+
import { tmpdir } from 'node:os';
|
|
9
|
+
import { dirname, join, resolve } from 'node:path';
|
|
10
|
+
import { fileURLToPath } from 'node:url';
|
|
11
|
+
import { execFileSync } from 'node:child_process';
|
|
12
|
+
|
|
13
|
+
const ASSETS = resolve(dirname(fileURLToPath(import.meta.url)), '../assets/editor');
|
|
14
|
+
const ASSET_FILES = ['layer-editor.css', 'layer-editor.js'];
|
|
15
|
+
const TAGS = ' <link rel="stylesheet" href="layer-editor.css">\n'
|
|
16
|
+
+ ' <script src="layer-editor.js" defer></script>\n';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* 临时把编辑器接到一张海报上,用于离线驱动。
|
|
20
|
+
* 临时 HTML 必须放在海报同目录,否则 assets/ 之类的相对路径会失效。
|
|
21
|
+
* cleanup() 会移除临时文件,并将项目原有的编辑器资产逐字节还原。
|
|
22
|
+
* 验收不得把技能内置运行时永久覆盖到已经完成的项目里。
|
|
23
|
+
*/
|
|
24
|
+
export function wireTemp(src, name = '_hf_tmp.html') {
|
|
25
|
+
const dir = dirname(src);
|
|
26
|
+
const tmp = join(dir, name);
|
|
27
|
+
const originalAssets = new Map(ASSET_FILES.map((f) => {
|
|
28
|
+
const target = join(dir, f);
|
|
29
|
+
return [f, existsSync(target) ? readFileSync(target) : null];
|
|
30
|
+
}));
|
|
31
|
+
const html = readFileSync(src, 'utf8');
|
|
32
|
+
if (!/<\/head>/i.test(html)) throw new Error('这份 HTML 没有 </head>,无法注入编辑器');
|
|
33
|
+
|
|
34
|
+
for (const f of ASSET_FILES) copyFileSync(join(ASSETS, f), join(dir, f));
|
|
35
|
+
writeFileSync(tmp, html.includes('layer-editor.js') ? html : html.replace(/<\/head>/i, TAGS + '</head>'));
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
file: tmp,
|
|
39
|
+
cleanup() {
|
|
40
|
+
try { unlinkSync(tmp); } catch { /* 已不存在 */ }
|
|
41
|
+
for (const f of ASSET_FILES) {
|
|
42
|
+
const target = join(dir, f);
|
|
43
|
+
const original = originalAssets.get(f);
|
|
44
|
+
if (original) writeFileSync(target, original);
|
|
45
|
+
else { try { unlinkSync(target); } catch { /* 已不存在 */ } }
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
let puppeteer;
|
|
52
|
+
try {
|
|
53
|
+
puppeteer = (await import('puppeteer-core')).default;
|
|
54
|
+
} catch {
|
|
55
|
+
console.error('缺少依赖 puppeteer-core。请先执行:');
|
|
56
|
+
console.error(' cd "' + dirname(fileURLToPath(import.meta.url)) + '" && npm install');
|
|
57
|
+
process.exit(2);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const CHROME_CANDIDATES = [
|
|
61
|
+
process.env.EDITABLE_DESIGN_BROWSER,
|
|
62
|
+
process.env.PUPPETEER_EXECUTABLE_PATH,
|
|
63
|
+
process.env.POSTER_BROWSER,
|
|
64
|
+
process.env.CHROME_PATH,
|
|
65
|
+
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
|
|
66
|
+
'/Applications/Chromium.app/Contents/MacOS/Chromium',
|
|
67
|
+
'/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge',
|
|
68
|
+
'/usr/bin/google-chrome',
|
|
69
|
+
'/usr/bin/chromium-browser',
|
|
70
|
+
'/usr/bin/chromium',
|
|
71
|
+
].filter(Boolean);
|
|
72
|
+
|
|
73
|
+
function findChrome() {
|
|
74
|
+
let hit = CHROME_CANDIDATES.find((p) => existsSync(p));
|
|
75
|
+
if (!hit) {
|
|
76
|
+
for (const name of ['chromium', 'google-chrome', 'chrome']) {
|
|
77
|
+
try {
|
|
78
|
+
const found = execFileSync('which', [name], { encoding: 'utf8' }).trim();
|
|
79
|
+
if (found && existsSync(found)) { hit = found; break; }
|
|
80
|
+
} catch { /* try the next name */ }
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (!hit) {
|
|
84
|
+
console.error('找不到 Chrome。请设置 EDITABLE_DESIGN_BROWSER 指向浏览器可执行文件。');
|
|
85
|
+
process.exit(2);
|
|
86
|
+
}
|
|
87
|
+
return hit;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export async function launch() {
|
|
91
|
+
// 每次用全新的临时 profile:既避开用户已开着的 Chrome 实例
|
|
92
|
+
// (否则会卡在 "Timed out waiting for the WS endpoint URL"),
|
|
93
|
+
// 也保证 localStorage 干净,草稿不会干扰固化结果。
|
|
94
|
+
const profile = mkdtempSync(join(tmpdir(), 'layer-editor-'));
|
|
95
|
+
const args = [
|
|
96
|
+
'--allow-file-access-from-files',
|
|
97
|
+
'--font-render-hinting=none',
|
|
98
|
+
'--disable-gpu',
|
|
99
|
+
`--user-data-dir=${profile}`,
|
|
100
|
+
];
|
|
101
|
+
if (process.env.EDITABLE_DESIGN_NO_SANDBOX === '1') args.push('--no-sandbox');
|
|
102
|
+
const browser = await puppeteer.launch({
|
|
103
|
+
executablePath: findChrome(),
|
|
104
|
+
headless: true,
|
|
105
|
+
args,
|
|
106
|
+
});
|
|
107
|
+
const origClose = browser.close.bind(browser);
|
|
108
|
+
browser.close = async () => {
|
|
109
|
+
await origClose();
|
|
110
|
+
try { rmSync(profile, { recursive: true, force: true }); } catch { /* 清理失败无妨 */ }
|
|
111
|
+
};
|
|
112
|
+
return browser;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* 加载一个本地 HTML 文件并等到可以安全测量为止。
|
|
117
|
+
* waitEditor=true 时额外等编辑器初始化完成(data-hf-ready)。
|
|
118
|
+
*/
|
|
119
|
+
export async function open(browser, file, { width = 1600, height = 1200, waitEditor = false } = {}) {
|
|
120
|
+
const page = await browser.newPage();
|
|
121
|
+
await page.setViewport({ width, height, deviceScaleFactor: 1 });
|
|
122
|
+
const errors = [];
|
|
123
|
+
page.on('pageerror', (e) => errors.push(String(e)));
|
|
124
|
+
page.on('console', (m) => { if (m.type() === 'error') errors.push('console: ' + m.text()); });
|
|
125
|
+
|
|
126
|
+
await page.goto('file://' + resolve(file), { waitUntil: 'networkidle0' });
|
|
127
|
+
if (waitEditor) await page.waitForSelector('html[data-hf-ready]', { timeout: 20000 });
|
|
128
|
+
// 字体与图片决定文字块尺寸和图层高度,量之前必须落地
|
|
129
|
+
await page.evaluate(() => document.fonts.ready);
|
|
130
|
+
await page.evaluate(() => Promise.all(
|
|
131
|
+
[...document.images].filter((i) => !i.complete).map((i) => new Promise((r) => {
|
|
132
|
+
i.addEventListener('load', r, { once: true });
|
|
133
|
+
i.addEventListener('error', r, { once: true });
|
|
134
|
+
})),
|
|
135
|
+
));
|
|
136
|
+
await new Promise((r) => setTimeout(r, 350));
|
|
137
|
+
return { page, errors };
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/** 读出每个 data-layer-id 图层相对画布的位置与尺寸(换算掉画布缩放) */
|
|
141
|
+
export function probe(page) {
|
|
142
|
+
return page.evaluate(() => {
|
|
143
|
+
const cv = document.querySelector('[data-canvas-width]') || document.querySelector('.poster-canvas');
|
|
144
|
+
if (!cv) return null;
|
|
145
|
+
const c = cv.getBoundingClientRect();
|
|
146
|
+
const scale = c.width / (+cv.dataset.canvasWidth || cv.offsetWidth);
|
|
147
|
+
const out = {};
|
|
148
|
+
for (const el of cv.querySelectorAll('[data-layer-id]')) {
|
|
149
|
+
const r = el.getBoundingClientRect();
|
|
150
|
+
out[el.dataset.layerId] = {
|
|
151
|
+
left: +((r.left - c.left) / scale).toFixed(1),
|
|
152
|
+
top: +((r.top - c.top) / scale).toFixed(1),
|
|
153
|
+
width: +(r.width / scale).toFixed(1),
|
|
154
|
+
height: +(r.height / scale).toFixed(1),
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
return out;
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/** 逐图层比对两次测量,返回最大偏差与超差清单 */
|
|
162
|
+
export function diff(a, b, tol = 1) {
|
|
163
|
+
const ids = [...new Set([...Object.keys(a || {}), ...Object.keys(b || {})])];
|
|
164
|
+
const rows = [];
|
|
165
|
+
let worst = 0;
|
|
166
|
+
for (const id of ids) {
|
|
167
|
+
if (!a?.[id] || !b?.[id]) { rows.push({ id, missing: true }); continue; }
|
|
168
|
+
const d = Math.max(Math.abs(a[id].left - b[id].left), Math.abs(a[id].top - b[id].top));
|
|
169
|
+
worst = Math.max(worst, d);
|
|
170
|
+
rows.push({ id, a: a[id], b: b[id], d: +d.toFixed(2), fail: d > tol });
|
|
171
|
+
}
|
|
172
|
+
return { worst: +worst.toFixed(2), rows, ok: rows.every((r) => !r.fail && !r.missing) };
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* 对两个页面中的画布做真实像素比对。
|
|
177
|
+
*
|
|
178
|
+
* 几何一致只能证明图层框没有移动,无法发现上下文选择器失效、背景消失、
|
|
179
|
+
* 伪元素丢失或绘制顺序改变。这里直接截取元素并交给浏览器解码 PNG,避免
|
|
180
|
+
* 再引入 sharp/pngjs 等依赖。perChannelTolerance 用于忽略极轻微的抗锯齿噪声。
|
|
181
|
+
*/
|
|
182
|
+
export async function pixelDiff(pageA, selectorA, pageB, selectorB, { perChannelTolerance = 2 } = {}) {
|
|
183
|
+
const elA = await pageA.$(selectorA);
|
|
184
|
+
const elB = await pageB.$(selectorB);
|
|
185
|
+
if (!elA || !elB) return { ok: false, reason: '找不到待比较画布' };
|
|
186
|
+
const capture = async (page, el) => {
|
|
187
|
+
const box = await el.boundingBox();
|
|
188
|
+
if (!box) throw new Error('待比较画布不可见');
|
|
189
|
+
// ElementHandle.screenshot() 会先尝试滚动元素到可见区。对于高于
|
|
190
|
+
// 普通视口的竖版海报,某些 Chrome 版本会在这一步长时间等待。
|
|
191
|
+
// 画布已被安置在足够大的视口中,直接按 bounding box 裁剪更稳定。
|
|
192
|
+
return page.screenshot({
|
|
193
|
+
type: 'png', omitBackground: true, captureBeyondViewport: true,
|
|
194
|
+
clip: { x: box.x, y: box.y, width: box.width, height: box.height },
|
|
195
|
+
});
|
|
196
|
+
};
|
|
197
|
+
// Puppeteer 会用同一把截图锁保护 BrowserContext,必须顺序执行。
|
|
198
|
+
const pngA = await capture(pageA, elA);
|
|
199
|
+
const pngB = await capture(pageB, elB);
|
|
200
|
+
if (Buffer.compare(pngA, pngB) === 0) {
|
|
201
|
+
return { ok: true, width: 0, height: 0, changed: 0, changedRatio: 0, meanAbs: 0, exact: true };
|
|
202
|
+
}
|
|
203
|
+
return pageA.evaluate(async ({ a, b, tolerance }) => {
|
|
204
|
+
const load = (base64) => new Promise((resolve, reject) => {
|
|
205
|
+
const img = new Image();
|
|
206
|
+
img.onload = () => resolve(img);
|
|
207
|
+
img.onerror = () => reject(new Error('PNG 解码失败'));
|
|
208
|
+
img.src = `data:image/png;base64,${base64}`;
|
|
209
|
+
});
|
|
210
|
+
const [imgA, imgB] = await Promise.all([load(a), load(b)]);
|
|
211
|
+
if (imgA.naturalWidth !== imgB.naturalWidth || imgA.naturalHeight !== imgB.naturalHeight) {
|
|
212
|
+
return {
|
|
213
|
+
ok: false, reason: '尺寸不一致',
|
|
214
|
+
a: [imgA.naturalWidth, imgA.naturalHeight], b: [imgB.naturalWidth, imgB.naturalHeight],
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
const width = imgA.naturalWidth, height = imgA.naturalHeight;
|
|
218
|
+
const cv = document.createElement('canvas');
|
|
219
|
+
cv.width = width; cv.height = height;
|
|
220
|
+
const ctx = cv.getContext('2d', { willReadFrequently: true });
|
|
221
|
+
ctx.clearRect(0, 0, width, height); ctx.drawImage(imgA, 0, 0);
|
|
222
|
+
const aData = ctx.getImageData(0, 0, width, height).data;
|
|
223
|
+
ctx.clearRect(0, 0, width, height); ctx.drawImage(imgB, 0, 0);
|
|
224
|
+
const bData = ctx.getImageData(0, 0, width, height).data;
|
|
225
|
+
let changed = 0, totalAbs = 0, worst = 0;
|
|
226
|
+
for (let i = 0; i < aData.length; i += 4) {
|
|
227
|
+
const dr = Math.abs(aData[i] - bData[i]);
|
|
228
|
+
const dg = Math.abs(aData[i + 1] - bData[i + 1]);
|
|
229
|
+
const db = Math.abs(aData[i + 2] - bData[i + 2]);
|
|
230
|
+
const da = Math.abs(aData[i + 3] - bData[i + 3]);
|
|
231
|
+
const local = Math.max(dr, dg, db, da);
|
|
232
|
+
if (local > tolerance) changed++;
|
|
233
|
+
totalAbs += dr + dg + db + da;
|
|
234
|
+
if (local > worst) worst = local;
|
|
235
|
+
}
|
|
236
|
+
const pixels = width * height;
|
|
237
|
+
return {
|
|
238
|
+
ok: true, width, height, changed,
|
|
239
|
+
changedRatio: changed / pixels,
|
|
240
|
+
meanAbs: totalAbs / (pixels * 4), worst, exact: false,
|
|
241
|
+
};
|
|
242
|
+
}, {
|
|
243
|
+
a: Buffer.from(pngA).toString('base64'),
|
|
244
|
+
b: Buffer.from(pngB).toString('base64'),
|
|
245
|
+
tolerance: perChannelTolerance,
|
|
246
|
+
});
|
|
247
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* bake.mjs —— 离线布局固化
|
|
4
|
+
*
|
|
5
|
+
* node bake.mjs <海报 index.html> [--in-place]
|
|
6
|
+
*
|
|
7
|
+
* 把文档流布局改写成纯绝对定位,视觉零变化。产物此后天然可拖,
|
|
8
|
+
* 打开编辑器时不再需要现场固化(也就不再依赖字体每次都加载成功)。
|
|
9
|
+
*
|
|
10
|
+
* 默认输出 <base>.absolute.html;--in-place 直接覆盖原文件。
|
|
11
|
+
* 验收:所有图层坐标偏差必须 ≤1px,否则不落盘并退出 1。
|
|
12
|
+
*/
|
|
13
|
+
import { writeFileSync, existsSync, unlinkSync } from 'node:fs';
|
|
14
|
+
import { dirname, join, resolve, basename, extname } from 'node:path';
|
|
15
|
+
import { launch, open, probe, diff, wireTemp } from './_browser.mjs';
|
|
16
|
+
|
|
17
|
+
const file = process.argv[2];
|
|
18
|
+
const inPlace = process.argv.includes('--in-place');
|
|
19
|
+
if (!file || !existsSync(resolve(file))) {
|
|
20
|
+
console.error('用法: node bake.mjs <海报 index.html> [--in-place]');
|
|
21
|
+
process.exit(2);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const src = resolve(file);
|
|
25
|
+
const dir = dirname(src);
|
|
26
|
+
const out = inPlace ? src : join(dir, `${basename(src, extname(src))}.absolute.html`);
|
|
27
|
+
|
|
28
|
+
let wired;
|
|
29
|
+
try {
|
|
30
|
+
wired = wireTemp(src, '_hf_bake.html');
|
|
31
|
+
} catch (err) {
|
|
32
|
+
console.error('❌ ' + err.message);
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const browser = await launch();
|
|
37
|
+
let code = 0;
|
|
38
|
+
try {
|
|
39
|
+
// 1. 原始海报作为基准
|
|
40
|
+
const { page: p0, errors: e0 } = await open(browser, src);
|
|
41
|
+
const before = await probe(p0);
|
|
42
|
+
if (!before || !Object.keys(before).length) {
|
|
43
|
+
console.error('❌ 原始海报里没有 data-layer-id 图层,先跑 check-contract.mjs');
|
|
44
|
+
code = 1;
|
|
45
|
+
} else {
|
|
46
|
+
if (e0.length) console.warn('⚠️ 原始海报有报错:', e0.join('; '));
|
|
47
|
+
|
|
48
|
+
// 2. 挂上编辑器跑固化,取导出结果
|
|
49
|
+
const { page: p1, errors: e1 } = await open(browser, wired.file, { waitEditor: true });
|
|
50
|
+
const baked = await p1.evaluate(() => window.__layerEditor.fullHTML());
|
|
51
|
+
if (e1.length) console.warn('⚠️ 固化过程有报错:', e1.join('; '));
|
|
52
|
+
|
|
53
|
+
// 3. 先写到临时位置验证,通过了才落到最终路径
|
|
54
|
+
const probeFile = join(dir, '_hf_bake_out.html');
|
|
55
|
+
writeFileSync(probeFile, baked);
|
|
56
|
+
const { page: p2, errors: e2 } = await open(browser, probeFile);
|
|
57
|
+
const after = await probe(p2);
|
|
58
|
+
const d = diff(before, after, 1);
|
|
59
|
+
try { unlinkSync(probeFile); } catch {}
|
|
60
|
+
|
|
61
|
+
console.log(`\n固化 · ${basename(src)}\n`);
|
|
62
|
+
console.log(' 图层'.padEnd(24) + '原始 left,top'.padEnd(20) + '固化后 left,top'.padEnd(20) + '偏差');
|
|
63
|
+
for (const r of d.rows) {
|
|
64
|
+
if (r.missing) { console.log(` ${r.id.padEnd(23)}缺失`); continue; }
|
|
65
|
+
console.log(` ${r.id.padEnd(23)}${`${r.a.left}, ${r.a.top}`.padEnd(20)}${`${r.b.left}, ${r.b.top}`.padEnd(20)}${r.d}${r.fail ? ' ❌' : ''}`);
|
|
66
|
+
}
|
|
67
|
+
console.log(`\n 最大偏差 ${d.worst}px 图层 ${d.rows.length} 个 产物 ${(baked.length / 1024).toFixed(1)}KB`);
|
|
68
|
+
|
|
69
|
+
const clean = !/hf-|layer-editor/.test(baked);
|
|
70
|
+
if (!clean) console.log(' ⚠️ 产物中检测到编辑器残留');
|
|
71
|
+
if (e2.length) console.log(' ⚠️ 产物加载有报错:', e2.join('; '));
|
|
72
|
+
|
|
73
|
+
if (d.ok && clean) {
|
|
74
|
+
writeFileSync(out, baked);
|
|
75
|
+
console.log(`\n✅ 视觉零偏差,已写入 ${out}\n`);
|
|
76
|
+
} else {
|
|
77
|
+
console.log('\n❌ 未通过验收,产物已丢弃。');
|
|
78
|
+
console.log(' 偏差不为 0 通常意味着:契约未满足(先跑 check-contract.mjs),');
|
|
79
|
+
console.log(' 或存在固化规则未覆盖的布局(float / sticky / 伪元素撑高 / writing-mode)。\n');
|
|
80
|
+
code = 1;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
} finally {
|
|
84
|
+
wired.cleanup();
|
|
85
|
+
await browser.close();
|
|
86
|
+
}
|
|
87
|
+
process.exit(code);
|