elanous 0.2.10 → 0.2.12
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/apps/pwa/out/404/index.html +1 -1
- package/apps/pwa/out/404.html +1 -1
- package/apps/pwa/out/_next/static/-6XrAoD3eU7NyMHAE4xPS/_buildManifest.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1147-466ec15afacc1a65.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1159-0c5ef8bc21cb6afb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1394-ee3795b112907122.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1452.93700483b9d4fc61.js +9 -0
- package/apps/pwa/out/_next/static/chunks/{6062-73e68343a9814f6a.js → 1829-b453a1b22d3999bb.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2176-c379e3ebce874151.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2426.8c6ee0c668d53def.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3170-7ec60a56fa0e4728.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3278-ae6ef084769f6195.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3454-988a53dac60a1763.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3638-aa80b4641ea439db.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3735-fe3402553ac1c9c6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3869-3cd46526879f454c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/390.c373e31b3b9d0c41.js +5 -0
- package/apps/pwa/out/_next/static/chunks/3992-2e522a8ac5f2afde.js +25 -0
- package/apps/pwa/out/_next/static/chunks/4215-c9d91dd644ec1719.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4508-5d0161d1e724d735.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4685-c3c1c625b71accd1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4733-623a79345b171e1c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4883.3bd969ea1d3aaaff.js +2 -0
- package/apps/pwa/out/_next/static/chunks/5532.6899a12958a89b72.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8067-87ce253ec2f23697.js → 5845-e6c003ce8d5fd36a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5978-b27004c677119115.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8046cadf-211ca3c0e00f2b72.js → 5cd7e3a9-404fd6b8d0ecd44c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/6048-4c5c33579bc4ef78.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6303-422dbf0f67c72aac.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6751-bb3595948b2e311b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7274-19b7279f18b47ab3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7277-0b2fc7c16ba2d64b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4323.c5dfb6f503304775.js → 7334.a6679d9168f37aa8.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7551-a0e0707b79164ddd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7758-0b018a9e4fc56200.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7777-79f845045aa1ed86.js +1 -0
- package/apps/pwa/out/_next/static/chunks/79f8be9e-957d68913b590b08.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8025-cc24ee5d8f2fb6f8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8039-df92e08fede5de8f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8206-c6684dcde12be721.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8421-1c4acfb1395a0edf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8605-0259994816604c49.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8725.bf46bb1395dd0fa2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8734-252d511cd276c0dc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8834-ca1cb09c1cb1a6bf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2415.ed6428ff334c7ce2.js → 9269.d2a4795bc6812717.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9538-2816b90923606459.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9656-c1540088f5859c80.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9906-482c6619b3fdda20.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9920-5cfdc5e8fd209825.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-d16993889b125c42.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-cb169620945d1952.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-cefe8169e36cf62a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-d2e35228bc497119.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/{page-54b32bd27726588d.js → page-5c05b0da4bc1392c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-e0ccdb576812b523.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-813c4a52c9d05ca8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-4731f2c215358937.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-a022b257950f39e6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-a2ffc717e04b8b0a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-b59ee4e70fc18fcf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-a67e11ba962337b5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-c172dabd796eb7a3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-d16993889b125c42.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/page-1efd0cb9e0ed9d13.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-d5dc7ff69a37b4cf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-e71c84189e8c683e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-1d6a533ce5a6efcb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-dfca9b7d2de0b135.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-793fa536b3a6ef37.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/page-6dd3bfbbde2a5c2c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-490653e8d4cc8852.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-77447356baad75d2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-29e961191f6057df.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-c822f55b884d9104.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-fa4ccfc432424e52.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-6d604227e1664b71.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-9c7e8f744a765daf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-4048543b4b7ad5e0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-4c3a3126abed551a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-64b0aecb1ca75e75.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-4292d0149020e8a7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-db14d0be7f1c460c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-e5d8072cd7cfef73.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-d16993889b125c42.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-9547b5cec7cf76bf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-e6dcb83265530636.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-45248f08d6aecae5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-2cddeb9e2aeedc55.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/page-e297866051595d81.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/today/page-baba2e047872fb0f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-e895da4ec9cac345.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-4344faf20216233b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-698bb29f11864b89.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-bd6a6dc1ddc273f2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-2e9e2fb01c9da1c9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-d62ceb13411ebba4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2ea96958-e8c7e112de50b067.js → f48170cc-d05d28bf87a43bf4.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/framework-172630e6aa5e2d7f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-f0fe2d7477845181.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-fc98ac70b44eccb0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-5bd7f10271f72413.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-97d0d85ea05fef9b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-9e4d02d567b98240.js +1 -0
- package/apps/pwa/out/_next/static/css/128fb7fb670b2fbf.css +1 -0
- package/apps/pwa/out/approvals/index.html +1 -1
- package/apps/pwa/out/approvals/index.txt +23 -23
- package/apps/pwa/out/autopilot/index.html +1 -1
- package/apps/pwa/out/autopilot/index.txt +23 -23
- package/apps/pwa/out/board/index.html +1 -1
- package/apps/pwa/out/board/index.txt +23 -23
- package/apps/pwa/out/botlab/index.html +1 -1
- package/apps/pwa/out/botlab/index.txt +22 -22
- package/apps/pwa/out/bots/index.html +1 -1
- package/apps/pwa/out/bots/index.txt +22 -22
- package/apps/pwa/out/chat/index.html +1 -1
- package/apps/pwa/out/chat/index.txt +22 -22
- package/apps/pwa/out/consult/index.html +1 -1
- package/apps/pwa/out/consult/index.txt +23 -23
- package/apps/pwa/out/control/index.html +1 -1
- package/apps/pwa/out/control/index.txt +23 -23
- package/apps/pwa/out/design-check/index.html +1 -1
- package/apps/pwa/out/design-check/index.txt +23 -23
- package/apps/pwa/out/editor/index.html +1 -1
- package/apps/pwa/out/editor/index.txt +23 -23
- package/apps/pwa/out/exec/index.html +1 -1
- package/apps/pwa/out/exec/index.txt +23 -23
- package/apps/pwa/out/field/index.html +1 -1
- package/apps/pwa/out/field/index.txt +23 -23
- package/apps/pwa/out/healthz +1 -1
- package/apps/pwa/out/index.html +1 -1
- package/apps/pwa/out/index.txt +22 -22
- package/apps/pwa/out/inside/index.html +1 -0
- package/apps/pwa/out/inside/index.txt +31 -0
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +23 -23
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +23 -23
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +22 -22
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +22 -22
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +23 -23
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +23 -23
- package/apps/pwa/out/ops/checklist/index.html +1 -1
- package/apps/pwa/out/ops/checklist/index.txt +22 -22
- package/apps/pwa/out/ops/release/index.html +1 -1
- package/apps/pwa/out/ops/release/index.txt +22 -22
- package/apps/pwa/out/ops/seats/index.html +1 -1
- package/apps/pwa/out/ops/seats/index.txt +22 -22
- package/apps/pwa/out/outputs/index.html +1 -0
- package/apps/pwa/out/outputs/index.txt +30 -0
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +23 -23
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +23 -23
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +22 -22
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +23 -23
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +23 -23
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +23 -23
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +23 -23
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +23 -23
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +22 -22
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +23 -23
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +23 -24
- package/apps/pwa/out/today/index.html +1 -1
- package/apps/pwa/out/today/index.txt +23 -23
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +23 -23
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +23 -23
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +23 -23
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +23 -24
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +23 -23
- package/graphs/context/nightly-condense.yaml +21 -0
- package/graphs/context/recipes.yaml +12 -0
- package/graphs/demo/inside-seed.yaml +20 -0
- package/graphs/demo/recipes.yaml +12 -0
- package/graphs/drafts/draft-cleanup.yaml +19 -0
- package/graphs/drafts/recipes.yaml +23 -0
- package/graphs/intake/intake-daily.yaml +2 -1
- package/graphs/ops/recipes.yaml +3 -0
- package/graphs/ops/secret-exposure.yaml +24 -0
- package/graphs/release/recipes.yaml +3 -0
- package/graphs/release/release-loop.yaml +4 -1
- package/graphs/video/explainer-line.yaml +2 -2
- package/package.json +2 -1
- package/plugins/card-followup/examples/sample-card.png +0 -0
- package/plugins/elanous-hwp/README.md +25 -0
- package/plugins/elanous-hwp/cli.ts +22 -0
- package/plugins/elanous-hwp/converter.ts +237 -0
- package/plugins/elanous-hwp/fixtures/fixed-controls.hwpx +0 -0
- package/plugins/elanous-hwp/fixtures/fixed-table-controls.hwpx +0 -0
- package/plugins/elanous-hwp/fixtures/fixed.hwpx +0 -0
- package/plugins/elanous-hwp/plugin.json +16 -0
- package/plugins/elanous-hwp/plugin.ts +40 -0
- package/scripts/ci-public-export-leak-gate.ts +75 -14
- package/scripts/ci-public-leak-gate.ts +44 -9
- package/scripts/context-hooks/claude-stop.sh +4 -0
- package/scripts/context-hooks/emit.ts +24 -0
- package/scripts/context-hooks/post-tool-use.sh +4 -0
- package/scripts/coord-channel-watch.sh +12 -0
- package/scripts/coord-requests-bridge.ts +143 -0
- package/scripts/field-feed/lib.ts +4 -0
- package/scripts/fleet/node-setup.sh +20 -3
- package/scripts/homebrew-formula-bump.ts +69 -0
- package/scripts/lib/telegram-inject-args.ts +31 -0
- package/scripts/marketing/measure-site-numbers.ts +169 -0
- package/scripts/measure-gate-shards.ts +309 -0
- package/scripts/measure-pod-memory-by-goal.ts +130 -0
- package/scripts/mission-request-judge.ts +31 -1
- package/scripts/morning-report.ts +2 -2
- package/scripts/opportunity-scan.ts +1 -1
- package/scripts/release-loop/auto-approve-node.ts +21 -4
- package/scripts/release-loop/checklist-gate-node.ts +2 -1
- package/scripts/release-loop/cut-branch.ts +84 -0
- package/scripts/release-loop/gate-node.ts +22 -15
- package/scripts/release-loop/mac-smoke-node.ts +229 -0
- package/scripts/release-loop/node-verdict.ts +3 -3
- package/scripts/release-loop/ops-upgrade-node.ts +47 -6
- package/scripts/release-loop/publish-node.ts +4 -1
- package/scripts/release-loop/tui-node-checks.ts +42 -0
- package/scripts/release-loop/tui-sim-node.ts +32 -8
- package/scripts/release-loop/unattended-release.ts +5 -3
- package/scripts/release-loop/version-node.ts +74 -13
- package/scripts/signal-digest-cycle.ts +2 -7
- package/scripts/signal-digest-photo.ts +11 -0
- package/scripts/tech1-public-measure.ts +94 -0
- package/scripts/telegram-inject.ts +14 -6
- package/scripts/test-diet/node.ts +1 -1
- package/scripts/test-diet/remeasure-list.ts +112 -0
- package/scripts/tui-regress.ts +2 -2
- package/scripts/ux/demo-rehearsal.ts +247 -0
- package/scripts/ux/demo-seed.ts +108 -0
- package/scripts/ux/lib/rehearsal-verdict.ts +80 -0
- package/skills/diagram-master/SKILL.md +366 -0
- package/skills/diagram-master/references/engines/excalidraw/color-palette.md +67 -0
- package/skills/diagram-master/references/engines/excalidraw/element-templates.md +182 -0
- package/skills/diagram-master/references/engines/excalidraw/json-schema.md +71 -0
- package/skills/diagram-master/references/engines/excalidraw/render_excalidraw.py +189 -0
- package/skills/diagram-master/references/engines/excalidraw/render_template.html +57 -0
- package/skills/diagram-master/references/engines/matplotlib/matplotlib-patterns.md +235 -0
- package/skills/diagram-master/references/engines/matplotlib/render_matplotlib.py +184 -0
- package/skills/diagram-master/references/engines/mermaid/domain-templates.md +435 -0
- package/skills/diagram-master/references/engines/mermaid/render_mermaid.py +116 -0
- package/skills/diagram-master/references/engines/mermaid/syntax-reference.md +2247 -0
- package/skills/diagram-master/references/engines/nanobannana/render_nanobannana2.py +168 -0
- package/skills/diagram-master/references/engines/svg/color-palette.md +188 -0
- package/skills/diagram-master/references/engines/svg/html-base-template.html +332 -0
- package/skills/diagram-master/references/engines/svg/interactivity-patterns.md +435 -0
- package/skills/diagram-master/references/engines/svg/render_interactive_svg.py +212 -0
- package/skills/diagram-master/references/engines/svg/svg-element-templates.md +349 -0
- package/skills/diagram-master/references/examples/README.md +69 -0
- package/skills/diagram-master/references/examples/ref_grid_architecture.png +0 -0
- package/skills/diagram-master/references/examples/ref_layered_flow.png +0 -0
- package/skills/diagram-master/references/pyproject.toml +16 -0
- package/skills/diagram-master/references/quality-checklist.md +33 -0
- package/skills/diagram-master/references/routing-guide.md +164 -0
- package/skills/diagram-master/references/uv.lock +1356 -0
- package/skills/google-workspace/SKILL.md +33 -0
- package/skills/google-workspace/scripts/gws-safe.sh +177 -0
- package/skills/grill-me/SKILL.md +1 -1
- package/skills/lecture-note-digitizer/SKILL.md +926 -0
- package/skills/lecture-note-digitizer/references/convert_to_pdf.py +30 -0
- package/skills/lecture-note-digitizer/references/extract_slide_diagram.py +73 -0
- package/skills/lecture-note-digitizer/references/html-template.md +167 -0
- package/skills/lecture-note-digitizer/references/katex-style-guide.md +165 -0
- package/skills/omni-crawl/SKILL.md +21 -11
- package/skills/omni-crawl/scripts/main.ts +6 -6
- package/skills/omni-crawl/src/router.ts +3 -3
- package/skills/omni-digest/SKILL.md +17 -9
- package/skills/omni-digest/digest.md +2 -2
- package/skills/omni-digest/src/fetch.ts +30 -3
- package/skills/pitch-deck/SKILL.md +2 -2
- package/skills/pitch-deck/template.html +2 -2
- package/skills/youtube-master/SKILL.md +163 -0
- package/skills/youtube-master/package-lock.json +558 -0
- package/skills/youtube-master/package.json +13 -0
- package/skills/youtube-master/references/study-note-template.md +124 -0
- package/skills/youtube-master/scripts/main.ts +435 -0
- package/skills/youtube-master/scripts/transcribe-local.ts +24 -0
- package/skills/youtube-master/src/audio.ts +63 -0
- package/skills/youtube-master/src/domain-staging.ts +50 -0
- package/skills/youtube-master/src/env.ts +36 -0
- package/skills/youtube-master/src/obsidian.ts +155 -0
- package/skills/youtube-master/src/router.ts +110 -0
- package/skills/youtube-master/src/stt.ts +199 -0
- package/skills/youtube-master/src/study-note.ts +175 -0
- package/skills/youtube-master/src/summarize.ts +358 -0
- package/skills/youtube-master/src/transcript.ts +76 -0
- package/skills/youtube-master/src/types.ts +91 -0
- package/skills/youtube-master/src/util.ts +93 -0
- package/skills/youtube-master/src/youtube.ts +70 -0
- package/skills/youtube-master/tsconfig.json +13 -0
- package/src/acp/server.ts +5 -2
- package/src/agent-mission/driver.ts +215 -23
- package/src/agent-mission/pty-decision.ts +71 -0
- package/src/agent-mission/review-loop.ts +30 -0
- package/src/autopilot/build/llm-conflict-merge.ts +16 -3
- package/src/autopilot/pty-control-loop.ts +4 -1
- package/src/autopilot/tool-registry.ts +2 -0
- package/src/boot/daemon-prompt-turn.ts +5 -0
- package/src/boot/daemon-runtime.ts +9 -3
- package/src/boot/daemon-tools/web-search.ts +3 -0
- package/src/card-followup/core.ts +109 -0
- package/src/chat/index.ts +2 -0
- package/src/cli/drive-input-jail.ts +101 -0
- package/src/cli/hooks-cli.ts +17 -3
- package/src/cli/make-cli.ts +43 -0
- package/src/cli/persona-cli.ts +98 -9
- package/src/cli/plugin-cli.ts +31 -22
- package/src/cli/pod-cli.ts +36 -9
- package/src/cli/pod-memory-advice.ts +35 -0
- package/src/cli/pr-cli.ts +51 -15
- package/src/cli/pty-drive-cli.ts +41 -7
- package/src/cli/pty-drive-verdict.ts +40 -0
- package/src/cli/release-cli.ts +63 -10
- package/src/cli/setup-cli.ts +43 -1
- package/src/cli/skills-cli.ts +17 -1
- package/src/context-bus/claude-hooks-install.ts +10 -0
- package/src/context-bus/context-now-surfaces.ts +65 -0
- package/src/context-bus/context-now.ts +104 -0
- package/src/context-bus/coord-events.ts +2 -2
- package/src/context-bus/external-events.ts +52 -0
- package/src/context-bus/long-term-memory.ts +108 -0
- package/src/context-bus/nightly-condense.ts +153 -0
- package/src/context-bus/session-events.ts +35 -0
- package/src/dashboard/dashboard-status-lines.ts +2 -0
- package/src/dashboard/index.ts +17 -4
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +31 -1
- package/src/decisions/decision-cards.ts +10 -3
- package/src/decisions/decision-ledger.ts +13 -5
- package/src/discord/sprint21-runtime.ts +5 -1
- package/src/discord-self-message.ts +32 -0
- package/src/discord-slash-wire.ts +5 -1
- package/src/discord.ts +17 -1
- package/src/domains/core-tools.ts +3 -2
- package/src/domains/outbound-alert.ts +105 -32
- package/src/domains/outbound-log-probe.ts +8 -0
- package/src/domains/telegram-kind-route.ts +51 -13
- package/src/exec-requests/default-outputs.ts +25 -0
- package/src/exec-requests/planner.ts +10 -2
- package/src/exec-requests/runner.ts +20 -6
- package/src/exec-requests/store.ts +3 -0
- package/src/execution-loop/launch-gate.ts +109 -0
- package/src/field/field-reel.ts +5 -1
- package/src/field-note/index.ts +201 -0
- package/src/field-note/telegram.ts +142 -0
- package/src/field-note/transcribe.ts +248 -0
- package/src/graph-kinds/registry.ts +3 -3
- package/src/graph-runner/graph-cli.ts +61 -1
- package/src/graph-runner/graph-grow-llm.ts +47 -0
- package/src/graph-runner/graph-grow.ts +50 -0
- package/src/graph-runner/runner.ts +329 -33
- package/src/grok/agent-search.ts +8 -2
- package/src/guardian/secret-exposure-scan.ts +101 -0
- package/src/harness/harness-cli-command.ts +375 -13
- package/src/harness/harness-pod-dispatch.ts +43 -23
- package/src/harness/harness-seams.ts +38 -4
- package/src/harness/harness-stop.ts +23 -4
- package/src/harness/launch-registry.ts +91 -0
- package/src/harness/process-garbage.ts +5 -3
- package/src/hooks/consult-intake.ts +153 -0
- package/src/hooks/dispatch.ts +82 -0
- package/src/hooks/expose.ts +254 -0
- package/src/hooks/github-shadow.ts +108 -0
- package/src/hooks/providers.ts +71 -5
- package/src/hooks/queue.ts +1 -1
- package/src/hooks/receiver.ts +94 -16
- package/src/index.ts +76 -14
- package/src/intake-plane/categorize.ts +18 -46
- package/src/intake-plane/discord-seat-work.ts +38 -2
- package/src/intake-plane/front-route-classifier.ts +33 -39
- package/src/intake-plane/persona-answer.ts +30 -0
- package/src/intake-plane/runtime-callables.ts +8 -1
- package/src/intake-plane/telegram-seat-work.ts +36 -2
- package/src/intake-plane/wish-card.ts +33 -0
- package/src/intake-plane/wish-folder.ts +67 -0
- package/src/intent-gate/gate.ts +30 -10
- package/src/live/detail-switch.ts +5 -0
- package/src/llm/difficulty.ts +57 -0
- package/src/llm/judge-layer.ts +101 -0
- package/src/llm/mission-router.ts +33 -19
- package/src/loops/contract/examples/cmo-seat.loop.yaml +51 -0
- package/src/loops/contract/examples/orchestrator.loop.yaml +57 -0
- package/src/loops/contract/examples/steward.loop.yaml +50 -0
- package/src/loops/contract/loop-agent.schema.json +138 -0
- package/src/loops/contract/validate.ts +64 -0
- package/src/loops/registry.ts +20 -6
- package/src/market/signed-index.ts +4 -0
- package/src/maturity/bot-command-maturity.ts +45 -0
- package/src/maturity/feature-maturity.ts +27 -4
- package/src/model-tier/index.ts +2 -2
- package/src/model-tier/tier-resolver.ts +20 -20
- package/src/model-tier/types.ts +6 -6
- package/src/mss/logging/log-store.ts +15 -0
- package/src/nexus/api/config-model-tier.ts +5 -4
- package/src/nexus/api/fabric-plans.ts +53 -0
- package/src/nexus/api/harness-api.ts +5 -1
- package/src/nexus/api/health.ts +2 -0
- package/src/nexus/api/http-server.ts +67 -8
- package/src/nexus/api/inside-events.ts +226 -0
- package/src/nexus/api/meta-api.ts +21 -8
- package/src/nexus/api/missions.ts +6 -1
- package/src/nexus/api/ops-seats.ts +33 -0
- package/src/nexus/api/outbound-report.ts +40 -7
- package/src/nexus/api/outputs-route.ts +44 -0
- package/src/nexus/api/personas.ts +95 -53
- package/src/nexus/api/seat-requests.ts +44 -2
- package/src/nexus/api/sessions-store.ts +17 -38
- package/src/nexus/api/sub-seat-charters.ts +34 -0
- package/src/nexus/api/tabs-mutations.ts +3 -1
- package/src/nexus/api/task-cards-api.ts +19 -0
- package/src/nexus/api/trace.ts +18 -6
- package/src/nexus/api/workflow-history.ts +88 -0
- package/src/nexus/api/workflow-run-event-bridge.ts +1 -0
- package/src/nexus/api/workflows.ts +132 -6
- package/src/nexus/index.ts +2 -0
- package/src/nexus/kinds/webterm.ts +2 -1
- package/src/nexus/outbound/delivery-ledger.ts +17 -8
- package/src/nexus/outbound/router.ts +8 -3
- package/src/nexus/webterm/pty.ts +6 -2
- package/src/onboarding/cli-auth-status.ts +80 -0
- package/src/onboarding/voice-ai.ts +3 -3
- package/src/org/seat-budget.ts +48 -0
- package/src/org/stall-escalation.ts +63 -0
- package/src/outputs/ledger.ts +120 -0
- package/src/persona/persona-todo.ts +79 -0
- package/src/persona/presets.ts +123 -2
- package/src/persona/team-set.ts +155 -0
- package/src/plugins/install/plugin-install.ts +14 -0
- package/src/plugins/maker/market-bundle.ts +110 -0
- package/src/plugins/maker/plugin-maker.ts +254 -11
- package/src/plugins/maker/wizard-generate.ts +103 -0
- package/src/pod-lease/admission.ts +150 -0
- package/src/pod-lease/dependency-state.ts +85 -0
- package/src/pod-lease/host-lease.ts +127 -0
- package/src/project/project-suggestion.ts +16 -0
- package/src/project/session-context.ts +24 -0
- package/src/release-loop/checklist.ts +17 -5
- package/src/release-loop/feature-store.ts +29 -13
- package/src/release-loop/landed-but-yellow.ts +48 -0
- package/src/release-loop/next-md-merge.ts +58 -0
- package/src/release-loop/release-note.ts +59 -4
- package/src/seat-dispatch/seat-ask.ts +130 -0
- package/src/seat-dispatch/seat-questions.ts +100 -0
- package/src/seat-loop/seat-loop.ts +709 -29
- package/src/seat-loop/seat-report.ts +37 -2
- package/src/self-dev/dev-cli.ts +4 -1
- package/src/self-dev/dev-pipeline.ts +37 -1
- package/src/self-dev/draft-sweep.ts +79 -40
- package/src/self-dev/draft-triage-rules.ts +62 -7
- package/src/self-dev/fabric-plan-core.ts +297 -0
- package/src/self-dev/orchestrate.ts +36 -4
- package/src/self-dev/release-path-guard.ts +62 -0
- package/src/self-dev/shard-aggregate.ts +230 -0
- package/src/self-dev/shard-placement.ts +60 -0
- package/src/self-dev/shard-plan.ts +48 -0
- package/src/self-dev/shard-pod-run.ts +77 -0
- package/src/self-dev/shard-run.ts +105 -0
- package/src/self-implement/budget-gate.ts +29 -12
- package/src/self-implement/gate-baseline.ts +1 -1
- package/src/self-implement/gate-candidate-ranking.ts +60 -0
- package/src/self-implement/gate-cli.ts +40 -1
- package/src/self-implement/gate-scope.ts +44 -13
- package/src/self-implement/graph-variant.ts +171 -0
- package/src/self-implement/harness-policy-gates.ts +1 -1
- package/src/self-implement/headless-elanous-driver.ts +27 -3
- package/src/self-implement/host-regate.ts +22 -1
- package/src/self-implement/importer-test-index.ts +2 -1
- package/src/self-implement/l8-merge-queue.ts +130 -0
- package/src/self-implement/orchestrator.ts +257 -9
- package/src/self-implement/route-consumer-test-index.ts +122 -0
- package/src/self-implement/seams.ts +72 -11
- package/src/self-implement/test-seams.ts +2 -0
- package/src/self-implement/uncommitted-work.ts +59 -0
- package/src/session/index.ts +36 -13
- package/src/skills/gift-install.ts +215 -0
- package/src/skills/tools/web-search.ts +4 -1
- package/src/steward/launch.ts +42 -26
- package/src/steward/steward-cards.ts +17 -9
- package/src/steward/triage.ts +46 -14
- package/src/task-cards/card-cli.ts +25 -1
- package/src/task-orchestrator/mission.ts +5 -0
- package/src/task-orchestrator/store.ts +12 -3
- package/src/task-orchestrator/surfaces/pod-command-job.ts +43 -17
- package/src/task-orchestrator/surfaces/pod-lease.ts +156 -19
- package/src/task-orchestrator/surfaces/pod-pool.ts +127 -26
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +222 -40
- package/src/task-orchestrator/surfaces/self-implement.ts +15 -2
- package/src/task-orchestrator/types.ts +2 -0
- package/src/telegram-card-followup.ts +16 -96
- package/src/telegram-commands.ts +31 -1
- package/src/telegram-project-command.ts +145 -0
- package/src/telegram-report.ts +21 -17
- package/src/telegram.ts +61 -8
- package/src/tool-runtime/self-cognition-runtimes.ts +13 -3
- package/src/user-config.ts +110 -24
- package/src/version/packed-revision.json +1 -1
- package/src/web-search/grok.ts +7 -1
- package/src/web-search/index.ts +28 -1
- package/src/web-search/provider.ts +4 -0
- package/src/web-search/x-intent.ts +5 -0
- package/src/workflow-runtime/executor.ts +277 -47
- package/src/workflow-runtime/index.ts +1 -0
- package/src/workflow-runtime/nodes/subworkflow.ts +60 -0
- package/src/workflow-runtime/plugin-kind-node.ts +1 -1
- package/src/workflow-runtime/schema.ts +79 -4
- package/src/workflow-runtime/types.ts +35 -4
- package/apps/pwa/out/_next/static/2DsiDfDCks44g1cPUMhiW/_buildManifest.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1105-c473ed46272fba79.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-cb6debea56cce4fb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/24-e6d28380efab7faf.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/3403.4bc97b4066945a94.js +0 -5
- package/apps/pwa/out/_next/static/chunks/3615-740dd270764ffa24.js +0 -1
- package/apps/pwa/out/_next/static/chunks/371-4ad6af55dad02ced.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3734-1015fe991eb9b7e7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4114-3e63117452378807.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5012-a7fe6f3c8b6fe45a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5609-012bb3557211f07e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5783-ef40ebfc91d55230.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5791-bb82743fa6299562.js +0 -1
- package/apps/pwa/out/_next/static/chunks/62-ff227c3edb8b248b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6320-baac91d68843a9a6.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/7633-1b3709b0854c9412.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/7951-8b03dbb10b24cd06.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7990-e12efba616f46e03.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8142-744998d65d7bb17e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8195-6fde3d7a39859206.js +0 -10
- package/apps/pwa/out/_next/static/chunks/8619-4365e03a2862830f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8894-b5fb36bab837cd29.js +0 -1
- package/apps/pwa/out/_next/static/chunks/920-f7dceb78f1c585ef.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9454-84d0d5d77446bd92.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9651-3cd291a6fa1370d2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/988-5f92e7ab7ccea3dd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9989-5582582f06429840.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-d2253d7e58ef1890.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-5441d4a9ab35e518.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-d9b12d680922d980.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-e268d6d145827a22.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-f8116559c7424da7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-1085399fd0f32112.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-1df686a14f65895a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-54e1f966ab60a4dc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-7ed95f296f5ee8e9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-11edac668d77e5c3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-59e2b9a22cd5a6d5.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-2976df21ad74ab48.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-34d211a67f16d510.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-8ff652d5d950639b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-b31610deda76337b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-6cb0e1bbefe5fb3d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-a286a152cf584576.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-d9237581e7003bcb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-83274e761643fdd2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-ceee6cfb1d4e6d68.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-9c9f8bb3e4a64091.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-c17217603ea3426a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-efb6177cbf1e8a51.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-d307523703bc4df3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-462f4e4bab45ce7d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-8990e96f33af3837.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-e168fa1030af0548.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-1233e05a4068bc9c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-13a1840b1fac337a.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-64a29fc80b11ab55.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-68e787339a16b3dc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-4fddc90b23feb215.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-886ba8260dc79c79.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-0f26507a1722e40b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-109d4ccd42259c9d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-f5c2a4e510726774.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-b2e0039416f42522.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-26102fd7350f171e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-708948bc8a802794.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-5e5611620f78fb0b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-139ba5c367bbf60a.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-202b4e81f33895ea.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/chunks/webpack-e5bea36f183b25e6.js +0 -1
- package/apps/pwa/out/_next/static/css/43feca5fd387dcbd.css +0 -1
- /package/apps/pwa/out/_next/static/{2DsiDfDCks44g1cPUMhiW → -6XrAoD3eU7NyMHAE4xPS}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import type { TranscriptEntry } from './index';
|
|
2
|
+
|
|
3
|
+
/** Mono, normalized PCM. The capture instant is required for NOTE1's absolute photo alignment. */
|
|
4
|
+
export interface FieldAudio {
|
|
5
|
+
samples: Float32Array;
|
|
6
|
+
sampleRate: number;
|
|
7
|
+
recordedAt: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface AudioChunk {
|
|
11
|
+
samples: Float32Array;
|
|
12
|
+
sampleRate: number;
|
|
13
|
+
/** Offset from the first sample of the recording, in seconds. */
|
|
14
|
+
startSeconds: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface SpeechSegment {
|
|
18
|
+
/** Start and end in seconds relative to the supplied chunk. */
|
|
19
|
+
startSeconds: number;
|
|
20
|
+
endSeconds: number;
|
|
21
|
+
text: string;
|
|
22
|
+
speaker?: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface EngineRequest {
|
|
26
|
+
language: string;
|
|
27
|
+
/** Preserve source-language speech rather than translating it. */
|
|
28
|
+
task: 'transcribe';
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface TranscriptionEngine {
|
|
32
|
+
transcribe(chunk: AudioChunk, request: EngineRequest): Promise<readonly SpeechSegment[]>;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** The caller provides the local Whisper runtime; this module never downloads a model. */
|
|
36
|
+
export interface LocalWhisperClient {
|
|
37
|
+
transcribe(input: {
|
|
38
|
+
audio: Float32Array;
|
|
39
|
+
sampleRate: number;
|
|
40
|
+
language: string;
|
|
41
|
+
task: 'transcribe';
|
|
42
|
+
}): Promise<readonly SpeechSegment[]>;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** The caller provides authentication/transport; no network call occurs on construction. */
|
|
46
|
+
export interface CloudSttClient {
|
|
47
|
+
transcribe(input: {
|
|
48
|
+
audio: Float32Array;
|
|
49
|
+
sampleRate: number;
|
|
50
|
+
language: string;
|
|
51
|
+
timestamps: true;
|
|
52
|
+
diarization: true;
|
|
53
|
+
}): Promise<readonly SpeechSegment[]>;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function createLocalWhisperEngine(client: LocalWhisperClient): TranscriptionEngine {
|
|
57
|
+
return {
|
|
58
|
+
transcribe: (chunk, request) => client.transcribe({
|
|
59
|
+
audio: chunk.samples, sampleRate: chunk.sampleRate, language: request.language, task: request.task,
|
|
60
|
+
}),
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function createCloudSttEngine(client: CloudSttClient): TranscriptionEngine {
|
|
65
|
+
return {
|
|
66
|
+
transcribe: (chunk, request) => client.transcribe({
|
|
67
|
+
audio: chunk.samples, sampleRate: chunk.sampleRate, language: request.language,
|
|
68
|
+
timestamps: true, diarization: true,
|
|
69
|
+
}),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export interface TranscriptionOptions {
|
|
74
|
+
/** Default: ko. */
|
|
75
|
+
language?: string;
|
|
76
|
+
/** Default: 30 seconds. */
|
|
77
|
+
chunkSeconds?: number;
|
|
78
|
+
/** Default: 2 seconds. Must be shorter than chunkSeconds. */
|
|
79
|
+
overlapSeconds?: number;
|
|
80
|
+
/** Used only if an engine omits a speaker label. Otherwise the label remains 화자 미상. */
|
|
81
|
+
defaultSpeaker?: string;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function validateAudio(audio: FieldAudio): number {
|
|
85
|
+
if (!Number.isInteger(audio.sampleRate) || audio.sampleRate <= 0) {
|
|
86
|
+
throw new RangeError('Audio sampleRate must be a positive integer');
|
|
87
|
+
}
|
|
88
|
+
const match = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.\d{1,3})?(Z|[+-]\d{2}:\d{2})$/.exec(audio.recordedAt);
|
|
89
|
+
if (!match) throw new RangeError('Audio recordedAt must be an ISO timestamp with a timezone offset');
|
|
90
|
+
const [, year, month, day, hour, minute, second, zone] = match;
|
|
91
|
+
const calendar = new Date(Date.UTC(+year!, +month! - 1, +day!, +hour!, +minute!, +second!));
|
|
92
|
+
const recordedAt = Date.parse(audio.recordedAt);
|
|
93
|
+
if (calendar.getUTCFullYear() !== +year! || calendar.getUTCMonth() + 1 !== +month! ||
|
|
94
|
+
calendar.getUTCDate() !== +day! || calendar.getUTCHours() !== +hour! ||
|
|
95
|
+
calendar.getUTCMinutes() !== +minute! || calendar.getUTCSeconds() !== +second! ||
|
|
96
|
+
(zone !== 'Z' && (+zone!.slice(1, 3) > 23 || +zone!.slice(4) > 59)) ||
|
|
97
|
+
!Number.isFinite(recordedAt)) {
|
|
98
|
+
throw new RangeError('Invalid audio recordedAt timestamp');
|
|
99
|
+
}
|
|
100
|
+
return recordedAt;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** Sample-index arithmetic avoids gaps and drift from repeated floating-point additions. */
|
|
104
|
+
export function splitAudioIntoChunks(audio: FieldAudio, options: TranscriptionOptions = {}): AudioChunk[] {
|
|
105
|
+
validateAudio(audio);
|
|
106
|
+
const chunkSeconds = options.chunkSeconds ?? 30;
|
|
107
|
+
const overlapSeconds = options.overlapSeconds ?? 2;
|
|
108
|
+
if (!Number.isFinite(chunkSeconds) || !Number.isFinite(overlapSeconds) ||
|
|
109
|
+
chunkSeconds <= 0 || overlapSeconds < 0 || overlapSeconds >= chunkSeconds) {
|
|
110
|
+
throw new RangeError('Audio chunk length must exceed nonnegative overlap');
|
|
111
|
+
}
|
|
112
|
+
const size = Math.round(chunkSeconds * audio.sampleRate);
|
|
113
|
+
const overlap = Math.round(overlapSeconds * audio.sampleRate);
|
|
114
|
+
if (size <= 0 || overlap >= size) throw new RangeError('Audio chunk and overlap must span valid samples');
|
|
115
|
+
const chunks: AudioChunk[] = [];
|
|
116
|
+
for (let start = 0; start < audio.samples.length;) {
|
|
117
|
+
const end = Math.min(start + size, audio.samples.length);
|
|
118
|
+
chunks.push({ samples: audio.samples.subarray(start, end), sampleRate: audio.sampleRate,
|
|
119
|
+
startSeconds: start / audio.sampleRate });
|
|
120
|
+
if (end === audio.samples.length) break;
|
|
121
|
+
start = end - overlap;
|
|
122
|
+
}
|
|
123
|
+
return chunks;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function mergeOverlappingText(left: string, right: string): string | null {
|
|
127
|
+
if (left === right) return left;
|
|
128
|
+
if (left.includes(right)) return left;
|
|
129
|
+
if (right.includes(left)) return right;
|
|
130
|
+
for (let length = Math.min(left.length, right.length); length >= 2; length--) {
|
|
131
|
+
if (left.endsWith(right.slice(0, length))) return left + right.slice(length);
|
|
132
|
+
}
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
interface TimedSegment {
|
|
137
|
+
start: number;
|
|
138
|
+
end: number;
|
|
139
|
+
speaker: string;
|
|
140
|
+
text: string;
|
|
141
|
+
chunkIndex: number;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/** Return absolute ISO timestamps accepted by NOTE1, preserving speaker labels and chronological order. */
|
|
145
|
+
export async function transcribeFieldAudio(
|
|
146
|
+
audio: FieldAudio,
|
|
147
|
+
engine: TranscriptionEngine,
|
|
148
|
+
options: TranscriptionOptions = {},
|
|
149
|
+
): Promise<TranscriptEntry[]> {
|
|
150
|
+
const origin = validateAudio(audio);
|
|
151
|
+
const chunks = splitAudioIntoChunks(audio, options);
|
|
152
|
+
const segments: TimedSegment[] = [];
|
|
153
|
+
for (const [chunkIndex, chunk] of chunks.entries()) {
|
|
154
|
+
const result = await engine.transcribe(chunk, { language: options.language ?? 'ko', task: 'transcribe' });
|
|
155
|
+
const duration = chunk.samples.length / chunk.sampleRate;
|
|
156
|
+
for (const segment of result) {
|
|
157
|
+
if (!Number.isFinite(segment.startSeconds) || !Number.isFinite(segment.endSeconds) ||
|
|
158
|
+
segment.startSeconds < 0 || segment.endSeconds < segment.startSeconds ||
|
|
159
|
+
// Only floating-point slack — a segment may not end after the chunk's real audio (NOTE3a review must-fix).
|
|
160
|
+
segment.endSeconds > duration + 1e-9) {
|
|
161
|
+
throw new RangeError(`Invalid transcription segment times in chunk ${chunkIndex}`);
|
|
162
|
+
}
|
|
163
|
+
const text = segment.text.trim();
|
|
164
|
+
if (!text) continue;
|
|
165
|
+
segments.push({
|
|
166
|
+
start: chunk.startSeconds + segment.startSeconds,
|
|
167
|
+
end: chunk.startSeconds + segment.endSeconds,
|
|
168
|
+
text, speaker: segment.speaker?.trim() || options.defaultSpeaker?.trim() || '화자 미상',
|
|
169
|
+
chunkIndex,
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
segments.sort((a, b) => a.chunkIndex - b.chunkIndex || a.start - b.start);
|
|
174
|
+
const stitched: TimedSegment[] = [];
|
|
175
|
+
const center = (segment: TimedSegment) => {
|
|
176
|
+
const source = chunks[segment.chunkIndex]!;
|
|
177
|
+
return source.startSeconds + source.samples.length / source.sampleRate / 2;
|
|
178
|
+
};
|
|
179
|
+
// Engine speaker IDs are chunk-scoped. A later chunk's ID that matched an earlier chunk's speech in the overlap takes
|
|
180
|
+
// the earlier global label; an ID that never matched is qualified with its chunk so different people never share a label.
|
|
181
|
+
const unlabeled = new Set(['화자 미상', options.defaultSpeaker?.trim()].filter((label): label is string => !!label));
|
|
182
|
+
const qualify = (speaker: string, chunkIndex: number) => chunkIndex && !unlabeled.has(speaker) ? `${speaker} · 구간 ${chunkIndex + 1}` : speaker;
|
|
183
|
+
for (const [chunkIndex, chunk] of chunks.entries()) {
|
|
184
|
+
const incoming = segments.filter((segment) => segment.chunkIndex === chunkIndex);
|
|
185
|
+
const speakerMap = new Map<string, string>();
|
|
186
|
+
const previous = stitched.filter((segment) => segment.chunkIndex === chunkIndex - 1);
|
|
187
|
+
const sharedStart = chunk.startSeconds;
|
|
188
|
+
const sharedEnd = chunkIndex ? Math.min(chunk.startSeconds + chunk.samples.length / chunk.sampleRate,
|
|
189
|
+
chunks[chunkIndex - 1]!.startSeconds + chunks[chunkIndex - 1]!.samples.length / audio.sampleRate) : sharedStart;
|
|
190
|
+
const eligible = (segment: TimedSegment) => segment.start <= sharedEnd && segment.end >= sharedStart;
|
|
191
|
+
const consumedPrevious = new Set<TimedSegment>();
|
|
192
|
+
const consumedIncoming = new Set<TimedSegment>();
|
|
193
|
+
const replacements: TimedSegment[] = [];
|
|
194
|
+
// A chunk may split one sentence into several timed segments while its
|
|
195
|
+
// neighbor reports the entire sentence. Match contiguous groups on both sides.
|
|
196
|
+
while (sharedEnd > sharedStart) {
|
|
197
|
+
let best: { earlier: TimedSegment[]; later: TimedSegment[]; text: string } | undefined;
|
|
198
|
+
for (let a = 0; a < previous.length; a++) {
|
|
199
|
+
for (let b = a + 1; b <= previous.length; b++) {
|
|
200
|
+
const earlier = previous.slice(a, b);
|
|
201
|
+
if (earlier.some((item) => consumedPrevious.has(item) || !eligible(item))) break;
|
|
202
|
+
for (let c = 0; c < incoming.length; c++) {
|
|
203
|
+
for (let d = c + 1; d <= incoming.length; d++) {
|
|
204
|
+
const later = incoming.slice(c, d);
|
|
205
|
+
if (later.some((item) => consumedIncoming.has(item) || !eligible(item))) break;
|
|
206
|
+
// Speaker IDs are scoped to each engine call, not stable across chunks.
|
|
207
|
+
// Keep distinct speakers within a chunk separate, but use speech and time across chunks.
|
|
208
|
+
if (earlier.some((item) => item.speaker !== earlier[0]!.speaker) ||
|
|
209
|
+
later.some((item) => item.speaker !== later[0]!.speaker)) continue;
|
|
210
|
+
const earlierStart = earlier[0]!.start;
|
|
211
|
+
const earlierEnd = Math.max(...earlier.map((item) => item.end));
|
|
212
|
+
const laterStart = later[0]!.start;
|
|
213
|
+
const laterEnd = Math.max(...later.map((item) => item.end));
|
|
214
|
+
if (earlier.some((item) => item.start > laterEnd || item.end < laterStart) ||
|
|
215
|
+
later.some((item) => item.start > earlierEnd || item.end < earlierStart)) continue;
|
|
216
|
+
const text = mergeOverlappingText(earlier.map((item) => item.text).join(' '),
|
|
217
|
+
later.map((item) => item.text).join(' '));
|
|
218
|
+
if (text !== null && (!best || earlier.length + later.length > best.earlier.length + best.later.length)) {
|
|
219
|
+
best = { earlier, later, text };
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
if (!best) break;
|
|
226
|
+
for (const item of best.earlier) consumedPrevious.add(item);
|
|
227
|
+
for (const item of best.later) consumedIncoming.add(item);
|
|
228
|
+
const earlier = best.earlier[0]!;
|
|
229
|
+
const later = best.later[0]!;
|
|
230
|
+
const chosen = Math.abs((later.start + later.end) / 2 - center(later)) <
|
|
231
|
+
Math.abs((earlier.start + earlier.end) / 2 - center(earlier)) ? later : earlier;
|
|
232
|
+
// The earlier side already carries a global label; first match decides the mapping for this chunk-local ID.
|
|
233
|
+
for (const item of best.later) if (!speakerMap.has(item.speaker)) speakerMap.set(item.speaker, earlier.speaker);
|
|
234
|
+
replacements.push({ ...chosen, speaker: earlier.speaker, chunkIndex, text: best.text,
|
|
235
|
+
start: Math.min(...best.earlier.map((item) => item.start), ...best.later.map((item) => item.start)),
|
|
236
|
+
end: Math.max(...best.earlier.map((item) => item.end), ...best.later.map((item) => item.end)) });
|
|
237
|
+
}
|
|
238
|
+
for (let i = stitched.length - 1; i >= 0; i--) {
|
|
239
|
+
if (consumedPrevious.has(stitched[i]!)) stitched.splice(i, 1);
|
|
240
|
+
}
|
|
241
|
+
stitched.push(...incoming.filter((item) => !consumedIncoming.has(item))
|
|
242
|
+
.map((item) => ({ ...item, speaker: speakerMap.get(item.speaker) ?? qualify(item.speaker, chunkIndex) })), ...replacements);
|
|
243
|
+
stitched.sort((a, b) => a.start - b.start || a.chunkIndex - b.chunkIndex);
|
|
244
|
+
}
|
|
245
|
+
return stitched.map(({ start, speaker, text }) => ({
|
|
246
|
+
speaker, text, timestamp: new Date(origin + Math.round(start * 1000)).toISOString(),
|
|
247
|
+
}));
|
|
248
|
+
}
|
|
@@ -22,12 +22,12 @@ export interface NodeKindEntry {
|
|
|
22
22
|
|
|
23
23
|
export const HARNESS_CORE_KINDS = ['agent', 'gate', 'git', 'judge', 'observe', 'hitl', 'subgraph'] as const;
|
|
24
24
|
|
|
25
|
-
// Workflow validation
|
|
26
|
-
export const WORKFLOW_CORE_KINDS = ['prompt', 'bash', 'skill', 'cft', 'approval', 'if', 'switch', 'iteration', 'classify', 'extract', 'set', 'filter', 'template', 'http', 'showroom', 'task', 'scheduleTrigger', 'webhookTrigger', 'discordTrigger', 'telegramTrigger', 'manualTrigger', 'chatTrigger'] as const;
|
|
25
|
+
// Workflow validation, the palette, and executor variant labels read the same keys.
|
|
26
|
+
export const WORKFLOW_CORE_KINDS = ['prompt', 'bash', 'skill', 'cft', 'approval', 'if', 'switch', 'iteration', 'classify', 'extract', 'set', 'filter', 'template', 'http', 'showroom', 'task', 'scheduleTrigger', 'webhookTrigger', 'discordTrigger', 'telegramTrigger', 'manualTrigger', 'chatTrigger', 'subworkflow'] as const;
|
|
27
27
|
|
|
28
28
|
const descriptions: Record<GraphKind, readonly string[]> = {
|
|
29
29
|
harness: ['Run an agent', 'Check an execution gate', 'Perform git operations', 'Judge an outcome', 'Observe a result', 'Request human input', 'Run a child graph'],
|
|
30
|
-
workflow: ['Run an LLM prompt', 'Run a shell command', 'Invoke a skill', 'Invoke a CFT method', 'Request approval', 'Branch on a condition', 'Select a case', 'Iterate items', 'Classify input', 'Extract structured data', 'Assign variables', 'Filter items', 'Render a template', 'Make an HTTP request', 'Run a showroom', 'Create a task', 'Start on a schedule', 'Start on a webhook', 'Start on Discord', 'Start on Telegram', 'Start manually', 'Start on chat'],
|
|
30
|
+
workflow: ['Run an LLM prompt', 'Run a shell command', 'Invoke a skill', 'Invoke a CFT method', 'Request approval', 'Branch on a condition', 'Select a case', 'Iterate items', 'Classify input', 'Extract structured data', 'Assign variables', 'Filter items', 'Render a template', 'Make an HTTP request', 'Run a showroom', 'Create a task', 'Start on a schedule', 'Start on a webhook', 'Start on Discord', 'Start on Telegram', 'Start manually', 'Start on chat', 'Call another workflow'],
|
|
31
31
|
};
|
|
32
32
|
|
|
33
33
|
const kinds = new Map<GraphKind, Map<string, NodeKindEntry>>();
|
|
@@ -3,8 +3,9 @@ import { existsSync, readFileSync, readdirSync } from 'node:fs';
|
|
|
3
3
|
import { join, resolve } from 'node:path';
|
|
4
4
|
import { parse as parseYaml } from 'yaml';
|
|
5
5
|
import { writeStdoutJson } from '../cli/stdout-json.js';
|
|
6
|
+
import type { GraphVariantPlan } from '../self-implement/graph-variant.js';
|
|
6
7
|
import { debug } from '../debug/log.js';
|
|
7
|
-
import { decideGraphApproval, graphRunAlive, lastJsonObject, latestGraphRun, listGraphRuns, runGraph, type GraphRunState } from './runner.js';
|
|
8
|
+
import { decideGraphApproval, graphRunAlive, lastJsonObject, latestGraphRun, listGraphRuns, manageGraphRun, runGraph, type GraphRunState } from './runner.js';
|
|
8
9
|
|
|
9
10
|
function findGraphFile(graphId: string): string | undefined {
|
|
10
11
|
const roots = [resolve('graphs'), resolve(import.meta.dir, '../../graphs')];
|
|
@@ -56,6 +57,43 @@ export function registerGraphCommands(program: Command, runsDeps: { root?: strin
|
|
|
56
57
|
process.exitCode = 1;
|
|
57
58
|
}
|
|
58
59
|
});
|
|
60
|
+
graph.command('variant <template>')
|
|
61
|
+
.description('Validate and run a graph variant, preserving the resulting graph beside its run ledger')
|
|
62
|
+
.requiredOption('--plan <json>', 'JSON variant plan (maxVisits, routes, or growth)')
|
|
63
|
+
.option('--dry-run', 'Walk the variant without executing commands')
|
|
64
|
+
.option('--run', 'Execute the validated variant')
|
|
65
|
+
.option('--json', 'Print run state as JSON')
|
|
66
|
+
.action(async (file: string, opts: { plan: string; dryRun?: boolean; run?: boolean; json?: boolean }) => {
|
|
67
|
+
try {
|
|
68
|
+
if (opts.dryRun === opts.run) throw new Error('choose exactly one of --dry-run or --run');
|
|
69
|
+
let plan: unknown;
|
|
70
|
+
try { plan = JSON.parse(opts.plan); } catch { throw new Error('--plan must be a JSON object'); }
|
|
71
|
+
if (!plan || typeof plan !== 'object' || Array.isArray(plan) ||
|
|
72
|
+
Object.keys(plan).some(key => !['maxVisits', 'routes', 'growth'].includes(key)) ||
|
|
73
|
+
(plan as Record<string, unknown>).maxVisits !== undefined &&
|
|
74
|
+
(typeof (plan as Record<string, unknown>).maxVisits !== 'object' || (plan as Record<string, unknown>).maxVisits === null || Array.isArray((plan as Record<string, unknown>).maxVisits)) ||
|
|
75
|
+
(plan as Record<string, unknown>).routes !== undefined && (!Array.isArray((plan as Record<string, unknown>).routes) ||
|
|
76
|
+
!(plan as { routes: unknown[] }).routes.every(route => route !== null && typeof route === 'object' && !Array.isArray(route) &&
|
|
77
|
+
typeof (route as Record<string, unknown>).from === 'string' && typeof (route as Record<string, unknown>).to === 'string' &&
|
|
78
|
+
typeof (route as Record<string, unknown>).outcome === 'string')) ||
|
|
79
|
+
(plan as Record<string, unknown>).growth !== undefined &&
|
|
80
|
+
(!(plan as Record<string, unknown>).growth || typeof (plan as Record<string, unknown>).growth !== 'object' ||
|
|
81
|
+
Array.isArray((plan as Record<string, unknown>).growth) ||
|
|
82
|
+
!(plan as { growth: Record<string, unknown> }).growth.node ||
|
|
83
|
+
typeof (plan as { growth: Record<string, unknown> }).growth.from !== 'string' ||
|
|
84
|
+
typeof (plan as { growth: Record<string, unknown> }).growth.outcome !== 'string')) {
|
|
85
|
+
throw new Error('--plan must be a JSON variant plan');
|
|
86
|
+
}
|
|
87
|
+
await (await import('../domains/standalone-log-sink.js')).registerStandaloneLogSink('graph');
|
|
88
|
+
const state = await runGraph(file, { dryRun: opts.dryRun, variant: { goal: 'g_graph_variant', plan: plan as GraphVariantPlan }, deps: { root: runsDeps.root } });
|
|
89
|
+
if (opts.json) await writeStdoutJson(JSON.stringify(state) + '\n');
|
|
90
|
+
else console.log(`${state.graphId} ${state.runId}: ${state.status} (${state.path.join(' → ')}, executed: ${state.executed})`);
|
|
91
|
+
if (state.status !== 'done' && state.status !== 'awaiting-approval') process.exitCode = 1;
|
|
92
|
+
} catch (error) {
|
|
93
|
+
console.error(`graph variant: ${error instanceof Error ? error.message : String(error)}`);
|
|
94
|
+
process.exitCode = 1;
|
|
95
|
+
}
|
|
96
|
+
});
|
|
59
97
|
graph.command('tick <file>')
|
|
60
98
|
.description('Advance one graph run, resuming a pending decision or starting only when requested')
|
|
61
99
|
.option('--start', 'Start a new run when the graph is idle')
|
|
@@ -139,6 +177,28 @@ export function registerGraphCommands(program: Command, runsDeps: { root?: strin
|
|
|
139
177
|
process.exitCode = 1;
|
|
140
178
|
}
|
|
141
179
|
});
|
|
180
|
+
for (const action of ['stop', 'destroy'] as const) {
|
|
181
|
+
runs.command(`${action} <run_id>`)
|
|
182
|
+
.description(action === 'stop' ? 'Fail a running or orphaned run so it can be resumed' : 'Stop and delete a run and its owned artifacts')
|
|
183
|
+
.action(async (runId: string) => {
|
|
184
|
+
try {
|
|
185
|
+
// Without the sink the stop/destroy observation lines never reach the log store (only `graph run` had it).
|
|
186
|
+
await (await import('../domains/standalone-log-sink.js')).registerStandaloneLogSink('graph');
|
|
187
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(runId) || runId === '.' || runId === '..') throw new Error(`invalid run id: ${runId}`);
|
|
188
|
+
const { runs: all, unreadable } = listGraphRuns(runsDeps.root);
|
|
189
|
+
const exact = all.filter(state => state.runId === runId);
|
|
190
|
+
const matches = exact.length ? exact : all.filter(state => state.runId.startsWith(runId));
|
|
191
|
+
if (matches.length !== 1) throw new Error(matches.length ? `ambiguous run id: ${runId}\n${matches.map(state => `${state.graphId}/${state.runId}`).join('\n')}` : `no run: ${runId}`);
|
|
192
|
+
const saved = matches[0]!;
|
|
193
|
+
const state = manageGraphRun(saved.graphId, saved.runId, action, runsDeps.root, runsDeps.processStartMs);
|
|
194
|
+
console.log(`${state.graphId} ${state.runId}: ${action === 'stop' ? state.status : 'destroyed'}`);
|
|
195
|
+
warning(unreadable);
|
|
196
|
+
} catch (error) {
|
|
197
|
+
console.error(`graph runs ${action}: ${error instanceof Error ? error.message : String(error)}`);
|
|
198
|
+
process.exitCode = 1;
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
}
|
|
142
202
|
runs.command('resume <run_id>')
|
|
143
203
|
.option('--from <node_id>', 'Restart at this node on the saved path')
|
|
144
204
|
.option('--use-current-graph', 'Use the installed graph and enforce the original hash')
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { PROVIDERS, streamLLM } from '../llm.js';
|
|
2
|
+
import { getUserConfig, resolveRoleLlm, type UserConfig } from '../user-config.js';
|
|
3
|
+
import type { GrowthProposal, GrowthProposer } from './graph-grow.js';
|
|
4
|
+
|
|
5
|
+
type GrowthLLM = (prompt: string) => Promise<string>;
|
|
6
|
+
const OUTPUT_TAIL_LENGTH = 2000;
|
|
7
|
+
|
|
8
|
+
export function graphGrowthLlmOptions(config: UserConfig): { model?: string; provider?: string } {
|
|
9
|
+
const role = config.roleLlm?.['graph-grow'];
|
|
10
|
+
if (!role || (!role.provider && !role.model && !role.tier)) return {};
|
|
11
|
+
const selected = resolveRoleLlm('graph-grow', { config });
|
|
12
|
+
return { model: selected.model, provider: selected.provider };
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async function defaultGrowthLLM(prompt: string): Promise<string> {
|
|
16
|
+
const selected = graphGrowthLlmOptions(getUserConfig());
|
|
17
|
+
return streamLLM([{ role: 'user', content: prompt }], () => {}, {
|
|
18
|
+
...(selected.model ? { model: selected.model, provider: PROVIDERS[selected.provider!] } : {}),
|
|
19
|
+
reasoningEffort: 'low',
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Model output is untrusted: structural and side-effect validation belongs to proposeGrowth. */
|
|
24
|
+
export function createLLMGrowthProposer(callLLM: GrowthLLM = defaultGrowthLLM): GrowthProposer {
|
|
25
|
+
return async (input: Parameters<GrowthProposer>[0]) => {
|
|
26
|
+
const serializedOutput = typeof input.output === 'string' ? input.output : input.output === undefined ? '' : JSON.stringify(input.output);
|
|
27
|
+
const prompt = [
|
|
28
|
+
'Propose exactly one new contracted graph node to handle the unseen outcome and one return edge to an existing node.',
|
|
29
|
+
'Reply with only JSON: {"node":{"nodeId":"...","kind":"agent","recipe":"none","maxVisits":1,"contract":{"inputs":[],"tools":"read-only","outputs":[]}},"returnTo":"existing-node-id","reason":"..."}.',
|
|
30
|
+
'Use only an existing recipe type (none, an existing cmd:/approval: recipe ID, or a catalog role); never invent commands. The missing-outcome edge and the return edge are built from node and returnTo after validation.',
|
|
31
|
+
'Do not alter existing nodes or edges. The proposal will be validated independently; do not assume a recipe is safe.',
|
|
32
|
+
`Graph snapshot: ${JSON.stringify(input.graph)}`,
|
|
33
|
+
`Blocked node ID: ${JSON.stringify(input.nodeId)}`,
|
|
34
|
+
`Unseen outcome: ${JSON.stringify(input.outcome)}`,
|
|
35
|
+
`Blocked node output tail: ${JSON.stringify(serializedOutput.slice(-OUTPUT_TAIL_LENGTH))}`,
|
|
36
|
+
].join('\n');
|
|
37
|
+
const response = await callLLM(prompt);
|
|
38
|
+
let parsed: unknown;
|
|
39
|
+
try { parsed = JSON.parse(response.trim().replace(/^```(?:json)?\s*/i, '').replace(/\s*```$/, '')); }
|
|
40
|
+
catch { return undefined; }
|
|
41
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) return undefined;
|
|
42
|
+
const proposal = parsed as Record<string, unknown>;
|
|
43
|
+
if (!proposal.node || typeof proposal.node !== 'object' || Array.isArray(proposal.node) ||
|
|
44
|
+
typeof proposal.reason !== 'string' || !proposal.reason.trim() || typeof proposal.returnTo !== 'string') return undefined;
|
|
45
|
+
return { node: proposal.node, reason: proposal.reason, returnTo: proposal.returnTo } as GrowthProposal;
|
|
46
|
+
};
|
|
47
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { createGraphVariant } from '../self-implement/graph-variant.js';
|
|
2
|
+
import type { GraphEdgeSpec, GraphNodeSpec, GraphTemplateSpec } from '../self-implement/graph-yaml.js';
|
|
3
|
+
import { createLLMGrowthProposer } from './graph-grow-llm.js';
|
|
4
|
+
|
|
5
|
+
export interface GrowthProposal {
|
|
6
|
+
node: GraphNodeSpec;
|
|
7
|
+
returnTo?: string;
|
|
8
|
+
reason: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export type GrowthProposer = (input: { graph: GraphTemplateSpec; nodeId: string; outcome: string; runId: string; output?: unknown }) => GrowthProposal | undefined | Promise<GrowthProposal | undefined>;
|
|
12
|
+
export type GrowthRecipeEffect = 'read-only' | 'external-effect' | 'unknown';
|
|
13
|
+
|
|
14
|
+
export interface GraphGrowth {
|
|
15
|
+
node: GraphNodeSpec;
|
|
16
|
+
edges: readonly GraphEdgeSpec[];
|
|
17
|
+
reason: string;
|
|
18
|
+
undo: { removeNode: string; removeOutcome: { from: string; outcome: string }; removeEdge?: GraphEdgeSpec };
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export async function proposeGrowth(input: Parameters<GrowthProposer>[0],
|
|
22
|
+
proposer: GrowthProposer = createLLMGrowthProposer(), classifyRecipe?: (node: GraphNodeSpec) => GrowthRecipeEffect): Promise<{ ok: true; graph: GraphTemplateSpec; growth: GraphGrowth } | { ok: false; reason: string; park?: boolean }> {
|
|
23
|
+
let proposal: GrowthProposal | undefined;
|
|
24
|
+
try { proposal = await proposer(input); }
|
|
25
|
+
catch (error) { return { ok: false, reason: `proposer failed: ${String(error)}` }; }
|
|
26
|
+
if (!proposal) return { ok: false, reason: 'no proposal' };
|
|
27
|
+
if (!proposal.node || typeof proposal.reason !== 'string' || !proposal.reason.trim()) return { ok: false, reason: 'proposal requires a node and reason' };
|
|
28
|
+
let result: ReturnType<typeof createGraphVariant>;
|
|
29
|
+
try {
|
|
30
|
+
result = createGraphVariant({ template: input.graph, goal: `g_${input.runId.replace(/[^a-z0-9_-]/gi, '_')}`,
|
|
31
|
+
plan: { growth: { node: proposal.node, from: input.nodeId, outcome: input.outcome, returnTo: proposal.returnTo } } });
|
|
32
|
+
} catch (error) { return { ok: false, reason: `growth rejected: ${String(error)}` }; }
|
|
33
|
+
if (!result.ok) return { ok: false, reason: `growth rejected: ${JSON.stringify(result.rejections)}` };
|
|
34
|
+
// Neither a recipe id nor its declared tools certify arbitrary executable code.
|
|
35
|
+
// Only a trusted classification of the resolved recipe may authorize execution.
|
|
36
|
+
let effect: GrowthRecipeEffect = 'unknown';
|
|
37
|
+
if (proposal.node.recipe !== 'none') {
|
|
38
|
+
try { effect = classifyRecipe?.(proposal.node) ?? 'unknown'; }
|
|
39
|
+
catch { effect = 'unknown'; }
|
|
40
|
+
if (effect !== 'read-only') {
|
|
41
|
+
return { ok: false, park: true, reason: '사람 확인 필요: external or unclassified side-effect recipe' };
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const edges: GraphEdgeSpec[] = [
|
|
45
|
+
{ from: input.nodeId, on: 'outcome', map: { [input.outcome]: proposal.node.nodeId } },
|
|
46
|
+
{ from: proposal.node.nodeId, to: proposal.returnTo as string },
|
|
47
|
+
];
|
|
48
|
+
return { ok: true, graph: result.template, growth: { node: proposal.node, edges, reason: proposal.reason,
|
|
49
|
+
undo: { removeNode: proposal.node.nodeId, removeOutcome: { from: input.nodeId, outcome: input.outcome }, removeEdge: edges[1]! } } };
|
|
50
|
+
}
|