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
package/src/hooks/receiver.ts
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
import { debug } from '../debug/log.js';
|
|
2
2
|
import { readFileSync } from 'node:fs';
|
|
3
|
-
import { userConfigPath } from '../user-config.js';
|
|
3
|
+
import { getUserConfig, parseEventsConfig, userConfigPath, type EventsConfig } from '../user-config.js';
|
|
4
|
+
import { dispatchHook, type HookWake } from './dispatch.js';
|
|
4
5
|
import { getSecretAsync } from '../nexus/config/secrets/index.js';
|
|
5
6
|
import { HookQueue, type QueuedHook } from './queue.js';
|
|
7
|
+
import { recordGithubShadow } from './github-shadow.js';
|
|
6
8
|
import { toExternalTask, verifyWebhook, type HookProvider } from './providers.js';
|
|
7
9
|
import { drainReports, handleReportPost, ReportLimiter, ReportQueue, type ReceivedReport } from './error-report.js';
|
|
10
|
+
import { ConsultLimiter, ConsultQueue, drainConsults, handleConsultPost, type QueuedConsult } from './consult-intake.js';
|
|
8
11
|
import { effectiveInstanceRoot } from '../instance/resolve.js';
|
|
9
12
|
|
|
10
13
|
export interface HookSecrets {
|
|
11
14
|
linear?: string;
|
|
12
15
|
asana?: string;
|
|
16
|
+
github?: string;
|
|
13
17
|
saveAsana?: (secret: string) => Promise<void>;
|
|
14
18
|
}
|
|
15
19
|
export interface HookReceiverOptions {
|
|
@@ -20,8 +24,17 @@ export interface HookReceiverOptions {
|
|
|
20
24
|
now?: () => number;
|
|
21
25
|
root?: string;
|
|
22
26
|
retryBaseMs?: number;
|
|
27
|
+
events?: EventsConfig;
|
|
28
|
+
wakeSeat?: HookWake;
|
|
23
29
|
/** ER2 — forward one queued error report to the Primary; default = POST /v1/reports/ingest over the tailnet. */
|
|
24
30
|
forwardReport?: (item: ReceivedReport) => Promise<boolean>;
|
|
31
|
+
/** CS1 — forward a queued consultation to the Primary's consult ledger. */
|
|
32
|
+
forwardConsult?: (item: QueuedConsult) => Promise<boolean>;
|
|
33
|
+
/** CS1 — the public consult route is a write path from the open internet, so it stays closed (404) until
|
|
34
|
+
* `hooks.consult.enabled === true` in user config (대표 decision D-20261003-09). Tests pass it directly. */
|
|
35
|
+
consultEnabled?: boolean;
|
|
36
|
+
/** GET-only public metadata lookup; failure forces human review. */
|
|
37
|
+
githubFetch?: typeof fetch;
|
|
25
38
|
}
|
|
26
39
|
|
|
27
40
|
/** `/v1/tasks` lives on the Primary's nexus API, not on the control plane — so the address is its own setting. */
|
|
@@ -33,37 +46,79 @@ export function hooksPrimaryUrl(config: { hooks?: { primaryUrl?: unknown } }): U
|
|
|
33
46
|
return url;
|
|
34
47
|
}
|
|
35
48
|
|
|
36
|
-
async function
|
|
49
|
+
async function forwardReportToPrimary(item: ReceivedReport): Promise<boolean> {
|
|
37
50
|
const config = JSON.parse(readFileSync(userConfigPath(), 'utf8')) as { hooks?: { primaryTokenRef?: string; primaryUrl?: unknown } };
|
|
38
51
|
const ref = config.hooks?.primaryTokenRef;
|
|
39
52
|
if (!ref) throw new Error('primary token reference missing');
|
|
40
53
|
const token = await getSecretAsync(ref);
|
|
41
54
|
if (!token) throw new Error('primary token missing');
|
|
42
|
-
|
|
43
|
-
method: 'POST', headers: { 'content-type': 'application/json', authorization: `Bearer ${token}
|
|
44
|
-
|
|
45
|
-
body: JSON.stringify({ ...event.task, eventId: `${event.provider}:${event.eventId}` }), signal: AbortSignal.timeout(10_000),
|
|
55
|
+
const response = await fetch(new URL('/v1/reports/ingest', hooksPrimaryUrl(config)), {
|
|
56
|
+
method: 'POST', headers: { 'content-type': 'application/json', authorization: `Bearer ${token}` },
|
|
57
|
+
body: JSON.stringify(item), signal: AbortSignal.timeout(10_000),
|
|
46
58
|
});
|
|
59
|
+
return response.ok;
|
|
47
60
|
}
|
|
48
61
|
|
|
49
|
-
async function
|
|
62
|
+
async function forwardConsultToPrimary(item: QueuedConsult): Promise<boolean> {
|
|
50
63
|
const config = JSON.parse(readFileSync(userConfigPath(), 'utf8')) as { hooks?: { primaryTokenRef?: string; primaryUrl?: unknown } };
|
|
51
64
|
const ref = config.hooks?.primaryTokenRef;
|
|
52
65
|
if (!ref) throw new Error('primary token reference missing');
|
|
53
66
|
const token = await getSecretAsync(ref);
|
|
54
67
|
if (!token) throw new Error('primary token missing');
|
|
55
|
-
const response = await fetch(new URL('/v1/
|
|
68
|
+
const response = await fetch(new URL('/v1/consult-requests', hooksPrimaryUrl(config)), {
|
|
56
69
|
method: 'POST', headers: { 'content-type': 'application/json', authorization: `Bearer ${token}` },
|
|
57
|
-
body: JSON.stringify(item), signal: AbortSignal.timeout(10_000),
|
|
70
|
+
body: JSON.stringify(item.consult), signal: AbortSignal.timeout(10_000),
|
|
58
71
|
});
|
|
59
72
|
return response.ok;
|
|
60
73
|
}
|
|
61
74
|
|
|
75
|
+
/** Raw read like the report forwarder: only an explicit `hooks.consult.enabled: true` opens the route. */
|
|
76
|
+
function consultRouteEnabled(): boolean {
|
|
77
|
+
try {
|
|
78
|
+
const config = JSON.parse(readFileSync(userConfigPath(), 'utf8')) as { hooks?: { consult?: { enabled?: unknown } } };
|
|
79
|
+
return config.hooks?.consult?.enabled === true;
|
|
80
|
+
} catch {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function consultOrigin(origin: string | null): string | null {
|
|
86
|
+
if (!origin) return null;
|
|
87
|
+
try {
|
|
88
|
+
const url = new URL(origin);
|
|
89
|
+
if (url.protocol !== 'https:' || url.origin !== origin) return null;
|
|
90
|
+
return url.hostname === 'elanous.ai' || url.hostname === 'www.elanous.ai' ||
|
|
91
|
+
/^[a-z0-9-]+\.vercel\.app$/i.test(url.hostname) ? origin : null;
|
|
92
|
+
} catch { return null; }
|
|
93
|
+
}
|
|
94
|
+
|
|
62
95
|
export function startHookReceiver(options: HookReceiverOptions): { url: string; stop: () => void; queue: HookQueue } {
|
|
63
96
|
const queue = new HookQueue(options.root);
|
|
64
97
|
const reportQueue = new ReportQueue(options.root ?? effectiveInstanceRoot(), (event, data) => debug.log('hooks.reports', event, data));
|
|
65
98
|
const reportLimiter = new ReportLimiter(options.now ?? Date.now);
|
|
66
99
|
const forwardReport = options.forwardReport ?? forwardReportToPrimary;
|
|
100
|
+
const consultEnabled = options.consultEnabled ?? consultRouteEnabled();
|
|
101
|
+
debug.log('hooks.consult', consultEnabled ? 'route-open' : 'route-closed', {});
|
|
102
|
+
const consultQueue = new ConsultQueue(options.root ?? effectiveInstanceRoot(), (_event, data) =>
|
|
103
|
+
debug.log('hooks.consult', 'rejected', { reason: 'expired', ...data }));
|
|
104
|
+
const consultLimiter = new ConsultLimiter(options.now ?? Date.now);
|
|
105
|
+
const forwardConsult = options.forwardConsult ?? forwardConsultToPrimary;
|
|
106
|
+
let consultFailures = 0;
|
|
107
|
+
let consultNextAt = 0;
|
|
108
|
+
let consultsDraining = false;
|
|
109
|
+
async function drainConsultQueue(): Promise<void> {
|
|
110
|
+
if (stopped || consultsDraining || Date.now() < consultNextAt) return;
|
|
111
|
+
consultsDraining = true;
|
|
112
|
+
try {
|
|
113
|
+
const result = await drainConsults(consultQueue, forwardConsult, (options.now ?? Date.now)());
|
|
114
|
+
if (result.delivered) debug.log('hooks.consult', 'forwarded', { queued: consultQueue.count(), delivered: result.delivered });
|
|
115
|
+
if (result.failed) {
|
|
116
|
+
consultFailures++;
|
|
117
|
+
consultNextAt = Date.now() + Math.min(300_000, Math.max(1, options.retryBaseMs ?? 1000) * 2 ** Math.min(consultFailures - 1, 20));
|
|
118
|
+
debug.log('hooks.consult', 'forward-failed', { queued: consultQueue.count(), reason: 'delivery-failed' });
|
|
119
|
+
} else consultFailures = 0;
|
|
120
|
+
} finally { consultsDraining = false; }
|
|
121
|
+
}
|
|
67
122
|
let reportFailures = 0;
|
|
68
123
|
let reportNextAt = 0;
|
|
69
124
|
let reportsDraining = false;
|
|
@@ -81,7 +136,12 @@ export function startHookReceiver(options: HookReceiverOptions): { url: string;
|
|
|
81
136
|
} finally { reportsDraining = false; }
|
|
82
137
|
}
|
|
83
138
|
const now = options.now ?? Date.now;
|
|
84
|
-
const
|
|
139
|
+
const events = options.events ?? getUserConfig().events ?? parseEventsConfig(undefined);
|
|
140
|
+
// L14: public-repository intake events take the shadow ledger path; every other event keeps the seat dispatch path.
|
|
141
|
+
const dispatch = options.forward ?? ((event: QueuedHook) => dispatchHook(event, options.root ?? effectiveInstanceRoot(), events, options.wakeSeat).then(() => 204));
|
|
142
|
+
const forward = (event: QueuedHook) => event.provider === 'github' && event.task.github
|
|
143
|
+
? recordGithubShadow(event, options.root ?? effectiveInstanceRoot(), options.githubFetch).then(() => 204)
|
|
144
|
+
: dispatch(event);
|
|
85
145
|
const attempts = new Map<string, { next: number; failures: number }>();
|
|
86
146
|
const pending = new Set<string>();
|
|
87
147
|
let stopped = false;
|
|
@@ -112,19 +172,35 @@ export function startHookReceiver(options: HookReceiverOptions): { url: string;
|
|
|
112
172
|
}
|
|
113
173
|
} finally {
|
|
114
174
|
void drainReportQueue();
|
|
175
|
+
void drainConsultQueue();
|
|
115
176
|
draining = false;
|
|
116
177
|
if (!stopped) timer = setTimeout(() => { void drain(); }, Math.min(1000, options.retryBaseMs ?? 1000));
|
|
117
178
|
}
|
|
118
179
|
}
|
|
119
180
|
const server = Bun.serve({ hostname: options.host ?? '127.0.0.1', port: options.port,
|
|
120
|
-
async fetch(request) {
|
|
181
|
+
async fetch(request, server) {
|
|
121
182
|
const url = new URL(request.url);
|
|
122
183
|
if (request.method === 'GET' && url.pathname === '/hooks/health')
|
|
123
184
|
return Response.json({ ok: true, queued: queue.count(), reportsQueued: reportQueue.count() });
|
|
124
185
|
if (request.method === 'POST' && url.pathname === '/v1/reports')
|
|
125
186
|
return handleReportPost(request, { limiter: reportLimiter, queue: reportQueue, ...(options.now ? { now: options.now } : {}),
|
|
126
187
|
log: (event, data) => debug.log('hooks.reports', event, data), wake: () => { reportNextAt = 0; void drainReportQueue(); } });
|
|
127
|
-
if (request.method
|
|
188
|
+
if (consultEnabled && url.pathname === '/v1/consult' && (request.method === 'POST' || request.method === 'OPTIONS')) {
|
|
189
|
+
const origin = consultOrigin(request.headers.get('origin'));
|
|
190
|
+
if (!origin) {
|
|
191
|
+
debug.log('hooks.consult', 'rejected', { reason: 'origin' });
|
|
192
|
+
return Response.json({ error: 'forbidden' }, { status: 403 });
|
|
193
|
+
}
|
|
194
|
+
const headers = { 'Access-Control-Allow-Origin': origin, Vary: 'Origin',
|
|
195
|
+
'Access-Control-Allow-Methods': 'POST, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type' };
|
|
196
|
+
if (request.method === 'OPTIONS') return new Response(null, { status: 204, headers });
|
|
197
|
+
const response = await handleConsultPost(request, { limiter: consultLimiter, queue: consultQueue, ...(options.now ? { now: options.now } : {}),
|
|
198
|
+
ip: server.requestIP(request)?.address ?? 'unknown',
|
|
199
|
+
log: (event, data) => debug.log('hooks.consult', event, data), wake: () => { consultNextAt = 0; void drainConsultQueue(); } });
|
|
200
|
+
for (const [key, value] of Object.entries(headers)) response.headers.set(key, value);
|
|
201
|
+
return response;
|
|
202
|
+
}
|
|
203
|
+
if (request.method !== 'POST' || !/^\/hooks\/(linear|asana|github)$/.test(url.pathname)) return new Response('Not Found', { status: 404 });
|
|
128
204
|
const provider = url.pathname.slice('/hooks/'.length) as HookProvider;
|
|
129
205
|
const reject = (reason: string) => {
|
|
130
206
|
debug.log('hooks.receiver', 'rejected', { provider, reason });
|
|
@@ -150,13 +226,15 @@ export function startHookReceiver(options: HookReceiverOptions): { url: string;
|
|
|
150
226
|
debug.log('hooks.receiver', 'ignored', { provider, kind: verified.ignored });
|
|
151
227
|
return new Response(null, { status: 200 });
|
|
152
228
|
}
|
|
153
|
-
if (provider === 'linear') {
|
|
229
|
+
if (provider === 'linear' || provider === 'github') {
|
|
154
230
|
const eventId = verified.eventIds[0]!;
|
|
155
|
-
|
|
231
|
+
const body = verified.body as { type?: string; action: string; githubEvent?: string };
|
|
232
|
+
const kind = provider === 'linear' ? `${body.type}:${body.action}` : `${body.githubEvent}:${body.action}`;
|
|
233
|
+
queue.enqueue({ provider, eventId, kind, task: toExternalTask(provider, { ...body, eventId }) });
|
|
156
234
|
} else {
|
|
157
235
|
const body = verified.body as { events: unknown[] };
|
|
158
|
-
const tasks = body.events.map(event => toExternalTask(provider, { event, task: (event as { task?: unknown }).task }));
|
|
159
|
-
for (const task of tasks) queue.enqueue({ provider, eventId: task.eventId, task });
|
|
236
|
+
const tasks = body.events.map(event => ({ event: event as { action?: string }, task: toExternalTask(provider, { event, task: (event as { task?: unknown }).task }) }));
|
|
237
|
+
for (const { event, task } of tasks) queue.enqueue({ provider, eventId: task.eventId, kind: `task:${event.action ?? 'unknown'}`, task });
|
|
160
238
|
}
|
|
161
239
|
if (!draining) {
|
|
162
240
|
if (timer) clearTimeout(timer);
|
package/src/index.ts
CHANGED
|
@@ -9,6 +9,7 @@ import { LOGS_SINCE_OPTION, registerLogsCommands } from './cli/logs-cli.js';
|
|
|
9
9
|
import { registerDocsCommands } from './cli/docs-cli.js';
|
|
10
10
|
import { registerA2ACommands } from './cli/a2a-cli.js';
|
|
11
11
|
import { registerPluginCommands } from './cli/plugin-cli.js';
|
|
12
|
+
import { registerMakeCommand } from './cli/make-cli.js';
|
|
12
13
|
import { registerConnectCommand, registerSkillsCommands } from './cli/skills-cli.js';
|
|
13
14
|
import { registerImportCommand } from './cli/import-cli.js';
|
|
14
15
|
import { registerPersonaCommands } from './cli/persona-cli.js';
|
|
@@ -873,8 +874,10 @@ seatCmd.command('loop').requiredOption('--seat <SEAT>', 'MK|OP|TC|UX')
|
|
|
873
874
|
.option('--json', 'JSON 출력')
|
|
874
875
|
.action(async (opts: { seat: string; once: boolean; json?: boolean }) => {
|
|
875
876
|
try {
|
|
876
|
-
|
|
877
|
-
|
|
877
|
+
// V3 F5: without the sink, the seat loop's judgment lines (seat.loop) never reach the log store when cron runs it.
|
|
878
|
+
await (await import('./domains/standalone-log-sink.js')).registerStandaloneLogSink('seat-loop');
|
|
879
|
+
const { runSeatLoopTurn } = await import('./seat-loop/seat-loop.js');
|
|
880
|
+
const result = await runSeatLoopTurn(opts.seat);
|
|
878
881
|
if (opts.json) await writeStdoutJson(`${JSON.stringify(result)}\n`);
|
|
879
882
|
else console.log(`seat loop ${opts.seat}: ${result.status}${'runId' in result && result.runId ? ` ${result.runId}` : ''}`);
|
|
880
883
|
} catch (error) { console.error(`seat loop: ${error instanceof Error ? error.message : String(error)}`); process.exitCode = 1; }
|
|
@@ -913,6 +916,7 @@ registerCardCommand(program);
|
|
|
913
916
|
registerLaunchHeadCommands(program);
|
|
914
917
|
registerA2ACommands(program);
|
|
915
918
|
registerPluginCommands(program);
|
|
919
|
+
registerMakeCommand(program);
|
|
916
920
|
registerSkillsCommands(program);
|
|
917
921
|
registerConnectCommand(program);
|
|
918
922
|
registerImportCommand(program);
|
|
@@ -3024,6 +3028,48 @@ const harnessOrchestrateCmd = registerHarnessOrchestrateCapabilityOptions(
|
|
|
3024
3028
|
await runHarnessOrchestrateExecution(plan, parts);
|
|
3025
3029
|
});
|
|
3026
3030
|
|
|
3031
|
+
const contextCmd = program.command('context').description('외부 에이전트 맥락 이벤트');
|
|
3032
|
+
contextCmd.command('hooks').description('Claude Code 맥락 훅 설정').command('install')
|
|
3033
|
+
.requiredOption('--print', '설정 조각만 출력하고 설정 파일은 수정하지 않음')
|
|
3034
|
+
.action(async () => {
|
|
3035
|
+
const { claudeHooksSettings } = await import('./context-bus/claude-hooks-install.js');
|
|
3036
|
+
console.log(claudeHooksSettings(REPOSITORY_ROOT));
|
|
3037
|
+
});
|
|
3038
|
+
contextCmd.command('emit [sessionKind]')
|
|
3039
|
+
.description('외부 에이전트 세션 이벤트: emit <kind> --seat <자리> --text <한 줄> [--ref <PR|칸>]')
|
|
3040
|
+
.option('--seat <seat>', 'OP|TC|MK|UX')
|
|
3041
|
+
.option('--text <line>', '한 줄 이벤트')
|
|
3042
|
+
.option('--ref <PR|cell>', '연결 PR 또는 칸')
|
|
3043
|
+
.option('--kind <kind>', '기존 Claude Code 훅 이벤트 종류')
|
|
3044
|
+
.option('--summary <line>', '기존 훅 한 줄 요약')
|
|
3045
|
+
.option('--source <link>', '기존 훅 출처 링크')
|
|
3046
|
+
.action(async (sessionKind: string | undefined, opts: { seat?: string; text?: string; ref?: string; kind?: string; summary?: string; source?: string }) => {
|
|
3047
|
+
try {
|
|
3048
|
+
if (sessionKind !== undefined) {
|
|
3049
|
+
if (opts.seat === undefined || opts.text === undefined || opts.kind !== undefined || opts.summary !== undefined || opts.source !== undefined) {
|
|
3050
|
+
throw new Error('context emit <kind> requires --seat and --text (not hook options)');
|
|
3051
|
+
}
|
|
3052
|
+
const { emitSessionEvent, SESSION_EVENT_KINDS } = await import('./context-bus/session-events.js');
|
|
3053
|
+
if (!SESSION_EVENT_KINDS.includes(sessionKind as import('./context-bus/session-events.js').SessionEventKind)) {
|
|
3054
|
+
throw new Error(`unknown context session kind: ${sessionKind}`);
|
|
3055
|
+
}
|
|
3056
|
+
emitSessionEvent({ kind: sessionKind as import('./context-bus/session-events.js').SessionEventKind,
|
|
3057
|
+
seat: opts.seat, text: opts.text, ...(opts.ref === undefined ? {} : { ref: opts.ref }) });
|
|
3058
|
+
} else {
|
|
3059
|
+
if (opts.seat !== undefined || opts.text !== undefined || opts.ref !== undefined || !opts.kind || opts.summary === undefined || opts.source === undefined) {
|
|
3060
|
+
throw new Error('context emit hook requires --kind, --summary and --source');
|
|
3061
|
+
}
|
|
3062
|
+
if (!['claimed', 'done', 'asked', 'guide-changed'].includes(opts.kind)) throw new Error(`unknown context hook kind: ${opts.kind}`);
|
|
3063
|
+
const { recordExternalEvent } = await import('./context-bus/external-events.js');
|
|
3064
|
+
recordExternalEvent({ origin: 'claude-code', kind: opts.kind as import('./context-bus/external-events.js').ContextHookKind,
|
|
3065
|
+
summary: opts.summary, source: opts.source });
|
|
3066
|
+
}
|
|
3067
|
+
} catch (error) {
|
|
3068
|
+
console.error(`context emit: ${error instanceof Error ? error.message : String(error)}`);
|
|
3069
|
+
process.exitCode = 2;
|
|
3070
|
+
}
|
|
3071
|
+
});
|
|
3072
|
+
|
|
3027
3073
|
const coordCmd = program.command('coord').description('조율 채널 맥락 원장');
|
|
3028
3074
|
coordCmd.command('event').command('record')
|
|
3029
3075
|
.requiredOption('--seat <ID>', '발신 자리')
|
|
@@ -3975,11 +4021,12 @@ selfCmd
|
|
|
3975
4021
|
.option('--changed', '변경 파일 범위 게이트임을 명시한다')
|
|
3976
4022
|
.option('--base <ref>', '커밋됐지만 PR 없는 변경의 비교 기준(ref...HEAD)')
|
|
3977
4023
|
.option('--pr <number>', '열린 PR 번호에서 gh pr view files로 변경 파일을 읽는다')
|
|
3978
|
-
.
|
|
3979
|
-
|
|
4024
|
+
.option('--shards [number]', '메모리 예산에 맞춰 시험을 별도 프로세스로 분할한다 (기본 2)')
|
|
4025
|
+
.action((opts: { changed?: boolean; base?: string; pr?: string; shards?: string | boolean }) => {
|
|
4026
|
+
if (!opts.changed && opts.shards === undefined) { ui.error('self gate requires --changed or --shards'); process.exitCode = 2; return; }
|
|
3980
4027
|
try {
|
|
3981
4028
|
const { runSelfGateCli } = require('./self-implement/gate-cli.js') as typeof import('./self-implement/gate-cli.js');
|
|
3982
|
-
const result = runSelfGateCli(process.cwd(), { base: opts.base, pr: opts.pr });
|
|
4029
|
+
const result = runSelfGateCli(process.cwd(), { base: opts.base, pr: opts.pr, shards: opts.shards === undefined ? undefined : opts.shards === true ? 2 : Number(opts.shards) });
|
|
3983
4030
|
console.log(result.lines.join('\n'));
|
|
3984
4031
|
process.exitCode = result.exitCode;
|
|
3985
4032
|
} catch (error) {
|
|
@@ -4011,7 +4058,8 @@ selfCmd
|
|
|
4011
4058
|
// runSelfImplement(내부 SelfImplement 툴과 동일 코어)를 감싼다: fork→worktree→헤드리스 goal-loop
|
|
4012
4059
|
// (+클린빌드 앵커)→gate(bun test)→PR(HITL). PR-open 은 --open-pr(명시 승인)일 때만·기본 fail-closed.
|
|
4013
4060
|
selfCmd
|
|
4014
|
-
.command('implement
|
|
4061
|
+
.command('implement [feature...]')
|
|
4062
|
+
.option('--feature-file <path>', 'feature 문면을 파일에서 읽는다 (문면을 argv 에 싣지 않음)')
|
|
4015
4063
|
.description('자율 구현(self-build) — feature 를 격리 worktree 에서 goal-loop + 클린빌드 앵커로 끝까지 구현하고 gate(bun test) 통과까지. --config-dir 의 provider 로 모델 선택(gemma 등). PR-open 은 --open-pr(HITL 명시승인)일 때만. 수분 소요.')
|
|
4016
4064
|
.option('--base <branch>', 'PR base 브랜치(생략 시 provider 기본)')
|
|
4017
4065
|
.option('--no-draft', 'non-draft PR (기본 draft)')
|
|
@@ -4029,8 +4077,11 @@ selfCmd
|
|
|
4029
4077
|
.option('--no-supervise', '⛔ 런 슈퍼바이저를 «끈다»(대표 2026-08-22: ***기본 ON***) — 켜져 있으면 실행이 끝나면 실패를 «트리아지»해서 다시 걸 수 있으면 스스로 재개한다(끝까지). 정지 사유는 converged|needs-human|max-rounds|no-progress 로 각각 «다른 값». 관측=elanous logs --category self-dev.supervisor')
|
|
4030
4078
|
.option('--supervise-rounds <n>', '슈퍼바이저 재개 라운드 상한 (기본 3 · 끄려면 --no-supervise)')
|
|
4031
4079
|
.option('--json', '구조화 출력 {stage, ok, branch, worktree, prUrl?, merged?}')
|
|
4032
|
-
.action(async (parts: string[], opts: { base?: string; draft?: boolean; openPr?: boolean; autoMerge?: boolean; autoReview?: boolean; maxWait?: string; json?: boolean; plan?: boolean; enhance?: boolean; ground?: boolean; observeOnly?: boolean }) => {
|
|
4033
|
-
|
|
4080
|
+
.action(async (parts: string[], opts: { featureFile?: string; base?: string; draft?: boolean; openPr?: boolean; autoMerge?: boolean; autoReview?: boolean; maxWait?: string; json?: boolean; plan?: boolean; enhance?: boolean; ground?: boolean; observeOnly?: boolean }) => {
|
|
4081
|
+
if (opts.featureFile && parts.length > 0) { ui.error('--feature-file 과 위치 인자 feature 는 함께 줄 수 없다'); process.exit(2); }
|
|
4082
|
+
let feature: string;
|
|
4083
|
+
try { feature = (opts.featureFile ? readFileSync(opts.featureFile, 'utf8') : parts.join(' ')).trim(); }
|
|
4084
|
+
catch (error) { ui.error(`--feature-file 읽기 실패: ${String(error)}`); process.exit(2); return; }
|
|
4034
4085
|
if (!feature) { ui.error('feature 필요: elanous self implement "<무엇을 구현할지>"'); process.exit(2); }
|
|
4035
4086
|
// Retired entry points must fail before run identity or log-sink setup creates observable execution state.
|
|
4036
4087
|
if (opts.plan) { ui.error('self implement --plan is retired and rejected'); process.exit(1); return; }
|
|
@@ -4128,8 +4179,14 @@ export function setSelfOrchestrateSpawnForTesting(spawn: typeof selfOrchestrateS
|
|
|
4128
4179
|
selfOrchestrateSpawnForTesting = spawn;
|
|
4129
4180
|
}
|
|
4130
4181
|
|
|
4182
|
+
export function readSelfOrchestrateGoals(parts: string[], goalFiles: readonly string[] = []): { request: string; goals: string[] } {
|
|
4183
|
+
const fileGoals = goalFiles.map((path) => readFileSync(path, 'utf8'));
|
|
4184
|
+
return { request: [...parts, ...fileGoals].join(' '), goals: [...splitOrchestrateGoalTexts(parts), ...fileGoals] };
|
|
4185
|
+
}
|
|
4186
|
+
|
|
4131
4187
|
const selfOrchestrateCmd = selfCmd
|
|
4132
4188
|
.command('orchestrate [goals...]')
|
|
4189
|
+
.option('--goal-file <path>', '골 문면을 파일에서 읽는다 (반복 가능)', (value: string, acc: string[]) => [...acc, value], [] as string[])
|
|
4133
4190
|
.description('병렬 self-dev — 여러 goal 을 각자 격리 worktree self-implement 서브프로세스로 동시성캡 병렬 실행. goal 은 `;;` 로 구분(또는 각 인자 1 goal). --concurrency 로 동시 잡 수(기본 2).')
|
|
4134
4191
|
.option('--concurrency <n>', '동시 실행 잡 수 (기본 2)')
|
|
4135
4192
|
.option('--auto-merge', '각 잡: 리뷰 clean 시 자동 병합(각 self-implement 에 --auto-merge 전달·리뷰노드 경유)')
|
|
@@ -4138,7 +4195,7 @@ const selfOrchestrateCmd = selfCmd
|
|
|
4138
4195
|
.option('--base <branch>', '각 잡 PR base 브랜치')
|
|
4139
4196
|
.option('--decompose', 'S2 — goal 1개를 LLM 으로 의존성 서브-DAG(위상 병렬 + hot-file 직렬)로 분해 후 실행')
|
|
4140
4197
|
.addOption(new Option('--pod-skill-env', 'pod: 필수 스킬(설정 pod-skills.txt)의 키(.env)를 이 런의 Secret 으로 넘긴다 — 명시 opt-in(유료 크레딧) · 이미지엔 안 들어간다').hideHelp())
|
|
4141
|
-
.addOption(new Option('--pod-pool <spec>', 'pod 풀 — 컨텍스트[@ssh호스트][:상한]
|
|
4198
|
+
.addOption(new Option('--pod-pool <spec>', 'pod 풀 — 컨텍스트[@ssh호스트][:상한][#k3d-레지스트리:포트] 쉼표, 앞이 우선(예 pool-node-b@node-b:12#k3d-elanous-registry:5051,pool-node-c@node-c:3#k3d-elanous-registry:5052) · 없으면 ELANOUS_POD_POOL · 그것도 없으면 현재 컨텍스트 하나').hideHelp())
|
|
4142
4199
|
.addOption(new Option('--reduce', '끝에 PR 을 연 조각들을 통합 브랜치 하나로 모아(게이트 한 번) PR 하나 — `--open-pr` 과 짝 · `--auto-merge` 와는 함께 못 쓴다(elanous self reduce)').hideHelp())
|
|
4143
4200
|
.option('--substrate <kind>', '실행 칸: local(기본 · 격리 워크트리) | pod(k8s Job · docker/harness 이미지 · MANUAL-pods-for-elanous-ops-and-dev)')
|
|
4144
4201
|
.option('--pod-account <name>', 'pod: codex 계정(~/.elanous/auth.json openai-codex:<name> · refresh 제외 사본) · 없으면 브로커가 Job 마다 잔량 많은 계정을 돌려 준다')
|
|
@@ -4146,11 +4203,14 @@ const selfOrchestrateCmd = selfCmd
|
|
|
4146
4203
|
.option('--pod-pass-env <keys>', 'pod: 호스트 env 에서 Pod 로 넘길 키(쉼표) — 예 OPENROUTER_API_KEY,ANTHROPIC_API_KEY(벤치마크 과금 경로)')
|
|
4147
4204
|
.option('--bench-arms <spec>', 'pod 벤치마크: 골 1개를 팔마다 «라벨 한 줄만 다르게» 복제해 동시에 — "id=provider[:model][@KEY+KEY];…" (예 codex=openai-codex;or-kimi=openrouter:openrouter/moonshotai/kimi-k3@OPENROUTER_API_KEY) · --auto-merge 거부 · RFC fleet 슈퍼바이저 §A3')
|
|
4148
4205
|
.option('--help-all', '모든 orchestrate 옵션 표시')
|
|
4149
|
-
.action(function (this: Command, parts: string[], opts: { concurrency?: string; autoMerge?: boolean; autoReview?: boolean; openPr?: boolean; base?: string; teardown?: boolean; resume?: string; board?: boolean; decompose?: boolean; fabricDecompose?: boolean; maxTasks?: string; supervise?: boolean; superviseRounds?: string; json?: boolean }) {
|
|
4206
|
+
.action(function (this: Command, parts: string[], opts: { goalFile?: string[]; concurrency?: string; autoMerge?: boolean; autoReview?: boolean; openPr?: boolean; base?: string; teardown?: boolean; resume?: string; board?: boolean; decompose?: boolean; fabricDecompose?: boolean; maxTasks?: string; supervise?: boolean; superviseRounds?: string; json?: boolean }) {
|
|
4150
4207
|
return (async () => {
|
|
4151
|
-
//
|
|
4152
|
-
|
|
4153
|
-
|
|
4208
|
+
// 위치 인자는 종전처럼 분리하고 파일 입력은 파일당 한 골이다.
|
|
4209
|
+
let inputGoals: ReturnType<typeof readSelfOrchestrateGoals>;
|
|
4210
|
+
try { inputGoals = readSelfOrchestrateGoals(parts, opts.goalFile); }
|
|
4211
|
+
catch (error) { ui.error(`--goal-file 읽기 실패: ${String(error)}`); process.exit(2); return; }
|
|
4212
|
+
const joined = inputGoals.request;
|
|
4213
|
+
let goalTexts = inputGoals.goals;
|
|
4154
4214
|
if ((opts as { reduce?: boolean }).reduce && opts.autoMerge) { ui.error('--reduce 는 --auto-merge 와 함께 못 쓴다 — 조각을 하나씩 main 에 병합하는 것과 하나로 모으는 것은 반대다(--open-pr 과 짝)'); process.exit(2); }
|
|
4155
4215
|
// ☸️ 벤치 팔 — 골 1개를 팔마다 라벨 한 줄만 다르게(A/B 매뉴얼 ②) · pod 전용 · 자동 머지 금지(한 팔이 머지되면 다른 팔의 밑 땅이 바뀐다).
|
|
4156
4216
|
const benchSpec = (opts as { benchArms?: string }).benchArms;
|
|
@@ -6298,7 +6358,7 @@ const selfDevCmd = program
|
|
|
6298
6358
|
// `drive --help` 에도 그대로 보이고 자식이 그것을 계약으로 읽는다.
|
|
6299
6359
|
// ⇒ 별칭을 없애지 않는다([[RFC-two-command-convergence-dev-and-pty-2026-07-28]] §6-2 = 층이 다르니
|
|
6300
6360
|
// `drive` 는 프리미티브로 **유지**한다) — 대신 **도움말이 그 갈림을 먼저 말하게** 한다.
|
|
6301
|
-
.description('⛔ `drive` 별칭으로 부르면 옵션은
|
|
6361
|
+
.description('⛔ `drive` 별칭으로 부르면 옵션은 아홉뿐 (--goal · --attach · --max-steps · --poll-ms · --model · --cwd · --worktree · --json · --jail-home) — `--attach <ref>` 는 이미 있는 PTY 를 몬다(생략하면 셸 명령을 새로 띄운다). 나머지는 전부 `dev` 전용이고 `drive` 에서는 거부된다. dev 와 drive 는 한 명령이라 이 도움말을 공유하므로, 아래 목록은 `dev` 기준이다. ⚠️ 실험 — 통합 self-dev 파이프라인 runDevPipeline. --backend self(디폴트·elanous-chat 자체구현)|codex/claude/gemini/grok(외부). --transport pty(디폴트·worktree·--branch 필수)|acp(cwd 세션·U6·capability 미검증). 미배선 조합은 NotYetUnified 명시 거부. ★self 는 무인 완결이 기본(PR 개설→auto-review 라벨→리뷰 clean 시 병합) — 끄려면 --no-open-pr/--no-auto-review/--no-auto-merge. 관측=elanous logs --category dev-pipeline · 상세=docs/manual/MANUAL-frontdoor-selfdev-dogfood-mechanism-2026-07-25.md')
|
|
6302
6362
|
.option('--file <path>', 'input 파일(verbatim 바이트·<text...> 대신)')
|
|
6303
6363
|
// ⭐ 대표 2026-08-11 — 발사 절차 «넷»을 한 명령으로. ask 파일을 주면 ⑴저작 → ⑵열린 PR ⊕ ⑶도는 런 검사 → ⑷발사.
|
|
6304
6364
|
// ⛔ 걸리면 «이름을 대며» 멈춘다(조용히 진행하지 않는다). 우회는 --force-preflight 이고 그 사실이 관측에 남는다.
|
|
@@ -6324,6 +6384,7 @@ const selfDevCmd = program
|
|
|
6324
6384
|
.option('-n, --max-steps <n>', 'elanous 또는 셸 drive: 최대 제어 스텝(기본 30)')
|
|
6325
6385
|
.option('-p, --poll-ms <ms>', 'elanous 또는 셸 drive: 제어 스텝 간 폴 간격(ms·0 허용·기본 800)')
|
|
6326
6386
|
.option('--attach <ref>', 'drive: 이미 있는 PTY 를 몬다(생략하면 셸 명령을 새로 띄운다·pty auto 와 같은 루프)')
|
|
6387
|
+
.option('--jail-home <dir>', 'drive: DRIVE-JAIL — 두뇌 입력에 이 디렉터리 밖 경로가 있으면 PTY 로 보내지 않는다')
|
|
6327
6388
|
.option('-m, --model <id>', 'elanous 또는 셸 drive: 제어 brain LLM 모델(기본 config)')
|
|
6328
6389
|
.option('--observe-only', 'elanous: child boot부터 SelfImplement 호출을 기록만 한다')
|
|
6329
6390
|
.option('--isolated-root <path>', 'elanous: child config/state 격리 루트(설정 실패 시 fail-closed)')
|
|
@@ -6620,6 +6681,7 @@ const selfDevCmd = program
|
|
|
6620
6681
|
...(devOpts.worktree === true ? { worktree: true } : {}),
|
|
6621
6682
|
...(opts.json === true ? { json: true } : {}),
|
|
6622
6683
|
attach: devOpts.attach,
|
|
6684
|
+
...(devOpts.jailHome ? { jailHome: devOpts.jailHome } : {}),
|
|
6623
6685
|
}, {
|
|
6624
6686
|
exit: ((code: number): never => {
|
|
6625
6687
|
completionGuard.conclude();
|
|
@@ -25,6 +25,7 @@ import type {
|
|
|
25
25
|
} from './enrich.js';
|
|
26
26
|
import { summariseContext } from './enrich.js';
|
|
27
27
|
import { buildResponseFormatHeader } from './prompt-format.js';
|
|
28
|
+
import { judge } from '../llm/judge-layer.js';
|
|
28
29
|
|
|
29
30
|
// ──────────────────── Closed sets ──────────────────────────────────────
|
|
30
31
|
|
|
@@ -69,7 +70,7 @@ export interface CategorizeResult {
|
|
|
69
70
|
}
|
|
70
71
|
|
|
71
72
|
export interface CategorizeCallable {
|
|
72
|
-
(args: { prompt: string; signal?: AbortSignal }): Promise<{
|
|
73
|
+
(args: { prompt: string; signal?: AbortSignal; provider?: string; model?: string }): Promise<{
|
|
73
74
|
text: string;
|
|
74
75
|
promptTokens?: number;
|
|
75
76
|
completionTokens?: number;
|
|
@@ -219,26 +220,6 @@ export function buildCategorizePrompt(decomposition: EnrichedDecomposition): str
|
|
|
219
220
|
|
|
220
221
|
// ──────────────────── Parse + coerce ──────────────────────────────────
|
|
221
222
|
|
|
222
|
-
function extractJsonBlock(text: string): unknown | null {
|
|
223
|
-
const trimmed = text.trim();
|
|
224
|
-
const fence = trimmed.match(/```(?:json)?\n([\s\S]*?)```/);
|
|
225
|
-
const candidate = fence ? fence[1]! : trimmed;
|
|
226
|
-
try {
|
|
227
|
-
return JSON.parse(candidate);
|
|
228
|
-
} catch {
|
|
229
|
-
const open = candidate.indexOf('{');
|
|
230
|
-
const close = candidate.lastIndexOf('}');
|
|
231
|
-
if (open >= 0 && close > open) {
|
|
232
|
-
try {
|
|
233
|
-
return JSON.parse(candidate.slice(open, close + 1));
|
|
234
|
-
} catch {
|
|
235
|
-
return null;
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
return null;
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
|
|
242
223
|
function coerceConfidence(v: unknown): 'high' | 'medium' | 'low' {
|
|
243
224
|
if (v === 'high' || v === 'medium' || v === 'low') return v;
|
|
244
225
|
return 'medium';
|
|
@@ -306,27 +287,18 @@ export async function categorizeDecomposition(
|
|
|
306
287
|
|
|
307
288
|
const prompt = buildCategorizePrompt(decomposition);
|
|
308
289
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
'LLM_CALL_FAILED',
|
|
316
|
-
err instanceof Error ? err.message : String(err),
|
|
317
|
-
);
|
|
318
|
-
}
|
|
319
|
-
return {
|
|
320
|
-
categorizations: Object.fromEntries(tasks.map((t) => [t.key, fallbackRow(t.key)])),
|
|
321
|
-
fallback: true,
|
|
322
|
-
};
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
const parsed = extractJsonBlock(raw.text);
|
|
326
|
-
const coerced = parsed ? coerceCategorizations(parsed, validKeys) : null;
|
|
327
|
-
if (coerced === null) {
|
|
290
|
+
const decision = await judge({
|
|
291
|
+
site: 'intake.categorize', prompt, signal: opts.signal,
|
|
292
|
+
call: ({ prompt, signal, provider, model }) => opts.callable({ prompt, signal, provider, model }),
|
|
293
|
+
schema: (parsed) => coerceCategorizations(parsed, validKeys),
|
|
294
|
+
});
|
|
295
|
+
if (!decision.ok) {
|
|
328
296
|
if (opts.strict) {
|
|
329
|
-
|
|
297
|
+
if (decision.reason === 'call') {
|
|
298
|
+
throw new CategorizeError('LLM_CALL_FAILED',
|
|
299
|
+
decision.error instanceof Error ? decision.error.message : String(decision.error));
|
|
300
|
+
}
|
|
301
|
+
throw new CategorizeError('PARSE_FAILED', 'no usable categorizations', decision.rawText);
|
|
330
302
|
}
|
|
331
303
|
return {
|
|
332
304
|
categorizations: Object.fromEntries(tasks.map((t) => [t.key, fallbackRow(t.key)])),
|
|
@@ -336,7 +308,7 @@ export async function categorizeDecomposition(
|
|
|
336
308
|
|
|
337
309
|
// Backfill any missing tasks with the fallback shape so callers can
|
|
338
310
|
// index by key without null checks.
|
|
339
|
-
const filled: Record<string, TaskCategorization> = { ...
|
|
311
|
+
const filled: Record<string, TaskCategorization> = { ...decision.value };
|
|
340
312
|
for (const t of tasks) {
|
|
341
313
|
if (!filled[t.key]) filled[t.key] = fallbackRow(t.key);
|
|
342
314
|
}
|
|
@@ -344,10 +316,10 @@ export async function categorizeDecomposition(
|
|
|
344
316
|
categorizations: filled,
|
|
345
317
|
fallback: false,
|
|
346
318
|
usage: {
|
|
347
|
-
promptTokens:
|
|
348
|
-
completionTokens:
|
|
349
|
-
costUsd:
|
|
350
|
-
modelId:
|
|
319
|
+
promptTokens: decision.reply.promptTokens,
|
|
320
|
+
completionTokens: decision.reply.completionTokens,
|
|
321
|
+
costUsd: decision.reply.costUsd,
|
|
322
|
+
modelId: decision.reply.modelId,
|
|
351
323
|
},
|
|
352
324
|
};
|
|
353
325
|
}
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import { debug } from '../debug/log.js';
|
|
2
2
|
import { discordDecisionOwner } from '../decisions/discord-decision-cards.js';
|
|
3
3
|
import { canonicalSeatId } from '../msg/msg-store.js';
|
|
4
|
+
import { awaitGlobalPersonaLoad, getGlobalPersonaRegistry } from '../persona/global-registry.js';
|
|
5
|
+
import type { PersonaSource } from '../persona/mention-parser.js';
|
|
4
6
|
import { dispatchCeoTask, type CeoCommandDeps } from '../seat-dispatch/ceo-commands.js';
|
|
5
7
|
import { ceoTaskDeps, classifyCeoIntent } from '../seat-dispatch/ceo-intent.js';
|
|
8
|
+
import { askSeat, parseSeatAsk, type SeatAskDeps } from '../seat-dispatch/seat-ask.js';
|
|
6
9
|
import { parseSeatAddress, resolveSeat } from '../seat-address/seat-address.js';
|
|
7
10
|
import { getUserConfig, type UserConfig } from '../user-config.js';
|
|
8
11
|
import { answerAsSeat } from './seat-answer.js';
|
|
12
|
+
import { answerAsPersona, resolvePersonaAddress, type PersonaAnswerDeps } from './persona-answer.js';
|
|
9
13
|
import {
|
|
10
14
|
submitIntakeWork,
|
|
11
15
|
type SubmitIntakeWorkDeps,
|
|
@@ -23,8 +27,12 @@ export interface DiscordSeatWorkDeps extends SubmitIntakeWorkDeps {
|
|
|
23
27
|
submit?: typeof submitIntakeWork;
|
|
24
28
|
config?: UserConfig;
|
|
25
29
|
answer?: typeof answerAsSeat;
|
|
30
|
+
personaSource?: PersonaSource;
|
|
31
|
+
personaAnswer?: typeof answerAsPersona;
|
|
32
|
+
personaAnswerDeps?: PersonaAnswerDeps;
|
|
26
33
|
dispatch?: typeof dispatchCeoTask;
|
|
27
34
|
commandDeps?: CeoCommandDeps;
|
|
35
|
+
askDeps?: SeatAskDeps;
|
|
28
36
|
}
|
|
29
37
|
|
|
30
38
|
/** Addressed work preserves graph intake except for one owner's private seat request. */
|
|
@@ -44,7 +52,15 @@ export async function handleDiscordSeatWork(
|
|
|
44
52
|
debug.log('seat.dispatch', 'intent', { seat, intent: 'task', via: 'discord', outcome: result.channel });
|
|
45
53
|
return result.reply;
|
|
46
54
|
};
|
|
47
|
-
|
|
55
|
+
if (parseSeatAsk(text)) {
|
|
56
|
+
const auth = owner();
|
|
57
|
+
if (!auth) return null;
|
|
58
|
+
if (!deps.askDeps) throw new Error('seat ask delivery unavailable');
|
|
59
|
+
return askSeat(text, { channel: 'discord', channelId: msg.channelId, messageId: msg.messageId,
|
|
60
|
+
...(msg.threadId ? { threadId: msg.threadId } : {}) },
|
|
61
|
+
deps.commandDeps ?? ceoTaskDeps(auth.cfg, auth.id), deps.askDeps);
|
|
62
|
+
}
|
|
63
|
+
const address = parseSeatAddress(text.replace(/^(@[A-Za-z][A-Za-z0-9_-]*(?:,@?[A-Za-z][A-Za-z0-9_-]*)*)/, (prefix) => prefix.replaceAll(',@', ',')));
|
|
48
64
|
if (!address) {
|
|
49
65
|
if (!text.trim() || /^\s*[/@@]/.test(text)) return null;
|
|
50
66
|
const auth = owner();
|
|
@@ -57,11 +73,31 @@ export async function handleDiscordSeatWork(
|
|
|
57
73
|
}
|
|
58
74
|
|
|
59
75
|
const seats = address.seats.map((name) => ({ name, seat: resolveSeat(name) }));
|
|
60
|
-
const
|
|
76
|
+
const hasUnresolved = seats.some(({ seat }) => !seat);
|
|
77
|
+
const auth = hasUnresolved ? owner() : null;
|
|
78
|
+
if (hasUnresolved && auth && !deps.personaSource) await awaitGlobalPersonaLoad();
|
|
79
|
+
const source = hasUnresolved && auth ? (deps.personaSource ?? getGlobalPersonaRegistry()) : null;
|
|
80
|
+
const addressed = seats.map(({ name, seat }) => ({
|
|
81
|
+
name, seat, persona: !seat && source ? resolvePersonaAddress(name, source) : null,
|
|
82
|
+
}));
|
|
83
|
+
const unknown = addressed.filter(({ seat, persona }) => !seat && (!persona || !auth)).map(({ name }) => `@${name}`);
|
|
61
84
|
if (unknown.length) return `어느 좌석을 말씀하시나요? ${unknown.join(', ')}은(는) 등록된 좌석이 아닙니다. 좌석을 확인해 다시 보내 주세요.`;
|
|
85
|
+
const personas = addressed.filter(({ persona }) => persona);
|
|
86
|
+
if (personas.length && addressed.length !== 1) {
|
|
87
|
+
debug.log('persona.address', 'rejected', { reason: 'mixed', via: 'discord' });
|
|
88
|
+
return '페르소나는 한 번에 하나만 부를 수 있습니다';
|
|
89
|
+
}
|
|
62
90
|
const body = address.body.trim();
|
|
63
91
|
if (!body) return '어떤 일을 맡길까요? 좌석 주소 뒤에 요청 내용을 적어 다시 보내 주세요.';
|
|
64
92
|
|
|
93
|
+
if (personas.length === 1 && personas[0]?.persona) {
|
|
94
|
+
const { name, persona } = personas[0];
|
|
95
|
+
debug.log('persona.address', 'resolved', { name, personaId: persona.personaId, via: 'discord' });
|
|
96
|
+
const answer = await (deps.personaAnswer ?? answerAsPersona)(persona, body, deps.personaAnswerDeps);
|
|
97
|
+
debug.log('persona.address', 'answered', { personaId: persona.personaId, via: 'discord' });
|
|
98
|
+
return answer;
|
|
99
|
+
}
|
|
100
|
+
|
|
65
101
|
if (seats.length === 1 && seats[0]?.seat) {
|
|
66
102
|
const auth = owner();
|
|
67
103
|
const seatId = canonicalSeatId(seats[0].seat.id);
|