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
|
@@ -73,6 +73,7 @@ export function publishWorkflowRunEvent(
|
|
|
73
73
|
const detail: Record<string, unknown> = {
|
|
74
74
|
runId: ctx.runId,
|
|
75
75
|
workflowName: ctx.workflowName,
|
|
76
|
+
...(evt.mode !== undefined ? { mode: evt.mode } : {}),
|
|
76
77
|
};
|
|
77
78
|
if (evt.type === 'node_start' || evt.type === 'node_skipped' || evt.type === 'node_done') {
|
|
78
79
|
detail.nodeId = evt.nodeId;
|
|
@@ -32,7 +32,9 @@ import { requirePosixShellCommand } from '../../platform/default-shell.js';
|
|
|
32
32
|
import { spawn } from 'child_process';
|
|
33
33
|
import { existsSync, readFileSync, readdirSync, statSync } from 'fs';
|
|
34
34
|
import { join } from 'path';
|
|
35
|
+
import { debug } from '../../debug/log.js';
|
|
35
36
|
import { elanousStateRoot } from '../../autopilot/state-paths.js';
|
|
37
|
+
import { getWorkflowHistoryVersion, listWorkflowHistory, snapshotBeforeSave } from './workflow-history.js';
|
|
36
38
|
import {
|
|
37
39
|
deleteWorkflow,
|
|
38
40
|
discoverWorkflows,
|
|
@@ -40,8 +42,12 @@ import {
|
|
|
40
42
|
parseWorkflowYaml,
|
|
41
43
|
runWorkflow,
|
|
42
44
|
saveWorkflow,
|
|
45
|
+
topoSort,
|
|
43
46
|
type WorkflowDeps,
|
|
44
47
|
type WorkflowEvent,
|
|
48
|
+
type WorkflowRunMode,
|
|
49
|
+
type NodeOutput,
|
|
50
|
+
type RunWorkflowOpts,
|
|
45
51
|
} from '../../workflow-runtime/index.js';
|
|
46
52
|
import { buildRunCft, buildRunSkill } from '../../workflow-runtime/deps-bridge.js';
|
|
47
53
|
import {
|
|
@@ -59,6 +65,7 @@ import { runApprovalAcrossChannels } from './workflow-approval-multi-channel.js'
|
|
|
59
65
|
interface RunRecord {
|
|
60
66
|
runId: string;
|
|
61
67
|
workflowName: string;
|
|
68
|
+
mode: WorkflowRunMode;
|
|
62
69
|
startedAt: number;
|
|
63
70
|
events: WorkflowEvent[];
|
|
64
71
|
/** Settled state: undefined while running, true on workflow_done,
|
|
@@ -227,6 +234,45 @@ export function handleWorkflowGet(
|
|
|
227
234
|
);
|
|
228
235
|
}
|
|
229
236
|
|
|
237
|
+
export function handleWorkflowHistoryList(
|
|
238
|
+
req: Request,
|
|
239
|
+
name: string,
|
|
240
|
+
opts: MetaApiOpts,
|
|
241
|
+
): Response {
|
|
242
|
+
if (!checkAuth(req, opts)) return jsonResponse({ error: 'unauthorized' }, 401);
|
|
243
|
+
if (req.method !== 'GET') return jsonResponse({ error: 'method-not-allowed', method: req.method }, 405);
|
|
244
|
+
const scope = new URL(req.url).searchParams.get('scope') === 'global' ? 'global' : 'project';
|
|
245
|
+
try {
|
|
246
|
+
return jsonResponse({ versions: listWorkflowHistory(name, { scope }) }, 200);
|
|
247
|
+
} catch (err) {
|
|
248
|
+
if (err instanceof Error && err.message === 'invalid workflow name') {
|
|
249
|
+
return jsonResponse({ error: 'bad_request', reason: err.message }, 400);
|
|
250
|
+
}
|
|
251
|
+
throw err;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
export function handleWorkflowHistoryVersionGet(
|
|
256
|
+
req: Request,
|
|
257
|
+
name: string,
|
|
258
|
+
id: string,
|
|
259
|
+
opts: MetaApiOpts,
|
|
260
|
+
): Response {
|
|
261
|
+
if (!checkAuth(req, opts)) return jsonResponse({ error: 'unauthorized' }, 401);
|
|
262
|
+
if (req.method !== 'GET') return jsonResponse({ error: 'method-not-allowed', method: req.method }, 405);
|
|
263
|
+
const scope = new URL(req.url).searchParams.get('scope') === 'global' ? 'global' : 'project';
|
|
264
|
+
try {
|
|
265
|
+
const yaml = getWorkflowHistoryVersion(name, id, { scope });
|
|
266
|
+
if (yaml === null) return jsonResponse({ error: 'not_found', name, id }, 404);
|
|
267
|
+
return jsonResponse({ yaml }, 200);
|
|
268
|
+
} catch (err) {
|
|
269
|
+
if (err instanceof Error && (err.message === 'invalid workflow name' || err.message === 'invalid workflow history version id')) {
|
|
270
|
+
return jsonResponse({ error: 'bad_request', reason: err.message }, 400);
|
|
271
|
+
}
|
|
272
|
+
throw err;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
230
276
|
export async function handleWorkflowPut(
|
|
231
277
|
req: Request,
|
|
232
278
|
name: string,
|
|
@@ -243,6 +289,17 @@ export async function handleWorkflowPut(
|
|
|
243
289
|
return jsonResponse({ error: 'bad_request', reason: '`yaml` must be a string' }, 400);
|
|
244
290
|
}
|
|
245
291
|
const scope = scopeRaw === 'global' ? 'global' : 'project';
|
|
292
|
+
const parsed = parseWorkflowYaml(yamlText);
|
|
293
|
+
if (parsed.ok && parsed.workflow?.name === name) {
|
|
294
|
+
// Capture the existing file before saveWorkflow overwrites it; a failed snapshot is non-fatal.
|
|
295
|
+
try {
|
|
296
|
+
snapshotBeforeSave(name, { scope });
|
|
297
|
+
} catch (err) {
|
|
298
|
+
debug.log('nexus.workflow-history', 'snapshot-failed', {
|
|
299
|
+
name, scope, error: err instanceof Error ? err.message : String(err),
|
|
300
|
+
}, { level: 'warn' });
|
|
301
|
+
}
|
|
302
|
+
}
|
|
246
303
|
const r = saveWorkflow(name, yamlText, { scope });
|
|
247
304
|
if (!r.ok) {
|
|
248
305
|
return jsonResponse(
|
|
@@ -384,10 +441,51 @@ export async function handleWorkflowRunStart(
|
|
|
384
441
|
// so the PWA "▶ Run now" button runs the dependent chain straight
|
|
385
442
|
// through. Default false preserves the production wire.
|
|
386
443
|
const dryRun: boolean = Boolean(body && typeof body === 'object' && (body as { dryRun?: unknown }).dryRun === true);
|
|
444
|
+
const input = body && typeof body === 'object' ? body as Record<string, unknown> : {};
|
|
445
|
+
const { onlyNode, fromNode, fromRunId } = input;
|
|
446
|
+
if ('usePins' in input || (onlyNode !== undefined && (fromNode !== undefined || fromRunId !== undefined))
|
|
447
|
+
|| (onlyNode !== undefined && (typeof onlyNode !== 'string' || !onlyNode.trim()))
|
|
448
|
+
|| (fromNode !== undefined && (typeof fromNode !== 'string' || !fromNode.trim()))
|
|
449
|
+
|| (fromRunId !== undefined && (typeof fromRunId !== 'string' || !fromRunId.trim()))
|
|
450
|
+
|| (fromNode === undefined) !== (fromRunId === undefined)
|
|
451
|
+
|| (input.mode !== undefined && input.mode !== 'test')) {
|
|
452
|
+
return jsonResponse({ error: 'bad_request', reason: 'invalid run selection' }, 400);
|
|
453
|
+
}
|
|
454
|
+
if ((onlyNode && !entry.definition.nodes.some(n => n.id === onlyNode))
|
|
455
|
+
|| (fromNode && !entry.definition.nodes.some(n => n.id === fromNode))) {
|
|
456
|
+
return jsonResponse({ error: 'bad_request', reason: 'unknown selected node' }, 400);
|
|
457
|
+
}
|
|
458
|
+
let previousOutputs: Record<string, NodeOutput> | undefined;
|
|
459
|
+
if (typeof fromRunId === 'string') {
|
|
460
|
+
const previous = RUN_REGISTRY.get(fromRunId);
|
|
461
|
+
if (previous) {
|
|
462
|
+
if (previous.workflowName !== name || previous.ok === undefined) {
|
|
463
|
+
return jsonResponse({ error: 'bad_request', reason: 'source run must be settled for this workflow' }, 400);
|
|
464
|
+
}
|
|
465
|
+
const terminal = previous.events.find(e => e.type === 'workflow_done' || e.type === 'workflow_failed');
|
|
466
|
+
previousOutputs = terminal?.type === 'workflow_done' ? terminal.outputs
|
|
467
|
+
: terminal?.type === 'workflow_failed' ? terminal.partial : {};
|
|
468
|
+
} else {
|
|
469
|
+
const disk = readRunOutputSnapshot(fromRunId);
|
|
470
|
+
if (!disk || disk.workflowName !== name || (disk.status !== 'done' && disk.status !== 'failed')) {
|
|
471
|
+
return jsonResponse({ error: 'bad_request', reason: 'source run must be settled for this workflow' }, 400);
|
|
472
|
+
}
|
|
473
|
+
previousOutputs = disk.outputs;
|
|
474
|
+
}
|
|
475
|
+
let order: string[];
|
|
476
|
+
try { order = topoSort(entry.definition.nodes); }
|
|
477
|
+
catch { return jsonResponse({ error: 'bad_request', reason: 'invalid workflow topology' }, 400); }
|
|
478
|
+
const upstream = order.slice(0, order.indexOf(fromNode as string));
|
|
479
|
+
if (upstream.some(id => previousOutputs?.[id] === undefined)) {
|
|
480
|
+
return jsonResponse({ error: 'bad_request', reason: 'source run missing upstream outputs' }, 400);
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
const mode: WorkflowRunMode = input.mode === 'test' ? 'test' : onlyNode ? 'only' : fromNode ? 'from' : 'full';
|
|
387
484
|
const runId = `wf-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
388
485
|
const record: RunRecord = {
|
|
389
486
|
runId,
|
|
390
487
|
workflowName: name,
|
|
488
|
+
mode,
|
|
391
489
|
startedAt: Date.now(),
|
|
392
490
|
events: [],
|
|
393
491
|
ok: undefined,
|
|
@@ -400,10 +498,14 @@ export async function handleWorkflowRunStart(
|
|
|
400
498
|
void (async () => {
|
|
401
499
|
const deps = buildDefaultWorkflowDeps({ runId });
|
|
402
500
|
try {
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
501
|
+
const runOpts: RunWorkflowOpts = {
|
|
502
|
+
workflow: entry.definition, arguments: args, runId, dryRun, mode,
|
|
503
|
+
...(typeof onlyNode === 'string' ? { onlyNode } : {}),
|
|
504
|
+
...(typeof fromNode === 'string' ? { fromNode } : {}),
|
|
505
|
+
...(previousOutputs ? { previousOutputs } : {}),
|
|
506
|
+
};
|
|
507
|
+
for await (const runtimeEvent of runWorkflow(runOpts, deps)) {
|
|
508
|
+
const evt = { ...runtimeEvent, mode };
|
|
407
509
|
record.events.push(evt);
|
|
408
510
|
// §15.8(b) — fan into NexusEventBus → PWA invalidates queries
|
|
409
511
|
// on push instead of polling. No-op when bus is unwired
|
|
@@ -423,13 +525,14 @@ export async function handleWorkflowRunStart(
|
|
|
423
525
|
type: 'workflow_failed' as const,
|
|
424
526
|
error: err instanceof Error ? err.message : String(err),
|
|
425
527
|
partial: {},
|
|
528
|
+
mode,
|
|
426
529
|
};
|
|
427
530
|
record.events.push(failEvt);
|
|
428
531
|
publishWorkflowRunEvent({ runId, workflowName: name }, failEvt);
|
|
429
532
|
}
|
|
430
533
|
})();
|
|
431
534
|
|
|
432
|
-
return jsonResponse({ ok: true, runId }, 202);
|
|
535
|
+
return jsonResponse({ ok: true, runId, mode }, 202);
|
|
433
536
|
}
|
|
434
537
|
|
|
435
538
|
export function handleWorkflowRunGet(
|
|
@@ -444,6 +547,7 @@ export function handleWorkflowRunGet(
|
|
|
444
547
|
{
|
|
445
548
|
runId: rec.runId,
|
|
446
549
|
workflowName: rec.workflowName,
|
|
550
|
+
mode: rec.mode,
|
|
447
551
|
startedAt: rec.startedAt,
|
|
448
552
|
ok: rec.ok,
|
|
449
553
|
events: rec.events,
|
|
@@ -597,6 +701,21 @@ interface DiskRunSummary {
|
|
|
597
701
|
* enough that abandoned runs don't pollute the list across sessions. */
|
|
598
702
|
const STALE_RUNNING_AFTER_MS = 30 * 60 * 1000;
|
|
599
703
|
|
|
704
|
+
function readRunOutputSnapshot(runId: string): {
|
|
705
|
+
workflowName: string;
|
|
706
|
+
status: string;
|
|
707
|
+
outputs: Record<string, NodeOutput>;
|
|
708
|
+
} | null {
|
|
709
|
+
if (!/^wf-[A-Za-z0-9-]+$/.test(runId) || runId.includes('..')) return null;
|
|
710
|
+
try {
|
|
711
|
+
const parsed = JSON.parse(readFileSync(join(workflowsRunsRoot(), runId, 'run.json'), 'utf-8')) as {
|
|
712
|
+
workflowName?: string; status?: string; outputs?: Record<string, NodeOutput>;
|
|
713
|
+
};
|
|
714
|
+
if (!parsed.workflowName || !parsed.status || !parsed.outputs || typeof parsed.outputs !== 'object') return null;
|
|
715
|
+
return { workflowName: parsed.workflowName, status: parsed.status, outputs: parsed.outputs };
|
|
716
|
+
} catch { return null; }
|
|
717
|
+
}
|
|
718
|
+
|
|
600
719
|
/** Read `<root>/<runId>/run.json` and translate into the same shape as
|
|
601
720
|
* GET /runs/<id> serves from memory. Returns null when the file is
|
|
602
721
|
* missing or unreadable. Events are reconstructed minimally from the
|
|
@@ -608,6 +727,7 @@ function loadRunFromDisk(runId: string): {
|
|
|
608
727
|
ok: boolean | undefined;
|
|
609
728
|
events: WorkflowEvent[];
|
|
610
729
|
outputs: Record<string, unknown>;
|
|
730
|
+
mode?: WorkflowRunMode;
|
|
611
731
|
} | null {
|
|
612
732
|
if (!runId || runId.includes('/') || runId.includes('..')) return null;
|
|
613
733
|
const root = workflowsRunsRoot();
|
|
@@ -623,6 +743,7 @@ function loadRunFromDisk(runId: string): {
|
|
|
623
743
|
completedAt?: number;
|
|
624
744
|
ok?: boolean;
|
|
625
745
|
status?: string;
|
|
746
|
+
mode?: WorkflowRunMode;
|
|
626
747
|
outputs?: Record<string, { output?: unknown }>;
|
|
627
748
|
};
|
|
628
749
|
if (!parsed.runId || !parsed.workflowName) return null;
|
|
@@ -634,7 +755,8 @@ function loadRunFromDisk(runId: string): {
|
|
|
634
755
|
// so a polling client still sees the node_done sequence even
|
|
635
756
|
// though the live run.json doesn't store events.
|
|
636
757
|
const events: WorkflowEvent[] = [];
|
|
637
|
-
events.push({ type: 'workflow_start', workflow: parsed.workflowName, runId: parsed.runId
|
|
758
|
+
events.push({ type: 'workflow_start', workflow: parsed.workflowName, runId: parsed.runId,
|
|
759
|
+
...(parsed.mode !== undefined ? { mode: parsed.mode } : {}) });
|
|
638
760
|
const nodesDir = join(runDir, 'nodes');
|
|
639
761
|
// Iterate `parsed.outputs` keys instead of `readdirSync(nodesDir)`
|
|
640
762
|
// so the reconstructed node_done sequence is in execution order
|
|
@@ -673,6 +795,7 @@ function loadRunFromDisk(runId: string): {
|
|
|
673
795
|
events.push({
|
|
674
796
|
type: 'node_done',
|
|
675
797
|
nodeId,
|
|
798
|
+
...(parsed.mode !== undefined ? { mode: parsed.mode } : {}),
|
|
676
799
|
result: {
|
|
677
800
|
ok: nodeData.ok,
|
|
678
801
|
output: nodeData.output ?? '',
|
|
@@ -684,6 +807,7 @@ function loadRunFromDisk(runId: string): {
|
|
|
684
807
|
if (parsed.status === 'done') {
|
|
685
808
|
events.push({
|
|
686
809
|
type: 'workflow_done',
|
|
810
|
+
...(parsed.mode !== undefined ? { mode: parsed.mode } : {}),
|
|
687
811
|
outputs: Object.fromEntries(
|
|
688
812
|
Object.entries(parsed.outputs ?? {}).map(([k, v]) => [
|
|
689
813
|
k,
|
|
@@ -694,6 +818,7 @@ function loadRunFromDisk(runId: string): {
|
|
|
694
818
|
} else if (parsed.status === 'failed') {
|
|
695
819
|
events.push({
|
|
696
820
|
type: 'workflow_failed',
|
|
821
|
+
...(parsed.mode !== undefined ? { mode: parsed.mode } : {}),
|
|
697
822
|
error: 'failed (see node events)',
|
|
698
823
|
partial: Object.fromEntries(
|
|
699
824
|
Object.entries(parsed.outputs ?? {}).map(([k, v]) => [
|
|
@@ -706,6 +831,7 @@ function loadRunFromDisk(runId: string): {
|
|
|
706
831
|
return {
|
|
707
832
|
runId: parsed.runId,
|
|
708
833
|
workflowName: parsed.workflowName,
|
|
834
|
+
...(parsed.mode !== undefined ? { mode: parsed.mode } : {}),
|
|
709
835
|
startedAt: parsed.startedAt ?? 0,
|
|
710
836
|
ok: parsed.status === 'done' ? true : parsed.status === 'failed' ? false : undefined,
|
|
711
837
|
events,
|
package/src/nexus/index.ts
CHANGED
|
@@ -1949,10 +1949,12 @@ export async function runNexus(opts: RunNexusOptions = {}): Promise<RunNexusHand
|
|
|
1949
1949
|
const tab = registry.get(tabId);
|
|
1950
1950
|
if (!tab || tab.spec.kind !== 'webterm') return;
|
|
1951
1951
|
const cwdMeta = (tab.spec.meta as { cwd?: string } | undefined)?.cwd;
|
|
1952
|
+
const projectSessionId = (tab.spec.meta as { sessionId?: string } | undefined)?.sessionId;
|
|
1952
1953
|
const backendFactory = effectiveWebtermSpawn
|
|
1953
1954
|
? () => {
|
|
1954
1955
|
const decided = resolveWebtermCwd({
|
|
1955
1956
|
...(cwdMeta ? { tabCwd: cwdMeta } : {}),
|
|
1957
|
+
...(projectSessionId ? { sessionId: projectSessionId } : {}),
|
|
1956
1958
|
...(runtimeToolCwd ? { toolCwd: runtimeToolCwd } : {}),
|
|
1957
1959
|
instance: resolveCurrentInstance(),
|
|
1958
1960
|
processCwd: process.cwd(),
|
|
@@ -24,6 +24,7 @@ export interface WebtermTabOpts {
|
|
|
24
24
|
id?: string; // default: 'webterm:1'
|
|
25
25
|
label?: string;
|
|
26
26
|
cwd?: string;
|
|
27
|
+
sessionId?: string;
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
export const WEBTERM_KIND: TabKind = 'webterm';
|
|
@@ -34,7 +35,7 @@ export function createWebtermTabSpec(opts: WebtermTabOpts = {}): TabSpec {
|
|
|
34
35
|
id,
|
|
35
36
|
kind: WEBTERM_KIND,
|
|
36
37
|
label: opts.label ?? id,
|
|
37
|
-
...(opts.cwd ? { meta: { cwd: opts.cwd } } : {}),
|
|
38
|
+
...(opts.cwd || opts.sessionId ? { meta: { ...(opts.cwd ? { cwd: opts.cwd } : {}), ...(opts.sessionId ? { sessionId: opts.sessionId } : {}) } } : {}),
|
|
38
39
|
};
|
|
39
40
|
}
|
|
40
41
|
|
|
@@ -52,20 +52,29 @@ export function deliveryDedupKey(kind: string, text: string): string {
|
|
|
52
52
|
return createHash('sha1').update(`${kind}\n${norm}`).digest('hex').slice(0, 16);
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
/** ① 중복 발사 제어 —
|
|
56
|
-
*
|
|
57
|
-
|
|
58
|
-
export function recentlyDelivered(
|
|
55
|
+
/** ① 중복 발사 제어 — windowSec 내 동일 메시지가 한 채널 이상 성공했으면 그 messageId.
|
|
56
|
+
* 실패 기록은 재시도를 막지 않는다. 짧은 창(기본 120s) 밖의 재발송은 통과. */
|
|
57
|
+
export function successfulDeliveryId(
|
|
59
58
|
db: Database, dedupKey: string, windowSec = 120, nowMs: number = Date.now(),
|
|
60
|
-
):
|
|
59
|
+
): string | null {
|
|
61
60
|
// ⚠️ 축 ②(JS 임계 · db-window 참조) — 같은 파일의 `recentDeliveryCount` 와 동형이다.
|
|
62
61
|
// SQL 안의 `datetime('now')` 를 쓰면 **시계를 주입할 수 없어** 테스트가 실제 시각에
|
|
63
62
|
// 매달린다. 실제로 이 함수의 테스트가 고정 날짜로 seed 한 채 시간이 흘러 어느 날 빨개진
|
|
64
63
|
// 시한폭탄이었다. `deliveries.ts` 는 ISO 로만 쓰므로 raw 비교가 옳고 인덱스도 산다.
|
|
65
64
|
const row = db.prepare(
|
|
66
|
-
`SELECT
|
|
67
|
-
|
|
68
|
-
|
|
65
|
+
`SELECT message_id FROM deliveries
|
|
66
|
+
WHERE dedup_key = ? AND ts >= ?
|
|
67
|
+
AND EXISTS (SELECT 1 FROM json_each(deliveries.channels) WHERE json_extract(value, '$.ok') = 1)
|
|
68
|
+
ORDER BY ts DESC LIMIT 1`,
|
|
69
|
+
).get(dedupKey, sinceTs(SECONDS(windowSec), nowMs)) as { message_id: string } | null;
|
|
70
|
+
return row?.message_id ?? null;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/** 기존 boolean 호출부 호환 — 성공 배송 기록만 중복으로 센다. */
|
|
74
|
+
export function recentlyDelivered(
|
|
75
|
+
db: Database, dedupKey: string, windowSec = 120, nowMs: number = Date.now(),
|
|
76
|
+
): boolean {
|
|
77
|
+
return successfulDeliveryId(db, dedupKey, windowSec, nowMs) !== null;
|
|
69
78
|
}
|
|
70
79
|
|
|
71
80
|
/** 최근 창(windowSec) 내 총 발송 수 — 버스트(밀림) 판정용. 전 kind 합산.
|
|
@@ -27,13 +27,14 @@
|
|
|
27
27
|
// that boolean before falling back to direct Telegram).
|
|
28
28
|
|
|
29
29
|
import { createHash } from 'node:crypto';
|
|
30
|
+
import { debug } from '../../debug/log.js';
|
|
30
31
|
import { sendTelegramReport } from '../../telegram-report.js';
|
|
31
32
|
import { getPushcutClient } from '../../pushcut/client.js';
|
|
32
33
|
import type { UserConfig } from '../../user-config.js';
|
|
33
34
|
import { formatForChannel, type OutboundChannelType, type OutboundMsg } from './format.js';
|
|
34
35
|
import { spillLongContent } from '../../storage/content-spill.js';
|
|
35
36
|
import {
|
|
36
|
-
openDeliveryDb, deliveryDedupKey,
|
|
37
|
+
openDeliveryDb, deliveryDedupKey, successfulDeliveryId, recordDelivery, type ChannelDelivery,
|
|
37
38
|
} from './delivery-ledger.js';
|
|
38
39
|
|
|
39
40
|
// 채널 타입·메시지·분할기는 format.ts가 단일 출처 — 기존 소비처(test 등) 호환 재export.
|
|
@@ -71,6 +72,8 @@ export interface RouteResult {
|
|
|
71
72
|
channels: ChannelResult[];
|
|
72
73
|
/** 중복 발사 제어(dedup)로 재팬아웃이 억제됨 — 최근 동일 발송 존재. */
|
|
73
74
|
suppressed?: boolean;
|
|
75
|
+
/** 억제 근거가 된 앞선 성공 발송의 식별자. */
|
|
76
|
+
suppressedBy?: string;
|
|
74
77
|
/** 이 발송의 식별자(리드 동기화·회상 교차참조용). */
|
|
75
78
|
messageId?: string;
|
|
76
79
|
}
|
|
@@ -207,9 +210,11 @@ export async function routeOutbound(cfg: UserConfig, msg: OutboundMsg, deps: Rou
|
|
|
207
210
|
// ① 중복 발사 제어 — 최근(120s) 동일 발송이면 재팬아웃 억제.
|
|
208
211
|
if (ledger && deps.dedup !== false) {
|
|
209
212
|
try {
|
|
210
|
-
|
|
213
|
+
const suppressedBy = successfulDeliveryId(ledger, dedupKey);
|
|
214
|
+
if (suppressedBy) {
|
|
211
215
|
if (ownLedger) ledger.close();
|
|
212
|
-
|
|
216
|
+
try { debug.log('outbound.send', 'suppressed', { kind: msg.kind, suppressedBy }); } catch { /* 관측 실패는 발송 결과에 영향 없음 */ }
|
|
217
|
+
return { delivered: true, channels: [], suppressed: true, suppressedBy, messageId };
|
|
213
218
|
}
|
|
214
219
|
} catch { /* 원장 조회 실패 — 억제 없이 진행 */ }
|
|
215
220
|
}
|
package/src/nexus/webterm/pty.ts
CHANGED
|
@@ -31,6 +31,7 @@ import { startPty as realStartPty, onPtyEvent as realOnPtyEvent } from '../../pt
|
|
|
31
31
|
import type { StartOpts, PtyHandle, PtyEvent } from '../../pty-shell/registry.js';
|
|
32
32
|
|
|
33
33
|
import { debug } from '../../debug/log.js';
|
|
34
|
+
import { resolveSessionProjectContext } from '../../project/session-context.js';
|
|
34
35
|
|
|
35
36
|
// ── PtyBackend interface ─────────────────────────────────────────────
|
|
36
37
|
|
|
@@ -229,15 +230,18 @@ export function createRegistryBackend(
|
|
|
229
230
|
}
|
|
230
231
|
|
|
231
232
|
/** 웹 터미널 셸이 열릴 작업 디렉토리를 정한다(실행 맥락 SSOT: 맥락은 «한 번» 정해지고 인자로 내려간다).
|
|
232
|
-
* 순서: 탭이 명시한 cwd →
|
|
233
|
+
* 순서: 탭이 명시한 cwd → 대화 프로젝트 폴더 → 데몬 tool cwd → (격리 우주면) 우주 뿌리 → 프로세스 cwd.
|
|
233
234
|
* ⛔ 격리(test) 우주에서 `process.cwd()` 로 떨어지면 셸이 «사람 작업 트리»에서 열린다(🅕 실측 2026-09-26). */
|
|
234
235
|
export function resolveWebtermCwd(input: {
|
|
235
236
|
tabCwd?: string;
|
|
237
|
+
sessionId?: string;
|
|
236
238
|
toolCwd?: string;
|
|
237
239
|
instance: { kind: 'prod' | 'test'; root: string };
|
|
238
240
|
processCwd: string;
|
|
239
|
-
}): { cwd: string; source: 'tab' | 'tool-cwd' | 'isolated-root' | 'process-cwd' } {
|
|
241
|
+
}): { cwd: string; source: 'tab' | 'project' | 'tool-cwd' | 'isolated-root' | 'process-cwd' } {
|
|
240
242
|
if (input.tabCwd) return { cwd: input.tabCwd, source: 'tab' };
|
|
243
|
+
const projectCwd = resolveSessionProjectContext(input.sessionId)?.cwd;
|
|
244
|
+
if (projectCwd) return { cwd: projectCwd, source: 'project' };
|
|
241
245
|
if (input.toolCwd) return { cwd: input.toolCwd, source: 'tool-cwd' };
|
|
242
246
|
if (input.instance.kind === 'test') return { cwd: input.instance.root, source: 'isolated-root' };
|
|
243
247
|
return { cwd: input.processCwd, source: 'process-cwd' };
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
import { accessSync, constants, statSync } from 'node:fs';
|
|
3
|
+
import { delimiter, join } from 'node:path';
|
|
4
|
+
|
|
5
|
+
export type SkillCli = 'gh' | 'gws' | 'op' | 'himalaya';
|
|
6
|
+
|
|
7
|
+
export interface CliAuthStatus {
|
|
8
|
+
cli: SkillCli;
|
|
9
|
+
found: boolean;
|
|
10
|
+
authenticated: boolean;
|
|
11
|
+
skippedReason?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface CliAuthStatusDeps {
|
|
15
|
+
path?: string;
|
|
16
|
+
findExecutable?: (name: SkillCli, path: string) => string | null;
|
|
17
|
+
runStatus?: (executable: string, args: readonly string[]) => { status: number | null; stdout?: string; error?: unknown };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const STATUS_COMMANDS: readonly { cli: SkillCli; args: readonly string[] }[] = [
|
|
21
|
+
{ cli: 'gh', args: ['auth', 'status'] },
|
|
22
|
+
{ cli: 'gws', args: ['auth', 'status'] },
|
|
23
|
+
{ cli: 'op', args: ['whoami'] },
|
|
24
|
+
{ cli: 'himalaya', args: ['account', 'check'] },
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
function findOnPath(name: SkillCli, path: string): string | null {
|
|
28
|
+
for (const directory of path.split(delimiter).filter(Boolean)) {
|
|
29
|
+
const executable = join(directory, name);
|
|
30
|
+
try {
|
|
31
|
+
accessSync(executable, constants.X_OK);
|
|
32
|
+
if (statSync(executable).isFile()) return executable;
|
|
33
|
+
} catch { /* Try the next PATH entry. */ }
|
|
34
|
+
}
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function runReadOnlyStatus(executable: string, args: readonly string[]) {
|
|
39
|
+
const result = spawnSync(executable, [...args], {
|
|
40
|
+
encoding: 'utf8', timeout: 5_000, maxBuffer: 64 * 1024,
|
|
41
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
42
|
+
});
|
|
43
|
+
return { status: result.status, stdout: result.stdout, error: result.error };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function gwsHasSession(stdout: string | undefined): boolean {
|
|
47
|
+
try {
|
|
48
|
+
const status: unknown = JSON.parse(stdout ?? '');
|
|
49
|
+
if (!status || typeof status !== 'object' || Array.isArray(status)) return false;
|
|
50
|
+
const auth = status as Record<string, unknown>;
|
|
51
|
+
return auth.token_valid === true;
|
|
52
|
+
} catch {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** No credential-file reads, login calls, prompts, or token-bearing output leave this probe. */
|
|
58
|
+
export function detectSkillCliAuth(deps: CliAuthStatusDeps = {}): CliAuthStatus[] {
|
|
59
|
+
const path = deps.path ?? process.env.PATH ?? '';
|
|
60
|
+
const find = deps.findExecutable ?? findOnPath;
|
|
61
|
+
const run = deps.runStatus ?? runReadOnlyStatus;
|
|
62
|
+
return STATUS_COMMANDS.map(({ cli, args }) => {
|
|
63
|
+
let executable: string | null;
|
|
64
|
+
try { executable = find(cli, path); }
|
|
65
|
+
catch { executable = null; }
|
|
66
|
+
if (!executable) return { cli, found: false, authenticated: false, skippedReason: 'not on PATH' };
|
|
67
|
+
try {
|
|
68
|
+
const result = run(executable, args);
|
|
69
|
+
if (result.error || result.status === null) {
|
|
70
|
+
return { cli, found: true, authenticated: false, skippedReason: 'status check unavailable' };
|
|
71
|
+
}
|
|
72
|
+
if (result.status !== 0 || (cli === 'gws' && !gwsHasSession(result.stdout))) {
|
|
73
|
+
return { cli, found: true, authenticated: false, skippedReason: 'not authenticated' };
|
|
74
|
+
}
|
|
75
|
+
return { cli, found: true, authenticated: true };
|
|
76
|
+
} catch {
|
|
77
|
+
return { cli, found: true, authenticated: false, skippedReason: 'status check unavailable' };
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
}
|
|
@@ -154,12 +154,12 @@ export async function askVoiceAI(
|
|
|
154
154
|
|
|
155
155
|
if (mode === 'preset') {
|
|
156
156
|
// Phase 2 catalog isn't shipped yet; the wizard records the intent
|
|
157
|
-
// by keeping the user on Smart defaults but tagging
|
|
157
|
+
// by keeping the user on Smart defaults but tagging profile='power'
|
|
158
158
|
// so the auto-suggest hint in PWA opens the preset card directly.
|
|
159
159
|
io.print(' (Preset catalog ships in Phase 2 · for now Smart defaults stay active.)');
|
|
160
160
|
io.print(' elanous has noted your preference — preset hints will appear when ready.');
|
|
161
161
|
return {
|
|
162
|
-
modelTier: {
|
|
162
|
+
modelTier: { profile: 'power' },
|
|
163
163
|
};
|
|
164
164
|
}
|
|
165
165
|
|
|
@@ -175,7 +175,7 @@ export async function askVoiceAI(
|
|
|
175
175
|
|
|
176
176
|
const answer: VoiceAIAnswer = {
|
|
177
177
|
modelTier: {
|
|
178
|
-
|
|
178
|
+
profile: 'custom',
|
|
179
179
|
voice: { stt: tier as ModelTier },
|
|
180
180
|
},
|
|
181
181
|
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { getUserConfig, type UserConfig } from '../user-config.js';
|
|
2
|
+
import type { SeatEntry } from '../seat-loop/seat-loop.js';
|
|
3
|
+
|
|
4
|
+
export const DEFAULT_DAILY_GOALS = 6;
|
|
5
|
+
export const DEFAULT_CONCURRENT_PODS = 2;
|
|
6
|
+
|
|
7
|
+
export type SeatBudgetResult = { allowed: true } | { allowed: false; reason: string };
|
|
8
|
+
export type RunningSeatPod = { seat: string; substrate?: string; status?: string };
|
|
9
|
+
export type SeatBudgetInput = {
|
|
10
|
+
seat: string;
|
|
11
|
+
now: Date;
|
|
12
|
+
ledger: readonly SeatEntry[];
|
|
13
|
+
running: readonly RunningSeatPod[];
|
|
14
|
+
config?: Pick<UserConfig, 'org'>;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
function limit(value: unknown, fallback: number): number {
|
|
18
|
+
return typeof value === 'number' && Number.isSafeInteger(value) && value >= 0 ? value : fallback;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function day(date: Date): string {
|
|
22
|
+
return new Intl.DateTimeFormat('en-CA', { timeZone: 'Asia/Seoul', year: 'numeric', month: '2-digit', day: '2-digit' }).format(date);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** A read-only seat quota judgment; the caller owns the launch and ledger write. */
|
|
26
|
+
export function checkSeatBudget({ seat, now, ledger, running, config }: SeatBudgetInput): SeatBudgetResult {
|
|
27
|
+
const override = (config ?? getUserConfig()).org?.budget?.[seat];
|
|
28
|
+
const dailyGoals = limit(override?.dailyGoals, DEFAULT_DAILY_GOALS);
|
|
29
|
+
const concurrentPods = limit(override?.concurrentPods, DEFAULT_CONCURRENT_PODS);
|
|
30
|
+
const today = day(now);
|
|
31
|
+
const launchedToday = ledger.filter((entry) => entry.seat === seat && entry.status === 'launched'
|
|
32
|
+
&& Number.isFinite(Date.parse(entry.ts ?? entry.at))
|
|
33
|
+
&& day(new Date(entry.ts ?? entry.at)) === today).length;
|
|
34
|
+
if (launchedToday >= dailyGoals) {
|
|
35
|
+
return { allowed: false, reason: `${seat} daily goals budget reached (${launchedToday}/${dailyGoals})` };
|
|
36
|
+
}
|
|
37
|
+
const active = running.filter((run) => run.seat === seat && (run.status === undefined || run.status === 'running' || run.status === 'unknown'));
|
|
38
|
+
// Confirmed = a Pod known to be running; an unknown substrate OR unknown liveness only counts as «cannot verify».
|
|
39
|
+
const pods = active.filter((run) => run.substrate === 'pod' && run.status !== 'unknown').length;
|
|
40
|
+
if (pods >= concurrentPods) {
|
|
41
|
+
return { allowed: false, reason: `${seat} concurrent Pods budget reached (${pods}/${concurrentPods})` };
|
|
42
|
+
}
|
|
43
|
+
const unknown = active.filter((run) => run.substrate === undefined || run.status === 'unknown').length;
|
|
44
|
+
if (pods + unknown >= concurrentPods) {
|
|
45
|
+
return { allowed: false, reason: `${seat} concurrent Pods budget cannot be verified (${pods} confirmed, ${unknown} unknown; limit ${concurrentPods})` };
|
|
46
|
+
}
|
|
47
|
+
return { allowed: true };
|
|
48
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { Checklist, ChecklistItem } from '../release-loop/checklist.js';
|
|
2
|
+
import { parseOwner } from '../release-loop/checklist.js';
|
|
3
|
+
import type { SeatLoopConfig } from '../user-config.js';
|
|
4
|
+
|
|
5
|
+
export interface StallEscalation {
|
|
6
|
+
item: ChecklistItem;
|
|
7
|
+
from: string;
|
|
8
|
+
to: string;
|
|
9
|
+
stalledMin: number;
|
|
10
|
+
/** Stable start of this uninterrupted stall interval (independent of the observation clock). */
|
|
11
|
+
startedAt: string;
|
|
12
|
+
reason: 'red' | 'blocked';
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** A missing parent is intentional: OP has no automatic escalation destination. */
|
|
16
|
+
export const DEFAULT_STALL_PARENTS: Readonly<Record<string, string>> = { MK: 'OP', TC: 'OP', UX: 'OP' };
|
|
17
|
+
export const DEFAULT_RED_MINUTES = 30;
|
|
18
|
+
export const DEFAULT_BLOCKED_MINUTES = 60;
|
|
19
|
+
|
|
20
|
+
function stallReason(item: ChecklistItem): StallEscalation['reason'] | null {
|
|
21
|
+
if (item.status === 'red') return 'red';
|
|
22
|
+
return item.status === 'yellow' && item.disposition === 'block' ? 'blocked' : null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Find the beginning of the current uninterrupted red/blocked interval, not the most recent evidence edit. */
|
|
26
|
+
function stallStart(item: ChecklistItem, history: Checklist['history'], reason: StallEscalation['reason']): number {
|
|
27
|
+
const changes = history.filter((entry) => entry.id === item.id && (entry.field === 'status' || entry.field === 'disposition'))
|
|
28
|
+
.filter((entry) => Number.isFinite(Date.parse(entry.at)))
|
|
29
|
+
.sort((a, b) => Date.parse(b.at) - Date.parse(a.at));
|
|
30
|
+
let status = item.status;
|
|
31
|
+
let disposition = item.disposition;
|
|
32
|
+
for (const entry of changes) {
|
|
33
|
+
const current = status === 'red' ? 'red' : status === 'yellow' && disposition === 'block' ? 'blocked' : null;
|
|
34
|
+
if (entry.field === 'status') status = entry.from as ChecklistItem['status'];
|
|
35
|
+
else disposition = entry.from as ChecklistItem['disposition'];
|
|
36
|
+
const previous = status === 'red' ? 'red' : status === 'yellow' && disposition === 'block' ? 'blocked' : null;
|
|
37
|
+
if (current === reason && previous !== reason) return Date.parse(entry.at);
|
|
38
|
+
}
|
|
39
|
+
return Date.parse(item.updatedAt);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Pure checklist snapshot judgment. Age is measured in minutes against the injected clock. */
|
|
43
|
+
export function findStalls(checklist: Checklist, config: SeatLoopConfig = { mode: 'off' }, now: Date = new Date()): StallEscalation[] {
|
|
44
|
+
const nowMs = now.getTime();
|
|
45
|
+
const parents = { ...DEFAULT_STALL_PARENTS, ...config.stall?.parents };
|
|
46
|
+
const results: StallEscalation[] = [];
|
|
47
|
+
for (const item of checklist.items) {
|
|
48
|
+
const reason = stallReason(item);
|
|
49
|
+
if (!reason || !item.owner) continue;
|
|
50
|
+
let from: string;
|
|
51
|
+
try { from = parseOwner(item.owner).seat; } catch { continue; }
|
|
52
|
+
const to = parents[from];
|
|
53
|
+
if (!to || to === from) continue;
|
|
54
|
+
const start = stallStart(item, checklist.history, reason);
|
|
55
|
+
if (!Number.isFinite(start) || start > nowMs) continue;
|
|
56
|
+
const stalledMin = (nowMs - start) / 60_000;
|
|
57
|
+
const threshold = reason === 'red' ? config.stall?.redMinutes ?? DEFAULT_RED_MINUTES
|
|
58
|
+
: config.stall?.blockedMinutes ?? DEFAULT_BLOCKED_MINUTES;
|
|
59
|
+
if (stalledMin < threshold) continue;
|
|
60
|
+
results.push({ item, from, to, stalledMin, startedAt: new Date(start).toISOString(), reason });
|
|
61
|
+
}
|
|
62
|
+
return results;
|
|
63
|
+
}
|