elanous 0.2.4 → 0.2.5
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 +3 -3
- package/apps/pwa/out/404/index.html +1 -1
- package/apps/pwa/out/404.html +1 -1
- package/apps/pwa/out/_next/static/chunks/06ef2eba-d1b99ac6d2ea663c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1413-7179a49332db5a80.js +1 -0
- package/apps/pwa/out/_next/static/chunks/150-25c277137a9638ab.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1640-bc99ec23bbe29d12.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2415.ed6428ff334c7ce2.js → 1751.50b96ea9c37b49b6.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2300-de059d0ab2a16630.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2684-05b0a81e75298c16.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3026-2ed7e317d9b02102.js +25 -0
- package/apps/pwa/out/_next/static/chunks/3611-77496ada38cd6358.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3717-68957c4dc9ceec90.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3929-46ba9af6f9d895cc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4015-62c5a3744698a8da.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4217-3c4317a7905f9eeb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4240-3230f230fae2d7d5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4271-e53e075ebd48593b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4377.3b125fef79576dfd.js +5 -0
- package/apps/pwa/out/_next/static/chunks/4440-18bb160d95819f4e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4853-35fdbe6bdbcdc0fc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2ea96958-e8c7e112de50b067.js → 4daa2798-1363d725c79f3593.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5007-6a3b30e23ff68a6e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5244-12b424c42070f5ff.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{5791-bb82743fa6299562.js → 5348-bbf838e119661eee.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5391-8793f88b03b30161.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5611-df00af3e4e4a61bb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/5890-dca2321773be829a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6123-37c9dc57ddaa7ab0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6588-b7975304a302ab91.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6604-c03961962b6273b6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7109-cf8c87e968e83a65.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7178-30f77877525a2efb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7262-871563fc9663730b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7294-f0eeebb92aa93459.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7429-881af44deed6958f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7527.943753b6ed829f09.js +1 -0
- package/apps/pwa/out/_next/static/chunks/764-a01e858525a190c0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7868-e35d5f7985ecd3f1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8320-51484af7b01fdfa5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4323.c5dfb6f503304775.js → 8617.465ca22a319c95b3.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/{5080-1613752891fcadb4.js → 8918-482b30ce2a8ebf4c.js} +3 -3
- package/apps/pwa/out/_next/static/chunks/9131-52f5fad51cceca04.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9238.2cd5f47f4bf7a2c3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{6062-73e68343a9814f6a.js → 9704-3221c102623c8d73.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-70c404c7bb6d7f0f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-3ffd80166b1050aa.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-f89e9a303515a033.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-4f403cd060442c95.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/{page-9fa879ebf5959096.js → page-0ac5d053f0444d21.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-4bcc63e272ae8205.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-880734bd07d62882.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/{page-4472ddf1e2458e69.js → page-72bd384898d88955.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-1018bbc9586ecae5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-de86f8c38076dd7b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-70c404c7bb6d7f0f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-cd6447196d8bafe6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-e733630c47fa102b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-d1c1a8357b161875.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-60c514128e81d787.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-8b637b7e325e13c1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/{page-112f7e477bda77fd.js → page-bccce0babceae30f.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-63301d11dbe73836.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-a8cf0dc472060db2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-02fba54881ccfa49.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-d5e8e90f0038f8de.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-b1ef6824f494466a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-d589bb0f233b1009.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-c9bbaebef4cda059.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-3639ce7916b92fed.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-7450ae7478955653.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-70c404c7bb6d7f0f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-b41ca4abfd618452.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-b333dd79ebee3fa9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-8be1227492793655.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-6e03e9371b552e0d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/page-911411e9fca18d03.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-792170e649b37088.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-c40463466937bc91.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-509c798b80384536.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-1cac2aa21d77c417.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-9626799d9b4a2cd1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-84cd419494e16b0f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8046cadf-211ca3c0e00f2b72.js → f6f3850d-7f324c6566002113.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/framework-361487d2da603917.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-607f5beb94cb2e07.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-d0222d219e29dddf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-a26980a31126decc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-edb2b37decf23e4d.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{webpack-e5bea36f183b25e6.js → webpack-2bf59c720fe9542c.js} +1 -1
- package/apps/pwa/out/_next/static/css/eaa74e8bb2f62269.css +1 -0
- package/apps/pwa/out/_next/static/{zoQX5iTvXOsIvCjxCe1Ji → ktMqfrBbf8BMGac0jqLrb}/_buildManifest.js +1 -1
- package/apps/pwa/out/approvals/index.html +1 -1
- package/apps/pwa/out/approvals/index.txt +29 -27
- package/apps/pwa/out/autopilot/index.html +1 -1
- package/apps/pwa/out/autopilot/index.txt +29 -27
- package/apps/pwa/out/board/index.html +1 -1
- package/apps/pwa/out/board/index.txt +29 -27
- package/apps/pwa/out/botlab/index.html +1 -1
- package/apps/pwa/out/botlab/index.txt +26 -24
- package/apps/pwa/out/bots/index.html +1 -1
- package/apps/pwa/out/bots/index.txt +26 -24
- package/apps/pwa/out/chat/index.html +1 -1
- package/apps/pwa/out/chat/index.txt +26 -24
- package/apps/pwa/out/control/index.html +1 -1
- package/apps/pwa/out/control/index.txt +29 -27
- package/apps/pwa/out/design-check/index.html +1 -1
- package/apps/pwa/out/design-check/index.txt +29 -27
- package/apps/pwa/out/editor/index.html +1 -1
- package/apps/pwa/out/editor/index.txt +29 -27
- package/apps/pwa/out/healthz +1 -1
- package/apps/pwa/out/icons/elanous-16.png +0 -0
- package/apps/pwa/out/icons/elanous-180.png +0 -0
- package/apps/pwa/out/icons/elanous-192.png +0 -0
- package/apps/pwa/out/icons/elanous-32.png +0 -0
- package/apps/pwa/out/icons/elanous-512.png +0 -0
- package/apps/pwa/out/index.html +1 -1
- package/apps/pwa/out/index.txt +26 -24
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +29 -27
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +29 -27
- package/apps/pwa/out/manifest.webmanifest +5 -2
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +26 -24
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +26 -24
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +29 -27
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +29 -27
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +27 -25
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +29 -27
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +26 -24
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +29 -27
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +29 -27
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +29 -27
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +29 -27
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +29 -27
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +26 -24
- package/apps/pwa/out/sw-strategies.js +44 -0
- package/apps/pwa/out/sw.js +6 -44
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +29 -27
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +29 -27
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +29 -27
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +29 -27
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +29 -27
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +29 -27
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +29 -27
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +29 -27
- package/catalog/resources.yaml +6 -6
- package/docs/goal-context/steward-directives-2026-09-28.md +35 -37
- package/graphs/landing/landing-heal.yaml +1 -1
- package/graphs/release/recipes.yaml +8 -1
- package/graphs/release/release-loop.yaml +6 -1
- package/graphs/video/README.md +1 -0
- package/graphs/video/explainer-line.yaml +58 -0
- package/package.json +3 -1
- package/plugins/job-coach/.codex-plugin/plugin.json +18 -1
- package/plugins/job-coach/README.md +12 -0
- package/plugins/job-coach/connectors/ncs/server.ts +4 -3
- package/plugins/job-coach/graphs/gap-judge.ts +44 -0
- package/plugins/job-coach/graphs/recipes.yaml +27 -0
- package/plugins/job-coach/graphs/report-enterprise.yaml +28 -0
- package/plugins/job-coach/graphs/run-step.ts +211 -17
- package/plugins/job-coach/plugin.json +16 -3
- package/plugins/job-coach/skills/enterprise-ai-fit/SKILL.md +8 -0
- package/plugins/job-coach/skills/enterprise-competency/SKILL.md +8 -0
- package/plugins/job-coach/skills/enterprise-needs/SKILL.md +8 -0
- package/plugins/job-coach/skills/enterprise-roadmap/SKILL.md +8 -0
- package/plugins/job-coach/skills/enterprise-task-analysis/SKILL.md +8 -0
- package/plugins/job-coach/skills/interview-to-profile/SKILL.md +18 -1
- package/scripts/backup/elanous-backup.sh +4 -1
- package/scripts/build-docs-site.ts +4 -3
- package/scripts/coord-channel-watch.sh +23 -4
- package/scripts/coord-post.sh +49 -12
- package/scripts/coord-tracks.json +5 -5
- package/scripts/eval-bot-vs-grok.ts +79 -0
- package/scripts/eval-grok-live-baseline.ts +36 -0
- package/scripts/fixtures/front-route-corpus.sample.json +17 -0
- package/scripts/fleet/node-setup.sh +46 -7
- package/scripts/landing-heal/must-fix-match.ts +26 -0
- package/scripts/landing-heal/run-mission.ts +114 -20
- package/scripts/lib/front-route-measurement.ts +131 -0
- package/scripts/lib/tui-sim-keys.ts +42 -0
- package/scripts/measure-front-route-classifier.ts +56 -0
- package/scripts/media/ocr-leak-scan.sh +21 -0
- package/scripts/public-export.ts +2 -3
- package/scripts/public-import-pr.ts +80 -6
- package/scripts/publish-internal-dist.ts +2 -3
- package/scripts/red-sweep-diff.ts +1 -1
- package/scripts/release-loop/auto-approve-node.ts +72 -0
- package/scripts/release-loop/gate-node.ts +332 -44
- package/scripts/release-loop/publish-node.ts +7 -3
- package/scripts/release-loop/release-docs.ts +20 -13
- package/scripts/release-loop/test-durations.ts +63 -0
- package/scripts/release-loop/upgrade-node.ts +3 -2
- package/scripts/test-audit-coverage-per-file.sh +16 -0
- package/scripts/test-audit-meaningless.ts +88 -0
- package/scripts/test-audit-overlap-and-weak.ts +73 -0
- package/scripts/test-deterministic.ts +27 -5
- package/scripts/tui-sim.ts +59 -14
- package/scripts/ux/bump-installed.sh +20 -0
- package/scripts/ux/lib/cdp.ts +72 -0
- package/scripts/ux/record-page.ts +50 -0
- package/skills/explainer-video/SKILL.md +99 -0
- package/skills/explainer-video/engine/brand/elanous-mark-on-dark.svg +1 -0
- package/skills/explainer-video/engine/build.mjs +431 -0
- package/skills/explainer-video/engine/vo.ts +37 -0
- package/skills/explainer-video/examples/elanous-0.2.5/script.json +155 -0
- package/src/agent/nested-agent-env.ts +1 -0
- package/src/agent-mission/driver.ts +95 -16
- package/src/agent-mission/mission-cli.ts +6 -0
- package/src/agent-mission/resource-ladder.ts +73 -25
- package/src/auth/acp-token.ts +16 -0
- package/src/auth/github-app-token.ts +112 -0
- package/src/autopilot/gh-rest-fallback.ts +177 -0
- package/src/autopilot/pr-manager.ts +51 -4
- package/src/boot/acp-server.ts +2 -16
- package/src/boot/daemon-tools/web-search.ts +2 -1
- package/src/boot/ws-bridge.ts +11 -0
- package/src/chat/index.ts +37 -8
- package/src/chat/log-scroll-key.ts +12 -0
- package/src/chat/submit-trace.ts +30 -0
- package/src/cli/agent-cli.ts +7 -2
- package/src/cli/decisions-cli.ts +94 -0
- package/src/cli/doctor-cli.ts +40 -54
- package/src/cli/doctor-readiness.ts +16 -24
- package/src/cli/intake-cli.ts +1 -1
- package/src/cli/mcp-call.ts +9 -0
- package/src/cli/mcp-gateway-cli.ts +7 -3
- package/src/cli/plugin-cli.ts +109 -11
- package/src/cli/pr-lineage.ts +2 -1
- package/src/cli/pwa-start.ts +3 -0
- package/src/cli/release-cli.ts +94 -7
- package/src/cli/self-update.ts +7 -4
- package/src/cli/start-cli.ts +33 -14
- package/src/dashboard/acp-boot.ts +3 -0
- package/src/dashboard/index.ts +62 -13
- package/src/dashboard/input/no-provider-reply.ts +13 -0
- package/src/dashboard/slash-runtime/unknown-slash-reply.ts +78 -0
- package/src/dashboard/stale-install-check.ts +77 -0
- package/src/decisions/decision-ledger.ts +404 -0
- package/src/domains/outbound-alert.ts +8 -2
- package/src/domains/telegram-kind-route.ts +21 -0
- package/src/execution-loop/dispatch-task.ts +139 -0
- package/src/execution-loop/gate-decision-summary.ts +29 -0
- package/src/execution-loop/gates.ts +197 -0
- package/src/graph-kinds/installed-plugin-nodes.ts +95 -0
- package/src/graph-kinds/plugin-nodes.ts +10 -2
- package/src/graph-runner/runner.ts +35 -5
- package/src/grounding/token.ts +12 -6
- package/src/harness/harness-cli-command.ts +68 -9
- package/src/harness/harness-pod-dispatch.ts +8 -2
- package/src/harness/harness-stop.ts +147 -18
- package/src/harness/self-send-decide.ts +26 -17
- package/src/harness/self-send-target.ts +22 -1
- package/src/harness/worktree-branch-prefix.ts +4 -3
- package/src/index.ts +56 -13
- package/src/instance/resolve.ts +6 -0
- package/src/intake-plane/collect-telegram-saved.ts +5 -0
- package/src/intake-plane/digest.ts +11 -2
- package/src/live/detail-switch.ts +8 -3
- package/src/llm/usable-llm.ts +32 -0
- package/src/loops/registry.ts +27 -5
- package/src/market/publish.ts +59 -3
- package/src/native-tool-catalog.ts +2 -2
- package/src/nexus/api/graph-approvals.ts +125 -0
- package/src/nexus/api/http-server.ts +60 -6
- package/src/nexus/api/log-fabric.ts +10 -1
- package/src/nexus/api/mcp-oauth-hint.ts +10 -9
- package/src/nexus/api/merge-approvals.ts +2 -1
- package/src/nexus/api/meta-api.ts +14 -0
- package/src/nexus/api/plugins-credentials-api.ts +47 -0
- package/src/nexus/api/plugins-market.ts +87 -3
- package/src/nexus/api/pod-credential-api.ts +68 -14
- package/src/nexus/api/public-routes.ts +7 -0
- package/src/nexus/api/trace.ts +57 -6
- package/src/nexus/boot/register-mcp-clients.ts +99 -14
- package/src/nexus/index.ts +33 -32
- package/src/nexus/outbound/router.ts +1 -1
- package/src/onboarding.ts +25 -2
- package/src/plugins/core/host.ts +14 -0
- package/src/plugins/install/market-fetch.ts +4 -3
- package/src/plugins/install/plugin-credentials.ts +106 -0
- package/src/plugins/install/plugin-install.ts +163 -32
- package/src/prompt-library/universal-preamble.ts +8 -2
- package/src/release-loop/checklist.ts +191 -0
- package/src/release-loop/release-note.ts +6 -3
- package/src/self-dev/dev-cli.ts +40 -20
- package/src/self-dev/dev-pipeline.ts +77 -1
- package/src/self-implement/gate-baseline.ts +3 -1
- package/src/self-implement/goal-author.ts +18 -1
- package/src/self-implement/host-regate.ts +6 -2
- package/src/self-implement/orchestrator.ts +7 -2
- package/src/self-implement/seams.ts +4 -2
- package/src/skills/tools/dev-harness.ts +42 -0
- package/src/steward/steward-cards.ts +45 -0
- package/src/steward/triage.ts +50 -14
- package/src/task-orchestrator/surfaces/pod-artifact-return.ts +61 -3
- package/src/task-orchestrator/surfaces/pod-command-job.ts +27 -6
- package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +39 -9
- package/src/task-orchestrator/surfaces/pod-source-bundle.ts +16 -1
- package/src/task-orchestrator/surfaces/pod-source-receive.ts +51 -13
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +172 -28
- package/src/telegram-report.ts +12 -6
- package/src/tui-client/acp-transport-ws-client.ts +72 -5
- package/src/tui.ts +3 -2
- package/src/user-config.ts +28 -2
- package/src/util/spawn-sync-output.ts +15 -0
- package/src/version/code-revision.ts +1 -1
- package/src/version/packed-revision.json +1 -1
- package/src/web-search/free.ts +77 -0
- package/src/web-search/index.ts +2 -0
- package/src/workflow-runtime/deps-bridge.ts +4 -3
- package/src/workflow-runtime/plugin-kind-node.ts +32 -4
- package/src/workflow-runtime/types.ts +2 -1
- package/apps/pwa/out/_next/static/chunks/1105-c473ed46272fba79.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1191-7b13a24117a689fa.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1201-09613bce624467c0.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1377-1efeffbbac0963ff.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1470.98a6ab61ccb4131c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/216-5acd01cbde4acda7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2330-c2f07246c8788af1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2375-3fcae5186c64fe6b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2929-617f1e66a55be184.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2977-e38442e86289f1d3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2982-2a2df543be3d2e5a.js +0 -25
- package/apps/pwa/out/_next/static/chunks/319-d37df1b6e0cbeff4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3403.4bc97b4066945a94.js +0 -5
- package/apps/pwa/out/_next/static/chunks/3441-a1dd4acfeda14488.js +0 -1
- package/apps/pwa/out/_next/static/chunks/371-4ad6af55dad02ced.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4114-3e63117452378807.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4836-3c93795ab834381e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5609-012bb3557211f07e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6090-1bd6077591603947.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6320-baac91d68843a9a6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6416-505ba707cacafbba.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6725-68ab7cc0b1faf00d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6998-a654fe5c58271600.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7457-f5cb1cc8db9f7453.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7647.2fcd30d894d5ee30.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7673-2eda1507d38dadb8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7990-e12efba616f46e03.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8067-f74bf14d67ad98f1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8142-011e1f474efb8b33.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8519-0059d82bdb4812bf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8619-4365e03a2862830f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/920-f7dceb78f1c585ef.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9651-3cd291a6fa1370d2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9740-52467f244755917f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9804-64c02c3c127d5014.js +0 -1
- package/apps/pwa/out/_next/static/chunks/ae787e4c-f2998de7f1ba72a4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-859cea1570b6227a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-21c3261af6ab377c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-1991445b8ea86274.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-4ebfaee2369fe248.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-ca7c3cc305c3285a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-9951930add3d2051.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-4de08d4b766f134b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-7a975e2b9db1dfb7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-859cea1570b6227a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-49270714ef35bb96.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-33fbdf353e2a5982.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-259f122e2dd64317.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-65b82726753658e1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-4b8df3748dc06285.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-542a5c0006da637c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-63ffb347831262ea.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-98e4e359d97263b4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-97e24ac675ce576e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-ac6391f26391d89d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-9f45c9d45ffc43bd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-36995b9cb5d98218.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-0c795b577988d63f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-b4311e2f71c6735a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-859cea1570b6227a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-eb2381074df20dba.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-b01336e64eba01ae.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-7af7f21c1f2858ef.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-a98ecd364586c89b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-57f0502dfbfa089b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-3467d2e1abd8a14a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-7842ca23d53ba682.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-ae9ac882912b0198.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-3a0d72e3f783bcef.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-f3b39fe8358c2a97.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-5a22af3181ac2afb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/framework-ea806bb57f2b8923.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-8d2302399c2c8f87.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-1457627bb302a22c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-b10928c60f0b8488.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-689039227d443fab.js +0 -1
- package/apps/pwa/out/_next/static/css/e66b7f5efc8df3f3.css +0 -1
- /package/apps/pwa/out/_next/static/{zoQX5iTvXOsIvCjxCe1Ji → ktMqfrBbf8BMGac0jqLrb}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// UX 녹화·캡처 공용 — 헤드리스 Chrome 하나를 띄워 CDP 로 몰고, 어떤 경로로 끝나도 Chrome 과 프로필을 치운다.
|
|
2
|
+
// 대표 상시지시: 측정·녹화 스크립트는 Chrome 을 반드시 죽인다(exit · SIGINT · SIGTERM · 전역 타임아웃 넷 다).
|
|
3
|
+
import { spawn, execFileSync } from 'node:child_process';
|
|
4
|
+
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
|
|
5
|
+
import { tmpdir } from 'node:os';
|
|
6
|
+
import { join } from 'node:path';
|
|
7
|
+
|
|
8
|
+
export const CHROME = process.env.UX_CHROME ?? '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome';
|
|
9
|
+
export const sleep = (ms: number) => new Promise<void>((r) => setTimeout(r, ms));
|
|
10
|
+
|
|
11
|
+
export type Cdp = {
|
|
12
|
+
send: (method: string, params?: object) => Promise<any>;
|
|
13
|
+
ev: <T = unknown>(expression: string) => Promise<T>;
|
|
14
|
+
click: (label: string, exact?: boolean) => Promise<string>;
|
|
15
|
+
png: (file: string) => Promise<void>;
|
|
16
|
+
close: () => void;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export async function launch(opts: { port: number; timeoutMs: number; width: number; height: number; dpr?: number; mobile?: boolean }): Promise<Cdp> {
|
|
20
|
+
const profile = mkdtempSync(join(tmpdir(), 'ux-cdp-'));
|
|
21
|
+
const chrome = spawn(CHROME, ['--headless=new', '--use-mock-keychain', '--password-store=basic', `--remote-debugging-port=${opts.port}`, `--user-data-dir=${profile}`, 'about:blank'], { stdio: 'ignore' });
|
|
22
|
+
const kill = () => { try { chrome.kill('SIGKILL'); } catch {} try { rmSync(profile, { recursive: true, force: true }); } catch {} };
|
|
23
|
+
process.on('exit', kill);
|
|
24
|
+
for (const s of ['SIGINT', 'SIGTERM'] as const) process.on(s, () => { kill(); process.exit(130); });
|
|
25
|
+
setTimeout(() => { console.error('global timeout'); kill(); process.exit(2); }, opts.timeoutMs).unref();
|
|
26
|
+
|
|
27
|
+
let ws = '';
|
|
28
|
+
for (let i = 0; i < 50 && !ws; i++) {
|
|
29
|
+
try { const l = (await (await fetch(`http://127.0.0.1:${opts.port}/json/list`)).json()) as Array<{ type: string; webSocketDebuggerUrl?: string }>; ws = l.find((t) => t.type === 'page')?.webSocketDebuggerUrl ?? ''; } catch {}
|
|
30
|
+
if (!ws) await sleep(200);
|
|
31
|
+
}
|
|
32
|
+
if (!ws) { kill(); throw new Error(`chrome did not expose a page on port ${opts.port}`); }
|
|
33
|
+
const sock = new WebSocket(ws);
|
|
34
|
+
await new Promise((r) => sock.addEventListener('open', r, { once: true }));
|
|
35
|
+
let id = 0;
|
|
36
|
+
const pend = new Map<number, (v: any) => void>();
|
|
37
|
+
sock.addEventListener('message', (m) => {
|
|
38
|
+
const x = JSON.parse(String(m.data));
|
|
39
|
+
if (x.id && pend.has(x.id)) { pend.get(x.id)!(x.result); pend.delete(x.id); }
|
|
40
|
+
if (x.method === 'Page.javascriptDialogOpening') sock.send(JSON.stringify({ id: ++id, method: 'Page.handleJavaScriptDialog', params: { accept: true } }));
|
|
41
|
+
});
|
|
42
|
+
const send = (method: string, params: object = {}) => new Promise<any>((res) => { const n = ++id; pend.set(n, res); sock.send(JSON.stringify({ id: n, method, params })); });
|
|
43
|
+
const ev = async <T,>(expression: string) => (await send('Runtime.evaluate', { returnByValue: true, awaitPromise: true, expression })).result?.value as T;
|
|
44
|
+
await send('Page.enable'); await send('Runtime.enable');
|
|
45
|
+
await send('Emulation.setDeviceMetricsOverride', { width: opts.width, height: opts.height, deviceScaleFactor: opts.dpr ?? 1, mobile: !!opts.mobile });
|
|
46
|
+
if (opts.mobile) await send('Emulation.setTouchEmulationEnabled', { enabled: true });
|
|
47
|
+
return {
|
|
48
|
+
send,
|
|
49
|
+
ev,
|
|
50
|
+
click: (label, exact = true) => ev<string>(`(()=>{const L=${JSON.stringify(label)}; const b=[...document.querySelectorAll('button,a,[role=button],summary')].find(e=>${exact ? 'e.textContent.trim()===L' : 'e.textContent.trim().includes(L)'}); if(!b) return 'missing'; b.scrollIntoView({block:'center'}); b.click(); return 'ok'})()`),
|
|
51
|
+
png: async (file) => { const r = await send('Page.captureScreenshot', { format: 'png' }); writeFileSync(file, Buffer.from(r.data, 'base64')); },
|
|
52
|
+
close: () => { try { sock.close(); } catch {} kill(); },
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** 공개 캡처 누설 점검 — `?capture=public` 화면에 남으면 안 되는 모양을 센다(값은 출력하지 않는다). */
|
|
57
|
+
export const PUBLIC_LEAK_CHECK = `(()=>{const t=document.body.innerText; const bad=[]; if(/\\/Users\\//.test(t)) bad.push('/Users/'); if(/\\$\\s?\\d/.test(t)) bad.push('USD'); if(/\\bmsb\\d+\\b/.test(t)) bad.push('msbN'); if(/\\.ts\\.net\\b/.test(t)) bad.push('ts.net'); if(/elt_[A-Za-z0-9_-]{16,}/.test(t)) bad.push('token'); return JSON.stringify({publicOn: t.includes('공개 캡처 켜짐'), bad, len: t.length})})()`;
|
|
58
|
+
|
|
59
|
+
/** 프레임(실제 촬영 시각)을 간격 그대로 mp4 로 — 상수 fps 가정 없이. */
|
|
60
|
+
export class Frames {
|
|
61
|
+
readonly dir: string;
|
|
62
|
+
readonly list: { f: string; t: number }[] = [];
|
|
63
|
+
constructor(outDir: string) { this.dir = join(outDir, 'frames'); mkdirSync(this.dir, { recursive: true }); }
|
|
64
|
+
add(base64Jpeg: string, t = Date.now() / 1000) { const f = join(this.dir, `f${String(this.list.length).padStart(5, '0')}.jpg`); writeFileSync(f, Buffer.from(base64Jpeg, 'base64')); this.list.push({ f, t }); }
|
|
65
|
+
toMp4(mp4: string, w: number, h: number) {
|
|
66
|
+
const lines: string[] = [];
|
|
67
|
+
for (let i = 0; i < this.list.length; i++) { const d = i + 1 < this.list.length ? Math.max(0.001, this.list[i + 1].t - this.list[i].t) : 0.04; lines.push(`file '${this.list[i].f}'`, `duration ${d.toFixed(4)}`); }
|
|
68
|
+
if (this.list.length) lines.push(`file '${this.list[this.list.length - 1].f}'`);
|
|
69
|
+
const txt = join(this.dir, '..', 'frames.txt'); writeFileSync(txt, lines.join('\n'));
|
|
70
|
+
execFileSync('ffmpeg', ['-y', '-loglevel', 'error', '-f', 'concat', '-safe', '0', '-i', txt, '-vf', `fps=30,scale=${w}:${h}:force_original_aspect_ratio=decrease,pad=${w}:${h}:(ow-iw)/2:(oh-ih)/2`, '-c:v', 'libx264', '-pix_fmt', 'yuv420p', '-crf', '16', mp4]);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// PWA 한 화면 실녹화 · 캡처 (UX 자리 · 내부 문서 `UX` §3).
|
|
2
|
+
// 사용:
|
|
3
|
+
// bun scripts/ux/record-page.ts --url http://127.0.0.1:<port>/app/board/ --out <dir> [--secs 20] [--size 1920x1080]
|
|
4
|
+
// [--mobile] (390x844 @3x 터치) [--type "<한 줄>"] (textarea 에 쳐서 Enter) [--shot] (PNG 한 장만)
|
|
5
|
+
// [--token-stdin] (단기 소유자 토큰을 표준 입력으로만 받는다 — 값은 출력하지 않는다)
|
|
6
|
+
// ⭐ URL 에 `capture=public` 을 자동으로 붙이고 15초마다 누설 점검 줄을 찍는다(bad 가 비어 있어야 공개 후보).
|
|
7
|
+
// ⛔ 공개는 이 산출이 아니라 1fps 전수 OCR(TC) 통과 뒤다.
|
|
8
|
+
import { mkdirSync } from 'node:fs';
|
|
9
|
+
import { join } from 'node:path';
|
|
10
|
+
import { Frames, launch, PUBLIC_LEAK_CHECK, sleep } from './lib/cdp.js';
|
|
11
|
+
|
|
12
|
+
const arg = (k: string) => { const i = process.argv.indexOf(`--${k}`); return i > 0 ? process.argv[i + 1] : undefined; };
|
|
13
|
+
const flag = (k: string) => process.argv.includes(`--${k}`);
|
|
14
|
+
const rawUrl = arg('url'); const out = arg('out');
|
|
15
|
+
if (!rawUrl || !out) { console.error('usage: --url <url> --out <dir> [--secs N] [--size WxH] [--mobile] [--type text] [--shot] [--token-stdin]'); process.exit(64); }
|
|
16
|
+
const mobile = flag('mobile');
|
|
17
|
+
const [W, H] = mobile ? [390, 844] : (arg('size') ?? '1920x1080').split('x').map(Number);
|
|
18
|
+
const DPR = mobile ? 3 : 1; const SECS = Number(arg('secs') ?? 20);
|
|
19
|
+
const u = new URL(rawUrl); u.searchParams.set('capture', 'public');
|
|
20
|
+
mkdirSync(out, { recursive: true });
|
|
21
|
+
|
|
22
|
+
const cdp = await launch({ port: 9480 + Math.floor(Math.random() * 15), timeoutMs: (SECS + 180) * 1000, width: W, height: H, dpr: DPR, mobile });
|
|
23
|
+
if (flag('token-stdin')) {
|
|
24
|
+
const temp = /elt_[A-Za-z0-9_-]{16,}/.exec(await Bun.stdin.text())?.[0] ?? '';
|
|
25
|
+
console.log('token', temp ? 'received' : 'none');
|
|
26
|
+
if (temp) { await cdp.send('Page.navigate', { url: `${u.origin}/app/` }); await sleep(3000); await cdp.ev(`localStorage.setItem('elanous.daemon.token', ${JSON.stringify(temp)})`); }
|
|
27
|
+
}
|
|
28
|
+
await cdp.send('Page.navigate', { url: u.toString() }); await sleep(8000);
|
|
29
|
+
const check = async (tag: string) => console.log(tag, await cdp.ev<string>(PUBLIC_LEAK_CHECK));
|
|
30
|
+
await check('before');
|
|
31
|
+
if (flag('shot')) { const f = join(out, `shot-${W}x${H}.png`); await cdp.png(f); console.log('png', f); cdp.close(); process.exit(0); }
|
|
32
|
+
|
|
33
|
+
const frames = new Frames(out); let recording = true;
|
|
34
|
+
const loop = (async () => { let last = Date.now(); while (recording) { const s = await cdp.send('Page.captureScreenshot', { format: 'jpeg', quality: 92 }); frames.add(s.data); if (Date.now() - last > 15_000) { last = Date.now(); await check('mid'); } } })();
|
|
35
|
+
const text = arg('type');
|
|
36
|
+
if (text) {
|
|
37
|
+
await sleep(800);
|
|
38
|
+
await cdp.ev(`document.querySelector('textarea')?.focus()`);
|
|
39
|
+
for (const ch of [...text]) { await cdp.send('Input.insertText', { text: ch }); await sleep(55); }
|
|
40
|
+
await sleep(500);
|
|
41
|
+
for (const type of ['keyDown', 'keyUp']) await cdp.send('Input.dispatchKeyEvent', { type, key: 'Enter', code: 'Enter', windowsVirtualKeyCode: 13 });
|
|
42
|
+
await sleep(3500);
|
|
43
|
+
} else await sleep(SECS * 1000);
|
|
44
|
+
recording = false; await loop;
|
|
45
|
+
await check('after');
|
|
46
|
+
cdp.close();
|
|
47
|
+
const mp4 = join(out, `rec-${W * DPR}x${H * DPR}.mp4`);
|
|
48
|
+
frames.toMp4(mp4, W * DPR, H * DPR);
|
|
49
|
+
console.log('frames', frames.list.length, 'mp4', mp4);
|
|
50
|
+
process.exit(0);
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: explainer-video
|
|
3
|
+
description: Make a narrated «N things at once» explainer video from a list of facts — a script in a fixed grammar, word-timed Korean or English voice-over (ElevenLabs), line-art diagrams that advance one step per spoken line, and a checked HyperFrames render. Use when someone asks to summarise a release, an event or a list of changes as a short explainer video.
|
|
4
|
+
requires: []
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Explainer video
|
|
8
|
+
|
|
9
|
+
You turn a list of facts into one continuous explainer: a header with progress dots, a black card before each chapter, a line-art diagram on the left that moves one step per spoken line, and on the right the chapter number, title, subtitle, a short rule and a one-line caption whose keywords light up **at the moment they are spoken**. A progress bar runs along the bottom.
|
|
10
|
+
|
|
11
|
+
`$SKILL` is this folder. Work in a project folder of your own (never inside `$SKILL`).
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
<project>/script.json ─▶ bun $SKILL/engine/vo.ts ─▶ node $SKILL/engine/build.mjs ─▶ <project>/hf/ ─▶ hyperframes check · snapshot · render ─▶ QC
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## 1. Write `script.json`
|
|
18
|
+
|
|
19
|
+
Copy `examples/elanous-0.2.5/script.json` and replace the content. Shape:
|
|
20
|
+
|
|
21
|
+
- `title`, `voice` (`id`, `model`), `sources` (where every claim comes from).
|
|
22
|
+
- `intro.beats`, `chapters[] { title, sub, diagram, beats[] }`, `outro { beats, cta { line, links } }`.
|
|
23
|
+
- A beat is `{ vo, cap, hl? }`:
|
|
24
|
+
- `vo` is what is **spoken**. Write names the voice can't read in the way it should say them (`plugin add` → «플러그인 애드»).
|
|
25
|
+
- `cap` is what is **shown**. Wrap keywords in `**…**`.
|
|
26
|
+
- `hl` maps a shown keyword to the spoken word that lights it: `[["elanous-basics", "베이직스"]]`. When omitted, the keyword's first word is looked up in `vo`.
|
|
27
|
+
- `diagram` is one of `mission`, `terminal`, `nodes`, `keys` or `approve`. The intro always uses `agenda` and the outro uses `summary`.
|
|
28
|
+
|
|
29
|
+
The grammar of a chapter (take it from the reference, don't improvise):
|
|
30
|
+
|
|
31
|
+
1. **Name it** — «N번째는 X입니다».
|
|
32
|
+
2. **Say it plainly** — one line on what it is.
|
|
33
|
+
3. **Show one concrete case** — «예를 들어 …», or the real first run.
|
|
34
|
+
4. **Contrast** — «(before) … 였다면, (now) …».
|
|
35
|
+
|
|
36
|
+
The outro gives one line that sums everything up, then the CTA.
|
|
37
|
+
|
|
38
|
+
⛔ Every claim must trace to a merged change or a measured run, listed in `sources`. Don't write «fully autonomous», dates you can't promise, or comparisons (`docs/marketing/GUIDE-launch-tone-and-banned-claims-*`).
|
|
39
|
+
|
|
40
|
+
## 2. Voice — `bun $SKILL/engine/vo.ts <project>/script.json`
|
|
41
|
+
|
|
42
|
+
- Makes one `/with-timestamps` call per beat and writes `source/vo/<key>.mp3` and `<key>.json`, where the JSON holds per-character times.
|
|
43
|
+
- A beat whose text hash is unchanged is skipped, so you can edit one line and re-run.
|
|
44
|
+
- The key comes from `ELEVENLABS_API_KEY`, which the plugin connector sets (`elanous plugin credentials video-explainer`). Never print it.
|
|
45
|
+
|
|
46
|
+
## 3. Compose — `node $SKILL/engine/build.mjs <project>/script.json`
|
|
47
|
+
|
|
48
|
+
- **Timing comes from the voice, not from guesses:**
|
|
49
|
+
- a beat lasts its speech plus 0.45 s;
|
|
50
|
+
- the last beat of a chapter gets another 0.8 s;
|
|
51
|
+
- a chapter card lasts 1.8 s;
|
|
52
|
+
- the CTA lasts 4.5 s.
|
|
53
|
+
- **Diagram steps** start at their beat.
|
|
54
|
+
- **Keywords** turn red at the spoken character time.
|
|
55
|
+
- **Audio**: each beat is its own `<audio>` clip; the renderer mixes them.
|
|
56
|
+
- **Assets**: fonts (Pretendard, Geist Mono; OFL) and GSAP are fetched once into `EXPLAINER_CACHE` (default `~/.cache/elanous-explainer`).
|
|
57
|
+
- **Output**: `<project>/hf/` (a HyperFrames project) and `<project>/timeline.json`.
|
|
58
|
+
|
|
59
|
+
## 4. Check, look, render
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
cd <project>/hf
|
|
63
|
+
npx hyperframes check # must pass: 0 errors (layout · contrast · lint)
|
|
64
|
+
npx hyperframes snapshot --no-end --at <one time per chapter> -o ../snap # look at the contact sheet yourself
|
|
65
|
+
npx hyperframes render --fps 30 --output ../out/<name>-16x9.mp4
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
If something wraps, overlaps or is off-frame, fix the component in `build.mjs` and rebuild. Don't patch `hf/index.html` by hand — it is regenerated.
|
|
69
|
+
|
|
70
|
+
## 5. QC before you hand it over
|
|
71
|
+
|
|
72
|
+
- **Speech equals script**: transcribe the render back (`whisper … --language ko`) and compare with the joined `vo` text. Anything under about 0.97 means a word was misread. Re-write that beat's `vo` and re-run step 2 (only that beat is regenerated).
|
|
73
|
+
- **Loudness**: integrated about −14 LUFS, true peak ≤ −1 dBTP (`ffmpeg -af loudnorm=print_format=summary`).
|
|
74
|
+
- **Side by side**: if there is a reference video, put matching frames next to each other and check that it reads in the same grammar.
|
|
75
|
+
- **Before anything goes public**: run a full 1 fps OCR for private names, home paths, accounts and device names. Publishing is a human decision.
|
|
76
|
+
|
|
77
|
+
## Look — Elanvital CI only
|
|
78
|
+
|
|
79
|
+
The reference supplies the **grammar** (components and staging), never its colours or artwork.
|
|
80
|
+
|
|
81
|
+
- **Ground**: Deepsea Blu `#1D2751`.
|
|
82
|
+
- **Accent**: **Icarus Red `#E95047`**, the only accent.
|
|
83
|
+
- **Chapter cards and CTA**: Real Black.
|
|
84
|
+
- **Text**: `#F2F1EE`.
|
|
85
|
+
- **Motif**: the V6 «엘랑 소용돌이» mark (`engine/brand/`), used in three places — a slow, faint rotation behind the scene, the header, and the chapter cards.
|
|
86
|
+
|
|
87
|
+
Why these choices, what the reference does, and what we can and cannot reproduce: `내부 문서 `RESEARCH-explainer-video-reference-decomposition-2026-09-30``.
|
|
88
|
+
|
|
89
|
+
## Graph
|
|
90
|
+
|
|
91
|
+
`graphs/video/explainer-line.yaml`:
|
|
92
|
+
|
|
93
|
+
- **Flow**: script → vo → build → render (the existing `hyperframes-render` recipe) → qc.
|
|
94
|
+
- **Edges back**:
|
|
95
|
+
- layout fault → build;
|
|
96
|
+
- speech mismatch → vo;
|
|
97
|
+
- bad script → script;
|
|
98
|
+
- public release → needs-human.
|
|
99
|
+
- **Not coded yet**: the `explainer-*` recipes. Until they are, you run these steps from this skill.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="150 150 724 724"><path d="M842 512 L838.6 517.2 L835.4 522.4 L832.2 527.5 L828.9 532.5 L825.7 537.4 L822.4 542.2 L819 547 L815.7 551.6 L812.2 556.1 L808.8 560.5 L805.3 564.8 L801.7 569 L798.2 573.1 L794.5 577.1 L790.9 581 L787.2 584.8 L783.5 588.5 L779.7 592.1 L776 595.6 L772.2 599 L768.4 602.3 L764.5 605.5 L760.7 608.6 L756.8 611.6 L752.9 614.5 L749 617.4 L745.1 620.1 L741.2 622.7 L737.3 625.2 L733.4 627.7 L729.5 630 L725.6 632.3 L721.7 634.5 L717.8 636.6 L713.9 638.6 L710 640.5 L706.1 642.3 L702.2 644.1 L698.3 645.8 L694.5 647.4 L690.7 648.9 L686.9 650.3 L683.1 651.7 L679.3 653 L675.5 654.2 L671.8 655.4 L668.1 656.5 L664.4 657.5 L660.7 658.5 L657.1 659.3 L653.5 660.2 L649.9 661 L646.3 661.7 L642.8 662.3 L639.3 662.9 L635.8 663.5 L632.4 664 L629 664.4 L625.6 664.8 L622.2 665.2 L618.9 665.5 L615.6 665.7 L612.4 665.9 L609.1 666.1 L605.9 666.2 L602.8 666.3 L599.6 666.4 L596.5 666.4 L593.4 666.4 L590.4 666.3 L587.4 666.2 L584.4 666.1 L581.4 666 L578.5 665.8 L575.6 665.6 L572.7 665.3 L569.9 665.1 L567 664.8 L564.2 664.5 L561.5 664.1 L558.7 663.7 L556 663.4 L553.3 663 L550.6 662.5 L548 662.1 L545.4 661.6 L542.8 661.1 L540.2 660.6 L537.6 660.1 L535.1 659.5 L532.5 658.9 L530 658.3 L527.5 657.7 L525.1 657.1 L522.6 656.5 L520.2 655.8 L517.7 655.1 L515.3 654.4 L512.9 653.7 L510.5 653 L508.2 652.2 L505.8 651.4 L503.5 650.6 L501.1 649.8 L498.8 649 L496.5 648.1 L494.2 647.3 L491.9 646.4 L489.6 645.5 L487.3 644.5 L485.1 643.6 L482.8 642.6 L480.6 641.6 L478.3 640.6 L476.1 639.5 L473.9 638.4 L471.7 637.3 L469.5 636.2 L467.3 635 L465.1 633.9 L462.9 632.6 L460.7 631.4 L458.6 630.1 L456.4 628.8 L454.3 627.5 L452.2 626.1 L450 624.7 L447.9 623.3 L445.8 621.9 L443.8 620.4 L441.7 618.8 L439.6 617.3 L437.6 615.7 L435.6 614 L433.6 612.3 L431.6 610.6 L429.6 608.9 L427.6 607.1 L425.7 605.2 L423.8 603.4 L421.9 601.4 L420 599.5 L418.1 597.5 L416.3 595.4 L414.5 593.3 L412.7 591.2 L410.9 589 L409.2 586.8 L407.5 584.6 L405.8 582.3 L404.1 579.9 L402.5 577.5 L400.9 575.1 L399.3 572.6 L397.8 570 L396.2 567.4 L394.7 564.8 L393.2 562.1 L391.6 559.3 L389.8 556.5 L389.8 556.5 L387.3 558.7 L385.1 561.2 L383 563.7 L381.1 566.4 L379.3 569.1 L377.5 572 L375.8 574.9 L374.3 577.9 L372.8 581.1 L371.4 584.2 L370.1 587.5 L368.9 590.9 L367.8 594.3 L366.8 597.7 L365.8 601.3 L365 604.9 L364.3 608.6 L363.7 612.3 L363.2 616.1 L362.8 619.9 L362.5 623.8 L362.3 627.7 L362.2 631.7 L362.3 635.7 L362.4 639.7 L362.7 643.8 L363.1 647.9 L363.6 652 L364.2 656.1 L364.9 660.3 L365.8 664.4 L366.7 668.6 L367.8 672.8 L369 677 L370.4 681.1 L371.8 685.3 L373.4 689.5 L375.1 693.6 L377 697.8 L378.9 701.9 L381 706 L383.2 710.1 L385.5 714.1 L387.9 718.1 L390.5 722.1 L393.1 726 L395.9 729.9 L398.8 733.7 L401.8 737.5 L405 741.3 L408.2 744.9 L411.6 748.5 L415 752.1 L418.6 755.6 L422.3 759 L426.1 762.3 L430 765.5 L434 768.7 L438.1 771.8 L442.3 774.8 L446.5 777.7 L450.9 780.5 L455.4 783.3 L459.9 785.9 L464.6 788.4 L469.3 790.9 L474.1 793.2 L479 795.4 L483.9 797.5 L488.9 799.5 L494 801.4 L499.2 803.1 L504.4 804.8 L509.7 806.3 L515 807.7 L520.4 809 L525.8 810.2 L531.3 811.2 L536.8 812.1 L542.4 812.9 L548 813.5 L553.6 814.1 L559.3 814.5 L565 814.7 L570.7 814.8 L576.4 814.8 L582.2 814.7 L587.9 814.4 L593.7 814 L599.5 813.4 L605.3 812.8 L611 811.9 L616.8 811 L622.6 809.9 L628.3 808.7 L634 807.3 L639.8 805.8 L645.5 804.2 L651.1 802.4 L656.8 800.5 L662.4 798.5 L667.9 796.3 L673.5 794 L678.9 791.6 L684.4 789.1 L689.8 786.4 L695.1 783.6 L700.4 780.7 L705.6 777.6 L710.8 774.5 L715.9 771.2 L720.9 767.8 L725.9 764.3 L730.8 760.7 L735.6 756.9 L740.4 753.1 L745 749.1 L749.6 745 L754.1 740.9 L758.5 736.6 L762.8 732.2 L767 727.8 L771.2 723.2 L775.2 718.5 L779.1 713.8 L782.9 709 L786.7 704.1 L790.3 699.1 L793.8 694 L797.2 688.8 L800.5 683.6 L803.7 678.3 L806.8 672.9 L809.7 667.5 L812.6 662 L815.3 656.4 L817.9 650.8 L820.4 645.1 L822.8 639.4 L825 633.6 L827.2 627.8 L829.2 621.9 L831 616 L832.8 610.1 L834.4 604.1 L835.9 598.1 L837.3 592.1 L838.5 586 L839.6 579.9 L840.6 573.8 L841.4 567.7 L842.1 561.5 L842.7 555.4 L843.1 549.2 L843.4 543 L843.5 536.8 L843.5 530.6 L843.2 524.4 L842.8 518.2 L842 512.0Z" fill="#F2F1EE"/><path d="M347 797.8 L344.2 792.2 L341.3 786.8 L338.5 781.5 L335.8 776.2 L333.1 770.9 L330.6 765.7 L328.2 760.4 L325.9 755.2 L323.7 750 L321.6 744.8 L319.6 739.6 L317.8 734.4 L316 729.3 L314.4 724.1 L312.8 719 L311.4 713.9 L310 708.9 L308.8 703.8 L307.6 698.8 L306.6 693.8 L305.6 688.9 L304.8 683.9 L304 679 L303.3 674.2 L302.7 669.4 L302.2 664.6 L301.8 659.9 L301.5 655.2 L301.3 650.5 L301.1 645.9 L301 641.3 L301 636.8 L301.1 632.3 L301.2 627.9 L301.5 623.5 L301.7 619.2 L302.1 614.9 L302.5 610.7 L303 606.5 L303.5 602.4 L304.1 598.3 L304.8 594.3 L305.5 590.3 L306.2 586.4 L307.1 582.5 L307.9 578.7 L308.8 574.9 L309.8 571.2 L310.8 567.6 L311.8 564 L312.9 560.4 L314.1 556.9 L315.2 553.5 L316.4 550.1 L317.6 546.8 L318.9 543.5 L320.2 540.3 L321.5 537.1 L322.9 534 L324.2 530.9 L325.6 527.9 L327.1 524.9 L328.5 522 L330 519.1 L331.5 516.2 L333 513.4 L334.5 510.7 L336 508 L337.6 505.3 L339.2 502.7 L340.7 500.2 L342.3 497.6 L344 495.1 L345.6 492.7 L347.2 490.3 L348.9 487.9 L350.5 485.6 L352.2 483.3 L353.8 481 L355.5 478.8 L357.2 476.6 L358.9 474.4 L360.6 472.3 L362.3 470.2 L364 468.1 L365.8 466.1 L367.5 464.1 L369.2 462.1 L371 460.2 L372.7 458.2 L374.5 456.3 L376.3 454.4 L378 452.6 L379.8 450.8 L381.6 449 L383.4 447.2 L385.2 445.4 L387 443.7 L388.8 442 L390.7 440.3 L392.5 438.6 L394.3 436.9 L396.2 435.3 L398.1 433.7 L400 432.1 L401.8 430.5 L403.8 428.9 L405.7 427.4 L407.6 425.9 L409.6 424.4 L411.5 422.9 L413.5 421.4 L415.5 420 L417.5 418.6 L419.5 417.2 L421.6 415.8 L423.6 414.4 L425.7 413.1 L427.8 411.7 L429.9 410.4 L432.1 409.2 L434.2 407.9 L436.4 406.7 L438.6 405.5 L440.8 404.3 L443.1 403.1 L445.3 402 L447.6 400.9 L449.9 399.8 L452.3 398.7 L454.6 397.7 L457 396.7 L459.4 395.7 L461.9 394.8 L464.3 393.9 L466.8 393 L469.3 392.2 L471.9 391.4 L474.4 390.6 L477 389.9 L479.6 389.2 L482.3 388.6 L484.9 388 L487.6 387.4 L490.3 386.9 L493.1 386.4 L495.8 385.9 L498.6 385.5 L501.4 385.2 L504.3 384.9 L507.1 384.6 L510 384.4 L512.9 384.3 L515.9 384.1 L518.9 384.1 L521.9 384 L524.9 384 L528 384.1 L531.2 384.1 L534.6 384 L534.6 384 L533.9 380.6 L532.9 377.5 L531.7 374.5 L530.4 371.4 L528.9 368.5 L527.3 365.5 L525.6 362.6 L523.8 359.7 L521.8 356.9 L519.7 354.1 L517.6 351.3 L515.3 348.6 L512.9 346 L510.4 343.3 L507.8 340.8 L505 338.3 L502.2 335.8 L499.3 333.4 L496.3 331.1 L493.2 328.8 L489.9 326.6 L486.6 324.5 L483.3 322.4 L479.8 320.5 L476.2 318.6 L472.5 316.8 L468.8 315.1 L465 313.5 L461.1 311.9 L457.1 310.5 L453.1 309.1 L449 307.9 L444.8 306.8 L440.6 305.7 L436.3 304.8 L432 304 L427.6 303.2 L423.1 302.6 L418.6 302.2 L414.1 301.8 L409.5 301.5 L404.9 301.4 L400.2 301.4 L395.5 301.5 L390.8 301.7 L386.1 302 L381.3 302.5 L376.6 303.1 L371.8 303.8 L367 304.7 L362.2 305.7 L357.4 306.8 L352.6 308 L347.8 309.4 L343 310.8 L338.2 312.5 L333.4 314.2 L328.7 316.1 L324 318.1 L319.3 320.2 L314.6 322.4 L310 324.8 L305.4 327.3 L300.8 330 L296.3 332.7 L291.9 335.6 L287.4 338.6 L283.1 341.7 L278.8 344.9 L274.5 348.3 L270.4 351.7 L266.3 355.3 L262.2 359 L258.3 362.8 L254.4 366.7 L250.6 370.8 L246.9 374.9 L243.2 379.1 L239.7 383.5 L236.2 387.9 L232.9 392.4 L229.6 397 L226.4 401.7 L223.3 406.5 L220.4 411.4 L217.5 416.4 L214.8 421.4 L212.1 426.6 L209.6 431.8 L207.2 437 L204.9 442.4 L202.7 447.8 L200.7 453.3 L198.7 458.8 L196.9 464.4 L195.2 470 L193.7 475.7 L192.2 481.5 L190.9 487.3 L189.8 493.1 L188.7 499 L187.8 504.9 L187 510.8 L186.4 516.8 L185.9 522.7 L185.5 528.8 L185.2 534.8 L185.1 540.8 L185.1 546.9 L185.3 552.9 L185.6 559 L186 565 L186.6 571.1 L187.3 577.2 L188.1 583.2 L189.1 589.2 L190.2 595.2 L191.4 601.2 L192.8 607.2 L194.2 613.2 L195.9 619.1 L197.6 625 L199.5 630.8 L201.5 636.7 L203.7 642.4 L205.9 648.2 L208.3 653.8 L210.9 659.5 L213.5 665.1 L216.3 670.6 L219.1 676.1 L222.1 681.5 L225.2 686.8 L228.5 692.1 L231.8 697.3 L235.3 702.5 L238.8 707.5 L242.5 712.5 L246.3 717.5 L250.1 722.3 L254.1 727 L258.2 731.7 L262.4 736.3 L266.7 740.8 L271 745.2 L275.5 749.5 L280 753.7 L284.7 757.8 L289.4 761.8 L294.2 765.7 L299.1 769.4 L304.1 773.1 L309.1 776.7 L314.3 780.1 L319.5 783.5 L324.8 786.7 L330.1 789.7 L335.6 792.6 L341.2 795.4 L347 797.8Z" fill="#F2F1EE"/><path d="M347 226.2 L353.2 226.6 L359.3 226.8 L365.4 227 L371.3 227.3 L377.2 227.6 L383 228.1 L388.7 228.6 L394.4 229.2 L400 229.9 L405.6 230.7 L411.1 231.6 L416.5 232.6 L421.8 233.6 L427.1 234.8 L432.3 236 L437.5 237.3 L442.5 238.6 L447.5 240.1 L452.4 241.6 L457.3 243.2 L462 244.8 L466.7 246.6 L471.3 248.3 L475.9 250.2 L480.3 252.1 L484.7 254 L489 256.1 L493.3 258.1 L497.4 260.3 L501.5 262.4 L505.5 264.6 L509.4 266.9 L513.2 269.2 L517 271.5 L520.7 273.9 L524.3 276.3 L527.8 278.8 L531.3 281.2 L534.7 283.7 L538 286.3 L541.2 288.8 L544.4 291.4 L547.5 294 L550.5 296.6 L553.4 299.3 L556.3 301.9 L559.1 304.6 L561.8 307.3 L564.5 310 L567.1 312.7 L569.6 315.4 L572 318.1 L574.4 320.8 L576.8 323.6 L579.1 326.3 L581.3 329 L583.4 331.7 L585.5 334.5 L587.5 337.2 L589.5 339.9 L591.4 342.7 L593.3 345.4 L595.1 348.1 L596.9 350.8 L598.6 353.5 L600.3 356.2 L601.9 358.9 L603.4 361.6 L605 364.3 L606.4 367 L607.9 369.6 L609.3 372.3 L610.6 374.9 L611.9 377.5 L613.2 380.1 L614.4 382.8 L615.6 385.4 L616.8 387.9 L617.9 390.5 L619 393.1 L620.1 395.7 L621.1 398.2 L622.1 400.7 L623 403.3 L624 405.8 L624.9 408.3 L625.7 410.8 L626.6 413.3 L627.4 415.8 L628.2 418.3 L629 420.8 L629.7 423.2 L630.4 425.7 L631.1 428.1 L631.8 430.6 L632.4 433 L633.1 435.5 L633.7 437.9 L634.2 440.3 L634.8 442.8 L635.3 445.2 L635.8 447.6 L636.3 450.1 L636.8 452.5 L637.2 454.9 L637.7 457.4 L638.1 459.8 L638.4 462.2 L638.8 464.7 L639.1 467.1 L639.4 469.5 L639.7 472 L639.9 474.4 L640.2 476.9 L640.4 479.3 L640.5 481.8 L640.7 484.3 L640.8 486.7 L640.9 489.2 L641 491.7 L641 494.2 L641 496.7 L641 499.2 L641 501.7 L640.9 504.2 L640.8 506.7 L640.6 509.3 L640.4 511.8 L640.2 514.4 L640 516.9 L639.7 519.5 L639.3 522 L639 524.6 L638.6 527.2 L638.1 529.8 L637.6 532.4 L637.1 534.9 L636.5 537.5 L635.9 540.1 L635.2 542.7 L634.5 545.4 L633.8 548 L633 550.6 L632.1 553.2 L631.2 555.8 L630.3 558.4 L629.3 561 L628.2 563.6 L627.1 566.2 L625.9 568.9 L624.7 571.5 L623.5 574.1 L622.2 576.7 L620.8 579.3 L619.4 581.9 L617.9 584.5 L616.4 587.2 L614.8 589.8 L613.2 592.6 L611.6 595.6 L611.6 595.6 L614.8 596.6 L618 597.3 L621.3 597.8 L624.5 598.2 L627.9 598.4 L631.2 598.5 L634.6 598.5 L638 598.3 L641.4 598 L644.9 597.6 L648.3 597.1 L651.8 596.5 L655.4 595.8 L658.9 594.9 L662.4 593.9 L665.9 592.8 L669.5 591.6 L673 590.3 L676.5 588.8 L680.1 587.3 L683.6 585.6 L687.1 583.8 L690.5 581.9 L694 579.8 L697.4 577.7 L700.8 575.4 L704.1 573.1 L707.4 570.6 L710.7 568 L713.9 565.3 L717.1 562.4 L720.3 559.5 L723.3 556.5 L726.3 553.3 L729.3 550.1 L732.2 546.7 L735 543.3 L737.7 539.7 L740.4 536.1 L743 532.3 L745.5 528.5 L748 524.5 L750.3 520.5 L752.6 516.4 L754.7 512.2 L756.8 507.9 L758.7 503.6 L760.6 499.1 L762.4 494.6 L764.1 490.1 L765.6 485.4 L767.1 480.7 L768.4 475.9 L769.6 471.1 L770.7 466.2 L771.7 461.2 L772.6 456.3 L773.3 451.2 L774 446.1 L774.5 441 L774.9 435.8 L775.1 430.6 L775.2 425.4 L775.2 420.1 L775.1 414.9 L774.9 409.6 L774.5 404.2 L773.9 398.9 L773.3 393.6 L772.5 388.2 L771.6 382.9 L770.5 377.5 L769.4 372.2 L768.1 366.9 L766.6 361.5 L765 356.2 L763.3 350.9 L761.5 345.7 L759.5 340.4 L757.4 335.2 L755.1 330 L752.8 324.9 L750.3 319.8 L747.7 314.8 L744.9 309.7 L742 304.8 L739 299.9 L735.9 295 L732.7 290.2 L729.3 285.5 L725.8 280.9 L722.2 276.3 L718.5 271.7 L714.7 267.3 L710.8 262.9 L706.7 258.7 L702.6 254.5 L698.3 250.3 L693.9 246.3 L689.5 242.4 L684.9 238.5 L680.3 234.8 L675.5 231.2 L670.7 227.6 L665.8 224.2 L660.8 220.8 L655.7 217.6 L650.5 214.5 L645.2 211.5 L639.9 208.6 L634.5 205.8 L629.1 203.2 L623.5 200.6 L617.9 198.2 L612.3 195.9 L606.6 193.7 L600.8 191.7 L595 189.7 L589.2 187.9 L583.3 186.2 L577.3 184.7 L571.3 183.3 L565.3 182 L559.3 180.8 L553.2 179.8 L547.1 178.9 L541 178.1 L534.8 177.5 L528.7 177 L522.5 176.6 L516.3 176.3 L510.2 176.2 L504 176.2 L497.8 176.4 L491.6 176.7 L485.4 177.1 L479.2 177.7 L473.1 178.3 L466.9 179.1 L460.8 180.1 L454.7 181.2 L448.6 182.4 L442.6 183.7 L436.6 185.1 L430.6 186.7 L424.6 188.4 L418.7 190.3 L412.8 192.2 L407 194.3 L401.2 196.6 L395.5 198.9 L389.8 201.4 L384.2 204 L378.7 206.7 L373.2 209.5 L367.7 212.5 L362.4 215.6 L357.1 218.9 L352 222.4 L347 226.2Z" fill="#F2F1EE"/><circle cx="512" cy="512" r="62" fill="#E95047"/></svg>
|