elanous 0.2.10 → 0.2.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/apps/pwa/out/404/index.html +1 -1
- package/apps/pwa/out/404.html +1 -1
- package/apps/pwa/out/_next/static/-6XrAoD3eU7NyMHAE4xPS/_buildManifest.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1147-466ec15afacc1a65.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1159-0c5ef8bc21cb6afb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1394-ee3795b112907122.js +1 -0
- package/apps/pwa/out/_next/static/chunks/1452.93700483b9d4fc61.js +9 -0
- package/apps/pwa/out/_next/static/chunks/{6062-73e68343a9814f6a.js → 1829-b453a1b22d3999bb.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/2176-c379e3ebce874151.js +1 -0
- package/apps/pwa/out/_next/static/chunks/2426.8c6ee0c668d53def.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3170-7ec60a56fa0e4728.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3278-ae6ef084769f6195.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3454-988a53dac60a1763.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3638-aa80b4641ea439db.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3735-fe3402553ac1c9c6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/3869-3cd46526879f454c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/390.c373e31b3b9d0c41.js +5 -0
- package/apps/pwa/out/_next/static/chunks/3992-2e522a8ac5f2afde.js +25 -0
- package/apps/pwa/out/_next/static/chunks/4215-c9d91dd644ec1719.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4508-5d0161d1e724d735.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4685-c3c1c625b71accd1.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4733-623a79345b171e1c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/4883.3bd969ea1d3aaaff.js +2 -0
- package/apps/pwa/out/_next/static/chunks/5532.6899a12958a89b72.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8067-87ce253ec2f23697.js → 5845-e6c003ce8d5fd36a.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/5978-b27004c677119115.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{8046cadf-211ca3c0e00f2b72.js → 5cd7e3a9-404fd6b8d0ecd44c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/6048-4c5c33579bc4ef78.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6303-422dbf0f67c72aac.js +1 -0
- package/apps/pwa/out/_next/static/chunks/6751-bb3595948b2e311b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7274-19b7279f18b47ab3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7277-0b2fc7c16ba2d64b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{4323.c5dfb6f503304775.js → 7334.a6679d9168f37aa8.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/7551-a0e0707b79164ddd.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7758-0b018a9e4fc56200.js +1 -0
- package/apps/pwa/out/_next/static/chunks/7777-79f845045aa1ed86.js +1 -0
- package/apps/pwa/out/_next/static/chunks/79f8be9e-957d68913b590b08.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8025-cc24ee5d8f2fb6f8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8039-df92e08fede5de8f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8206-c6684dcde12be721.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8421-1c4acfb1395a0edf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8605-0259994816604c49.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8725.bf46bb1395dd0fa2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8734-252d511cd276c0dc.js +1 -0
- package/apps/pwa/out/_next/static/chunks/8834-ca1cb09c1cb1a6bf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2415.ed6428ff334c7ce2.js → 9269.d2a4795bc6812717.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/9538-2816b90923606459.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9656-c1540088f5859c80.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9906-482c6619b3fdda20.js +1 -0
- package/apps/pwa/out/_next/static/chunks/9920-5cfdc5e8fd209825.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-d16993889b125c42.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-cb169620945d1952.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-cefe8169e36cf62a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/board/page-d2e35228bc497119.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/botlab/{page-54b32bd27726588d.js → page-5c05b0da4bc1392c.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-e0ccdb576812b523.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/chat/page-813c4a52c9d05ca8.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/consult/page-4731f2c215358937.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/control/page-a022b257950f39e6.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-a2ffc717e04b8b0a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/editor/page-b59ee4e70fc18fcf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/exec/page-a67e11ba962337b5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/field/page-c172dabd796eb7a3.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-d16993889b125c42.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/inside/page-1efd0cb9e0ed9d13.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/intake/page-d5dc7ff69a37b4cf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/layout-e71c84189e8c683e.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/live/page-1d6a533ce5a6efcb.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/market/page-dfca9b7d2de0b135.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-793fa536b3a6ef37.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/morning/page-6dd3bfbbde2a5c2c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/not-found-490653e8d4cc8852.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-77447356baad75d2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-29e961191f6057df.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-c822f55b884d9104.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-fa4ccfc432424e52.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/outputs/page-6d604227e1664b71.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/page-9c7e8f744a765daf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-4048543b4b7ad5e0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-4c3a3126abed551a.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-64b0aecb1ca75e75.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-4292d0149020e8a7.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/settings/page-db14d0be7f1c460c.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-e5d8072cd7cfef73.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-d16993889b125c42.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/setup/page-9547b5cec7cf76bf.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/share/page-e6dcb83265530636.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-45248f08d6aecae5.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-2cddeb9e2aeedc55.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/term/page-e297866051595d81.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/today/page-baba2e047872fb0f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/trace/page-e895da4ec9cac345.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/vault/page-4344faf20216233b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-698bb29f11864b89.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-bd6a6dc1ddc273f2.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-2e9e2fb01c9da1c9.js +1 -0
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-d62ceb13411ebba4.js +1 -0
- package/apps/pwa/out/_next/static/chunks/{2ea96958-e8c7e112de50b067.js → f48170cc-d05d28bf87a43bf4.js} +1 -1
- package/apps/pwa/out/_next/static/chunks/framework-172630e6aa5e2d7f.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-app-f0fe2d7477845181.js +1 -0
- package/apps/pwa/out/_next/static/chunks/main-fc98ac70b44eccb0.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_app-5bd7f10271f72413.js +1 -0
- package/apps/pwa/out/_next/static/chunks/pages/_error-97d0d85ea05fef9b.js +1 -0
- package/apps/pwa/out/_next/static/chunks/webpack-9e4d02d567b98240.js +1 -0
- package/apps/pwa/out/_next/static/css/128fb7fb670b2fbf.css +1 -0
- package/apps/pwa/out/approvals/index.html +1 -1
- package/apps/pwa/out/approvals/index.txt +23 -23
- package/apps/pwa/out/autopilot/index.html +1 -1
- package/apps/pwa/out/autopilot/index.txt +23 -23
- package/apps/pwa/out/board/index.html +1 -1
- package/apps/pwa/out/board/index.txt +23 -23
- package/apps/pwa/out/botlab/index.html +1 -1
- package/apps/pwa/out/botlab/index.txt +22 -22
- package/apps/pwa/out/bots/index.html +1 -1
- package/apps/pwa/out/bots/index.txt +22 -22
- package/apps/pwa/out/chat/index.html +1 -1
- package/apps/pwa/out/chat/index.txt +22 -22
- package/apps/pwa/out/consult/index.html +1 -1
- package/apps/pwa/out/consult/index.txt +23 -23
- package/apps/pwa/out/control/index.html +1 -1
- package/apps/pwa/out/control/index.txt +23 -23
- package/apps/pwa/out/design-check/index.html +1 -1
- package/apps/pwa/out/design-check/index.txt +23 -23
- package/apps/pwa/out/editor/index.html +1 -1
- package/apps/pwa/out/editor/index.txt +23 -23
- package/apps/pwa/out/exec/index.html +1 -1
- package/apps/pwa/out/exec/index.txt +23 -23
- package/apps/pwa/out/field/index.html +1 -1
- package/apps/pwa/out/field/index.txt +23 -23
- package/apps/pwa/out/healthz +1 -1
- package/apps/pwa/out/index.html +1 -1
- package/apps/pwa/out/index.txt +22 -22
- package/apps/pwa/out/inside/index.html +1 -0
- package/apps/pwa/out/inside/index.txt +31 -0
- package/apps/pwa/out/intake/index.html +1 -1
- package/apps/pwa/out/intake/index.txt +23 -23
- package/apps/pwa/out/live/index.html +1 -1
- package/apps/pwa/out/live/index.txt +23 -23
- package/apps/pwa/out/market/index.html +1 -1
- package/apps/pwa/out/market/index.txt +22 -22
- package/apps/pwa/out/missions/placeholder/index.html +1 -1
- package/apps/pwa/out/missions/placeholder/index.txt +22 -22
- package/apps/pwa/out/morning/index.html +1 -1
- package/apps/pwa/out/morning/index.txt +23 -23
- package/apps/pwa/out/observatory/index.html +1 -1
- package/apps/pwa/out/observatory/index.txt +23 -23
- package/apps/pwa/out/ops/checklist/index.html +1 -1
- package/apps/pwa/out/ops/checklist/index.txt +22 -22
- package/apps/pwa/out/ops/release/index.html +1 -1
- package/apps/pwa/out/ops/release/index.txt +22 -22
- package/apps/pwa/out/ops/seats/index.html +1 -1
- package/apps/pwa/out/ops/seats/index.txt +22 -22
- package/apps/pwa/out/outputs/index.html +1 -0
- package/apps/pwa/out/outputs/index.txt +30 -0
- package/apps/pwa/out/reflection/index.html +1 -1
- package/apps/pwa/out/reflection/index.txt +23 -23
- package/apps/pwa/out/scheduler/index.html +1 -1
- package/apps/pwa/out/scheduler/index.txt +23 -23
- package/apps/pwa/out/sessions/index.html +1 -1
- package/apps/pwa/out/sessions/index.txt +22 -22
- package/apps/pwa/out/settings/devices/index.html +1 -1
- package/apps/pwa/out/settings/devices/index.txt +23 -23
- package/apps/pwa/out/settings/index.html +1 -1
- package/apps/pwa/out/settings/index.txt +23 -23
- package/apps/pwa/out/setup/done/index.html +1 -1
- package/apps/pwa/out/setup/done/index.txt +23 -23
- package/apps/pwa/out/setup/index.html +1 -1
- package/apps/pwa/out/setup/index.txt +23 -23
- package/apps/pwa/out/share/index.html +1 -1
- package/apps/pwa/out/share/index.txt +23 -23
- package/apps/pwa/out/showroom/index.html +1 -1
- package/apps/pwa/out/showroom/index.txt +22 -22
- package/apps/pwa/out/tasks/index.html +1 -1
- package/apps/pwa/out/tasks/index.txt +23 -23
- package/apps/pwa/out/term/index.html +1 -1
- package/apps/pwa/out/term/index.txt +23 -24
- package/apps/pwa/out/today/index.html +1 -1
- package/apps/pwa/out/today/index.txt +23 -23
- package/apps/pwa/out/trace/index.html +1 -1
- package/apps/pwa/out/trace/index.txt +23 -23
- package/apps/pwa/out/vault/index.html +1 -1
- package/apps/pwa/out/vault/index.txt +23 -23
- package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
- package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
- package/apps/pwa/out/workflows/index.html +1 -1
- package/apps/pwa/out/workflows/index.txt +23 -23
- package/apps/pwa/out/workspace/index.html +1 -1
- package/apps/pwa/out/workspace/index.txt +23 -24
- package/apps/pwa/out/worktrees/index.html +1 -1
- package/apps/pwa/out/worktrees/index.txt +23 -23
- package/graphs/context/nightly-condense.yaml +21 -0
- package/graphs/context/recipes.yaml +12 -0
- package/graphs/demo/inside-seed.yaml +20 -0
- package/graphs/demo/recipes.yaml +12 -0
- package/graphs/drafts/draft-cleanup.yaml +19 -0
- package/graphs/drafts/recipes.yaml +23 -0
- package/graphs/intake/intake-daily.yaml +2 -1
- package/graphs/ops/recipes.yaml +3 -0
- package/graphs/ops/secret-exposure.yaml +24 -0
- package/graphs/release/recipes.yaml +3 -0
- package/graphs/release/release-loop.yaml +4 -1
- package/graphs/video/explainer-line.yaml +2 -2
- package/package.json +2 -1
- package/plugins/card-followup/examples/sample-card.png +0 -0
- package/plugins/elanous-hwp/README.md +25 -0
- package/plugins/elanous-hwp/cli.ts +22 -0
- package/plugins/elanous-hwp/converter.ts +237 -0
- package/plugins/elanous-hwp/fixtures/fixed-controls.hwpx +0 -0
- package/plugins/elanous-hwp/fixtures/fixed-table-controls.hwpx +0 -0
- package/plugins/elanous-hwp/fixtures/fixed.hwpx +0 -0
- package/plugins/elanous-hwp/plugin.json +16 -0
- package/plugins/elanous-hwp/plugin.ts +40 -0
- package/scripts/ci-public-export-leak-gate.ts +75 -14
- package/scripts/ci-public-leak-gate.ts +44 -9
- package/scripts/context-hooks/claude-stop.sh +4 -0
- package/scripts/context-hooks/emit.ts +24 -0
- package/scripts/context-hooks/post-tool-use.sh +4 -0
- package/scripts/coord-channel-watch.sh +12 -0
- package/scripts/coord-requests-bridge.ts +143 -0
- package/scripts/field-feed/lib.ts +4 -0
- package/scripts/fleet/node-setup.sh +20 -3
- package/scripts/homebrew-formula-bump.ts +69 -0
- package/scripts/lib/telegram-inject-args.ts +31 -0
- package/scripts/marketing/measure-site-numbers.ts +169 -0
- package/scripts/measure-gate-shards.ts +309 -0
- package/scripts/measure-pod-memory-by-goal.ts +130 -0
- package/scripts/mission-request-judge.ts +31 -1
- package/scripts/morning-report.ts +2 -2
- package/scripts/opportunity-scan.ts +1 -1
- package/scripts/release-loop/auto-approve-node.ts +21 -4
- package/scripts/release-loop/checklist-gate-node.ts +2 -1
- package/scripts/release-loop/cut-branch.ts +84 -0
- package/scripts/release-loop/gate-node.ts +22 -15
- package/scripts/release-loop/mac-smoke-node.ts +229 -0
- package/scripts/release-loop/node-verdict.ts +3 -3
- package/scripts/release-loop/ops-upgrade-node.ts +47 -6
- package/scripts/release-loop/publish-node.ts +4 -1
- package/scripts/release-loop/tui-node-checks.ts +42 -0
- package/scripts/release-loop/tui-sim-node.ts +32 -8
- package/scripts/release-loop/unattended-release.ts +5 -3
- package/scripts/release-loop/version-node.ts +74 -13
- package/scripts/signal-digest-cycle.ts +2 -7
- package/scripts/signal-digest-photo.ts +11 -0
- package/scripts/tech1-public-measure.ts +94 -0
- package/scripts/telegram-inject.ts +14 -6
- package/scripts/test-diet/node.ts +1 -1
- package/scripts/test-diet/remeasure-list.ts +112 -0
- package/scripts/tui-regress.ts +2 -2
- package/scripts/ux/demo-rehearsal.ts +247 -0
- package/scripts/ux/demo-seed.ts +108 -0
- package/scripts/ux/lib/rehearsal-verdict.ts +80 -0
- package/skills/diagram-master/SKILL.md +366 -0
- package/skills/diagram-master/references/engines/excalidraw/color-palette.md +67 -0
- package/skills/diagram-master/references/engines/excalidraw/element-templates.md +182 -0
- package/skills/diagram-master/references/engines/excalidraw/json-schema.md +71 -0
- package/skills/diagram-master/references/engines/excalidraw/render_excalidraw.py +189 -0
- package/skills/diagram-master/references/engines/excalidraw/render_template.html +57 -0
- package/skills/diagram-master/references/engines/matplotlib/matplotlib-patterns.md +235 -0
- package/skills/diagram-master/references/engines/matplotlib/render_matplotlib.py +184 -0
- package/skills/diagram-master/references/engines/mermaid/domain-templates.md +435 -0
- package/skills/diagram-master/references/engines/mermaid/render_mermaid.py +116 -0
- package/skills/diagram-master/references/engines/mermaid/syntax-reference.md +2247 -0
- package/skills/diagram-master/references/engines/nanobannana/render_nanobannana2.py +168 -0
- package/skills/diagram-master/references/engines/svg/color-palette.md +188 -0
- package/skills/diagram-master/references/engines/svg/html-base-template.html +332 -0
- package/skills/diagram-master/references/engines/svg/interactivity-patterns.md +435 -0
- package/skills/diagram-master/references/engines/svg/render_interactive_svg.py +212 -0
- package/skills/diagram-master/references/engines/svg/svg-element-templates.md +349 -0
- package/skills/diagram-master/references/examples/README.md +69 -0
- package/skills/diagram-master/references/examples/ref_grid_architecture.png +0 -0
- package/skills/diagram-master/references/examples/ref_layered_flow.png +0 -0
- package/skills/diagram-master/references/pyproject.toml +16 -0
- package/skills/diagram-master/references/quality-checklist.md +33 -0
- package/skills/diagram-master/references/routing-guide.md +164 -0
- package/skills/diagram-master/references/uv.lock +1356 -0
- package/skills/google-workspace/SKILL.md +33 -0
- package/skills/google-workspace/scripts/gws-safe.sh +177 -0
- package/skills/grill-me/SKILL.md +1 -1
- package/skills/lecture-note-digitizer/SKILL.md +926 -0
- package/skills/lecture-note-digitizer/references/convert_to_pdf.py +30 -0
- package/skills/lecture-note-digitizer/references/extract_slide_diagram.py +73 -0
- package/skills/lecture-note-digitizer/references/html-template.md +167 -0
- package/skills/lecture-note-digitizer/references/katex-style-guide.md +165 -0
- package/skills/omni-crawl/SKILL.md +21 -11
- package/skills/omni-crawl/scripts/main.ts +6 -6
- package/skills/omni-crawl/src/router.ts +3 -3
- package/skills/omni-digest/SKILL.md +17 -9
- package/skills/omni-digest/digest.md +2 -2
- package/skills/omni-digest/src/fetch.ts +30 -3
- package/skills/pitch-deck/SKILL.md +2 -2
- package/skills/pitch-deck/template.html +2 -2
- package/skills/youtube-master/SKILL.md +163 -0
- package/skills/youtube-master/package-lock.json +558 -0
- package/skills/youtube-master/package.json +13 -0
- package/skills/youtube-master/references/study-note-template.md +124 -0
- package/skills/youtube-master/scripts/main.ts +435 -0
- package/skills/youtube-master/scripts/transcribe-local.ts +24 -0
- package/skills/youtube-master/src/audio.ts +63 -0
- package/skills/youtube-master/src/domain-staging.ts +50 -0
- package/skills/youtube-master/src/env.ts +36 -0
- package/skills/youtube-master/src/obsidian.ts +155 -0
- package/skills/youtube-master/src/router.ts +110 -0
- package/skills/youtube-master/src/stt.ts +199 -0
- package/skills/youtube-master/src/study-note.ts +175 -0
- package/skills/youtube-master/src/summarize.ts +358 -0
- package/skills/youtube-master/src/transcript.ts +76 -0
- package/skills/youtube-master/src/types.ts +91 -0
- package/skills/youtube-master/src/util.ts +93 -0
- package/skills/youtube-master/src/youtube.ts +70 -0
- package/skills/youtube-master/tsconfig.json +13 -0
- package/src/acp/server.ts +5 -2
- package/src/agent-mission/driver.ts +215 -23
- package/src/agent-mission/pty-decision.ts +71 -0
- package/src/agent-mission/review-loop.ts +30 -0
- package/src/autopilot/build/llm-conflict-merge.ts +16 -3
- package/src/autopilot/pty-control-loop.ts +4 -1
- package/src/autopilot/tool-registry.ts +2 -0
- package/src/boot/daemon-prompt-turn.ts +5 -0
- package/src/boot/daemon-runtime.ts +9 -3
- package/src/boot/daemon-tools/web-search.ts +3 -0
- package/src/card-followup/core.ts +109 -0
- package/src/chat/index.ts +2 -0
- package/src/cli/drive-input-jail.ts +101 -0
- package/src/cli/hooks-cli.ts +17 -3
- package/src/cli/make-cli.ts +43 -0
- package/src/cli/persona-cli.ts +98 -9
- package/src/cli/plugin-cli.ts +31 -22
- package/src/cli/pod-cli.ts +36 -9
- package/src/cli/pod-memory-advice.ts +35 -0
- package/src/cli/pr-cli.ts +51 -15
- package/src/cli/pty-drive-cli.ts +41 -7
- package/src/cli/pty-drive-verdict.ts +40 -0
- package/src/cli/release-cli.ts +63 -10
- package/src/cli/setup-cli.ts +43 -1
- package/src/cli/skills-cli.ts +17 -1
- package/src/context-bus/claude-hooks-install.ts +10 -0
- package/src/context-bus/context-now-surfaces.ts +65 -0
- package/src/context-bus/context-now.ts +104 -0
- package/src/context-bus/coord-events.ts +2 -2
- package/src/context-bus/external-events.ts +52 -0
- package/src/context-bus/long-term-memory.ts +108 -0
- package/src/context-bus/nightly-condense.ts +153 -0
- package/src/context-bus/session-events.ts +35 -0
- package/src/dashboard/dashboard-status-lines.ts +2 -0
- package/src/dashboard/index.ts +17 -4
- package/src/dashboard/slash-runtime/dashboard-handlers.ts +31 -1
- package/src/decisions/decision-cards.ts +10 -3
- package/src/decisions/decision-ledger.ts +13 -5
- package/src/discord/sprint21-runtime.ts +5 -1
- package/src/discord-self-message.ts +32 -0
- package/src/discord-slash-wire.ts +5 -1
- package/src/discord.ts +17 -1
- package/src/domains/core-tools.ts +3 -2
- package/src/domains/outbound-alert.ts +105 -32
- package/src/domains/outbound-log-probe.ts +8 -0
- package/src/domains/telegram-kind-route.ts +51 -13
- package/src/exec-requests/default-outputs.ts +25 -0
- package/src/exec-requests/planner.ts +10 -2
- package/src/exec-requests/runner.ts +20 -6
- package/src/exec-requests/store.ts +3 -0
- package/src/execution-loop/launch-gate.ts +109 -0
- package/src/field/field-reel.ts +5 -1
- package/src/field-note/index.ts +201 -0
- package/src/field-note/telegram.ts +142 -0
- package/src/field-note/transcribe.ts +248 -0
- package/src/graph-kinds/registry.ts +3 -3
- package/src/graph-runner/graph-cli.ts +61 -1
- package/src/graph-runner/graph-grow-llm.ts +47 -0
- package/src/graph-runner/graph-grow.ts +50 -0
- package/src/graph-runner/runner.ts +329 -33
- package/src/grok/agent-search.ts +8 -2
- package/src/guardian/secret-exposure-scan.ts +101 -0
- package/src/harness/harness-cli-command.ts +375 -13
- package/src/harness/harness-pod-dispatch.ts +43 -23
- package/src/harness/harness-seams.ts +38 -4
- package/src/harness/harness-stop.ts +23 -4
- package/src/harness/launch-registry.ts +91 -0
- package/src/harness/process-garbage.ts +5 -3
- package/src/hooks/consult-intake.ts +153 -0
- package/src/hooks/dispatch.ts +82 -0
- package/src/hooks/expose.ts +254 -0
- package/src/hooks/github-shadow.ts +108 -0
- package/src/hooks/providers.ts +71 -5
- package/src/hooks/queue.ts +1 -1
- package/src/hooks/receiver.ts +94 -16
- package/src/index.ts +76 -14
- package/src/intake-plane/categorize.ts +18 -46
- package/src/intake-plane/discord-seat-work.ts +38 -2
- package/src/intake-plane/front-route-classifier.ts +33 -39
- package/src/intake-plane/persona-answer.ts +30 -0
- package/src/intake-plane/runtime-callables.ts +8 -1
- package/src/intake-plane/telegram-seat-work.ts +36 -2
- package/src/intake-plane/wish-card.ts +33 -0
- package/src/intake-plane/wish-folder.ts +67 -0
- package/src/intent-gate/gate.ts +30 -10
- package/src/live/detail-switch.ts +5 -0
- package/src/llm/difficulty.ts +57 -0
- package/src/llm/judge-layer.ts +101 -0
- package/src/llm/mission-router.ts +33 -19
- package/src/loops/contract/examples/cmo-seat.loop.yaml +51 -0
- package/src/loops/contract/examples/orchestrator.loop.yaml +57 -0
- package/src/loops/contract/examples/steward.loop.yaml +50 -0
- package/src/loops/contract/loop-agent.schema.json +138 -0
- package/src/loops/contract/validate.ts +64 -0
- package/src/loops/registry.ts +20 -6
- package/src/market/signed-index.ts +4 -0
- package/src/maturity/bot-command-maturity.ts +45 -0
- package/src/maturity/feature-maturity.ts +27 -4
- package/src/model-tier/index.ts +2 -2
- package/src/model-tier/tier-resolver.ts +20 -20
- package/src/model-tier/types.ts +6 -6
- package/src/mss/logging/log-store.ts +15 -0
- package/src/nexus/api/config-model-tier.ts +5 -4
- package/src/nexus/api/fabric-plans.ts +53 -0
- package/src/nexus/api/harness-api.ts +5 -1
- package/src/nexus/api/health.ts +2 -0
- package/src/nexus/api/http-server.ts +67 -8
- package/src/nexus/api/inside-events.ts +226 -0
- package/src/nexus/api/meta-api.ts +21 -8
- package/src/nexus/api/missions.ts +6 -1
- package/src/nexus/api/ops-seats.ts +33 -0
- package/src/nexus/api/outbound-report.ts +40 -7
- package/src/nexus/api/outputs-route.ts +44 -0
- package/src/nexus/api/personas.ts +95 -53
- package/src/nexus/api/seat-requests.ts +44 -2
- package/src/nexus/api/sessions-store.ts +17 -38
- package/src/nexus/api/sub-seat-charters.ts +34 -0
- package/src/nexus/api/tabs-mutations.ts +3 -1
- package/src/nexus/api/task-cards-api.ts +19 -0
- package/src/nexus/api/trace.ts +18 -6
- package/src/nexus/api/workflow-history.ts +88 -0
- package/src/nexus/api/workflow-run-event-bridge.ts +1 -0
- package/src/nexus/api/workflows.ts +132 -6
- package/src/nexus/index.ts +2 -0
- package/src/nexus/kinds/webterm.ts +2 -1
- package/src/nexus/outbound/delivery-ledger.ts +17 -8
- package/src/nexus/outbound/router.ts +8 -3
- package/src/nexus/webterm/pty.ts +6 -2
- package/src/onboarding/cli-auth-status.ts +80 -0
- package/src/onboarding/voice-ai.ts +3 -3
- package/src/org/seat-budget.ts +48 -0
- package/src/org/stall-escalation.ts +63 -0
- package/src/outputs/ledger.ts +120 -0
- package/src/persona/persona-todo.ts +79 -0
- package/src/persona/presets.ts +123 -2
- package/src/persona/team-set.ts +155 -0
- package/src/plugins/install/plugin-install.ts +14 -0
- package/src/plugins/maker/market-bundle.ts +110 -0
- package/src/plugins/maker/plugin-maker.ts +254 -11
- package/src/plugins/maker/wizard-generate.ts +103 -0
- package/src/pod-lease/admission.ts +150 -0
- package/src/pod-lease/dependency-state.ts +85 -0
- package/src/pod-lease/host-lease.ts +127 -0
- package/src/project/project-suggestion.ts +16 -0
- package/src/project/session-context.ts +24 -0
- package/src/release-loop/checklist.ts +17 -5
- package/src/release-loop/feature-store.ts +29 -13
- package/src/release-loop/landed-but-yellow.ts +48 -0
- package/src/release-loop/next-md-merge.ts +58 -0
- package/src/release-loop/release-note.ts +59 -4
- package/src/seat-dispatch/seat-ask.ts +130 -0
- package/src/seat-dispatch/seat-questions.ts +100 -0
- package/src/seat-loop/seat-loop.ts +709 -29
- package/src/seat-loop/seat-report.ts +37 -2
- package/src/self-dev/dev-cli.ts +4 -1
- package/src/self-dev/dev-pipeline.ts +37 -1
- package/src/self-dev/draft-sweep.ts +79 -40
- package/src/self-dev/draft-triage-rules.ts +62 -7
- package/src/self-dev/fabric-plan-core.ts +297 -0
- package/src/self-dev/orchestrate.ts +36 -4
- package/src/self-dev/release-path-guard.ts +62 -0
- package/src/self-dev/shard-aggregate.ts +230 -0
- package/src/self-dev/shard-placement.ts +60 -0
- package/src/self-dev/shard-plan.ts +48 -0
- package/src/self-dev/shard-pod-run.ts +77 -0
- package/src/self-dev/shard-run.ts +105 -0
- package/src/self-implement/budget-gate.ts +29 -12
- package/src/self-implement/gate-baseline.ts +1 -1
- package/src/self-implement/gate-candidate-ranking.ts +60 -0
- package/src/self-implement/gate-cli.ts +40 -1
- package/src/self-implement/gate-scope.ts +44 -13
- package/src/self-implement/graph-variant.ts +171 -0
- package/src/self-implement/harness-policy-gates.ts +1 -1
- package/src/self-implement/headless-elanous-driver.ts +27 -3
- package/src/self-implement/host-regate.ts +22 -1
- package/src/self-implement/importer-test-index.ts +2 -1
- package/src/self-implement/l8-merge-queue.ts +130 -0
- package/src/self-implement/orchestrator.ts +257 -9
- package/src/self-implement/route-consumer-test-index.ts +122 -0
- package/src/self-implement/seams.ts +72 -11
- package/src/self-implement/test-seams.ts +2 -0
- package/src/self-implement/uncommitted-work.ts +59 -0
- package/src/session/index.ts +36 -13
- package/src/skills/gift-install.ts +215 -0
- package/src/skills/tools/web-search.ts +4 -1
- package/src/steward/launch.ts +42 -26
- package/src/steward/steward-cards.ts +17 -9
- package/src/steward/triage.ts +46 -14
- package/src/task-cards/card-cli.ts +25 -1
- package/src/task-orchestrator/mission.ts +5 -0
- package/src/task-orchestrator/store.ts +12 -3
- package/src/task-orchestrator/surfaces/pod-command-job.ts +43 -17
- package/src/task-orchestrator/surfaces/pod-lease.ts +156 -19
- package/src/task-orchestrator/surfaces/pod-pool.ts +127 -26
- package/src/task-orchestrator/surfaces/self-implement-pod.ts +222 -40
- package/src/task-orchestrator/surfaces/self-implement.ts +15 -2
- package/src/task-orchestrator/types.ts +2 -0
- package/src/telegram-card-followup.ts +16 -96
- package/src/telegram-commands.ts +31 -1
- package/src/telegram-project-command.ts +145 -0
- package/src/telegram-report.ts +21 -17
- package/src/telegram.ts +61 -8
- package/src/tool-runtime/self-cognition-runtimes.ts +13 -3
- package/src/user-config.ts +110 -24
- package/src/version/packed-revision.json +1 -1
- package/src/web-search/grok.ts +7 -1
- package/src/web-search/index.ts +28 -1
- package/src/web-search/provider.ts +4 -0
- package/src/web-search/x-intent.ts +5 -0
- package/src/workflow-runtime/executor.ts +277 -47
- package/src/workflow-runtime/index.ts +1 -0
- package/src/workflow-runtime/nodes/subworkflow.ts +60 -0
- package/src/workflow-runtime/plugin-kind-node.ts +1 -1
- package/src/workflow-runtime/schema.ts +79 -4
- package/src/workflow-runtime/types.ts +35 -4
- package/apps/pwa/out/_next/static/2DsiDfDCks44g1cPUMhiW/_buildManifest.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1105-c473ed46272fba79.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1377-1efeffbbac0963ff.js +0 -1
- package/apps/pwa/out/_next/static/chunks/1470.98a6ab61ccb4131c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/216-5acd01cbde4acda7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2330-c2f07246c8788af1.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2375-cb6debea56cce4fb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/24-e6d28380efab7faf.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2977-e38442e86289f1d3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/2982-2a2df543be3d2e5a.js +0 -25
- package/apps/pwa/out/_next/static/chunks/3403.4bc97b4066945a94.js +0 -5
- package/apps/pwa/out/_next/static/chunks/3615-740dd270764ffa24.js +0 -1
- package/apps/pwa/out/_next/static/chunks/371-4ad6af55dad02ced.js +0 -1
- package/apps/pwa/out/_next/static/chunks/3734-1015fe991eb9b7e7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/4114-3e63117452378807.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5012-a7fe6f3c8b6fe45a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5609-012bb3557211f07e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5783-ef40ebfc91d55230.js +0 -1
- package/apps/pwa/out/_next/static/chunks/5791-bb82743fa6299562.js +0 -1
- package/apps/pwa/out/_next/static/chunks/62-ff227c3edb8b248b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6320-baac91d68843a9a6.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6725-68ab7cc0b1faf00d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/6998-a654fe5c58271600.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7633-1b3709b0854c9412.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7647.2fcd30d894d5ee30.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7673-2eda1507d38dadb8.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7951-8b03dbb10b24cd06.js +0 -1
- package/apps/pwa/out/_next/static/chunks/7990-e12efba616f46e03.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8142-744998d65d7bb17e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8195-6fde3d7a39859206.js +0 -10
- package/apps/pwa/out/_next/static/chunks/8619-4365e03a2862830f.js +0 -1
- package/apps/pwa/out/_next/static/chunks/8894-b5fb36bab837cd29.js +0 -1
- package/apps/pwa/out/_next/static/chunks/920-f7dceb78f1c585ef.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9454-84d0d5d77446bd92.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9651-3cd291a6fa1370d2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/988-5f92e7ab7ccea3dd.js +0 -1
- package/apps/pwa/out/_next/static/chunks/9989-5582582f06429840.js +0 -1
- package/apps/pwa/out/_next/static/chunks/ae787e4c-f2998de7f1ba72a4.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/_not-found/page-859cea1570b6227a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/approvals/page-d2253d7e58ef1890.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/autopilot/page-5441d4a9ab35e518.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/board/page-d9b12d680922d980.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/bots/page-e268d6d145827a22.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/chat/page-f8116559c7424da7.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/consult/page-1085399fd0f32112.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/control/page-1df686a14f65895a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/design-check/page-54e1f966ab60a4dc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/editor/page-7ed95f296f5ee8e9.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/exec/page-11edac668d77e5c3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/field/page-59e2b9a22cd5a6d5.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/healthz/route-859cea1570b6227a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/intake/page-2976df21ad74ab48.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/layout-34d211a67f16d510.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/live/page-8ff652d5d950639b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/market/page-b31610deda76337b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-6cb0e1bbefe5fb3d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/morning/page-a286a152cf584576.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/not-found-d9237581e7003bcb.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/observatory/page-83274e761643fdd2.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-ceee6cfb1d4e6d68.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/release/page-9c9f8bb3e4a64091.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-c17217603ea3426a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/page-efb6177cbf1e8a51.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/reflection/page-d307523703bc4df3.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/scheduler/page-462f4e4bab45ce7d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/sessions/page-8990e96f33af3837.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-e168fa1030af0548.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/settings/page-1233e05a4068bc9c.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/done/page-13a1840b1fac337a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/layout-859cea1570b6227a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/setup/page-64a29fc80b11ab55.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/share/page-68e787339a16b3dc.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/showroom/page-4fddc90b23feb215.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/tasks/page-886ba8260dc79c79.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/term/page-0f26507a1722e40b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/today/page-109d4ccd42259c9d.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/trace/page-f5c2a4e510726774.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/vault/page-b2e0039416f42522.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-26102fd7350f171e.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workflows/page-708948bc8a802794.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/workspace/page-5e5611620f78fb0b.js +0 -1
- package/apps/pwa/out/_next/static/chunks/app/worktrees/page-139ba5c367bbf60a.js +0 -1
- package/apps/pwa/out/_next/static/chunks/framework-ea806bb57f2b8923.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-8d2302399c2c8f87.js +0 -1
- package/apps/pwa/out/_next/static/chunks/main-app-202b4e81f33895ea.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_app-b10928c60f0b8488.js +0 -1
- package/apps/pwa/out/_next/static/chunks/pages/_error-689039227d443fab.js +0 -1
- package/apps/pwa/out/_next/static/chunks/webpack-e5bea36f183b25e6.js +0 -1
- package/apps/pwa/out/_next/static/css/43feca5fd387dcbd.css +0 -1
- /package/apps/pwa/out/_next/static/{2DsiDfDCks44g1cPUMhiW → -6XrAoD3eU7NyMHAE4xPS}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "NodeNext",
|
|
5
|
+
"moduleResolution": "NodeNext",
|
|
6
|
+
"strict": true,
|
|
7
|
+
"esModuleInterop": true,
|
|
8
|
+
"skipLibCheck": true,
|
|
9
|
+
"outDir": "dist",
|
|
10
|
+
"rootDir": "."
|
|
11
|
+
},
|
|
12
|
+
"include": ["src/**/*.ts", "scripts/**/*.ts"]
|
|
13
|
+
}
|
package/src/acp/server.ts
CHANGED
|
@@ -241,6 +241,8 @@ export interface AcpServerOptions {
|
|
|
241
241
|
/** ACP standalone entry: require session cwd or an explicit boot default. */
|
|
242
242
|
requireSessionToolCwd?: boolean;
|
|
243
243
|
bootToolCwd?: string;
|
|
244
|
+
/** Optional PTY factory for the web terminal; production uses PreviewTerminal. */
|
|
245
|
+
createWebTerminal?: (opts: ConstructorParameters<typeof import('../preview/terminal.js').PreviewTerminal>[0]) => import('../preview/terminal.js').PreviewTerminal;
|
|
244
246
|
/** Test seam for exercising stdio EOF with controlled byte streams. */
|
|
245
247
|
stdioInput?: ReadableStream<Uint8Array>;
|
|
246
248
|
stdioOutput?: WritableStream<Uint8Array>;
|
|
@@ -2190,7 +2192,8 @@ function wireAcpConnection(
|
|
|
2190
2192
|
throw new Error('terminal/spawn: sessionId required');
|
|
2191
2193
|
}
|
|
2192
2194
|
const tid = resolveAcpTerminalId(p.terminalId);
|
|
2193
|
-
const cwd = typeof p.cwd === 'string' && p.cwd.length > 0 ? p.cwd
|
|
2195
|
+
const cwd = typeof p.cwd === 'string' && p.cwd.length > 0 ? p.cwd
|
|
2196
|
+
: (await import('../project/session-context.js')).resolveSessionProjectContext(p.sessionId)?.cwd ?? process.cwd();
|
|
2194
2197
|
const cols = typeof p.cols === 'number' && p.cols > 0 ? p.cols : 80;
|
|
2195
2198
|
const rows = typeof p.rows === 'number' && p.rows > 0 ? p.rows : 24;
|
|
2196
2199
|
|
|
@@ -2234,7 +2237,7 @@ function wireAcpConnection(
|
|
|
2234
2237
|
}
|
|
2235
2238
|
|
|
2236
2239
|
const { PreviewTerminal } = await import('../preview/terminal.js');
|
|
2237
|
-
const pt = new PreviewTerminal({
|
|
2240
|
+
const pt = (opts.createWebTerminal ?? ((terminalOpts) => new PreviewTerminal(terminalOpts)))({
|
|
2238
2241
|
cols, rows, cwd,
|
|
2239
2242
|
// Web-terminal child shell renders inside the PWA's xterm.js,
|
|
2240
2243
|
// which implements the xterm-256color terminfo. When the daemon
|
|
@@ -20,8 +20,12 @@ import { configuredWorktreeRoot } from '../user-config.js';
|
|
|
20
20
|
import { worktreeHasChanges, commitWorktree, changedFiles } from '../self-implement/seams.js';
|
|
21
21
|
import { streamLLM, type LLMMessage } from '../llm.js';
|
|
22
22
|
import { debug } from '../debug/log.js';
|
|
23
|
+
import { emitPtyDecision, type DecisionInput } from './pty-decision.js';
|
|
24
|
+
import { observeExternalEvent } from '../context-bus/external-events.js';
|
|
25
|
+
import { emitSessionEvent, type SessionEventInput } from '../context-bus/session-events.js';
|
|
23
26
|
import { emitDecision } from '../live/detail-switch.js';
|
|
24
27
|
import { resolvePtyWebAddress } from '../cli/pty-web-address.js';
|
|
28
|
+
import { verdictForFinalPtyScreen } from '../cli/pty-drive-verdict.js';
|
|
25
29
|
import { reemitPtyUsage } from '../budget/pty-usage-reemit.js';
|
|
26
30
|
import { classifyAuthError } from '../oauth/codex.js';
|
|
27
31
|
import type { FallbackStep } from '../oauth/fallback-chain.js';
|
|
@@ -449,6 +453,8 @@ export interface AgentMissionSpec {
|
|
|
449
453
|
evidence: EvidenceMode;
|
|
450
454
|
/** RFC 최대 라운드(기본 16). */
|
|
451
455
|
maxRounds?: number;
|
|
456
|
+
/** 화면 무변화 회복 문턱(ms, 기본 45초). */
|
|
457
|
+
recoverAfterMs?: number;
|
|
452
458
|
/** 완료 시 자동 commit(기본 true). */
|
|
453
459
|
commit?: boolean;
|
|
454
460
|
/** 스크린 캡처 저장 디렉토리. */
|
|
@@ -522,6 +528,8 @@ export interface AgentMissionDeps {
|
|
|
522
528
|
createWorktree?: typeof createWorktree;
|
|
523
529
|
recordWorktreeProvenance?: typeof recordHarnessWorktreeProvenance;
|
|
524
530
|
runControlLoop?: typeof runPtyControlLoop;
|
|
531
|
+
/** Capture decisions in tests without replacing the process-wide debug logger. */
|
|
532
|
+
emitPtyDecision?: typeof emitPtyDecision;
|
|
525
533
|
/** Inject controller responses while keeping the production control loop. */
|
|
526
534
|
controlStream?: StreamLLMFn;
|
|
527
535
|
resolvePtyWebAddress?: typeof resolvePtyWebAddress;
|
|
@@ -534,6 +542,12 @@ export interface AgentMissionDeps {
|
|
|
534
542
|
checkEvidence?: typeof checkEvidence;
|
|
535
543
|
commitWorktree?: typeof commitWorktree;
|
|
536
544
|
dispatchOpenPullRequest?: typeof dispatchOpenPullRequest;
|
|
545
|
+
/** Optional context-journal sink for isolated missions. */
|
|
546
|
+
emitContextEvent?: (input: SessionEventInput) => void;
|
|
547
|
+
/** Internal continuation retains the original mission's context-event owner. */
|
|
548
|
+
contextEventRun?: boolean;
|
|
549
|
+
/** Carries a PR number back to the outer mission's context event. */
|
|
550
|
+
onMissionPrNumber?: (number: number) => void;
|
|
537
551
|
terminateProcessTree?: typeof terminateMissionProcessTree;
|
|
538
552
|
repoStatus?: (repo: string) => string | Promise<string>;
|
|
539
553
|
emitDecision?: typeof emitDecision;
|
|
@@ -830,18 +844,37 @@ export interface MissionControlBrainOpts {
|
|
|
830
844
|
readonly handoffEnabled?: boolean;
|
|
831
845
|
/** Screen-grounded brain summary for the next backend, never the raw PTY screen. */
|
|
832
846
|
readonly onSummary?: (summary: string) => void;
|
|
847
|
+
readonly onDecision?: (text: string, reply?: { question: string; answer: string }) => void;
|
|
848
|
+
readonly recoverAfterMs?: number;
|
|
849
|
+
readonly initialCommand?: string;
|
|
850
|
+
readonly onRecover?: (blocked: string, action: string) => void;
|
|
833
851
|
}
|
|
834
852
|
|
|
835
853
|
/** 기존 5-action mission 판단을 canonical PTY control-loop 결정으로 축소한다. search는 이 경계에서만
|
|
836
854
|
* 부작용(context 기록)을 끝내고, child에는 context를 읽고 계속하라는 단일 input만 전달한다. */
|
|
837
|
-
export
|
|
855
|
+
export type MissionControlBrain = RunSupervisor & {
|
|
856
|
+
/** Report whether the last returned input was accepted by the PTY; recovery stages and events commit only on acceptance. */
|
|
857
|
+
readonly onInputResult: (text: string, accepted: boolean) => void;
|
|
858
|
+
};
|
|
859
|
+
|
|
860
|
+
export function createMissionControlBrain(opts: MissionControlBrainOpts): MissionControlBrain {
|
|
838
861
|
const history: string[] = [];
|
|
839
862
|
const backendName = (opts.backend ?? codexBackend).name;
|
|
840
863
|
// ★ P4 dedup(제한적 재시도·리뷰) — (layer:spec)별 시도횟수. 성공 시 영구 차단, 실패는 최대 2회까지
|
|
841
864
|
// 허용(일시 네트워크/프로세스 오류는 재시도, 지속 실패는 루프 차단).
|
|
842
865
|
const provisionAttempts = new Map<string, number>();
|
|
843
866
|
const PROVISION_MAX_ATTEMPTS = 2;
|
|
844
|
-
|
|
867
|
+
const recoverAfterMs = opts.recoverAfterMs ?? 45_000;
|
|
868
|
+
if (!Number.isFinite(recoverAfterMs) || recoverAfterMs <= 0) throw new Error('recoverAfterMs must be positive');
|
|
869
|
+
let lastScreen: string | undefined;
|
|
870
|
+
let repeatedQuestion = 0;
|
|
871
|
+
let lastQuestion: string | undefined;
|
|
872
|
+
let recoveryStage = 0;
|
|
873
|
+
let pendingReplayBlocked: string | undefined;
|
|
874
|
+
// The recovery input returned by the last decide(); committed (stage advance + event) only when the PTY accepts it.
|
|
875
|
+
let pendingRecovery: { blocked: string; action: string; text: string; replay?: boolean } | undefined;
|
|
876
|
+
let lastCommand = opts.initialCommand ?? opts.mission;
|
|
877
|
+
const llmBrain = createLlmControlBrain({
|
|
845
878
|
goal: opts.mission,
|
|
846
879
|
stream: opts.stream,
|
|
847
880
|
maxTokens: 500,
|
|
@@ -855,7 +888,7 @@ export function createMissionControlBrain(opts: MissionControlBrainOpts): RunSup
|
|
|
855
888
|
행동(action):
|
|
856
889
|
- "wait": ${backendName} 가 아직 작업 중(도구 실행/생성)이면 대기.
|
|
857
890
|
- "verify": ${backendName} 가 MISSION-COMPLETE/완료를 주장하면 증거 게이트(내가 실행)로 검증. 완료주장 시 이걸 우선.
|
|
858
|
-
- "send": ${backendName} 가 멈추거나 계속 진행이 필요하면 짧고 명확한 지시(text).
|
|
891
|
+
- "send": ${backendName} 가 멈추거나 계속 진행이 필요하면 짧고 명확한 지시(text). 화면의 질문에 직접 답하는 경우에만 reason 을 Answering question: <화면의 질문 원문> 으로 기록하라. 다른 send 의 reason 은 종전처럼 행동 이유를 적어라.
|
|
859
892
|
- "search": ${backendName} 가 정보/라이브러리/문법/외부자원에 막혔으면 omni-crawl 로 조사(query). ⭐외부 힌트 없이 스스로 판단.
|
|
860
893
|
${opts.handoffEnabled ? ` - "handoff": 다른 담당자로 넘길 때 to(codex/claude/elanous), mission(다음 지시), carry(diff/summary 선택). carry=summary 면 reason 에 화면에서 확인한 리뷰 지적을 구체적으로 요약하라(다음 backend 에 전달된다). claude 리뷰 뒤 지적은 codex 에 summary 로 되돌려라. elanous 는 증거 게이트와 PR.
|
|
861
894
|
- "ask-human": 화면에 로그인 URL/장치 코드가 보이면 reason, url/code(보이는 것만). 토큰·자격파일을 열지 마라.` : ''}${opts.provision ? `
|
|
@@ -873,10 +906,19 @@ ${opts.handoffEnabled ? ` - "handoff": 다른 담당자로 넘길 때 to(codex/c
|
|
|
873
906
|
history.push(`s${obs.step}:${decision.action}`);
|
|
874
907
|
debug.log('agent-mission', 'brain', { step: obs.step, action: decision.action,
|
|
875
908
|
...(decision.action === 'ask-human' ? {} : { reason: decision.reason.slice(0, 120) }) });
|
|
909
|
+
// A '?' on screen alone does not establish that this send answered it. Only an
|
|
910
|
+
// explicit question citation in the brain's reason can attribute the reply.
|
|
911
|
+
const citedQuestion = /^Answering question:\s*(.+\?)\s*$/i.exec(decision.reason)?.[1]?.trim();
|
|
912
|
+
const question = citedQuestion && classifierFrameLines(obs.screen).find((line) => line === citedQuestion);
|
|
913
|
+
opts.onDecision?.(`step ${obs.step}: ${decision.action}${decision.action === 'ask-human' ? '' : ` — ${decision.reason || decision.text || decision.query || ''}`}`,
|
|
914
|
+
decision.action === 'send' && decision.text?.trim() && question ? { question, answer: decision.text } : undefined);
|
|
876
915
|
if (decision.reason && decision.action !== 'ask-human') opts.onSummary?.(decision.reason.slice(0, 2000));
|
|
877
916
|
if (decision.action === 'handoff' && decision.to && decision.mission) return { action: 'handoff', to: decision.to, mission: decision.mission, ...(decision.carry ? { carry: decision.carry } : {}) };
|
|
878
917
|
if (decision.action === 'ask-human') return { action: 'ask-human', reason: decision.reason, ...(decision.url ? { url: decision.url } : {}), ...(decision.code ? { code: decision.code } : {}) };
|
|
879
|
-
if (decision.action === 'send')
|
|
918
|
+
if (decision.action === 'send') {
|
|
919
|
+
lastCommand = decision.text || 'continue';
|
|
920
|
+
return { action: 'input', text: `${lastCommand}\r` };
|
|
921
|
+
}
|
|
880
922
|
if (decision.action === 'verify' || decision.action === 'done') return { action: 'done', reason: decision.reason || 'agent completed' };
|
|
881
923
|
if (decision.action === 'search') {
|
|
882
924
|
await opts.search(decision.query || opts.mission.slice(0, 120), obs.step);
|
|
@@ -911,6 +953,57 @@ ${opts.handoffEnabled ? ` - "handoff": 다른 담당자로 넘길 때 to(codex/c
|
|
|
911
953
|
return { action: 'wait' };
|
|
912
954
|
},
|
|
913
955
|
});
|
|
956
|
+
return {
|
|
957
|
+
onInputResult: (text, accepted) => {
|
|
958
|
+
const recovery = pendingRecovery;
|
|
959
|
+
// Only the input this brain returned settles its recovery step (a trust answer in between does not).
|
|
960
|
+
if (!recovery || recovery.text !== text) return;
|
|
961
|
+
pendingRecovery = undefined;
|
|
962
|
+
if (!accepted) return;
|
|
963
|
+
if (recovery.replay) { pendingReplayBlocked = undefined; opts.onRecover?.(recovery.blocked, recovery.action); return; }
|
|
964
|
+
recoveryStage += 1;
|
|
965
|
+
if (recovery.action === 'Ctrl-C and replay previous command') pendingReplayBlocked = recovery.blocked;
|
|
966
|
+
else opts.onRecover?.(recovery.blocked, recovery.action);
|
|
967
|
+
},
|
|
968
|
+
decide: async (obs, signal) => {
|
|
969
|
+
pendingRecovery = undefined;
|
|
970
|
+
if (signal?.aborted) return { action: 'wait' };
|
|
971
|
+
const lines = classifierFrameLines(obs.screen);
|
|
972
|
+
// Only the active bottom line can be a repeated prompt; a question left in
|
|
973
|
+
// scrollback while new work appears is not a request for input.
|
|
974
|
+
const tail = lines.at(-1);
|
|
975
|
+
const question = tail && /\?(?:\s*\[[^\]\r\n]+\])?\s*$/.test(tail) ? tail : undefined;
|
|
976
|
+
const screenChanged = lastScreen !== undefined && obs.screen !== lastScreen;
|
|
977
|
+
if (screenChanged) recoveryStage = 0;
|
|
978
|
+
repeatedQuestion = question ? (!screenChanged && question === lastQuestion ? repeatedQuestion + 1 : 1) : 0;
|
|
979
|
+
lastQuestion = question;
|
|
980
|
+
lastScreen = obs.screen;
|
|
981
|
+
if (pendingReplayBlocked !== undefined) {
|
|
982
|
+
// Ctrl-C consumes its own step; replay on the next observation even when the
|
|
983
|
+
// interrupted child keeps redrawing a non-prompt screen. A rejected replay is retried.
|
|
984
|
+
const text = `${lastCommand}\r`;
|
|
985
|
+
pendingRecovery = { blocked: pendingReplayBlocked, action: 'Ctrl-C and replay previous command', text, replay: true };
|
|
986
|
+
return { action: 'input', text };
|
|
987
|
+
}
|
|
988
|
+
const blocked = repeatedQuestion >= 3 ? `same question repeated three times: ${question}`
|
|
989
|
+
: (obs.sameScreenMs ?? 0) >= recoverAfterMs ? `screen unchanged for ${obs.sameScreenMs}ms` : undefined;
|
|
990
|
+
if (blocked && opts.evidenceReady()) return { action: 'done', reason: 'Evidence ready on stalled screen' };
|
|
991
|
+
if (blocked && !signal?.aborted) {
|
|
992
|
+
const action = ['Enter', 'Esc', 'Ctrl-C and replay previous command', 'Human needed'] as const;
|
|
993
|
+
const next = action[Math.min(recoveryStage, 3)]!;
|
|
994
|
+
if (next !== 'Human needed') {
|
|
995
|
+
const text = next === 'Enter' ? '\r' : next === 'Esc' ? '\x1b' : '\x03';
|
|
996
|
+
pendingRecovery = { blocked, action: next, text };
|
|
997
|
+
return { action: 'input', text };
|
|
998
|
+
}
|
|
999
|
+
recoveryStage += 1;
|
|
1000
|
+
opts.onRecover?.(blocked, next);
|
|
1001
|
+
const summary = lines.slice(-3).join(' | ').slice(0, 240) || '(empty screen)';
|
|
1002
|
+
return { action: 'no-progress', terminal: true, reason: `사람 필요 · 마지막 화면 요약: ${summary}` };
|
|
1003
|
+
}
|
|
1004
|
+
return llmBrain.decide(obs, signal);
|
|
1005
|
+
},
|
|
1006
|
+
};
|
|
914
1007
|
}
|
|
915
1008
|
|
|
916
1009
|
/**
|
|
@@ -974,6 +1067,7 @@ export function makeMissionObserveStep(deps: {
|
|
|
974
1067
|
bus: ChannelBus;
|
|
975
1068
|
ident: { ptyId: string; instance: string; runId?: string };
|
|
976
1069
|
now?: () => number;
|
|
1070
|
+
onPublishedFrame?: (obs: ControlObservation) => void;
|
|
977
1071
|
}): (obs: ControlObservation, decision: ControlDecision) => Promise<void> {
|
|
978
1072
|
const now = deps.now ?? ((): number => Date.now());
|
|
979
1073
|
let lastFrameState: FrameState | null = null;
|
|
@@ -1008,6 +1102,7 @@ export function makeMissionObserveStep(deps: {
|
|
|
1008
1102
|
...(deps.ident.runId ? { runId: deps.ident.runId } : {}),
|
|
1009
1103
|
...(pngRef ? { pngRef } : {}),
|
|
1010
1104
|
});
|
|
1105
|
+
deps.onPublishedFrame?.(obs);
|
|
1011
1106
|
// capture 는 원 semantics 유지 — 예외 전파(증거/전사 계약 불변).
|
|
1012
1107
|
await deps.capture(`s${obs.step}-${decision.action}`);
|
|
1013
1108
|
};
|
|
@@ -1260,6 +1355,21 @@ export async function runAgentMission(spec: AgentMissionSpec, deps: AgentMission
|
|
|
1260
1355
|
} finally { signal?.removeEventListener('abort', stopWaiting); }
|
|
1261
1356
|
}
|
|
1262
1357
|
const startedAt = Date.now();
|
|
1358
|
+
const contextOwner = !deps.contextEventRun;
|
|
1359
|
+
const contextRunId = contextOwner ? ensureRunId() : undefined;
|
|
1360
|
+
let contextPrNumber: number | undefined;
|
|
1361
|
+
const emitContext = (kind: 'task-claimed' | 'task-done', detail: string): void => {
|
|
1362
|
+
if (!contextOwner) return;
|
|
1363
|
+
try {
|
|
1364
|
+
(deps.emitContextEvent ?? emitSessionEvent)({ kind, seat: 'TC', text: `Agent mission ${detail}: ${spec.mission.split(/\r?\n/, 1)[0]}`,
|
|
1365
|
+
ref: `runId=${contextRunId}${contextPrNumber === undefined ? '' : ` PR=#${contextPrNumber}`}` });
|
|
1366
|
+
} catch (error) {
|
|
1367
|
+
try { debug.log('agent-mission', 'context-event-failed', { kind, runId: contextRunId, error: String(error) }, { level: 'warn' }); } catch { /* fail-soft */ }
|
|
1368
|
+
}
|
|
1369
|
+
};
|
|
1370
|
+
emitContext('task-claimed', 'claimed');
|
|
1371
|
+
let result: AgentMissionResult | undefined;
|
|
1372
|
+
try {
|
|
1263
1373
|
const initialFiles = workdir && spec.evidence.kind === 'doc' ? initialEvidenceFiles(workdir, spec.evidence) : undefined;
|
|
1264
1374
|
let handle: PtyHandle | undefined;
|
|
1265
1375
|
let childPid: number | undefined;
|
|
@@ -1293,10 +1403,12 @@ export async function runAgentMission(spec: AgentMissionSpec, deps: AgentMission
|
|
|
1293
1403
|
});
|
|
1294
1404
|
signal?.addEventListener('abort', abort, { once: true });
|
|
1295
1405
|
if (signal?.aborted) abort();
|
|
1296
|
-
let result: AgentMissionResult;
|
|
1297
1406
|
try {
|
|
1298
1407
|
if (cancelled) await aborted;
|
|
1299
|
-
const body = runAgentMissionBody(spec, { ...deps,
|
|
1408
|
+
const body = runAgentMissionBody(spec, { ...deps, contextEventRun: true, onMissionPrNumber: (number) => {
|
|
1409
|
+
contextPrNumber = number;
|
|
1410
|
+
try { deps.onMissionPrNumber?.(number); } catch { /* context propagation never changes a mission result */ }
|
|
1411
|
+
}, onControlActive: (pending) => {
|
|
1300
1412
|
activeSettled = false;
|
|
1301
1413
|
activeControl = pending.then(() => { activeSettled = true; }, () => { activeSettled = true; });
|
|
1302
1414
|
}, onControlPending: (pending) => {
|
|
@@ -1364,10 +1476,12 @@ export async function runAgentMission(spec: AgentMissionSpec, deps: AgentMission
|
|
|
1364
1476
|
if (paths.length) {
|
|
1365
1477
|
debug.log('agent-mission', 'outside-write', { workdir, pids: [], reason: paths.join(', ') });
|
|
1366
1478
|
(deps.emitDecision ?? emitDecision)({ kind: 'ESCALATE', what: '작업 폴더 밖 쓰기', reason: paths.join(', '), purpose: '사람이 확인한다', target: 'human' });
|
|
1367
|
-
|
|
1479
|
+
result = { ...result, ok: false, reason: 'outside-write', paths, committed: false };
|
|
1480
|
+
return result;
|
|
1368
1481
|
}
|
|
1369
1482
|
}
|
|
1370
1483
|
return result;
|
|
1484
|
+
} finally { emitContext('task-done', result?.ok ? 'completed' : 'ended'); }
|
|
1371
1485
|
}
|
|
1372
1486
|
|
|
1373
1487
|
async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDeps, startedAt: number, initialFiles?: ReadonlyMap<string, string>): Promise<AgentMissionResult> {
|
|
@@ -1574,9 +1688,19 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
|
|
|
1574
1688
|
if (deps.isMissionAborted?.()) { offLive(); throw new Error('MISSION_ABORTED'); }
|
|
1575
1689
|
try { h = spawnPty(ptyOpts); }
|
|
1576
1690
|
catch (error) { offLive(); throw error; }
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1691
|
+
if (backend.name === 'codex') observeExternalEvent({ origin: 'codex-agent-mission', kind: 'started',
|
|
1692
|
+
summary: 'Codex agent mission started', source: `elanous://agent-mission/${encodeURIComponent(runId)}/${encodeURIComponent(h.id)}` });
|
|
1693
|
+
let contextFinished = false;
|
|
1694
|
+
const finishContext = (ok: boolean): void => {
|
|
1695
|
+
if (contextFinished || backend.name !== 'codex') return;
|
|
1696
|
+
contextFinished = true;
|
|
1697
|
+
observeExternalEvent({ origin: 'codex-agent-mission', kind: 'finished',
|
|
1698
|
+
summary: `Codex agent mission ${ok ? 'completed' : 'failed'}`,
|
|
1699
|
+
source: `elanous://agent-mission/${encodeURIComponent(runId)}/${encodeURIComponent(h.id)}` });
|
|
1700
|
+
};
|
|
1701
|
+
deps.onPtyStarted?.(h, () => { if (liveTimer) clearInterval(liveTimer); offLive(); finishContext(false); });
|
|
1702
|
+
if (deps.isMissionAborted?.()) { finishContext(false); return { ok: false, reason: 'aborted', worktree: wt.path, branch: wt.branch,
|
|
1703
|
+
rounds: 0, evidencePath: null, committed: false, usedOmniCrawl: false, detail: 'aborted' }; }
|
|
1580
1704
|
const executorRef = buildExecutorPtyRef({
|
|
1581
1705
|
ptyId: h.id,
|
|
1582
1706
|
backend: backend.name,
|
|
@@ -1589,6 +1713,12 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
|
|
|
1589
1713
|
process.stderr.write(`[agent-mission] pty=${h.id} watch=${webAddress.webUrl ?? `(web unavailable: ${webAddress.pwaUnavailableReason ?? 'not-resolved'})`}\n`);
|
|
1590
1714
|
debug.log('agent-mission', 'pty-link', { id: h.id, webUrl: webAddress.webUrl, webUrlSource: webAddress.webUrlSource });
|
|
1591
1715
|
|
|
1716
|
+
const decisionIdentity = { missionId: runId, sessionId: runId, terminalId: h.id, agent: backend.name };
|
|
1717
|
+
const decisionEvent = (event: Omit<DecisionInput, keyof typeof decisionIdentity>): void => {
|
|
1718
|
+
try { (deps.emitPtyDecision ?? emitPtyDecision)({ ...decisionIdentity, ...event } as DecisionInput); }
|
|
1719
|
+
catch { /* Observation must not change mission control or handoff. */ }
|
|
1720
|
+
};
|
|
1721
|
+
|
|
1592
1722
|
// ⭐P2 arbiter: the child is accessMode='auto' (brain-owned), so the driver —
|
|
1593
1723
|
// the autonomous brain — must write as 'agent' or the arbiter denies it. This
|
|
1594
1724
|
// makes "protected autonomy" real: a human attaching mid-mission (read) can't
|
|
@@ -1615,6 +1745,7 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
|
|
|
1615
1745
|
: 'AGENT_YIELDED: PTY 제어가 사람에게 이양됨(takeover) — 자율 미션 중단');
|
|
1616
1746
|
}
|
|
1617
1747
|
h['write'](s, 'agent');
|
|
1748
|
+
decisionEvent({ step: 'input', text: s === '\r' ? 'Sent Enter' : `Sent ${s.startsWith('\x1b') ? 'key' : 'text'}: ${s.startsWith('\x1b') ? 'navigation' : s}` });
|
|
1618
1749
|
};
|
|
1619
1750
|
|
|
1620
1751
|
let seq = 0;
|
|
@@ -1638,7 +1769,8 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
|
|
|
1638
1769
|
if (liveChunks % 20 === 0) debug.log('agent-mission', 'live', { chunks: liveChunks, tail: s.slice(-80).replace(/\s+/g, ' ') });
|
|
1639
1770
|
}).catch(() => { /* noop */ });
|
|
1640
1771
|
}, 800);
|
|
1641
|
-
const stopLive = (): void => { if (liveTimer) clearInterval(liveTimer); offLive(); };
|
|
1772
|
+
const stopLive = (ok = false): void => { if (liveTimer) clearInterval(liveTimer); offLive(); if (ok) finishContext(true); };
|
|
1773
|
+
try {
|
|
1642
1774
|
|
|
1643
1775
|
// ready + trust — backend 별 신뢰/권한 프롬프트 처리(codex=1, 이후 백엔드는 자체 handler).
|
|
1644
1776
|
await (deps.awaitMission ? deps.awaitMission(waitForQuiet(h, 1500, 20000)) : waitForQuiet(h, 1500, 20000));
|
|
@@ -1648,7 +1780,11 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
|
|
|
1648
1780
|
// A trust menu can need more than one key (claude: ↓ to «Yes», then Enter) — answer until it is gone, at most 3 times.
|
|
1649
1781
|
// 🩸 09-29: one pass sent only ↓, the mission text went into the menu and its Enter confirmed «Yes» instead of
|
|
1650
1782
|
// submitting the mission, which then sat unsent in the input box.
|
|
1651
|
-
for (let pass = 0; pass < 3 && backend.handleTrust?.(screen, (s) =>
|
|
1783
|
+
for (let pass = 0; pass < 3 && backend.handleTrust?.(screen, (s) => {
|
|
1784
|
+
drive(s);
|
|
1785
|
+
// Moving the selection is only input; the trust question is answered when the choice is confirmed.
|
|
1786
|
+
if (s === '\r') decisionEvent({ step: 'answer', text: 'Answered folder trust prompt', detail: { question: 'Trust this folder?', answer: 'Confirm selected choice' } });
|
|
1787
|
+
}); pass++) {
|
|
1652
1788
|
debug.log('agent-mission', 'trust', { agent: backend.name, action: 'handled', pass });
|
|
1653
1789
|
const trusted = (async () => { await waitForQuiet(h, 1500, 15000); return capture('trusted'); })();
|
|
1654
1790
|
screen = await (deps.awaitMission ? deps.awaitMission(trusted) : trusted);
|
|
@@ -1744,6 +1880,8 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
|
|
|
1744
1880
|
if (deps.isMissionAborted?.()) throw new Error('MISSION_ABORTED');
|
|
1745
1881
|
// 미션 전송 — 인핸싱/기억으로 가공됐으면(멀티라인) 파일로 떨궈 read 지시(TUI 멀티라인 위험·verbatim 보존).
|
|
1746
1882
|
// 원문 그대로면(단문) 타이핑.
|
|
1883
|
+
let submittedCommand = spec.mission;
|
|
1884
|
+
const submittedInputs: string[] = [];
|
|
1747
1885
|
if (missionText !== spec.mission) {
|
|
1748
1886
|
const pf = join(wt.path, '.mission-prompt.md');
|
|
1749
1887
|
try { writeFileSync(pf, missionText); } catch { /* noop */ }
|
|
@@ -1751,9 +1889,12 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
|
|
|
1751
1889
|
? '.mission-prompt.md 파일을 읽고 그 안의 미션을 완수하라. [elanous 인핸싱]의 커버리지 체크리스트 모든 항목을 산출물에 빠짐없이 반영하고(요약·일반화 금지), 완료하면 MISSION-COMPLETE 라고 답하라.'
|
|
1752
1890
|
: '.mission-prompt.md 파일을 읽고 그 안의 미션을 완수하라(원문 그대로·[elanous 기억]은 참조 컨텍스트). 완료하면 MISSION-COMPLETE 라고 답하라.';
|
|
1753
1891
|
debug.log('agent-mission', 'mission-send', { via: 'file', file: '.mission-prompt.md', chars: missionText.length, enhanced: enhanceActive });
|
|
1892
|
+
submittedCommand = note;
|
|
1893
|
+
submittedInputs.push(note);
|
|
1754
1894
|
drive(note); await sleep(800); drive('\r');
|
|
1755
1895
|
} else {
|
|
1756
1896
|
debug.log('agent-mission', 'mission-send', { via: 'type', chars: spec.mission.length });
|
|
1897
|
+
submittedInputs.push(spec.mission);
|
|
1757
1898
|
drive(spec.mission); await sleep(800); drive('\r');
|
|
1758
1899
|
}
|
|
1759
1900
|
|
|
@@ -1761,13 +1902,21 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
|
|
|
1761
1902
|
let controllerSummary = deps.previousSummary ?? '';
|
|
1762
1903
|
let reviewSummary = '';
|
|
1763
1904
|
let coverageRetries = enhanceActive && checklist.length ? 2 : 0;
|
|
1905
|
+
let pendingAnswer: { text: string; question: string; answer: string } | undefined;
|
|
1764
1906
|
const search = createMissionSearch({ worktree: wt.path, omniPath });
|
|
1765
1907
|
const brain = createMissionControlBrain({
|
|
1766
1908
|
mission: spec.mission,
|
|
1767
1909
|
backend,
|
|
1768
1910
|
stream: deps.controlStream,
|
|
1769
1911
|
handoffEnabled: true,
|
|
1912
|
+
recoverAfterMs: spec.recoverAfterMs,
|
|
1913
|
+
initialCommand: submittedCommand,
|
|
1914
|
+
onRecover: (blocked, action) => { decisionEvent({ step: 'recover', text: action, detail: { blocked, action } }); },
|
|
1770
1915
|
onSummary: (summary) => { controllerSummary = summary; },
|
|
1916
|
+
onDecision: (text, reply) => {
|
|
1917
|
+
pendingAnswer = reply ? { text: `${reply.answer || 'continue'}\r`, ...reply } : undefined;
|
|
1918
|
+
decisionEvent({ step: 'judge', text });
|
|
1919
|
+
},
|
|
1771
1920
|
evidenceReady: () => spec.chain && spec.chain.length > 1 ? true : verifyEvidence(wt.path, spec.evidence).ok,
|
|
1772
1921
|
search: async (query, step) => {
|
|
1773
1922
|
usedOmni = true;
|
|
@@ -1784,9 +1933,14 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
|
|
|
1784
1933
|
// before asking the LLM — otherwise the mission text is typed into the prompt and the run stalls.
|
|
1785
1934
|
const trustAwareBrain: RunSupervisor = {
|
|
1786
1935
|
decide: (obs, signal) => {
|
|
1936
|
+
decisionEvent({ step: 'read', text: `step ${obs.step} (${obs.state}): ${classifierFrameLines(obs.screen).at(-1) ?? 'empty screen'}` });
|
|
1937
|
+
pendingAnswer = undefined;
|
|
1787
1938
|
let answer: string | undefined;
|
|
1788
1939
|
if (backend.handleTrust?.(obs.screen, (bytes) => { answer = bytes; }) && answer !== undefined) {
|
|
1789
1940
|
debug.log('agent-mission', 'trust', { agent: backend.name, action: 'handled-in-loop', step: obs.step });
|
|
1941
|
+
decisionEvent({ step: 'judge', text: `step ${obs.step}: trust prompt` });
|
|
1942
|
+
// Only the confirming Enter answers the trust question; a navigation key stays an input event.
|
|
1943
|
+
if (answer === '\r') pendingAnswer = { text: answer, question: 'Trust this folder?', answer: 'Confirm selected choice' };
|
|
1790
1944
|
emitDecision({ kind: 'ROUTE', what: `${backend.name} 폴더 신뢰 화면 → 계속`, reason: '시작 뒤 늦게 뜬 신뢰 확인', purpose: '미션을 이어 간다', target: backend.name, phase: 'implement' });
|
|
1791
1945
|
return { action: 'input', text: answer };
|
|
1792
1946
|
}
|
|
@@ -1845,7 +1999,8 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
|
|
|
1845
1999
|
handoffPrSkipped = true;
|
|
1846
2000
|
debug.log('agent-mission', 'handoff-pr-skipped', { reason: 'origin-not-github' });
|
|
1847
2001
|
} else {
|
|
1848
|
-
(deps.dispatchOpenPullRequest ?? dispatchOpenPullRequest)({ title: `agent-mission: ${spec.branch}`, body: deps.originalMission ?? spec.mission, head: spec.branch, base: spec.base ?? 'main' }, { cwd: worktree });
|
|
2002
|
+
const opened = (deps.dispatchOpenPullRequest ?? dispatchOpenPullRequest)({ title: `agent-mission: ${spec.branch}`, body: deps.originalMission ?? spec.mission, head: spec.branch, base: spec.base ?? 'main' }, { cwd: worktree });
|
|
2003
|
+
if (opened.number !== null) deps.onMissionPrNumber?.(opened.number);
|
|
1849
2004
|
}
|
|
1850
2005
|
gatedHandoff = true;
|
|
1851
2006
|
},
|
|
@@ -1879,15 +2034,37 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
|
|
|
1879
2034
|
(d) => debug.log('agent-mission.observe', 'progress', { surfaceId: d.surfaceId, state: d.state, summary: d.summary, unknownInput: d.unknownInput, frame: d.frameCount, runId: d.runId }),
|
|
1880
2035
|
() => {
|
|
1881
2036
|
const handleDeps = controlDepsForHandle(h);
|
|
2037
|
+
const inject = backend.name === 'claude' ? submitSeparately(handleDeps.inject) : handleDeps.inject;
|
|
1882
2038
|
const pending = (deps.runControlLoop ?? runPtyControlLoop)(trustAwareBrain, {
|
|
1883
2039
|
...handleDeps,
|
|
1884
|
-
|
|
2040
|
+
inject: (text) => {
|
|
2041
|
+
const reply = pendingAnswer?.text === text ? pendingAnswer : undefined;
|
|
2042
|
+
pendingAnswer = undefined;
|
|
2043
|
+
const accepted = inject(text);
|
|
2044
|
+
if (accepted) {
|
|
2045
|
+
submittedInputs.push(text);
|
|
2046
|
+
decisionEvent({ step: 'input', text: `Sent ${text.startsWith('\x1b') ? 'key' : 'text'}: ${text.startsWith('\x1b') ? 'navigation' : text}` });
|
|
2047
|
+
}
|
|
2048
|
+
// Recovery stages and recover events are committed only after the PTY accepted the input.
|
|
2049
|
+
brain.onInputResult(text, accepted);
|
|
2050
|
+
if (accepted) {
|
|
2051
|
+
if (reply) decisionEvent({ step: 'answer', text: 'Answered agent question', detail: { question: reply.question, answer: reply.answer } });
|
|
2052
|
+
}
|
|
2053
|
+
return accepted;
|
|
2054
|
+
},
|
|
2055
|
+
injectKey: handleDeps.injectKey && ((name, repeat) => {
|
|
2056
|
+
const accepted = handleDeps.injectKey!(name, repeat);
|
|
2057
|
+
if (accepted) decisionEvent({ step: 'input', text: `Pressed ${name}${repeat ? ` ×${repeat}` : ''}`, detail: { keys: name } });
|
|
2058
|
+
return accepted;
|
|
2059
|
+
}),
|
|
1885
2060
|
...(deps.isMissionAborted ? {
|
|
1886
2061
|
controlStance: () => deps.isMissionAborted!() ? 'unknown' as const : probeControlStance(h, 'agent', (e) =>
|
|
1887
2062
|
debug.log('agent-mission', 'hascontrol-error', { id: h.id, error: (e as Error)?.message ?? String(e) })),
|
|
1888
2063
|
} : {}),
|
|
1889
2064
|
awaitOwnership: { maxWaitMs: AGENT_MISSION_TAKEOVER_WAIT_MS },
|
|
1890
2065
|
settle: async () => {
|
|
2066
|
+
// A frozen screen goes quiet after 6 s, so stall recovery is still observed; work that keeps
|
|
2067
|
+
// drawing output keeps the original 360 s settle and round budget.
|
|
1891
2068
|
const quiet = waitForQuiet(h, 6000, 360000);
|
|
1892
2069
|
await (deps.awaitMission ? deps.awaitMission(quiet) : quiet);
|
|
1893
2070
|
},
|
|
@@ -1903,7 +2080,11 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
|
|
|
1903
2080
|
}
|
|
1904
2081
|
}
|
|
1905
2082
|
},
|
|
1906
|
-
verifyDone: spec.chain && spec.chain.length > 1 ? async () => ({ ok: true as const }) :
|
|
2083
|
+
verifyDone: spec.chain && spec.chain.length > 1 ? async () => ({ ok: true as const }) : async (obs) => {
|
|
2084
|
+
const verdict = await verifyDone(obs);
|
|
2085
|
+
if (!verdict.ok) decisionEvent({ step: 'recover', text: 'Evidence check requires another attempt', detail: { blocked: verdict.retry, action: 'Retry after fixing evidence' } });
|
|
2086
|
+
return verdict;
|
|
2087
|
+
},
|
|
1907
2088
|
handoff: async (decision, obs) => {
|
|
1908
2089
|
try {
|
|
1909
2090
|
if (spec.chain && decision.to !== spec.chain[1]) throw new Error(`chain order violation: expected ${spec.chain[1] ?? 'completion'}, got ${decision.to}`);
|
|
@@ -1916,12 +2097,13 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
|
|
|
1916
2097
|
askHuman: async (decision) => {
|
|
1917
2098
|
try {
|
|
1918
2099
|
await waitForHumanLogin(decision, handoffOps);
|
|
2100
|
+
decisionEvent({ step: 'answer', text: 'Human login question resolved', detail: { question: decision.reason, answer: 'Login completed' } });
|
|
1919
2101
|
} catch (error) {
|
|
1920
2102
|
transitionFailure = error instanceof Error ? error.message : String(error);
|
|
1921
2103
|
throw error;
|
|
1922
2104
|
}
|
|
1923
2105
|
},
|
|
1924
|
-
}, { maxSteps: maxRounds });
|
|
2106
|
+
}, { maxSteps: maxRounds, stuckLimit: maxRounds + 1 });
|
|
1925
2107
|
deps.onControlActive?.(pending);
|
|
1926
2108
|
return pending;
|
|
1927
2109
|
},
|
|
@@ -1954,7 +2136,9 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
|
|
|
1954
2136
|
}
|
|
1955
2137
|
// A gate/PR handoff only counts as success when the control loop itself did not end in error.
|
|
1956
2138
|
if (gatedHandoff && control.termination.kind !== 'error') {
|
|
1957
|
-
|
|
2139
|
+
// The gate hands off a branch, not a file: record what is known instead of mislabeling the worktree directory.
|
|
2140
|
+
decisionEvent({ step: 'done', text: 'Mission handoff gate completed', detail: { result: { kind: 'text', ref: `branch ${wt.branch}` } } });
|
|
2141
|
+
stopLive(true);
|
|
1958
2142
|
try { h.kill(); } catch { /* noop */ }
|
|
1959
2143
|
return { ok: true, worktree: wt.path, branch: wt.branch, rounds: control.steps, evidencePath: wt.path, committed: true, usedOmniCrawl: usedOmni,
|
|
1960
2144
|
...(handoffPrSkipped ? { pr: 'skipped' as const, reason: 'origin-not-github' as const } : {}),
|
|
@@ -1985,6 +2169,7 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
|
|
|
1985
2169
|
maxFallbackDescents: runtimeFallback.maxDescents,
|
|
1986
2170
|
});
|
|
1987
2171
|
if (nextBackend && !deps.isMissionAborted?.()) {
|
|
2172
|
+
decisionEvent({ step: 'recover', text: `Switching ${backend.name} to ${nextBackend.name}`, detail: { blocked: control.termination.message, action: `Retry with ${nextBackend.name}` } });
|
|
1988
2173
|
const nextStep: FallbackStep = nextBackend.name === 'grok' ? 'grok' : 'codex-rotate';
|
|
1989
2174
|
stopLive();
|
|
1990
2175
|
if (h.pid) await (deps.terminateProcessTree ?? terminateMissionProcessTree)(h.pid);
|
|
@@ -2011,24 +2196,31 @@ async function runAgentMissionBody(spec: AgentMissionSpec, deps: AgentMissionDep
|
|
|
2011
2196
|
if (deps.isMissionAborted?.()) return { ok: false, reason: 'aborted', worktree: wt.path, branch: wt.branch,
|
|
2012
2197
|
rounds: round, evidencePath: null, committed: false, usedOmniCrawl: usedOmni, detail: 'aborted' };
|
|
2013
2198
|
const finalEv = verifyEvidence(wt.path, spec.evidence);
|
|
2014
|
-
const
|
|
2199
|
+
const finalScreen = await h.renderScreen();
|
|
2200
|
+
const driveVerdict = verdictForFinalPtyScreen({ screen: finalScreen, inputHistory: submittedInputs, exitCode: h.exitCode ?? null });
|
|
2201
|
+
debug.log('agent-mission', 'drive-verdict', { kind: driveVerdict.kind, reason: driveVerdict.reason.slice(0, 200) });
|
|
2202
|
+
const recoverExhausted = control.termination.kind === 'stuck' && control.termination.reason.startsWith('사람 필요');
|
|
2203
|
+
const accepted = finalEv.ok && !recoverExhausted && driveVerdict.kind !== 'done-but-failed';
|
|
2204
|
+
const evidencePath = accepted ? finalEv.path : null;
|
|
2015
2205
|
let committed = false;
|
|
2016
|
-
if (!deps.isMissionAborted?.() && !spec.workdir &&
|
|
2206
|
+
if (!deps.isMissionAborted?.() && !spec.workdir && accepted && (spec.commit ?? true)) {
|
|
2017
2207
|
const c = (deps.commitWorktree ?? commitWorktree)(wt.path, `chore(agent-mission): ${spec.branch} — ${backend.name}-in-elanous PTY RFC 산출`);
|
|
2018
2208
|
committed = c.ok;
|
|
2019
2209
|
debug.log('agent-mission', 'commit', { ok: c.ok, out: c.out.slice(0, 120) });
|
|
2020
2210
|
}
|
|
2021
|
-
debug.log('agent-mission', 'result', { ok:
|
|
2022
|
-
|
|
2211
|
+
debug.log('agent-mission', 'result', { ok: accepted, rounds: round, evidencePath, committed, usedOmni });
|
|
2212
|
+
decisionEvent({ step: 'done', text: accepted ? 'Mission evidence accepted' : 'Mission ended without sufficient evidence', detail: { result: { kind: evidencePath ? 'file' : 'text', ref: evidencePath ?? (control.termination.kind === 'error' ? control.termination.message : recoverExhausted ? control.termination.reason : 'evidence unavailable') } } });
|
|
2213
|
+
stopLive(accepted);
|
|
2023
2214
|
if (h.pid) await terminateMissionProcessTree(h.pid);
|
|
2024
2215
|
try { h.kill(); } catch { /* noop */ }
|
|
2025
2216
|
|
|
2026
2217
|
return {
|
|
2027
|
-
ok:
|
|
2218
|
+
ok: accepted, worktree: wt.path, branch: wt.branch, rounds: round,
|
|
2028
2219
|
evidencePath, committed, usedOmniCrawl: usedOmni,
|
|
2029
2220
|
ptyId: h.id, webUrl: webAddress.webUrl,
|
|
2030
|
-
detail: done ? '완료(증거 충족)' : (finalEv.ok ? '증거 충족(루프 종료)' : '미완(증거 부족)'),
|
|
2221
|
+
detail: recoverExhausted ? control.termination.reason : driveVerdict.kind === 'done-but-failed' ? `미완(DRIVE-OK: ${driveVerdict.reason})` : done ? '완료(증거 충족)' : (finalEv.ok ? '증거 충족(루프 종료)' : '미완(증거 부족)'),
|
|
2031
2222
|
};
|
|
2223
|
+
} finally { stopLive(); finishContext(false); }
|
|
2032
2224
|
}
|
|
2033
2225
|
|
|
2034
2226
|
/** @deprecated codex 특정 이름 — runAgentMission 을 쓰라(codex 는 기본 backend). */
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { debug } from '../debug/log.js';
|
|
2
|
+
|
|
3
|
+
type Identity = {
|
|
4
|
+
ts: string;
|
|
5
|
+
missionId: string;
|
|
6
|
+
seq: number;
|
|
7
|
+
sessionId: string;
|
|
8
|
+
terminalId: string;
|
|
9
|
+
agent: string;
|
|
10
|
+
text: string;
|
|
11
|
+
};
|
|
12
|
+
type Detail = { keys?: string; row?: number };
|
|
13
|
+
|
|
14
|
+
export type PtyDecision = Identity & (
|
|
15
|
+
| { step: 'read' | 'judge' | 'input'; detail?: Detail }
|
|
16
|
+
| { step: 'answer'; detail: Detail & { question: string; answer: string } }
|
|
17
|
+
| { step: 'recover'; detail: Detail & { blocked: string; action: string } }
|
|
18
|
+
| { step: 'done'; detail: Detail & { result: { kind: 'pr' | 'file' | 'text'; ref: string } } }
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
export type DecisionInput = Omit<Identity, 'ts' | 'seq'> & (
|
|
22
|
+
| { step: 'read' | 'judge' | 'input'; detail?: Detail }
|
|
23
|
+
| { step: 'answer'; detail: Detail & { question: string; answer: string } }
|
|
24
|
+
| { step: 'recover'; detail: Detail & { blocked: string; action: string } }
|
|
25
|
+
| { step: 'done'; detail: Detail & { result: { kind: 'pr' | 'file' | 'text'; ref: string } } }
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
const missionStreams = new Map<string, { alias: string; seq: number }>();
|
|
29
|
+
export const PTY_DECISION_TEXT_MAX = 240;
|
|
30
|
+
|
|
31
|
+
function safe(value: string): string {
|
|
32
|
+
const masked = value
|
|
33
|
+
.replace(/\bBearer\s+(?:"[^"]*"|'[^']*'|[^\s"'<>]+)/gi, 'Bearer [redacted]')
|
|
34
|
+
.replace(/\b([a-z0-9_]*(?:token|key(?:[_-]?id)?|secret|password|authorization)\s*[:=]\s*)(?:"[^"]*"|'[^']*'|[^\s"'<>]+)/gi, '$1[redacted]')
|
|
35
|
+
.replace(/\b(?:sk-[a-z0-9_-]+|gh[pousr]_[a-z0-9_]+|github_pat_[a-z0-9_]+|AIza[a-z0-9_-]+|xox[baprs]-[a-z0-9-]+)\b/gi, '[redacted]')
|
|
36
|
+
.replace(/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi, '[redacted]')
|
|
37
|
+
.replace(/[\x00-\x1f\x7f-\x9f]/g, ' ')
|
|
38
|
+
.trim();
|
|
39
|
+
const clipped = masked.slice(0, PTY_DECISION_TEXT_MAX);
|
|
40
|
+
return clipped.replace(/[\uD800-\uDBFF]$/, '') || '[redacted]';
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** The only emission point for the inside-PTY decision stream. Never log unsanitized input. */
|
|
44
|
+
export function emitPtyDecision(input: DecisionInput, log: typeof debug.log = (category, event, data) => debug.log(category, event, data)): PtyDecision {
|
|
45
|
+
let stream = missionStreams.get(input.missionId);
|
|
46
|
+
if (!stream) {
|
|
47
|
+
stream = { alias: `mission-${missionStreams.size + 1}`, seq: -1 };
|
|
48
|
+
missionStreams.set(input.missionId, stream);
|
|
49
|
+
}
|
|
50
|
+
stream.seq += 1;
|
|
51
|
+
const base = {
|
|
52
|
+
ts: new Date().toISOString(),
|
|
53
|
+
missionId: stream.alias,
|
|
54
|
+
seq: stream.seq,
|
|
55
|
+
sessionId: safe(input.sessionId),
|
|
56
|
+
terminalId: safe(input.terminalId),
|
|
57
|
+
agent: safe(input.agent),
|
|
58
|
+
text: safe(input.text),
|
|
59
|
+
};
|
|
60
|
+
const common = input.detail ? {
|
|
61
|
+
...(input.detail.keys !== undefined ? { keys: safe(input.detail.keys) } : {}),
|
|
62
|
+
...(input.detail.row !== undefined ? { row: input.detail.row } : {}),
|
|
63
|
+
} : {};
|
|
64
|
+
let decision: PtyDecision;
|
|
65
|
+
if (input.step === 'answer') decision = { ...base, step: input.step, detail: { ...common, question: safe(input.detail.question), answer: safe(input.detail.answer) } };
|
|
66
|
+
else if (input.step === 'recover') decision = { ...base, step: input.step, detail: { ...common, blocked: safe(input.detail.blocked), action: safe(input.detail.action) } };
|
|
67
|
+
else if (input.step === 'done') decision = { ...base, step: input.step, detail: { ...common, result: { kind: input.detail.result.kind, ref: safe(input.detail.result.ref) } } };
|
|
68
|
+
else decision = { ...base, step: input.step, ...(input.detail ? { detail: common } : {}) };
|
|
69
|
+
log('pty.decision', decision.step, decision);
|
|
70
|
+
return decision;
|
|
71
|
+
}
|