@litfamily/lithermes 1.0.8 → 1.0.9
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/README.md +299 -13
- package/README_Ko-KR.md +300 -14
- package/assets/lithermes-plugin/README.md +17 -6
- package/assets/lithermes-plugin/__init__.py +96 -21
- package/assets/lithermes-plugin/core.py +15 -6
- package/assets/lithermes-plugin/core_commands.py +140 -28
- package/assets/lithermes-plugin/core_contexts.py +88 -15
- package/assets/lithermes-plugin/core_contract.py +118 -9
- package/assets/lithermes-plugin/core_routing.py +197 -8
- package/assets/lithermes-plugin/deliverable_hedge_guard.py +378 -357
- package/assets/lithermes-plugin/diagnostics.py +53 -2
- package/assets/lithermes-plugin/humanizer_detector.py +348 -0
- package/assets/lithermes-plugin/humanizer_ko_metrics.py +108 -0
- package/assets/lithermes-plugin/humanizer_office.py +18 -0
- package/assets/lithermes-plugin/lit_mark.py +1 -1
- package/assets/lithermes-plugin/motion_receipts.py +80 -0
- package/assets/lithermes-plugin/payload-version.json +2240 -64
- package/assets/lithermes-plugin/plugin.yaml +1 -1
- package/assets/lithermes-plugin/rules/bundled-rules/lit-humanizer.md +14 -0
- package/assets/lithermes-plugin/skills/autoconference/assets/report_template.md +2 -1
- package/assets/lithermes-plugin/skills/autoconference/modes/ship/SKILL.md +11 -8
- package/assets/lithermes-plugin/skills/autoresearch/modes/ship/type-checklists.md +2 -2
- package/assets/lithermes-plugin/skills/browser-drive/ORIGIN.json +17 -0
- package/assets/lithermes-plugin/skills/browser-drive/SKILL.md +41 -16
- package/assets/lithermes-plugin/skills/browser-drive/scripts/capability_probe.py +122 -10
- package/assets/lithermes-plugin/skills/frontend-ui-ux/SKILL.md +45 -13
- package/assets/lithermes-plugin/skills/frontend-ui-ux/examples/phase-3-readme-ab/README.md +51 -0
- package/assets/lithermes-plugin/skills/frontend-ui-ux/references/README.md +44 -0
- package/assets/lithermes-plugin/skills/frontend-ui-ux/references/adaptive-layout.md +34 -62
- package/assets/lithermes-plugin/skills/frontend-ui-ux/references/brand-and-imagery.md +22 -70
- package/assets/lithermes-plugin/skills/frontend-ui-ux/references/complete-contract.md +18 -4
- package/assets/lithermes-plugin/skills/frontend-ui-ux/references/composition.md +27 -78
- package/assets/lithermes-plugin/skills/frontend-ui-ux/references/craft-floor.md +74 -0
- package/assets/lithermes-plugin/skills/frontend-ui-ux/references/creative-directions.md +25 -69
- package/assets/lithermes-plugin/skills/frontend-ui-ux/references/evidence-review.md +18 -97
- package/assets/lithermes-plugin/skills/frontend-ui-ux/references/implementation-platforms.md +23 -83
- package/assets/lithermes-plugin/skills/frontend-ui-ux/references/inclusive-interface.md +22 -70
- package/assets/lithermes-plugin/skills/frontend-ui-ux/references/interaction-motion.md +34 -68
- package/assets/lithermes-plugin/skills/frontend-ui-ux/references/motion-guide.md +62 -0
- package/assets/lithermes-plugin/skills/frontend-ui-ux/references/operating-lanes.md +14 -78
- package/assets/lithermes-plugin/skills/frontend-ui-ux/references/performance-delivery.md +22 -71
- package/assets/lithermes-plugin/skills/frontend-ui-ux/references/product-direction.md +17 -70
- package/assets/lithermes-plugin/skills/frontend-ui-ux/references/production.md +19 -7
- package/assets/lithermes-plugin/skills/frontend-ui-ux/references/redesign-playbook.md +23 -76
- package/assets/lithermes-plugin/skills/frontend-ui-ux/references/slop-register.md +69 -0
- package/assets/lithermes-plugin/skills/frontend-ui-ux/references/system-foundations.md +22 -67
- package/assets/lithermes-plugin/skills/frontend-ui-ux/references/visual-language.md +16 -72
- package/assets/lithermes-plugin/skills/frontend-ui-ux/references/visual-reconstruction.md +16 -81
- package/assets/lithermes-plugin/skills/frontend-ui-ux/resources/THIRD-PARTY-NOTICE.txt +15 -0
- package/assets/lithermes-plugin/skills/frontend-ui-ux/scripts/probe-page.js +311 -0
- package/assets/lithermes-plugin/skills/frontend-ui-ux/scripts/probe-rules.json +46 -0
- package/assets/lithermes-plugin/skills/frontend-ui-ux/scripts/probe.mjs +231 -0
- package/assets/lithermes-plugin/skills/lit-comprehend/SKILL.md +36 -25
- package/assets/lithermes-plugin/skills/lit-comprehend/references/artifact-template.md +45 -87
- package/assets/lithermes-plugin/skills/lit-comprehend/scripts/verify-explainer.py +3 -27
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/NOTICE +33 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/SKILL.md +308 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-architecture-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-architecture-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-architecture-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-bar-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-bar-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-bar-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-beeswarm-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-beeswarm-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-beeswarm-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-bubble-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-bubble-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-bubble-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-bump-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-bump-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-bump-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-data-flow-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-data-flow-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-data-flow-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-datalake-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-datalake-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-datalake-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-db-schema-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-db-schema-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-db-schema-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-dependency-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-dependency-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-dependency-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-deployment-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-deployment-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-deployment-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-dp-integration-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-dp-integration-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-dp-integration-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-dp-security-matrix-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-dp-security-matrix-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-dp-security-matrix-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-er-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-er-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-er-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-fishbone-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-fishbone-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-fishbone-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-flowchart-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-flowchart-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-flowchart-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-gantt-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-gantt-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-gantt-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-heatmap-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-heatmap-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-heatmap-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-high-level-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-high-level-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-high-level-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-high-level-vertical-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-high-level-vertical-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-high-level-vertical-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-import-drawio-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-import-drawio-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-import-drawio-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-import-excalidraw-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-import-excalidraw-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-import-excalidraw-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-import-mermaid-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-import-mermaid-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-import-mermaid-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-it-state-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-it-state-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-it-state-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-journey-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-journey-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-journey-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-kanban-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-kanban-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-kanban-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-layers-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-layers-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-layers-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-line-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-line-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-line-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-loop-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-loop-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-loop-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-loop-terminal-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-loop-terminal-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-loop-terminal-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-marimekko-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-marimekko-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-marimekko-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-medallion-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-medallion-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-medallion-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-nested-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-nested-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-nested-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-org-chart-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-org-chart-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-org-chart-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-paved-road-animated-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-paved-road-animated-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-paved-road-animated-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-polar-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-polar-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-polar-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-policy-trace-animated-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-policy-trace-animated-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-policy-trace-animated-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-process-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-process-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-process-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-pyramid-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-pyramid-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-pyramid-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-quadrant-consultant-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-quadrant-consultant-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-quadrant-consultant-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-quadrant-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-quadrant-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-quadrant-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-queue-animated-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-queue-animated-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-queue-animated-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-radar-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-radar-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-radar-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-ridgeline-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-ridgeline-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-ridgeline-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-sankey-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-sankey-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-sankey-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-scatter-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-scatter-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-scatter-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-sequence-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-sequence-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-sequence-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-sequence-oauth-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-sequence-oauth-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-sequence-oauth-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-slopegraph-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-slopegraph-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-slopegraph-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-state-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-state-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-state-lifecycle-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-state-lifecycle-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-state-lifecycle-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-state-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-story-map-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-story-map-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-story-map-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-streamgraph-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-streamgraph-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-streamgraph-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-swimlane-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-swimlane-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-swimlane-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-timeline-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-timeline-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-timeline-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-tree-block-decomposition-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-tree-block-decomposition-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-tree-block-decomposition-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-tree-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-tree-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-tree-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-treemap-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-treemap-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-treemap-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-uml-class-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-uml-class-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-uml-class-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-venn-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-venn-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-venn-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-wardley-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-wardley-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-wardley-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-waterfall-dark.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-waterfall-full.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/examples/type-waterfall-light.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/fonts/OFL.txt +94 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/fonts/PretendardVariable.woff2 +0 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/fonts/provenance.json +22 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/icons.html +231 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/index.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/licenses/devicon-MIT.txt +20 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/licenses/diagram-design-MIT.txt +21 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/licenses/log-z-MIT.txt +21 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/licenses/simple-icons-CC0.md +30 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/assets/licenses/tabler-MIT.txt +21 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/examples/01-service-architecture/after.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/examples/01-service-architecture/brief.md +33 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/examples/02-release-decision/after.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/examples/02-release-decision/brief.md +18 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/examples/03-data-retention/after.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/examples/03-data-retention/brief.md +19 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/examples/04-oauth-sequence/after.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/examples/04-oauth-sequence/brief.md +17 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/examples/05-review-lanes/after.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/examples/05-review-lanes/brief.md +17 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/examples/06-rollout-gates/after.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/examples/06-rollout-gates/brief.md +17 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/examples/07-deployment-boundary/after.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/examples/07-deployment-boundary/brief.md +19 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/examples/08-policy-traces/after.html +1 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/examples/08-policy-traces/brief.md +20 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/accessibility.md +37 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/export.md +29 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/import-drawio.md +21 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/import-excalidraw.md +14 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/import-mermaid.md +18 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/import-schema.md +28 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/korean-typography.md +34 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/motion.md +29 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/office-pptx-docx.md +40 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/output-spec.md +48 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/primitive-annotation.md +12 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/primitive-icons.md +21 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/primitive-sketchy.md +11 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/primitive-terminal.md +11 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/profiles.md +24 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/semantic-patterns.md +27 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/style-guide.md +67 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-architecture.md +51 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-bar.md +51 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-beeswarm.md +49 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-bubble.md +49 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-bump.md +49 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-catalog.json +1433 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-data-flow.md +51 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-datalake.md +49 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-db-schema.md +49 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-dependency.md +49 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-deployment.md +49 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-dp-integration.md +49 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-dp-security-matrix.md +49 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-er.md +49 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-fishbone.md +49 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-flowchart.md +49 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-gantt.md +49 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-heatmap.md +53 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-high-level-vertical.md +53 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-high-level.md +53 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-import-drawio.md +53 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-import-excalidraw.md +53 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-import-mermaid.md +53 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-it-state.md +54 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-journey.md +54 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-kanban.md +54 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-layers.md +54 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-line.md +54 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-loop-terminal.md +53 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-loop.md +54 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-marimekko.md +54 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-medallion.md +54 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-nested.md +59 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-org-chart.md +58 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-paved-road-animated.md +72 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-polar.md +67 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-policy-trace-animated.md +69 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-process.md +58 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-pyramid.md +59 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-quadrant-consultant.md +60 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-quadrant.md +57 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-queue-animated.md +63 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-radar.md +57 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-ridgeline.md +63 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-sankey.md +68 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-scatter.md +60 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-sequence-oauth.md +66 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-sequence.md +63 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-slopegraph.md +65 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-state-lifecycle.md +53 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-state.md +59 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-story-map.md +52 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-streamgraph.md +53 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-swimlane.md +52 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-timeline.md +52 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-tree-block-decomposition.md +57 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-tree.md +54 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-treemap.md +54 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-uml-class.md +52 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-venn.md +51 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-wardley.md +52 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/type-waterfall.md +54 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/references/verifier-guide.md +31 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/scripts/block-registry.mjs +43 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/scripts/browser-version.mjs +12 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/scripts/check-visible-text.py +12 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/scripts/diagram_brief.py +192 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/scripts/diagram_catalog.py +135 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/scripts/diagram_checks.py +123 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/scripts/diagram_cli.py +94 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/scripts/diagram_geometry.py +130 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/scripts/diagram_metrics.py +166 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/scripts/diagram_quality.py +293 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/scripts/diagram_quality_geometry.py +200 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/scripts/diagram_records.py +205 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/scripts/diagram_sequence.py +55 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/scripts/doctor.mjs +24 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/scripts/drawio_extract.py +209 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/scripts/drawio_source.py +188 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/scripts/excalidraw_extract.py +233 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/scripts/excalidraw_support.py +64 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/scripts/export.mjs +125 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/scripts/mermaid_extract.py +240 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/scripts/mermaid_source.py +39 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/scripts/office-safety.mjs +54 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/scripts/verify-all.py +12 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/scripts/verify-brief.py +12 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/scripts/verify-diagram.py +12 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/scripts/verify-motion.py +12 -0
- package/assets/lithermes-plugin/skills/lit-diagram-drawer/scripts/verify-type.py +12 -0
- package/assets/lithermes-plugin/skills/lit-docx/NOTICE +1 -0
- package/assets/lithermes-plugin/skills/lit-docx/SKILL.md +97 -0
- package/assets/lithermes-plugin/skills/lit-docx/references/frontmatter_schema.md +42 -0
- package/assets/lithermes-plugin/skills/lit-docx/references/journal_style_spec.md +17 -0
- package/assets/lithermes-plugin/skills/lit-docx/references/markdown_quality_checklist.md +37 -0
- package/assets/lithermes-plugin/skills/lit-docx/references/slop_phrase_list.yaml +58 -0
- package/assets/lithermes-plugin/skills/lit-docx/references/slop_rules.md +35 -0
- package/assets/lithermes-plugin/skills/lit-docx/scripts/clean_markdown.py +95 -0
- package/assets/lithermes-plugin/skills/lit-docx/scripts/convert_md_to_docx.py +1041 -0
- package/assets/lithermes-plugin/skills/lit-docx/scripts/convert_md_to_pdf.py +281 -0
- package/assets/lithermes-plugin/skills/lit-docx/scripts/convert_pdf.py +130 -0
- package/assets/lithermes-plugin/skills/lit-docx/scripts/edit_docx.py +297 -0
- package/assets/lithermes-plugin/skills/lit-docx/scripts/embed_images.py +78 -0
- package/assets/lithermes-plugin/skills/lit-docx/scripts/generate_docx_templates.py +491 -0
- package/assets/lithermes-plugin/skills/lit-docx/scripts/slop_lint.py +536 -0
- package/assets/lithermes-plugin/skills/lit-docx/scripts/visual_audit.py +41 -0
- package/assets/lithermes-plugin/skills/lit-docx/templates/docx/acs.docx +0 -0
- package/assets/lithermes-plugin/skills/lit-docx/templates/docx/elsevier.docx +0 -0
- package/assets/lithermes-plugin/skills/lit-docx/templates/docx/ieee.docx +0 -0
- package/assets/lithermes-plugin/skills/lit-docx/templates/docx/korean-generic.docx +0 -0
- package/assets/lithermes-plugin/skills/lit-docx/templates/docx/nature.docx +0 -0
- package/assets/lithermes-plugin/skills/lit-docx/templates/latex/acs/README.md +5 -0
- package/assets/lithermes-plugin/skills/lit-docx/templates/latex/acs/template.tex +37 -0
- package/assets/lithermes-plugin/skills/lit-docx/templates/latex/elsevier/README.md +5 -0
- package/assets/lithermes-plugin/skills/lit-docx/templates/latex/elsevier/template.tex +38 -0
- package/assets/lithermes-plugin/skills/lit-docx/templates/latex/ieee/README.md +5 -0
- package/assets/lithermes-plugin/skills/lit-docx/templates/latex/ieee/template.tex +37 -0
- package/assets/lithermes-plugin/skills/lit-docx/templates/latex/korean-generic/README.md +5 -0
- package/assets/lithermes-plugin/skills/lit-docx/templates/latex/korean-generic/template.tex +37 -0
- package/assets/lithermes-plugin/skills/lit-docx/templates/latex/nature/README.md +5 -0
- package/assets/lithermes-plugin/skills/lit-docx/templates/latex/nature/template.tex +37 -0
- package/assets/lithermes-plugin/skills/lit-docx/templates/registry.yaml +1366 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/NOTICE +170 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/SKILL.md +125 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/assets/report-skeleton.md +26 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/assets/slide-text-skeleton.md +30 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/examples/accessibility-note/after.md +7 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/examples/accessibility-note/before.md +7 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/examples/api-reference/after.md +9 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/examples/api-reference/before.md +15 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/examples/changelog/after.md +5 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/examples/changelog/before.md +12 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/examples/code-comments/after.md +10 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/examples/code-comments/before.md +19 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/examples/commit/after.md +5 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/examples/commit/before.md +7 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/examples/data-release/after.md +7 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/examples/data-release/before.md +9 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/examples/detector-validation/ko-metrics-golden.json +49 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/examples/detector-validation/pos-real.txt +26 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/examples/detector-validation/rule-cases.json +306 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/examples/english-essay/after.md +5 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/examples/english-essay/before.md +5 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/examples/incident-update/after.md +7 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/examples/incident-update/before.md +7 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/examples/ko-essay/after.md +7 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/examples/ko-essay/before.md +9 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/examples/ko-report/after.md +9 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/examples/ko-report/before.md +13 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/examples/ko-slide/after.md +19 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/examples/ko-slide/before.md +21 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/examples/meeting-brief/after.md +9 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/examples/meeting-brief/before.md +11 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/examples/policy-faq/after.md +9 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/examples/policy-faq/before.md +9 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/examples/pr/after.md +15 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/examples/pr/before.md +17 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/examples/project-update/after.md +7 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/examples/project-update/before.md +9 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/examples/readme/after.md +12 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/examples/readme/before.md +14 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/examples/report/after.md +13 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/examples/report/before.md +11 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/examples/research-abstract/after.md +5 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/examples/research-abstract/before.md +5 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/examples/slides/after.md +19 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/examples/slides/before.md +19 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/examples/troubleshooting/after.md +11 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/examples/troubleshooting/before.md +11 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/references/README.md +16 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/references/always-on-rule.md +9 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/references/code-patterns.md +468 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/references/deliverable-channels.md +111 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/references/en-patterns-checklist.md +43 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/references/en-patterns-content.md +243 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/references/en-patterns-structure.md +375 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/references/en-patterns.md +57 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/references/ko-metrics.md +33 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/references/ko-patterns-a-d.md +659 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/references/ko-patterns-e-j.md +387 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/references/ko-patterns.md +31 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/references/rewrite-playbook.md +54 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/references/taxonomy.md +153 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/rules.json +884 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/scripts/detect.py +17 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/scripts/extract_office_text.py +114 -0
- package/assets/lithermes-plugin/skills/lit-humanizer/scripts/ko_metrics.py +35 -0
- package/assets/lithermes-plugin/skills/lit-pptx/NOTICE +1 -0
- package/assets/lithermes-plugin/skills/lit-pptx/SKILL.md +109 -0
- package/assets/lithermes-plugin/skills/lit-pptx/agents/analyst.md +49 -0
- package/assets/lithermes-plugin/skills/lit-pptx/agents/antithesis.md +65 -0
- package/assets/lithermes-plugin/skills/lit-pptx/agents/architect.md +44 -0
- package/assets/lithermes-plugin/skills/lit-pptx/agents/critic.md +42 -0
- package/assets/lithermes-plugin/skills/lit-pptx/agents/synthesizer.md +47 -0
- package/assets/lithermes-plugin/skills/lit-pptx/agents/thesis.md +33 -0
- package/assets/lithermes-plugin/skills/lit-pptx/assets/azure/circle-lg.png +0 -0
- package/assets/lithermes-plugin/skills/lit-pptx/assets/azure/circle-md.png +0 -0
- package/assets/lithermes-plugin/skills/lit-pptx/assets/azure/circle-sm.png +0 -0
- package/assets/lithermes-plugin/skills/lit-pptx/bin/office.mjs +77 -0
- package/assets/lithermes-plugin/skills/lit-pptx/fonts/PRETENDARD-OFL.txt +94 -0
- package/assets/lithermes-plugin/skills/lit-pptx/fonts/a2z-font/A2Z-Black.otf +0 -0
- package/assets/lithermes-plugin/skills/lit-pptx/fonts/a2z-font/A2Z-Bold.otf +0 -0
- package/assets/lithermes-plugin/skills/lit-pptx/fonts/a2z-font/A2Z-ExtraBold.otf +0 -0
- package/assets/lithermes-plugin/skills/lit-pptx/fonts/a2z-font/A2Z-ExtraLight.otf +0 -0
- package/assets/lithermes-plugin/skills/lit-pptx/fonts/a2z-font/A2Z-Light.otf +0 -0
- package/assets/lithermes-plugin/skills/lit-pptx/fonts/a2z-font/A2Z-Medium.otf +0 -0
- package/assets/lithermes-plugin/skills/lit-pptx/fonts/a2z-font/A2Z-Regular.otf +0 -0
- package/assets/lithermes-plugin/skills/lit-pptx/fonts/a2z-font/A2Z-SemiBold.otf +0 -0
- package/assets/lithermes-plugin/skills/lit-pptx/fonts/a2z-font/A2Z-Thin.otf +0 -0
- package/assets/lithermes-plugin/skills/lit-pptx/fonts/a2z-font/OFL.txt +94 -0
- package/assets/lithermes-plugin/skills/lit-pptx/fonts/a2z-font/SOURCE.md +29 -0
- package/assets/lithermes-plugin/skills/lit-pptx/pretendard-font/public/static/PretendardGOV-Bold.otf +0 -0
- package/assets/lithermes-plugin/skills/lit-pptx/pretendard-font/public/static/PretendardGOV-Regular.otf +0 -0
- package/assets/lithermes-plugin/skills/lit-pptx/references/anti-slop-checklist.md +71 -0
- package/assets/lithermes-plugin/skills/lit-pptx/references/authoring-guide.md +139 -0
- package/assets/lithermes-plugin/skills/lit-pptx/references/consensus-protocol.md +125 -0
- package/assets/lithermes-plugin/skills/lit-pptx/references/data-display-cookbook.md +45 -0
- package/assets/lithermes-plugin/skills/lit-pptx/references/design-system-azure.md +58 -0
- package/assets/lithermes-plugin/skills/lit-pptx/runtime/package-lock.json +750 -0
- package/assets/lithermes-plugin/skills/lit-pptx/runtime/package.json +15 -0
- package/assets/lithermes-plugin/skills/lit-pptx/runtime/requirements.in +7 -0
- package/assets/lithermes-plugin/skills/lit-pptx/runtime/requirements.lock +391 -0
- package/assets/lithermes-plugin/skills/lit-pptx/scripts/compile-deck.js +447 -0
- package/assets/lithermes-plugin/skills/lit-pptx/scripts/craft_extras.py +215 -0
- package/assets/lithermes-plugin/skills/lit-pptx/scripts/embed_fonts.py +199 -0
- package/assets/lithermes-plugin/skills/lit-pptx/scripts/integrity.py +60 -0
- package/assets/lithermes-plugin/skills/lit-pptx/scripts/inventory.py +64 -0
- package/assets/lithermes-plugin/skills/lit-pptx/scripts/learn_template.py +433 -0
- package/assets/lithermes-plugin/skills/lit-pptx/scripts/lib/derive-palette.js +176 -0
- package/assets/lithermes-plugin/skills/lit-pptx/scripts/lib/directive-parser.js +244 -0
- package/assets/lithermes-plugin/skills/lit-pptx/scripts/lib/font-map.js +79 -0
- package/assets/lithermes-plugin/skills/lit-pptx/scripts/lib/gen-bg.js +85 -0
- package/assets/lithermes-plugin/skills/lit-pptx/scripts/lib/gen-gradient-assets.js +36 -0
- package/assets/lithermes-plugin/skills/lit-pptx/scripts/lib/layout-resolver.js +736 -0
- package/assets/lithermes-plugin/skills/lit-pptx/scripts/lib/markdown-loader.js +136 -0
- package/assets/lithermes-plugin/skills/lit-pptx/scripts/lib/render-adapter-html.js +357 -0
- package/assets/lithermes-plugin/skills/lit-pptx/scripts/lib/render-adapter-pptx.js +1864 -0
- package/assets/lithermes-plugin/skills/lit-pptx/scripts/lib/slide-ast.js +539 -0
- package/assets/lithermes-plugin/skills/lit-pptx/scripts/lib/spec-validator.js +94 -0
- package/assets/lithermes-plugin/skills/lit-pptx/scripts/lib/template-registry.js +355 -0
- package/assets/lithermes-plugin/skills/lit-pptx/scripts/qa_deck.py +791 -0
- package/assets/lithermes-plugin/skills/lit-pptx/scripts/validate_pptx.py +206 -0
- package/assets/lithermes-plugin/skills/lit-pptx/slide-formats/markdown-slide-spec-v1.md +251 -0
- package/assets/lithermes-plugin/skills/lit-pptx/slide-formats/markdown-slide-spec-v2.md +221 -0
- package/assets/lithermes-plugin/skills/lit-pptx/slide-formats/slide-ast-v1.schema.json +229 -0
- package/assets/lithermes-plugin/skills/lit-pptx/slide-formats/slide-ast-v2.schema.json +144 -0
- package/assets/lithermes-plugin/skills/lit-pptx/slide-formats/template-enrollment-contract.md +228 -0
- package/assets/lithermes-plugin/skills/lit-pptx/templates/enrolled/AZURE-A2Z/capabilities.yaml +146 -0
- package/assets/lithermes-plugin/skills/lit-pptx/templates/enrolled/AZURE-A2Z/layout-mapping.yaml +384 -0
- package/assets/lithermes-plugin/skills/lit-pptx/templates/enrolled/AZURE-A2Z/template.yaml +37 -0
- package/assets/lithermes-plugin/skills/lit-pptx/templates/enrolled/AZURE-PRO/capabilities.yaml +154 -0
- package/assets/lithermes-plugin/skills/lit-pptx/templates/enrolled/AZURE-PRO/layout-mapping.yaml +405 -0
- package/assets/lithermes-plugin/skills/lit-pptx/templates/enrolled/AZURE-PRO/template.yaml +37 -0
- package/assets/lithermes-plugin/skills/lit-pptx/templates/enrolled/BOILERPLATE-A2Z/capabilities.yaml +179 -0
- package/assets/lithermes-plugin/skills/lit-pptx/templates/enrolled/BOILERPLATE-A2Z/layout-mapping.yaml +299 -0
- package/assets/lithermes-plugin/skills/lit-pptx/templates/enrolled/BOILERPLATE-A2Z/template.yaml +45 -0
- package/assets/lithermes-plugin/skills/lit-pptx/templates/enrolled/BOILERPLATE-PRETENDARD/capabilities.yaml +181 -0
- package/assets/lithermes-plugin/skills/lit-pptx/templates/enrolled/BOILERPLATE-PRETENDARD/layout-mapping.yaml +299 -0
- package/assets/lithermes-plugin/skills/lit-pptx/templates/enrolled/BOILERPLATE-PRETENDARD/template.yaml +44 -0
- package/assets/lithermes-plugin/skills/lit-scientific-visualization/SKILL.md +2 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/SKILL.md +71 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/bin/audio.py +45 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/bin/motion.mjs +690 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/bin/runtime.mjs +299 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/NOTICE +23 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/THIRD_PARTY_NOTICES +55 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/browser.mjs +169 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/completion.mjs +52 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/constants.mjs +162 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/director.mjs +33 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/encode.mjs +191 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/flash.mjs +163 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/frame.mjs +428 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/gate.mjs +483 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/look.mjs +223 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/page.js +622 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/presets.mjs +170 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/scenes.mjs +242 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/sound.mjs +382 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/stage-gate.mjs +97 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/stage-init.js +186 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/stage-kit.js +389 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/stage-qa.mjs +358 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/stage-worker.mjs +33 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/stage.mjs +691 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/stills.mjs +71 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/stroke.mjs +231 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/timeline.mjs +177 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/treatment.mjs +244 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/type.mjs +183 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/engine/util.mjs +152 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/references/craft-loop.md +175 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/references/engine-contract.md +166 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/references/runtime.md +122 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/references/stage.md +261 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/references/style-bibles.md +122 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/references/treatment.md +164 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/references/type-craft.md +92 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/runtime/fonts.json +154 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/runtime/licenses/CREDITS +20 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/runtime/licenses/EMS-OFL.txt +91 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/runtime/package-lock.json +88 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/runtime/package.json +12 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/runtime/requirements.in +1 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/runtime/requirements.lock +727 -0
- package/assets/lithermes-plugin/skills/lit-typographic-motion/runtime/word-timing.json +9 -0
- package/assets/lithermes-plugin/skills/litresearch/SKILL.md +19 -18
- package/assets/lithermes-plugin/skills/litwork/SKILL.md +28 -0
- package/assets/lithermes-plugin/skills/visual-qa/references/complete-contract.md +3 -3
- package/package.json +1 -1
- package/readme-assets/ab-simple/s11-ui-baseline-desktop.webp +0 -0
- package/readme-assets/ab-simple/s11-ui-lithermes-desktop.webp +0 -0
- package/readme-assets/ab-simple/s3-ui-baseline-desktop.webp +0 -0
- package/readme-assets/ab-simple/s3-ui-lithermes-desktop.webp +0 -0
- package/readme-assets/ab-simple/s4-ui-baseline-desktop.webp +0 -0
- package/readme-assets/ab-simple/s4-ui-lithermes-desktop.webp +0 -0
- package/readme-assets/ab-simple/s5-office-baseline-slides.webp +0 -0
- package/readme-assets/ab-simple/s5-office-lithermes-slides.webp +0 -0
- package/readme-assets/ab-simple/s7-lithermes-diagram.webp +0 -0
- package/readme-assets/ab-simple/s8-office-baseline-slides.webp +0 -0
- package/readme-assets/ab-simple/s8-office-lithermes-slides.webp +0 -0
- package/readme-assets/ab-simple/s9-office-lithermes-pages.webp +0 -0
- package/readme-assets/badge-version.svg +1 -1
- package/readme-assets/cover-motion-still.webp +0 -0
- package/readme-assets/cover-motion.webp +0 -0
- package/readme-assets/skills/autoconference.webp +0 -0
- package/readme-assets/skills/autoresearch.webp +0 -0
- package/readme-assets/skills/browser-drive.webp +0 -0
- package/readme-assets/skills/comment-checker.webp +0 -0
- package/readme-assets/skills/debugging.webp +0 -0
- package/readme-assets/skills/deep-interview.webp +0 -0
- package/readme-assets/skills/frontend-ui-ux.webp +0 -0
- package/readme-assets/skills/lit-burnoff-file.webp +0 -0
- package/readme-assets/skills/lit-burnoff.webp +0 -0
- package/readme-assets/skills/lit-code.webp +0 -0
- package/readme-assets/skills/lit-commit.webp +0 -0
- package/readme-assets/skills/lit-comprehend.webp +0 -0
- package/readme-assets/skills/lit-crucible.webp +0 -0
- package/readme-assets/skills/lit-diagram-drawer.webp +0 -0
- package/readme-assets/skills/lit-docx.webp +0 -0
- package/readme-assets/skills/lit-handoff.webp +0 -0
- package/readme-assets/skills/lit-humanizer.webp +0 -0
- package/readme-assets/skills/lit-init.webp +0 -0
- package/readme-assets/skills/lit-plan.webp +0 -0
- package/readme-assets/skills/lit-pptx.webp +0 -0
- package/readme-assets/skills/lit-recap.webp +0 -0
- package/readme-assets/skills/lit-scientific-visualization.webp +0 -0
- package/readme-assets/skills/lit-typographic-motion.webp +0 -0
- package/readme-assets/skills/litgoal.webp +0 -0
- package/readme-assets/skills/litresearch.webp +0 -0
- package/readme-assets/skills/litwork.webp +0 -0
- package/readme-assets/skills/lsp-setup.webp +0 -0
- package/readme-assets/skills/lsp.webp +0 -0
- package/readme-assets/skills/readme-studio.webp +0 -0
- package/readme-assets/skills/refactor.webp +0 -0
- package/readme-assets/skills/review-work.webp +0 -0
- package/readme-assets/skills/rules.webp +0 -0
- package/readme-assets/skills/start-work.webp +0 -0
- package/readme-assets/skills/structural-search.webp +0 -0
- package/readme-assets/skills/visual-qa.webp +0 -0
- package/readme-assets/skills/wikify.webp +0 -0
- package/src/cli.js +40 -1
- package/src/lib/check.js +21 -0
- package/src/lib/install.js +262 -7
- package/src/lib/skillPayload.js +3 -3
- package/assets/lithermes-plugin/skills/lit-korean/SKILL.md +0 -237
- package/assets/lithermes-plugin/skills/lit-korean/references/quick-rules.md +0 -24
- package/assets/lithermes-plugin/skills/lit-korean/references/safety-checklist.md +0 -23
- package/readme-assets/cover.webp +0 -0
|
@@ -0,0 +1,690 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// lit-typographic-motion render CLI for LitHermes. The mode set and flags
|
|
3
|
+
// follow pdoom's scripts/render.ts (stills, sheet, perf, video; --samples,
|
|
4
|
+
// --shutter, --scale), MIT, see NOTICE; `run` is the one end-to-end command
|
|
5
|
+
// and `gate`/`complete` re-check an existing output directory. The render only
|
|
6
|
+
// reads the pre-warmed cache and writes inside --out (MO-A-43).
|
|
7
|
+
import { createHash } from 'node:crypto';
|
|
8
|
+
import { spawnSync } from 'node:child_process';
|
|
9
|
+
import { existsSync, mkdirSync, readFileSync, realpathSync, rmSync, statSync, writeFileSync } from 'node:fs';
|
|
10
|
+
import { dirname, isAbsolute, join, resolve } from 'node:path';
|
|
11
|
+
import { fileURLToPath } from 'node:url';
|
|
12
|
+
import { CREDIT_LINE, ENGINE_CREDIT, EXIT, FRAME, PERF, SAMPLING } from '../engine/constants.mjs';
|
|
13
|
+
import { PRESETS, pickPreset, planPasses, terminalSignal } from '../engine/presets.mjs';
|
|
14
|
+
import { buildTimeline, normalizeBrief, shotsOf } from '../engine/timeline.mjs';
|
|
15
|
+
import { FONT_FILES, FrameComposer, resolveFontId } from '../engine/frame.mjs';
|
|
16
|
+
import { openTypeAdapter, scriptRuns } from '../engine/type.mjs';
|
|
17
|
+
import { parseStrokeFont, STROKE_FONTS } from '../engine/stroke.mjs';
|
|
18
|
+
import { FlashDetector } from '../engine/flash.mjs';
|
|
19
|
+
import { measureContrast, preflightGate, promoteExports, renderReport, runGate } from '../engine/gate.mjs';
|
|
20
|
+
import { areaResize, contactSheet, encodePreview, ffprobe, hasFfmpeg, pngDecode, pngEncode, startMaster } from '../engine/encode.mjs';
|
|
21
|
+
import { openRenderer } from '../engine/browser.mjs';
|
|
22
|
+
import { WARM, audioState, findCache, fontFile, fontState, hangulPath, runtimeRequire, skillRoot, wordTimingReady } from './runtime.mjs';
|
|
23
|
+
import { loadTreatment } from '../engine/treatment.mjs';
|
|
24
|
+
import { recordFirstTreatment } from '../engine/director.mjs';
|
|
25
|
+
import { stageCommand, stageRegate } from '../engine/stage.mjs';
|
|
26
|
+
import { completeCommand, lookCommand } from '../engine/look.mjs';
|
|
27
|
+
import { stampStills, stillsPlan, writeStillsSet } from '../engine/stills.mjs';
|
|
28
|
+
import { produceSound, soundCommand, soundGate } from '../engine/sound.mjs';
|
|
29
|
+
import { viewedFiles } from '../engine/director.mjs';
|
|
30
|
+
|
|
31
|
+
const USAGE = `LitHermes lit-typographic-motion
|
|
32
|
+
usage: node motion.mjs <subcommand> --out DIR [options] (write DIR/treatment.json first)
|
|
33
|
+
stage --out DIR [--stills-only] [--round 1-3] stage path: capture DIR/stage/index.html frame by frame; stills, film, sound, gate
|
|
34
|
+
run --out DIR [--brief FILE] [--round 1-3] [--stills-only] type path: the WebGL2 type engine; stills, cut sheet, film, preview, poster, gate
|
|
35
|
+
sound --out DIR build the generated sound bed and sound-cues.json from the treatment
|
|
36
|
+
look --out DIR --round 1-3 --answers FILE record one look round against the latest stills set
|
|
37
|
+
gate --out DIR rerun the gate on an existing output dir
|
|
38
|
+
complete --out DIR exit 0 only when this film is done (treatment, gate, look rounds)
|
|
39
|
+
type-path tools: stills, sheet, video, perf (--brief FILE --out DIR)
|
|
40
|
+
options: --scale 1-4 --word-timing --force-software
|
|
41
|
+
exit: 0 ok, 10 no Chrome, 11 no WebGL2, 12 no ffmpeg for video, 13 QA gate failed, 14 not pre-warmed, 15 font missing or corrupt,
|
|
42
|
+
16 treatment invalid, 17 stage contract, 18 stage not deterministic, 19 stage network request, 20 sound invalid
|
|
43
|
+
${CREDIT_LINE}`;
|
|
44
|
+
|
|
45
|
+
const sha = (data) => createHash('sha256').update(data).digest('hex');
|
|
46
|
+
const fail = (code, message) => Object.assign(new Error(message), { exitCode: code });
|
|
47
|
+
const writeJson = (file, value) => writeFileSync(file, `${JSON.stringify(value, null, 2)}\n`);
|
|
48
|
+
const NOTICE_SHA = '6734178ad953e5f40585d000c13e4803e670d9e8982b7f6ef0395d47a9eedf30';
|
|
49
|
+
|
|
50
|
+
function parseArgs(argv) {
|
|
51
|
+
const flags = { _: [] };
|
|
52
|
+
for (let i = 0; i < argv.length; i++) {
|
|
53
|
+
const arg = argv[i];
|
|
54
|
+
if (!arg.startsWith('--')) { flags._.push(arg); continue; }
|
|
55
|
+
const key = arg.slice(2);
|
|
56
|
+
if (['stills-only', 'cuts', 'word-timing', 'force-software', 'help', 'no-rerender', 'aids', 'detach'].includes(key)) flags[key] = true;
|
|
57
|
+
else if (key === 'viewed') flags.viewed = String(argv[++i] || '').split(',').map((v) => Number(v.replace(/^f/, ''))).filter(Number.isInteger);
|
|
58
|
+
else flags[key] = argv[++i];
|
|
59
|
+
}
|
|
60
|
+
return flags;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
class FontSet {
|
|
64
|
+
constructor(opentype, cache) { this.opentype = opentype; this.cache = cache; this.fonts = new Map(); }
|
|
65
|
+
path(id) {
|
|
66
|
+
const file = FONT_FILES[id];
|
|
67
|
+
return file.startsWith('lit-pptx:') ? hangulPath(file.slice(9)) : fontFile(this.cache, file);
|
|
68
|
+
}
|
|
69
|
+
get(id) {
|
|
70
|
+
if (!this.fonts.has(id)) {
|
|
71
|
+
const bytes = readFileSync(this.path(id));
|
|
72
|
+
const parsed = this.opentype.parse(bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength));
|
|
73
|
+
this.fonts.set(id, openTypeAdapter(parsed, id, FONT_FILES[id].replace(/^lit-pptx:/, '').split('/').pop()));
|
|
74
|
+
}
|
|
75
|
+
return this.fonts.get(id);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
class StrokeSet {
|
|
80
|
+
constructor(cache) { this.cache = cache; this.fonts = new Map(); }
|
|
81
|
+
get(name) {
|
|
82
|
+
if (!this.fonts.has(name)) {
|
|
83
|
+
const file = STROKE_FONTS[name];
|
|
84
|
+
const font = parseStrokeFont(readFileSync(fontFile(this.cache, `fonts/stroke/${file}`), 'utf8'), name);
|
|
85
|
+
font.file = file;
|
|
86
|
+
this.fonts.set(name, font);
|
|
87
|
+
}
|
|
88
|
+
return this.fonts.get(name);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const FILTER_ORDER = { 'swiss-signal': ['dither'], terminalcore: ['crt', 'dither', 'glitch'], tidal: ['glitch'] };
|
|
93
|
+
|
|
94
|
+
class Session {
|
|
95
|
+
constructor(flags, mode) {
|
|
96
|
+
this.flags = flags;
|
|
97
|
+
this.mode = mode;
|
|
98
|
+
this.out = resolve(flags.out || 'motion-output');
|
|
99
|
+
this.round = Number(flags.round || 1);
|
|
100
|
+
this.scale = Math.max(1, Math.min(FRAME.maxScale, Math.round(Number(flags.scale || 1))));
|
|
101
|
+
this.framesViewed = flags.viewed || [];
|
|
102
|
+
this.records = [];
|
|
103
|
+
this.previewRecords = [];
|
|
104
|
+
this.contrast = [];
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
prepare() {
|
|
108
|
+
if (!this.flags.brief) throw fail(2, 'missing --brief FILE (a JSON brief with "text": ["line", ...])');
|
|
109
|
+
this.briefPath = resolve(this.flags.brief);
|
|
110
|
+
if (!existsSync(this.briefPath)) throw fail(2, `brief not found: ${this.briefPath}`);
|
|
111
|
+
const rawBytes = readFileSync(this.briefPath);
|
|
112
|
+
let raw;
|
|
113
|
+
try { raw = JSON.parse(rawBytes.toString('utf8')); } catch (error) { throw fail(2, `brief is not valid JSON: ${error.message}`); }
|
|
114
|
+
try { this.brief = normalizeBrief(raw); } catch (error) { throw fail(2, error.message); }
|
|
115
|
+
this.briefSha = sha(rawBytes);
|
|
116
|
+
if (![1, 2, 3].includes(this.round)) throw fail(2, '--round must be 1, 2 or 3');
|
|
117
|
+
if ((this.flags['word-timing'] || this.brief.wordTiming) && !wordTimingReady()) {
|
|
118
|
+
throw fail(EXIT.BLOCKED_DEPS_NOT_PREWARMED, `BLOCKED_DEPS_NOT_PREWARMED: word-timing models are not installed; run \`${WARM} --word-timing\` outside this session (Tier 3 is fail-closed until its Korean alignment model is pinned)`);
|
|
119
|
+
}
|
|
120
|
+
this.require = runtimeRequire();
|
|
121
|
+
this.cache = findCache();
|
|
122
|
+
const fonts = fontState();
|
|
123
|
+
if (!fonts.ok) {
|
|
124
|
+
throw fail(EXIT.BLOCKED_FONT_FETCH, `BLOCKED_FONT_FETCH: ${[...fonts.missing.map((f) => `missing ${f}`), ...fonts.mismatched.map((f) => `sha256 mismatch ${f}`)].join('; ')}; run \`${WARM}\` outside this session`);
|
|
125
|
+
}
|
|
126
|
+
this.PNG = this.require('pngjs').PNG;
|
|
127
|
+
this.fonts = new FontSet(this.require('opentype.js'), this.cache);
|
|
128
|
+
this.strokes = new StrokeSet(this.cache);
|
|
129
|
+
if (this.treatment && this.brief.durationSec == null) this.brief.durationSec = this.treatment.durationSec;
|
|
130
|
+
this.choice = pickPreset(this.brief, { request: this.treatment?.request || '' });
|
|
131
|
+
this.presetId = this.choice.id;
|
|
132
|
+
this.preset = PRESETS[this.presetId];
|
|
133
|
+
this.signal = this.presetId === 'terminalcore' ? terminalSignal(this.brief) : this.preset.palette.signal;
|
|
134
|
+
this.warnings = [];
|
|
135
|
+
this.audioGrid = null;
|
|
136
|
+
if (this.brief.audio) this.audioGrid = this.analyzeAudio();
|
|
137
|
+
const built = buildTimeline(this.brief, { presetId: this.presetId, fps: FRAME.fps, audioGrid: this.audioGrid });
|
|
138
|
+
this.timeline = built.timeline;
|
|
139
|
+
this.durationSec = built.durationSec;
|
|
140
|
+
this.warnings.push(...built.warnings);
|
|
141
|
+
this.totalFrames = Math.round(this.durationSec * FRAME.fps);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
analyzeAudio() {
|
|
145
|
+
const audioPath = isAbsolute(this.brief.audio) ? this.brief.audio : resolve(dirname(this.briefPath), this.brief.audio);
|
|
146
|
+
const state = audioState();
|
|
147
|
+
if (state.state !== 'ready') {
|
|
148
|
+
this.warnings.push(state.state === 'absent'
|
|
149
|
+
? `audio analysis not prewarmed: run ${WARM} --audio (Tier 1 text timing used)`
|
|
150
|
+
: `audio venv does not match its pins (${state.detail}); run ${WARM} --audio (Tier 1 text timing used)`);
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
mkdirSync(this.out, { recursive: true });
|
|
154
|
+
const grid = join(this.out, 'audio-grid.json');
|
|
155
|
+
const result = spawnSync(state.python, [join(skillRoot, 'bin', 'audio.py'), audioPath, grid], { encoding: 'utf8', timeout: 300000 });
|
|
156
|
+
if (result.status !== 0 || !existsSync(grid)) {
|
|
157
|
+
this.warnings.push(`audio analysis failed (${(result.stderr || result.error?.message || '').trim().split('\n').at(-1)}); Tier 1 text timing used`);
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
const parsed = JSON.parse(readFileSync(grid, 'utf8'));
|
|
161
|
+
if (!parsed.beats?.length) { this.warnings.push('audio analysis found no beats; Tier 1 text timing used'); return null; }
|
|
162
|
+
this.audioPath = audioPath;
|
|
163
|
+
return parsed;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
baseManifest() {
|
|
167
|
+
return {
|
|
168
|
+
schemaVersion: 1, engineCredit: ENGINE_CREDIT, presetId: this.presetId, seed: this.brief.seed, fps: FRAME.fps,
|
|
169
|
+
resolution: [FRAME.width * this.scale, FRAME.height * this.scale], scale: this.scale,
|
|
170
|
+
samples: this.samples ?? SAMPLING.masterSamples, shutter: SAMPLING.masterShutter,
|
|
171
|
+
renderer: this.renderer?.renderer || '', softwareRenderer: Boolean(this.renderer?.software), chromeFlags: this.renderer?.flags || [],
|
|
172
|
+
previewEncoder: this.previewEncoder || '', audioTier: this.audioGrid ? 'librosa-beat-grid' : 'text-reading-time',
|
|
173
|
+
...(this.audioGrid ? { beatGrid: this.audioGrid.beats } : { bpm: this.brief.bpm }),
|
|
174
|
+
durationSec: this.durationSec, generatedAt: new Date().toISOString(),
|
|
175
|
+
passRanges: this.plan?.passRanges || [], timeline: this.timeline, warnings: this.warnings,
|
|
176
|
+
lithermes: {
|
|
177
|
+
mode: this.mode, round: this.round, presetReason: this.choice.reason, brief: { path: this.briefPath, sha256: this.briefSha },
|
|
178
|
+
signal: this.signal, events: this.plan?.events || [], shots: this.shotStates || [], egress: this.renderer?.egress, listenError: this.renderer?.listenError,
|
|
179
|
+
chromeSockets: this.renderer?.sockets, previewFps: this.previewFps, previewWidth: this.previewWidth, previewAttempts: this.previewAttempts,
|
|
180
|
+
stills: this.stillFrames, cuts: this.cutFrames, contrastFrames: this.contrastFrames, determinism: this.determinism, perf: this.perf, sound: this.sound?.summary,
|
|
181
|
+
reducedInk: this.reducedInk, posterInk: this.posterInk, accent: this.accent, cache: this.cache, framesViewed: this.framesViewed,
|
|
182
|
+
},
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
composer() {
|
|
187
|
+
const shots = shotsOf(this.timeline);
|
|
188
|
+
let accent = null;
|
|
189
|
+
const host = this.brief.accent === false ? null : shots[typeof this.brief.accent === 'number' ? this.brief.accent : 0];
|
|
190
|
+
if (host && this.preset.palette.accent) {
|
|
191
|
+
const beat = 60 / this.brief.bpm;
|
|
192
|
+
const from = (this.preset.motion.entranceSec ?? 0.18) + 0.1;
|
|
193
|
+
const capSec = Math.floor(0.1 * this.totalFrames) / FRAME.fps;
|
|
194
|
+
const to = Math.min(from + 2 * beat, host.holdSec - 1 / FRAME.fps, from + capSec);
|
|
195
|
+
if (to > from) accent = { shotId: host.id, from: Math.round(from * FRAME.fps) / FRAME.fps, to: Math.round(to * FRAME.fps) / FRAME.fps };
|
|
196
|
+
}
|
|
197
|
+
this.accent = accent;
|
|
198
|
+
return new FrameComposer({
|
|
199
|
+
fonts: this.fonts, strokeFonts: this.strokes, presetId: this.presetId, signal: this.signal, timeline: this.timeline,
|
|
200
|
+
plan: this.plan, fps: FRAME.fps, durationSec: this.durationSec, runSeed: this.brief.seed, software: Boolean(this.renderer?.software),
|
|
201
|
+
brief: this.brief, accent,
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// MO-D-04 on exactly the elements that will be drawn, before any frame.
|
|
206
|
+
preflight() {
|
|
207
|
+
this.plan = planPasses({ presetId: this.presetId, timeline: this.timeline, runSeed: this.brief.seed, fps: FRAME.fps, software: false, brief: this.brief });
|
|
208
|
+
const composer = this.composer();
|
|
209
|
+
const missing = new Map();
|
|
210
|
+
const check = (text, voice, weight, widthStep) => {
|
|
211
|
+
for (const run of scriptRuns(text)) {
|
|
212
|
+
const font = this.fonts.get(resolveFontId(this.presetId, voice, run.script, weight, widthStep));
|
|
213
|
+
for (const ch of run.text) if (ch.trim() && !font.has(ch)) missing.set(`${ch}|${font.file}`, { ch, font: font.file });
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
shotsOf(this.timeline).forEach((_, i) => {
|
|
217
|
+
for (const reduced of [false, true]) {
|
|
218
|
+
const { display } = composer.sceneAt(0, { still: true, reduced, shotIndex: i });
|
|
219
|
+
for (const el of display.texts) check(el.text, el.voice, el.weight, el.widthStep);
|
|
220
|
+
for (const st of display.strokes || []) {
|
|
221
|
+
const font = this.strokes.get(st.font);
|
|
222
|
+
for (const ch of st.text) if (ch.trim() && !font.glyphs.has(ch)) missing.set(`${ch}|${font.file}`, { ch, font: font.file });
|
|
223
|
+
}
|
|
224
|
+
if (display.terminal) for (const text of [display.terminal.title.toUpperCase(), display.terminal.status]) check(text, 'label', 400, 100);
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
this.missingGlyphs = [...missing.values()];
|
|
228
|
+
const manifest = this.baseManifest();
|
|
229
|
+
const gate = preflightGate(manifest, { missingGlyphs: this.missingGlyphs });
|
|
230
|
+
if (gate.failed.length) {
|
|
231
|
+
mkdirSync(this.out, { recursive: true });
|
|
232
|
+
writeJson(join(this.out, 'manifest.json'), manifest);
|
|
233
|
+
writeFileSync(join(this.out, 'gate-report.txt'), renderReport(manifest, gate, { preflight: true }));
|
|
234
|
+
throw Object.assign(fail(EXIT.GATE_FAIL_QA, `GATE_FAIL_QA (pre-flight, nothing rendered): ${gate.rules.filter((r) => r.status === 'FAIL').map((r) => `${r.id} ${r.detail}`).join('; ')}`), { failed: gate.failed });
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
async openChrome() {
|
|
239
|
+
mkdirSync(join(this.out, '.run'), { recursive: true });
|
|
240
|
+
this.renderer = await openRenderer({
|
|
241
|
+
runtime: this.require, pageScript: join(skillRoot, 'engine', 'page.js'), profileRoot: join(this.out, '.run', `c${process.pid % 100000}`),
|
|
242
|
+
scale: this.scale, forceSoftware: Boolean(this.flags['force-software']),
|
|
243
|
+
});
|
|
244
|
+
const software = this.renderer.software;
|
|
245
|
+
this.samples = software ? 1 : SAMPLING.masterSamples;
|
|
246
|
+
if (software) this.warnings.push(`software GL detected (${this.renderer.renderer}); renders will be slower, --samples lowered to 1`);
|
|
247
|
+
this.plan = planPasses({ presetId: this.presetId, timeline: this.timeline, runSeed: this.brief.seed, fps: FRAME.fps, software, brief: this.brief });
|
|
248
|
+
const persistence = this.plan.passRanges.some((r) => r.pass === 'crt' && r.params.persistenceEnabled);
|
|
249
|
+
this.shotStates = shotsOf(this.timeline).map((s) => ({ sceneId: s.sceneId, shotIndex: s.shotIndex, stateful: persistence || s.sceneId === 'number-counter', prerollMax: s.sceneId === 'number-counter' ? s.holdSec : persistence ? 2 / FRAME.fps : 0 }));
|
|
250
|
+
this.comp = this.composer();
|
|
251
|
+
this.lastRendered = null;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
persistenceFor(frame) {
|
|
255
|
+
const range = this.plan.passRanges.find((r) => r.pass === 'crt' && frame >= r.frameStart && frame <= r.frameEnd);
|
|
256
|
+
return range?.params.persistenceEnabled ? range : null;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
async renderFrame(frame, { samples, settled = null } = {}) {
|
|
260
|
+
const range = settled ? null : this.persistenceFor(frame);
|
|
261
|
+
if (range && !(this.lastRendered && this.lastRendered.frame === frame - 1 && this.lastRendered.samples === samples)) {
|
|
262
|
+
const from = Math.max(range.frameStart, frame - 2);
|
|
263
|
+
for (let f = from; f < frame; f++) {
|
|
264
|
+
const { spec } = this.comp.frameSpec(f, { samples, shutter: SAMPLING.masterShutter });
|
|
265
|
+
spec.order = FILTER_ORDER[this.presetId]; spec.prime = true; spec.resetRing = f === from;
|
|
266
|
+
await this.renderer.frame(spec);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
const { spec, meta } = this.comp.frameSpec(frame, { samples, shutter: SAMPLING.masterShutter, settled });
|
|
270
|
+
spec.order = FILTER_ORDER[this.presetId];
|
|
271
|
+
spec.resetRing = Boolean(range) && !(this.lastRendered && this.lastRendered.frame === frame - 1 && this.lastRendered.samples === samples) && frame === range.frameStart;
|
|
272
|
+
const result = await this.renderer.frame(spec);
|
|
273
|
+
this.lastRendered = settled ? null : { frame, samples };
|
|
274
|
+
const bytes = result.bytes;
|
|
275
|
+
const px = bytes.length / 4;
|
|
276
|
+
const mask = Buffer.alloc(px);
|
|
277
|
+
let ink = 0;
|
|
278
|
+
for (let i = 0, j = 3; i < px; i++, j += 4) { const a = bytes[j]; mask[i] = a; if (a >= 128) ink++; bytes[j] = 255; }
|
|
279
|
+
return { bytes, mask, ink, meta, page: result.meta };
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
shotFrames() {
|
|
283
|
+
return shotsOf(this.timeline).map((s) => {
|
|
284
|
+
const a = Math.round(s.start * FRAME.fps), b = Math.round(s.end * FRAME.fps) - 1;
|
|
285
|
+
return { shot: s, first: a, last: b, rep: Math.max(a, b - 6) };
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
savePng(file, bytes, width, height, opts) {
|
|
290
|
+
mkdirSync(dirname(file), { recursive: true });
|
|
291
|
+
writeFileSync(file, pngEncode(this.PNG, bytes, width, height, opts));
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
async stills() {
|
|
295
|
+
const W = FRAME.width * this.scale, H = FRAME.height * this.scale;
|
|
296
|
+
const dir = join(this.out, 'stills');
|
|
297
|
+
rmSync(dir, { recursive: true, force: true });
|
|
298
|
+
const paths = [];
|
|
299
|
+
this.stillFrames = [];
|
|
300
|
+
for (const [i, s] of this.shotFrames().entries()) {
|
|
301
|
+
const r = await this.renderFrame(s.rep, { samples: SAMPLING.previewSamples });
|
|
302
|
+
const file = join(dir, `${String(i + 1).padStart(2, '0')}-${s.shot.id}-f${s.rep}.png`);
|
|
303
|
+
this.savePng(file, r.bytes, W, H);
|
|
304
|
+
paths.push(file);
|
|
305
|
+
this.stillFrames.push(s.rep);
|
|
306
|
+
}
|
|
307
|
+
return paths;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
async sheet(cuts = true) {
|
|
311
|
+
const W = FRAME.width * this.scale, H = FRAME.height * this.scale;
|
|
312
|
+
const frames = [];
|
|
313
|
+
if (cuts) for (const s of this.shotFrames().slice(1)) for (const f of [s.first - 6, s.first - 1, s.first, s.first + 6]) frames.push(Math.max(0, Math.min(this.totalFrames - 1, f)));
|
|
314
|
+
if (!frames.length) for (let i = 0; i < 12; i++) frames.push(Math.round((i * (this.totalFrames - 1)) / 11));
|
|
315
|
+
this.cutFrames = this.shotFrames().slice(1).map((s) => s.first);
|
|
316
|
+
const tiles = [];
|
|
317
|
+
for (const f of frames) {
|
|
318
|
+
const r = await this.renderFrame(f, { samples: SAMPLING.previewSamples });
|
|
319
|
+
tiles.push({ data: r.bytes, width: W, height: H, frame: f });
|
|
320
|
+
}
|
|
321
|
+
mkdirSync(join(this.out, 'sheet'), { recursive: true });
|
|
322
|
+
const file = join(this.out, 'sheet', cuts ? 'cuts.png' : 'sheet.png');
|
|
323
|
+
contactSheet(this.PNG, tiles, file);
|
|
324
|
+
return file;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// The master: every byte streamed to ffmpeg is the byte hashed and flash-audited.
|
|
328
|
+
async master() {
|
|
329
|
+
const W = FRAME.width * this.scale, H = FRAME.height * this.scale;
|
|
330
|
+
const run = join(this.out, '.run');
|
|
331
|
+
const film = join(run, 'film.mp4');
|
|
332
|
+
const video = join(run, 'video.mp4');
|
|
333
|
+
const encoder = startMaster({ width: W, height: H, fps: FRAME.fps, output: video });
|
|
334
|
+
const detector = new FlashDetector(W, H);
|
|
335
|
+
const previewDir = join(run, 'preview-src');
|
|
336
|
+
rmSync(previewDir, { recursive: true, force: true });
|
|
337
|
+
mkdirSync(previewDir, { recursive: true });
|
|
338
|
+
const previewFrames = [];
|
|
339
|
+
const shots = this.shotFrames();
|
|
340
|
+
const sampled = new Set([...shots.map((s) => s.rep), ...shots.slice(1).map((s) => s.first), 0]);
|
|
341
|
+
this.contrastFrames = [...sampled].sort((a, b) => a - b);
|
|
342
|
+
const LUT = Float64Array.from({ length: 256 }, (_, v) => { const s = v / 255; return s <= 0.04045 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4; });
|
|
343
|
+
const passes = this.preset.passes;
|
|
344
|
+
this.dplan = this.directorPlan();
|
|
345
|
+
const planFrames = new Set(this.dplan.frames);
|
|
346
|
+
this.planPngs = new Map();
|
|
347
|
+
for (let f = 0; f < this.totalFrames; f++) {
|
|
348
|
+
const r = await this.renderFrame(f, { samples: this.samples });
|
|
349
|
+
const flash = detector.push(r.bytes);
|
|
350
|
+
const bins = new Uint32Array(1024);
|
|
351
|
+
for (let i = 0; i < r.bytes.length; i += 4) {
|
|
352
|
+
const l = 0.2126 * LUT[r.bytes[i]] + 0.7152 * LUT[r.bytes[i + 1]] + 0.0722 * LUT[r.bytes[i + 2]];
|
|
353
|
+
bins[Math.min(1023, Math.floor(l * 1024))]++;
|
|
354
|
+
}
|
|
355
|
+
let acc = 0, p995 = 1;
|
|
356
|
+
const target = 0.995 * (r.bytes.length / 4);
|
|
357
|
+
for (let i = 0; i < 1024; i++) { acc += bins[i]; if (acc >= target) { p995 = (i + 1) / 1024; break; } }
|
|
358
|
+
if (planFrames.has(f)) this.planPngs.set(f, pngEncode(this.PNG, r.bytes, W, H, { level: 1, scratch: true }));
|
|
359
|
+
await encoder.write(r.bytes);
|
|
360
|
+
if (f % 2 === 0) {
|
|
361
|
+
const small = areaResize(r.bytes, W, H, 960);
|
|
362
|
+
const file = join(previewDir, `s${String(f).padStart(5, '0')}.png`);
|
|
363
|
+
writeFileSync(file, pngEncode(this.PNG, small.data, small.width, small.height, { level: 1, scratch: true }));
|
|
364
|
+
previewFrames[f] = file;
|
|
365
|
+
}
|
|
366
|
+
if (sampled.has(f)) {
|
|
367
|
+
this.savePng(join(run, 'masks', `f${String(f).padStart(5, '0')}.png`), r.mask, W, H, { gray: true });
|
|
368
|
+
this.savePng(join(run, 'frames', `f${String(f).padStart(5, '0')}.png`), r.bytes, W, H);
|
|
369
|
+
for (const box of r.meta.textBoxes) {
|
|
370
|
+
if (!box.settled) continue;
|
|
371
|
+
const m = measureContrast(r.bytes, r.mask, W, H, box, this.scale);
|
|
372
|
+
if (m) this.contrast.push({ frame: f, elementId: box.elementId, ratio: m.ratio, floor: m.floor, fontSizePx: box.fontSizePx, weight: box.weight, fill: box.fill });
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
this.records.push({
|
|
376
|
+
frame: f, pass: null, rgbaSha256: sha(r.bytes), textBoxes: r.meta.textBoxes, graphics: r.meta.graphics, block: r.meta.block,
|
|
377
|
+
glyphInk: r.ink, lumP995: Number(p995.toFixed(4)), flash: { general: flash.general, generalBoth: flash.generalBoth, red: flash.red, redBoth: flash.redBoth },
|
|
378
|
+
fullFrameStep: Number(flash.fullFrameStep.toFixed(4)), overrides: r.meta.overrides, accent: r.meta.accent, fills: r.meta.fills,
|
|
379
|
+
sampleTimes: r.meta.sampleTimes, sceneId: r.meta.sceneId, shotIndex: r.meta.shotIndex, renderMs: Number(r.page.renderMs.toFixed(2)),
|
|
380
|
+
});
|
|
381
|
+
for (const pass of passes) {
|
|
382
|
+
const logged = r.page.passes[pass];
|
|
383
|
+
this.records.push({ frame: f, pass, draws: logged?.draws || 0, uniforms: logged?.uniforms || {} });
|
|
384
|
+
}
|
|
385
|
+
if (f % 60 === 59) process.stderr.write(`motion: ${f + 1}/${this.totalFrames} frames\n`);
|
|
386
|
+
}
|
|
387
|
+
const encoded = await encoder.finish();
|
|
388
|
+
if (encoded.code !== 0) throw fail(1, `ffmpeg master encode failed: ${encoded.stderr.split('\n').filter(Boolean).at(-1) || encoded.code}`);
|
|
389
|
+
// Every planned track is muxed here, whatever the --audio tier's state:
|
|
390
|
+
// the beat grid is optional, the soundtrack is not.
|
|
391
|
+
const supplied = this.brief.audio ? (isAbsolute(this.brief.audio) ? this.brief.audio : resolve(dirname(this.briefPath), this.brief.audio)) : null;
|
|
392
|
+
this.sound = await produceSound({
|
|
393
|
+
out: this.out, treatment: this.treatment, fps: FRAME.fps, totalFrames: this.totalFrames,
|
|
394
|
+
cuts: this.shotFrames().slice(1).map((s) => s.first / FRAME.fps), video, output: film, suppliedAudio: supplied,
|
|
395
|
+
});
|
|
396
|
+
rmSync(video, { force: true });
|
|
397
|
+
const preview = encodePreview({ PNG: this.PNG, sourceFrames: previewFrames, masterFps: FRAME.fps, durationSec: this.durationSec, workDir: run,
|
|
398
|
+
minGlyphPx: Math.min(...this.records.flatMap((row) => (row.textBoxes || []).map((b) => b.fontSizePx)).filter(Boolean), 64) });
|
|
399
|
+
rmSync(previewDir, { recursive: true, force: true });
|
|
400
|
+
this.previewAttempts = preview.attempts;
|
|
401
|
+
if (preview.file) {
|
|
402
|
+
this.previewEncoder = preview.encoder; this.previewFps = preview.fps; this.previewWidth = preview.width;
|
|
403
|
+
this.previewRecords = preview.records.map((row) => ({ ...row, preview: true }));
|
|
404
|
+
this.previewName = preview.encoder === 'gif' ? 'preview.gif' : 'preview.webp';
|
|
405
|
+
}
|
|
406
|
+
return film;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
async stillsForExport() {
|
|
410
|
+
const W = FRAME.width * this.scale, H = FRAME.height * this.scale;
|
|
411
|
+
const shots = shotsOf(this.timeline);
|
|
412
|
+
const poster = await this.renderFrame(Math.round(shots[0].end * FRAME.fps) - 1, { samples: 1, settled: { shotIndex: 0, reduced: false } });
|
|
413
|
+
this.savePng(join(this.out, '.run', 'poster.png'), poster.bytes, W, H, { level: 9 });
|
|
414
|
+
this.posterInk = poster.ink;
|
|
415
|
+
const reduced = await this.renderFrame(this.totalFrames - 1, { samples: 1, settled: { shotIndex: shots.length - 1, reduced: true } });
|
|
416
|
+
this.savePng(join(this.out, '.run', 'reduced-motion.png'), reduced.bytes, W, H, { level: 9 });
|
|
417
|
+
this.savePng(join(this.out, '.run', 'masks', 'reduced.png'), reduced.mask, W, H, { gray: true });
|
|
418
|
+
this.reducedInk = reduced.ink;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// MO-C-09 / MO-A-25: each cut frame re-rendered as a seek in a fresh process.
|
|
422
|
+
determinismCheck() {
|
|
423
|
+
const shots = this.shotFrames();
|
|
424
|
+
const frames = [...new Set([0, ...shots.slice(1).map((s) => s.first), ...shots.filter((s) => s.shot.sceneId === 'number-counter').map((s) => Math.round((s.first + s.last) / 2))])].slice(0, 6);
|
|
425
|
+
const byFrame = new Map(this.records.filter((r) => r.pass === null).map((r) => [r.frame, r.rgbaSha256]));
|
|
426
|
+
const child = (frame, software) => {
|
|
427
|
+
const dir = join(this.out, '.run', `det-${frame}${software ? '-sw' : ''}-${Math.random().toString(36).slice(2, 6)}`);
|
|
428
|
+
const args = [fileURLToPath(import.meta.url), 'hash-frame', '--brief', this.briefPath, '--out', dir, '--frame', String(frame), '--samples', String(this.samples), '--scale', String(this.scale)];
|
|
429
|
+
if (software) args.push('--force-software');
|
|
430
|
+
if (this.flags['force-software']) args.push('--force-software');
|
|
431
|
+
const res = spawnSync(process.execPath, args, { encoding: 'utf8', timeout: 600000 });
|
|
432
|
+
rmSync(dir, { recursive: true, force: true });
|
|
433
|
+
const line = (res.stdout || '').split('\n').find((l) => l.startsWith('MOTION_FRAME '));
|
|
434
|
+
if (!line) throw new Error(`determinism child for frame ${frame} failed: ${(res.stderr || '').trim().split('\n').at(-1) || res.status}`);
|
|
435
|
+
return JSON.parse(line.slice('MOTION_FRAME '.length));
|
|
436
|
+
};
|
|
437
|
+
const checks = [];
|
|
438
|
+
for (const frame of frames) {
|
|
439
|
+
const seeked = child(frame, false);
|
|
440
|
+
const sameHost = seeked.renderer === this.renderer.renderer && seeked.flags.join(' ') === this.renderer.flags.join(' ');
|
|
441
|
+
const entry = { frame, sequential: byFrame.get(frame), seeked: seeked.rgbaSha256, match: sameHost && seeked.rgbaSha256 === byFrame.get(frame), renderer: seeked.renderer };
|
|
442
|
+
if (!entry.match) {
|
|
443
|
+
const a = child(frame, true), b = child(frame, true);
|
|
444
|
+
entry.software = { first: a.rgbaSha256, second: b.rgbaSha256, renderer: a.renderer };
|
|
445
|
+
}
|
|
446
|
+
checks.push(entry);
|
|
447
|
+
}
|
|
448
|
+
this.determinism = { checks, samples: this.samples };
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
async perfRun() {
|
|
452
|
+
const times = [];
|
|
453
|
+
for (let i = 0; i < PERF.frames; i++) {
|
|
454
|
+
const f = Math.round((i * (this.totalFrames - 1)) / (PERF.frames - 1));
|
|
455
|
+
this.lastRendered = null;
|
|
456
|
+
const r = await this.renderFrame(f, { samples: 1 });
|
|
457
|
+
times.push(r.page.renderMs);
|
|
458
|
+
}
|
|
459
|
+
times.sort((a, b) => a - b);
|
|
460
|
+
this.perf = { frames: times.length, p50Ms: times[Math.floor(times.length / 2)], p95Ms: times[Math.ceil(times.length * 0.95) - 1], maxMs: times.at(-1), software: this.renderer.software, samples: 1 };
|
|
461
|
+
return this.perf;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
// The director stills set (craft-loop.md): every shot's midpoint, a strip
|
|
465
|
+
// per cut, the contact sheet and the poster.
|
|
466
|
+
directorPlan() {
|
|
467
|
+
const beats = this.shotFrames().map((s, index) => ({ index, first: s.first, last: s.last, mid: Math.round((s.first + s.last) / 2) }));
|
|
468
|
+
return stillsPlan({ totalFrames: this.totalFrames, beats });
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
async directorStillsOnly() {
|
|
472
|
+
const W = FRAME.width * this.scale, H = FRAME.height * this.scale;
|
|
473
|
+
const plan = this.directorPlan();
|
|
474
|
+
const pngs = new Map();
|
|
475
|
+
for (const f of plan.frames) {
|
|
476
|
+
const r = await this.renderFrame(f, { samples: SAMPLING.previewSamples });
|
|
477
|
+
pngs.set(f, pngEncode(this.PNG, r.bytes, W, H, { level: 1, scratch: true }));
|
|
478
|
+
}
|
|
479
|
+
const shots = shotsOf(this.timeline);
|
|
480
|
+
const poster = await this.renderFrame(Math.round(shots[0].end * FRAME.fps) - 1, { samples: 1, settled: { shotIndex: 0, reduced: false } });
|
|
481
|
+
return writeStillsSet({ out: this.out, PNG: this.PNG, pngs, plan, size: [W, H], round: this.round, mode: 'stills-only', posterPng: pngEncode(this.PNG, poster.bytes, W, H) });
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
directorStillsFromMaster() {
|
|
485
|
+
const W = FRAME.width * this.scale, H = FRAME.height * this.scale;
|
|
486
|
+
return writeStillsSet({ out: this.out, PNG: this.PNG, pngs: this.planPngs, plan: this.dplan, size: [W, H], round: this.round, mode: this.mode, posterPng: readFileSync(join(this.out, '.run', 'poster.png')) });
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
gateNow() {
|
|
490
|
+
const manifest = this.baseManifest();
|
|
491
|
+
const where = (name) => [join(this.out, '.run', name), join(this.out, name), join(this.out, 'withheld', name)].find((p) => existsSync(p));
|
|
492
|
+
const films = where('film.mp4'), prev = this.previewName && where(this.previewName), poster = where('poster.png'), reduced = where('reduced-motion.png');
|
|
493
|
+
const exports = {
|
|
494
|
+
probe: films ? ffprobe(films) : null,
|
|
495
|
+
sizes: { film: films && statSync(films).size, preview: prev && statSync(prev).size, poster: poster && statSync(poster).size, reduced: reduced && statSync(reduced).size },
|
|
496
|
+
present: { film: Boolean(films), preview: Boolean(prev), poster: Boolean(poster), reduced: Boolean(reduced), manifest: true },
|
|
497
|
+
};
|
|
498
|
+
const notice = existsSync(join(skillRoot, 'engine', 'NOTICE')) && sha(readFileSync(join(skillRoot, 'engine', 'NOTICE'))) === NOTICE_SHA;
|
|
499
|
+
const gate = runGate({ manifest, records: this.records, preview: this.previewRecords, exports, contrast: this.contrast, preflight: { missingGlyphs: this.missingGlyphs || [] }, notice });
|
|
500
|
+
gate.rules.push(...(this.sound?.rules || []));
|
|
501
|
+
gate.failed = gate.rules.filter((r) => r.status === 'FAIL').map((r) => r.id);
|
|
502
|
+
return { manifest, gate, exports };
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
writeOutputs(manifest, gate, { keepManifest = false } = {}) {
|
|
506
|
+
if (!keepManifest) writeJson(join(this.out, 'manifest.json'), manifest);
|
|
507
|
+
writeFileSync(join(this.out, 'render.jsonl'), [...this.records, ...this.previewRecords].map((row) => JSON.stringify(row)).join('\n') + '\n');
|
|
508
|
+
const outputs = gate.withhold
|
|
509
|
+
? { film: 'withheld/film.mp4', preview: `withheld/${this.previewName || 'preview.webp'}`, poster: 'withheld/poster.png', reduced: 'withheld/reduced-motion.png' }
|
|
510
|
+
: { film: 'film.mp4', preview: this.previewName || 'preview (not produced)', poster: 'poster.png', reduced: 'reduced-motion.png' };
|
|
511
|
+
const looked = viewedFiles(this.out);
|
|
512
|
+
writeFileSync(join(this.out, 'gate-report.txt'), renderReport(manifest, gate, { outputs, framesViewed: looked.length ? looked : this.framesViewed, egress: this.renderer?.egress, withheld: gate.withhold }));
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
// Type path: the treatment comes first. Without --brief the engine brief is
|
|
517
|
+
// DIR/brief.json, written from the treatment's copy the first time and then
|
|
518
|
+
// yours to refine (scenes, style, accent).
|
|
519
|
+
function typePathTreatment(session) {
|
|
520
|
+
const { treatment } = loadTreatment(session.out, EXIT.BLOCKED_TREATMENT_INVALID);
|
|
521
|
+
if (treatment.path !== 'type') {
|
|
522
|
+
throw fail(EXIT.BLOCKED_TREATMENT_INVALID, 'BLOCKED_TREATMENT_INVALID: field path: this treatment takes the stage path; render it with `stage --out DIR`');
|
|
523
|
+
}
|
|
524
|
+
recordFirstTreatment(session.out, treatment);
|
|
525
|
+
session.treatment = treatment;
|
|
526
|
+
if (!session.flags.brief) {
|
|
527
|
+
const derived = join(session.out, 'brief.json');
|
|
528
|
+
if (!existsSync(derived)) writeJson(derived, { text: treatment.copy.lines, durationSec: treatment.durationSec });
|
|
529
|
+
session.flags.brief = derived;
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
function writeState(out, state) {
|
|
534
|
+
if (!out) return;
|
|
535
|
+
mkdirSync(out, { recursive: true });
|
|
536
|
+
writeJson(join(out, 'run-state.json'), { ...state, finishedAt: new Date().toISOString() });
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
async function main(argv) {
|
|
540
|
+
const flags = parseArgs(argv);
|
|
541
|
+
const mode = flags._[0];
|
|
542
|
+
if (!mode || flags.help || mode === 'help') { console.log(USAGE); return 0; }
|
|
543
|
+
if (mode === 'complete') return completeCommand(resolve(flags.out || 'motion-output'));
|
|
544
|
+
if (mode === 'stage') return stageCommand(flags);
|
|
545
|
+
if (mode === 'sound') return soundCommand(flags);
|
|
546
|
+
if (mode === 'look') return lookCommand(flags);
|
|
547
|
+
if (!['run', 'stills', 'sheet', 'video', 'perf', 'gate', 'hash-frame'].includes(mode)) { console.error(USAGE); return 2; }
|
|
548
|
+
if (mode === 'gate') return regate(flags);
|
|
549
|
+
const session = new Session(flags, flags['stills-only'] ? 'stills-only' : mode);
|
|
550
|
+
const stateOut = mode === 'hash-frame' ? null : session.out;
|
|
551
|
+
if (stateOut) writeState(stateOut, { exitCode: null, mode: session.mode, round: session.round, finished: false });
|
|
552
|
+
try {
|
|
553
|
+
if (mode !== 'hash-frame') typePathTreatment(session);
|
|
554
|
+
session.prepare();
|
|
555
|
+
if (mode !== 'hash-frame') session.preflight();
|
|
556
|
+
const ffmpeg = hasFfmpeg();
|
|
557
|
+
if (mode === 'video' && !ffmpeg) throw fail(EXIT.BLOCKED_NO_FFMPEG_FOR_VIDEO, 'BLOCKED_NO_FFMPEG_FOR_VIDEO: ffmpeg is not on PATH; `stills` and `sheet` still work, install ffmpeg for the film');
|
|
558
|
+
await session.openChrome();
|
|
559
|
+
try {
|
|
560
|
+
if (mode === 'hash-frame') {
|
|
561
|
+
const frame = Number(flags.frame);
|
|
562
|
+
if (!Number.isInteger(frame) || frame < 0 || frame >= session.totalFrames) throw fail(2, '--frame must name a frame of this film');
|
|
563
|
+
session.samples = Number(flags.samples || session.samples);
|
|
564
|
+
// --from K renders K..frame sequentially in this one process (a video-mode
|
|
565
|
+
// frame line); without it the frame is a cold seek (MO-A-25, MO-C-09).
|
|
566
|
+
const from = flags.from == null ? frame : Number(flags.from);
|
|
567
|
+
let r;
|
|
568
|
+
for (let f = Math.max(0, Math.min(from, frame)); f <= frame; f++) r = await session.renderFrame(f, { samples: session.samples });
|
|
569
|
+
console.log(`MOTION_FRAME ${JSON.stringify({ frame, rgbaSha256: sha(r.bytes), renderer: session.renderer.renderer, flags: session.renderer.flags, egress: session.renderer.egress })}`);
|
|
570
|
+
return 0;
|
|
571
|
+
}
|
|
572
|
+
if (mode === 'perf') {
|
|
573
|
+
const perf = await session.perfRun();
|
|
574
|
+
mkdirSync(session.out, { recursive: true });
|
|
575
|
+
writeJson(join(session.out, 'perf.json'), { ...perf, renderer: session.renderer.renderer, flags: session.renderer.flags });
|
|
576
|
+
console.log(`motion perf: p95 ${perf.p95Ms.toFixed(1)} ms (p50 ${perf.p50Ms.toFixed(1)}, max ${perf.maxMs.toFixed(1)}) over ${perf.frames} frames at samples 1; renderer ${session.renderer.renderer}`);
|
|
577
|
+
const ceiling = perf.software ? PERF.softwareP95Ms : PERF.hardwareP95Ms;
|
|
578
|
+
writeState(session.out, { exitCode: perf.p95Ms > ceiling ? 13 : 0, mode, round: session.round, finished: true, failed: perf.p95Ms > ceiling ? ['MO-D-02'] : [] });
|
|
579
|
+
return perf.p95Ms > ceiling ? 13 : 0;
|
|
580
|
+
}
|
|
581
|
+
if (mode === 'run' || mode === 'stills') {
|
|
582
|
+
const stills = await session.stills();
|
|
583
|
+
console.log(`stills: ${stills.join(' ')}`);
|
|
584
|
+
}
|
|
585
|
+
if (mode === 'run' || mode === 'sheet') {
|
|
586
|
+
const sheet = await session.sheet(mode === 'run' || Boolean(flags.cuts));
|
|
587
|
+
console.log(`sheet: ${sheet}`);
|
|
588
|
+
}
|
|
589
|
+
if (mode === 'run' && flags['stills-only']) {
|
|
590
|
+
const set = await session.directorStillsOnly();
|
|
591
|
+
console.log(`stills set: ${set.files.map((f) => join(session.out, f.file)).join(' ')}`);
|
|
592
|
+
}
|
|
593
|
+
if (mode === 'stills' || mode === 'sheet' || flags['stills-only']) {
|
|
594
|
+
writeJson(join(session.out, 'manifest.json'), session.baseManifest());
|
|
595
|
+
if (mode === 'run') stampStills(session.out);
|
|
596
|
+
writeState(session.out, { exitCode: 0, mode: session.mode, round: session.round, finished: true, failed: [] });
|
|
597
|
+
console.log('View every still, strip and the contact sheet with your image tool, then record the round with `look` before the full render.');
|
|
598
|
+
return 0;
|
|
599
|
+
}
|
|
600
|
+
if (!ffmpeg) {
|
|
601
|
+
writeJson(join(session.out, 'manifest.json'), session.baseManifest());
|
|
602
|
+
throw fail(EXIT.BLOCKED_NO_FFMPEG_FOR_VIDEO, `BLOCKED_NO_FFMPEG_FOR_VIDEO: stills and the cut sheet are in ${session.out}; ffmpeg is not on PATH, so no film was encoded`);
|
|
603
|
+
}
|
|
604
|
+
await session.master();
|
|
605
|
+
await session.stillsForExport();
|
|
606
|
+
await session.perfRun();
|
|
607
|
+
session.determinismCheck();
|
|
608
|
+
if (mode === 'run') session.directorStillsFromMaster();
|
|
609
|
+
const { manifest, gate } = session.gateNow();
|
|
610
|
+
promoteExports(session.out, { withhold: gate.withhold, previewName: session.previewName || 'preview.webp' });
|
|
611
|
+
session.writeOutputs(manifest, gate);
|
|
612
|
+
if (mode === 'run') stampStills(session.out);
|
|
613
|
+
const code = gate.failed.length ? EXIT.GATE_FAIL_QA : EXIT.OK;
|
|
614
|
+
writeState(session.out, { exitCode: code, mode: session.mode, round: session.round, finished: true, failed: gate.failed, withheld: gate.withhold });
|
|
615
|
+
console.log(`motion ${gate.failed.length ? `QA FAIL (${gate.failed.join(', ')})` : 'QA PASS'}; report ${join(session.out, 'gate-report.txt')}${gate.withhold ? '; exports WITHHELD in withheld/' : ''}`);
|
|
616
|
+
if (gate.failed.length && session.round >= 3) console.log(gate.withhold ? 'Round 3 of 3: the render is withheld pending a fix of the flash failure.' : 'Round 3 of 3: stop and hand back the report with the delivered artifacts.');
|
|
617
|
+
else if (gate.failed.length) console.log(`Fix the named rules and rerun with --round ${session.round + 1}.`);
|
|
618
|
+
return code;
|
|
619
|
+
} finally { await session.renderer.close(); }
|
|
620
|
+
} catch (error) {
|
|
621
|
+
const code = error.exitCode ?? 1;
|
|
622
|
+
console.error(error.exitCode ? error.message : `motion internal error: ${error.stack || error.message}`);
|
|
623
|
+
if (stateOut) writeState(stateOut, { exitCode: code, mode: session.mode, round: session.round, finished: true, failed: error.failed || [], message: String(error.message).split('\n')[0] });
|
|
624
|
+
return code;
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
// `gate`: re-measure contrast from the saved masks, rerun determinism and perf,
|
|
629
|
+
// and rewrite the report for an existing output directory.
|
|
630
|
+
async function regate(flags) {
|
|
631
|
+
const out = resolve(flags.out || 'motion-output');
|
|
632
|
+
const manifestPath = join(out, 'manifest.json');
|
|
633
|
+
if (!existsSync(manifestPath) || !existsSync(join(out, 'render.jsonl'))) { console.error(`no finished render in ${out}`); return 2; }
|
|
634
|
+
const manifest = JSON.parse(readFileSync(manifestPath, 'utf8'));
|
|
635
|
+
if (manifest.path === 'stage') return stageRegate(out);
|
|
636
|
+
const session = new Session({ ...flags, brief: manifest.lithermes.brief.path, round: manifest.lithermes.round, scale: manifest.scale }, manifest.lithermes.mode);
|
|
637
|
+
try {
|
|
638
|
+
session.prepare();
|
|
639
|
+
session.preflight();
|
|
640
|
+
const rows = readFileSync(join(out, 'render.jsonl'), 'utf8').trim().split('\n').map((line) => JSON.parse(line));
|
|
641
|
+
session.records = rows.filter((r) => !r.preview);
|
|
642
|
+
session.previewRecords = rows.filter((r) => r.preview);
|
|
643
|
+
session.previewEncoder = manifest.previewEncoder; session.previewFps = manifest.lithermes.previewFps; session.previewWidth = manifest.lithermes.previewWidth;
|
|
644
|
+
session.previewName = manifest.previewEncoder === 'gif' ? 'preview.gif' : 'preview.webp';
|
|
645
|
+
session.reducedInk = manifest.lithermes.reducedInk; session.posterInk = manifest.lithermes.posterInk;
|
|
646
|
+
session.framesViewed = manifest.lithermes.framesViewed || [];
|
|
647
|
+
session.stillFrames = manifest.lithermes.stills; session.cutFrames = manifest.lithermes.cuts; session.contrastFrames = manifest.lithermes.contrastFrames;
|
|
648
|
+
const W = FRAME.width * session.scale, H = FRAME.height * session.scale;
|
|
649
|
+
for (const f of session.contrastFrames || []) {
|
|
650
|
+
const framePng = join(out, '.run', 'frames', `f${String(f).padStart(5, '0')}.png`), maskPng = join(out, '.run', 'masks', `f${String(f).padStart(5, '0')}.png`);
|
|
651
|
+
if (!existsSync(framePng) || !existsSync(maskPng)) continue;
|
|
652
|
+
const rgba = pngDecode(session.PNG, framePng).data, maskImg = pngDecode(session.PNG, maskPng).data;
|
|
653
|
+
const mask = Buffer.alloc(W * H);
|
|
654
|
+
for (let i = 0; i < mask.length; i++) mask[i] = maskImg[i * 4];
|
|
655
|
+
const row = session.records.find((r) => r.pass === null && r.frame === f);
|
|
656
|
+
for (const box of row?.textBoxes || []) {
|
|
657
|
+
if (!box.settled) continue;
|
|
658
|
+
const m = measureContrast(rgba, mask, W, H, box, session.scale);
|
|
659
|
+
if (m) session.contrast.push({ frame: f, elementId: box.elementId, ratio: m.ratio, floor: m.floor, fontSizePx: box.fontSizePx, weight: box.weight, fill: box.fill });
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
if (flags['no-rerender']) { session.determinism = manifest.lithermes.determinism; session.perf = manifest.lithermes.perf; session.renderer = { renderer: manifest.renderer, flags: manifest.chromeFlags, software: manifest.softwareRenderer, egress: manifest.lithermes.egress }; }
|
|
663
|
+
else {
|
|
664
|
+
await session.openChrome();
|
|
665
|
+
try { await session.perfRun(); } finally { await session.renderer.close(); }
|
|
666
|
+
session.determinismCheck();
|
|
667
|
+
}
|
|
668
|
+
session.plan = { passRanges: manifest.passRanges, events: manifest.lithermes.events };
|
|
669
|
+
const planned = manifest.lithermes.sound;
|
|
670
|
+
const filmFile = [join(out, 'film.mp4'), join(out, 'withheld', 'film.mp4')].find((f) => existsSync(f));
|
|
671
|
+
session.sound = { summary: planned, rules: planned && planned.mode !== 'none' && filmFile ? soundGate({ file: filmFile, mode: planned.mode }).rules : [{ id: 'sound-stream', status: 'PASS', detail: 'no sound planned' }] };
|
|
672
|
+
session.shotStates = manifest.lithermes.shots;
|
|
673
|
+
session.samples = manifest.samples;
|
|
674
|
+
const { manifest: fresh, gate } = session.gateNow();
|
|
675
|
+
session.writeOutputs({ ...fresh, generatedAt: manifest.generatedAt }, gate, { keepManifest: true });
|
|
676
|
+
console.log(readFileSync(join(out, 'gate-report.txt'), 'utf8'));
|
|
677
|
+
writeState(out, { exitCode: gate.failed.length ? 13 : 0, mode: manifest.lithermes.mode, round: manifest.lithermes.round, finished: true, failed: gate.failed, withheld: gate.withhold });
|
|
678
|
+
return gate.failed.length ? EXIT.GATE_FAIL_QA : EXIT.OK;
|
|
679
|
+
} catch (error) {
|
|
680
|
+
console.error(error.exitCode ? error.message : `motion internal error: ${error.stack || error.message}`);
|
|
681
|
+
return error.exitCode ?? 1;
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
function isMain() {
|
|
686
|
+
try { return realpathSync(process.argv[1]) === realpathSync(fileURLToPath(import.meta.url)); } catch { return false; }
|
|
687
|
+
}
|
|
688
|
+
if (isMain()) process.exitCode = await main(process.argv.slice(2));
|
|
689
|
+
|
|
690
|
+
export { main, parseArgs, USAGE };
|